diff --git a/changelog/fragments/liveness_readiness_probe_for_operator.yaml b/changelog/fragments/liveness_readiness_probe_for_operator.yaml new file mode 100644 index 00000000000..dfe7df56210 --- /dev/null +++ b/changelog/fragments/liveness_readiness_probe_for_operator.yaml @@ -0,0 +1,91 @@ +# entries is a list of entries to include in +# release notes and/or the migration guide +entries: + - description: > + For Helm-based operators, added Liveness and Readiness probe by default using [`healthz.Ping`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/healthz#CheckHandler). + + # kind is one of: + # - addition + # - change + # - deprecation + # - removal + # - bugfix + kind: "addition" + + # Is this a breaking change? + breaking: false + + # Migration can be defined to automatically add a section to + # the migration guide. This is required for breaking changes. + migration: + header: (Optional) For Helm-based operators, add Liveness and Readiness probe + body: > + New projects built with the tool will have the probes configured by default. The endpoints `/healthz` and + `/readyz` are available now in the image based provided. + + You can update your pre-existing project to use them. For that update the Dockerfile to use the latest + release base image, then add the following to the `manager` container in + `config/default/manager/manager.yaml`: + + ```yaml + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + ``` + - description: > + For Ansible-based operators, added Liveness and Readiness probe by default using [`healthz.Ping`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/healthz#CheckHandler). + + # kind is one of: + # - addition + # - change + # - deprecation + # - removal + # - bugfix + kind: "addition" + + # Is this a breaking change? + breaking: false + + # Migration can be defined to automatically add a section to + # the migration guide. This is required for breaking changes. + migration: + header: (Optional) For Ansible-based operators, add Liveness and Readiness probe + body: > + New projects built with the tool will have the probes configured by default. The endpoints `/healthz` and + `/readyz` are available now in the image based provided. + + You can update your pre-existing project to use them. For that update the Dockerfile to use the latest + release base image, then add the following to the `manager` container in + `config/default/manager/manager.yaml`: + + ```yaml + livenessProbe: + httpGet: + path: /healthz + port: 6789 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: 6789 + initialDelaySeconds: 5 + periodSeconds: 10 + ``` + - description: > + For Ansible-based operators, the `/ping` endpoint is deprecated. Use `/healthz` instead. + kind: "deprecation" + breaking: false + + - description: > + For Ansible/Helm-based operators, added new flag `--health-probe-bind-address` to set the health probe address. + kind: "addition" diff --git a/internal/ansible/flags/flag.go b/internal/ansible/flags/flag.go index 8e8168d78a6..3fb6cd644e2 100644 --- a/internal/ansible/flags/flag.go +++ b/internal/ansible/flags/flag.go @@ -32,6 +32,7 @@ type Flags struct { AnsibleRolesPath string AnsibleCollectionsPath string MetricsAddress string + ProbeAddr string LeaderElectionID string LeaderElectionNamespace string AnsibleArgs string @@ -82,6 +83,14 @@ func (f *Flags) AddTo(flagSet *pflag.FlagSet) { ":8080", "The address the metric endpoint binds to", ) + // todo: for Go/Helm the port used is: 8081 + // update it to keep the project aligned to the other + // types for 2.0 + flagSet.StringVar(&f.ProbeAddr, + "health-probe-bind-address", + ":6789", + "The address the probe endpoint binds to.", + ) flagSet.BoolVar(&f.EnableLeaderElection, "enable-leader-election", false, diff --git a/internal/cmd/ansible-operator/run/cmd.go b/internal/cmd/ansible-operator/run/cmd.go index fe3764c5a3e..d09fa3ba065 100644 --- a/internal/cmd/ansible-operator/run/cmd.go +++ b/internal/cmd/ansible-operator/run/cmd.go @@ -45,11 +45,7 @@ import ( sdkVersion "github.com/operator-framework/operator-sdk/internal/version" ) -var ( - metricsHost = "0.0.0.0" - log = logf.Log.WithName("cmd") - healthProbePort int32 = 6789 -) +var log = logf.Log.WithName("cmd") func printVersion() { log.Info("Version", @@ -105,8 +101,8 @@ func run(cmd *cobra.Command, f *flags.Flags) { // Set default manager options // TODO: probably should expose the host & port as an environment variables options := manager.Options{ - HealthProbeBindAddress: fmt.Sprintf("%s:%d", metricsHost, healthProbePort), MetricsBindAddress: f.MetricsAddress, + HealthProbeBindAddress: f.ProbeAddr, LeaderElection: f.EnableLeaderElection, LeaderElectionID: f.LeaderElectionID, LeaderElectionResourceLock: resourcelock.ConfigMapsResourceLock, @@ -148,6 +144,15 @@ func run(cmd *cobra.Command, f *flags.Flags) { os.Exit(1) } + if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { + log.Error(err, "Unable to set up health check") + os.Exit(1) + } + if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { + log.Error(err, "Unable to set up ready check") + os.Exit(1) + } + cMap := controllermap.NewControllerMap() watches, err := watches.Load(f.WatchesFile, f.MaxConcurrentReconciles, f.AnsibleVerbosity) if err != nil { @@ -183,6 +188,7 @@ func run(cmd *cobra.Command, f *flags.Flags) { }, w.Blacklist) } + // todo: remove when a upper version be bumped err = mgr.AddHealthzCheck("ping", healthz.Ping) if err != nil { log.Error(err, "Failed to add Healthz check.") diff --git a/internal/cmd/helm-operator/run/cmd.go b/internal/cmd/helm-operator/run/cmd.go index 195d4a9f9c1..b10bf950c0e 100644 --- a/internal/cmd/helm-operator/run/cmd.go +++ b/internal/cmd/helm-operator/run/cmd.go @@ -26,6 +26,7 @@ import ( "k8s.io/client-go/tools/leaderelection/resourcelock" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client/config" + "sigs.k8s.io/controller-runtime/pkg/healthz" logf "sigs.k8s.io/controller-runtime/pkg/log" zapf "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/manager" @@ -96,6 +97,7 @@ func run(cmd *cobra.Command, f *flags.Flags) { // Set default manager options options := manager.Options{ MetricsBindAddress: f.MetricsAddress, + HealthProbeBindAddress: f.ProbeAddr, LeaderElection: f.EnableLeaderElection, LeaderElectionID: f.LeaderElectionID, LeaderElectionResourceLock: resourcelock.ConfigMapsResourceLock, @@ -130,6 +132,15 @@ func run(cmd *cobra.Command, f *flags.Flags) { os.Exit(1) } + if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { + log.Error(err, "Unable to set up health check") + os.Exit(1) + } + if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { + log.Error(err, "Unable to set up ready check") + os.Exit(1) + } + ws, err := watches.Load(f.WatchesFile) if err != nil { log.Error(err, "Failed to create new manager factories.") diff --git a/internal/helm/flags/flag.go b/internal/helm/flags/flag.go index e272a8b4bff..2b2750c7357 100644 --- a/internal/helm/flags/flag.go +++ b/internal/helm/flags/flag.go @@ -30,6 +30,7 @@ type Flags struct { LeaderElectionID string LeaderElectionNamespace string MaxConcurrentReconciles int + ProbeAddr string } // AddTo - Add the helm operator flags to the the flagset @@ -49,6 +50,11 @@ func (f *Flags) AddTo(flagSet *pflag.FlagSet) { ":8080", "The address the metric endpoint binds to", ) + flagSet.StringVar(&f.ProbeAddr, + "health-probe-bind-address", + ":8081", + "The address the probe endpoint binds to.", + ) flagSet.BoolVar(&f.EnableLeaderElection, "enable-leader-election", false, diff --git a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/manager/manager.go b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/manager/manager.go index 9a076261186..463ded8493a 100644 --- a/internal/plugins/ansible/v1/scaffolds/internal/templates/config/manager/manager.go +++ b/internal/plugins/ansible/v1/scaffolds/internal/templates/config/manager/manager.go @@ -78,5 +78,17 @@ spec: - name: ANSIBLE_GATHERING value: explicit image: {{ .Image }} + livenessProbe: + httpGet: + path: /readyz + port: 6789 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /healthz + port: 6789 + initialDelaySeconds: 5 + periodSeconds: 10 terminationGracePeriodSeconds: 10 ` diff --git a/internal/plugins/helm/v1/scaffolds/internal/templates/config/manager/manager.go b/internal/plugins/helm/v1/scaffolds/internal/templates/config/manager/manager.go index 6568b0467fc..beb54f70ee0 100644 --- a/internal/plugins/helm/v1/scaffolds/internal/templates/config/manager/manager.go +++ b/internal/plugins/helm/v1/scaffolds/internal/templates/config/manager/manager.go @@ -75,6 +75,18 @@ spec: - "--enable-leader-election" - "--leader-election-id={{ .ProjectName }}" name: manager + livenessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 resources: limits: cpu: 100m diff --git a/testdata/ansible/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml b/testdata/ansible/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml index 43f07252740..8fefea49050 100644 --- a/testdata/ansible/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml +++ b/testdata/ansible/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml @@ -124,7 +124,19 @@ spec: - name: ANSIBLE_GATHERING value: explicit image: quay.io/example/memcached-operator:v0.0.1 + livenessProbe: + httpGet: + path: /readyz + port: 6789 + initialDelaySeconds: 15 + periodSeconds: 20 name: manager + readinessProbe: + httpGet: + path: /healthz + port: 6789 + initialDelaySeconds: 5 + periodSeconds: 10 resources: {} terminationGracePeriodSeconds: 10 permissions: diff --git a/testdata/ansible/memcached-operator/config/manager/manager.yaml b/testdata/ansible/memcached-operator/config/manager/manager.yaml index 0141d1e514e..d39460e3688 100644 --- a/testdata/ansible/memcached-operator/config/manager/manager.yaml +++ b/testdata/ansible/memcached-operator/config/manager/manager.yaml @@ -31,4 +31,16 @@ spec: - name: ANSIBLE_GATHERING value: explicit image: controller:latest + livenessProbe: + httpGet: + path: /readyz + port: 6789 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /healthz + port: 6789 + initialDelaySeconds: 5 + periodSeconds: 10 terminationGracePeriodSeconds: 10 diff --git a/testdata/helm/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml b/testdata/helm/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml index eba15872125..3cd62bf7e7f 100644 --- a/testdata/helm/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml +++ b/testdata/helm/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml @@ -209,7 +209,19 @@ spec: - --enable-leader-election - --leader-election-id=memcached-operator image: quay.io/example/memcached-operator:v0.0.1 + livenessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 name: manager + readinessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 resources: limits: cpu: 100m diff --git a/testdata/helm/memcached-operator/config/manager/manager.yaml b/testdata/helm/memcached-operator/config/manager/manager.yaml index 26a86eadc53..72d3a0cefaf 100644 --- a/testdata/helm/memcached-operator/config/manager/manager.yaml +++ b/testdata/helm/memcached-operator/config/manager/manager.yaml @@ -28,6 +28,18 @@ spec: - "--enable-leader-election" - "--leader-election-id=memcached-operator" name: manager + livenessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 resources: limits: cpu: 100m