---
title: Encrypting Confidential Data at Rest
reviewers:
- aramase
- enj
content_type: task
weight: 210
---
<!-- overview -->
All of the APIs in Kubernetes that let you write persistent API resource data support
at-rest encryption. For example, you can enable at-rest encryption for
{{< glossary_tooltip text="Secrets" term_id="secret" >}}.
This at-rest encryption is additional to any system-level encryption for the
etcd cluster or for the filesystem(s) on hosts where you are running the
kube-apiserver.
This page shows how to enable and configure encryption of API data at rest.
{{< note >}}
This task covers encryption for resource data stored using the
{{< glossary_tooltip text="Kubernetes API" term_id="kubernetes-api" >}}. For example, you can
encrypt Secret objects, including the key-value data they contain.
If you want to encrypt data in filesystems that are mounted into containers, you instead need
to either:
- use a storage integration that provides encrypted
{{< glossary_tooltip text="volumes" term_id="volume" >}}
- encrypt the data within your own application
{{< /note >}}
## {{% heading "prerequisites" %}}
* {{< include "task-tutorial-prereqs.md" >}}
* This task assumes that you are running the Kubernetes API server as a
{{< glossary_tooltip text="static pod" term_id="static-pod" >}} on each control
plane node.
* Your cluster's control plane **must** use etcd v3.x (major version 3, any minor version).
* To encrypt a custom resource, your cluster must be running Kubernetes v1.26 or newer.
* To use a wildcard to match resources, your cluster must be running Kubernetes v1.27 or newer.
{{< version-check >}}
<!-- steps -->
## Determine whether encryption at rest is already enabled {#determining-whether-encryption-at-rest-is-already-enabled}
By default, the API server stores plain-text representations of resources into etcd, with
no at-rest encryption.
The `kube-apiserver` process accepts an argument `--encryption-provider-config`
that specifies a path to a configuration file. The contents of that file, if you specify one,
control how Kubernetes API data is encrypted in etcd.
If you are running the kube-apiserver without the `--encryption-provider-config` command line
argument, you do not have encryption at rest enabled. If you are running the kube-apiserver
with the `--encryption-provider-config` command line argument, and the file that it references
specifies the `identity` provider as the first encryption provider in the list, then you
do not have at-rest encryption enabled
(**the default `identity` provider does not provide any confidentiality protection.**)
If you are running the kube-apiserver
with the `--encryption-provider-config` command line argument, and the file that it references
specifies a provider other than `identity` as the first encryption provider in the list, then
you already have at-rest encryption enabled. However, that check does not tell you whether
a previous migration to encrypted storage has succeeded. If you are not sure, see
[ensure all relevant data are encrypted](#ensure-all-secrets-are-encrypted).
## Understanding the encryption at rest configuration
<!-- note to localizers: the highlight is to make the initial comment obvious -->
<!-- you can use as many lines as makes sense for your target localization -->
{{< highlight yaml "linenos=false,hl_lines=2-5" >}}
---
#
# CAUTION: this is an example configuration.
# Do not use this for your own cluster!
#
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
- configmaps
- pandas.awesome.bears.example # a custom resource API
providers:
# This configuration does not provide data confidentiality. The first
# configured provider is specifying the "identity" mechanism, which
# stores resources as plain text.
#
- identity: {} # plain text, in other words NO encryption
- aesgcm:
keys:
- name: key1
secret: c2VjcmV0IGlzIHNlY3VyZQ==
- name: key2
secret: dGhpcyBpcyBwYXNzd29yZA==
- aescbc:
keys:
- name: key1
secret: c2VjcmV0IGlzIHNlY3VyZQ==
- name: key2
secret: dGhpcyBpcyBwYXNzd29yZA==
- secretbox:
keys:
- name: key1
secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=
- resources:
- events
providers:
- identity: {} # do not encrypt Events even though *.* is specified below
- resources:
- '*.apps' # wildcard match requires Kubernetes 1.27 or later
providers:
- aescbc:
keys:
- name: key2
secret: c2VjcmV0IGlzIHNlY3VyZSwgb3IgaXMgaXQ/Cg==
- resources:
- '*.*' # wildcard match requires Kubernetes 1.27 or later
providers:
- aescbc:
keys:
- name: key3
secret: c2VjcmV0IGlzIHNlY3VyZSwgSSB0aGluaw==
{{< /highlight >}}
Each `resources` array item is a separate config and contains a complete configuration. The
`resources.resources` field is an array of Kubernetes resource names (`resource` or `resource.group`)
that should be encrypted like Secrets, ConfigMaps, or other resources.
If custom resources are added to `EncryptionConfiguration` and the cluster version is 1.26 or newer,
any newly created custom resources mentioned in the `EncryptionConfiguration` will be encrypted.
Any custom resources that existed in etcd prior to that version and configuration will be unencrypted
until they are next written to storage. This is the same behavior as built-in resources.
See the [Ensure all secrets are encrypted](#ensure-all-secrets-are-encrypted) section.
The `providers` array is an ordered list of the possible encryption providers to use for the APIs that you listed.
Each provider supports multiple keys - the keys are tried in order for decryption, and if the provider
is the first provider, the first key is used for encryption.
Only one provider type may be specified per entry (`identity` or `aescbc` may be provided,
but not both in the same item).
The first provider in the list is used to encrypt resources written into the storage. When reading
resources from storage, each provider that matches the stored data attempts in order to decrypt the
data. If no provider can read the stored data due to a mismatch in format or secret key, an error
is returned which prevents clients from accessing that resource.
`EncryptionConfiguration` supports the use of wildcards to specify the resources that should be encrypted.
Use '`*.<group>`' to encrypt all resources within a group (for eg '`*.apps`' in above example) or '`*.*`'
to encrypt all resources. '`*.`' can be used to encrypt all resource in the core group. '`*.*`' will
encrypt all resources, even custom resources that are added after API server start.
{{< note >}} Use of wildcards that overlap within the same resource list or across multiple entries are not allowed
since part of the configuration would be ineffective. The `resources` list's processing order and precedence
are determined by the order it's listed in the configuration. {{< /note >}}
If you have a wildcard covering resources and want to opt out of at-rest encryption for a particular kind
of resource, you achieve that by adding a separate `resources` array item with the name of the resource that
you want to exempt, followed by a `providers` array item where you specify the `identity` provider. You add
this item to the list so that it appears earlier than the configuration where you do specify encryption
(a provider that is not `identity`).
For example, if '`*.*`' is enabled and you want to opt out of encryption for Events and ConfigMaps, add a
new **earlier** item to the `resources`, followed by the providers array item with `identity` as the
provider. The more specific entry must come before the wildcard entry.
The new item would look similar to:
```yaml
...
- resources:
- configmaps. # specifically from the core API group,
# because of trailing "."
- events
providers:
- identity: {}
# and then other entries in resources
```
Ensure that the exemption is listed _before_ the wildcard '`*.*`' item in the resources array
to give it precedence.
For more detailed information about the `EncryptionConfiguration` struct, please refer to the
[encryption configuration API](/docs/reference/config-api/apiserver-config.v1/).
{{< caution >}}
If any resource is not readable via the encryption configuration (because keys were changed),
and you cannot restore a working configuration, your only recourse is to delete that entry from
the underlying etcd directly.
Any calls to the Kubernetes API that attempt to read that resource will fail until it is deleted
or a valid decryption key is provided.
{{< /caution >}}
### Available providers {#providers}
Before you configure encryption-at-rest for data in your cluster's Kubernetes API, you
need to select which provider(s) you will use.
The following table describes each available provider.
<!-- localization note: if it makes sense to adapt this table to work for your localization,
please do that. Each sentence in the English original should have a direct equivalent in the adapted
layout, although this may not always be possible -->
<table class="complex-layout">
<caption style="display: none;">Providers for Kubernetes encryption at rest</caption>
<thead>
<tr>
<th>Name</th>
<th>Encryption</th>
<th>Strength</th>
<th>Speed</th>
<th>Key length</th>
</tr>
</thead>
<tbody id="encryption-providers-identity">
<!-- list identity first, even when the remaining rows are sorted alphabetically -->
<tr>
<th rowspan="2" scope="row"><tt>identity</tt></th>
<td><strong>None</strong></td>
<td>N/A</td>
<td>N/A</td>
<td>N/A</td>
</tr>
<tr>
<td colspan="4">Resources written as-is without encryption. When set as the first provider, the resource will be decrypted as new values are written. Existing encrypted resources are <strong>not</strong> automatically overwritten with the plaintext data.
The <tt>identity</tt> provider is the default if you do not specify otherwise.</td>
</tr>
</tbody>
<tbody id="encryption-providers-that-encrypt">
<tr>
<th rowspan="2" scope="row"><tt>aescbc</tt></th>
<td>AES-CBC with <a href="https://datatracker.ietf.org/doc/html/rfc2315">PKCS#7</a> padding</td>
<td>Weak</td>
<td>Fast</td>
<td>16, 24, or 32-byte</td>
</tr>
<tr>
<td colspan="4">Not recommended due to CBC's vulnerability to padding oracle attacks. Key material accessible from control plane host.</td>
</tr>
<tr>
<th rowspan="2" scope="row"><tt>aesgcm</tt></th>
<td>AES-GCM with random nonce</td>
<td>Must be rotated every 200,000 writes</td>
<td>Fastest</td>
<td>16, 24, or 32-byte</td>
</tr>
<tr>
<td colspan="4">Not recommended for use except when an automated key rotation scheme is implemented. Key material accessible from control plane host.</td>
</tr>
<tr>
<th rowspan="2" scope="row"><tt>kms</tt> v1 <em>(deprecated since Kubernetes v1.28)</em></th>
<td>Uses envelope encryption scheme with DEK per resource.</td>
<td>Strongest</td>
<td>Slow (<em>compared to <tt>kms</tt> version 2</em>)</td>
<td>32-bytes</td>
</tr>
<tr>
<td colspan="4">
Data is encrypted by data encryption keys (DEKs) using AES-GCM;
DEKs are encrypted by key encryption keys (KEKs) according to
configuration in Key Management Service (KMS).
Simple key rotation, with a new DEK generated for each encryption, and
KEK rotation controlled by the user.
<br />
Read how to <a href="/docs/tasks/administer-cluster/kms-provider#configuring-the-kms-provider-kms-v1">configure the KMS V1 provider</a>.
</td>
</tr>
<tr>
<th rowspan="2" scope="row"><tt>kms</tt> v2 </th>
<td>Uses envelope encryption scheme with DEK per API server.</td>
<td>Strongest</td>
<td>Fast</td>
<td>32-bytes</td>
</tr>
<tr>
<td colspan="4">
Data is encrypted by data encryption keys (DEKs) using AES-GCM; DEKs
are encrypted by key encryption keys (KEKs) according to configuration
in Key Management Service (KMS).
Kubernetes generates a new DEK per encryption from a secret seed.
The seed is rotated whenever the KEK is rotated.<br/>
A good choice if using a third party tool for key management.
Available as stable from Kubernetes v1.29.
<br />
Read how to <a href="/docs/tasks/administer-cluster/kms-provider#configuring-the-kms-provider-kms-v2">configure the KMS V2 provider</a>.
</td>
</tr>
<tr>
<th rowspan="2" scope="row"><tt>secretbox</tt></th>
<td>XSalsa20 and Poly1305</td>
<td>Strong</td>
<td>Faster</td>
<td>32-byte</td>
</tr>
<tr>
<td colspan="4">Uses relatively new encryption technologies that may not be considered acceptable in environments that require high levels of review. Key material accessible from control plane host.</td>
</tr>
</tbody>
</table>
The `identity` provider is the default if you do not specify otherwise. **The `identity` provider does not
encrypt stored data and provides _no_ additional confidentiality protection.**
### Key storage
#### Local key storage
Encrypting secret data with a locally managed key protects against an etcd compromise, but it fails to
protect against a host compromise. Since the encryption keys are stored on the host in the
EncryptionConfiguration YAML file, a skilled attacker can access that file and extract the encryption
keys.
#### Managed (KMS) key storage {#kms-key-storage}
The KMS provider uses _envelope encryption_: Kubernetes encrypts resources using a data key, and then
encrypts that data key using the managed encryption service. Kubernetes generates a unique data key for
each resource. The API server stores an encrypted version of the data key in etcd alongside the ciphertext;
when reading the resource, the API server calls the managed encryption service and provides both the
ciphertext and the (encrypted) data key.
Within the managed encryption service, the provider use a _key encryption key_ to decipher the data key,
deciphers the data key, and finally recovers the plain text. Communication between the control plane
and the KMS requires in-transit protection, such as TLS.
Using envelope encryption creates dependence on the key encryption key, which is not stored in Kubernetes.
In the KMS case, an attacker who intends to get unauthorised access to the plaintext
values would need to compromise etcd **and** the third-party KMS provider.
### Protection for encryption keys
You should take appropriate measures to protect the confidential information that allows decryption,
whether that is a local encryption key, or an authentication token that allows the API server to
call KMS.
Even when you rely on a provider to manage the use and lifecycle of the main encryption key (or keys), you are still responsible
for making sure that access controls and other security measures for the managed encryption service are
appropriate for your security needs.
## Encrypt your data {#encrypting-your-data}
### Generate the encryption key {#generate-key-no-kms}
The following steps assume that you are not using KMS, and therefore the steps also
assume that you need to generate an encryption key. If you already have an encryption key,
skip to [Write an encryption configuration file](#write-an-encryption-configuration-file).
{{< caution >}}
Storing the raw encryption key in the EncryptionConfig only moderately improves your security posture,
compared to no encryption.
For additional secrecy, consider using the `kms` provider as this relies on keys held outside your
Kubernetes cluster. Implementations of `kms` can work with hardware security modules or with
encryption services managed by your cloud provider.
To learn about setting
up encryption at rest using KMS, see
[Using a KMS provider for data encryption](/docs/tasks/administer-cluster/kms-provider/).
The KMS provider plugin that you use may also come with additional specific documentation.
{{< /caution >}}
Start by generating a new encryption key, and then encode it using base64:
{{< tabs name="generate_encryption_key" >}}
{{% tab name="Linux" %}}
Generate a 32-byte random key and base64 encode it. You can use this command:
```shell
head -c 32 /dev/urandom | base64
```
You can use `/dev/hwrng` instead of `/dev/urandom` if you want to
use your PC's built-in hardware entropy source. Not all Linux
devices provide a hardware random generator.
{{% /tab %}}
{{% tab name="macOS" %}}
<!-- localization note: this is similar to the Linux tab and the wording
should match wherever the English text does -->
Generate a 32-byte random key and base64 encode it. You can use this command:
```shell
head -c 32 /dev/urandom | base64
```
{{% /tab %}}
{{% tab name="Windows" %}}
Generate a 32-byte random key and base64 encode it. You can use this command:
```powershell
# Do not run this in a session where you have set a random number
# generator seed.
[Convert]::ToBase64String((1..32|%{[byte](Get-Random -Max 256)}))
```
{{% /tab %}}
{{< /tabs >}}
{{< note >}}
Keep the encryption key confidential, including while you generate it and
ideally even after you are no longer actively using it.
{{< /note >}}
### Replicate the encryption key
Using a secure mechanism for file transfer, make a copy of that encryption key
available to every other control plane host.
At a minimum, use encryption in transit - for example, secure shell (SSH). For more
security, use asymmetric encryption between hosts, or change the approach you are using
so that you're relying on KMS encryption.
### Write an encryption configuration file
{{< caution >}}
The encryption configuration file may contain keys that can decrypt content in etcd.
If the configuration file contains any key material, you must properly
restrict permissions on all your control plane hosts so only the user
who runs the kube-apiserver can read this configuration.
{{< /caution >}}
Create a new encryption configuration file. The contents should be similar to:
```yaml
---
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
- configmaps
- pandas.awesome.bears.example
providers:
- aescbc:
keys:
- name: key1
# See the following text for more details about the secret value
secret: <BASE 64 ENCODED SECRET>
- identity: {} # this fallback allows reading unencrypted secrets;
# for example, during initial migration
```
To create a new encryption key (that does not use KMS), see
[Generate the encryption key](#generate-key-no-kms).
### Use the new encryption configuration file
You will need to mount the new encryption config file to the `kube-apiserver` static pod. Here is an example on how to do that:
1. Save the new encryption config file to `/etc/kubernetes/enc/enc.yaml` on the control-plane node.
1. Edit the manifest for the `kube-apiserver` static pod: `/etc/kubernetes/manifests/kube-apiserver.yaml` so that it is similar to:
```yaml
---
#
# This is a fragment of a manifest for a static Pod.
# Check whether this is correct for your cluster and for your API server.
#
apiVersion: v1
kind: Pod
metadata:
annotations:
kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 10.20.30.40:443
creationTimestamp: null
labels:
app.kubernetes.io/component: kube-apiserver
tier: control-plane
name: kube-apiserver
namespace: kube-system
spec:
containers:
- command:
- kube-apiserver
...
- --encryption-provider-config=/etc/kubernetes/enc/enc.yaml # add this line
volumeMounts:
...
- name: enc # add this line
mountPath: /etc/kubernetes/enc # add this line
readOnly: true # add this line
...
volumes:
...
- name: enc # add this line
hostPath: # add this line
path: /etc/kubernetes/enc # add this line
type: DirectoryOrCreate # add this line
...
```
1. Restart your API server.
{{< caution >}}
Your config file contains keys that can decrypt the contents in etcd, so you must properly restrict
permissions on your control-plane nodes so only the user who runs the `kube-apiserver` can read it.
{{< /caution >}}
You now have encryption in place for **one** control plane host. A typical
Kubernetes cluster has multiple control plane hosts, so there is more to do.
### Reconfigure other control plane hosts {#api-server-config-update-more}
If you have multiple API servers in your cluster, you should deploy the
changes in turn to each API server.
{{< caution >}}
For cluster configurations with two or more control plane nodes, the encryption configuration
should be identical across each control plane node.
If there is a difference in the encryption provider configuration between control plane
nodes, this difference may mean that the kube-apiserver can't decrypt data.
{{< /caution >}}
When you are planning to update the encryption configuration of your cluster, plan this
so that the API servers in your control plane can always decrypt the stored data
(even part way through rolling out the change).
Make sure that you use the **same** encryption configuration on each
control plane host.
### Verify that newly written data is encrypted {#verifying-that-data-is-encrypted}
Data is encrypted when written to etcd. After restarting your `kube-apiserver`, any newly
created or updated Secret (or other resource kinds configured in `EncryptionConfiguration`)
should be encrypted when stored.
To check this, you can use the `etcdctl` command line
program to retrieve the contents of your secret data.
This example shows how to check this for encrypting the Secret API.
1. Create a new Secret called `secret1` in the `default` namespace:
```shell
kubectl create secret generic secret1 -n default --from-literal=mykey=mydata
```
1. Using the `etcdctl` command line tool, read that Secret out of etcd:
```
ETCDCTL_API=3 etcdctl get /registry/secrets/default/secret1 [...] | hexdump -C
```
where `[...]` must be the additional arguments for connecting to the etcd server.
For example:
```shell
ETCDCTL_API=3 etcdctl \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
get /registry/secrets/default/secret1 | hexdump -C
```
The output is similar to this (abbreviated):
```hexdump
00000000 2f 72 65 67 69 73 74 72 79 2f 73 65 63 72 65 74 |/registry/secret|
00000010 73 2f 64 65 66 61 75 6c 74 2f 73 65 63 72 65 74 |s/default/secret|
00000020 31 0a 6b 38 73 3a 65 6e 63 3a 61 65 73 63 62 63 |1.k8s:enc:aescbc|
00000030 3a 76 31 3a 6b 65 79 31 3a c7 6c e7 d3 09 bc 06 |:v1:key1:.l.....|
00000040 25 51 91 e4 e0 6c e5 b1 4d 7a 8b 3d b9 c2 7c 6e |%Q...l..Mz.=..|n|
00000050 b4 79 df 05 28 ae 0d 8e 5f 35 13 2c c0 18 99 3e |.y..(..._5.,...>|
[...]
00000110 23 3a 0d fc 28 ca 48 2d 6b 2d 46 cc 72 0b 70 4c |#:..(.H-k-F.r.pL|
00000120 a5 fc 35 43 12 4e 60 ef bf 6f fe cf df 0b ad 1f |..5C.N`..o......|
00000130 82 c4 88 53 02 da 3e 66 ff 0a |...S..>f..|
0000013a
```
1. Verify the stored Secret is prefixed with `k8s:enc:aescbc:v1:` which indicates
the `aescbc` provider has encrypted the resulting data. Confirm that the key name shown in `etcd`
matches the key name specified in the `EncryptionConfiguration` mentioned above. In this example,
you can see that the encryption key named `key1` is used in `etcd` and in `EncryptionConfiguration`.
1. Verify the Secret is correctly decrypted when retrieved via the API:
```shell
kubectl get secret secret1 -n default -o yaml
```
The output should contain `mykey: bXlkYXRh`, with contents of `mydata` encoded using base64;
read
[decoding a Secret](/docs/tasks/configmap-secret/managing-secret-using-kubectl/#decoding-secret)
to learn how to completely decode the Secret.
### Ensure all relevant data are encrypted {#ensure-all-secrets-are-encrypted}
It's often not enough to make sure that new objects get encrypted: you also want that
encryption to apply to the objects that are already stored.
For this example, you have configured your cluster so that Secrets are encrypted on write.
Performing a replace operation for each Secret will encrypt that content at rest,
where the objects are unchanged.
You can make this change across all Secrets in your cluster:
```shell
# Run this as an administrator that can read and write all Secrets
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
```
The command above reads all Secrets and then updates them with the same data, in order to
apply server side encryption.
{{< note >}}
If an error occurs due to a conflicting write, retry the command.
It is safe to run that command more than once.
For larger clusters, you may wish to subdivide the Secrets by namespace,
or script an update.
{{< /note >}}
## Prevent plain text retrieval {#cleanup-all-secrets-encrypted}
If you want to make sure that the only access to a particular API kind is done using
encryption, you can remove the API server's ability to read that API's backing data
as plaintext.
{{< warning >}}
Making this change prevents the API server from retrieving resources that are marked
as encrypted at rest, but are actually stored in the clear.
When you have configured encryption at rest for an API (for example: the API kind
`Secret`, representing `secrets` resources in the core API group), you **must** ensure
that all those resources in this cluster really are encrypted at rest. Check this before
you carry on with the next steps.
{{< /warning >}}
Once all Secrets in your cluster are encrypted, you can remove the `identity`
part of the encryption configuration. For example:
{{< highlight yaml "linenos=false,hl_lines=12" >}}
---
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <BASE 64 ENCODED SECRET>
- identity: {} # REMOVE THIS LINE
{{< /highlight >}}
…and then restart each API server in turn. This change prevents the API server
from accessing a plain-text Secret, even by accident.
## Rotate a decryption key {#rotating-a-decryption-key}
Changing an encryption key for Kubernetes without incurring downtime requires a multi-step operation,
especially in the presence of a highly-available deployment where multiple `kube-apiserver` processes
are running.
1. Generate a new key and add it as the second key entry for the current provider on all
control plane nodes.
1. Restart **all** `kube-apiserver` processes, to ensure each server can decrypt
any data that are encrypted with the new key.
1. Make a secure backup of the new encryption key. If you lose all copies of this key you would
need to delete all the resources were encrypted under the lost key, and workloads may not
operate as expected during the time that at-rest encryption is broken.
1. Make the new key the first entry in the `keys` array so that it is used for encryption-at-rest
for new writes
1. Restart all `kube-apiserver` processes to ensure each control plane host now encrypts using the new key
1. As a privileged user, run `kubectl get secrets --all-namespaces -o json | kubectl replace -f -`
to encrypt all existing Secrets with the new key
1. After you have updated all existing Secrets to use the new key and have made a secure backup of the
new key, remove the old decryption key from the configuration.
## Decrypt all data {#decrypting-all-data}
This example shows how to stop encrypting the Secret API at rest. If you are encrypting
other API kinds, adjust the steps to match.
To disable encryption at rest, place the `identity` provider as the first
entry in your encryption configuration file:
```yaml
---
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
# list any other resources here that you previously were
# encrypting at rest
providers:
- identity: {} # add this line
- aescbc:
keys:
- name: key1
secret: <BASE 64 ENCODED SECRET> # keep this in place
# make sure it comes after "identity"
```
Then run the following command to force decryption of all Secrets:
```shell
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
```
Once you have replaced all existing encrypted resources with backing data that
don't use encryption, you can remove the encryption settings from the
`kube-apiserver`.
## Configure automatic reloading
You can configure automatic reloading of encryption provider configuration.
That setting determines whether the
{{< glossary_tooltip text="API server" term_id="kube-apiserver" >}} should
load the file you specify for `--encryption-provider-config` only once at
startup, or automatically whenever you change that file. Enabling this option
allows you to change the keys for encryption at rest without restarting the
API server.
To allow automatic reloading, configure the API server to run with:
`--encryption-provider-config-automatic-reload=true`.
When enabled, file changes are polled every minute to observe the modifications.
The `apiserver_encryption_config_controller_automatic_reload_last_timestamp_seconds`
metric identifies when the new config becomes effective. This allows
encryption keys to be rotated without restarting the API server.
## {{% heading "whatsnext" %}}
* Read about [decrypting data that are already stored at rest](/docs/tasks/administer-cluster/decrypt-data/)
* Learn more about the [EncryptionConfiguration configuration API (v1)](/docs/reference/config-api/apiserver-config.v1/).