You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by as...@apache.org on 2019/10/09 12:24:40 UTC

[camel-k] 01/04: fix(kaniko): Do not co-locate Kaniko warmer pod with the operator pod

This is an automated email from the ASF dual-hosted git repository.

astefanutti pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit ac7dee21b2ffbe34a764460fa489775e8daf79a3
Author: Antonin Stefanutti <an...@stefanutti.fr>
AuthorDate: Tue Oct 8 15:23:38 2019 +0200

    fix(kaniko): Do not co-locate Kaniko warmer pod with the operator pod
---
 pkg/builder/kaniko/publisher.go                    | 16 +----
 pkg/controller/build/schedule_pod.go               | 73 ++++++++++++++++------
 pkg/controller/integrationplatform/kaniko_cache.go | 20 +-----
 3 files changed, 60 insertions(+), 49 deletions(-)

diff --git a/pkg/builder/kaniko/publisher.go b/pkg/builder/kaniko/publisher.go
index 6529dcb..535cfbb 100644
--- a/pkg/builder/kaniko/publisher.go
+++ b/pkg/builder/kaniko/publisher.go
@@ -26,7 +26,6 @@ import (
 	"time"
 
 	"github.com/apache/camel-k/pkg/builder"
-	"github.com/apache/camel-k/pkg/platform"
 	"github.com/apache/camel-k/pkg/util/defaults"
 	"github.com/apache/camel-k/pkg/util/kubernetes"
 	"github.com/apache/camel-k/pkg/util/tar"
@@ -187,25 +186,14 @@ func publisher(ctx *builder.Context) error {
 		},
 	}
 
