diff --git a/api/v1alpha1/perconaservermysql_types.go b/api/v1alpha1/perconaservermysql_types.go index 874a010e4..f0c791ec1 100644 --- a/api/v1alpha1/perconaservermysql_types.go +++ b/api/v1alpha1/perconaservermysql_types.go @@ -218,6 +218,8 @@ type PMMSpec struct { Resources corev1.ResourceRequirements `json:"resources,omitempty"` ContainerSecurityContext *corev1.SecurityContext `json:"containerSecurityContext,omitempty"` ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` + LivenessProbes *corev1.Probe `json:"livenessProbes,omitempty"` + ReadinessProbes *corev1.Probe `json:"readinessProbes,omitempty"` } type BackupSpec struct { diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 9751997ac..984ff1727 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -416,6 +416,16 @@ func (in *PMMSpec) DeepCopyInto(out *PMMSpec) { *out = new(corev1.SecurityContext) (*in).DeepCopyInto(*out) } + if in.LivenessProbes != nil { + in, out := &in.LivenessProbes, &out.LivenessProbes + *out = new(corev1.Probe) + (*in).DeepCopyInto(*out) + } + if in.ReadinessProbes != nil { + in, out := &in.ReadinessProbes, &out.ReadinessProbes + *out = new(corev1.Probe) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PMMSpec. diff --git a/config/crd/bases/ps.percona.com_perconaservermysqls.yaml b/config/crd/bases/ps.percona.com_perconaservermysqls.yaml index 4865c3ff3..69702175c 100644 --- a/config/crd/bases/ps.percona.com_perconaservermysqls.yaml +++ b/config/crd/bases/ps.percona.com_perconaservermysqls.yaml @@ -6438,8 +6438,170 @@ spec: type: string imagePullPolicy: type: string + livenessProbes: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object mysqlParams: type: string + readinessProbes: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object resources: properties: claims: diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 12772fb3a..982bcc981 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -8361,8 +8361,170 @@ spec: type: string imagePullPolicy: type: string + livenessProbes: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object mysqlParams: type: string + readinessProbes: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object resources: properties: claims: diff --git a/deploy/cr.yaml b/deploy/cr.yaml index e0dea5f12..ac09d9045 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -418,6 +418,18 @@ spec: enabled: false image: perconalab/pmm-client:3-dev-latest imagePullPolicy: Always +# readinessProbes: +# initialDelaySeconds: 15 +# timeoutSeconds: 15 +# periodSeconds: 30 +# successThreshold: 1 +# failureThreshold: 5 +# livenessProbes: +# initialDelaySeconds: 300 +# timeoutSeconds: 5 +# periodSeconds: 10 +# successThreshold: 1 +# failureThreshold: 3 # mysqlParams: "--disable-tablestats-limit=2000" resources: requests: diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 0dded2e46..6b9eeff91 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -8361,8 +8361,170 @@ spec: type: string imagePullPolicy: type: string + livenessProbes: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object mysqlParams: type: string + readinessProbes: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object resources: properties: claims: diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index a23728c35..eda872b2f 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -8361,8 +8361,170 @@ spec: type: string imagePullPolicy: type: string + livenessProbes: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object mysqlParams: type: string + readinessProbes: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object resources: properties: claims: diff --git a/e2e-tests/tests/monitoring/02-assert.yaml b/e2e-tests/tests/monitoring/02-assert.yaml index 160711707..595e52870 100644 --- a/e2e-tests/tests/monitoring/02-assert.yaml +++ b/e2e-tests/tests/monitoring/02-assert.yaml @@ -85,6 +85,25 @@ spec: value: --query-source=perfschema - name: PMM_ADMIN_CUSTOM_PARAMS value: --disable-tablestats-limit=2000 + lifecycle: + preStop: + exec: + command: + - bash + - -c + - pmm-admin unregister --force + livenessProbe: + failureThreshold: 3 + httpGet: + path: /local/Status + port: 7777 + scheme: HTTP + initialDelaySeconds: 60 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + + status: observedGeneration: 1 replicas: 3 diff --git a/pkg/pmm/container.go b/pkg/pmm/container.go index 40675dad4..2af45e718 100644 --- a/pkg/pmm/container.go +++ b/pkg/pmm/container.go @@ -1,10 +1,11 @@ package pmm import ( - corev1 "k8s.io/api/core/v1" - apiv1alpha1 "github.com/percona/percona-server-mysql-operator/api/v1alpha1" "github.com/percona/percona-server-mysql-operator/pkg/k8s" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "reflect" ) func Container( @@ -28,7 +29,7 @@ func Container( }) } - return corev1.Container{ + container := corev1.Container{ Name: "pmm-client", Image: pmmSpec.Image, ImagePullPolicy: pmmSpec.ImagePullPolicy, @@ -36,6 +37,28 @@ func Container( Ports: ports, Resources: pmmSpec.Resources, Env: envs, + Lifecycle: &corev1.Lifecycle{ + PreStop: &corev1.LifecycleHandler{ + Exec: &corev1.ExecAction{ + Command: []string{ + "bash", + "-c", + "pmm-admin unregister --force", + }, + }, + }, + }, + LivenessProbe: &corev1.Probe{ + InitialDelaySeconds: 60, + TimeoutSeconds: 5, + PeriodSeconds: 10, + ProbeHandler: corev1.ProbeHandler{ + HTTPGet: &corev1.HTTPGetAction{ + Port: intstr.FromInt32(7777), + Path: "/local/Status", + }, + }, + }, VolumeMounts: []corev1.VolumeMount{ { Name: apiv1alpha1.BinVolumeName, @@ -43,6 +66,28 @@ func Container( }, }, } + + if pmmSpec.LivenessProbes != nil { + container.LivenessProbe = pmmSpec.LivenessProbes + if reflect.DeepEqual(container.LivenessProbe.ProbeHandler, corev1.ProbeHandler{}) { + container.LivenessProbe.HTTPGet = &corev1.HTTPGetAction{ + Port: intstr.FromInt32(7777), + Path: "/local/Status", + } + } + } + + if pmmSpec.ReadinessProbes != nil { + container.ReadinessProbe = pmmSpec.ReadinessProbes + if reflect.DeepEqual(container.ReadinessProbe.ProbeHandler, corev1.ProbeHandler{}) { + container.ReadinessProbe.HTTPGet = &corev1.HTTPGetAction{ + Port: intstr.FromInt32(7777), + Path: "/local/Status", + } + } + } + + return container } func pmmEnvs(cr *apiv1alpha1.PerconaServerMySQL, secret *corev1.Secret, dbType string) []corev1.EnvVar {