diff --git a/cluster/charts/crossplane/templates/deployment.yaml b/cluster/charts/crossplane/templates/deployment.yaml index df77fd084e7..7d066b60556 100644 --- a/cluster/charts/crossplane/templates/deployment.yaml +++ b/cluster/charts/crossplane/templates/deployment.yaml @@ -123,9 +123,17 @@ spec: name: {{ .Chart.Name }} resources: {{- toYaml .Values.resourcesCrossplane | nindent 12 }} - {{- if or .Values.metrics.enabled (.Values.webhooks.enabled) }} + livenessProbe: + httpGet: + path: /healthz + port: healthz + readinessProbe: + httpGet: + path: /readyz + port: healthz ports: - {{- end }} + - name: healthz + containerPort: 5000 {{- if .Values.metrics.enabled }} - name: metrics containerPort: 8080 diff --git a/cmd/crossplane/core/core.go b/cmd/crossplane/core/core.go index 160323d9cff..783d7c93ab5 100644 --- a/cmd/crossplane/core/core.go +++ b/cmd/crossplane/core/core.go @@ -36,6 +36,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/webhook" "github.com/crossplane/crossplane-runtime/pkg/certificates" @@ -148,7 +149,7 @@ func (c *startCommand) Run(s *runtime.Scheme, log logging.Logger) error { //noli cfg, err := ctrl.GetConfig() if err != nil { - return errors.Wrap(err, "Cannot get config") + return errors.Wrap(err, "cannot get config") } cfg.WarningHandler = rest.NewWarningWriter(os.Stderr, rest.WarningWriterOptions{ @@ -188,9 +189,11 @@ func (c *startCommand) Run(s *runtime.Scheme, log logging.Logger) error { //noli LeaderElectionResourceLock: resourcelock.LeasesResourceLock, LeaseDuration: func() *time.Duration { d := 60 * time.Second; return &d }(), RenewDeadline: func() *time.Duration { d := 50 * time.Second; return &d }(), + + HealthProbeBindAddress: ":5000", }) if err != nil { - return errors.Wrap(err, "Cannot create manager") + return errors.Wrap(err, "cannot create manager") } o := controller.Options{ @@ -250,7 +253,7 @@ func (c *startCommand) Run(s *runtime.Scheme, log logging.Logger) error { //noli filepath.Join(c.TLSClientCertsDir, corev1.TLSPrivateKeyKey), false) if err != nil { - return errors.Wrap(err, "Cannot load TLS certificates for external secret stores") + return errors.Wrap(err, "cannot load TLS certificates for external secret stores") } o.ESSOptions = &controller.ESSOptions{ @@ -267,7 +270,7 @@ func (c *startCommand) Run(s *runtime.Scheme, log logging.Logger) error { //noli } if err := apiextensions.Setup(mgr, ao); err != nil { - return errors.Wrap(err, "Cannot setup API extension controllers") + return errors.Wrap(err, "cannot setup API extension controllers") } po := pkgcontroller.Options{ @@ -282,13 +285,13 @@ func (c *startCommand) Run(s *runtime.Scheme, log logging.Logger) error { //noli if c.CABundlePath != "" { rootCAs, err := ParseCertificatesFromPath(c.CABundlePath) if err != nil { - return errors.Wrap(err, "Cannot parse CA bundle") + return errors.Wrap(err, "cannot parse CA bundle") } po.FetcherOptions = append(po.FetcherOptions, xpkg.WithCustomCA(rootCAs)) } if err := pkg.Setup(mgr, po); err != nil { - return errors.Wrap(err, "Cannot add packages controllers to manager") + return errors.Wrap(err, "cannot add packages controllers to manager") } // Registering webhooks with the manager is what actually starts the webhook @@ -310,5 +313,34 @@ func (c *startCommand) Run(s *runtime.Scheme, log logging.Logger) error { //noli } } - return errors.Wrap(mgr.Start(ctrl.SetupSignalHandler()), "Cannot start controller manager") + if err := c.SetupProbes(mgr); err != nil { + return errors.Wrap(err, "cannot setup probes") + } + + return errors.Wrap(mgr.Start(ctrl.SetupSignalHandler()), "cannot start controller manager") +} + +// SetupProbes sets up the health and ready probes. +func (c *startCommand) SetupProbes(mgr ctrl.Manager) error { + // Add default readiness probe + if err := mgr.AddReadyzCheck("ping", healthz.Ping); err != nil { + return errors.Wrap(err, "cannot create ping ready check") + } + + // Add default health probe + if err := mgr.AddHealthzCheck("ping", healthz.Ping); err != nil { + return errors.Wrap(err, "cannot create ping health check") + } + + // Add probes waiting for the webhook server if webhooks are enabled + if c.WebhookEnabled { + hookServer := mgr.GetWebhookServer() + if err := mgr.AddReadyzCheck("webhook", hookServer.StartedChecker()); err != nil { + return errors.Wrap(err, "cannot create webhook ready check") + } + if err := mgr.AddHealthzCheck("webhook", hookServer.StartedChecker()); err != nil { + return errors.Wrap(err, "cannot create webhook health check") + } + } + return nil }