×

OpenShift Container Platform 4.18 supports Operator SDK 1.38.0. If you already have the 1.36.1 CLI installed on your workstation, you can update the CLI to 1.38.0 by installing the latest version.

The Red Hat-supported version of the Operator SDK CLI tool, including the related scaffolding and testing tools for Operator projects, is deprecated and is planned to be removed in a future release of OpenShift Container Platform. Red Hat will provide bug fixes and support for this feature during the current release lifecycle, but this feature will no longer receive enhancements and will be removed from future OpenShift Container Platform releases.

The Red Hat-supported version of the Operator SDK is not recommended for creating new Operator projects. Operator authors with existing Operator projects can use the version of the Operator SDK CLI tool released with OpenShift Container Platform 4.18 to maintain their projects and create Operator releases targeting newer versions of OpenShift Container Platform.

The following related base images for Operator projects are not deprecated. The runtime functionality and configuration APIs for these base images are still supported for bug fixes and for addressing CVEs.

  • The base image for Ansible-based Operator projects

  • The base image for Helm-based Operator projects

For the most recent list of major functionality that has been deprecated or removed within OpenShift Container Platform, refer to the Deprecated and removed features section of the OpenShift Container Platform release notes.

For information about the unsupported, community-maintained, version of the Operator SDK, see Operator SDK (Operator Framework).

However, to ensure your existing Operator projects maintain compatibility with Operator SDK 1.38.0, update steps are required for the associated breaking changes introduced since 1.36.1. You must perform the update steps manually in any of your Operator projects that were previously created or maintained with 1.36.1.

Updating Go-based Operator projects for Operator SDK 1.38.0

The following procedure updates an existing Go-based Operator project for compatibility with 1.38.0.

Prerequisites
  • Operator SDK 1.38.0 installed

  • An Operator project created or maintained with Operator SDK 1.36.1

