Skip to content

Upgrading from v4.x to v5.x

This release introduces a breaking change to the rawResources configuration structure.

The rawResources configuration has been restructured to use a manifest wrapper. This brings raw resources in line with standard Kubernetes manifests and improves how labels and annotations are handled.

rawResources:
validating-webhook:
enabled: true
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
name: my-webhook
labels:
app: my-app
annotations:
description: "My webhook"
spec:
rules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE"]
resources: ["pods"]
scope: "Namespaced"
rawResources:
validating-webhook:
enabled: true
manifest:
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
name: my-webhook
metadata:
labels:
app: my-app
annotations:
description: "My webhook"
rules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE"]
resources: ["pods"]
scope: "Namespaced"
  1. The entire Kubernetes manifest now goes inside a manifest key
  2. Labels and annotations must now be nested under metadata
  3. The spec key is no longer used — all manifest fields go directly at the manifest level

A dedicated ServiceAccount is now created by default when you deploy a controller without explicitly configuring a ServiceAccount. The ServiceAccount uses the Helm release name as its identifier. This improves security isolation by ensuring each application runs with its own unprivileged ServiceAccount rather than using the namespace’s default ServiceAccount.

When no ServiceAccount was configured, pods would use the namespace’s default ServiceAccount.

A dedicated ServiceAccount is automatically created using the Helm release name as the identifier. For example, a Helm release named myapp would create a ServiceAccount with identifier myapp. This ServiceAccount has no special privileges (unprivileged), which follows the principle of least privilege.

If you prefer to use the namespace default ServiceAccount, you can disable this behavior by setting:

global:
createDefaultServiceAccount: false
  1. Improved security — Each application gets its own ServiceAccount with minimal privileges
  2. Better auditability — API operations can be traced to specific applications
  3. Reduced blast radius — A compromise of one application doesn’t affect others using the default ServiceAccount

If you explicitly configure any ServiceAccounts in your values, the default ServiceAccount is not created. Your configured ServiceAccounts take precedence:

# Example: Custom ServiceAccount configuration
serviceAccount:
myCustomSA:
annotations:
example.com/purpose: "custom"

In this case, myCustomSA is used instead of the auto-generated default.

The automountServiceAccountToken option now defaults to false, improving security by preventing automatic mounting of the ServiceAccount token into pods.

By default, the ServiceAccount token was automatically mounted into pods.

The ServiceAccount token is not mounted by default. If your application requires access to the Kubernetes API, you must explicitly enable token mounting:

defaultPodOptions:
automountServiceAccountToken: true

ServiceMonitor and PodMonitor jobLabel default

Section titled “ServiceMonitor and PodMonitor jobLabel default”

The jobLabel field for ServiceMonitor and PodMonitor now defaults to app.kubernetes.io/name when not explicitly specified. This provides better compatibility with Prometheus scraping by aligning with standard Kubernetes app labels.

When no jobLabel was specified, the field was set to the value of metadata.name of the ServiceMonitor / PodMonitor object.

When no jobLabel is specified, it defaults to app.kubernetes.io/name.

The controller and podSelector fields for NetworkPolicy are now mutually exclusive. Use controller to target a specific controller’s pods, or use podSelector for custom pod selection that doesn’t follow the controller naming convention.

If you have exactly one controller defined and don’t specify a controller or podSelector, the NetworkPolicy will automatically target that controller. This simplifies configuration for simple single-controller setups.