Enabling Kubernetes Encryption Providers

Encryption Providers support is a Kubernetes solution to implement data encryption at rest. When enabled, the cluster administrator can ensure that secrets and other sensitive Kubernetes resources are encrypted before they are stored in the etcd backend.

Kubernetes supports several providers. Additionally, it supports external Key Management Systems (KMS) through the KMS provider.

Encryption Providers are supported by Kubernetes since v1.13.

KubeOne Support

KubeOne provides managed support for Encryption Providers as of v1.3. The following operations are supported:

  • Enabling/disabling Encryption Providers
  • Rotating Encryption keys
  • Using custom Encryption Providers configuration

Enabling Encryption Providers

To enable Encryption Providers support, the following section is added to the KubeOne Cluster configuration manifest:

apiVersion: kubeone.k8c.io/v1beta2
kind: KubeOneCluster
name: k1-cluster
versions:
  kubernetes: '1.29.4'
features:
  # enable encryption providers
  encryptionProviders:
    enable: true

For managed configuration, KubeOne will enable the Encryption Providers flag for the Kubernetes API server and will pass a generated configuration file such as the following one:

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- providers:
  - aescbc:
      keys:
      - name: kubeone-xkau31
       secret: 6utsip/8CJ1GFQpM6iWq4oL2z2g8tJ5UkGbIgkSWAAc=
  - identity: {}
  resources:
  - secrets

By default, KubeOne will use the AESCBC provider and will generate a randomized key for it. Also, only secret resources are encrypted.

Once KubeOne has pushed the configuration file and updated the kube-apiserver flags as required, it will restart the kube-apiserver pods and ensure all secret resources are rewritten with encryption enabled.

To enable Encryption Providers support for existing cluster, you must run kubeone apply --force-upgrade to apply the feature.

Disabling Encryption Providers

To disable this feature, simply set the enable option to false and upgrade your cluster with the --force-upgrade flag:

apiVersion: kubeone.k8c.io/v1beta2
kind: KubeOneCluster
name: k1-cluster
versions:
  kubernetes: '1.29.4'
features:
  # enable encryption providers
  encryptionProviders:
    enable: false
kubeone apply --manifest kubeone.yaml --tfjson output.json --force-upgrade

KubeOne will remove the configuration file from the control plane nodes and update the kube-apiserver flags. Additionally, it will rewrite all secret resources again to ensure that they are written back in plain text.

Rotating Encryption keys

KubeOne also supports rotating encryption keys to allow having a rotation policy for secret keys. The new --rotate-encryption-key flag is added to the apply command for this.

kubeone apply --manifest kubeone.yaml --tfjson output.json --force-upgrade --rotate-encryption-key

Similar to how enable/disable work, to rotate they key, you need to use the --force-upgrade flag as well.

During rotation, KubeOne will apply several steps that involve restarting the kube-apiserver pods and rewriting the cluster secrets.

Custom Encryption Providers configuration

KubeOne allows advanced users to manage their own configuration as well, for advanced use cases such as specifying multiple resources to encrypt, using multiple key providers or using an external KMS.

However, unlink the managed configuration, for custom configuration files, KubeOne only push the configuration file the control plane nodes and manage the kube-apiserver flags. It will not handle the content of the configuration file. This means that managed key rotation is not supported with custom configuration.

When custom configuration is used, the user will be responsible for managing the configuration to apply the steps required for enable, disable and rotate processes.

To use custom configuration, you simply add them inline to your KubeOne cluster configuration manifest:

apiVersion: kubeone.k8c.io/v1beta2
kind: KubeOneCluster
name: k1-cluster
versions:
  kubernetes: '1.29.4'
features:
  encryptionProviders:
    enable: true
    customEncryptionConfiguration: |
      apiVersion: apiserver.config.k8s.io/v1
      kind: EncryptionConfiguration
      resources:
      - providers:
        - aescbc:
            keys:
            - name: custom-key
              secret: lsn9B5vaIePTsbH2cxxzB0EfbBIZkYplC1fwfiNksJo=
        - identity: {}
        resources:
        - secrets      

Using an external KMS Provider

It is possible to use KubeOne to configure your Kubernetes cluster to use an external Key Management System. This provides an additional layer of security since it doesn’t require storing the a plain text key on control plane nodes.

Kubernetes requires using a KMS plugin to be able to communicate with the external KMS providers. Most cloud providers have KMS plugin implementations to allow Kubernetes to use their KMS services. For example:

Kubernetes communicates with the KMS Encryption Provider through a unix socket. For this to work, the cluster administrator needs to deploy KMS plugin on all control plane nodes. The plugin can be deployed as binary, a standalone docker container, a static pod or as a Daemonset configured to run only the control plan nodes. KubeOne will detect the unix socket path from the custom configuration and add a bind-mount to the KubeAPI static pod to allow it to communicate to the KMS plugins.

An example of custom encryption providers configuration to enable AWS Encryption Provider would look like this:

apiVersion: kubeone.k8c.io/v1beta2
kind: KubeOneCluster
name: kms-test
versions:
  kubernetes: '1.29.4'
cloudProvider:
  aws: {}
features:
  encryptionProviders:
    enable: true
    customEncryptionConfiguration: |
      apiVersion: apiserver.config.k8s.io/v1
      kind: EncryptionConfiguration
      resources:
        - resources:
          - secrets
          providers:
          - identity: {}
          - kms:
              name: aws-encryption-provider
              endpoint: unix:///var/run/kmsplugin/socket.sock
              cachesize: 1000
              timeout: 3s      

A Note About Backups

It’s important to understand that the data will be encrypted during the etcd backup operation as well. This means that when restoring a backup, the cluster should be configured using the same encryption key that was used during the backup. If that’s not the case, the Kubernetes API server will not be able to access the encrypted data.