Add Readiness and Liveness probes
This commit is contained in:
parent
7f106df949
commit
2c9f630926
|
|
@ -5,6 +5,26 @@ metadata:
|
|||
spec:
|
||||
master:
|
||||
image: jenkins/jenkins:lts
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /login
|
||||
port: 8080
|
||||
scheme: HTTP
|
||||
failureThreshold: 12
|
||||
initialDelaySeconds: 20
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 5
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /login
|
||||
port: 8080
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 20
|
||||
failureThreshold: 12
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 5
|
||||
seedJobs:
|
||||
- id: jenkins-operator
|
||||
targets: "cicd/jobs/*.jenkins"
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ type JenkinsMaster struct {
|
|||
Annotations map[string]string `json:"masterAnnotations,omitempty"`
|
||||
Resources corev1.ResourceRequirements `json:"resources,omitempty"`
|
||||
Env []corev1.EnvVar `json:"env,omitempty"`
|
||||
LivenessProbe *corev1.Probe `json:"livenessProbe,omitempty"`
|
||||
ReadinessProbe *corev1.Probe `json:"readinessProbe,omitempty"`
|
||||
// OperatorPlugins contains plugins required by operator
|
||||
OperatorPlugins map[string][]string `json:"basePlugins,omitempty"`
|
||||
// Plugins contains plugins required by user
|
||||
|
|
|
|||
|
|
@ -135,6 +135,16 @@ func (in *JenkinsMaster) DeepCopyInto(out *JenkinsMaster) {
|
|||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.LivenessProbe != nil {
|
||||
in, out := &in.LivenessProbe, &out.LivenessProbe
|
||||
*out = new(v1.Probe)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ReadinessProbe != nil {
|
||||
in, out := &in.ReadinessProbe, &out.ReadinessProbe
|
||||
*out = new(v1.Probe)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.OperatorPlugins != nil {
|
||||
in, out := &in.OperatorPlugins, &out.OperatorPlugins
|
||||
*out = make(map[string][]string, len(*in))
|
||||
|
|
|
|||
|
|
@ -407,6 +407,18 @@ func (r *ReconcileJenkinsBaseConfiguration) isRecreatePodNeeded(currentJenkinsMa
|
|||
return true
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(r.jenkins.Spec.Master.ReadinessProbe, currentJenkinsMasterPod.Spec.Containers[0].ReadinessProbe) {
|
||||
r.logger.Info(fmt.Sprintf("Jenkins pod readinessProbe have changed, actual '%+v' required '%+v' - recreating pod",
|
||||
currentJenkinsMasterPod.Spec.Containers[0].ReadinessProbe, r.jenkins.Spec.Master.ReadinessProbe))
|
||||
return true
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(r.jenkins.Spec.Master.LivenessProbe, currentJenkinsMasterPod.Spec.Containers[0].LivenessProbe) {
|
||||
r.logger.Info(fmt.Sprintf("Jenkins pod livenessProbe have changed, actual '%+v' required '%+v' - recreating pod",
|
||||
currentJenkinsMasterPod.Spec.Containers[0].LivenessProbe, r.jenkins.Spec.Master.LivenessProbe))
|
||||
return true
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(r.jenkins.Spec.Master.NodeSelector, currentJenkinsMasterPod.Spec.NodeSelector) {
|
||||
r.logger.Info(fmt.Sprintf("Jenkins pod node selector has changed, actual '%+v' required '%+v' - recreating pod",
|
||||
currentJenkinsMasterPod.Spec.NodeSelector, r.jenkins.Spec.Master.NodeSelector))
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import (
|
|||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -75,9 +74,6 @@ func GetJenkinsMasterPodBaseEnvs() []corev1.EnvVar {
|
|||
|
||||
// NewJenkinsMasterPod builds Jenkins Master Kubernetes Pod resource
|
||||
func NewJenkinsMasterPod(objectMeta metav1.ObjectMeta, jenkins *v1alpha1.Jenkins) *corev1.Pod {
|
||||
initialDelaySeconds := int32(30)
|
||||
timeoutSeconds := int32(5)
|
||||
failureThreshold := int32(12)
|
||||
runAsUser := jenkinsUserUID
|
||||
|
||||
objectMeta.Annotations = jenkins.Spec.Master.Annotations
|
||||
|
|
@ -104,28 +100,8 @@ func NewJenkinsMasterPod(objectMeta metav1.ObjectMeta, jenkins *v1alpha1.Jenkins
|
|||
"bash",
|
||||
fmt.Sprintf("%s/%s", jenkinsScriptsVolumePath, initScriptName),
|
||||
},
|
||||
LivenessProbe: &corev1.Probe{
|
||||
Handler: corev1.Handler{
|
||||
HTTPGet: &corev1.HTTPGetAction{
|
||||
Path: "/login",
|
||||
Port: intstr.FromString(httpPortName),
|
||||
Scheme: corev1.URISchemeHTTP,
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: initialDelaySeconds,
|
||||
TimeoutSeconds: timeoutSeconds,
|
||||
FailureThreshold: failureThreshold,
|
||||
},
|
||||
ReadinessProbe: &corev1.Probe{
|
||||
Handler: corev1.Handler{
|
||||
HTTPGet: &corev1.HTTPGetAction{
|
||||
Path: "/login",
|
||||
Port: intstr.FromString(httpPortName),
|
||||
Scheme: corev1.URISchemeHTTP,
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: initialDelaySeconds,
|
||||
},
|
||||
LivenessProbe: jenkins.Spec.Master.LivenessProbe,
|
||||
ReadinessProbe: jenkins.Spec.Master.ReadinessProbe,
|
||||
Ports: []corev1.ContainerPort{
|
||||
{
|
||||
Name: httpPortName,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package jenkins
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"reflect"
|
||||
|
||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkinsio/v1alpha1"
|
||||
|
|
@ -136,7 +137,6 @@ func (r *ReconcileJenkins) reconcile(request reconcile.Request, logger logr.Logg
|
|||
// Error reading the object - requeue the request.
|
||||
return reconcile.Result{}, errors.WithStack(err)
|
||||
}
|
||||
|
||||
err = r.setDefaults(jenkins, logger)
|
||||
if err != nil {
|
||||
return reconcile.Result{}, err
|
||||
|
|
@ -227,6 +227,36 @@ func (r *ReconcileJenkins) setDefaults(jenkins *v1alpha1.Jenkins, logger logr.Lo
|
|||
changed = true
|
||||
jenkins.Spec.Master.ImagePullPolicy = corev1.PullAlways
|
||||
}
|
||||
if jenkins.Spec.Master.ReadinessProbe == nil {
|
||||
logger.Info("Setting default Jenkins readinessProbe")
|
||||
changed = true
|
||||
jenkins.Spec.Master.ReadinessProbe = &corev1.Probe{
|
||||
Handler: corev1.Handler{
|
||||
HTTPGet: &corev1.HTTPGetAction{
|
||||
Path: "/login",
|
||||
Port: intstr.FromString("http"),
|
||||
Scheme: corev1.URISchemeHTTP,
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: int32(30),
|
||||
}
|
||||
}
|
||||
if jenkins.Spec.Master.LivenessProbe == nil {
|
||||
logger.Info("Setting default Jenkins livenessProbe")
|
||||
changed = true
|
||||
jenkins.Spec.Master.LivenessProbe = &corev1.Probe{
|
||||
Handler: corev1.Handler{
|
||||
HTTPGet: &corev1.HTTPGetAction{
|
||||
Path: "/login",
|
||||
Port: intstr.FromString("http"),
|
||||
Scheme: corev1.URISchemeHTTP,
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: int32(30),
|
||||
TimeoutSeconds: int32(5),
|
||||
FailureThreshold: int32(12),
|
||||
}
|
||||
}
|
||||
if len(jenkins.Spec.Master.OperatorPlugins) == 0 {
|
||||
logger.Info("Setting default operator plugins")
|
||||
changed = true
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ func TestConfiguration(t *testing.T) {
|
|||
// Deletes test namespace
|
||||
defer ctx.Cleanup()
|
||||
|
||||
t.Logf("BASE")
|
||||
jenkinsCRName := "e2e"
|
||||
numberOfExecutors := 6
|
||||
systemMessage := "Configuration as Code integration works!!!"
|
||||
|
|
@ -42,6 +43,7 @@ func TestConfiguration(t *testing.T) {
|
|||
}
|
||||
|
||||
// base
|
||||
|
||||
createUserConfigurationSecret(t, jenkinsCRName, namespace, systemMessageEnvName, systemMessage)
|
||||
createUserConfigurationConfigMap(t, jenkinsCRName, namespace, numberOfExecutors, fmt.Sprintf("${%s}", systemMessageEnvName))
|
||||
jenkins := createJenkinsCR(t, jenkinsCRName, namespace, &[]v1alpha1.SeedJob{mySeedJob.SeedJob})
|
||||
|
|
@ -151,6 +153,14 @@ func verifyJenkinsMasterPodAttributes(t *testing.T, jenkins *v1alpha1.Jenkins) {
|
|||
t.Fatalf("Invalid jenkins pod node selector expected '%+v', actual '%+v'", jenkins.Spec.Master.NodeSelector, jenkinsPod.Spec.NodeSelector)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(jenkinsPod.Spec.Containers[0].ReadinessProbe, jenkins.Spec.Master.ReadinessProbe) {
|
||||
t.Fatalf("Invalid jenkins pod readinessProbe. Expected '%+v', actual '%+v'", jenkins.Spec.Master.NodeSelector, jenkinsPod.Spec.NodeSelector)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(jenkinsPod.Spec.Containers[0].LivenessProbe, jenkins.Spec.Master.LivenessProbe) {
|
||||
t.Fatalf("Invalid jenkins pod livenessProbe. Expected '%+v', actual '%+v'", jenkins.Spec.Master.NodeSelector, jenkinsPod.Spec.NodeSelector)
|
||||
}
|
||||
|
||||
requiredEnvs := resources.GetJenkinsMasterPodBaseEnvs()
|
||||
requiredEnvs = append(requiredEnvs, jenkins.Spec.Master.Env...)
|
||||
if !reflect.DeepEqual(jenkinsPod.Spec.Containers[0].Env, requiredEnvs) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package e2e
|
|||
|
||||
import (
|
||||
"context"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"testing"
|
||||
|
||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkinsio/v1alpha1"
|
||||
|
|
@ -10,6 +11,7 @@ import (
|
|||
|
||||
framework "github.com/operator-framework/operator-sdk/pkg/test"
|
||||
"k8s.io/api/core/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
|
@ -84,6 +86,28 @@ func createJenkinsCR(t *testing.T, name, namespace string, seedJob *[]v1alpha1.S
|
|||
Value: "test_env_value",
|
||||
},
|
||||
},
|
||||
ReadinessProbe: &corev1.Probe{
|
||||
Handler: corev1.Handler{
|
||||
HTTPGet: &corev1.HTTPGetAction{
|
||||
Path: "/login",
|
||||
Port: intstr.FromString("http"),
|
||||
Scheme: corev1.URISchemeHTTP,
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: int32(50),
|
||||
},
|
||||
LivenessProbe: &corev1.Probe{
|
||||
Handler: corev1.Handler{
|
||||
HTTPGet: &corev1.HTTPGetAction{
|
||||
Path: "/login",
|
||||
Port: intstr.FromString("http"),
|
||||
Scheme: corev1.URISchemeHTTP,
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: int32(40),
|
||||
TimeoutSeconds: int32(8),
|
||||
FailureThreshold: int32(15),
|
||||
},
|
||||
},
|
||||
SeedJobs: seedJobs,
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue