Repository: aws/karpenter-provider-aws
Pull request #7279: feat(chart): Improved default security context
Author: login: stevehipwell
Created: 2024-10-25T15:53:20Z | Merged: 2025-04-17T16:29:17Z

<!-- Please follow the guidelines at https://www.conventionalcommits.org/en/v1.0.0/ and use one of the following in your title:
feat:            <-- New features that require a MINOR version update
fix:             <-- Bug fixes that require at PATCH version update
chore:           <-- Smaller changes that impact behavior but aren't large enough to be features
perf:            <-- Code changes that improve performance but do not impact behavior
docs:            <-- Documentation changes that do not impact code
test:            <-- Test changes that do not impact behavior
ci:              <-- Changes that affect test or rollout automation
!${type}:        <-- Include ! if your change includes a backwards incompatible change.

Please review the Karpenter contribution docs at https://karpenter.sh/docs/contributing/ before submitting your pull request.
-->

Fixes #N/A <!-- issue number -->

**Description**
This PR improves the default security context posture and adds support for setting container values which should be user defined.

**How was this change tested?**
The Helm chart was templated with the new values.

**Does this change impact docs?**
- [x] Yes, PR includes docs updates <!-- docs must be added to /preview to be included in future version releases -->
- [ ] Yes, issue opened: # <!-- issue number -->
- [ ] No

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.


Diff:
diff --git a/charts/karpenter-crd/README.md b/charts/karpenter-crd/README.md
index 566d9a7efa12..1538a497c2fc 100644
--- a/charts/karpenter-crd/README.md
+++ b/charts/karpenter-crd/README.md
@@ -1,6 +1,6 @@
 # karpenter-crd
 
-![Version: 0.36.0](https://img.shields.io/badge/Version-0.36.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.36.0](https://img.shields.io/badge/AppVersion-0.36.0-informational?style=flat-square)
+![Version: 1.3.2](https://img.shields.io/badge/Version-1.3.2-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.3.2](https://img.shields.io/badge/AppVersion-1.3.2-informational?style=flat-square)
 
 A Helm chart for Karpenter Custom Resource Definitions (CRDs).
 
@@ -10,6 +10,12 @@ A Helm chart for Karpenter Custom Resource Definitions (CRDs).
 
 * <https://github.com/aws/karpenter/>
 
+## Values
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| additionalAnnotations | object | `{}` | Additional annotations for the custom resource definitions. |
+
 ----------------------------------------------
 
 Autogenerated from chart metadata using [helm-docs](https://github.com/norwoodj/helm-docs/).
diff --git a/charts/karpenter/README.md b/charts/karpenter/README.md
index 5fe09d2e33c0..60f750526855 100644
--- a/charts/karpenter/README.md
+++ b/charts/karpenter/README.md
@@ -47,13 +47,16 @@ cosign verify public.ecr.aws/karpenter/karpenter:1.3.2 \
 | controller.containerName | string | `"controller"` | Distinguishing container name (containerName: karpenter-controller). |
 | controller.env | list | `[]` | Additional environment variables for the controller pod. |
 | controller.envFrom | list | `[]` |  |
-| controller.extraVolumeMounts | list | `[]` | Additional volumeMounts for the controller pod. |
+| controller.extraVolumeMounts | list | `[]` | Additional volumeMounts for the controller container. |
 | controller.healthProbe.port | int | `8081` | The container port to use for http health probe. |
 | controller.image.digest | string | `"sha256:3fffcbbb6d0b1a2183a07bbe52c902d344fa41f8a8485de43760432ef7e2fd17"` | SHA256 digest of the controller image. |
 | controller.image.repository | string | `"public.ecr.aws/karpenter/controller"` | Repository path to the controller image. |
 | controller.image.tag | string | `"1.3.2"` | Tag of the controller image. |
 | controller.metrics.port | int | `8080` | The container port to use for metrics. |
-| controller.resources | object | `{}` | Resources for the controller pod. |
+| controller.resources | object | `{}` | Resources for the controller container. |
+| controller.securityContext.appArmorProfile | object | `{}` | AppArmor profile for the controller container. |
+| controller.securityContext.seLinuxOptions | object | `{}` | SELinux options for the controller container. |
+| controller.securityContext.seccompProfile | object | `{}` | Seccomp profile for the controller container. |
 | controller.sidecarContainer | list | `[]` | Additional sidecarContainer config |
 | controller.sidecarVolumeMounts | list | `[]` | Additional volumeMounts for the sidecar - this will be added to the volume mounts on top of extraVolumeMounts |
 | dnsConfig | object | `{}` | Configure DNS Config for the pod |
@@ -73,7 +76,7 @@ cosign verify public.ecr.aws/karpenter/karpenter:1.3.2 \
 | podDisruptionBudget.maxUnavailable | int | `1` |  |
 | podDisruptionBudget.name | string | `"karpenter"` |  |
 | podLabels | object | `{}` | Additional labels for the pod. |
-| podSecurityContext | object | `{"fsGroup":65532}` | SecurityContext for the pod. |
+| podSecurityContext | object | `{"fsGroup":65532,"runAsNonRoot":false,"seccompProfile":{"type":"RuntimeDefault"}}` | SecurityContext for the pod. |
 | priorityClassName | string | `"system-cluster-critical"` | PriorityClass name for the pod. |
 | replicas | int | `2` | Number of replicas. |
 | revisionHistoryLimit | int | `10` | The number of old ReplicaSets to retain to allow rollback. |
@@ -89,16 +92,17 @@ cosign verify public.ecr.aws/karpenter/karpenter:1.3.2 \
 | settings.batchIdleDuration | string | `"1s"` | The maximum amount of time with no new ending pods that if exceeded ends the current batching window. If pods arrive faster than this time, the batching window will be extended up to the maxDuration. If they arrive slower, the pods will be batched separately. |
 | settings.batchMaxDuration | string | `"10s"` | The maximum length of a batch window. The longer this is, the more pods we can consider for provisioning at one time which usually results in fewer but larger nodes. |
 | settings.clusterCABundle | string | `""` | Cluster CA bundle for TLS configuration of provisioned nodes. If not set, this is taken from the controller's TLS configuration for the API server. |
-| settings.clusterEndpoint | string | `""` | Cluster endpoint. If not set, will be discovered during startup (EKS only) |
+| settings.clusterEndpoint | string | `""` | Cluster endpoint. If not set, will be discovered during startup (EKS only). |
 | settings.clusterName | string | `""` | Cluster name. |
-| settings.featureGates | object | `{"nodeRepair":false,"reservedCapacity":false,"spotToSpotConsolidation":false}` | Feature Gate configuration values. Feature Gates will follow the same graduation process and requirements as feature gates in Kubernetes. More information here https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/#feature-gates-for-alpha-or-beta-features |
+| settings.eksControlPlane | bool | `false` | Marking this true means that your cluster is running with an EKS control plane and Karpenter should attempt to discover cluster details from the DescribeCluster API. |
+| settings.featureGates | object | `{"nodeRepair":false,"reservedCapacity":false,"spotToSpotConsolidation":false}` | Feature Gate configuration values. Feature Gates will follow the same graduation process and requirements as feature gates in Kubernetes. More information here https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/#feature-gates-for-alpha-or-beta-features. |
 | settings.featureGates.nodeRepair | bool | `false` | nodeRepair is ALPHA and is disabled by default. Setting this to true will enable node repair. |
 | settings.featureGates.reservedCapacity | bool | `false` | reservedCapacity is ALPHA and is disabled by default. Setting this will enable native on-demand capacity reservation support. |
 | settings.featureGates.spotToSpotConsolidation | bool | `false` | spotToSpotConsolidation is ALPHA and is disabled by default. Setting this to true will enable spot replacement consolidation for both single and multi-node consolidation. |
-| settings.interruptionQueue | string | `""` | Interruption queue is the name of the SQS queue used for processing interruption events from EC2 Interruption handling is disabled if not specified. Enabling interruption handling may require additional permissions on the controller service account. Additional permissions are outlined in the docs. |
-| settings.isolatedVPC | bool | `false` | If true then assume we can't reach AWS services which don't have a VPC endpoint This also has the effect of disabling look-ups to the AWS pricing endpoint |
+| settings.interruptionQueue | string | `""` | Interruption queue is the name of the SQS queue used for processing interruption events from EC2. Interruption handling is disabled if not specified. Enabling interruption handling may require additional permissions on the controller service account. Additional permissions are outlined in the docs. |
+| settings.isolatedVPC | bool | `false` | If true then assume we can't reach AWS services which don't have a VPC endpoint. This also has the effect of disabling look-ups to the AWS pricing endpoint. |
 | settings.preferencePolicy | string | `"Respect"` | How the Karpenter scheduler should treat preferences. Preferences include preferredDuringSchedulingIgnoreDuringExecution node and pod affinities/anti-affinities and ScheduleAnyways topologySpreadConstraints. Can be one of 'Ignore' and 'Respect' |
-| settings.reservedENIs | string | `"0"` | Reserved ENIs are not included in the calculations for max-pods or kube-reserved This is most often used in the VPC CNI custom networking setup https://docs.aws.amazon.com/eks/latest/userguide/cni-custom-network.html |
+| settings.reservedENIs | string | `"0"` | Reserved ENIs are not included in the calculations for max-pods or kube-reserved. This is most often used in the VPC CNI custom networking setup https://docs.aws.amazon.com/eks/latest/userguide/cni-custom-network.html. |
 | settings.vmMemoryOverheadPercent | float | `0.075` | The VM memory overhead as a percent that will be subtracted from the total memory for all instance types. The value of `0.075` equals to 7.5%. |
 | strategy | object | `{"rollingUpdate":{"maxUnavailable":1}}` | Strategy for updating the pod. |
 | terminationGracePeriodSeconds | string | `nil` | Override the default termination grace period for the pod. |
diff --git a/charts/karpenter/templates/deployment.yaml b/charts/karpenter/templates/deployment.yaml
index 851b7bc2e100..ac2500cceb48 100644
--- a/charts/karpenter/templates/deployment.yaml
+++ b/charts/karpenter/templates/deployment.yaml
@@ -63,16 +63,29 @@ spec:
       containers:
         - name: {{ include "karpenter.controller.containerName" . }}
           securityContext:
+            privileged: false
+            allowPrivilegeEscalation: false
+            readOnlyRootFilesystem: true
+            runAsNonRoot: true
             runAsUser: 65532
             runAsGroup: 65532
-            runAsNonRoot: true
-            seccompProfile:
-              type: RuntimeDefault
-            allowPrivilegeEscalation: false
             capabilities:
               drop:
                 - ALL
-            readOnlyRootFilesystem: true
+          {{- with .Values.controller.securityContext }}
+          {{- with .appArmorProfile }}
+            appArmorProfile:
+              {{- toYaml . | nindent 14}}
+          {{- end }}
+          {{- with .seLinuxOptions }}
+            seLinuxOptions:
+              {{- toYaml . | nindent 14}}
+          {{- end }}
+          {{- with .seccompProfile }}
+            seccompProfile:
+              {{- toYaml . | nindent 14}}
+          {{- end }}
+          {{- end }}
           image: {{ include "karpenter.controller.image" . }}
           imagePullPolicy: {{ .Values.imagePullPolicy }}
           env:
diff --git a/charts/karpenter/values.yaml b/charts/karpenter/values.yaml
index 842cfff02d71..db7edeb6d85c 100644
--- a/charts/karpenter/values.yaml
+++ b/charts/karpenter/values.yaml
@@ -51,7 +51,10 @@ podDisruptionBudget:
   maxUnavailable: 1
 # -- SecurityContext for the pod.
 podSecurityContext:
+  runAsNonRoot: false
   fsGroup: 65532
+  seccompProfile:
+    type: RuntimeDefault
 # -- PriorityClass name for the pod.
 priorityClassName: system-cluster-critical
 # -- Override the default termination grace period for the pod.
@@ -121,7 +124,14 @@ controller:
   # - name: AWS_REGION
   #   value: eu-west-1
   envFrom: []
-  # -- Resources for the controller pod.
+  securityContext:
+    # -- AppArmor profile for the controller container.
+    appArmorProfile: {}
+    # -- SELinux options for the controller container.
+    seLinuxOptions: {}
+    # -- Seccomp profile for the controller container.
+    seccompProfile: {}
+  # -- Resources for the controller container.
   resources: {}
   # We usually recommend not to specify default resources and to leave this as a conscious
   # choice for the user. This also increases chances charts run on environments with little
@@ -133,8 +143,7 @@ controller:
   #  limits:
   #    cpu: 1
   #    memory: 1Gi
-
-  # -- Additional volumeMounts for the controller pod.
+  # -- Additional volumeMounts for the controller container.
   extraVolumeMounts: []
   # - name: aws-iam-token
   #   mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount
@@ -173,24 +182,24 @@ settings:
   clusterCABundle: ""
   # -- Cluster name.
   clusterName: ""
-  # -- Cluster endpoint. If not set, will be discovered during startup (EKS only)
+  # -- Cluster endpoint. If not set, will be discovered during startup (EKS only).
   clusterEndpoint: ""
-  # -- If true then assume we can't reach AWS services which don't have a VPC endpoint
-  # This also has the effect of disabling look-ups to the AWS pricing endpoint
+  # -- If true then assume we can't reach AWS services which don't have a VPC endpoint.
+  # This also has the effect of disabling look-ups to the AWS pricing endpoint.
   isolatedVPC: false
-  # Marking this true means that your cluster is running with an EKS control plane and Karpenter should attempt to discover cluster details from the DescribeCluster API
+  # -- Marking this true means that your cluster is running with an EKS control plane and Karpenter should attempt to discover cluster details from the DescribeCluster API.
   eksControlPlane: false
   # -- The VM memory overhead as a percent that will be subtracted from the total memory for all instance types. The value of `0.075` equals to 7.5%.
   vmMemoryOverheadPercent: 0.075
-  # -- Interruption queue is the name of the SQS queue used for processing interruption events from EC2
+  # -- Interruption queue is the name of the SQS queue used for processing interruption events from EC2.
   # Interruption handling is disabled if not specified. Enabling interruption handling may
   # require additional permissions on the controller service account. Additional permissions are outlined in the docs.
   interruptionQueue: ""
-  # -- Reserved ENIs are not included in the calculations for max-pods or kube-reserved
-  # This is most often used in the VPC CNI custom networking setup https://docs.aws.amazon.com/eks/latest/userguide/cni-custom-network.html
+  # -- Reserved ENIs are not included in the calculations for max-pods or kube-reserved.
+  # This is most often used in the VPC CNI custom networking setup https://docs.aws.amazon.com/eks/latest/userguide/cni-custom-network.html.
   reservedENIs: "0"
   # -- Feature Gate configuration values. Feature Gates will follow the same graduation process and requirements as feature gates
-  # in Kubernetes. More information here https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/#feature-gates-for-alpha-or-beta-features
+  # in Kubernetes. More information here https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/#feature-gates-for-alpha-or-beta-features.
   featureGates:
     # -- nodeRepair is ALPHA and is disabled by default.
     # Setting this to true will enable node repair.


Reviews:
user: login: saurav-agarwalla
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-01-17T19:17:58Z
user: login: stevehipwell
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-01-17T20:07:41Z
user: login: stevehipwell
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-01-17T20:08:34Z
user: login: stevehipwell
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-01-17T20:09:13Z
user: login: saurav-agarwalla
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-01-17T20:25:54Z
user: login: saurav-agarwalla
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-01-17T20:31:57Z
user: login: stevehipwell
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-01-18T17:11:23Z
user: login: stevehipwell
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-01-18T17:13:22Z
user: login: stevehipwell
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-01-18T17:14:57Z
user: login: stevehipwell
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-01-20T11:10:42Z
user: login: saurav-agarwalla
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-01-22T21:05:43Z
user: login: saurav-agarwalla
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-01-22T21:05:48Z
user: login: stevehipwell
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-01-23T11:51:34Z
user: login: stevehipwell
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-01-23T11:52:19Z
user: login: jonathan-innis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-07T06:29:30Z
user: login: stevehipwell
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-07T14:10:00Z
user: login: stevehipwell
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-07T14:16:23Z
user: login: stevehipwell
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-07T14:18:38Z
user: login: jonathan-innis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-14T01:23:52Z
user: login: jonathan-innis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-14T01:24:00Z
user: login: jonathan-innis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-14T01:27:26Z
user: login: stevehipwell
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-14T10:15:37Z
user: login: jonathan-innis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T22:34:54Z
user: login: stevehipwell
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T15:51:58Z
user: login: stevehipwell
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T15:52:26Z
user: login: jonathan-innis
body: LGTM 🚀 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T16:23:41Z

Review comments:
diff_hunk: @@ -72,7 +75,7 @@ cosign verify public.ecr.aws/karpenter/karpenter:1.1.1 \
 | podDisruptionBudget.maxUnavailable | int | `1` |  |
 | podDisruptionBudget.name | string | `"karpenter"` |  |
 | podLabels | object | `{}` | Additional labels for the pod. |
-| podSecurityContext | object | `{"fsGroup":65532}` | SecurityContext for the pod. |
+| podSecurityContext | object | `{"fsGroup":65532,"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}}` | SecurityContext for the pod. |
path: charts/karpenter/README.md
user: login: saurav-agarwalla
body: Why do we need to change the defaults?
created_at: 2025-01-02T20:57:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -90,7 +93,6 @@ cosign verify public.ecr.aws/karpenter/karpenter:1.1.1 \
 | settings.clusterCABundle | string | `""` | Cluster CA bundle for TLS configuration of provisioned nodes. If not set, this is taken from the controller's TLS configuration for the API server. |
 | settings.clusterEndpoint | string | `""` | Cluster endpoint. If not set, will be discovered during startup (EKS only) |
 | settings.clusterName | string | `""` | Cluster name. |
-| settings.eksControlPlane | bool | `false` | Marking this true means that your cluster is running with an EKS control plane and Karpenter should attempt to discover cluster details from the DescribeCluster API |
path: charts/karpenter/README.md
user: login: saurav-agarwalla
body: Any reason this is being removed?
created_at: 2025-01-02T20:58:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -62,16 +62,29 @@ spec:
       containers:
         - name: {{ .Values.controller.containerName | default "controller" }}
           securityContext:
+            privileged: false
path: charts/karpenter/templates/deployment.yaml
user: login: saurav-agarwalla
body: Is this something you wanted to add? If so, should we parameterize it for backwards compatibility like the others?
created_at: 2025-01-02T21:00:36Z
author_association: CONTRIBUTOR
diff_hunk: @@ -62,16 +62,29 @@ spec:
       containers:
         - name: {{ .Values.controller.containerName | default "controller" }}
           securityContext:
+            privileged: false
path: charts/karpenter/templates/deployment.yaml
user: login: stevehipwell
body: There is no need to make this optional as Karpenter doesn't need it. Some systems want it explicitly set for policy purposes.
created_at: 2025-01-17T20:07:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -72,7 +75,7 @@ cosign verify public.ecr.aws/karpenter/karpenter:1.1.1 \
 | podDisruptionBudget.maxUnavailable | int | `1` |  |
 | podDisruptionBudget.name | string | `"karpenter"` |  |
 | podLabels | object | `{}` | Additional labels for the pod. |
-| podSecurityContext | object | `{"fsGroup":65532}` | SecurityContext for the pod. |
+| podSecurityContext | object | `{"fsGroup":65532,"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}}` | SecurityContext for the pod. |
path: charts/karpenter/README.md
user: login: stevehipwell
body: Some systems need this making explicit for policy purposes.
created_at: 2025-01-17T20:08:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -90,7 +93,6 @@ cosign verify public.ecr.aws/karpenter/karpenter:1.1.1 \
 | settings.clusterCABundle | string | `""` | Cluster CA bundle for TLS configuration of provisioned nodes. If not set, this is taken from the controller's TLS configuration for the API server. |
 | settings.clusterEndpoint | string | `""` | Cluster endpoint. If not set, will be discovered during startup (EKS only) |
 | settings.clusterName | string | `""` | Cluster name. |
-| settings.eksControlPlane | bool | `false` | Marking this true means that your cluster is running with an EKS control plane and Karpenter should attempt to discover cluster details from the DescribeCluster API |
path: charts/karpenter/README.md
user: login: stevehipwell
body: I'm not sure, I guess it might be a merge artifact.
created_at: 2025-01-17T20:09:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -62,16 +62,29 @@ spec:
       containers:
         - name: {{ .Values.controller.containerName | default "controller" }}
           securityContext:
+            privileged: false
path: charts/karpenter/templates/deployment.yaml
user: login: saurav-agarwalla
body: From the docs:
> `privileged` _boolean_	
> Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false. Note that this field cannot be set when spec.os.name is windows.

So I don't think we can set it without parameterizing it.
created_at: 2025-01-17T20:25:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -72,7 +75,7 @@ cosign verify public.ecr.aws/karpenter/karpenter:1.1.1 \
 | podDisruptionBudget.maxUnavailable | int | `1` |  |
 | podDisruptionBudget.name | string | `"karpenter"` |  |
 | podLabels | object | `{}` | Additional labels for the pod. |
-| podSecurityContext | object | `{"fsGroup":65532}` | SecurityContext for the pod. |
+| podSecurityContext | object | `{"fsGroup":65532,"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}}` | SecurityContext for the pod. |
path: charts/karpenter/README.md
user: login: saurav-agarwalla
body: Same comment as the other one below. As per the documentation, we're changing the desired behavior by setting these values so I am not sure if we should be setting this for everyone:
> Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.

https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#securitycontext-v1-core
created_at: 2025-01-17T20:30:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -90,7 +93,6 @@ cosign verify public.ecr.aws/karpenter/karpenter:1.1.1 \
 | settings.clusterCABundle | string | `""` | Cluster CA bundle for TLS configuration of provisioned nodes. If not set, this is taken from the controller's TLS configuration for the API server. |
 | settings.clusterEndpoint | string | `""` | Cluster endpoint. If not set, will be discovered during startup (EKS only) |
 | settings.clusterName | string | `""` | Cluster name. |
-| settings.eksControlPlane | bool | `false` | Marking this true means that your cluster is running with an EKS control plane and Karpenter should attempt to discover cluster details from the DescribeCluster API |
path: charts/karpenter/README.md
user: login: saurav-agarwalla
body: Can you add it back? I am seeing this in the latest main so I don't think we want to remove it: https://github.com/aws/karpenter-provider-aws/blob/main/charts/karpenter/README.md?plain=1#L93.
created_at: 2025-01-17T20:31:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -90,7 +93,6 @@ cosign verify public.ecr.aws/karpenter/karpenter:1.1.1 \
 | settings.clusterCABundle | string | `""` | Cluster CA bundle for TLS configuration of provisioned nodes. If not set, this is taken from the controller's TLS configuration for the API server. |
 | settings.clusterEndpoint | string | `""` | Cluster endpoint. If not set, will be discovered during startup (EKS only) |
 | settings.clusterName | string | `""` | Cluster name. |
-| settings.eksControlPlane | bool | `false` | Marking this true means that your cluster is running with an EKS control plane and Karpenter should attempt to discover cluster details from the DescribeCluster API |
path: charts/karpenter/README.md
user: login: stevehipwell
body: I'll add this back.
created_at: 2025-01-18T17:11:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -62,16 +62,29 @@ spec:
       containers:
         - name: {{ .Values.controller.containerName | default "controller" }}
           securityContext:
+            privileged: false
path: charts/karpenter/templates/deployment.yaml
user: login: stevehipwell
body: The default is un privileged, we're just making it explicit as some org policies require it to be so. Karpenter will never need this so there is no valid reason to set it otherwise. Helm charts should only offer customisation where required, first party Helm charts even more so.
created_at: 2025-01-18T17:13:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -72,7 +75,7 @@ cosign verify public.ecr.aws/karpenter/karpenter:1.1.1 \
 | podDisruptionBudget.maxUnavailable | int | `1` |  |
 | podDisruptionBudget.name | string | `"karpenter"` |  |
 | podLabels | object | `{}` | Additional labels for the pod. |
-| podSecurityContext | object | `{"fsGroup":65532}` | SecurityContext for the pod. |
+| podSecurityContext | object | `{"fsGroup":65532,"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}}` | SecurityContext for the pod. |
path: charts/karpenter/README.md
user: login: stevehipwell
body: Karpenter runs as non-root so this can be set with no implications. It is 100% a best practice to set this.
created_at: 2025-01-18T17:14:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -90,7 +93,6 @@ cosign verify public.ecr.aws/karpenter/karpenter:1.1.1 \
 | settings.clusterCABundle | string | `""` | Cluster CA bundle for TLS configuration of provisioned nodes. If not set, this is taken from the controller's TLS configuration for the API server. |
 | settings.clusterEndpoint | string | `""` | Cluster endpoint. If not set, will be discovered during startup (EKS only) |
 | settings.clusterName | string | `""` | Cluster name. |
-| settings.eksControlPlane | bool | `false` | Marking this true means that your cluster is running with an EKS control plane and Karpenter should attempt to discover cluster details from the DescribeCluster API |
path: charts/karpenter/README.md
user: login: stevehipwell
body: So it turns out I didn't remove anything; whoever added this didn't configure the helm-docs comment correctly and then manually updated the README to work around it. When I ran `helm-docs` for this PR it was removed.
created_at: 2025-01-20T11:10:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -62,16 +62,29 @@ spec:
       containers:
         - name: {{ .Values.controller.containerName | default "controller" }}
           securityContext:
+            privileged: false
path: charts/karpenter/templates/deployment.yaml
user: login: saurav-agarwalla
body: > The default is un privileged, we're just making it explicit as some org policies require it to be so.

But setting it will break windows like I linked above. So why not offer it as a parameter for anyone who wants to set it?
created_at: 2025-01-22T21:05:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -72,7 +75,7 @@ cosign verify public.ecr.aws/karpenter/karpenter:1.1.1 \
 | podDisruptionBudget.maxUnavailable | int | `1` |  |
 | podDisruptionBudget.name | string | `"karpenter"` |  |
 | podLabels | object | `{}` | Additional labels for the pod. |
-| podSecurityContext | object | `{"fsGroup":65532}` | SecurityContext for the pod. |
+| podSecurityContext | object | `{"fsGroup":65532,"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}}` | SecurityContext for the pod. |
path: charts/karpenter/README.md
user: login: saurav-agarwalla
body: @stevehipwell My question was more around if/why this needs to be a breaking change (although I don't disagree that this is a best practice).
created_at: 2025-01-22T21:05:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -62,16 +62,29 @@ spec:
       containers:
         - name: {{ .Values.controller.containerName | default "controller" }}
           securityContext:
+            privileged: false
path: charts/karpenter/templates/deployment.yaml
user: login: stevehipwell
body: @saurav-agarwalla Karpenter is linux only!
created_at: 2025-01-23T11:51:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -72,7 +75,7 @@ cosign verify public.ecr.aws/karpenter/karpenter:1.1.1 \
 | podDisruptionBudget.maxUnavailable | int | `1` |  |
 | podDisruptionBudget.name | string | `"karpenter"` |  |
 | podLabels | object | `{}` | Additional labels for the pod. |
-| podSecurityContext | object | `{"fsGroup":65532}` | SecurityContext for the pod. |
+| podSecurityContext | object | `{"fsGroup":65532,"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}}` | SecurityContext for the pod. |
path: charts/karpenter/README.md
user: login: stevehipwell
body: It's not a breaking change, Karpenter already runs as non-root!
created_at: 2025-01-23T11:52:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -62,16 +62,29 @@ spec:
       containers:
         - name: {{ .Values.controller.containerName | default "controller" }}
           securityContext:
+            privileged: false
+            allowPrivilegeEscalation: false
+            readOnlyRootFilesystem: true
+            runAsNonRoot: true
             runAsUser: 65532
             runAsGroup: 65532
-            runAsNonRoot: true
-            seccompProfile:
-              type: RuntimeDefault
-            allowPrivilegeEscalation: false
             capabilities:
               drop:
                 - ALL
-            readOnlyRootFilesystem: true
+          {{- with .Values.controller.securityContext }}
+          {{- with .appArmorProfile }}
+            appArmorProfile:
+              {{- toYaml . | nindent 14}}
+          {{- end }}
+          {{- with .seLinuxOptions }}
+            seLinuxOptions:
+              {{- toYaml . | nindent 14}}
+          {{- end }}
+          {{- with .seccompProfile }}
path: charts/karpenter/templates/deployment.yaml
user: login: jonathan-innis
body: Just curious since I'm less familiar with the securityContext details: What's the reason that you need to set the seccompProfile rather than just using the RuntimeDefault?
created_at: 2025-02-07T06:28:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -51,7 +51,10 @@ podDisruptionBudget:
   maxUnavailable: 1
 # -- SecurityContext for the pod.
 podSecurityContext:
+  runAsNonRoot: true
path: charts/karpenter/values.yaml
user: login: jonathan-innis
body: Can we do this? I think we explicitly avoided doing this since it would change the security context of sidecar containers that may not support the more locked-down configuration
created_at: 2025-02-07T06:29:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -51,7 +51,10 @@ podDisruptionBudget:
   maxUnavailable: 1
 # -- SecurityContext for the pod.
 podSecurityContext:
+  runAsNonRoot: true
   fsGroup: 65532
+  seccompProfile:
path: charts/karpenter/values.yaml
user: login: jonathan-innis
body: Similar question about the seccompProfile
created_at: 2025-02-07T06:29:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -62,16 +62,29 @@ spec:
       containers:
         - name: {{ .Values.controller.containerName | default "controller" }}
           securityContext:
+            privileged: false
+            allowPrivilegeEscalation: false
+            readOnlyRootFilesystem: true
+            runAsNonRoot: true
             runAsUser: 65532
             runAsGroup: 65532
-            runAsNonRoot: true
-            seccompProfile:
-              type: RuntimeDefault
-            allowPrivilegeEscalation: false
             capabilities:
               drop:
                 - ALL
-            readOnlyRootFilesystem: true
+          {{- with .Values.controller.securityContext }}
+          {{- with .appArmorProfile }}
+            appArmorProfile:
+              {{- toYaml . | nindent 14}}
+          {{- end }}
+          {{- with .seLinuxOptions }}
+            seLinuxOptions:
+              {{- toYaml . | nindent 14}}
+          {{- end }}
+          {{- with .seccompProfile }}
path: charts/karpenter/templates/deployment.yaml
user: login: stevehipwell
body: Because you might want to use a more restrictive profile, I can't see a downside to this as it needs to be an actual profile and so you can't use it to turn this off.
created_at: 2025-02-07T14:10:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -51,7 +51,10 @@ podDisruptionBudget:
   maxUnavailable: 1
 # -- SecurityContext for the pod.
 podSecurityContext:
+  runAsNonRoot: true
path: charts/karpenter/values.yaml
user: login: stevehipwell
body: This sets the default which can then be overridden by the consumer. Karpenter would be a high value target and this makes it really clear when adding a sidecar that running as root impacts the whole pod and not just the container.
created_at: 2025-02-07T14:16:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -51,7 +51,10 @@ podDisruptionBudget:
   maxUnavailable: 1
 # -- SecurityContext for the pod.
 podSecurityContext:
+  runAsNonRoot: true
   fsGroup: 65532
+  seccompProfile:
path: charts/karpenter/values.yaml
user: login: stevehipwell
body: The same as above. In addition, by providing a default it makes the intent clear and supports policies that don't consider the implicit defaults.
created_at: 2025-02-07T14:18:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -51,7 +51,10 @@ podDisruptionBudget:
   maxUnavailable: 1
 # -- SecurityContext for the pod.
 podSecurityContext:
+  runAsNonRoot: true
path: charts/karpenter/values.yaml
user: login: jonathan-innis
body: We did this and then pulled it back because multiple people ran into issues with it -- I'm fine having a more open discussion on this in something like a working group but I'm against breaking users in this way after the number of issues that were opened when we first tried to make this change (see https://github.com/aws/karpenter-provider-aws/pull/4681)
created_at: 2025-02-14T01:23:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -51,7 +51,10 @@ podDisruptionBudget:
   maxUnavailable: 1
 # -- SecurityContext for the pod.
 podSecurityContext:
+  runAsNonRoot: true
   fsGroup: 65532
+  seccompProfile:
path: charts/karpenter/values.yaml
user: login: jonathan-innis
body: See comment above
created_at: 2025-02-14T01:23:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -51,7 +51,10 @@ podDisruptionBudget:
   maxUnavailable: 1
 # -- SecurityContext for the pod.
 podSecurityContext:
+  runAsNonRoot: true
path: charts/karpenter/values.yaml
user: login: jonathan-innis
body: I'm pretty weary of this, too since this is a breaking change to the chart post-v1 and I believe that folks will miss this during the upgrade process
created_at: 2025-02-14T01:27:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -51,7 +51,10 @@ podDisruptionBudget:
   maxUnavailable: 1
 # -- SecurityContext for the pod.
 podSecurityContext:
+  runAsNonRoot: true
path: charts/karpenter/values.yaml
user: login: stevehipwell
body: @jonathan-innis let's take this to a separate discussion, I'll change this to false for the PR.

That said I am very interested why it was reversed in the first place? It significantly increases the attack surface for all users, but off the top of my head I can't think of many valid uses for root sidecars? Furthermore anyone using sidecars as root should have the K8s contextual knowledge to be proactively checking the pod security spec of the targets.
created_at: 2025-02-14T10:15:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -121,7 +124,14 @@ controller:
   # - name: AWS_REGION
   #   value: eu-west-1
   envFrom: []
-  # -- Resources for the controller pod.
+  securityContext:
+    # -- AppArmor profile for the controller container.
+    appArmorProfile: {}
+    # -- SELinux options for the controller container.
+    seLinuxOptions: {}
+    # -- Seccomp profile for the controller container.
+    seccompProfile: {}
path: charts/karpenter/values.yaml
user: login: jonathan-innis
body: @stevehipwell Do we want to change the SecComp profile from what it was where it was set to RuntimeDefault?
created_at: 2025-04-09T22:34:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -121,7 +124,14 @@ controller:
   # - name: AWS_REGION
   #   value: eu-west-1
   envFrom: []
-  # -- Resources for the controller pod.
+  securityContext:
+    # -- AppArmor profile for the controller container.
+    appArmorProfile: {}
+    # -- SELinux options for the controller container.
+    seLinuxOptions: {}
+    # -- Seccomp profile for the controller container.
+    seccompProfile: {}
path: charts/karpenter/values.yaml
user: login: stevehipwell
body: This is will inherit the parent value which we are setting (line 57) [docs](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#securitycontext-v1-core).
created_at: 2025-04-10T15:51:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -121,7 +124,14 @@ controller:
   # - name: AWS_REGION
   #   value: eu-west-1
   envFrom: []
-  # -- Resources for the controller pod.
+  securityContext:
+    # -- AppArmor profile for the controller container.
+    appArmorProfile: {}
+    # -- SELinux options for the controller container.
+    seLinuxOptions: {}
+    # -- Seccomp profile for the controller container.
+    seccompProfile: {}
path: charts/karpenter/values.yaml
user: login: stevehipwell
body: That said I'm happy to add it back here.
created_at: 2025-04-10T15:52:25Z
author_association: CONTRIBUTOR

PR comments:
user: login: netlify[bot]
created_at: 2024-10-25T15:53:37Z
body: ### <span aria-hidden="true">✅</span> Deploy Preview for *karpenter-docs-prod* ready!


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | b24b786f0eff04e85f6cbbe3deaf3bcdcea0d11a |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/karpenter-docs-prod/deploys/6800d394d8940a0008b4cb5c |
|<span aria-hidden="true">😎</span> Deploy Preview | [https://deploy-preview-7279--karpenter-docs-prod.netlify.app](https://deploy-preview-7279--karpenter-docs-prod.netlify.app) |
|<span aria-hidden="true">📱</span> Preview on mobile | <details><summary> Toggle QR Code... </summary><br /><br />![QR Code](https://app.netlify.com/qr-code/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL2RlcGxveS1wcmV2aWV3LTcyNzktLWthcnBlbnRlci1kb2NzLXByb2QubmV0bGlmeS5hcHAifQ.cB0OBIPEEUS_MnuJOtp1vEH6nMApgf49JZcMbafonDo)<br /><br />_Use your smartphone camera to open QR code link._</details> |
---
<!-- [karpenter-docs-prod Preview](https://deploy-preview-7279--karpenter-docs-prod.netlify.app) -->
_To edit notification comments on pull requests, go to your [Netlify site configuration](https://app.netlify.com/sites/karpenter-docs-prod/configuration/notifications#deploy-webhooks)._
author_association: NONE
user: login: stevehipwell
created_at: 2024-10-25T15:54:04Z
body: CC @jonathan-innis
author_association: CONTRIBUTOR
user: login: stevehipwell
created_at: 2024-11-18T09:48:26Z
body: @tzneal could you take a look at this please?
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2024-12-02T12:06:33Z
body: This PR has been inactive for 14 days. StaleBot will close this stale PR after 14 more days of inactivity.
author_association: CONTRIBUTOR
user: login: stevehipwell
created_at: 2024-12-02T17:04:41Z
body: @jonathan-innis @tzneal could someone please take a look at this?
author_association: CONTRIBUTOR
user: login: stevehipwell
created_at: 2024-12-12T10:43:54Z
body: @jonathan-innis @tzneal could someone please take a look at this?
author_association: CONTRIBUTOR
user: login: saurav-agarwalla
created_at: 2024-12-13T17:09:48Z
body: I'll take a look at this.
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2024-12-28T12:04:59Z
body: This PR has been inactive for 14 days. StaleBot will close this stale PR after 14 more days of inactivity.
author_association: CONTRIBUTOR
user: login: stevehipwell
created_at: 2025-01-02T13:04:30Z
body: /not-stale
author_association: CONTRIBUTOR
user: login: stevehipwell
created_at: 2025-01-14T15:40:06Z
body: @saurav-agarwalla did you manage to take a look at this?
author_association: CONTRIBUTOR
user: login: saurav-agarwalla
created_at: 2025-01-14T21:40:16Z
body: @stevehipwell apologies for the delay, I started reviewing this but then got side-tracked with the holidays and other things. Planning to get back to it this week.
author_association: CONTRIBUTOR
user: login: coveralls
created_at: 2025-01-17T19:34:59Z
body: ## Pull Request Test Coverage Report for [Build 14513302984](https://coveralls.io/builds/73277146)


### Details

* **0** of **0**   changed or added relevant lines in **0** files are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage increased (+**0.02%**) to **66.444%**

---



|  Totals | [![Coverage Status](https://coveralls.io/builds/73277146/badge)](https://coveralls.io/builds/73277146) |
| :-- | --: |
| Change from base [Build 14504624666](https://coveralls.io/builds/73264570): |  0.02% |
| Covered Lines: | 6768 |
| Relevant Lines: | 10186 |

---
##### 💛  - [Coveralls](https://coveralls.io)

author_association: NONE
user: login: stevehipwell
created_at: 2025-01-23T12:00:08Z
body: @saurav-agarwalla I think there is some confusion over what a first party Helm chart should be. A first party Helm chart should be opinionated and follow both industry and project best practices. As it owns the constraints it doesn't need to open everything up for customization.

Karpenter's constraints are that it runs on Linux, as a non-root user, and doesn't need any additional OS permissions; therefore there is no valid reason to allow an end-user to lower this security posture.

CC @jonathan-innis @tzneal @bwagner5 
author_association: CONTRIBUTOR
user: login: jonathan-innis
created_at: 2025-02-07T06:30:17Z
body: Hey @stevehipwell  -- sorry that we've been slow on this -- I just took a look, most of the changes look reasonable -- just a few questions about potential breaking changes and why you need certain levels of customization
author_association: CONTRIBUTOR
user: login: stevehipwell
created_at: 2025-02-07T14:21:16Z
body: @jonathan-innis I've replied to your comments and rebased.
author_association: CONTRIBUTOR
user: login: stevehipwell
created_at: 2025-02-14T10:23:59Z
body: @jonathan-innis I've reverted the pod non-root default.
author_association: CONTRIBUTOR
user: login: stevehipwell
created_at: 2025-03-05T10:34:34Z
body: @jonathan-innis I've rebased this PR again and it'd be great to get it merged.
author_association: CONTRIBUTOR
user: login: stevehipwell
created_at: 2025-03-13T10:29:39Z
body: 👀 @jonathan-innis
author_association: CONTRIBUTOR
user: login: jonathan-innis
created_at: 2025-04-09T22:35:17Z
body: I think that's my last question -- everything else looks good to ship -- just if there is a strong reason from removing RuntimeDefault
author_association: CONTRIBUTOR
user: login: stevehipwell
created_at: 2025-04-17T10:11:14Z
body: @jonathan-innis could we get this merged before the release for v1.4.0?
author_association: CONTRIBUTOR
user: login: jonathan-innis
created_at: 2025-04-17T16:22:38Z
body: > could we get this merged before the release for v1.4.0

I think we're going to have to punt this into v1.5.0 at this point -- we've already staged out the changes for v1.4.0. I wouldn't expect us to have a huge lead time to the next minor version, though -- we've got a number of perf things that we'd like to get through and release soon-ish
author_association: CONTRIBUTOR