-	var labelKey string
-	var labelValue string
-	if ctx.Namespace == platform.GetOperatorNamespace() {
-		// Check if the operator is running in the same namespace
-		labelKey = "camel.apache.org/component"
-		labelValue = "operator"
-	} else {
-		labelKey = "camel.apache.org/build"
-		labelValue = ctx.Build.Meta.Name
-	}
-
-	// Co-locate with builder pod for sharing the volume
+	// Co-locate with the build pod for sharing the volume
 	pod.Spec.Affinity = &corev1.Affinity{
 		PodAffinity: &corev1.PodAffinity{
 			RequiredDuringSchedulingIgnoredDuringExecution: []corev1.PodAffinityTerm{
 				{
 					LabelSelector: &metav1.LabelSelector{
 						MatchLabels: map[string]string{
-							labelKey: labelValue,
+							"camel.apache.org/build": ctx.Build.Meta.Name,
 						},
 					},
 					TopologyKey: "kubernetes.io/hostname",
diff --git a/pkg/controller/build/schedule_pod.go b/pkg/controller/build/schedule_pod.go
index b3b3dcd..affba9b 100644
--- a/pkg/controller/build/schedule_pod.go
+++ b/pkg/controller/build/schedule_pod.go
@@ -21,16 +21,18 @@ import (
 	"context"
 	"sync"
 
-	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
-	"github.com/apache/camel-k/pkg/platform"
-	"github.com/apache/camel-k/pkg/util/defaults"
-
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/apimachinery/pkg/selection"
 
 	k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
 
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/platform"
+	"github.com/apache/camel-k/pkg/util/defaults"
+
 	"github.com/pkg/errors"
 )
 
@@ -96,7 +98,10 @@ func (action *schedulePodAction) Handle(ctx context.Context, build *v1alpha1.Bui
 
 		// We may want to explicitly manage build priority as opposed to relying on
 		// the reconcile loop to handle the queuing
-		pod = newBuildPod(build, operatorImage)
+		pod, err = action.newBuildPod(ctx, build, operatorImage)
+		if err != nil {
+			return nil, err
+		}
 
 		// Set the Build instance as the owner and controller
 		if err := controllerutil.SetControllerReference(build, pod, action.client.GetScheme()); err != nil {
@@ -113,7 +118,7 @@ func (action *schedulePodAction) Handle(ctx context.Context, build *v1alpha1.Bui
 	return build, nil
 }
 
-func newBuildPod(build *v1alpha1.Build, operatorImage string) *corev1.Pod {
+func (action *schedulePodAction) newBuildPod(ctx context.Context, build *v1alpha1.Build, operatorImage string) (*corev1.Pod, error) {
 	builderImage := operatorImage
 	if builderImage == "" {
 		builderImage = defaults.ImageName + ":" + defaults.Version
@@ -127,7 +132,8 @@ func newBuildPod(build *v1alpha1.Build, operatorImage string) *corev1.Pod {
 			Namespace: build.Namespace,
 			Name:      buildPodName(build.Spec.Meta),
 			Labels: map[string]string{
-				"camel.apache.org/build": build.Name,
+				"camel.apache.org/build":     build.Name,
+				"camel.apache.org/component": "builder",
 			},
 		},
 		Spec: corev1.PodSpec{
@@ -185,21 +191,52 @@ func newBuildPod(build *v1alpha1.Build, operatorImage string) *corev1.Pod {
 			},
 		})
 
-		// Use affinity only when the operator is present in the namespaced
-		if build.Namespace == platform.GetOperatorNamespace() {
-			// Co-locate with the builder pod for sharing the host path volume as the current
+		// Use affinity when Kaniko cache warming is enabled
+		if build.Spec.Platform.Build.IsKanikoCacheEnabled() {
+			// Co-locate with the Kaniko warmer pod for sharing the host path volume as the current
 			// persistent volume claim uses the default storage class which is likely relying
 			// on the host path provisioner.
+			// This has to be done manually by retrieving the Kaniko warmer pod node name and using
+			// node affinity as pod affinity only works for running pods and the Kaniko warmer pod
+			// has already completed at that stage.
+
+			// Locate the kaniko warmer pod
+			byComponentLabel, err := labels.NewRequirement("camel.apache.org/component", selection.Equals, []string{"kaniko-warmer"})
+			if err != nil {
+				return nil, err
+			}
+
+			selector := labels.NewSelector().Add(*byComponentLabel)
+
+			options := &k8sclient.ListOptions{
+				Namespace:     build.Namespace,
+				LabelSelector: selector,
+			}
+
+			pods := &corev1.PodList{}
+			err = action.client.List(ctx, options, pods)
+			if err != nil {
+				return nil, err
+			}
+
+			if len(pods.Items) != 1 {
+				return nil, errors.New("failed to locate the Kaniko cache warmer pod")
+			}
+
+			// Use node affinity with the Kaniko warmer pod node name
 			pod.Spec.Affinity = &corev1.Affinity{
-				PodAffinity: &corev1.PodAffinity{
-					RequiredDuringSchedulingIgnoredDuringExecution: []corev1.PodAffinityTerm{
-						{
-							LabelSelector: &metav1.LabelSelector{
-								MatchLabels: map[string]string{
-									"camel.apache.org/component": "operator",
+				NodeAffinity: &corev1.NodeAffinity{
+					RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
+						NodeSelectorTerms: []corev1.NodeSelectorTerm{
+							{
+								MatchExpressions: []corev1.NodeSelectorRequirement{
+									{
+										Key:      "kubernetes.io/hostname",
+										Operator: "In",
+										Values:   []string{pods.Items[0].Spec.NodeName},
+									},
 								},
 							},
-							TopologyKey: "kubernetes.io/hostname",
 						},
 					},
 				},
@@ -207,5 +244,5 @@ func newBuildPod(build *v1alpha1.Build, operatorImage string) *corev1.Pod {
 		}
 	}
 
-	return pod
+	return pod, nil
 }
diff --git a/pkg/controller/integrationplatform/kaniko_cache.go b/pkg/controller/integrationplatform/kaniko_cache.go
index 3470663..217c50f 100644
--- a/pkg/controller/integrationplatform/kaniko_cache.go
+++ b/pkg/controller/integrationplatform/kaniko_cache.go
@@ -48,6 +48,9 @@ func createKanikoCacheWarmerPod(ctx context.Context, client client.Client, platf
 		ObjectMeta: metav1.ObjectMeta{
 			Namespace: platform.Namespace,
 			Name:      platform.Name + "-cache",
+			Labels: map[string]string{
+				"camel.apache.org/component": "kaniko-warmer",
+			},
 		},
 		Spec: corev1.PodSpec{
 			Containers: []corev1.Container{
@@ -93,23 +96,6 @@ func createKanikoCacheWarmerPod(ctx context.Context, client client.Client, platf
 					},
 				},
 			},
-			// Co-locate with the builder pod for sharing the host path volume as the current
-			// persistent volume claim uses the default storage class which is likely relying
-			// on the host path provisioner.
-			Affinity: &corev1.Affinity{
-				PodAffinity: &corev1.PodAffinity{
-					RequiredDuringSchedulingIgnoredDuringExecution: []corev1.PodAffinityTerm{
-						{
-							LabelSelector: &metav1.LabelSelector{
-								MatchLabels: map[string]string{
-									"camel.apache.org/component": "operator",
-								},
-							},
-							TopologyKey: "kubernetes.io/hostname",
-						},
-					},
-				},
-			},
 		},
 	}