From d6ca677caf7b8e5ac8eefa96f5d48a8dd7af1122 Mon Sep 17 00:00:00 2001 From: Alvaro Neira Ayuso Date: Thu, 7 Nov 2024 12:28:11 +0100 Subject: [PATCH 1/5] Configure max retries Signed-off-by: Alvaro Neira Ayuso --- cmd/controller/main.go | 2 + helm/sealed-secrets/README.md | 141 +++++++++--------- helm/sealed-secrets/templates/deployment.yaml | 4 + helm/sealed-secrets/values.yaml | 3 + pkg/controller/controller.go | 8 +- pkg/controller/main.go | 3 +- 6 files changed, 87 insertions(+), 74 deletions(-) diff --git a/cmd/controller/main.go b/cmd/controller/main.go index 9da88ba72c..7ce7ddc42a 100644 --- a/cmd/controller/main.go +++ b/cmd/controller/main.go @@ -58,6 +58,8 @@ func bindControllerFlags(f *controller.Flags, fs *flag.FlagSet) { fs.DurationVar(&f.KeyRenewPeriod, "rotate-period", defaultKeyRenewPeriod, "") _ = fs.MarkDeprecated("rotate-period", "please use key-renew-period instead") + + fs.IntVar(&f.MaxRetries, "max-retries", 5, "Max retries.") } func bindFlags(f *controller.Flags, fs *flag.FlagSet, gofs *goflag.FlagSet) { diff --git a/helm/sealed-secrets/README.md b/helm/sealed-secrets/README.md index b273715ca6..6ba930fd1a 100644 --- a/helm/sealed-secrets/README.md +++ b/helm/sealed-secrets/README.md @@ -82,76 +82,77 @@ The command removes all the Kubernetes components associated with the chart and ### Sealed Secrets Parameters -| Name | Description | Value | -| ------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ----------------------------------- | -| `image.registry` | Sealed Secrets image registry | `docker.io` | -| `image.repository` | Sealed Secrets image repository | `bitnami/sealed-secrets-controller` | -| `image.tag` | Sealed Secrets image tag (immutable tags are recommended) | `0.27.2` | -| `image.pullPolicy` | Sealed Secrets image pull policy | `IfNotPresent` | -| `image.pullSecrets` | Sealed Secrets image pull secrets | `[]` | -| `revisionHistoryLimit` | Number of old history to retain to allow rollback (If not set, default Kubernetes value is set to 10) | `""` | -| `createController` | Specifies whether the Sealed Secrets controller should be created | `true` | -| `secretName` | The name of an existing TLS secret containing the key used to encrypt secrets | `sealed-secrets-key` | -| `updateStatus` | Specifies whether the Sealed Secrets controller should update the status subresource | `true` | -| `skipRecreate` | Specifies whether the Sealed Secrets controller should skip recreating removed secrets | `false` | -| `keyrenewperiod` | Specifies key renewal period. Default 30 days | `""` | -| `keyttl` | Specifies generated certificate validity duration. Default 10 years | `""` | -| `keycutofftime` | Specifies a date at which the controller must generate a new key. Useful in early renewal scenarios. | `""` | -| `rateLimit` | Number of allowed sustained request per second for verify endpoint | `""` | -| `rateLimitBurst` | Number of requests allowed to exceed the rate limit per second for verify endpoint | `""` | -| `additionalNamespaces` | List of namespaces used to manage the Sealed Secrets | `[]` | -| `privateKeyAnnotations` | Map of annotations to be set on the sealing keypairs | `{}` | -| `privateKeyLabels` | Map of labels to be set on the sealing keypairs | `{}` | -| `logInfoStdout` | Specifies whether the Sealed Secrets controller will log info to stdout | `false` | -| `logLevel` | Specifies log level of controller (INFO,ERROR) | `""` | -| `logFormat` | Specifies log format (text,json) | `""` | -| `command` | Override default container command | `[]` | -| `args` | Override default container args | `[]` | -| `livenessProbe.enabled` | Enable livenessProbe on Sealed Secret containers | `true` | -| `livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `0` | -| `livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | -| `livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `1` | -| `livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `3` | -| `livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | -| `readinessProbe.enabled` | Enable readinessProbe on Sealed Secret containers | `true` | -| `readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `0` | -| `readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | -| `readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | -| `readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `3` | -| `readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | -| `startupProbe.enabled` | Enable startupProbe on Sealed Secret containers | `false` | -| `startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `0` | -| `startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | -| `startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `1` | -| `startupProbe.failureThreshold` | Failure threshold for startupProbe | `3` | -| `startupProbe.successThreshold` | Success threshold for startupProbe | `1` | -| `customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | -| `customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | -| `customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | -| `resources.limits` | The resources limits for the Sealed Secret containers | `{}` | -| `resources.requests` | The requested resources for the Sealed Secret containers | `{}` | -| `podSecurityContext.enabled` | Enabled Sealed Secret pods' Security Context | `true` | -| `podSecurityContext.fsGroup` | Set Sealed Secret pod's Security Context fsGroup | `65534` | -| `containerSecurityContext.enabled` | Enabled Sealed Secret containers' Security Context | `true` | -| `containerSecurityContext.readOnlyRootFilesystem` | Whether the Sealed Secret container has a read-only root filesystem | `true` | -| `containerSecurityContext.runAsNonRoot` | Indicates that the Sealed Secret container must run as a non-root user | `true` | -| `containerSecurityContext.runAsUser` | Set Sealed Secret containers' Security Context runAsUser | `1001` | -| `containerSecurityContext.capabilities` | Adds and removes POSIX capabilities from running containers (see `values.yaml`) | | -| `podLabels` | Extra labels for Sealed Secret pods | `{}` | -| `podAnnotations` | Annotations for Sealed Secret pods | `{}` | -| `priorityClassName` | Sealed Secret pods' priorityClassName | `""` | -| `runtimeClassName` | Sealed Secret pods' runtimeClassName | `""` | -| `affinity` | Affinity for Sealed Secret pods assignment | `{}` | -| `nodeSelector` | Node labels for Sealed Secret pods assignment | `{}` | -| `tolerations` | Tolerations for Sealed Secret pods assignment | `[]` | -| `additionalVolumes` | Extra Volumes for the Sealed Secrets Controller Deployment | `{}` | -| `additionalVolumeMounts` | Extra volumeMounts for the Sealed Secrets Controller container | `{}` | -| `hostNetwork` | Sealed Secrets pods' hostNetwork | `false` | -| `containerPorts.http` | Controller HTTP Port on the Host and Container | `8080` | -| `containerPorts.metrics` | Metrics HTTP Port on the Host and Container | `8081` | -| `hostPorts.http` | Controller HTTP Port on the Host | `""` | -| `hostPorts.metrics` | Metrics HTTP Port on the Host | `""` | -| `dnsPolicy` | Sealed Secrets pods' dnsPolicy | `""` | +| Name | Description | Value | +| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ----------------------------------- | +| `image.registry` | Sealed Secrets image registry | `docker.io` | +| `image.repository` | Sealed Secrets image repository | `bitnami/sealed-secrets-controller` | +| `image.tag` | Sealed Secrets image tag (immutable tags are recommended) | `0.27.2` | +| `image.pullPolicy` | Sealed Secrets image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Sealed Secrets image pull secrets | `[]` | +| `revisionHistoryLimit` | Number of old history to retain to allow rollback (If not set, default Kubernetes value is set to 10) | `""` | +| `createController` | Specifies whether the Sealed Secrets controller should be created | `true` | +| `secretName` | The name of an existing TLS secret containing the key used to encrypt secrets | `sealed-secrets-key` | +| `updateStatus` | Specifies whether the Sealed Secrets controller should update the status subresource | `true` | +| `skipRecreate` | Specifies whether the Sealed Secrets controller should skip recreating removed secrets | `false` | +| `keyrenewperiod` | Specifies key renewal period. Default 30 days | `""` | +| `keyttl` | Specifies the certificate validity duration. Default 10 years. | `""` | +| `keycutofftime` | Specifies a date at which the controller should generate a new certificate. Useful in early key renewal scenarios. | `""` | +| `rateLimit` | Number of allowed sustained request per second for verify endpoint | `""` | +| `rateLimitBurst` | Number of requests allowed to exceed the rate limit per second for verify endpoint | `""` | +| `additionalNamespaces` | List of namespaces used to manage the Sealed Secrets | `[]` | +| `privateKeyAnnotations` | Map of annotations to be set on the sealing keypairs | `{}` | +| `privateKeyLabels` | Map of labels to be set on the sealing keypairs | `{}` | +| `logInfoStdout` | Specifies whether the Sealed Secrets controller will log info to stdout | `false` | +| `logLevel` | Specifies log level of controller (INFO,ERROR) | `""` | +| `logFormat` | Specifies log format (text,json) | `""` | +| `maxRetries` | Number of maximum retries | `""` | +| `command` | Override default container command | `[]` | +| `args` | Override default container args | `[]` | +| `livenessProbe.enabled` | Enable livenessProbe on Sealed Secret containers | `true` | +| `livenessProbe.initialDelaySeconds` | Initial delay seconds for livenessProbe | `0` | +| `livenessProbe.periodSeconds` | Period seconds for livenessProbe | `10` | +| `livenessProbe.timeoutSeconds` | Timeout seconds for livenessProbe | `1` | +| `livenessProbe.failureThreshold` | Failure threshold for livenessProbe | `3` | +| `livenessProbe.successThreshold` | Success threshold for livenessProbe | `1` | +| `readinessProbe.enabled` | Enable readinessProbe on Sealed Secret containers | `true` | +| `readinessProbe.initialDelaySeconds` | Initial delay seconds for readinessProbe | `0` | +| `readinessProbe.periodSeconds` | Period seconds for readinessProbe | `10` | +| `readinessProbe.timeoutSeconds` | Timeout seconds for readinessProbe | `1` | +| `readinessProbe.failureThreshold` | Failure threshold for readinessProbe | `3` | +| `readinessProbe.successThreshold` | Success threshold for readinessProbe | `1` | +| `startupProbe.enabled` | Enable startupProbe on Sealed Secret containers | `false` | +| `startupProbe.initialDelaySeconds` | Initial delay seconds for startupProbe | `0` | +| `startupProbe.periodSeconds` | Period seconds for startupProbe | `10` | +| `startupProbe.timeoutSeconds` | Timeout seconds for startupProbe | `1` | +| `startupProbe.failureThreshold` | Failure threshold for startupProbe | `3` | +| `startupProbe.successThreshold` | Success threshold for startupProbe | `1` | +| `customLivenessProbe` | Custom livenessProbe that overrides the default one | `{}` | +| `customReadinessProbe` | Custom readinessProbe that overrides the default one | `{}` | +| `customStartupProbe` | Custom startupProbe that overrides the default one | `{}` | +| `resources.limits` | The resources limits for the Sealed Secret containers | `{}` | +| `resources.requests` | The requested resources for the Sealed Secret containers | `{}` | +| `podSecurityContext.enabled` | Enabled Sealed Secret pods' Security Context | `true` | +| `podSecurityContext.fsGroup` | Set Sealed Secret pod's Security Context fsGroup | `65534` | +| `containerSecurityContext.enabled` | Enabled Sealed Secret containers' Security Context | `true` | +| `containerSecurityContext.readOnlyRootFilesystem` | Whether the Sealed Secret container has a read-only root filesystem | `true` | +| `containerSecurityContext.runAsNonRoot` | Indicates that the Sealed Secret container must run as a non-root user | `true` | +| `containerSecurityContext.runAsUser` | Set Sealed Secret containers' Security Context runAsUser | `1001` | +| `containerSecurityContext.capabilities` | Adds and removes POSIX capabilities from running containers (see `values.yaml`) | | +| `podLabels` | Extra labels for Sealed Secret pods | `{}` | +| `podAnnotations` | Annotations for Sealed Secret pods | `{}` | +| `priorityClassName` | Sealed Secret pods' priorityClassName | `""` | +| `runtimeClassName` | Sealed Secret pods' runtimeClassName | `""` | +| `affinity` | Affinity for Sealed Secret pods assignment | `{}` | +| `nodeSelector` | Node labels for Sealed Secret pods assignment | `{}` | +| `tolerations` | Tolerations for Sealed Secret pods assignment | `[]` | +| `additionalVolumes` | Extra Volumes for the Sealed Secrets Controller Deployment | `{}` | +| `additionalVolumeMounts` | Extra volumeMounts for the Sealed Secrets Controller container | `{}` | +| `hostNetwork` | Sealed Secrets pods' hostNetwork | `false` | +| `containerPorts.http` | Controller HTTP Port on the Host and Container | `8080` | +| `containerPorts.metrics` | Metrics HTTP Port on the Host and Container | `8081` | +| `hostPorts.http` | Controller HTTP Port on the Host | `""` | +| `hostPorts.metrics` | Metrics HTTP Port on the Host | `""` | +| `dnsPolicy` | Sealed Secrets pods' dnsPolicy | `""` | ### Traffic Exposure Parameters diff --git a/helm/sealed-secrets/templates/deployment.yaml b/helm/sealed-secrets/templates/deployment.yaml index c86e10ae54..49cc474a37 100644 --- a/helm/sealed-secrets/templates/deployment.yaml +++ b/helm/sealed-secrets/templates/deployment.yaml @@ -145,6 +145,10 @@ spec: - --listen-metrics-addr - {{ printf ":%s" (.Values.containerPorts.metrics | toString) }} {{- end }} + {{- if .Values.maxRetries }} + - --max-retries + - {{ .Values.maxRetries | quote }} + {{- end }} {{- end }} image: {{ printf "%s/%s:%s" .Values.image.registry .Values.image.repository .Values.image.tag }} imagePullPolicy: {{ .Values.image.pullPolicy }} diff --git a/helm/sealed-secrets/values.yaml b/helm/sealed-secrets/values.yaml index bde9c54300..2a2c9e45db 100644 --- a/helm/sealed-secrets/values.yaml +++ b/helm/sealed-secrets/values.yaml @@ -112,6 +112,9 @@ logLevel: "" ## @param logFormat Specifies log format (text,json) ## logFormat: "" +## @param maxRetries Number of maximum retries +## +maxRetries: "" ## @param command Override default container command ## command: [] diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index 7c42469b4f..8987ffadcc 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -38,8 +38,6 @@ import ( ) const ( - maxRetries = 5 - // SuccessUnsealed is used as part of the Event 'reason' when // a SealedSecret is unsealed successfully. SuccessUnsealed = "Unsealed" @@ -60,6 +58,8 @@ const ( var ( // ErrCast happens when a K8s any type cannot be casted to the expected type. ErrCast = errors.New("cast error") + + maxRetries = 5 ) // Controller implements the main sealed-secrets-controller loop. @@ -77,7 +77,7 @@ type Controller struct { } // NewController returns the main sealed-secrets controller loop. -func NewController(clientset kubernetes.Interface, ssclientset ssclientset.Interface, ssinformer ssinformer.SharedInformerFactory, sinformer informers.SharedInformerFactory, keyRegistry *KeyRegistry) (*Controller, error) { +func NewController(clientset kubernetes.Interface, ssclientset ssclientset.Interface, ssinformer ssinformer.SharedInformerFactory, sinformer informers.SharedInformerFactory, keyRegistry *KeyRegistry, maxRetriesConfig int) (*Controller, error) { queue := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) utilruntime.Must(ssscheme.AddToScheme(scheme.Scheme)) @@ -102,6 +102,8 @@ func NewController(clientset kubernetes.Interface, ssclientset ssclientset.Inter } } + maxRetries = maxRetriesConfig + return &Controller{ ssInformer: ssInformer, sInformer: sInformer, diff --git a/pkg/controller/main.go b/pkg/controller/main.go index 84b15f2bc7..dd2f934957 100644 --- a/pkg/controller/main.go +++ b/pkg/controller/main.go @@ -55,6 +55,7 @@ type Flags struct { LogFormat string PrivateKeyAnnotations string PrivateKeyLabels string + MaxRetries int } func initKeyPrefix(keyPrefix string) (string, error) { @@ -267,7 +268,7 @@ func Main(f *Flags, version string) error { func prepareController(clientset kubernetes.Interface, namespace string, tweakopts func(*metav1.ListOptions), f *Flags, ssclientset versioned.Interface, keyRegistry *KeyRegistry) (*Controller, error) { sinformer := initSecretInformerFactory(clientset, namespace, tweakopts, f.SkipRecreate) ssinformer := ssinformers.NewFilteredSharedInformerFactory(ssclientset, 0, namespace, tweakopts) - controller, err := NewController(clientset, ssclientset, ssinformer, sinformer, keyRegistry) + controller, err := NewController(clientset, ssclientset, ssinformer, sinformer, keyRegistry, f.MaxRetries) return controller, err } From e52e6a6fa119683abe593dfca1b5033c7c3f6519 Mon Sep 17 00:00:00 2001 From: Alvaro Neira Ayuso Date: Thu, 7 Nov 2024 13:30:36 +0100 Subject: [PATCH 2/5] Include readme section Signed-off-by: Alvaro Neira Ayuso --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 3e3b5dfd67..384053b63c 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ original Secret from the SealedSecret. - [How to use kubeseal if the controller is not running within the `kube-system` namespace?](#how-to-use-kubeseal-if-the-controller-is-not-running-within-the-kube-system-namespace) - [How to verify the images?](#how-to-verify-the-images) - [How to use one controller for a subset of namespaces](#How-to-use-one-controller-for-a-subset-of-namespaces) + - [Can I configure the controller retries](#can-i-configure-the-controller-retries) - [Community](#community) - [Related projects](#related-projects) @@ -826,6 +827,10 @@ cosign verify --key .github/workflows/cosign.pub docker.io/bitnami/sealed-secret If you want to use one controller for more than one namespace, but not all namespaces, you can provide additional namespaces using the command line flag `--additional-namespaces=,,<...>`. Make sure you provide appropriate roles and rolebindings in the target namespaces, so the controller can manage the secrets in there. +### Can I configure the Controller retries? + +The answer is yes, you can configure the number of retries in your controller using the flag `--max-retries`. This flag allows you to configure the number of maximum retries to unseal your Sealed Secrets. + ## Community - [#sealed-secrets on Kubernetes Slack](https://kubernetes.slack.com/messages/sealed-secrets) From 08438af35d88f979ec3b2b201cc97cc9e3e3862d Mon Sep 17 00:00:00 2001 From: Alvaro Neira Ayuso Date: Thu, 7 Nov 2024 13:58:09 +0100 Subject: [PATCH 3/5] Update README.md Co-authored-by: Alfredo Garcia Signed-off-by: Alvaro Neira Ayuso --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 384053b63c..a7e82ddbf5 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ original Secret from the SealedSecret. - [How to use kubeseal if the controller is not running within the `kube-system` namespace?](#how-to-use-kubeseal-if-the-controller-is-not-running-within-the-kube-system-namespace) - [How to verify the images?](#how-to-verify-the-images) - [How to use one controller for a subset of namespaces](#How-to-use-one-controller-for-a-subset-of-namespaces) - - [Can I configure the controller retries](#can-i-configure-the-controller-retries) + - [Can I configure the controller unseal retries](#can-i-configure-the-controller-unseal-retries) - [Community](#community) - [Related projects](#related-projects) From a9cfbd9e6a2e2c221f9a3f6b3fb9e20ee98f1e1b Mon Sep 17 00:00:00 2001 From: Alvaro Neira Ayuso Date: Thu, 7 Nov 2024 13:58:17 +0100 Subject: [PATCH 4/5] Update README.md Co-authored-by: Alfredo Garcia Signed-off-by: Alvaro Neira Ayuso --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a7e82ddbf5..2b129633dc 100644 --- a/README.md +++ b/README.md @@ -827,7 +827,7 @@ cosign verify --key .github/workflows/cosign.pub docker.io/bitnami/sealed-secret If you want to use one controller for more than one namespace, but not all namespaces, you can provide additional namespaces using the command line flag `--additional-namespaces=,,<...>`. Make sure you provide appropriate roles and rolebindings in the target namespaces, so the controller can manage the secrets in there. -### Can I configure the Controller retries? +### Can I configure the Controller unseal retries? The answer is yes, you can configure the number of retries in your controller using the flag `--max-retries`. This flag allows you to configure the number of maximum retries to unseal your Sealed Secrets. From ba7ccd00e962b0f59219f80eb8576f009302beb8 Mon Sep 17 00:00:00 2001 From: Alvaro Neira Ayuso Date: Thu, 7 Nov 2024 14:00:20 +0100 Subject: [PATCH 5/5] Apply changes requested Signed-off-by: Alvaro Neira Ayuso --- README.md | 2 +- cmd/controller/main.go | 2 +- helm/sealed-secrets/templates/deployment.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2b129633dc..9275281fff 100644 --- a/README.md +++ b/README.md @@ -829,7 +829,7 @@ If you want to use one controller for more than one namespace, but not all names ### Can I configure the Controller unseal retries? -The answer is yes, you can configure the number of retries in your controller using the flag `--max-retries`. This flag allows you to configure the number of maximum retries to unseal your Sealed Secrets. +The answer is yes, you can configure the number of retries in your controller using the flag `--max-unseal-retries`. This flag allows you to configure the number of maximum retries to unseal your Sealed Secrets. ## Community diff --git a/cmd/controller/main.go b/cmd/controller/main.go index 7ce7ddc42a..6790f57b01 100644 --- a/cmd/controller/main.go +++ b/cmd/controller/main.go @@ -59,7 +59,7 @@ func bindControllerFlags(f *controller.Flags, fs *flag.FlagSet) { fs.DurationVar(&f.KeyRenewPeriod, "rotate-period", defaultKeyRenewPeriod, "") _ = fs.MarkDeprecated("rotate-period", "please use key-renew-period instead") - fs.IntVar(&f.MaxRetries, "max-retries", 5, "Max retries.") + fs.IntVar(&f.MaxRetries, "max-unseal-retries", 5, "Max unseal retries.") } func bindFlags(f *controller.Flags, fs *flag.FlagSet, gofs *goflag.FlagSet) { diff --git a/helm/sealed-secrets/templates/deployment.yaml b/helm/sealed-secrets/templates/deployment.yaml index 49cc474a37..75e19395ba 100644 --- a/helm/sealed-secrets/templates/deployment.yaml +++ b/helm/sealed-secrets/templates/deployment.yaml @@ -146,7 +146,7 @@ spec: - {{ printf ":%s" (.Values.containerPorts.metrics | toString) }} {{- end }} {{- if .Values.maxRetries }} - - --max-retries + - --max-unseal-retries - {{ .Values.maxRetries | quote }} {{- end }} {{- end }}