From 5d739b59eab9b3a5d168efe5d28091e5e071798e Mon Sep 17 00:00:00 2001 From: Alex Shearn Date: Tue, 7 May 2024 14:18:12 +0100 Subject: [PATCH 1/4] Expose the deployment strategy values for the policy controller Prior to this change, the policy controller webhook was not able to have its deployment strategy modified. If you only deployed a single replica, it could not perform a rolling update due to the default `maxSurge: 25%` being rounded down to 0. This change exposes those values, so that the `maxSurge` can be updated and a single instance can be rolled. Fixes #748. Signed-off-by: Alex Shearn --- charts/policy-controller/README.md | 54 +++++++++++++++++++ .../templates/webhook/deployment_webhook.yaml | 7 +++ charts/policy-controller/values.yaml | 7 +++ 3 files changed, 68 insertions(+) diff --git a/charts/policy-controller/README.md b/charts/policy-controller/README.md index a603ed62..b4cb2ac3 100644 --- a/charts/policy-controller/README.md +++ b/charts/policy-controller/README.md @@ -12,6 +12,60 @@ The Helm chart for Policy Controller * +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| commonAnnotations | object | `{}` | | +| commonNodeSelector | object | `{}` | | +| commonTolerations | list | `[]` | | +| cosign.cosignPub | string | `""` | | +| cosign.webhookName | string | `"policy.sigstore.dev"` | | +| imagePullSecrets | list | `[]` | | +| installCRDs | bool | `true` | | +| leasescleanup.image.pullPolicy | string | `"IfNotPresent"` | | +| leasescleanup.image.repository | string | `"cgr.dev/chainguard/kubectl"` | | +| leasescleanup.image.version | string | `"latest-dev"` | | +| loglevel | string | `"info"` | | +| serviceMonitor.enabled | bool | `false` | | +| webhook.configData | object | `{}` | | +| webhook.customLabels | object | `{}` | | +| webhook.env | object | `{}` | | +| webhook.extraArgs | object | `{}` | | +| webhook.failurePolicy | string | `"Fail"` | | +| webhook.image.pullPolicy | string | `"IfNotPresent"` | | +| webhook.image.repository | string | `"ghcr.io/sigstore/policy-controller/policy-controller"` | | +| webhook.image.version | string | `"sha256:f291fce5b9c1a69ba54990eda7e0fe4114043b1afefb0f4ee3e6f84ec9ef1605"` | | +| webhook.name | string | `"webhook"` | | +| webhook.namespaceSelector.matchExpressions[0].key | string | `"policy.sigstore.dev/include"` | | +| webhook.namespaceSelector.matchExpressions[0].operator | string | `"In"` | | +| webhook.namespaceSelector.matchExpressions[0].values[0] | string | `"true"` | | +| webhook.podDisruptionBudget.enabled | bool | `true` | | +| webhook.podDisruptionBudget.minAvailable | int | `1` | | +| webhook.podSecurityContext.allowPrivilegeEscalation | bool | `false` | | +| webhook.podSecurityContext.capabilities.drop[0] | string | `"ALL"` | | +| webhook.podSecurityContext.enabled | bool | `true` | | +| webhook.podSecurityContext.readOnlyRootFilesystem | bool | `true` | | +| webhook.podSecurityContext.runAsUser | int | `1000` | | +| webhook.registryCaBundle | object | `{}` | | +| webhook.replicaCount | int | `1` | | +| webhook.resources.limits.cpu | string | `"200m"` | | +| webhook.resources.limits.memory | string | `"512Mi"` | | +| webhook.resources.requests.cpu | string | `"100m"` | | +| webhook.resources.requests.memory | string | `"128Mi"` | | +| webhook.securityContext.enabled | bool | `false` | | +| webhook.securityContext.runAsUser | int | `65532` | | +| webhook.service.annotations | object | `{}` | | +| webhook.service.port | int | `443` | | +| webhook.service.type | string | `"ClusterIP"` | | +| webhook.serviceAccount.annotations | object | `{}` | | +| webhook.serviceAccount.create | bool | `true` | | +| webhook.serviceAccount.name | string | `""` | | +| webhook.volumeMounts | list | `[]` | | +| webhook.volumes | list | `[]` | | +| webhook.webhookNames.defaulting | string | `"defaulting.clusterimagepolicy.sigstore.dev"` | | +| webhook.webhookNames.validating | string | `"validating.clusterimagepolicy.sigstore.dev"` | | + ### Deploy `policy-controller` Helm Chart Install `policy-controller` using Helm: diff --git a/charts/policy-controller/templates/webhook/deployment_webhook.yaml b/charts/policy-controller/templates/webhook/deployment_webhook.yaml index 0474b7c1..6d49bc6c 100644 --- a/charts/policy-controller/templates/webhook/deployment_webhook.yaml +++ b/charts/policy-controller/templates/webhook/deployment_webhook.yaml @@ -12,6 +12,13 @@ spec: matchLabels: {{- include "policy-controller.selectorLabels" . | nindent 6 }} control-plane: {{ template "policy-controller.fullname" . }}-webhook + +{{- if .Values.deployment.strategy }} + strategy: +{{ toYaml .Values.deployment.strategy | trim | indent 4 }} + {{ if eq .Values.deployment.strategy.type "Recreate" }}rollingUpdate: null{{ end }} +{{- end }} + template: metadata: {{- with .Values.webhook.podAnnotations }} diff --git a/charts/policy-controller/values.yaml b/charts/policy-controller/values.yaml index 6ee8023a..b510fe90 100644 --- a/charts/policy-controller/values.yaml +++ b/charts/policy-controller/values.yaml @@ -9,6 +9,13 @@ imagePullSecrets: [] loglevel: info +deployment: + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + maxSurge: 1 + webhook: customLabels: {} configData: {} From a5bd9a526914be3663a8631d90bbd4552968ade8 Mon Sep 17 00:00:00 2001 From: Alex Shearn Date: Thu, 10 Oct 2024 08:49:20 +0100 Subject: [PATCH 2/4] Update README with extra options Signed-off-by: Alex Shearn --- charts/policy-controller/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/charts/policy-controller/README.md b/charts/policy-controller/README.md index b4cb2ac3..0cb4e392 100644 --- a/charts/policy-controller/README.md +++ b/charts/policy-controller/README.md @@ -21,6 +21,9 @@ The Helm chart for Policy Controller | commonTolerations | list | `[]` | | | cosign.cosignPub | string | `""` | | | cosign.webhookName | string | `"policy.sigstore.dev"` | | +| deployment.strategy.rollingUpdate.maxSurge | int | `1` | | +| deployment.strategy.rollingUpdate.maxUnavailable | int | `1` | | +| deployment.strategy.type | string | `"RollingUpdate"` | | | imagePullSecrets | list | `[]` | | | installCRDs | bool | `true` | | | leasescleanup.image.pullPolicy | string | `"IfNotPresent"` | | From 8e8d223b4aef2d05778ae605f13be53b736b6931 Mon Sep 17 00:00:00 2001 From: Alex Shearn Date: Thu, 10 Oct 2024 08:49:32 +0100 Subject: [PATCH 3/4] Update values schema via helm-schema Signed-off-by: Alex Shearn --- charts/policy-controller/values.schema.json | 848 ++++++++++++++------ 1 file changed, 614 insertions(+), 234 deletions(-) diff --git a/charts/policy-controller/values.schema.json b/charts/policy-controller/values.schema.json index a6fc34ef..c3fc2bb0 100644 --- a/charts/policy-controller/values.schema.json +++ b/charts/policy-controller/values.schema.json @@ -1,255 +1,635 @@ { - "$schema": "http://json-schema.org/schema#", - "type": "object", - "properties": { - "commonAnnotations": { - "type": "object" - }, - "commonNodeSelector": { - "type": "object" - }, - "commonTolerations": { - "type": "array" - }, - "cosign": { - "type": "object", - "properties": { - "cosignPub": { - "type": "string" + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "commonAnnotations": { + "additionalProperties": false, + "description": "# This will set some annotations in config maps and secrets. Use case: Disable versioning to deploy helm chart using spinnaker", + "required": [], + "title": "commonAnnotations", + "type": "object" + }, + "commonNodeSelector": { + "additionalProperties": false, + "description": "# common node selector for all the pods", + "required": [], + "title": "commonNodeSelector", + "type": "object" + }, + "commonTolerations": { + "description": "# common tolerations for all the pods", + "items": { + "required": [] + }, + "required": [], + "title": "commonTolerations", + "type": "array" + }, + "cosign": { + "additionalProperties": false, + "properties": { + "cosignPub": { + "default": "", + "description": "add the values in base64 encoded", + "required": [], + "title": "cosignPub", + "type": "string" + }, + "webhookName": { + "default": "policy.sigstore.dev", + "required": [], + "title": "webhookName", + "type": "string" + } + }, + "required": [ + "cosignPub", + "webhookName" + ], + "title": "cosign", + "type": "object" + }, + "deployment": { + "additionalProperties": false, + "properties": { + "strategy": { + "additionalProperties": false, + "properties": { + "rollingUpdate": { + "additionalProperties": false, + "properties": { + "maxSurge": { + "default": 1, + "required": [], + "title": "maxSurge", + "type": "integer" }, - "webhookName": { - "type": "string" + "maxUnavailable": { + "default": 1, + "required": [], + "title": "maxUnavailable", + "type": "integer" } + }, + "required": [ + "maxUnavailable", + "maxSurge" + ], + "title": "rollingUpdate", + "type": "object" + }, + "type": { + "default": "RollingUpdate", + "required": [], + "title": "type", + "type": "string" } + }, + "required": [ + "type", + "rollingUpdate" + ], + "title": "strategy", + "type": "object" + } + }, + "required": [ + "strategy" + ], + "title": "deployment", + "type": "object" + }, + "global": { + "description": "Global values are values that can be accessed from any chart or subchart by exactly the same name.", + "required": [], + "title": "global", + "type": "object" + }, + "imagePullSecrets": { + "items": { + "required": [] + }, + "required": [], + "title": "imagePullSecrets", + "type": "array" + }, + "installCRDs": { + "default": true, + "required": [], + "title": "installCRDs", + "type": "boolean" + }, + "leasescleanup": { + "additionalProperties": false, + "properties": { + "image": { + "additionalProperties": false, + "properties": { + "pullPolicy": { + "default": "IfNotPresent", + "required": [], + "title": "pullPolicy", + "type": "string" + }, + "repository": { + "default": "cgr.dev/chainguard/kubectl", + "required": [], + "title": "repository", + "type": "string" + }, + "version": { + "default": "latest-dev", + "required": [], + "title": "version", + "type": "string" + } + }, + "required": [ + "repository", + "version", + "pullPolicy" + ], + "title": "image", + "type": "object" + } + }, + "required": [ + "image" + ], + "title": "leasescleanup", + "type": "object" + }, + "loglevel": { + "default": "info", + "required": [], + "title": "loglevel", + "type": "string" + }, + "serviceMonitor": { + "additionalProperties": false, + "description": "# serviceMonitor makes policy controller metrics discoverable to prometheus", + "properties": { + "enabled": { + "default": false, + "required": [], + "title": "enabled", + "type": "boolean" + } + }, + "required": [ + "enabled" + ], + "title": "serviceMonitor", + "type": "object" + }, + "webhook": { + "additionalProperties": false, + "properties": { + "configData": { + "additionalProperties": false, + "required": [], + "title": "configData", + "type": "object" }, - "imagePullSecrets": { - "type": "array" + "customLabels": { + "additionalProperties": false, + "required": [], + "title": "customLabels", + "type": "object" }, - "installCRDs": { - "type": "boolean" + "env": { + "additionalProperties": false, + "required": [], + "title": "env", + "type": "object" }, - "leasescleanup": { - "type": "object", - "properties": { - "image": { - "type": "object", - "properties": { - "pullPolicy": { - "type": "string" - }, - "repository": { - "type": "string" - }, - "version": { - "type": "string" - } - } - } - } + "extraArgs": { + "additionalProperties": false, + "required": [], + "title": "extraArgs", + "type": "object" }, - "loglevel": { - "type": "string" + "failurePolicy": { + "default": "Fail", + "required": [], + "title": "failurePolicy", + "type": "string" }, - "serviceMonitor": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean" - } + "image": { + "additionalProperties": false, + "properties": { + "pullPolicy": { + "default": "IfNotPresent", + "required": [], + "title": "pullPolicy", + "type": "string" + }, + "repository": { + "default": "ghcr.io/sigstore/policy-controller/policy-controller", + "required": [], + "title": "repository", + "type": "string" + }, + "version": { + "default": "sha256:f291fce5b9c1a69ba54990eda7e0fe4114043b1afefb0f4ee3e6f84ec9ef1605", + "description": "crane digest ghcr.io/sigstore/policy-controller/policy-controller:v0.8.2", + "required": [], + "title": "version", + "type": "string" } + }, + "required": [ + "repository", + "version", + "pullPolicy" + ], + "title": "image", + "type": "object" }, - "webhook": { - "type": "object", - "properties": { - "configData": { - "type": "object" - }, - "customLabels": { - "type": "object" - }, - "env": { - "type": "object" - }, - "extraArgs": { - "type": "object" - }, - "failurePolicy": { - "type": "string" - }, - "image": { - "type": "object", - "properties": { - "pullPolicy": { - "type": "string" - }, - "repository": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "name": { - "type": "string" - }, - "namespaceSelector": { - "type": "object", - "properties": { - "matchExpressions": { - "type": "array", - "items": { - "type": "object", - "properties": { - "key": { - "type": "string" - }, - "operator": { - "type": "string" - }, - "values": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - } - }, - "podAnnotations": { - "type": "object" - }, - "podDisruptionBudget": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean" - }, - "minAvailable": { - "type": "integer" - } - } - }, - "podSecurityContext": { - "type": "object", + "name": { + "default": "webhook", + "required": [], + "title": "name", + "type": "string" + }, + "namespaceSelector": { + "additionalProperties": false, + "properties": { + "matchExpressions": { + "items": { + "anyOf": [ + { + "additionalProperties": false, "properties": { - "allowPrivilegeEscalation": { - "type": "boolean" - }, - "capabilities": { - "type": "object", - "properties": { - "drop": { - "type": "array", - "items": { - "type": "string" - } - } + "key": { + "default": "policy.sigstore.dev/include", + "required": [], + "title": "key", + "type": "string" + }, + "operator": { + "default": "In", + "required": [], + "title": "operator", + "type": "string" + }, + "values": { + "items": { + "anyOf": [ + { + "required": [], + "type": "string" } + ], + "required": [] }, - "enabled": { - "type": "boolean" - }, - "readOnlyRootFilesystem": { - "type": "boolean" - }, - "runAsUser": { - "type": "integer" - } - } - }, - "registryCaBundle": { + "required": [], + "title": "values", + "type": "array" + } + }, + "required": [ + "key", + "operator", + "values" + ], "type": "object" + } + ], + "required": [] + }, + "required": [], + "title": "matchExpressions", + "type": "array" + } + }, + "required": [ + "matchExpressions" + ], + "title": "namespaceSelector", + "type": "object" + }, + "podAnnotations": { + "additionalProperties": false, + "required": [], + "title": "podAnnotations", + "type": "object" + }, + "podDisruptionBudget": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "required": [], + "title": "enabled", + "type": "boolean" + }, + "minAvailable": { + "default": 1, + "required": [], + "title": "minAvailable", + "type": "integer" + } + }, + "required": [ + "enabled", + "minAvailable" + ], + "title": "podDisruptionBudget", + "type": "object" + }, + "podSecurityContext": { + "additionalProperties": false, + "properties": { + "allowPrivilegeEscalation": { + "default": false, + "required": [], + "title": "allowPrivilegeEscalation", + "type": "boolean" + }, + "capabilities": { + "additionalProperties": false, + "properties": { + "drop": { + "items": { + "anyOf": [ + { + "required": [], + "type": "string" + } + ], + "required": [] + }, + "required": [], + "title": "drop", + "type": "array" + } + }, + "required": [ + "drop" + ], + "title": "capabilities", + "type": "object" + }, + "enabled": { + "default": true, + "required": [], + "title": "enabled", + "type": "boolean" + }, + "readOnlyRootFilesystem": { + "default": true, + "required": [], + "title": "readOnlyRootFilesystem", + "type": "boolean" + }, + "runAsUser": { + "default": 1000, + "required": [], + "title": "runAsUser", + "type": "integer" + } + }, + "required": [ + "enabled", + "allowPrivilegeEscalation", + "readOnlyRootFilesystem", + "runAsUser", + "capabilities" + ], + "title": "podSecurityContext", + "type": "object" + }, + "registryCaBundle": { + "additionalProperties": false, + "required": [], + "title": "registryCaBundle", + "type": "object" + }, + "replicaCount": { + "default": 1, + "required": [], + "title": "replicaCount", + "type": "integer" + }, + "resources": { + "additionalProperties": false, + "properties": { + "limits": { + "additionalProperties": false, + "properties": { + "cpu": { + "default": "200m", + "required": [], + "title": "cpu", + "type": "string" }, - "replicaCount": { - "type": "integer" - }, - "resources": { - "type": "object", - "properties": { - "limits": { - "type": "object", - "properties": { - "cpu": { - "type": "string" - }, - "memory": { - "type": "string" - } - } - }, - "requests": { - "type": "object", - "properties": { - "cpu": { - "type": "string" - }, - "memory": { - "type": "string" - } - } - } - } - }, - "securityContext": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean" - }, - "runAsUser": { - "type": "integer" - } - } - }, - "service": { - "type": "object", - "properties": { - "annotations": { - "type": "object" - }, - "port": { - "type": "integer" - }, - "type": { - "type": "string" - } - } - }, - "serviceAccount": { - "type": "object", - "properties": { - "annotations": { - "type": "object" - }, - "create": { - "type": "boolean" - }, - "name": { - "type": "string" - } - } - }, - "volumeMounts": { - "type": "array" - }, - "volumes": { - "type": "array" + "memory": { + "default": "512Mi", + "required": [], + "title": "memory", + "type": "string" + } + }, + "required": [ + "cpu", + "memory" + ], + "title": "limits", + "type": "object" + }, + "requests": { + "additionalProperties": false, + "properties": { + "cpu": { + "default": "100m", + "required": [], + "title": "cpu", + "type": "string" }, - "webhookNames": { - "type": "object", - "properties": { - "defaulting": { - "type": "string" - }, - "validating": { - "type": "string" - } - } + "memory": { + "default": "128Mi", + "required": [], + "title": "memory", + "type": "string" } + }, + "required": [ + "cpu", + "memory" + ], + "title": "requests", + "type": "object" + } + }, + "required": [ + "limits", + "requests" + ], + "title": "resources", + "type": "object" + }, + "securityContext": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": false, + "required": [], + "title": "enabled", + "type": "boolean" + }, + "runAsUser": { + "default": 65532, + "required": [], + "title": "runAsUser", + "type": "integer" + } + }, + "required": [ + "enabled", + "runAsUser" + ], + "title": "securityContext", + "type": "object" + }, + "service": { + "additionalProperties": false, + "properties": { + "annotations": { + "additionalProperties": false, + "required": [], + "title": "annotations", + "type": "object" + }, + "port": { + "default": 443, + "required": [], + "title": "port", + "type": "integer" + }, + "type": { + "default": "ClusterIP", + "required": [], + "title": "type", + "type": "string" + } + }, + "required": [ + "annotations", + "type", + "port" + ], + "title": "service", + "type": "object" + }, + "serviceAccount": { + "additionalProperties": false, + "properties": { + "annotations": { + "additionalProperties": false, + "required": [], + "title": "annotations", + "type": "object" + }, + "create": { + "default": true, + "required": [], + "title": "create", + "type": "boolean" + }, + "name": { + "default": "", + "required": [], + "title": "name", + "type": "string" + } + }, + "required": [ + "annotations", + "create", + "name" + ], + "title": "serviceAccount", + "type": "object" + }, + "volumeMounts": { + "items": { + "required": [] + }, + "required": [], + "title": "volumeMounts", + "type": "array" + }, + "volumes": { + "items": { + "required": [] + }, + "required": [], + "title": "volumes", + "type": "array" + }, + "webhookNames": { + "additionalProperties": false, + "properties": { + "defaulting": { + "default": "defaulting.clusterimagepolicy.sigstore.dev", + "required": [], + "title": "defaulting", + "type": "string" + }, + "validating": { + "default": "validating.clusterimagepolicy.sigstore.dev", + "required": [], + "title": "validating", + "type": "string" } + }, + "required": [ + "defaulting", + "validating" + ], + "title": "webhookNames", + "type": "object" } + }, + "required": [ + "customLabels", + "configData", + "replicaCount", + "name", + "image", + "env", + "extraArgs", + "resources", + "securityContext", + "failurePolicy", + "podAnnotations", + "podSecurityContext", + "podDisruptionBudget", + "serviceAccount", + "service", + "volumeMounts", + "volumes", + "namespaceSelector", + "registryCaBundle", + "webhookNames" + ], + "title": "webhook", + "type": "object" } -} + }, + "required": [ + "cosign", + "installCRDs", + "imagePullSecrets", + "loglevel", + "deployment", + "webhook", + "leasescleanup", + "commonNodeSelector", + "commonTolerations", + "commonAnnotations", + "serviceMonitor" + ], + "type": "object" +} \ No newline at end of file From d81c861d91200ca0893df490dcb01fec7de131cf Mon Sep 17 00:00:00 2001 From: Alex Shearn Date: Thu, 10 Oct 2024 08:53:40 +0100 Subject: [PATCH 4/4] Bump chart version Signed-off-by: Alex Shearn --- charts/policy-controller/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/policy-controller/Chart.yaml b/charts/policy-controller/Chart.yaml index 905f212e..5f095e2c 100644 --- a/charts/policy-controller/Chart.yaml +++ b/charts/policy-controller/Chart.yaml @@ -8,7 +8,7 @@ sources: type: application name: policy-controller -version: 0.7.0 +version: 0.8.0 appVersion: 0.8.2 maintainers: