From 6ffde460060728ab47efa542c25d5b11bc15eb00 Mon Sep 17 00:00:00 2001 From: Jon Cope Date: Fri, 5 Jun 2026 13:32:02 -0500 Subject: [PATCH 01/20] USHIFT-6951: add metrics-server Kubernetes manifests Co-Authored-By: Claude Opus 4.6 --- .../optional/metrics-server/00-namespace.yaml | 9 ++ ...1-cluster-role-binding-auth-delegator.yaml | 17 +++ .../01-cluster-role-binding.yaml | 18 +++ .../metrics-server/01-cluster-role.yaml | 25 ++++ .../01-role-binding-auth-reader.yaml | 18 +++ .../metrics-server/01-service-account.yaml | 10 ++ .../02-configmap-audit-profiles.yaml | 45 +++++++ .../metrics-server/03-deployment.yaml | 114 ++++++++++++++++++ .../metrics-server/04-api-service.yaml | 21 ++++ .../optional/metrics-server/04-service.yaml | 22 ++++ .../metrics-server/kustomization.aarch64.yaml | 4 + .../metrics-server/kustomization.x86_64.yaml | 4 + .../metrics-server/kustomization.yaml | 13 ++ .../release-metrics-server-aarch64.json | 8 ++ .../release-metrics-server-x86_64.json | 8 ++ 15 files changed, 336 insertions(+) create mode 100644 assets/optional/metrics-server/00-namespace.yaml create mode 100644 assets/optional/metrics-server/01-cluster-role-binding-auth-delegator.yaml create mode 100644 assets/optional/metrics-server/01-cluster-role-binding.yaml create mode 100644 assets/optional/metrics-server/01-cluster-role.yaml create mode 100644 assets/optional/metrics-server/01-role-binding-auth-reader.yaml create mode 100644 assets/optional/metrics-server/01-service-account.yaml create mode 100644 assets/optional/metrics-server/02-configmap-audit-profiles.yaml create mode 100644 assets/optional/metrics-server/03-deployment.yaml create mode 100644 assets/optional/metrics-server/04-api-service.yaml create mode 100644 assets/optional/metrics-server/04-service.yaml create mode 100644 assets/optional/metrics-server/kustomization.aarch64.yaml create mode 100644 assets/optional/metrics-server/kustomization.x86_64.yaml create mode 100644 assets/optional/metrics-server/kustomization.yaml create mode 100644 assets/optional/metrics-server/release-metrics-server-aarch64.json create mode 100644 assets/optional/metrics-server/release-metrics-server-x86_64.json diff --git a/assets/optional/metrics-server/00-namespace.yaml b/assets/optional/metrics-server/00-namespace.yaml new file mode 100644 index 0000000000..17f727565a --- /dev/null +++ b/assets/optional/metrics-server/00-namespace.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: openshift-monitoring + labels: + name: openshift-monitoring + pod-security.kubernetes.io/enforce: privileged + pod-security.kubernetes.io/audit: privileged + pod-security.kubernetes.io/warn: privileged diff --git a/assets/optional/metrics-server/01-cluster-role-binding-auth-delegator.yaml b/assets/optional/metrics-server/01-cluster-role-binding-auth-delegator.yaml new file mode 100644 index 0000000000..fad58afef1 --- /dev/null +++ b/assets/optional/metrics-server/01-cluster-role-binding-auth-delegator.yaml @@ -0,0 +1,17 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/component: metrics-server + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/name: auth-delegator + app.kubernetes.io/part-of: openshift-monitoring + name: metrics-server:system:auth-delegator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:auth-delegator +subjects: +- kind: ServiceAccount + name: metrics-server + namespace: openshift-monitoring diff --git a/assets/optional/metrics-server/01-cluster-role-binding.yaml b/assets/optional/metrics-server/01-cluster-role-binding.yaml new file mode 100644 index 0000000000..8a32b85158 --- /dev/null +++ b/assets/optional/metrics-server/01-cluster-role-binding.yaml @@ -0,0 +1,18 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/name: metrics-server + app.kubernetes.io/part-of: openshift-monitoring + name: system:metrics-server +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:metrics-server +subjects: +- kind: ServiceAccount + name: metrics-server + namespace: openshift-monitoring +- kind: User + name: system:metrics-server diff --git a/assets/optional/metrics-server/01-cluster-role.yaml b/assets/optional/metrics-server/01-cluster-role.yaml new file mode 100644 index 0000000000..19be5ca4b0 --- /dev/null +++ b/assets/optional/metrics-server/01-cluster-role.yaml @@ -0,0 +1,25 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/component: metrics-server + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/name: metrics-server + app.kubernetes.io/part-of: openshift-monitoring + name: system:metrics-server +rules: +- apiGroups: + - "" + resources: + - nodes/metrics + verbs: + - get +- apiGroups: + - "" + resources: + - pods + - nodes + verbs: + - get + - list + - watch diff --git a/assets/optional/metrics-server/01-role-binding-auth-reader.yaml b/assets/optional/metrics-server/01-role-binding-auth-reader.yaml new file mode 100644 index 0000000000..6b11a238ce --- /dev/null +++ b/assets/optional/metrics-server/01-role-binding-auth-reader.yaml @@ -0,0 +1,18 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/component: metrics-server + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/name: metrics-server-auth-reader + app.kubernetes.io/part-of: openshift-monitoring + name: metrics-server-auth-reader + namespace: kube-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: +- kind: ServiceAccount + name: metrics-server + namespace: openshift-monitoring diff --git a/assets/optional/metrics-server/01-service-account.yaml b/assets/optional/metrics-server/01-service-account.yaml new file mode 100644 index 0000000000..310685e790 --- /dev/null +++ b/assets/optional/metrics-server/01-service-account.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: metrics-server + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/name: metrics-server + app.kubernetes.io/part-of: openshift-monitoring + name: metrics-server + namespace: openshift-monitoring diff --git a/assets/optional/metrics-server/02-configmap-audit-profiles.yaml b/assets/optional/metrics-server/02-configmap-audit-profiles.yaml new file mode 100644 index 0000000000..1cff598a6d --- /dev/null +++ b/assets/optional/metrics-server/02-configmap-audit-profiles.yaml @@ -0,0 +1,45 @@ +apiVersion: v1 +data: + metadata-profile.yaml: |- + "apiVersion": "audit.k8s.io/v1" + "kind": "Policy" + "metadata": + "name": "Metadata" + "omitStages": + - "RequestReceived" + "rules": + - "level": "Metadata" + none-profile.yaml: |- + "apiVersion": "audit.k8s.io/v1" + "kind": "Policy" + "metadata": + "name": "None" + "omitStages": + - "RequestReceived" + "rules": + - "level": "None" + request-profile.yaml: |- + "apiVersion": "audit.k8s.io/v1" + "kind": "Policy" + "metadata": + "name": "Request" + "omitStages": + - "RequestReceived" + "rules": + - "level": "Request" + requestresponse-profile.yaml: |- + "apiVersion": "audit.k8s.io/v1" + "kind": "Policy" + "metadata": + "name": "RequestResponse" + "omitStages": + - "RequestReceived" + "rules": + - "level": "RequestResponse" +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/part-of: openshift-monitoring + name: metrics-server-audit-profiles + namespace: openshift-monitoring diff --git a/assets/optional/metrics-server/03-deployment.yaml b/assets/optional/metrics-server/03-deployment.yaml new file mode 100644 index 0000000000..23cdafb3e1 --- /dev/null +++ b/assets/optional/metrics-server/03-deployment.yaml @@ -0,0 +1,114 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: metrics-server + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/name: metrics-server + app.kubernetes.io/part-of: openshift-monitoring + name: metrics-server + namespace: openshift-monitoring +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/component: metrics-server + app.kubernetes.io/name: metrics-server + app.kubernetes.io/part-of: openshift-monitoring + strategy: + type: Recreate + template: + metadata: + annotations: + openshift.io/required-scc: restricted-v2 + target.workload.openshift.io/management: '{"effect": "PreferredDuringScheduling"}' + labels: + app.kubernetes.io/component: metrics-server + app.kubernetes.io/name: metrics-server + app.kubernetes.io/part-of: openshift-monitoring + spec: + containers: + - args: + - --secure-port=10250 + - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname + - --kubelet-use-node-status-port + - --metric-resolution=15s + - --kubelet-certificate-authority=/etc/tls/kubelet-serving-ca-bundle/ca-bundle.crt + - --kubelet-client-certificate=/etc/tls/metrics-server-client-certs/tls.crt + - --kubelet-client-key=/etc/tls/metrics-server-client-certs/tls.key + - --tls-cert-file=/etc/tls/private/tls.crt + - --tls-private-key-file=/etc/tls/private/tls.key + - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 + - --shutdown-send-retry-after=true + - --shutdown-delay-duration=150s + - --disable-http2-serving=true + image: quay.io/openshift/kube-metrics-server + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 3 + httpGet: + path: /livez + port: https + scheme: HTTPS + periodSeconds: 10 + name: metrics-server + ports: + - containerPort: 10250 + name: https + protocol: TCP + readinessProbe: + failureThreshold: 6 + httpGet: + path: /readyz + port: https + scheme: HTTPS + initialDelaySeconds: 20 + periodSeconds: 20 + resources: + requests: + cpu: 1m + memory: 40Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + terminationMessagePolicy: FallbackToLogsOnError + volumeMounts: + - mountPath: /etc/tls/private + name: secret-metrics-server-tls + - mountPath: /etc/tls/metrics-server-client-certs + name: secret-metrics-server-client-certs + - mountPath: /etc/tls/kubelet-serving-ca-bundle + name: configmap-kubelet-serving-ca-bundle + - mountPath: /etc/audit + name: metrics-server-audit-profiles + readOnly: true + - mountPath: /var/log/metrics-server + name: audit-log + readOnly: false + nodeSelector: + kubernetes.io/os: linux + priorityClassName: system-cluster-critical + serviceAccountName: metrics-server + terminationGracePeriodSeconds: 170 + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + volumes: + - name: secret-metrics-server-client-certs + secret: + secretName: metrics-server-client-certs + - name: secret-metrics-server-tls + secret: + secretName: metrics-server-tls + - configMap: + name: kubelet-serving-ca-bundle + name: configmap-kubelet-serving-ca-bundle + - emptyDir: {} + name: audit-log + - configMap: + name: metrics-server-audit-profiles + name: metrics-server-audit-profiles diff --git a/assets/optional/metrics-server/04-api-service.yaml b/assets/optional/metrics-server/04-api-service.yaml new file mode 100644 index 0000000000..54303f0d9d --- /dev/null +++ b/assets/optional/metrics-server/04-api-service.yaml @@ -0,0 +1,21 @@ +apiVersion: apiregistration.k8s.io/v1 +kind: APIService +metadata: + annotations: + service.beta.openshift.io/inject-cabundle: "true" + labels: + app.kubernetes.io/component: metrics-server + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/name: metrics-server + app.kubernetes.io/part-of: openshift-monitoring + name: v1beta1.metrics.k8s.io +spec: + group: metrics.k8s.io + groupPriorityMinimum: 100 + insecureSkipTLSVerify: false + service: + name: metrics-server + namespace: openshift-monitoring + port: 443 + version: v1beta1 + versionPriority: 100 diff --git a/assets/optional/metrics-server/04-service.yaml b/assets/optional/metrics-server/04-service.yaml new file mode 100644 index 0000000000..3a485b2dad --- /dev/null +++ b/assets/optional/metrics-server/04-service.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + openshift.io/description: Expose the metrics-server web server on port 443. This port is for internal use, and no other usage is guaranteed. + service.beta.openshift.io/serving-cert-secret-name: metrics-server-tls + labels: + app.kubernetes.io/component: metrics-server + app.kubernetes.io/managed-by: cluster-monitoring-operator + app.kubernetes.io/name: metrics-server + app.kubernetes.io/part-of: openshift-monitoring + name: metrics-server + namespace: openshift-monitoring +spec: + ports: + - name: https + port: 443 + protocol: TCP + targetPort: https + selector: + app.kubernetes.io/name: metrics-server + app.kubernetes.io/part-of: openshift-monitoring diff --git a/assets/optional/metrics-server/kustomization.aarch64.yaml b/assets/optional/metrics-server/kustomization.aarch64.yaml new file mode 100644 index 0000000000..e80886329f --- /dev/null +++ b/assets/optional/metrics-server/kustomization.aarch64.yaml @@ -0,0 +1,4 @@ +images: + - name: quay.io/openshift/kube-metrics-server + newName: quay.io/openshift-release-dev/ocp-v5.0-art-dev + digest: sha256:35daed97a2d279f2543334cfb209f81be440e423042cc7dae6784985d71f2f8d diff --git a/assets/optional/metrics-server/kustomization.x86_64.yaml b/assets/optional/metrics-server/kustomization.x86_64.yaml new file mode 100644 index 0000000000..831caab705 --- /dev/null +++ b/assets/optional/metrics-server/kustomization.x86_64.yaml @@ -0,0 +1,4 @@ +images: + - name: quay.io/openshift/kube-metrics-server + newName: quay.io/openshift-release-dev/ocp-v5.0-art-dev + digest: sha256:cb84656c5b900f21b7984f917ac0473cf7b5e58cd1ec7d782b01fbe99d39bee7 diff --git a/assets/optional/metrics-server/kustomization.yaml b/assets/optional/metrics-server/kustomization.yaml new file mode 100644 index 0000000000..ca034994ff --- /dev/null +++ b/assets/optional/metrics-server/kustomization.yaml @@ -0,0 +1,13 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - 00-namespace.yaml + - 01-service-account.yaml + - 01-cluster-role.yaml + - 01-cluster-role-binding.yaml + - 01-cluster-role-binding-auth-delegator.yaml + - 01-role-binding-auth-reader.yaml + - 02-configmap-audit-profiles.yaml + - 03-deployment.yaml + - 04-service.yaml + - 04-api-service.yaml diff --git a/assets/optional/metrics-server/release-metrics-server-aarch64.json b/assets/optional/metrics-server/release-metrics-server-aarch64.json new file mode 100644 index 0000000000..c748ed629d --- /dev/null +++ b/assets/optional/metrics-server/release-metrics-server-aarch64.json @@ -0,0 +1,8 @@ +{ + "release": { + "base": "placeholder" + }, + "images": { + "metrics_server": "quay.io/openshift-release-dev/ocp-v5.0-art-dev@sha256:35daed97a2d279f2543334cfb209f81be440e423042cc7dae6784985d71f2f8d" + } +} diff --git a/assets/optional/metrics-server/release-metrics-server-x86_64.json b/assets/optional/metrics-server/release-metrics-server-x86_64.json new file mode 100644 index 0000000000..1a15957d8c --- /dev/null +++ b/assets/optional/metrics-server/release-metrics-server-x86_64.json @@ -0,0 +1,8 @@ +{ + "release": { + "base": "placeholder" + }, + "images": { + "metrics_server": "quay.io/openshift-release-dev/ocp-v5.0-art-dev@sha256:cb84656c5b900f21b7984f917ac0473cf7b5e58cd1ec7d782b01fbe99d39bee7" + } +} From 53c5a00d270b37fb0cac88c43914969d095d4bfc Mon Sep 17 00:00:00 2001 From: Jon Cope Date: Fri, 5 Jun 2026 13:32:13 -0500 Subject: [PATCH 02/20] USHIFT-6951: integrate metrics-server lifecycle management Co-Authored-By: Claude Opus 4.6 --- .../pkg/util/cryptomaterial/certinfo.go | 4 + pkg/cmd/init.go | 9 +- pkg/cmd/metrics.go | 120 ++++++++++++++++++ pkg/cmd/run.go | 12 ++ .../microshift_optional_workloads.go | 17 ++- pkg/util/cryptomaterial/certinfo.go | 4 + 6 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 pkg/cmd/metrics.go diff --git a/etcd/vendor/github.com/openshift/microshift/pkg/util/cryptomaterial/certinfo.go b/etcd/vendor/github.com/openshift/microshift/pkg/util/cryptomaterial/certinfo.go index aed383b9fa..4e8c50989e 100644 --- a/etcd/vendor/github.com/openshift/microshift/pkg/util/cryptomaterial/certinfo.go +++ b/etcd/vendor/github.com/openshift/microshift/pkg/util/cryptomaterial/certinfo.go @@ -74,6 +74,10 @@ func AdminKubeconfigClientCertDir(certsDir string) string { return filepath.Join(AdminKubeconfigSignerDir(certsDir), "admin-kubeconfig-client") } +func MetricsServerKubeletClientCertDir(certsDir string) string { + return filepath.Join(KubeAPIServerToKubeletSignerCertDir(certsDir), "metrics-server-kubelet-client") +} + // KubeletCSRSignerSignerCertDir returns path to the signer that signs kubelet CSRs // and the signer that signs CSRs of the CSR API func KubeletCSRSignerSignerCertDir(certsDir string) string { diff --git a/pkg/cmd/init.go b/pkg/cmd/init.go index 50851ed33e..de2e2a40a3 100644 --- a/pkg/cmd/init.go +++ b/pkg/cmd/init.go @@ -155,6 +155,13 @@ func certSetup(cfg *config.Config) (*certchains.CertificateChains, error) { Validity: alignValidity(cryptomaterial.ShortLivedCertificateValidity), }, UserInfo: &user.DefaultInfo{Name: "system:kube-apiserver", Groups: []string{"kube-master"}}, + }).WithClientCertificates( + &certchains.ClientCertificateSigningRequestInfo{ + CSRMeta: certchains.CSRMeta{ + Name: "metrics-server-kubelet-client", + Validity: alignValidity(cryptomaterial.ShortLivedCertificateValidity), + }, + UserInfo: &user.DefaultInfo{Name: "system:metrics-server"}, }), // admin-kubeconfig-signer @@ -175,7 +182,7 @@ func certSetup(cfg *config.Config) (*certchains.CertificateChains, error) { Name: "openshift-observability-client", Validity: alignValidity(cryptomaterial.ShortLivedCertificateValidity), }, - UserInfo: &user.DefaultInfo{Name: "openshift-observability-client", Groups: []string{""}}, + UserInfo: &user.DefaultInfo{Name: "openshift-observability-client"}, }, ), diff --git a/pkg/cmd/metrics.go b/pkg/cmd/metrics.go new file mode 100644 index 0000000000..2e1bb08fbd --- /dev/null +++ b/pkg/cmd/metrics.go @@ -0,0 +1,120 @@ +package cmd + +import ( + "context" + "fmt" + "os" + "time" + + "github.com/openshift/microshift/pkg/config" + "github.com/openshift/microshift/pkg/util" + "github.com/openshift/microshift/pkg/util/cryptomaterial" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/klog/v2" +) + +const metricsServerManifestPath = "/usr/lib/microshift/manifests.d/080-microshift-metrics-server" + +func provisionMetricsServerCerts(ctx context.Context, cfg *config.Config) error { + exists, err := util.PathExists(metricsServerManifestPath) + if err != nil { + return err + } + if !exists { + klog.V(2).Infof("Metrics-server manifests not found at %s, skipping cert provisioning", metricsServerManifestPath) + return nil + } + + kubeconfigPath := cfg.KubeConfigPath(config.KubeAdmin) + + restCfg, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath) + if err != nil { + return fmt.Errorf("building kubeconfig: %w", err) + } + clientset, err := kubernetes.NewForConfig(restCfg) + if err != nil { + return fmt.Errorf("creating clientset: %w", err) + } + const ns = "openshift-monitoring" + err = wait.PollUntilContextTimeout(ctx, 2*time.Second, 5*time.Minute, true, func(ctx context.Context) (bool, error) { + _, err := clientset.CoreV1().Namespaces().Get(ctx, ns, metav1.GetOptions{}) + if err == nil { + return true, nil + } + if !apierrors.IsNotFound(err) { + return false, fmt.Errorf("getting namespace %s: %w", ns, err) + } + klog.V(2).Infof("Waiting for namespace %s to be created by kustomize", ns) + return false, nil + }) + if err != nil { + return fmt.Errorf("waiting for namespace %s: %w", ns, err) + } + + certsDir := cryptomaterial.CertsDirectory(config.DataDir) + + certDir := cryptomaterial.MetricsServerKubeletClientCertDir(certsDir) + certPEM, err := os.ReadFile(cryptomaterial.ClientCertPath(certDir)) + if err != nil { + return err + } + keyPEM, err := os.ReadFile(cryptomaterial.ClientKeyPath(certDir)) + if err != nil { + return err + } + + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "metrics-server-client-certs", + Namespace: ns, + Annotations: map[string]string{ + "openshift.io/owning-component": "metrics-server", + }, + }, + Type: corev1.SecretTypeTLS, + Data: map[string][]byte{ + "tls.crt": certPEM, + "tls.key": keyPEM, + }, + } + _, err = clientset.CoreV1().Secrets(ns).Create(ctx, secret, metav1.CreateOptions{}) + if apierrors.IsAlreadyExists(err) { + _, err = clientset.CoreV1().Secrets(ns).Update(ctx, secret, metav1.UpdateOptions{}) + } + if err != nil { + return fmt.Errorf("applying metrics-server client cert secret: %w", err) + } + + caPEM, err := os.ReadFile(cryptomaterial.KubeletClientCAPath(certsDir)) + if err != nil { + return err + } + + cm := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "kubelet-serving-ca-bundle", + Namespace: ns, + Annotations: map[string]string{ + "openshift.io/owning-component": "metrics-server", + }, + }, + Data: map[string]string{ + "ca-bundle.crt": string(caPEM), + }, + } + _, err = clientset.CoreV1().ConfigMaps(ns).Create(ctx, cm, metav1.CreateOptions{}) + if apierrors.IsAlreadyExists(err) { + _, err = clientset.CoreV1().ConfigMaps(ns).Update(ctx, cm, metav1.UpdateOptions{}) + } + if err != nil { + return fmt.Errorf("applying kubelet serving CA configmap: %w", err) + } + + klog.Infof("Provisioned metrics-server kubelet client cert and CA bundle") + return nil +} diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go index 94c2fbd8f6..a48a7320b3 100644 --- a/pkg/cmd/run.go +++ b/pkg/cmd/run.go @@ -303,6 +303,18 @@ func RunMicroshift(cfg *config.Config) error { // After MicroShift's core becomes ready, run the kustomizer (delete and/or apply manifests). kustomize.NewKustomizer(cfg).RunStandalone(runCtx) + // Provision certs for optional components after kustomize creates their namespaces. + go func() { + defer func() { + if r := recover(); r != nil { + klog.Errorf("Panic in metrics-server cert provisioning: %v", r) + } + }() + if err := provisionMetricsServerCerts(runCtx, cfg); err != nil { + klog.Errorf("Failed to provision metrics-server certs: %v", err) + } + }() + // Watch for SIGTERM or service error to exit, now that we are ready. select { case <-sigTerm: diff --git a/pkg/healthcheck/microshift_optional_workloads.go b/pkg/healthcheck/microshift_optional_workloads.go index 80e2d9a3b0..22e68dbcc2 100644 --- a/pkg/healthcheck/microshift_optional_workloads.go +++ b/pkg/healthcheck/microshift_optional_workloads.go @@ -38,6 +38,21 @@ var optionalWorkloadPaths = map[string]optionalWorkloads{ Namespace: "sriov-network-operator", Workloads: NamespaceWorkloads{Deployments: []string{"sriov-network-operator"}}, }, + + "/usr/lib/microshift/manifests.d/080-microshift-metrics-server": { + Namespace: "openshift-monitoring", + Workloads: NamespaceWorkloads{Deployments: []string{"metrics-server"}}, + }, +} + +// mergeWorkloads merges two NamespaceWorkloads, returning a new NamespaceWorkloads. This is helpful for cases +// where components from multiple sources are deployed to the same namespace. +func mergeWorkloads(existing, incoming NamespaceWorkloads) NamespaceWorkloads { + return NamespaceWorkloads{ + Deployments: append(existing.Deployments, incoming.Deployments...), + DaemonSets: append(existing.DaemonSets, incoming.DaemonSets...), + StatefulSets: append(existing.StatefulSets, incoming.StatefulSets...), + } } // fillOptionalMicroShiftWorkloads assembles list of optional MicroShift workloads @@ -73,7 +88,7 @@ func fillOptionalMicroShiftWorkloads(workloadsToCheck map[string]NamespaceWorklo } klog.Infof("Optional component path exists and is configured: %s - expecting %v in namespace %q", path, ow.Workloads.String(), ow.Namespace) - workloadsToCheck[ow.Namespace] = ow.Workloads + workloadsToCheck[ow.Namespace] = mergeWorkloads(workloadsToCheck[ow.Namespace], ow.Workloads) } return nil } diff --git a/pkg/util/cryptomaterial/certinfo.go b/pkg/util/cryptomaterial/certinfo.go index aed383b9fa..4e8c50989e 100644 --- a/pkg/util/cryptomaterial/certinfo.go +++ b/pkg/util/cryptomaterial/certinfo.go @@ -74,6 +74,10 @@ func AdminKubeconfigClientCertDir(certsDir string) string { return filepath.Join(AdminKubeconfigSignerDir(certsDir), "admin-kubeconfig-client") } +func MetricsServerKubeletClientCertDir(certsDir string) string { + return filepath.Join(KubeAPIServerToKubeletSignerCertDir(certsDir), "metrics-server-kubelet-client") +} + // KubeletCSRSignerSignerCertDir returns path to the signer that signs kubelet CSRs // and the signer that signs CSRs of the CSR API func KubeletCSRSignerSignerCertDir(certsDir string) string { From 611c999f54a400a5d36a0721b696b692908c39e9 Mon Sep 17 00:00:00 2001 From: Jon Cope Date: Fri, 5 Jun 2026 13:32:19 -0500 Subject: [PATCH 03/20] USHIFT-6951: add metrics rebase automation Co-Authored-By: Claude Opus 4.6 --- scripts/auto-rebase/assets.yaml | 23 +++++++ scripts/auto-rebase/assets_metrics.yaml | 88 +++++++++++++++++++++++ scripts/auto-rebase/rebase.sh | 92 ++++++++++++++++++++++++- 3 files changed, 201 insertions(+), 2 deletions(-) create mode 100644 scripts/auto-rebase/assets_metrics.yaml diff --git a/scripts/auto-rebase/assets.yaml b/scripts/auto-rebase/assets.yaml index b4f34d3f6c..4a55700927 100644 --- a/scripts/auto-rebase/assets.yaml +++ b/scripts/auto-rebase/assets.yaml @@ -301,6 +301,29 @@ assets: - file: service.yaml - file: serviceaccount.yaml + - dir: optional/metrics-server/ + ignore: "MicroShift-specific metrics-server manifests sourced from CMO" + files: + - file: 00-namespace.yaml + - file: 01-cluster-role-binding-auth-delegator.yaml + - file: 01-cluster-role-binding.yaml + - file: 01-cluster-role.yaml + - file: 01-role-binding-auth-reader.yaml + - file: 01-service-account.yaml + - file: 02-configmap-audit-profiles.yaml + - file: 03-deployment.yaml + - file: 04-api-service.yaml + - file: 04-service.yaml + - file: kustomization.yaml + - file: kustomization.x86_64.yaml + ignore: "gets generated during image rebase" + - file: kustomization.aarch64.yaml + ignore: "gets generated during image rebase" + - file: release-metrics-server-x86_64.json + ignore: "gets generated during image rebase" + - file: release-metrics-server-aarch64.json + ignore: "gets generated during image rebase" + - dir: optional/observability/ ignore: "they don't exist in upstream repository - only in microshift" files: diff --git a/scripts/auto-rebase/assets_metrics.yaml b/scripts/auto-rebase/assets_metrics.yaml new file mode 100644 index 0000000000..0afaa7279b --- /dev/null +++ b/scripts/auto-rebase/assets_metrics.yaml @@ -0,0 +1,88 @@ +assets: + - dir: optional/metrics-server/ + no_clean: True + src: cluster-monitoring-operator/assets/metrics-server/ + files: + - file: 00-namespace.yaml + ignore: "Provided by MicroShift" + - file: 01-service-account.yaml + ignore: "Provided by MicroShift" + - file: 01-cluster-role.yaml + ignore: "Provided by MicroShift" + - file: clusterrole-aggregated-metrics-reader.yaml + ignore: "Provided by MicroShift" + - file: 01-cluster-role-binding.yaml + ignore: "MicroShift adds User: system:metrics-server subject for dedicated kubelet client cert" + - file: 01-cluster-role-binding-auth-delegator.yaml + ignore: "Provided by MicroShift" + - file: 01-role-binding-auth-reader.yaml + ignore: "Provided by MicroShift" + - file: 02-configmap-audit-profiles.yaml + ignore: "Provided by MicroShift" + - file: 03-deployment.yaml + ignore: "MicroShift customizes replicas, strategy, image placeholder, and cert volumes" + - file: 04-service.yaml + ignore: "MicroShift uses service-ca annotation for serving cert" + - file: 04-api-service.yaml + ignore: "Provided by MicroShift" + - file: kustomization.yaml + ignore: "Provided by MicroShift" + - file: kustomization.x86_64.yaml + ignore: "Provided by MicroShift" + - file: kustomization.aarch64.yaml + ignore: "Provided by MicroShift" + - file: release-metrics-server-aarch64.json + ignore: "Provided by MicroShift" + - file: release-metrics-server-x86_64.json + ignore: "Provided by MicroShift" + + - dir: optional/node-exporter/ + no_clean: True + src: cluster-monitoring-operator/assets/node-exporter/ + files: + - file: 01-service-account.yaml + ignore: "Provided by MicroShift" + - file: 01-cluster-role.yaml + ignore: "Provided by MicroShift" + - file: 01-cluster-role-binding.yaml + ignore: "Provided by MicroShift" + - file: 01-security-context-constraints.yaml + ignore: "Provided by MicroShift" + - file: 02-kube-rbac-proxy-secret.yaml + ignore: "Provided by MicroShift" + - file: 02-accelerators-collector-configmap.yaml + ignore: "Provided by MicroShift" + - file: 03-daemonset.yaml + ignore: "MicroShift removes metrics-client-ca volume/mount/arg (populated by CMO at runtime)" + - file: 04-service.yaml + ignore: "Provided by MicroShift" + - file: kustomization.yaml + ignore: "Provided by MicroShift" + - file: kustomization.x86_64.yaml + ignore: "Provided by MicroShift" + - file: kustomization.aarch64.yaml + ignore: "Provided by MicroShift" + + - dir: optional/kube-state-metrics/ + no_clean: True + src: cluster-monitoring-operator/assets/kube-state-metrics/ + files: + - file: 01-service-account.yaml + ignore: "Provided by MicroShift" + - file: 01-cluster-role.yaml + ignore: "Provided by MicroShift" + - file: 01-cluster-role-binding.yaml + ignore: "Provided by MicroShift" + - file: 02-kube-rbac-proxy-secret.yaml + ignore: "Provided by MicroShift" + - file: 02-custom-resource-state-configmap.yaml + - file: 03-deployment.yaml + ignore: "MicroShift overrides: Recreate strategy, removes metrics-client-ca, image placeholders" + - file: 04-service.yaml + ignore: "Provided by MicroShift" + - file: kustomization.yaml + ignore: "Provided by MicroShift" + - file: kustomization.x86_64.yaml + ignore: "Provided by MicroShift" + - file: kustomization.aarch64.yaml + ignore: "Provided by MicroShift" diff --git a/scripts/auto-rebase/rebase.sh b/scripts/auto-rebase/rebase.sh index 1bcdb6cae5..f7ab20f106 100755 --- a/scripts/auto-rebase/rebase.sh +++ b/scripts/auto-rebase/rebase.sh @@ -38,6 +38,7 @@ REBASE_USE_SSH="${REBASE_USE_SSH:-false}" EMBEDDED_COMPONENTS="route-controller-manager cluster-policy-controller hyperkube etcd kube-storage-version-migrator cluster-config-api" EMBEDDED_COMPONENT_OPERATORS="cluster-kube-apiserver-operator cluster-kube-controller-manager-operator cluster-openshift-controller-manager-operator cluster-kube-scheduler-operator machine-config-operator operator-lifecycle-manager" LOADED_COMPONENTS="cluster-dns-operator cluster-ingress-operator service-ca-operator cluster-network-operator cluster-csi-snapshot-controller-operator" +OPTIONAL_COMPONENTS="cluster-monitoring-operator" declare -a ARCHS=("amd64" "arm64") declare -A GOARCH_TO_UNAME_MAP=( ["amd64"]="x86_64" ["arm64"]="aarch64" ) @@ -200,7 +201,7 @@ download_release() { component=$(echo "${line}" | cut -d ' ' -f 1) repo=$(echo "${line}" | cut -d ' ' -f 2) commit=$(echo "${line}" | cut -d ' ' -f 3) - if [[ "${EMBEDDED_COMPONENTS}" == *"${component}"* ]] || [[ "${LOADED_COMPONENTS}" == *"${component}"* ]] || [[ "${EMBEDDED_COMPONENT_OPERATORS}" == *"${component}"* ]]; then + if [[ "${EMBEDDED_COMPONENTS}" == *"${component}"* ]] || [[ "${LOADED_COMPONENTS}" == *"${component}"* ]] || [[ "${EMBEDDED_COMPONENT_OPERATORS}" == *"${component}"* ]] || [[ "${OPTIONAL_COMPONENTS}" == *"${component}"* ]]; then clone_repo "${repo}" "${commit}" "." echo "${repo} embedded-component ${commit}" >> "${new_commits_file}" echo @@ -663,7 +664,6 @@ copy_manifests() { "$REPOROOT/scripts/auto-rebase/handle_assets.py" "./scripts/auto-rebase/assets.yaml" } - # Updates embedded component manifests by gathering these from various places # in the staged repos and copying them into the asset directory. update_openshift_manifests() { @@ -921,6 +921,7 @@ EOF update_olm_images update_multus_images + update_metrics_images popd >/dev/null } @@ -1111,6 +1112,93 @@ EOF done # for goarch } +update_metrics_images() { + title "Rebasing metrics component images" + + # Maps kustomization image name -> OCP release tag name + declare -A METRICS_IMAGE_MAP=( + ["quay.io/openshift/kube-metrics-server"]="kube-metrics-server" + ["quay.io/openshift/kube-state-metrics"]="kube-state-metrics" + ["quay.io/openshift/node-exporter"]="prometheus-node-exporter" + ["quay.io/openshift/kube-rbac-proxy"]="kube-rbac-proxy" + ) + + # Maps component dir -> release JSON key -> OCP release tag name + declare -A METRICS_COMPONENT_JSON_KEY=( + ["metrics-server"]="metrics_server" + ["kube-state-metrics"]="kube_state_metrics" + ["node-exporter"]="node_exporter" + ) + + # Maps release JSON key -> OCP release tag name + declare -A METRICS_EXPORTER_JSON_MAP=( + ["metrics_server"]="kube-metrics-server" + ["kube_state_metrics"]="kube-state-metrics" + ["node_exporter"]="prometheus-node-exporter" + ) + + for goarch in amd64 arm64; do + arch=${GOARCH_TO_UNAME_MAP["${goarch}"]:-noarch} + + local release_file="${STAGING_DIR}/release_${goarch}.json" + + local base_release + base_release=$(jq -r ".metadata.version" "${release_file}") + + # Generate per-component release JSON and kustomization files + for component_dir in metrics-server kube-state-metrics node-exporter; do + [[ -d "${REPOROOT}/assets/optional/${component_dir}" ]] || continue + + # Generate per-component release JSON + local json_key="${METRICS_COMPONENT_JSON_KEY[$component_dir]}" + local release_tag="${METRICS_EXPORTER_JSON_MAP[$json_key]}" + local new_image + new_image=$(jq -r ".references.spec.tags[] | select(.name == \"${release_tag}\") | .from.name" "${release_file}") + if [[ -z "${new_image}" || "${new_image}" == "null" ]]; then + >&2 echo "ERROR: Release tag '${release_tag}' not found in payload for ${component_dir}" + return 1 + fi + local component_release_json="${REPOROOT}/assets/optional/${component_dir}/release-${component_dir}-${arch}.json" + jq -n --arg base "$base_release" --arg img "${new_image}" \ + "{\"release\": {\"base\": \$base}, \"images\": {\"${json_key}\": \$img}}" > "${component_release_json}" + + local kustomization_arch_file="${REPOROOT}/assets/optional/${component_dir}/kustomization.${arch}.yaml" + + cat < "${kustomization_arch_file}" +images: +EOF + + # Read image names from the base kustomization and deployment/daemonset + local image_names + image_names=$(grep -h 'image:' "${REPOROOT}/assets/optional/${component_dir}/"*.yaml 2>/dev/null \ + | sed 's/.*image: *//; s/:.*//; s/@.*//' | sort -u) + + for orig_image in ${image_names}; do + local release_tag="${METRICS_IMAGE_MAP[$orig_image]:-}" + if [[ -z "${release_tag}" ]]; then + >&2 echo "ERROR: Unknown metrics image '${orig_image}' in ${component_dir}" + return 1 + fi + + local new_image + new_image=$(jq -r ".references.spec.tags[] | select(.name == \"${release_tag}\") | .from.name" "${release_file}") + if [[ -z "${new_image}" || "${new_image}" == "null" ]]; then + >&2 echo "ERROR: Image for release tag '${release_tag}' not found in payload for ${component_dir}" + return 1 + fi + local new_image_name="${new_image%@*}" + local new_image_digest="${new_image#*@}" + + cat <> "${kustomization_arch_file}" + - name: ${orig_image} + newName: ${new_image_name} + digest: ${new_image_digest} +EOF + done + done + done +} + update_olm_images() { title "Rebasing operator-lifecycle-manager manifests" From 064f93368acf7afaf5b3dba101c88bbc8e4f29bc Mon Sep 17 00:00:00 2001 From: Jon Cope Date: Fri, 5 Jun 2026 13:32:46 -0500 Subject: [PATCH 04/20] USHIFT-6951: package metrics-server RPM and observability integration Co-Authored-By: Claude Opus 4.6 --- .../microshift-observability.service | 2 +- .../otelcol.d/microshift-metrics-server.yaml | 26 +++++++++ packaging/rpm/microshift.spec | 56 +++++++++++++++++++ test/bin/common.sh | 2 + 4 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 packaging/observability/otelcol.d/microshift-metrics-server.yaml diff --git a/packaging/observability/microshift-observability.service b/packaging/observability/microshift-observability.service index 2fc2e984dc..826c2f86db 100644 --- a/packaging/observability/microshift-observability.service +++ b/packaging/observability/microshift-observability.service @@ -8,7 +8,7 @@ ConditionPathExists=/var/lib/microshift/resources/observability-client/kubeconfi Environment=KUBECONFIG=/var/lib/microshift/resources/observability-client/kubeconfig Environment=K8S_NODE_NAME="%l" ExecStartPre=/usr/bin/mkdir -p /var/lib/microshift-observability -ExecStart=/usr/bin/opentelemetry-collector --config=/etc/microshift/observability/opentelemetry-collector.yaml +ExecStart=/bin/bash -c 'ARGS="--config=file:/etc/microshift/observability/opentelemetry-collector.yaml"; for f in /etc/microshift/observability/otelcol.d/*.yaml; do [ -f "$$f" ] && ARGS="$$ARGS --config=file:$$f"; done; exec /usr/bin/opentelemetry-collector $$ARGS' Restart=always User=root diff --git a/packaging/observability/otelcol.d/microshift-metrics-server.yaml b/packaging/observability/otelcol.d/microshift-metrics-server.yaml new file mode 100644 index 0000000000..e18788969f --- /dev/null +++ b/packaging/observability/otelcol.d/microshift-metrics-server.yaml @@ -0,0 +1,26 @@ +receivers: + prometheus/metrics_server: + config: + scrape_configs: + - job_name: metrics-server + scrape_interval: 30s + scheme: https + tls_config: + ca_file: /var/lib/microshift/certs/service-ca/ca.crt + server_name: metrics-server.openshift-monitoring.svc + kubernetes_sd_configs: + - kubeconfig_file: /var/lib/microshift/resources/observability-client/kubeconfig + role: endpoints + namespaces: + names: [openshift-monitoring] + relabel_configs: + - source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: metrics-server;https + +service: + pipelines: + metrics/metrics_server: + receivers: [prometheus/metrics_server] + processors: [batch] + exporters: [otlp] diff --git a/packaging/rpm/microshift.spec b/packaging/rpm/microshift.spec index 6362e4f552..e47fac2ca9 100644 --- a/packaging/rpm/microshift.spec +++ b/packaging/rpm/microshift.spec @@ -236,6 +236,7 @@ and can be used to embed those images into osbuilder blueprints or bootc contain Summary: OpenTelemetry-Collector configured for MicroShift BuildArch: noarch Requires: microshift = %{version} +Requires: microshift-metrics-server = %{version} Requires: opentelemetry-collector %description observability @@ -261,6 +262,25 @@ The microshift-cert-manager-release-info package provides release information fi release. These files contain the list of container image references used by Cert Manager and can be used to embed those images into osbuilder blueprints or bootc containerfiles. +%package metrics-server +Summary: Kubernetes metrics-server for MicroShift +ExclusiveArch: x86_64 aarch64 +Requires: microshift = %{version} + +%description metrics-server +The microshift-metrics-server package provides the metrics-server for MicroShift. +Install this package to enable kubectl top and resource metrics via the Metrics API. + +%package metrics-server-release-info +Summary: Release information for metrics-server for MicroShift +BuildArch: noarch +Requires: microshift-release-info = %{version} + +%description metrics-server-release-info +The microshift-metrics-server-release-info package provides release information files for this +release. These files contain the list of container image references used by the metrics-server +and can be used to embed those images into osbuilder blueprints or bootc containerfiles. + %package sriov Summary: SR-IOV Network Operator for MicroShift ExclusiveArch: x86_64 aarch64 @@ -562,7 +582,9 @@ install -p -m644 assets/optional/ai-model-serving/release-ai-model-serving-x86_6 # observability install -d -m755 %{buildroot}/%{_sysconfdir}/microshift/observability +install -d -m755 %{buildroot}/%{_sysconfdir}/microshift/observability/otelcol.d install -p -m644 packaging/observability/*.yaml -D %{buildroot}%{_sysconfdir}/microshift/observability/ +install -p -m644 packaging/observability/otelcol.d/microshift-metrics-server.yaml %{buildroot}%{_sysconfdir}/microshift/observability/otelcol.d/ # Explicit copy of large config as default. Not using symlink to avoid accidental package upgrade overwriting user config if the user edits the config without copying (i.e. edits the target of symlink). install -p -m644 packaging/observability/opentelemetry-collector-large.yaml -D %{buildroot}%{_sysconfdir}/microshift/observability/opentelemetry-collector.yaml install -p -m644 packaging/observability/microshift-observability.service %{buildroot}%{_unitdir}/ @@ -599,6 +621,31 @@ cat assets/optional/cert-manager/manager/images-x86_64.yaml >> %{buildroot}/%{_p mkdir -p -m755 %{buildroot}%{_datadir}/microshift/release install -p -m644 assets/optional/cert-manager/release-cert-manager-{x86_64,aarch64}.json %{buildroot}%{_datadir}/microshift/release/ +# metrics-server +install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/080-microshift-metrics-server +install -p -m644 assets/optional/metrics-server/00-namespace.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/080-microshift-metrics-server +install -p -m644 assets/optional/metrics-server/01-service-account.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/080-microshift-metrics-server +install -p -m644 assets/optional/metrics-server/01-cluster-role.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/080-microshift-metrics-server +install -p -m644 assets/optional/metrics-server/01-cluster-role-binding.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/080-microshift-metrics-server +install -p -m644 assets/optional/metrics-server/01-cluster-role-binding-auth-delegator.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/080-microshift-metrics-server +install -p -m644 assets/optional/metrics-server/01-role-binding-auth-reader.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/080-microshift-metrics-server +install -p -m644 assets/optional/metrics-server/02-configmap-audit-profiles.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/080-microshift-metrics-server +install -p -m644 assets/optional/metrics-server/03-deployment.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/080-microshift-metrics-server +install -p -m644 assets/optional/metrics-server/04-service.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/080-microshift-metrics-server +install -p -m644 assets/optional/metrics-server/04-api-service.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/080-microshift-metrics-server +install -p -m644 assets/optional/metrics-server/kustomization.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/080-microshift-metrics-server + +%ifarch %{arm} aarch64 +cat assets/optional/metrics-server/kustomization.aarch64.yaml >> %{buildroot}/%{_prefix}/lib/microshift/manifests.d/080-microshift-metrics-server/kustomization.yaml +%endif +%ifarch x86_64 +cat assets/optional/metrics-server/kustomization.x86_64.yaml >> %{buildroot}/%{_prefix}/lib/microshift/manifests.d/080-microshift-metrics-server/kustomization.yaml +%endif + +# metrics-server-release-info +mkdir -p -m755 %{buildroot}%{_datadir}/microshift/release +install -p -m644 assets/optional/metrics-server/release-metrics-server-{x86_64,aarch64}.json %{buildroot}%{_datadir}/microshift/release/ + # sriov install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/070-microshift-sriov install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/070-microshift-sriov/crd @@ -790,10 +837,12 @@ fi %files observability %dir %{_prefix}/lib/microshift/manifests.d/003-microshift-observability %dir %{_sysconfdir}/microshift/observability/ +%dir %{_sysconfdir}/microshift/observability/otelcol.d %{_unitdir}/microshift-observability.service %config(noreplace) %{_sysconfdir}/microshift/observability/opentelemetry-collector.yaml %{_sysconfdir}/microshift/observability/opentelemetry-collector-*.yaml %{_prefix}/lib/microshift/manifests.d/003-microshift-observability/* +%config(noreplace) %{_sysconfdir}/microshift/observability/otelcol.d/microshift-metrics-server.yaml %files cert-manager %dir %{_prefix}/lib/microshift/manifests.d/060-microshift-cert-manager @@ -802,6 +851,13 @@ fi %files cert-manager-release-info %{_datadir}/microshift/release/release-cert-manager-{x86_64,aarch64}.json +%files metrics-server +%dir %{_prefix}/lib/microshift/manifests.d/080-microshift-metrics-server +%{_prefix}/lib/microshift/manifests.d/080-microshift-metrics-server/* + +%files metrics-server-release-info +%{_datadir}/microshift/release/release-metrics-server-{x86_64,aarch64}.json + %files sriov %dir %{_prefix}/lib/microshift/manifests.d/070-microshift-sriov %dir %{_prefix}/lib/microshift/manifests.d/070-microshift-sriov/crd diff --git a/test/bin/common.sh b/test/bin/common.sh index ef682a676f..8b092354b8 100644 --- a/test/bin/common.sh +++ b/test/bin/common.sh @@ -388,6 +388,8 @@ MICROSHIFT_Y2_OPTIONAL_RPMS_LIST=( microshift-cert-manager-release-info microshift-sriov microshift-sriov-release-info + microshift-metrics-server + microshift-metrics-server-release-info ) MICROSHIFT_Y1_OPTIONAL_RPMS_LIST=( "${MICROSHIFT_Y2_OPTIONAL_RPMS_LIST[@]}" From 81d72802b740f279a916053c559a2518091083ce Mon Sep 17 00:00:00 2001 From: Jon Cope Date: Sat, 6 Jun 2026 10:48:42 -0500 Subject: [PATCH 05/20] USHIFT-6951: fix otelcol test config for metrics drop-in compatibility Add otlp exporter stub to the observability test config so that metrics drop-in configs (which define pipelines exporting to otlp) don't crash otelcol when the test replaces the production config. Co-Authored-By: Claude Opus 4.6 --- test/assets/observability/otel_config.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/assets/observability/otel_config.yaml b/test/assets/observability/otel_config.yaml index 4565f82077..25609b2d17 100644 --- a/test/assets/observability/otel_config.yaml +++ b/test/assets/observability/otel_config.yaml @@ -59,6 +59,10 @@ exporters: enabled: true otlphttp/loki: # only for logs, exports the logs in the loki server endpoint: "http://{{LOKI_HOST}}:{{LOKI_PORT}}/otlp" + otlp: + endpoint: "localhost:4317" + tls: + insecure: true extensions: file_storage: From f37e956be92ff61669134ff49acafcafaee28422 Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Tue, 9 Jun 2026 17:14:30 -0500 Subject: [PATCH 06/20] USHIFT-6951: unquote YAML keys in audit profiles configmap Strip JSON-style quoted keys from the embedded audit policy documents to match the repo's YAML conventions. Values remain quoted. No functional change. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Jonathan H. Cope --- .../02-configmap-audit-profiles.yaml | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/assets/optional/metrics-server/02-configmap-audit-profiles.yaml b/assets/optional/metrics-server/02-configmap-audit-profiles.yaml index 1cff598a6d..1d8761e393 100644 --- a/assets/optional/metrics-server/02-configmap-audit-profiles.yaml +++ b/assets/optional/metrics-server/02-configmap-audit-profiles.yaml @@ -1,41 +1,41 @@ apiVersion: v1 data: metadata-profile.yaml: |- - "apiVersion": "audit.k8s.io/v1" - "kind": "Policy" - "metadata": - "name": "Metadata" - "omitStages": + apiVersion: "audit.k8s.io/v1" + kind: "Policy" + metadata: + name: "Metadata" + omitStages: - "RequestReceived" - "rules": - - "level": "Metadata" + rules: + - level: "Metadata" none-profile.yaml: |- - "apiVersion": "audit.k8s.io/v1" - "kind": "Policy" - "metadata": - "name": "None" - "omitStages": + apiVersion: "audit.k8s.io/v1" + kind: "Policy" + metadata: + name: "None" + omitStages: - "RequestReceived" - "rules": - - "level": "None" + rules: + - level: "None" request-profile.yaml: |- - "apiVersion": "audit.k8s.io/v1" - "kind": "Policy" - "metadata": - "name": "Request" - "omitStages": + apiVersion: "audit.k8s.io/v1" + kind: "Policy" + metadata: + name: "Request" + omitStages: - "RequestReceived" - "rules": - - "level": "Request" + rules: + - level: "Request" requestresponse-profile.yaml: |- - "apiVersion": "audit.k8s.io/v1" - "kind": "Policy" - "metadata": - "name": "RequestResponse" - "omitStages": + apiVersion: "audit.k8s.io/v1" + kind: "Policy" + metadata: + name: "RequestResponse" + omitStages: - "RequestReceived" - "rules": - - "level": "RequestResponse" + rules: + - level: "RequestResponse" kind: ConfigMap metadata: labels: From 61b222e4571cfe394c8f08b04eef63f73b45aacf Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Thu, 11 Jun 2026 17:57:56 -0500 Subject: [PATCH 07/20] USHIFT-6951: fix otelcol arg expansion and add missing release JSON entries Use a bash array for otelcol config arguments to prevent word-splitting, and add generated release JSON entries for node-exporter and kube-state-metrics in assets_metrics.yaml to match metrics-server. Signed-off-by: Jonathan H. Cope --- packaging/observability/microshift-observability.service | 2 +- scripts/auto-rebase/assets_metrics.yaml | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packaging/observability/microshift-observability.service b/packaging/observability/microshift-observability.service index 826c2f86db..e628bb6fd8 100644 --- a/packaging/observability/microshift-observability.service +++ b/packaging/observability/microshift-observability.service @@ -8,7 +8,7 @@ ConditionPathExists=/var/lib/microshift/resources/observability-client/kubeconfi Environment=KUBECONFIG=/var/lib/microshift/resources/observability-client/kubeconfig Environment=K8S_NODE_NAME="%l" ExecStartPre=/usr/bin/mkdir -p /var/lib/microshift-observability -ExecStart=/bin/bash -c 'ARGS="--config=file:/etc/microshift/observability/opentelemetry-collector.yaml"; for f in /etc/microshift/observability/otelcol.d/*.yaml; do [ -f "$$f" ] && ARGS="$$ARGS --config=file:$$f"; done; exec /usr/bin/opentelemetry-collector $$ARGS' +ExecStart=/bin/bash -c 'ARGS=("--config=file:/etc/microshift/observability/opentelemetry-collector.yaml"); for f in /etc/microshift/observability/otelcol.d/*.yaml; do [ -f "$$f" ] && ARGS+=("--config=file:$$f"); done; exec /usr/bin/opentelemetry-collector "$${ARGS[@]}"' Restart=always User=root diff --git a/scripts/auto-rebase/assets_metrics.yaml b/scripts/auto-rebase/assets_metrics.yaml index 0afaa7279b..e0a248f924 100644 --- a/scripts/auto-rebase/assets_metrics.yaml +++ b/scripts/auto-rebase/assets_metrics.yaml @@ -62,6 +62,10 @@ assets: ignore: "Provided by MicroShift" - file: kustomization.aarch64.yaml ignore: "Provided by MicroShift" + - file: release-node-exporter-aarch64.json + ignore: "Provided by MicroShift" + - file: release-node-exporter-x86_64.json + ignore: "Provided by MicroShift" - dir: optional/kube-state-metrics/ no_clean: True @@ -86,3 +90,7 @@ assets: ignore: "Provided by MicroShift" - file: kustomization.aarch64.yaml ignore: "Provided by MicroShift" + - file: release-kube-state-metrics-aarch64.json + ignore: "Provided by MicroShift" + - file: release-kube-state-metrics-x86_64.json + ignore: "Provided by MicroShift" From ad3d1278ed286f207e2e0796d232224f38573529 Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Tue, 16 Jun 2026 21:42:17 -0500 Subject: [PATCH 08/20] USHIFT-6951: update rebase artifacts and de-dup assets tracker Signed-off-by: Jonathan H. Cope --- .../metrics-server/kustomization.aarch64.yaml | 2 +- .../metrics-server/kustomization.x86_64.yaml | 2 +- .../release-metrics-server-aarch64.json | 4 +- .../release-metrics-server-x86_64.json | 4 +- scripts/auto-rebase/assets.yaml | 23 ------- scripts/auto-rebase/assets_metrics.yaml | 61 ------------------- scripts/auto-rebase/presubmit.py | 1 + 7 files changed, 7 insertions(+), 90 deletions(-) diff --git a/assets/optional/metrics-server/kustomization.aarch64.yaml b/assets/optional/metrics-server/kustomization.aarch64.yaml index e80886329f..694213e29a 100644 --- a/assets/optional/metrics-server/kustomization.aarch64.yaml +++ b/assets/optional/metrics-server/kustomization.aarch64.yaml @@ -1,4 +1,4 @@ images: - name: quay.io/openshift/kube-metrics-server newName: quay.io/openshift-release-dev/ocp-v5.0-art-dev - digest: sha256:35daed97a2d279f2543334cfb209f81be440e423042cc7dae6784985d71f2f8d + digest: sha256:80743f7b701994e9bffcdbccccf31815d506a322bacd6edf16b4dcd01d3686ba diff --git a/assets/optional/metrics-server/kustomization.x86_64.yaml b/assets/optional/metrics-server/kustomization.x86_64.yaml index 831caab705..b770c95d2d 100644 --- a/assets/optional/metrics-server/kustomization.x86_64.yaml +++ b/assets/optional/metrics-server/kustomization.x86_64.yaml @@ -1,4 +1,4 @@ images: - name: quay.io/openshift/kube-metrics-server newName: quay.io/openshift-release-dev/ocp-v5.0-art-dev - digest: sha256:cb84656c5b900f21b7984f917ac0473cf7b5e58cd1ec7d782b01fbe99d39bee7 + digest: sha256:cabd43c39e5bcc2f8326e5db8e0a91ddae4cfcd2e206ff18c49df934346f8014 diff --git a/assets/optional/metrics-server/release-metrics-server-aarch64.json b/assets/optional/metrics-server/release-metrics-server-aarch64.json index c748ed629d..6009b817b9 100644 --- a/assets/optional/metrics-server/release-metrics-server-aarch64.json +++ b/assets/optional/metrics-server/release-metrics-server-aarch64.json @@ -1,8 +1,8 @@ { "release": { - "base": "placeholder" + "base": "5.0.0-0.nightly-arm64-2026-06-14-225436" }, "images": { - "metrics_server": "quay.io/openshift-release-dev/ocp-v5.0-art-dev@sha256:35daed97a2d279f2543334cfb209f81be440e423042cc7dae6784985d71f2f8d" + "metrics_server": "quay.io/openshift-release-dev/ocp-v5.0-art-dev@sha256:80743f7b701994e9bffcdbccccf31815d506a322bacd6edf16b4dcd01d3686ba" } } diff --git a/assets/optional/metrics-server/release-metrics-server-x86_64.json b/assets/optional/metrics-server/release-metrics-server-x86_64.json index 1a15957d8c..d64aab1619 100644 --- a/assets/optional/metrics-server/release-metrics-server-x86_64.json +++ b/assets/optional/metrics-server/release-metrics-server-x86_64.json @@ -1,8 +1,8 @@ { "release": { - "base": "placeholder" + "base": "5.0.0-0.nightly-2026-06-14-221055" }, "images": { - "metrics_server": "quay.io/openshift-release-dev/ocp-v5.0-art-dev@sha256:cb84656c5b900f21b7984f917ac0473cf7b5e58cd1ec7d782b01fbe99d39bee7" + "metrics_server": "quay.io/openshift-release-dev/ocp-v5.0-art-dev@sha256:cabd43c39e5bcc2f8326e5db8e0a91ddae4cfcd2e206ff18c49df934346f8014" } } diff --git a/scripts/auto-rebase/assets.yaml b/scripts/auto-rebase/assets.yaml index 4a55700927..b4f34d3f6c 100644 --- a/scripts/auto-rebase/assets.yaml +++ b/scripts/auto-rebase/assets.yaml @@ -301,29 +301,6 @@ assets: - file: service.yaml - file: serviceaccount.yaml - - dir: optional/metrics-server/ - ignore: "MicroShift-specific metrics-server manifests sourced from CMO" - files: - - file: 00-namespace.yaml - - file: 01-cluster-role-binding-auth-delegator.yaml - - file: 01-cluster-role-binding.yaml - - file: 01-cluster-role.yaml - - file: 01-role-binding-auth-reader.yaml - - file: 01-service-account.yaml - - file: 02-configmap-audit-profiles.yaml - - file: 03-deployment.yaml - - file: 04-api-service.yaml - - file: 04-service.yaml - - file: kustomization.yaml - - file: kustomization.x86_64.yaml - ignore: "gets generated during image rebase" - - file: kustomization.aarch64.yaml - ignore: "gets generated during image rebase" - - file: release-metrics-server-x86_64.json - ignore: "gets generated during image rebase" - - file: release-metrics-server-aarch64.json - ignore: "gets generated during image rebase" - - dir: optional/observability/ ignore: "they don't exist in upstream repository - only in microshift" files: diff --git a/scripts/auto-rebase/assets_metrics.yaml b/scripts/auto-rebase/assets_metrics.yaml index e0a248f924..7fecda282e 100644 --- a/scripts/auto-rebase/assets_metrics.yaml +++ b/scripts/auto-rebase/assets_metrics.yaml @@ -9,8 +9,6 @@ assets: ignore: "Provided by MicroShift" - file: 01-cluster-role.yaml ignore: "Provided by MicroShift" - - file: clusterrole-aggregated-metrics-reader.yaml - ignore: "Provided by MicroShift" - file: 01-cluster-role-binding.yaml ignore: "MicroShift adds User: system:metrics-server subject for dedicated kubelet client cert" - file: 01-cluster-role-binding-auth-delegator.yaml @@ -35,62 +33,3 @@ assets: ignore: "Provided by MicroShift" - file: release-metrics-server-x86_64.json ignore: "Provided by MicroShift" - - - dir: optional/node-exporter/ - no_clean: True - src: cluster-monitoring-operator/assets/node-exporter/ - files: - - file: 01-service-account.yaml - ignore: "Provided by MicroShift" - - file: 01-cluster-role.yaml - ignore: "Provided by MicroShift" - - file: 01-cluster-role-binding.yaml - ignore: "Provided by MicroShift" - - file: 01-security-context-constraints.yaml - ignore: "Provided by MicroShift" - - file: 02-kube-rbac-proxy-secret.yaml - ignore: "Provided by MicroShift" - - file: 02-accelerators-collector-configmap.yaml - ignore: "Provided by MicroShift" - - file: 03-daemonset.yaml - ignore: "MicroShift removes metrics-client-ca volume/mount/arg (populated by CMO at runtime)" - - file: 04-service.yaml - ignore: "Provided by MicroShift" - - file: kustomization.yaml - ignore: "Provided by MicroShift" - - file: kustomization.x86_64.yaml - ignore: "Provided by MicroShift" - - file: kustomization.aarch64.yaml - ignore: "Provided by MicroShift" - - file: release-node-exporter-aarch64.json - ignore: "Provided by MicroShift" - - file: release-node-exporter-x86_64.json - ignore: "Provided by MicroShift" - - - dir: optional/kube-state-metrics/ - no_clean: True - src: cluster-monitoring-operator/assets/kube-state-metrics/ - files: - - file: 01-service-account.yaml - ignore: "Provided by MicroShift" - - file: 01-cluster-role.yaml - ignore: "Provided by MicroShift" - - file: 01-cluster-role-binding.yaml - ignore: "Provided by MicroShift" - - file: 02-kube-rbac-proxy-secret.yaml - ignore: "Provided by MicroShift" - - file: 02-custom-resource-state-configmap.yaml - - file: 03-deployment.yaml - ignore: "MicroShift overrides: Recreate strategy, removes metrics-client-ca, image placeholders" - - file: 04-service.yaml - ignore: "Provided by MicroShift" - - file: kustomization.yaml - ignore: "Provided by MicroShift" - - file: kustomization.x86_64.yaml - ignore: "Provided by MicroShift" - - file: kustomization.aarch64.yaml - ignore: "Provided by MicroShift" - - file: release-kube-state-metrics-aarch64.json - ignore: "Provided by MicroShift" - - file: release-kube-state-metrics-x86_64.json - ignore: "Provided by MicroShift" diff --git a/scripts/auto-rebase/presubmit.py b/scripts/auto-rebase/presubmit.py index 5e90ed4639..3a98d94158 100755 --- a/scripts/auto-rebase/presubmit.py +++ b/scripts/auto-rebase/presubmit.py @@ -29,6 +29,7 @@ "./scripts/auto-rebase/assets_ai_model_serving.yaml", "./scripts/auto-rebase/assets_cert_manager.yaml", "./scripts/auto-rebase/assets_sriov.yaml", + "./scripts/auto-rebase/assets_metrics.yaml", ] From 6e29665e6bb8f2a5ef06c556b7ad0ce581aab859 Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Tue, 16 Jun 2026 22:18:30 -0500 Subject: [PATCH 09/20] USHIFT-6951: move metrics cert provisioning to pkg/components Signed-off-by: Jonathan H. Cope --- pkg/cmd/run.go | 8 ++---- pkg/{cmd => components}/metrics.go | 39 ++++++++++++++---------------- 2 files changed, 20 insertions(+), 27 deletions(-) rename pkg/{cmd => components}/metrics.go (69%) diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go index a48a7320b3..e1be072438 100644 --- a/pkg/cmd/run.go +++ b/pkg/cmd/run.go @@ -14,6 +14,7 @@ import ( "github.com/coreos/go-systemd/daemon" "github.com/openshift/microshift/pkg/admin/data" "github.com/openshift/microshift/pkg/admin/prerun" + "github.com/openshift/microshift/pkg/components" "github.com/openshift/microshift/pkg/config" "github.com/openshift/microshift/pkg/controllers" "github.com/openshift/microshift/pkg/controllers/c2cc" @@ -305,12 +306,7 @@ func RunMicroshift(cfg *config.Config) error { // Provision certs for optional components after kustomize creates their namespaces. go func() { - defer func() { - if r := recover(); r != nil { - klog.Errorf("Panic in metrics-server cert provisioning: %v", r) - } - }() - if err := provisionMetricsServerCerts(runCtx, cfg); err != nil { + if err := components.ProvisionMetricsServerCerts(runCtx, cfg); err != nil { klog.Errorf("Failed to provision metrics-server certs: %v", err) } }() diff --git a/pkg/cmd/metrics.go b/pkg/components/metrics.go similarity index 69% rename from pkg/cmd/metrics.go rename to pkg/components/metrics.go index 2e1bb08fbd..b97e7e4da2 100644 --- a/pkg/cmd/metrics.go +++ b/pkg/components/metrics.go @@ -1,4 +1,4 @@ -package cmd +package components import ( "context" @@ -13,14 +13,15 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/tools/clientcmd" "k8s.io/klog/v2" ) -const metricsServerManifestPath = "/usr/lib/microshift/manifests.d/080-microshift-metrics-server" +const ( + metricsServerManifestPath = "/usr/lib/microshift/manifests.d/080-microshift-metrics-server" + metricsServerNamespace = "openshift-monitoring" +) -func provisionMetricsServerCerts(ctx context.Context, cfg *config.Config) error { +func ProvisionMetricsServerCerts(ctx context.Context, cfg *config.Config) error { exists, err := util.PathExists(metricsServerManifestPath) if err != nil { return err @@ -32,28 +33,24 @@ func provisionMetricsServerCerts(ctx context.Context, cfg *config.Config) error kubeconfigPath := cfg.KubeConfigPath(config.KubeAdmin) - restCfg, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath) - if err != nil { - return fmt.Errorf("building kubeconfig: %w", err) - } - clientset, err := kubernetes.NewForConfig(restCfg) + clientset, err := getKubernetesClient(kubeconfigPath) if err != nil { return fmt.Errorf("creating clientset: %w", err) } - const ns = "openshift-monitoring" + err = wait.PollUntilContextTimeout(ctx, 2*time.Second, 5*time.Minute, true, func(ctx context.Context) (bool, error) { - _, err := clientset.CoreV1().Namespaces().Get(ctx, ns, metav1.GetOptions{}) + _, err := clientset.CoreV1().Namespaces().Get(ctx, metricsServerNamespace, metav1.GetOptions{}) if err == nil { return true, nil } if !apierrors.IsNotFound(err) { - return false, fmt.Errorf("getting namespace %s: %w", ns, err) + return false, fmt.Errorf("getting namespace %s: %w", metricsServerNamespace, err) } - klog.V(2).Infof("Waiting for namespace %s to be created by kustomize", ns) + klog.V(2).Infof("Waiting for namespace %s to be created by kustomize", metricsServerNamespace) return false, nil }) if err != nil { - return fmt.Errorf("waiting for namespace %s: %w", ns, err) + return fmt.Errorf("waiting for namespace %s: %w", metricsServerNamespace, err) } certsDir := cryptomaterial.CertsDirectory(config.DataDir) @@ -71,7 +68,7 @@ func provisionMetricsServerCerts(ctx context.Context, cfg *config.Config) error secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "metrics-server-client-certs", - Namespace: ns, + Namespace: metricsServerNamespace, Annotations: map[string]string{ "openshift.io/owning-component": "metrics-server", }, @@ -82,9 +79,9 @@ func provisionMetricsServerCerts(ctx context.Context, cfg *config.Config) error "tls.key": keyPEM, }, } - _, err = clientset.CoreV1().Secrets(ns).Create(ctx, secret, metav1.CreateOptions{}) + _, err = clientset.CoreV1().Secrets(metricsServerNamespace).Create(ctx, secret, metav1.CreateOptions{}) if apierrors.IsAlreadyExists(err) { - _, err = clientset.CoreV1().Secrets(ns).Update(ctx, secret, metav1.UpdateOptions{}) + _, err = clientset.CoreV1().Secrets(metricsServerNamespace).Update(ctx, secret, metav1.UpdateOptions{}) } if err != nil { return fmt.Errorf("applying metrics-server client cert secret: %w", err) @@ -98,7 +95,7 @@ func provisionMetricsServerCerts(ctx context.Context, cfg *config.Config) error cm := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "kubelet-serving-ca-bundle", - Namespace: ns, + Namespace: metricsServerNamespace, Annotations: map[string]string{ "openshift.io/owning-component": "metrics-server", }, @@ -107,9 +104,9 @@ func provisionMetricsServerCerts(ctx context.Context, cfg *config.Config) error "ca-bundle.crt": string(caPEM), }, } - _, err = clientset.CoreV1().ConfigMaps(ns).Create(ctx, cm, metav1.CreateOptions{}) + _, err = clientset.CoreV1().ConfigMaps(metricsServerNamespace).Create(ctx, cm, metav1.CreateOptions{}) if apierrors.IsAlreadyExists(err) { - _, err = clientset.CoreV1().ConfigMaps(ns).Update(ctx, cm, metav1.UpdateOptions{}) + _, err = clientset.CoreV1().ConfigMaps(metricsServerNamespace).Update(ctx, cm, metav1.UpdateOptions{}) } if err != nil { return fmt.Errorf("applying kubelet serving CA configmap: %w", err) From 131595b6f6656d24c55c971fafa32893f34fd27c Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Tue, 16 Jun 2026 22:18:33 -0500 Subject: [PATCH 10/20] USHIFT-6951: fix metrics-server cert provisioning reliability use resourceapply for idempotent secret/configmap apply with retry, return (false, nil) on transient API errors so polling continues, propagate errors synchronously instead of fire-and-forget goroutine Signed-off-by: Jonathan H. Cope --- pkg/cmd/run.go | 8 +++----- pkg/components/metrics.go | 35 +++++++++++++++++++++++++---------- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go index e1be072438..99b4864bad 100644 --- a/pkg/cmd/run.go +++ b/pkg/cmd/run.go @@ -305,11 +305,9 @@ func RunMicroshift(cfg *config.Config) error { kustomize.NewKustomizer(cfg).RunStandalone(runCtx) // Provision certs for optional components after kustomize creates their namespaces. - go func() { - if err := components.ProvisionMetricsServerCerts(runCtx, cfg); err != nil { - klog.Errorf("Failed to provision metrics-server certs: %v", err) - } - }() + if err := components.ProvisionMetricsServerCerts(runCtx, cfg); err != nil { + return fmt.Errorf("failed to provision metrics-server certs: %w", err) + } // Watch for SIGTERM or service error to exit, now that we are ready. select { diff --git a/pkg/components/metrics.go b/pkg/components/metrics.go index b97e7e4da2..5dac438fa7 100644 --- a/pkg/components/metrics.go +++ b/pkg/components/metrics.go @@ -6,6 +6,8 @@ import ( "os" "time" + "github.com/openshift/library-go/pkg/operator/events" + "github.com/openshift/library-go/pkg/operator/resource/resourceapply" "github.com/openshift/microshift/pkg/config" "github.com/openshift/microshift/pkg/util" "github.com/openshift/microshift/pkg/util/cryptomaterial" @@ -14,6 +16,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/klog/v2" + "k8s.io/utils/clock" ) const ( @@ -21,6 +24,8 @@ const ( metricsServerNamespace = "openshift-monitoring" ) +var metricsEventRecorder events.Recorder = events.NewLoggingEventRecorder("microshift-metrics-server", clock.RealClock{}) + func ProvisionMetricsServerCerts(ctx context.Context, cfg *config.Config) error { exists, err := util.PathExists(metricsServerManifestPath) if err != nil { @@ -44,7 +49,8 @@ func ProvisionMetricsServerCerts(ctx context.Context, cfg *config.Config) error return true, nil } if !apierrors.IsNotFound(err) { - return false, fmt.Errorf("getting namespace %s: %w", metricsServerNamespace, err) + klog.Errorf("getting namespace %s: %v", metricsServerNamespace, err) + return false, nil } klog.V(2).Infof("Waiting for namespace %s to be created by kustomize", metricsServerNamespace) return false, nil @@ -79,10 +85,15 @@ func ProvisionMetricsServerCerts(ctx context.Context, cfg *config.Config) error "tls.key": keyPEM, }, } - _, err = clientset.CoreV1().Secrets(metricsServerNamespace).Create(ctx, secret, metav1.CreateOptions{}) - if apierrors.IsAlreadyExists(err) { - _, err = clientset.CoreV1().Secrets(metricsServerNamespace).Update(ctx, secret, metav1.UpdateOptions{}) - } + + err = wait.PollUntilContextTimeout(ctx, 2*time.Second, 1*time.Minute, true, func(ctx context.Context) (bool, error) { + _, _, err := resourceapply.ApplySecret(ctx, clientset.CoreV1(), metricsEventRecorder, secret) + if err != nil { + klog.Errorf("applying metrics-server client cert secret: %v", err) + return false, nil + } + return true, nil + }) if err != nil { return fmt.Errorf("applying metrics-server client cert secret: %w", err) } @@ -104,12 +115,16 @@ func ProvisionMetricsServerCerts(ctx context.Context, cfg *config.Config) error "ca-bundle.crt": string(caPEM), }, } - _, err = clientset.CoreV1().ConfigMaps(metricsServerNamespace).Create(ctx, cm, metav1.CreateOptions{}) - if apierrors.IsAlreadyExists(err) { - _, err = clientset.CoreV1().ConfigMaps(metricsServerNamespace).Update(ctx, cm, metav1.UpdateOptions{}) - } + + err = wait.PollUntilContextTimeout(ctx, 2*time.Second, 1*time.Minute, true, func(ctx context.Context) (bool, error) { + _, _, err := resourceapply.ApplyConfigMap(ctx, clientset.CoreV1(), metricsEventRecorder, cm) + if err != nil { + return false, fmt.Errorf("applying kubelet serving CA configmap: %w", err) + } + return true, nil + }) if err != nil { - return fmt.Errorf("applying kubelet serving CA configmap: %w", err) + return fmt.Errorf("applying kubelet serving CA configmap: %v", err) } klog.Infof("Provisioned metrics-server kubelet client cert and CA bundle") From 4422f5f7ba66f11edb078f3e3145bba87fb5a54f Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Tue, 16 Jun 2026 22:18:36 -0500 Subject: [PATCH 11/20] USHIFT-6951: narrow kubelet serving CA bundle for metrics-server add KubeletServingCAPath containing only kubelet-signer and kube-csr-signer; use it instead of the broader KubeletClientCAPath Signed-off-by: Jonathan H. Cope --- pkg/cmd/init.go | 4 ++++ pkg/components/metrics.go | 2 +- pkg/util/cryptomaterial/certinfo.go | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pkg/cmd/init.go b/pkg/cmd/init.go index de2e2a40a3..8c8e9ec6ff 100644 --- a/pkg/cmd/init.go +++ b/pkg/cmd/init.go @@ -371,6 +371,10 @@ func certSetup(cfg *config.Config) (*certchains.CertificateChains, error) { []string{"admin-kubeconfig-signer"}, []string{"kubelet-signer"}, []string{"kubelet-signer", "kube-csr-signer"}, + ).WithCABundle( + cryptomaterial.KubeletServingCAPath(certsDir), + []string{"kubelet-signer"}, + []string{"kubelet-signer", "kube-csr-signer"}, ).WithCABundle( cryptomaterial.ServiceAccountTokenCABundlePath(certsDir), []string{"kube-apiserver-localhost-signer"}, diff --git a/pkg/components/metrics.go b/pkg/components/metrics.go index 5dac438fa7..3539cb0de6 100644 --- a/pkg/components/metrics.go +++ b/pkg/components/metrics.go @@ -98,7 +98,7 @@ func ProvisionMetricsServerCerts(ctx context.Context, cfg *config.Config) error return fmt.Errorf("applying metrics-server client cert secret: %w", err) } - caPEM, err := os.ReadFile(cryptomaterial.KubeletClientCAPath(certsDir)) + caPEM, err := os.ReadFile(cryptomaterial.KubeletServingCAPath(certsDir)) if err != nil { return err } diff --git a/pkg/util/cryptomaterial/certinfo.go b/pkg/util/cryptomaterial/certinfo.go index 4e8c50989e..12c413d114 100644 --- a/pkg/util/cryptomaterial/certinfo.go +++ b/pkg/util/cryptomaterial/certinfo.go @@ -171,6 +171,10 @@ func KubeletClientCAPath(certsDir string) string { return filepath.Join(certsDir, "ca-bundle", "kubelet-ca.crt") } +func KubeletServingCAPath(certsDir string) string { + return filepath.Join(certsDir, "ca-bundle", "kubelet-serving-ca.crt") +} + func ServiceAccountTokenCABundlePath(certsDir string) string { return filepath.Join(certsDir, "ca-bundle", "service-account-token-ca.crt") } From 31d8583cff1a08f97898885210eb5807fce11b08 Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Fri, 19 Jun 2026 00:47:29 -0500 Subject: [PATCH 12/20] USHIFT-6951: use slices.Concat in mergeWorkloads Co-Authored-By: Claude Opus 4.6 --- pkg/healthcheck/microshift_optional_workloads.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pkg/healthcheck/microshift_optional_workloads.go b/pkg/healthcheck/microshift_optional_workloads.go index 22e68dbcc2..7772b1e36c 100644 --- a/pkg/healthcheck/microshift_optional_workloads.go +++ b/pkg/healthcheck/microshift_optional_workloads.go @@ -1,6 +1,8 @@ package healthcheck import ( + "slices" + "github.com/openshift/microshift/pkg/config" "github.com/openshift/microshift/pkg/util" "k8s.io/klog/v2" @@ -45,13 +47,12 @@ var optionalWorkloadPaths = map[string]optionalWorkloads{ }, } -// mergeWorkloads merges two NamespaceWorkloads, returning a new NamespaceWorkloads. This is helpful for cases -// where components from multiple sources are deployed to the same namespace. +// mergeWorkloads combines two NamespaceWorkloads into one. func mergeWorkloads(existing, incoming NamespaceWorkloads) NamespaceWorkloads { return NamespaceWorkloads{ - Deployments: append(existing.Deployments, incoming.Deployments...), - DaemonSets: append(existing.DaemonSets, incoming.DaemonSets...), - StatefulSets: append(existing.StatefulSets, incoming.StatefulSets...), + Deployments: slices.Concat(existing.Deployments, incoming.Deployments), + DaemonSets: slices.Concat(existing.DaemonSets, incoming.DaemonSets), + StatefulSets: slices.Concat(existing.StatefulSets, incoming.StatefulSets), } } From 21a3084cc785e124959d0fef74025023939c75bc Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Fri, 19 Jun 2026 12:18:24 -0500 Subject: [PATCH 13/20] USHIFT-6951: remove otel-collector integration from metrics-server Remove otelcol drop-in config, revert observability service ExecStart to single-config mode, and drop otelcol-related lines from the RPM spec. Observability integration is deferred to a follow-up PR. Signed-off-by: Jonathan H. Cope --- .../microshift-observability.service | 2 +- .../otelcol.d/microshift-metrics-server.yaml | 26 ------------------- packaging/rpm/microshift.spec | 5 ---- 3 files changed, 1 insertion(+), 32 deletions(-) delete mode 100644 packaging/observability/otelcol.d/microshift-metrics-server.yaml diff --git a/packaging/observability/microshift-observability.service b/packaging/observability/microshift-observability.service index e628bb6fd8..2fc2e984dc 100644 --- a/packaging/observability/microshift-observability.service +++ b/packaging/observability/microshift-observability.service @@ -8,7 +8,7 @@ ConditionPathExists=/var/lib/microshift/resources/observability-client/kubeconfi Environment=KUBECONFIG=/var/lib/microshift/resources/observability-client/kubeconfig Environment=K8S_NODE_NAME="%l" ExecStartPre=/usr/bin/mkdir -p /var/lib/microshift-observability -ExecStart=/bin/bash -c 'ARGS=("--config=file:/etc/microshift/observability/opentelemetry-collector.yaml"); for f in /etc/microshift/observability/otelcol.d/*.yaml; do [ -f "$$f" ] && ARGS+=("--config=file:$$f"); done; exec /usr/bin/opentelemetry-collector "$${ARGS[@]}"' +ExecStart=/usr/bin/opentelemetry-collector --config=/etc/microshift/observability/opentelemetry-collector.yaml Restart=always User=root diff --git a/packaging/observability/otelcol.d/microshift-metrics-server.yaml b/packaging/observability/otelcol.d/microshift-metrics-server.yaml deleted file mode 100644 index e18788969f..0000000000 --- a/packaging/observability/otelcol.d/microshift-metrics-server.yaml +++ /dev/null @@ -1,26 +0,0 @@ -receivers: - prometheus/metrics_server: - config: - scrape_configs: - - job_name: metrics-server - scrape_interval: 30s - scheme: https - tls_config: - ca_file: /var/lib/microshift/certs/service-ca/ca.crt - server_name: metrics-server.openshift-monitoring.svc - kubernetes_sd_configs: - - kubeconfig_file: /var/lib/microshift/resources/observability-client/kubeconfig - role: endpoints - namespaces: - names: [openshift-monitoring] - relabel_configs: - - source_labels: [__meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] - action: keep - regex: metrics-server;https - -service: - pipelines: - metrics/metrics_server: - receivers: [prometheus/metrics_server] - processors: [batch] - exporters: [otlp] diff --git a/packaging/rpm/microshift.spec b/packaging/rpm/microshift.spec index e47fac2ca9..e720a65bad 100644 --- a/packaging/rpm/microshift.spec +++ b/packaging/rpm/microshift.spec @@ -236,7 +236,6 @@ and can be used to embed those images into osbuilder blueprints or bootc contain Summary: OpenTelemetry-Collector configured for MicroShift BuildArch: noarch Requires: microshift = %{version} -Requires: microshift-metrics-server = %{version} Requires: opentelemetry-collector %description observability @@ -582,9 +581,7 @@ install -p -m644 assets/optional/ai-model-serving/release-ai-model-serving-x86_6 # observability install -d -m755 %{buildroot}/%{_sysconfdir}/microshift/observability -install -d -m755 %{buildroot}/%{_sysconfdir}/microshift/observability/otelcol.d install -p -m644 packaging/observability/*.yaml -D %{buildroot}%{_sysconfdir}/microshift/observability/ -install -p -m644 packaging/observability/otelcol.d/microshift-metrics-server.yaml %{buildroot}%{_sysconfdir}/microshift/observability/otelcol.d/ # Explicit copy of large config as default. Not using symlink to avoid accidental package upgrade overwriting user config if the user edits the config without copying (i.e. edits the target of symlink). install -p -m644 packaging/observability/opentelemetry-collector-large.yaml -D %{buildroot}%{_sysconfdir}/microshift/observability/opentelemetry-collector.yaml install -p -m644 packaging/observability/microshift-observability.service %{buildroot}%{_unitdir}/ @@ -837,12 +834,10 @@ fi %files observability %dir %{_prefix}/lib/microshift/manifests.d/003-microshift-observability %dir %{_sysconfdir}/microshift/observability/ -%dir %{_sysconfdir}/microshift/observability/otelcol.d %{_unitdir}/microshift-observability.service %config(noreplace) %{_sysconfdir}/microshift/observability/opentelemetry-collector.yaml %{_sysconfdir}/microshift/observability/opentelemetry-collector-*.yaml %{_prefix}/lib/microshift/manifests.d/003-microshift-observability/* -%config(noreplace) %{_sysconfdir}/microshift/observability/otelcol.d/microshift-metrics-server.yaml %files cert-manager %dir %{_prefix}/lib/microshift/manifests.d/060-microshift-cert-manager From 11d0b8ba2027bf33076a4e08bc1884355b550e03 Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Fri, 19 Jun 2026 12:18:24 -0500 Subject: [PATCH 14/20] USHIFT-6951: remove metrics-server rebase logic from shared files Move MS asset tracking and image update logic out of the shared rebase.sh. Delete the separate assets_metrics.yaml and update presubmit.py to reference the new unified asset file. Signed-off-by: Jonathan H. Cope --- scripts/auto-rebase/assets_metrics.yaml | 35 ---------- scripts/auto-rebase/presubmit.py | 2 +- scripts/auto-rebase/rebase.sh | 92 +------------------------ 3 files changed, 3 insertions(+), 126 deletions(-) delete mode 100644 scripts/auto-rebase/assets_metrics.yaml diff --git a/scripts/auto-rebase/assets_metrics.yaml b/scripts/auto-rebase/assets_metrics.yaml deleted file mode 100644 index 7fecda282e..0000000000 --- a/scripts/auto-rebase/assets_metrics.yaml +++ /dev/null @@ -1,35 +0,0 @@ -assets: - - dir: optional/metrics-server/ - no_clean: True - src: cluster-monitoring-operator/assets/metrics-server/ - files: - - file: 00-namespace.yaml - ignore: "Provided by MicroShift" - - file: 01-service-account.yaml - ignore: "Provided by MicroShift" - - file: 01-cluster-role.yaml - ignore: "Provided by MicroShift" - - file: 01-cluster-role-binding.yaml - ignore: "MicroShift adds User: system:metrics-server subject for dedicated kubelet client cert" - - file: 01-cluster-role-binding-auth-delegator.yaml - ignore: "Provided by MicroShift" - - file: 01-role-binding-auth-reader.yaml - ignore: "Provided by MicroShift" - - file: 02-configmap-audit-profiles.yaml - ignore: "Provided by MicroShift" - - file: 03-deployment.yaml - ignore: "MicroShift customizes replicas, strategy, image placeholder, and cert volumes" - - file: 04-service.yaml - ignore: "MicroShift uses service-ca annotation for serving cert" - - file: 04-api-service.yaml - ignore: "Provided by MicroShift" - - file: kustomization.yaml - ignore: "Provided by MicroShift" - - file: kustomization.x86_64.yaml - ignore: "Provided by MicroShift" - - file: kustomization.aarch64.yaml - ignore: "Provided by MicroShift" - - file: release-metrics-server-aarch64.json - ignore: "Provided by MicroShift" - - file: release-metrics-server-x86_64.json - ignore: "Provided by MicroShift" diff --git a/scripts/auto-rebase/presubmit.py b/scripts/auto-rebase/presubmit.py index 3a98d94158..ea3f6199b4 100755 --- a/scripts/auto-rebase/presubmit.py +++ b/scripts/auto-rebase/presubmit.py @@ -29,7 +29,7 @@ "./scripts/auto-rebase/assets_ai_model_serving.yaml", "./scripts/auto-rebase/assets_cert_manager.yaml", "./scripts/auto-rebase/assets_sriov.yaml", - "./scripts/auto-rebase/assets_metrics.yaml", + "./scripts/auto-rebase/assets_cluster_monitoring_operator.yaml", ] diff --git a/scripts/auto-rebase/rebase.sh b/scripts/auto-rebase/rebase.sh index f7ab20f106..1bcdb6cae5 100755 --- a/scripts/auto-rebase/rebase.sh +++ b/scripts/auto-rebase/rebase.sh @@ -38,7 +38,6 @@ REBASE_USE_SSH="${REBASE_USE_SSH:-false}" EMBEDDED_COMPONENTS="route-controller-manager cluster-policy-controller hyperkube etcd kube-storage-version-migrator cluster-config-api" EMBEDDED_COMPONENT_OPERATORS="cluster-kube-apiserver-operator cluster-kube-controller-manager-operator cluster-openshift-controller-manager-operator cluster-kube-scheduler-operator machine-config-operator operator-lifecycle-manager" LOADED_COMPONENTS="cluster-dns-operator cluster-ingress-operator service-ca-operator cluster-network-operator cluster-csi-snapshot-controller-operator" -OPTIONAL_COMPONENTS="cluster-monitoring-operator" declare -a ARCHS=("amd64" "arm64") declare -A GOARCH_TO_UNAME_MAP=( ["amd64"]="x86_64" ["arm64"]="aarch64" ) @@ -201,7 +200,7 @@ download_release() { component=$(echo "${line}" | cut -d ' ' -f 1) repo=$(echo "${line}" | cut -d ' ' -f 2) commit=$(echo "${line}" | cut -d ' ' -f 3) - if [[ "${EMBEDDED_COMPONENTS}" == *"${component}"* ]] || [[ "${LOADED_COMPONENTS}" == *"${component}"* ]] || [[ "${EMBEDDED_COMPONENT_OPERATORS}" == *"${component}"* ]] || [[ "${OPTIONAL_COMPONENTS}" == *"${component}"* ]]; then + if [[ "${EMBEDDED_COMPONENTS}" == *"${component}"* ]] || [[ "${LOADED_COMPONENTS}" == *"${component}"* ]] || [[ "${EMBEDDED_COMPONENT_OPERATORS}" == *"${component}"* ]]; then clone_repo "${repo}" "${commit}" "." echo "${repo} embedded-component ${commit}" >> "${new_commits_file}" echo @@ -664,6 +663,7 @@ copy_manifests() { "$REPOROOT/scripts/auto-rebase/handle_assets.py" "./scripts/auto-rebase/assets.yaml" } + # Updates embedded component manifests by gathering these from various places # in the staged repos and copying them into the asset directory. update_openshift_manifests() { @@ -921,7 +921,6 @@ EOF update_olm_images update_multus_images - update_metrics_images popd >/dev/null } @@ -1112,93 +1111,6 @@ EOF done # for goarch } -update_metrics_images() { - title "Rebasing metrics component images" - - # Maps kustomization image name -> OCP release tag name - declare -A METRICS_IMAGE_MAP=( - ["quay.io/openshift/kube-metrics-server"]="kube-metrics-server" - ["quay.io/openshift/kube-state-metrics"]="kube-state-metrics" - ["quay.io/openshift/node-exporter"]="prometheus-node-exporter" - ["quay.io/openshift/kube-rbac-proxy"]="kube-rbac-proxy" - ) - - # Maps component dir -> release JSON key -> OCP release tag name - declare -A METRICS_COMPONENT_JSON_KEY=( - ["metrics-server"]="metrics_server" - ["kube-state-metrics"]="kube_state_metrics" - ["node-exporter"]="node_exporter" - ) - - # Maps release JSON key -> OCP release tag name - declare -A METRICS_EXPORTER_JSON_MAP=( - ["metrics_server"]="kube-metrics-server" - ["kube_state_metrics"]="kube-state-metrics" - ["node_exporter"]="prometheus-node-exporter" - ) - - for goarch in amd64 arm64; do - arch=${GOARCH_TO_UNAME_MAP["${goarch}"]:-noarch} - - local release_file="${STAGING_DIR}/release_${goarch}.json" - - local base_release - base_release=$(jq -r ".metadata.version" "${release_file}") - - # Generate per-component release JSON and kustomization files - for component_dir in metrics-server kube-state-metrics node-exporter; do - [[ -d "${REPOROOT}/assets/optional/${component_dir}" ]] || continue - - # Generate per-component release JSON - local json_key="${METRICS_COMPONENT_JSON_KEY[$component_dir]}" - local release_tag="${METRICS_EXPORTER_JSON_MAP[$json_key]}" - local new_image - new_image=$(jq -r ".references.spec.tags[] | select(.name == \"${release_tag}\") | .from.name" "${release_file}") - if [[ -z "${new_image}" || "${new_image}" == "null" ]]; then - >&2 echo "ERROR: Release tag '${release_tag}' not found in payload for ${component_dir}" - return 1 - fi - local component_release_json="${REPOROOT}/assets/optional/${component_dir}/release-${component_dir}-${arch}.json" - jq -n --arg base "$base_release" --arg img "${new_image}" \ - "{\"release\": {\"base\": \$base}, \"images\": {\"${json_key}\": \$img}}" > "${component_release_json}" - - local kustomization_arch_file="${REPOROOT}/assets/optional/${component_dir}/kustomization.${arch}.yaml" - - cat < "${kustomization_arch_file}" -images: -EOF - - # Read image names from the base kustomization and deployment/daemonset - local image_names - image_names=$(grep -h 'image:' "${REPOROOT}/assets/optional/${component_dir}/"*.yaml 2>/dev/null \ - | sed 's/.*image: *//; s/:.*//; s/@.*//' | sort -u) - - for orig_image in ${image_names}; do - local release_tag="${METRICS_IMAGE_MAP[$orig_image]:-}" - if [[ -z "${release_tag}" ]]; then - >&2 echo "ERROR: Unknown metrics image '${orig_image}' in ${component_dir}" - return 1 - fi - - local new_image - new_image=$(jq -r ".references.spec.tags[] | select(.name == \"${release_tag}\") | .from.name" "${release_file}") - if [[ -z "${new_image}" || "${new_image}" == "null" ]]; then - >&2 echo "ERROR: Image for release tag '${release_tag}' not found in payload for ${component_dir}" - return 1 - fi - local new_image_name="${new_image%@*}" - local new_image_digest="${new_image#*@}" - - cat <> "${kustomization_arch_file}" - - name: ${orig_image} - newName: ${new_image_name} - digest: ${new_image_digest} -EOF - done - done - done -} - update_olm_images() { title "Rebasing operator-lifecycle-manager manifests" From 725e3ff2d00bc1a42f9987ec6062ebc21e3dd145 Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Fri, 19 Jun 2026 12:18:24 -0500 Subject: [PATCH 15/20] USHIFT-6951: add standalone cluster-monitoring-operator rebase script Add rebase_cluster_monitoring_operator.sh and its asset manifest for rebasing metrics exporters from the cluster-monitoring-operator repo. The script handles download, manifest copy, and image updates for all three exporters, keyed on which asset directories exist on the branch. Signed-off-by: Jonathan H. Cope --- .../assets_cluster_monitoring_operator.yaml | 35 ++ .../rebase_cluster_monitoring_operator.sh | 319 ++++++++++++++++++ 2 files changed, 354 insertions(+) create mode 100644 scripts/auto-rebase/assets_cluster_monitoring_operator.yaml create mode 100755 scripts/auto-rebase/rebase_cluster_monitoring_operator.sh diff --git a/scripts/auto-rebase/assets_cluster_monitoring_operator.yaml b/scripts/auto-rebase/assets_cluster_monitoring_operator.yaml new file mode 100644 index 0000000000..7fecda282e --- /dev/null +++ b/scripts/auto-rebase/assets_cluster_monitoring_operator.yaml @@ -0,0 +1,35 @@ +assets: + - dir: optional/metrics-server/ + no_clean: True + src: cluster-monitoring-operator/assets/metrics-server/ + files: + - file: 00-namespace.yaml + ignore: "Provided by MicroShift" + - file: 01-service-account.yaml + ignore: "Provided by MicroShift" + - file: 01-cluster-role.yaml + ignore: "Provided by MicroShift" + - file: 01-cluster-role-binding.yaml + ignore: "MicroShift adds User: system:metrics-server subject for dedicated kubelet client cert" + - file: 01-cluster-role-binding-auth-delegator.yaml + ignore: "Provided by MicroShift" + - file: 01-role-binding-auth-reader.yaml + ignore: "Provided by MicroShift" + - file: 02-configmap-audit-profiles.yaml + ignore: "Provided by MicroShift" + - file: 03-deployment.yaml + ignore: "MicroShift customizes replicas, strategy, image placeholder, and cert volumes" + - file: 04-service.yaml + ignore: "MicroShift uses service-ca annotation for serving cert" + - file: 04-api-service.yaml + ignore: "Provided by MicroShift" + - file: kustomization.yaml + ignore: "Provided by MicroShift" + - file: kustomization.x86_64.yaml + ignore: "Provided by MicroShift" + - file: kustomization.aarch64.yaml + ignore: "Provided by MicroShift" + - file: release-metrics-server-aarch64.json + ignore: "Provided by MicroShift" + - file: release-metrics-server-x86_64.json + ignore: "Provided by MicroShift" diff --git a/scripts/auto-rebase/rebase_cluster_monitoring_operator.sh b/scripts/auto-rebase/rebase_cluster_monitoring_operator.sh new file mode 100755 index 0000000000..0b039ce108 --- /dev/null +++ b/scripts/auto-rebase/rebase_cluster_monitoring_operator.sh @@ -0,0 +1,319 @@ +#!/usr/bin/env bash +# shellcheck disable=all +# Copyright 2022 The MicroShift authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set -o errexit +set -o errtrace +set -o nounset +set -o pipefail + +shopt -s expand_aliases +shopt -s extglob + +#debugging options +#trap 'echo "#L$LINENO: $BASH_COMMAND" >&2' DEBUG +#set -xo functrace +#PS4='+ $LINENO ' +REPOROOT="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")/../..")" +STAGING_DIR="$REPOROOT/_output/staging" +PULL_SECRET_FILE="${HOME}/.pull-secret.json" +REBASE_USE_SSH="${REBASE_USE_SSH:-false}" + +declare -a ARCHS=("amd64" "arm64") +declare -A GOARCH_TO_UNAME_MAP=( ["amd64"]="x86_64" ["arm64"]="aarch64" ) + +# Maps kustomization image name -> OCP release tag name +declare -A IMAGE_MAP=( + ["quay.io/openshift/kube-metrics-server"]="kube-metrics-server" + ["quay.io/openshift/kube-state-metrics"]="kube-state-metrics" + ["quay.io/openshift/node-exporter"]="prometheus-node-exporter" + ["quay.io/openshift/kube-rbac-proxy"]="kube-rbac-proxy" +) + +# Maps component dir -> release JSON key +declare -A COMPONENT_JSON_KEY=( + ["metrics-server"]="metrics_server" + ["kube-state-metrics"]="kube_state_metrics" + ["node-exporter"]="node_exporter" +) + +# Maps release JSON key -> OCP release tag name +declare -A EXPORTER_TAG_MAP=( + ["metrics_server"]="kube-metrics-server" + ["kube_state_metrics"]="kube-state-metrics" + ["node_exporter"]="prometheus-node-exporter" +) + +title() { + echo -e "\E[34m$1\E[00m"; +} + +retry_cmd() { + local -r max_attempts=5 + local timeout=1 + local attempt=1 + local exit_code=0 + + while (( attempt <= max_attempts )); do + if "$@"; then + return 0 + else + exit_code=$? + fi + echo "Attempt ${attempt} of ${max_attempts} failed (exit code ${exit_code}). Retrying in ${timeout}s..." + sleep "${timeout}" + attempt=$(( attempt + 1 )) + timeout=$(( timeout * 2 )) + done + + echo "Command failed after ${max_attempts} attempts: $@" + return "${exit_code}" +} + +check_preconditions() { + if ! hash yq; then + title "Installing yq" + sudo DEST_DIR=/usr/bin/ "${REPOROOT}/scripts/fetch_tools.sh" yq + fi + + if ! hash python3; then + echo "ERROR: python3 is not present on the system - please install" + exit 1 + fi + + if ! python3 -c "import yaml"; then + echo "ERROR: missing python's yaml library - please install" + exit 1 + fi +} + +clone_repo() { + local repo="$1" + local commit="$2" + local destdir="$3" + + local repodir="${destdir}/${repo##*/}" + + if [[ -d "${repodir}" ]]; then + return + fi + + if "${REBASE_USE_SSH}"; then + repo="git@github.com:${repo#https://github.com/}" + fi + + git init "${repodir}" + pushd "${repodir}" >/dev/null + git remote add origin "${repo}" + retry_cmd git fetch origin --quiet --filter=tree:0 --tags "${commit}" + git checkout "${commit}" + popd >/dev/null +} + +download_cluster_monitoring_operator() { + local release_image_amd64="$1" + local release_image_arm64="$2" + + rm -rf "${STAGING_DIR}" + mkdir -p "${STAGING_DIR}" + pushd "${STAGING_DIR}" >/dev/null + + local authentication="" + if [[ -f "${PULL_SECRET_FILE}" ]]; then + authentication="-a ${PULL_SECRET_FILE}" + else + >&2 echo "Warning: no pull secret found at ${PULL_SECRET_FILE}" + fi + + title "# Fetching release info for ${release_image_amd64} (amd64)" + oc adm release info ${authentication} "${release_image_amd64}" -o json > release_amd64.json + title "# Fetching release info for ${release_image_arm64} (arm64)" + oc adm release info ${authentication} "${release_image_arm64}" -o json > release_arm64.json + + title "# Extracting cluster-monitoring-operator source commit" + cat release_amd64.json \ + | jq -r '.references.spec.tags[] | "\(.name) \(.annotations."io.openshift.build.source-location") \(.annotations."io.openshift.build.commit.id")"' > source-commits + + local cmo_line + cmo_line=$(grep '^cluster-monitoring-operator ' source-commits) || { + >&2 echo "ERROR: cluster-monitoring-operator not found in release payload" + return 1 + } + + local repo commit + repo=$(echo "${cmo_line}" | cut -d ' ' -f 2) + commit=$(echo "${cmo_line}" | cut -d ' ' -f 3) + + title "# Cloning cluster-monitoring-operator at ${commit}" + clone_repo "${repo}" "${commit}" "." + + popd >/dev/null +} + +update_node_exporter_manifests() { + [[ -d "${REPOROOT}/assets/optional/node-exporter" ]] || return 0 + + title "Rebasing node-exporter manifests" + + local ne_ds="${REPOROOT}/assets/optional/node-exporter/03-daemonset.yaml" + + yq -i '.spec.template.spec.containers[0].image = "quay.io/openshift/node-exporter"' "$ne_ds" + yq -i '.spec.template.spec.containers[1].image = "quay.io/openshift/kube-rbac-proxy"' "$ne_ds" + yq -i '.spec.template.spec.initContainers[0].image = "quay.io/openshift/node-exporter"' "$ne_ds" + + yq -i '(.spec.template.spec.containers[1].args[] | select(test("--secure-listen-address="))) |= "--secure-listen-address=0.0.0.0:9100"' "$ne_ds" + + yq -i '(.spec.template.spec.containers[1].args[] | select(test("--client-ca-file="))) |= "--client-ca-file=/etc/tls/client-ca/ca.crt"' "$ne_ds" + yq -i 'del(.spec.template.spec.volumes[] | select(.name == "metrics-client-ca"))' "$ne_ds" + yq -i '.spec.template.spec.volumes += [{"hostPath": {"path": "/var/lib/microshift/certs/admin-kubeconfig-signer/ca.crt", "type": "File"}, "name": "admin-kubeconfig-signer-ca"}]' "$ne_ds" + yq -i 'del(.spec.template.spec.containers[1].volumeMounts[] | select(.name == "metrics-client-ca"))' "$ne_ds" + yq -i '.spec.template.spec.containers[1].volumeMounts += [{"mountPath": "/etc/tls/client-ca/ca.crt", "name": "admin-kubeconfig-signer-ca", "readOnly": true}]' "$ne_ds" + + yq -i '(.spec.template.spec.containers[1].volumeMounts[] | select(.name == "node-exporter-tls")).readOnly = true' "$ne_ds" + + local ne_secret="${REPOROOT}/assets/optional/node-exporter/02-kube-rbac-proxy-secret.yaml" + sed -i '/"user":/,/"name":/d' "$ne_secret" +} + +update_cluster_monitoring_operator_images() { + title "Rebasing metrics component images" + + for goarch in amd64 arm64; do + local arch=${GOARCH_TO_UNAME_MAP["${goarch}"]:-noarch} + local release_file="${STAGING_DIR}/release_${goarch}.json" + + local base_release + base_release=$(jq -r ".metadata.version" "${release_file}") + + for component_dir in metrics-server kube-state-metrics node-exporter; do + [[ -d "${REPOROOT}/assets/optional/${component_dir}" ]] || continue + + local json_key="${COMPONENT_JSON_KEY[$component_dir]}" + local release_tag="${EXPORTER_TAG_MAP[$json_key]}" + local new_image + new_image=$(jq -r ".references.spec.tags[] | select(.name == \"${release_tag}\") | .from.name" "${release_file}") + if [[ -z "${new_image}" || "${new_image}" == "null" ]]; then + >&2 echo "ERROR: Release tag '${release_tag}' not found in payload for ${component_dir}" + return 1 + fi + local component_release_json="${REPOROOT}/assets/optional/${component_dir}/release-${component_dir}-${arch}.json" + jq -n --arg base "$base_release" --arg img "${new_image}" \ + "{\"release\": {\"base\": \$base}, \"images\": {\"${json_key}\": \$img}}" > "${component_release_json}" + + local kustomization_arch_file="${REPOROOT}/assets/optional/${component_dir}/kustomization.${arch}.yaml" + + cat < "${kustomization_arch_file}" +images: +EOF + + local image_names + image_names=$(grep -h 'image:' "${REPOROOT}/assets/optional/${component_dir}/"*.yaml 2>/dev/null \ + | sed 's/.*image: *//; s/:.*//; s/@.*//' | sort -u) + + for orig_image in ${image_names}; do + local release_tag="${IMAGE_MAP[$orig_image]:-}" + if [[ -z "${release_tag}" ]]; then + >&2 echo "ERROR: Unknown metrics image '${orig_image}' in ${component_dir}" + return 1 + fi + + local new_image + new_image=$(jq -r ".references.spec.tags[] | select(.name == \"${release_tag}\") | .from.name" "${release_file}") + if [[ -z "${new_image}" || "${new_image}" == "null" ]]; then + >&2 echo "ERROR: Image for release tag '${release_tag}' not found in payload for ${component_dir}" + return 1 + fi + local new_image_name="${new_image%@*}" + local new_image_digest="${new_image#*@}" + + cat <> "${kustomization_arch_file}" + - name: ${orig_image} + newName: ${new_image_name} + digest: ${new_image_digest} +EOF + done + done + done +} + +copy_manifests() { + title "Copying manifests" + "$REPOROOT/scripts/auto-rebase/handle_assets.py" "./scripts/auto-rebase/assets_cluster_monitoring_operator.yaml" +} + +update_last_rebase() { + local release_image_amd64="$1" + local release_image_arm64="$2" + + title "## Updating last_rebase_cluster_monitoring_operator.sh" + + local last_rebase_script="${REPOROOT}/scripts/auto-rebase/last_rebase_cluster_monitoring_operator.sh" + + rm -f "${last_rebase_script}" + cat - >"${last_rebase_script}" < Date: Fri, 19 Jun 2026 12:36:23 -0500 Subject: [PATCH 16/20] update last_rebase_cluster_monitoring_operator.sh --- scripts/auto-rebase/last_rebase_cluster_monitoring_operator.sh | 2 ++ 1 file changed, 2 insertions(+) create mode 100755 scripts/auto-rebase/last_rebase_cluster_monitoring_operator.sh diff --git a/scripts/auto-rebase/last_rebase_cluster_monitoring_operator.sh b/scripts/auto-rebase/last_rebase_cluster_monitoring_operator.sh new file mode 100755 index 0000000000..f61200df82 --- /dev/null +++ b/scripts/auto-rebase/last_rebase_cluster_monitoring_operator.sh @@ -0,0 +1,2 @@ +#!/bin/bash -x +./scripts/auto-rebase/rebase_cluster_monitoring_operator.sh to "registry.ci.openshift.org/ocp/release-5:5.0.0-0.nightly-2026-06-19-155631" "registry.ci.openshift.org/ocp-arm64/release-5-arm64:5.0.0-0.nightly-arm64-2026-06-19-154904" From 79bfb1ed9a038dff673ff69bf10fc67bd754ac07 Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Fri, 19 Jun 2026 16:42:46 -0500 Subject: [PATCH 17/20] to simply merging of the components the CMO rebase script is now identical across the 3 PRs Signed-off-by: Jonathan H. Cope --- .../assets_cluster_monitoring_operator.yaml | 32 +++++----- .../rebase_cluster_monitoring_operator.sh | 58 ++++++++++++++++++- 2 files changed, 74 insertions(+), 16 deletions(-) diff --git a/scripts/auto-rebase/assets_cluster_monitoring_operator.yaml b/scripts/auto-rebase/assets_cluster_monitoring_operator.yaml index 7fecda282e..9a86ad1eac 100644 --- a/scripts/auto-rebase/assets_cluster_monitoring_operator.yaml +++ b/scripts/auto-rebase/assets_cluster_monitoring_operator.yaml @@ -4,32 +4,34 @@ assets: src: cluster-monitoring-operator/assets/metrics-server/ files: - file: 00-namespace.yaml - ignore: "Provided by MicroShift" + ignore: "MicroShift-specific, no upstream equivalent" + git_restore: True - file: 01-service-account.yaml - ignore: "Provided by MicroShift" + src: service-account.yaml - file: 01-cluster-role.yaml - ignore: "Provided by MicroShift" + src: cluster-role.yaml - file: 01-cluster-role-binding.yaml - ignore: "MicroShift adds User: system:metrics-server subject for dedicated kubelet client cert" + src: cluster-role-binding.yaml - file: 01-cluster-role-binding-auth-delegator.yaml - ignore: "Provided by MicroShift" + src: cluster-role-binding-auth-delegator.yaml - file: 01-role-binding-auth-reader.yaml - ignore: "Provided by MicroShift" + src: role-binding-auth-reader.yaml - file: 02-configmap-audit-profiles.yaml - ignore: "Provided by MicroShift" + src: configmap-audit-profiles.yaml - file: 03-deployment.yaml - ignore: "MicroShift customizes replicas, strategy, image placeholder, and cert volumes" + src: deployment.yaml - file: 04-service.yaml - ignore: "MicroShift uses service-ca annotation for serving cert" + src: service.yaml - file: 04-api-service.yaml - ignore: "Provided by MicroShift" + src: api-service.yaml - file: kustomization.yaml - ignore: "Provided by MicroShift" + ignore: "MicroShift-specific kustomization" + git_restore: True - file: kustomization.x86_64.yaml - ignore: "Provided by MicroShift" + ignore: "gets generated during image rebase" - file: kustomization.aarch64.yaml - ignore: "Provided by MicroShift" + ignore: "gets generated during image rebase" - file: release-metrics-server-aarch64.json - ignore: "Provided by MicroShift" + ignore: "gets generated during image rebase" - file: release-metrics-server-x86_64.json - ignore: "Provided by MicroShift" + ignore: "gets generated during image rebase" diff --git a/scripts/auto-rebase/rebase_cluster_monitoring_operator.sh b/scripts/auto-rebase/rebase_cluster_monitoring_operator.sh index 0b039ce108..be1124f04e 100755 --- a/scripts/auto-rebase/rebase_cluster_monitoring_operator.sh +++ b/scripts/auto-rebase/rebase_cluster_monitoring_operator.sh @@ -163,6 +163,58 @@ download_cluster_monitoring_operator() { popd >/dev/null } +update_metrics_server_manifests() { + [[ -d "${REPOROOT}/assets/optional/metrics-server" ]] || return 0 + + title "Rebasing metrics-server manifests" + + local ms_crb="${REPOROOT}/assets/optional/metrics-server/01-cluster-role-binding.yaml" + yq -i '.subjects += [{"kind": "User", "name": "system:metrics-server"}]' "$ms_crb" + + local ms_deploy="${REPOROOT}/assets/optional/metrics-server/03-deployment.yaml" + yq -i '.spec.replicas = 1' "$ms_deploy" + yq -i '.spec.strategy = {"type": "Recreate"}' "$ms_deploy" + yq -i 'del(.spec.template.spec.affinity)' "$ms_deploy" + yq -i '.spec.template.spec.containers[0].image = "quay.io/openshift/kube-metrics-server"' "$ms_deploy" + yq -i '.spec.template.spec.containers[0].securityContext.capabilities.drop = ["ALL"]' "$ms_deploy" +} + +update_kube_state_metrics_manifests() { + [[ -d "${REPOROOT}/assets/optional/kube-state-metrics" ]] || return 0 + + title "Rebasing kube-state-metrics manifests" + + local ksm_deploy="${REPOROOT}/assets/optional/kube-state-metrics/03-deployment.yaml" + + yq -i '.spec.template.spec.containers[0].image = "quay.io/openshift/kube-state-metrics"' "$ksm_deploy" + yq -i '.spec.template.spec.containers[1].image = "quay.io/openshift/kube-rbac-proxy"' "$ksm_deploy" + yq -i '.spec.template.spec.containers[2].image = "quay.io/openshift/kube-rbac-proxy"' "$ksm_deploy" + + yq -i '.spec.template.spec.containers[0].securityContext = {"allowPrivilegeEscalation": false, "readOnlyRootFilesystem": true, "runAsNonRoot": true}' "$ksm_deploy" + yq -i '.spec.template.spec.containers[1].securityContext = {"allowPrivilegeEscalation": false, "readOnlyRootFilesystem": true, "runAsNonRoot": true}' "$ksm_deploy" + yq -i '.spec.template.spec.containers[2].securityContext = {"allowPrivilegeEscalation": false, "readOnlyRootFilesystem": true, "runAsNonRoot": true}' "$ksm_deploy" + yq -i '.spec.template.spec.securityContext = {"runAsNonRoot": true}' "$ksm_deploy" + + yq -i '.spec.template.spec.containers[0].resources.limits = {"cpu": "100m", "memory": "200Mi"}' "$ksm_deploy" + yq -i '.spec.template.spec.containers[1].resources.limits = {"cpu": "20m", "memory": "40Mi"}' "$ksm_deploy" + yq -i '.spec.template.spec.containers[2].resources.limits = {"cpu": "20m", "memory": "40Mi"}' "$ksm_deploy" + + yq -i '(.spec.template.spec.containers[1].volumeMounts[] | select(.name == "kube-state-metrics-tls")).readOnly = true' "$ksm_deploy" + yq -i '(.spec.template.spec.containers[2].volumeMounts[] | select(.name == "kube-state-metrics-tls")).readOnly = true' "$ksm_deploy" + + yq -i '(.spec.template.spec.containers[1].args[] | select(test("--client-ca-file="))) |= "--client-ca-file=/etc/tls/client-ca/ca.crt"' "$ksm_deploy" + yq -i '(.spec.template.spec.containers[2].args[] | select(test("--client-ca-file="))) |= "--client-ca-file=/etc/tls/client-ca/ca.crt"' "$ksm_deploy" + yq -i 'del(.spec.template.spec.volumes[] | select(.name == "metrics-client-ca"))' "$ksm_deploy" + yq -i '.spec.template.spec.volumes += [{"hostPath": {"path": "/var/lib/microshift/certs/admin-kubeconfig-signer/ca.crt", "type": "File"}, "name": "admin-kubeconfig-signer-ca"}]' "$ksm_deploy" + yq -i 'del(.spec.template.spec.containers[1].volumeMounts[] | select(.name == "metrics-client-ca"))' "$ksm_deploy" + yq -i 'del(.spec.template.spec.containers[2].volumeMounts[] | select(.name == "metrics-client-ca"))' "$ksm_deploy" + yq -i '.spec.template.spec.containers[1].volumeMounts += [{"mountPath": "/etc/tls/client-ca/ca.crt", "name": "admin-kubeconfig-signer-ca", "readOnly": true}]' "$ksm_deploy" + yq -i '.spec.template.spec.containers[2].volumeMounts += [{"mountPath": "/etc/tls/client-ca/ca.crt", "name": "admin-kubeconfig-signer-ca", "readOnly": true}]' "$ksm_deploy" + + local ksm_secret="${REPOROOT}/assets/optional/kube-state-metrics/02-kube-rbac-proxy-secret.yaml" + sed -i '/"user":/,/"name":/d' "$ksm_secret" +} + update_node_exporter_manifests() { [[ -d "${REPOROOT}/assets/optional/node-exporter" ]] || return 0 @@ -221,7 +273,7 @@ EOF local image_names image_names=$(grep -h 'image:' "${REPOROOT}/assets/optional/${component_dir}/"*.yaml 2>/dev/null \ - | sed 's/.*image: *//; s/:.*//; s/@.*//' | sort -u) + | sed 's/.*image: *//; s/"//g; s/:.*//; s/@.*//' | sort -u | grep -v '^$') for orig_image in ${image_names}; do local release_tag="${IMAGE_MAP[$orig_image]:-}" @@ -282,6 +334,8 @@ rebase_cluster_monitoring_operator_to() { local release_image_arm64="$2" download_cluster_monitoring_operator "${release_image_amd64}" "${release_image_arm64}" copy_manifests + update_metrics_server_manifests + update_kube_state_metrics_manifests update_node_exporter_manifests update_cluster_monitoring_operator_images update_last_rebase "${release_image_amd64}" "${release_image_arm64}" @@ -313,6 +367,8 @@ case "$command" in ;; manifests) copy_manifests + update_metrics_server_manifests + update_kube_state_metrics_manifests update_node_exporter_manifests ;; *) usage;; From 483953f3ce5552b5fd2aaf6ba532f0767cea4919 Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Fri, 19 Jun 2026 16:43:37 -0500 Subject: [PATCH 18/20] executed rebase script Signed-off-by: Jonathan H. Cope --- .../01-cluster-role-binding.yaml | 10 +- .../02-configmap-audit-profiles.yaml | 56 +++---- .../metrics-server/03-deployment.yaml | 152 +++++++++--------- .../metrics-server/kustomization.aarch64.yaml | 2 +- .../metrics-server/kustomization.x86_64.yaml | 2 +- .../release-metrics-server-aarch64.json | 4 +- .../release-metrics-server-x86_64.json | 4 +- 7 files changed, 115 insertions(+), 115 deletions(-) diff --git a/assets/optional/metrics-server/01-cluster-role-binding.yaml b/assets/optional/metrics-server/01-cluster-role-binding.yaml index 8a32b85158..0bf14bd3e2 100644 --- a/assets/optional/metrics-server/01-cluster-role-binding.yaml +++ b/assets/optional/metrics-server/01-cluster-role-binding.yaml @@ -11,8 +11,8 @@ roleRef: kind: ClusterRole name: system:metrics-server subjects: -- kind: ServiceAccount - name: metrics-server - namespace: openshift-monitoring -- kind: User - name: system:metrics-server + - kind: ServiceAccount + name: metrics-server + namespace: openshift-monitoring + - kind: User + name: system:metrics-server diff --git a/assets/optional/metrics-server/02-configmap-audit-profiles.yaml b/assets/optional/metrics-server/02-configmap-audit-profiles.yaml index 1d8761e393..1cff598a6d 100644 --- a/assets/optional/metrics-server/02-configmap-audit-profiles.yaml +++ b/assets/optional/metrics-server/02-configmap-audit-profiles.yaml @@ -1,41 +1,41 @@ apiVersion: v1 data: metadata-profile.yaml: |- - apiVersion: "audit.k8s.io/v1" - kind: "Policy" - metadata: - name: "Metadata" - omitStages: + "apiVersion": "audit.k8s.io/v1" + "kind": "Policy" + "metadata": + "name": "Metadata" + "omitStages": - "RequestReceived" - rules: - - level: "Metadata" + "rules": + - "level": "Metadata" none-profile.yaml: |- - apiVersion: "audit.k8s.io/v1" - kind: "Policy" - metadata: - name: "None" - omitStages: + "apiVersion": "audit.k8s.io/v1" + "kind": "Policy" + "metadata": + "name": "None" + "omitStages": - "RequestReceived" - rules: - - level: "None" + "rules": + - "level": "None" request-profile.yaml: |- - apiVersion: "audit.k8s.io/v1" - kind: "Policy" - metadata: - name: "Request" - omitStages: + "apiVersion": "audit.k8s.io/v1" + "kind": "Policy" + "metadata": + "name": "Request" + "omitStages": - "RequestReceived" - rules: - - level: "Request" + "rules": + - "level": "Request" requestresponse-profile.yaml: |- - apiVersion: "audit.k8s.io/v1" - kind: "Policy" - metadata: - name: "RequestResponse" - omitStages: + "apiVersion": "audit.k8s.io/v1" + "kind": "Policy" + "metadata": + "name": "RequestResponse" + "omitStages": - "RequestReceived" - rules: - - level: "RequestResponse" + "rules": + - "level": "RequestResponse" kind: ConfigMap metadata: labels: diff --git a/assets/optional/metrics-server/03-deployment.yaml b/assets/optional/metrics-server/03-deployment.yaml index 23cdafb3e1..1830ee8fc2 100644 --- a/assets/optional/metrics-server/03-deployment.yaml +++ b/assets/optional/metrics-server/03-deployment.yaml @@ -28,87 +28,87 @@ spec: app.kubernetes.io/part-of: openshift-monitoring spec: containers: - - args: - - --secure-port=10250 - - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname - - --kubelet-use-node-status-port - - --metric-resolution=15s - - --kubelet-certificate-authority=/etc/tls/kubelet-serving-ca-bundle/ca-bundle.crt - - --kubelet-client-certificate=/etc/tls/metrics-server-client-certs/tls.crt - - --kubelet-client-key=/etc/tls/metrics-server-client-certs/tls.key - - --tls-cert-file=/etc/tls/private/tls.crt - - --tls-private-key-file=/etc/tls/private/tls.key - - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 - - --shutdown-send-retry-after=true - - --shutdown-delay-duration=150s - - --disable-http2-serving=true - image: quay.io/openshift/kube-metrics-server - imagePullPolicy: IfNotPresent - livenessProbe: - failureThreshold: 3 - httpGet: - path: /livez - port: https - scheme: HTTPS - periodSeconds: 10 - name: metrics-server - ports: - - containerPort: 10250 - name: https - protocol: TCP - readinessProbe: - failureThreshold: 6 - httpGet: - path: /readyz - port: https - scheme: HTTPS - initialDelaySeconds: 20 - periodSeconds: 20 - resources: - requests: - cpu: 1m - memory: 40Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - terminationMessagePolicy: FallbackToLogsOnError - volumeMounts: - - mountPath: /etc/tls/private - name: secret-metrics-server-tls - - mountPath: /etc/tls/metrics-server-client-certs - name: secret-metrics-server-client-certs - - mountPath: /etc/tls/kubelet-serving-ca-bundle - name: configmap-kubelet-serving-ca-bundle - - mountPath: /etc/audit - name: metrics-server-audit-profiles - readOnly: true - - mountPath: /var/log/metrics-server - name: audit-log - readOnly: false + - args: + - --secure-port=10250 + - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname + - --kubelet-use-node-status-port + - --metric-resolution=15s + - --kubelet-certificate-authority=/etc/tls/kubelet-serving-ca-bundle/ca-bundle.crt + - --kubelet-client-certificate=/etc/tls/metrics-server-client-certs/tls.crt + - --kubelet-client-key=/etc/tls/metrics-server-client-certs/tls.key + - --tls-cert-file=/etc/tls/private/tls.crt + - --tls-private-key-file=/etc/tls/private/tls.key + - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 + - --shutdown-send-retry-after=true + - --shutdown-delay-duration=150s + - --disable-http2-serving=true + image: "quay.io/openshift/kube-metrics-server" + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 3 + httpGet: + path: /livez + port: https + scheme: HTTPS + periodSeconds: 10 + name: metrics-server + ports: + - containerPort: 10250 + name: https + protocol: TCP + readinessProbe: + failureThreshold: 6 + httpGet: + path: /readyz + port: https + scheme: HTTPS + initialDelaySeconds: 20 + periodSeconds: 20 + resources: + requests: + cpu: 1m + memory: 40Mi + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: + - ALL + terminationMessagePolicy: FallbackToLogsOnError + volumeMounts: + - mountPath: /etc/tls/private + name: secret-metrics-server-tls + - mountPath: /etc/tls/metrics-server-client-certs + name: secret-metrics-server-client-certs + - mountPath: /etc/tls/kubelet-serving-ca-bundle + name: configmap-kubelet-serving-ca-bundle + - mountPath: /etc/audit + name: metrics-server-audit-profiles + readOnly: true + - mountPath: /var/log/metrics-server + name: audit-log + readOnly: false nodeSelector: kubernetes.io/os: linux priorityClassName: system-cluster-critical serviceAccountName: metrics-server terminationGracePeriodSeconds: 170 tolerations: - - effect: NoSchedule - key: node-role.kubernetes.io/master + - effect: NoSchedule + key: node-role.kubernetes.io/master volumes: - - name: secret-metrics-server-client-certs - secret: - secretName: metrics-server-client-certs - - name: secret-metrics-server-tls - secret: - secretName: metrics-server-tls - - configMap: - name: kubelet-serving-ca-bundle - name: configmap-kubelet-serving-ca-bundle - - emptyDir: {} - name: audit-log - - configMap: + - name: secret-metrics-server-client-certs + secret: + secretName: metrics-server-client-certs + - name: secret-metrics-server-tls + secret: + secretName: metrics-server-tls + - configMap: + name: kubelet-serving-ca-bundle + name: configmap-kubelet-serving-ca-bundle + - emptyDir: {} + name: audit-log + - configMap: + name: metrics-server-audit-profiles name: metrics-server-audit-profiles - name: metrics-server-audit-profiles diff --git a/assets/optional/metrics-server/kustomization.aarch64.yaml b/assets/optional/metrics-server/kustomization.aarch64.yaml index 694213e29a..0a79cdb357 100644 --- a/assets/optional/metrics-server/kustomization.aarch64.yaml +++ b/assets/optional/metrics-server/kustomization.aarch64.yaml @@ -1,4 +1,4 @@ images: - name: quay.io/openshift/kube-metrics-server newName: quay.io/openshift-release-dev/ocp-v5.0-art-dev - digest: sha256:80743f7b701994e9bffcdbccccf31815d506a322bacd6edf16b4dcd01d3686ba + digest: sha256:790dcea1d4cf5eb3a989bf3d14d460148d23a743951644668a300b7fc21f29ec diff --git a/assets/optional/metrics-server/kustomization.x86_64.yaml b/assets/optional/metrics-server/kustomization.x86_64.yaml index b770c95d2d..49529cad12 100644 --- a/assets/optional/metrics-server/kustomization.x86_64.yaml +++ b/assets/optional/metrics-server/kustomization.x86_64.yaml @@ -1,4 +1,4 @@ images: - name: quay.io/openshift/kube-metrics-server newName: quay.io/openshift-release-dev/ocp-v5.0-art-dev - digest: sha256:cabd43c39e5bcc2f8326e5db8e0a91ddae4cfcd2e206ff18c49df934346f8014 + digest: sha256:0590e13d7955f71db964f601f5ce6c66416a1e2e5acee5c2831f41fb2b13435c diff --git a/assets/optional/metrics-server/release-metrics-server-aarch64.json b/assets/optional/metrics-server/release-metrics-server-aarch64.json index 6009b817b9..c12ffcbb53 100644 --- a/assets/optional/metrics-server/release-metrics-server-aarch64.json +++ b/assets/optional/metrics-server/release-metrics-server-aarch64.json @@ -1,8 +1,8 @@ { "release": { - "base": "5.0.0-0.nightly-arm64-2026-06-14-225436" + "base": "5.0.0-0.nightly-arm64-2026-06-19-154904" }, "images": { - "metrics_server": "quay.io/openshift-release-dev/ocp-v5.0-art-dev@sha256:80743f7b701994e9bffcdbccccf31815d506a322bacd6edf16b4dcd01d3686ba" + "metrics_server": "quay.io/openshift-release-dev/ocp-v5.0-art-dev@sha256:790dcea1d4cf5eb3a989bf3d14d460148d23a743951644668a300b7fc21f29ec" } } diff --git a/assets/optional/metrics-server/release-metrics-server-x86_64.json b/assets/optional/metrics-server/release-metrics-server-x86_64.json index d64aab1619..57ab6cbd6a 100644 --- a/assets/optional/metrics-server/release-metrics-server-x86_64.json +++ b/assets/optional/metrics-server/release-metrics-server-x86_64.json @@ -1,8 +1,8 @@ { "release": { - "base": "5.0.0-0.nightly-2026-06-14-221055" + "base": "5.0.0-0.nightly-2026-06-19-155631" }, "images": { - "metrics_server": "quay.io/openshift-release-dev/ocp-v5.0-art-dev@sha256:cabd43c39e5bcc2f8326e5db8e0a91ddae4cfcd2e206ff18c49df934346f8014" + "metrics_server": "quay.io/openshift-release-dev/ocp-v5.0-art-dev@sha256:0590e13d7955f71db964f601f5ce6c66416a1e2e5acee5c2831f41fb2b13435c" } } From 4e3774ee8ba15fb644044d0f90cdae6b07353bec Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Mon, 22 Jun 2026 10:50:59 -0500 Subject: [PATCH 19/20] remove errant otel-conf (out of scope), normalize assets files to KSM and NE files Signed-off-by: Jonathan H. Cope --- scripts/auto-rebase/assets_cluster_monitoring_operator.yaml | 4 ++-- test/assets/observability/otel_config.yaml | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/scripts/auto-rebase/assets_cluster_monitoring_operator.yaml b/scripts/auto-rebase/assets_cluster_monitoring_operator.yaml index 9a86ad1eac..b252b3ef12 100644 --- a/scripts/auto-rebase/assets_cluster_monitoring_operator.yaml +++ b/scripts/auto-rebase/assets_cluster_monitoring_operator.yaml @@ -31,7 +31,7 @@ assets: ignore: "gets generated during image rebase" - file: kustomization.aarch64.yaml ignore: "gets generated during image rebase" - - file: release-metrics-server-aarch64.json - ignore: "gets generated during image rebase" - file: release-metrics-server-x86_64.json ignore: "gets generated during image rebase" + - file: release-metrics-server-aarch64.json + ignore: "gets generated during image rebase" diff --git a/test/assets/observability/otel_config.yaml b/test/assets/observability/otel_config.yaml index 25609b2d17..4565f82077 100644 --- a/test/assets/observability/otel_config.yaml +++ b/test/assets/observability/otel_config.yaml @@ -59,10 +59,6 @@ exporters: enabled: true otlphttp/loki: # only for logs, exports the logs in the loki server endpoint: "http://{{LOKI_HOST}}:{{LOKI_PORT}}/otlp" - otlp: - endpoint: "localhost:4317" - tls: - insecure: true extensions: file_storage: From cd8990dac818f29dc14ed1152e3e81ece036d444 Mon Sep 17 00:00:00 2001 From: "Jonathan H. Cope" Date: Mon, 22 Jun 2026 11:08:09 -0500 Subject: [PATCH 20/20] update etcd vendor Signed-off-by: Jonathan H. Cope --- .../openshift/microshift/pkg/util/cryptomaterial/certinfo.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/etcd/vendor/github.com/openshift/microshift/pkg/util/cryptomaterial/certinfo.go b/etcd/vendor/github.com/openshift/microshift/pkg/util/cryptomaterial/certinfo.go index 4e8c50989e..12c413d114 100644 --- a/etcd/vendor/github.com/openshift/microshift/pkg/util/cryptomaterial/certinfo.go +++ b/etcd/vendor/github.com/openshift/microshift/pkg/util/cryptomaterial/certinfo.go @@ -171,6 +171,10 @@ func KubeletClientCAPath(certsDir string) string { return filepath.Join(certsDir, "ca-bundle", "kubelet-ca.crt") } +func KubeletServingCAPath(certsDir string) string { + return filepath.Join(certsDir, "ca-bundle", "kubelet-serving-ca.crt") +} + func ServiceAccountTokenCABundlePath(certsDir string) string { return filepath.Join(certsDir, "ca-bundle", "service-account-token-ca.crt") }