diff --git a/api/v1beta/lightrunjavaagent_types.go b/api/v1beta/lightrunjavaagent_types.go index bef29df..73140d5 100644 --- a/api/v1beta/lightrunjavaagent_types.go +++ b/api/v1beta/lightrunjavaagent_types.go @@ -17,6 +17,7 @@ limitations under the License. package v1beta import ( + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -41,6 +42,8 @@ type InitContainer struct { SharedVolumeMountPath string `json:"sharedVolumeMountPath"` // Image of the init container. Image name and tag will define platform and version of the agent Image string `json:"image"` + // Pull policy of the init container. Can be one of: Always, IfNotPresent, or Never. + ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` } // LightrunJavaAgentSpec defines the desired state of LightrunJavaAgent diff --git a/charts/lightrun-agents/README.md b/charts/lightrun-agents/README.md index f988fb7..c4ca0d8 100644 --- a/charts/lightrun-agents/README.md +++ b/charts/lightrun-agents/README.md @@ -35,6 +35,7 @@ The values.yaml file includes the following configurable parameters for each Jav | `javaAgents[].workloadType` | Type of the Kubernetes workload. Must be either `"Deployment"` or `"StatefulSet"`. **Required when using `workloadName`**. | Required (if `workloadName` is used) | | `javaAgents[].deploymentName` | **[DEPRECATED]** Name of the Kubernetes deployment to attach the Lightrun Java Agent. Use `workloadName` and `workloadType` instead. | Required (if `workloadName` not used) | | `javaAgents[].initContainer.image` | Image for the Lightrun Java Agent init container. | Required | +| `javaAgents[].initContainer.imagePullPolicy` | Image pull policy for the init container. Can be one of: Always, IfNotPresent, or Never. | Optional (if not provided, defaults according to [Kubernetes Default Image Pull Policy](https://kubernetes.io/docs/concepts/containers/images/#imagepullpolicy-defaulting)) | | `javaAgents[].initContainer.sharedVolumeMountPath` | Mount path for the shared volume in the init container. | Optional (if not provided, defaults to `"/lightrun"`" | | `javaAgents[].initContainer.sharedVolumeName` | Name of the shared volume for the init container. | Optional (if not provided, defaults to `"lightrun-agent-init"`" | | `javaAgents[].name` | Name of the Lightrun Java Agent custom resource. | Required | @@ -130,6 +131,7 @@ javaAgents: serverHostname: 'lightrun.example.com' initContainer: image: "lightruncom/k8s-operator-init-java-agent-linux:latest" + imagePullPolicy: "IfNotPresent" agentPoolCredentials: existingSecret: "" apiKey: "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" @@ -197,6 +199,7 @@ javaAgents: agentCliFlags: "--lightrun_extra_class_path=:,lightrun_init_wait_time_ms" initContainer: image: "lightruncom/k8s-operator-init-java-agent-linux:latest" + imagePullPolicy: "IfNotPresent" sharedVolumeName: 'my-shared-volume' sharedVolumeMountPath: '/mypath' agentPoolCredentials: @@ -212,6 +215,7 @@ javaAgents: namespace: 'my-namespace-2' initContainer: image: "lightruncom/k8s-operator-init-java-agent-linux:latest" + imagePullPolicy: "IfNotPresent" sharedVolumeName: 'my-shared-volume' sharedVolumeMountPath: '/mypath' # StatefulSet configuration with full options diff --git a/charts/lightrun-agents/templates/java-agent-cr.yaml b/charts/lightrun-agents/templates/java-agent-cr.yaml index 5ef82f0..648f2a0 100644 --- a/charts/lightrun-agents/templates/java-agent-cr.yaml +++ b/charts/lightrun-agents/templates/java-agent-cr.yaml @@ -8,6 +8,9 @@ metadata: spec: initContainer: image: {{ .initContainer.image }} + {{- if .initContainer.imagePullPolicy }} + imagePullPolicy: {{ .initContainer.imagePullPolicy }} + {{- end }} sharedVolumeName: {{ .initContainer.sharedVolumeName | default "lightrun-agent-init" }} sharedVolumeMountPath: {{ .initContainer.sharedVolumeMountPath | default "/lightrun" }} {{- if .workloadName }} diff --git a/charts/lightrun-agents/values.yaml b/charts/lightrun-agents/values.yaml index bcb594e..68874a2 100644 --- a/charts/lightrun-agents/values.yaml +++ b/charts/lightrun-agents/values.yaml @@ -21,6 +21,7 @@ javaAgents: [] # serverHostname: 'lightrun.example.com' # initContainer: # image: "lightruncom/k8s-operator-init-java-agent-linux:latest" +# imagePullPolicy: "IfNotPresent" # agentPoolCredentials: # existingSecret: "" # apiKey: "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" @@ -34,6 +35,7 @@ javaAgents: [] # namespace: 'my-namespace-2' # initContainer: # image: "lightruncom/k8s-operator-init-java-agent-linux:latest" +# imagePullPolicy: "IfNotPresent" # # Example of StatefulSet configuration # workloadName: "my-statefulset-2" # workloadType: "StatefulSet" @@ -73,6 +75,7 @@ javaAgents: [] # agentCliFlags: "--lightrun_extra_class_path=:,lightrun_init_wait_time_ms" # initContainer: # image: "lightruncom/k8s-operator-init-java-agent-linux:latest" +# imagePullPolicy: "IfNotPresent" # sharedVolumeName: 'my-shared-volume' # sharedVolumeMountPath: '/mypath' # agentPoolCredentials: @@ -88,6 +91,7 @@ javaAgents: [] # namespace: 'my-namespace-2' # initContainer: # image: "lightruncom/k8s-operator-init-java-agent-linux:latest" +# imagePullPolicy: "IfNotPresent" # sharedVolumeName: 'my-shared-volume' # sharedVolumeMountPath: '/mypath' # # Example of StatefulSet configuration diff --git a/charts/lightrun-operator/crds/lightrunjavaagent_crd.yaml b/charts/lightrun-operator/crds/lightrunjavaagent_crd.yaml index d748749..04a3629 100644 --- a/charts/lightrun-operator/crds/lightrunjavaagent_crd.yaml +++ b/charts/lightrun-operator/crds/lightrunjavaagent_crd.yaml @@ -98,6 +98,10 @@ spec: description: Image of the init container. Image name and tag will define platform and version of the agent type: string + imagePullPolicy: + description: 'Pull policy of the init container. Can be one of: + Always, IfNotPresent, or Never.' + type: string sharedVolumeMountPath: description: Path in the app container where volume with agent will be mounted diff --git a/config/crd/bases/agents.lightrun.com_lightrunjavaagents.yaml b/config/crd/bases/agents.lightrun.com_lightrunjavaagents.yaml index 9ca3b13..096cbb6 100644 --- a/config/crd/bases/agents.lightrun.com_lightrunjavaagents.yaml +++ b/config/crd/bases/agents.lightrun.com_lightrunjavaagents.yaml @@ -99,6 +99,10 @@ spec: description: Image of the init container. Image name and tag will define platform and version of the agent type: string + imagePullPolicy: + description: 'Pull policy of the init container. Can be one of: + Always, IfNotPresent, or Never.' + type: string sharedVolumeMountPath: description: Path in the app container where volume with agent will be mounted diff --git a/config/samples/operator.yaml b/config/samples/operator.yaml index b8c65a9..230b38d 100644 --- a/config/samples/operator.yaml +++ b/config/samples/operator.yaml @@ -110,6 +110,10 @@ spec: description: Image of the init container. Image name and tag will define platform and version of the agent type: string + imagePullPolicy: + description: 'Pull policy of the init container. Can be one of: + Always, IfNotPresent, or Never.' + type: string sharedVolumeMountPath: description: Path in the app container where volume with agent will be mounted diff --git a/docs/custom_resource.md b/docs/custom_resource.md index 872b54f..040698b 100644 --- a/docs/custom_resource.md +++ b/docs/custom_resource.md @@ -11,6 +11,8 @@ spec: # agent version - first part of the tag (1.7.0) # init container sub-version - last part of the tag (init.0) image: "lightruncom/k8s-operator-init-java-agent-linux:1.7.0-init.0" + # imagePullPolicy of the init container. Can be one of: Always, IfNotPresent, or Never. + imagePullPolicy: "IfNotPresent" # Volume name in case you have some convention in the names sharedVolumeName: lightrun-agent-init # Mount path where volume will be parked. Various distributions may have it's limitations. diff --git a/examples/operator.yaml b/examples/operator.yaml index 000dfc3..0c0d456 100644 --- a/examples/operator.yaml +++ b/examples/operator.yaml @@ -100,6 +100,10 @@ spec: description: Image of the init container. Image name and tag will define platform and version of the agent type: string + imagePullPolicy: + description: 'Pull policy of the init container. Can be one of: + Always, IfNotPresent, or Never.' + type: string sharedVolumeMountPath: description: Path in the app container where volume with agent will be mounted diff --git a/internal/controller/patch_funcs.go b/internal/controller/patch_funcs.go index 68365a7..202088f 100644 --- a/internal/controller/patch_funcs.go +++ b/internal/controller/patch_funcs.go @@ -99,54 +99,57 @@ func (r *LightrunJavaAgentReconciler) addVolume(deploymentApplyConfig *appsv1ac. } func (r *LightrunJavaAgentReconciler) addInitContainer(deploymentApplyConfig *appsv1ac.DeploymentApplyConfiguration, lightrunJavaAgent *agentv1beta.LightrunJavaAgent, secret *corev1.Secret) { - - deploymentApplyConfig.Spec.Template.Spec.WithInitContainers( - corev1ac.Container(). - WithName(initContainerName). - WithImage(lightrunJavaAgent.Spec.InitContainer.Image). - WithVolumeMounts( - corev1ac.VolumeMount().WithName(lightrunJavaAgent.Spec.InitContainer.SharedVolumeName).WithMountPath("/tmp/"), - corev1ac.VolumeMount().WithName(cmVolumeName).WithMountPath("/tmp/cm/"), - ).WithEnv( - corev1ac.EnvVar().WithName("LIGHTRUN_KEY").WithValueFrom( - corev1ac.EnvVarSource().WithSecretKeyRef( - corev1ac.SecretKeySelector().WithName(secret.Name).WithKey("lightrun_key"), - ), + spec := lightrunJavaAgent.Spec + isImagePullPolicyConfigured := spec.InitContainer.ImagePullPolicy != "" + initContainerApplyConfig := corev1ac.Container(). + WithName(initContainerName). + WithImage(spec.InitContainer.Image). + WithVolumeMounts( + corev1ac.VolumeMount().WithName(spec.InitContainer.SharedVolumeName).WithMountPath("/tmp/"), + corev1ac.VolumeMount().WithName(cmVolumeName).WithMountPath("/tmp/cm/"), + ).WithEnv( + corev1ac.EnvVar().WithName("LIGHTRUN_KEY").WithValueFrom( + corev1ac.EnvVarSource().WithSecretKeyRef( + corev1ac.SecretKeySelector().WithName(secret.Name).WithKey("lightrun_key"), ), - corev1ac.EnvVar().WithName("PINNED_CERT").WithValueFrom( - corev1ac.EnvVarSource().WithSecretKeyRef( - corev1ac.SecretKeySelector().WithName(secret.Name).WithKey("pinned_cert_hash"), - ), + ), + corev1ac.EnvVar().WithName("PINNED_CERT").WithValueFrom( + corev1ac.EnvVarSource().WithSecretKeyRef( + corev1ac.SecretKeySelector().WithName(secret.Name).WithKey("pinned_cert_hash"), ), - corev1ac.EnvVar().WithName("LIGHTRUN_SERVER").WithValue(lightrunJavaAgent.Spec.ServerHostname), - ). - WithResources( - corev1ac.ResourceRequirements(). - WithLimits( - corev1.ResourceList{ - corev1.ResourceCPU: *resource.NewMilliQuantity(int64(50), resource.BinarySI), - corev1.ResourceMemory: *resource.NewScaledQuantity(int64(64), resource.Scale(6)), // 500 * 10^6 = 500M - }, - ).WithRequests( + ), + corev1ac.EnvVar().WithName("LIGHTRUN_SERVER").WithValue(spec.ServerHostname), + ). + WithResources( + corev1ac.ResourceRequirements(). + WithLimits( corev1.ResourceList{ corev1.ResourceCPU: *resource.NewMilliQuantity(int64(50), resource.BinarySI), - corev1.ResourceMemory: *resource.NewScaledQuantity(int64(64), resource.Scale(6)), + corev1.ResourceMemory: *resource.NewScaledQuantity(int64(64), resource.Scale(6)), // 500 * 10^6 = 500M }, - ), - ). - WithSecurityContext( - corev1ac.SecurityContext(). - WithCapabilities( - corev1ac.Capabilities().WithDrop(corev1.Capability("ALL")), - ). - WithAllowPrivilegeEscalation(false). - WithRunAsNonRoot(true). - WithSeccompProfile( - corev1ac.SeccompProfile(). - WithType(corev1.SeccompProfileTypeRuntimeDefault), - ), + ).WithRequests( + corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewMilliQuantity(int64(50), resource.BinarySI), + corev1.ResourceMemory: *resource.NewScaledQuantity(int64(64), resource.Scale(6)), + }, ), - ) + ). + WithSecurityContext( + corev1ac.SecurityContext(). + WithCapabilities( + corev1ac.Capabilities().WithDrop(corev1.Capability("ALL")), + ). + WithAllowPrivilegeEscalation(false). + WithRunAsNonRoot(true). + WithSeccompProfile( + corev1ac.SeccompProfile(). + WithType(corev1.SeccompProfileTypeRuntimeDefault), + ), + ) + if isImagePullPolicyConfigured { + initContainerApplyConfig.WithImagePullPolicy(spec.InitContainer.ImagePullPolicy) + } + deploymentApplyConfig.Spec.Template.Spec.WithInitContainers(initContainerApplyConfig) } func (r *LightrunJavaAgentReconciler) patchAppContainers(lightrunJavaAgent *agentv1beta.LightrunJavaAgent, origDeployment *appsv1.Deployment, deploymentApplyConfig *appsv1ac.DeploymentApplyConfiguration) error { @@ -275,53 +278,57 @@ func (r *LightrunJavaAgentReconciler) addVolumeToStatefulSet(statefulSetApplyCon } func (r *LightrunJavaAgentReconciler) addInitContainerToStatefulSet(statefulSetApplyConfig *appsv1ac.StatefulSetApplyConfiguration, lightrunJavaAgent *agentv1beta.LightrunJavaAgent, secret *corev1.Secret) { - statefulSetApplyConfig.Spec.Template.Spec.WithInitContainers( - corev1ac.Container(). - WithName(initContainerName). - WithImage(lightrunJavaAgent.Spec.InitContainer.Image). - WithVolumeMounts( - corev1ac.VolumeMount().WithName(lightrunJavaAgent.Spec.InitContainer.SharedVolumeName).WithMountPath("/tmp/"), - corev1ac.VolumeMount().WithName(cmVolumeName).WithMountPath("/tmp/cm/"), - ).WithEnv( - corev1ac.EnvVar().WithName("LIGHTRUN_KEY").WithValueFrom( - corev1ac.EnvVarSource().WithSecretKeyRef( - corev1ac.SecretKeySelector().WithName(secret.Name).WithKey("lightrun_key"), - ), + spec := lightrunJavaAgent.Spec + isImagePullPolicyConfigured := spec.InitContainer.ImagePullPolicy != "" + initContainerApplyConfig := corev1ac.Container(). + WithName(initContainerName). + WithImage(spec.InitContainer.Image). + WithVolumeMounts( + corev1ac.VolumeMount().WithName(spec.InitContainer.SharedVolumeName).WithMountPath("/tmp/"), + corev1ac.VolumeMount().WithName(cmVolumeName).WithMountPath("/tmp/cm/"), + ).WithEnv( + corev1ac.EnvVar().WithName("LIGHTRUN_KEY").WithValueFrom( + corev1ac.EnvVarSource().WithSecretKeyRef( + corev1ac.SecretKeySelector().WithName(secret.Name).WithKey("lightrun_key"), ), - corev1ac.EnvVar().WithName("PINNED_CERT").WithValueFrom( - corev1ac.EnvVarSource().WithSecretKeyRef( - corev1ac.SecretKeySelector().WithName(secret.Name).WithKey("pinned_cert_hash"), - ), + ), + corev1ac.EnvVar().WithName("PINNED_CERT").WithValueFrom( + corev1ac.EnvVarSource().WithSecretKeyRef( + corev1ac.SecretKeySelector().WithName(secret.Name).WithKey("pinned_cert_hash"), ), - corev1ac.EnvVar().WithName("LIGHTRUN_SERVER").WithValue(lightrunJavaAgent.Spec.ServerHostname), - ). - WithResources( - corev1ac.ResourceRequirements(). - WithLimits( - corev1.ResourceList{ - corev1.ResourceCPU: *resource.NewMilliQuantity(int64(50), resource.BinarySI), - corev1.ResourceMemory: *resource.NewScaledQuantity(int64(64), resource.Scale(6)), // 64M - }, - ).WithRequests( + ), + corev1ac.EnvVar().WithName("LIGHTRUN_SERVER").WithValue(spec.ServerHostname), + ). + WithResources( + corev1ac.ResourceRequirements(). + WithLimits( corev1.ResourceList{ corev1.ResourceCPU: *resource.NewMilliQuantity(int64(50), resource.BinarySI), - corev1.ResourceMemory: *resource.NewScaledQuantity(int64(64), resource.Scale(6)), + corev1.ResourceMemory: *resource.NewScaledQuantity(int64(64), resource.Scale(6)), // 64M }, - ), - ). - WithSecurityContext( - corev1ac.SecurityContext(). - WithCapabilities( - corev1ac.Capabilities().WithDrop(corev1.Capability("ALL")), - ). - WithAllowPrivilegeEscalation(false). - WithRunAsNonRoot(true). - WithSeccompProfile( - corev1ac.SeccompProfile(). - WithType(corev1.SeccompProfileTypeRuntimeDefault), - ), + ).WithRequests( + corev1.ResourceList{ + corev1.ResourceCPU: *resource.NewMilliQuantity(int64(50), resource.BinarySI), + corev1.ResourceMemory: *resource.NewScaledQuantity(int64(64), resource.Scale(6)), + }, ), - ) + ). + WithSecurityContext( + corev1ac.SecurityContext(). + WithCapabilities( + corev1ac.Capabilities().WithDrop(corev1.Capability("ALL")), + ). + WithAllowPrivilegeEscalation(false). + WithRunAsNonRoot(true). + WithSeccompProfile( + corev1ac.SeccompProfile(). + WithType(corev1.SeccompProfileTypeRuntimeDefault), + ), + ) + if isImagePullPolicyConfigured { + initContainerApplyConfig.WithImagePullPolicy(spec.InitContainer.ImagePullPolicy) + } + statefulSetApplyConfig.Spec.Template.Spec.WithInitContainers(initContainerApplyConfig) } func (r *LightrunJavaAgentReconciler) patchStatefulSetAppContainers(lightrunJavaAgent *agentv1beta.LightrunJavaAgent, origStatefulSet *appsv1.StatefulSet, statefulSetApplyConfig *appsv1ac.StatefulSetApplyConfiguration) error {