Detect Jenkins Master Pod starting issues

This commit is contained in:
Tomasz Sęk 2019-06-09 16:46:50 +02:00
parent f9ad157c8b
commit 0ae462dbb5
No known key found for this signature in database
GPG Key ID: DC356D23F6A644D0
3 changed files with 62 additions and 7 deletions

View File

@ -63,7 +63,9 @@ rules:
resources: resources:
- events - events
verbs: verbs:
- list
- create - create
- patch
- apiGroups: - apiGroups:
- apps - apps
resourceNames: resourceNames:

View File

@ -83,6 +83,14 @@ func (r *ReconcileJenkinsBaseConfiguration) Reconcile() (reconcile.Result, jenki
} }
r.logger.V(log.VDebug).Info("Jenkins master pod is present") r.logger.V(log.VDebug).Info("Jenkins master pod is present")
stopReconcileLoop, err := r.detectJenkinsMasterPodStartingIssues(metaObject)
if err != nil {
return reconcile.Result{}, nil, err
}
if stopReconcileLoop {
return reconcile.Result{Requeue: false}, nil, nil
}
result, err = r.waitForJenkins(metaObject) result, err = r.waitForJenkins(metaObject)
if err != nil { if err != nil {
return reconcile.Result{}, nil, err return reconcile.Result{}, nil, err
@ -435,8 +443,6 @@ func (r *ReconcileJenkinsBaseConfiguration) isRecreatePodNeeded(currentJenkinsMa
return true return true
} }
//TODO check if image can't be pulled, volume can't be mounted etc. (get info from events)
if currentJenkinsMasterPod.Status.Phase == corev1.PodFailed || if currentJenkinsMasterPod.Status.Phase == corev1.PodFailed ||
currentJenkinsMasterPod.Status.Phase == corev1.PodSucceeded || currentJenkinsMasterPod.Status.Phase == corev1.PodSucceeded ||
currentJenkinsMasterPod.Status.Phase == corev1.PodUnknown { currentJenkinsMasterPod.Status.Phase == corev1.PodUnknown {
@ -593,24 +599,68 @@ func (r *ReconcileJenkinsBaseConfiguration) restartJenkinsMasterPod(meta metav1.
return stackerr.WithStack(r.k8sClient.Delete(context.TODO(), currentJenkinsMasterPod)) return stackerr.WithStack(r.k8sClient.Delete(context.TODO(), currentJenkinsMasterPod))
} }
func (r *ReconcileJenkinsBaseConfiguration) detectJenkinsMasterPodStartingIssues(meta metav1.ObjectMeta) (stopReconcileLoop bool, err error) {
jenkinsMasterPod, err := r.getJenkinsMasterPod(meta)
if err != nil {
return false, err
}
if jenkinsMasterPod.Status.Phase == corev1.PodPending {
timeout := r.jenkins.Status.ProvisionStartTime.Add(time.Minute * 2).UTC()
now := time.Now().UTC()
if now.After(timeout) {
events := &corev1.EventList{}
err = r.k8sClient.List(context.TODO(), &client.ListOptions{Namespace: r.jenkins.Namespace}, events)
if err != nil {
return false, stackerr.WithStack(err)
}
filteredEvents := r.filterEvents(*events, *jenkinsMasterPod)
r.logger.Info(fmt.Sprintf("Jenkins master pod starting timeout, events '%+v'", filteredEvents))
return true, nil
}
}
return false, nil
}
func (r *ReconcileJenkinsBaseConfiguration) filterEvents(source corev1.EventList, jenkinsMasterPod corev1.Pod) []string {
events := []string{}
for _, event := range source.Items {
if r.jenkins.Status.ProvisionStartTime.UTC().After(event.LastTimestamp.UTC()) {
continue
}
if event.Type == corev1.EventTypeNormal {
continue
}
if !strings.HasPrefix(event.ObjectMeta.Name, jenkinsMasterPod.Name) {
continue
}
events = append(events, fmt.Sprintf("Message: %s Subobject: %s", event.Message, event.InvolvedObject.FieldPath))
}
return events
}
func (r *ReconcileJenkinsBaseConfiguration) waitForJenkins(meta metav1.ObjectMeta) (reconcile.Result, error) { func (r *ReconcileJenkinsBaseConfiguration) waitForJenkins(meta metav1.ObjectMeta) (reconcile.Result, error) {
jenkinsMasterPodStatus, err := r.getJenkinsMasterPod(meta) jenkinsMasterPod, err := r.getJenkinsMasterPod(meta)
if err != nil { if err != nil {
return reconcile.Result{}, err return reconcile.Result{}, err
} }
if jenkinsMasterPodStatus.ObjectMeta.DeletionTimestamp != nil { if jenkinsMasterPod.ObjectMeta.DeletionTimestamp != nil {
r.logger.V(log.VDebug).Info("Jenkins master pod is terminating") r.logger.V(log.VDebug).Info("Jenkins master pod is terminating")
return reconcile.Result{Requeue: true, RequeueAfter: time.Second * 5}, nil return reconcile.Result{Requeue: true, RequeueAfter: time.Second * 5}, nil
} }
if jenkinsMasterPodStatus.Status.Phase != corev1.PodRunning { if jenkinsMasterPod.Status.Phase != corev1.PodRunning {
r.logger.V(log.VDebug).Info("Jenkins master pod not ready") r.logger.V(log.VDebug).Info("Jenkins master pod not ready")
return reconcile.Result{Requeue: true, RequeueAfter: time.Second * 5}, nil return reconcile.Result{Requeue: true, RequeueAfter: time.Second * 5}, nil
} }
containersReadyCount := 0 containersReadyCount := 0
for _, containerStatus := range jenkinsMasterPodStatus.Status.ContainerStatuses { for _, containerStatus := range jenkinsMasterPod.Status.ContainerStatuses {
if containerStatus.State.Terminated != nil { if containerStatus.State.Terminated != nil {
r.logger.Info(fmt.Sprintf("Container '%s' is terminated, status '%+v', recreating pod", containerStatus.Name, containerStatus)) r.logger.Info(fmt.Sprintf("Container '%s' is terminated, status '%+v', recreating pod", containerStatus.Name, containerStatus))
return reconcile.Result{Requeue: true}, r.restartJenkinsMasterPod(meta) return reconcile.Result{Requeue: true}, r.restartJenkinsMasterPod(meta)
@ -621,7 +671,7 @@ func (r *ReconcileJenkinsBaseConfiguration) waitForJenkins(meta metav1.ObjectMet
containersReadyCount++ containersReadyCount++
} }
} }
if containersReadyCount != len(jenkinsMasterPodStatus.Status.ContainerStatuses) { if containersReadyCount != len(jenkinsMasterPod.Status.ContainerStatuses) {
return reconcile.Result{Requeue: true, RequeueAfter: time.Second * 5}, nil return reconcile.Result{Requeue: true, RequeueAfter: time.Second * 5}, nil
} }

View File

@ -164,6 +164,9 @@ func (r *ReconcileJenkins) reconcile(request reconcile.Request, logger logr.Logg
if result.Requeue { if result.Requeue {
return result, nil return result, nil
} }
if jenkinsClient == nil {
return reconcile.Result{Requeue: false}, nil
}
if jenkins.Status.BaseConfigurationCompletedTime == nil { if jenkins.Status.BaseConfigurationCompletedTime == nil {
now := metav1.Now() now := metav1.Now()