Procedure
  1. Edit the Makefile of your Operator project to update the Operator SDK version to 1.38.0, as shown in the following example:

    Example Makefile
    # Set the Operator SDK version to use. By default, what is installed on the system is used.
    # This is useful for CI or a project to utilize a specific version of the operator-sdk toolkit.
    OPERATOR_SDK_VERSION ?= v1.38.0 (1)
    1 Change the version from 1.36.1 to 1.38.0.
  2. You must upgrade the Kubernetes versions in your Operator project to use 1.30 and Kubebuilder v4.

    This update include complex scaffolding changes due to the removal of kube-rbac-proxy. If these migrations become difficult to follow, scaffold a new sample project for comparison.

    1. Update your go.mod file with the following changes to upgrade your dependencies:

      go 1.22.0
      
      github.com/onsi/ginkgo/v2 v2.17.1
      github.com/onsi/gomega v1.32.0
      k8s.io/api v0.30.1
      k8s.io/apimachinery v0.30.1
      k8s.io/client-go v0.30.1
      sigs.k8s.io/controller-runtime v0.18.4
    2. Download the upgraded dependencies by running the following command:

      $ go mod tidy
    3. Update your Makefile with the following changes:

      - ENVTEST_K8S_VERSION = 1.29.0
      + ENVTEST_K8S_VERSION = 1.30.0
      - KUSTOMIZE ?= $(LOCALBIN)/kustomize-$(KUSTOMIZE_VERSION)
      - CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen-$(CONTROLLER_TOOLS_VERSION)
      - ENVTEST ?= $(LOCALBIN)/setup-envtest-$(ENVTEST_VERSION)
      - GOLANGCI_LINT = $(LOCALBIN)/golangci-lint-$(GOLANGCI_LINT_VERSION)
      + KUSTOMIZE ?= $(LOCALBIN)/kustomize
      + CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
      + ENVTEST ?= $(LOCALBIN)/setup-envtest
      + GOLANGCI_LINT = $(LOCALBIN)/golangci-lint
      - KUSTOMIZE_VERSION ?= v5.3.0
      - CONTROLLER_TOOLS_VERSION ?= v0.14.0
      - ENVTEST_VERSION ?= release-0.17
      - GOLANGCI_LINT_VERSION ?= v1.57.2
      + KUSTOMIZE_VERSION ?= v5.4.2
      + CONTROLLER_TOOLS_VERSION ?= v0.15.0
      + ENVTEST_VERSION ?= release-0.18
      + GOLANGCI_LINT_VERSION ?= v1.59.1
      - $(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,${GOLANGCI_LINT_VERSION})
      + $(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION))
      - $(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,${GOLANGCI_LINT_VERSION})
      + $(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION))
      - @[ -f $(1) ] || { \
      + @[ -f "$(1)-$(3)" ] || { \
        echo "Downloading $${package}" ;\
      + rm -f $(1) || true ;\
      - mv "$$(echo "$(1)" | sed "s/-$(3)$$//")" $(1) ;\
      - }
      + mv $(1) $(1)-$(3) ;\
      + } ;\
      + ln -sf $(1)-$(3) $(1)
    4. Update your .golangci.yml file with the following changes:

      -  exportloopref
      +     - ginkgolinter
            - prealloc
      +     - revive
      +
      + linters-settings:
      +   revive:
      +     rules:
      +       - name: comment-spacings
    5. Update your Dockerfile with the following changes:

      - FROM golang:1.21 AS builder
      + FROM golang:1.22 AS builder
    6. Update your main.go file with the following changes:

           "sigs.k8s.io/controller-runtime/pkg/log/zap"
      +    "sigs.k8s.io/controller-runtime/pkg/metrics/filters"
      
           var enableHTTP2 bool
      -    flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
      +    var tlsOpts []func(*tls.Config)
      +    flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+
      +        "Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
           flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
           flag.BoolVar(&enableLeaderElection, "leader-elect", false,
               "Enable leader election for controller manager. "+
                   "Enabling this will ensure there is only one active controller manager.")
      -    flag.BoolVar(&secureMetrics, "metrics-secure", false,
      -        "If set the metrics endpoint is served securely")
      +    flag.BoolVar(&secureMetrics, "metrics-secure", true,
      +        "If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.")
      
      -    tlsOpts := []func(*tls.Config){}
      
      +    // Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server.
      +    // More info:
      +    // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.18.4/pkg/metrics/server
      +    // - https://book.kubebuilder.io/reference/metrics.html
      +    metricsServerOptions := metricsserver.Options{
      +        BindAddress:   metricsAddr,
      +        SecureServing: secureMetrics,
      +        // TODO(user): TLSOpts is used to allow configuring the TLS config used for the server. If certificates are
      +        // not provided, self-signed certificates will be generated by default. This option is not recommended for
      +        // production environments as self-signed certificates do not offer the same level of trust and security
      +        // as certificates issued by a trusted Certificate Authority (CA). The primary risk is potentially allowing
      +        // unauthorized access to sensitive metrics data. Consider replacing with CertDir, CertName, and KeyName
      +        // to provide certificates, ensuring the server communicates using trusted and secure certificates.
      +        TLSOpts: tlsOpts,
      +    }
      +
      +    if secureMetrics {
      +        // FilterProvider is used to protect the metrics endpoint with authn/authz.
      +        // These configurations ensure that only authorized users and service accounts
      +        // can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info:
      +        // https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.18.4/pkg/metrics/filters#WithAuthenticationAndAuthorization
      +        metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization
      +    }
      +
           mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
      -        Scheme: scheme,
      -        Metrics: metricsserver.Options{
      -            BindAddress:   metricsAddr,
      -            SecureServing: secureMetrics,
      -            TLSOpts:       tlsOpts,
      -        },
      +        Scheme:                 scheme,
      +        Metrics:                metricsServerOptions,
    7. Update your config/default/kustomization.yaml file with the following changes:

        # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.
        #- ../prometheus
      + # [METRICS] Expose the controller manager metrics service.
      + - metrics_service.yaml
      
      + # Uncomment the patches line if you enable Metrics, and/or are using webhooks and cert-manager
        patches:
      - # Protect the /metrics endpoint by putting it behind auth.
      - # If you want your controller-manager to expose the /metrics
      - # endpoint w/o any authn/z, please comment the following line.
      - - path: manager_auth_proxy_patch.yaml
      + # [METRICS] The following patch will enable the metrics endpoint using HTTPS and the port :8443.
      + # More info: https://book.kubebuilder.io/reference/metrics
      + - path: manager_metrics_patch.yaml
      +   target:
      +     kind: Deployment
    8. Remove the config/default/manager_auth_proxy_patch.yaml and config/default/manager_config_patch.yaml files.

    9. Create a config/default/manager_metrics_patch.yaml file with the following content:

      # This patch adds the args to allow exposing the metrics endpoint using HTTPS
      - op: add
        path: /spec/template/spec/containers/0/args/0
        value: --metrics-bind-address=:8443
    10. Create a config/default/metrics_service.yaml file with the following content:

      apiVersion: v1
      kind: Service
      metadata:
        labels:
          control-plane: controller-manager
          app.kubernetes.io/name: <operator-name>
          app.kubernetes.io/managed-by: kustomize
        name: controller-manager-metrics-service
        namespace: system
      spec:
        ports:
          - name: https
            port: 8443
            protocol: TCP
            targetPort: 8443
        selector:
          control-plane: controller-manager
    11. Update your config/manager/manager.yaml file with the following changes:

        - --leader-elect
      + - --health-probe-bind-address=:8081
    12. Update your config/prometheus/monitor.yaml file with the following changes:

           - path: /metrics
      -      port: https
      +      port: https # Ensure this is the name of the port that exposes HTTPS metrics
             tlsConfig:
      +        # TODO(user): The option insecureSkipVerify: true is not recommended for production since it disables
      +        # certificate verification. This poses a significant security risk by making the system vulnerable to
      +        # man-in-the-middle attacks, where an attacker could intercept and manipulate the communication between
      +        # Prometheus and the monitored services. This could lead to unauthorized access to sensitive metrics data,
      +        # compromising the integrity and confidentiality of the information.
      +        # Please use the following options for secure configurations:
      +        # caFile: /etc/metrics-certs/ca.crt
      +        # certFile: /etc/metrics-certs/tls.crt
      +        # keyFile: /etc/metrics-certs/tls.key
               insecureSkipVerify: true
    13. Remove the following files from the config/rbac/ directory:

      • auth_proxy_client_clusterrole.yaml

      • auth_proxy_role.yaml

      • auth_proxy_role_binding.yaml

      • auth_proxy_service.yaml

    14. Update your config/rbac/kustomization.yaml file with the following changes:

        - leader_election_role_binding.yaml
      - # Comment the following 4 lines if you want to disable
      - # the auth proxy (https://github.com/brancz/kube-rbac-proxy)
      - # which protects your /metrics endpoint.
      - - auth_proxy_service.yaml
      - - auth_proxy_role.yaml
      - - auth_proxy_role_binding.yaml
      - - auth_proxy_client_clusterrole.yaml
      + # The following RBAC configurations are used to protect
      + # the metrics endpoint with authn/authz. These configurations
      + # ensure that only authorized users and service accounts
      + # can access the metrics endpoint. Comment the following
      + # permissions if you want to disable this protection.
      + # More info: https://book.kubebuilder.io/reference/metrics.html
      + - metrics_auth_role.yaml
      + - metrics_auth_role_binding.yaml
      + - metrics_reader_role.yaml
    15. Create a config/rbac/metrics_auth_role_binding.yaml file with the following content:

      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRoleBinding
      metadata:
        name: metrics-auth-rolebinding
      roleRef:
        apiGroup: rbac.authorization.k8s.io
        kind: ClusterRole
        name: metrics-auth-role
      subjects:
        - kind: ServiceAccount
          name: controller-manager
          namespace: system
    16. Create a config/rbac/metrics_reader_role.yaml file with the following content:

      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        name: metrics-reader
      rules:
      - nonResourceURLs:
        - "/metrics"
        verbs:
        - get