Merge pull request #41185 from windsonsea/kmspr
[zh] sync /administer-cluster/kms-provider.mdpull/41194/head
commit
81688c61d3
|
|
@ -14,11 +14,15 @@ weight: 370
|
|||
<!-- overview -->
|
||||
|
||||
<!--
|
||||
This page shows how to configure a Key Management Service (KMS) provider and plugin to enable secret data encryption. Currently there are two KMS API versions. KMS v1 will continue to work while v2 develops in maturity. If you are not sure which KMS API version to pick, choose v1.
|
||||
This page shows how to configure a Key Management Service (KMS) provider and plugin to enable secret data encryption.
|
||||
Currently there are two KMS API versions. New integrations that only need to support Kubernetes v1.27+
|
||||
should use KMS v2 as it offers significantly better performance characteristics than v1
|
||||
(note the `Caution` sections below for specific cases when KMS v2 must not be used.)
|
||||
-->
|
||||
本页展示了如何配置密钥管理服务(Key Management Service,KMS)驱动和插件以启用 Secret 数据加密。
|
||||
目前有两个 KMS API 版本。KMS v1 将继续工作,而 KMS v2 将开发得逐渐成熟。
|
||||
如果你不确定要选用哪个 KMS API 版本,可选择 v1。
|
||||
目前有两个 KMS API 版本。如果是只需要支持 Kubernetes v1.27+ 的新场景,应使用 KMS v2,
|
||||
因为 KMS v2 相比 KMS v1 具有显著更佳的性能特征。
|
||||
(请注意,下文的“注意”部分说明了不得使用 KMS v2 的特殊场景。)
|
||||
|
||||
## {{% heading "prerequisites" %}}
|
||||
|
||||
|
|
@ -26,7 +30,7 @@ This page shows how to configure a Key Management Service (KMS) provider and plu
|
|||
|
||||
<!--
|
||||
The version of Kubernetes that you need depends on which KMS API version
|
||||
you have selected.
|
||||
you have selected.
|
||||
|
||||
- If you selected KMS API v1, any supported Kubernetes version will work fine.
|
||||
- If you selected KMS API v2, you should use Kubernetes v{{< skew currentVersion >}}
|
||||
|
|
@ -43,6 +47,8 @@ you have selected.
|
|||
|
||||
### KMS v1
|
||||
|
||||
{{< feature-state for_k8s_version="v1.12" state="beta" >}}
|
||||
|
||||
<!--
|
||||
* Kubernetes version 1.10.0 or later is required
|
||||
|
||||
|
|
@ -51,40 +57,80 @@ you have selected.
|
|||
* 需要 Kubernetes 1.10.0 或更高版本
|
||||
* 你的集群必须使用 etcd v3 或更高版本
|
||||
|
||||
{{< feature-state for_k8s_version="v1.12" state="beta" >}}
|
||||
|
||||
### KMS v2
|
||||
|
||||
<!--
|
||||
* Kubernetes version 1.25.0 or later is required
|
||||
{{< feature-state for_k8s_version="v1.27" state="beta" >}}
|
||||
|
||||
* Set kube-apiserver feature gate: `--feature-gates=KMSv2=true` to configure a KMS v2 provider
|
||||
<!--
|
||||
* For version 1.25 and 1.26, enabling the feature via kube-apiserver feature gate is required.
|
||||
Set `--feature-gates=KMSv2=true` to configure a KMS v2 provider.
|
||||
|
||||
* Your cluster must use etcd v3 or later
|
||||
-->
|
||||
* 需要 Kubernetes 1.25.0 或更高版本
|
||||
* 对于 Kubernetes 1.25 和 1.26 版本,需要通过 kube-apiserver 特性门控启用此特性。
|
||||
设置 `--feature-gates=KMSv2=true` 以配置 KMS v2 驱动。
|
||||
|
||||
* 设置 kube-apiserver 特性门控:`--feature-gates=KMSv2=true` 以配置 KMS v2 驱动
|
||||
* 你的集群必须使用 etcd v3 或更高版本。
|
||||
|
||||
* 你的集群必须使用 etcd v3 或更高版本
|
||||
|
||||
{{< feature-state for_k8s_version="v1.25" state="alpha" >}}
|
||||
{{< caution >}}
|
||||
<!--
|
||||
The KMS v2 API and implementation changed in incompatible ways in-between the alpha release in v1.25
|
||||
and the beta release in v1.27. Attempting to upgrade from old versions with the alpha feature
|
||||
enabled will result in data loss.
|
||||
-->
|
||||
KMS v2 API 和实现在 v1.25 的 Alpha 版本和 v1.27 的 Beta 版本之间以不兼容的方式进行了更改。
|
||||
如果尝试从启用了 Alpha 特性的旧版本进行升级将导致数据丢失。
|
||||
{{< /caution >}}
|
||||
|
||||
<!-- steps -->
|
||||
|
||||
<!--
|
||||
The KMS encryption provider uses an envelope encryption scheme to encrypt data in etcd.
|
||||
The data is encrypted using a data encryption key (DEK); a new DEK is generated for each encryption.
|
||||
The data is encrypted using a data encryption key (DEK).
|
||||
The DEKs are encrypted with a key encryption key (KEK) that is stored and managed in a remote KMS.
|
||||
The KMS provider uses gRPC to communicate with a specific KMS plugin.
|
||||
With KMS v1, a new DEK is generated for each encryption.
|
||||
With KMS v2, a new DEK is generated on server startup and when the KMS plugin informs the API server
|
||||
that a KEK rotation has occurred (see `Understanding key_id and Key Rotation` section below).
|
||||
The KMS provider uses gRPC to communicate with a specific KMS plugin over a UNIX domain socket.
|
||||
The KMS plugin, which is implemented as a gRPC server and deployed on the same host(s)
|
||||
as the Kubernetes control plane, is responsible for all communication with the remote KMS.
|
||||
-->
|
||||
KMS 加密驱动使用封套加密模型来加密 etcd 中的数据。
|
||||
数据使用数据加密密钥(DEK)加密;每次加密都生成一个新的 DEK。
|
||||
KMS 加密驱动使用封套加密模型来加密 etcd 中的数据。数据使用数据加密密钥(DEK)加密。
|
||||
这些 DEK 经一个密钥加密密钥(KEK)加密后在一个远端的 KMS 中存储和管理。
|
||||
KMS 驱动使用 gRPC 与一个特定的 KMS 插件通信。这个 KMS 插件作为一个 gRPC
|
||||
服务器被部署在 Kubernetes 控制平面的相同主机上,负责与远端 KMS 的通信。
|
||||
对于 KMS v1,每次加密将生成新的 DEK。对于 KMS v2,在服务器启动和 KMS 插件通知 API
|
||||
服务器已出现 KEK 轮换时生成新的 DEK。(参见以下“了解 key_id 和密钥轮换”章节)。
|
||||
KMS 驱动使用 gRPC 通过 UNIX 域套接字与一个特定的 KMS 插件通信。
|
||||
这个 KMS 插件作为一个 gRPC 服务器被部署在 Kubernetes 控制平面的相同主机上,负责与远端 KMS 的通信。
|
||||
|
||||
{{< caution >}}
|
||||
<!--
|
||||
If you are running virtual machine (VM) based nodes that leverage VM state store with this feature, you must not use KMS v2.
|
||||
|
||||
With KMS v2, the API server uses AES-GCM with a 12 byte nonce (8 byte atomic counter and 4 bytes random data) for encryption.
|
||||
The following issues could occur if the VM is saved and restored:
|
||||
-->
|
||||
如果你正在运行基于虚拟机 (VM) 的节点并利用此特性使用 VM 状态存储,则不得使用 KMS v2。
|
||||
|
||||
使用 KMS v2 时,API 服务器使用带有 12 字节随机数(8 字节原子计数器和 4 字节随机数据)
|
||||
的 AES-GCM 进行加密。如果保存并恢复 VM,则可能会出现以下问题:
|
||||
|
||||
<!--
|
||||
1. The counter value may be lost or corrupted if the VM is saved in an inconsistent state or restored improperly.
|
||||
This can lead to a situation where the same counter value is used twice, resulting in the same nonce being used
|
||||
for two different messages.
|
||||
2. If the VM is restored to a previous state, the counter value may be set back to its previous value,
|
||||
resulting in the same nonce being used again.
|
||||
-->
|
||||
1. 如果 VM 在不一致的状态下保存或恢复不当,则可能会丢失或损坏计数器值。
|
||||
这可能导致相同的计数器值被用了两次,从而造成两个不同的消息使用相同的随机数。
|
||||
2. 如果将 VM 还原到先前的状态,则计数器值可能会被设置回其先前的值,导致再次使用相同的随机数。
|
||||
|
||||
<!--
|
||||
Although both of these cases are partially mitigated by the 4 byte random nonce, this can compromise
|
||||
the security of the encryption.
|
||||
-->
|
||||
尽管这两种情况都通过 4 字节随机数进行了部分缓解,但这可能会损害加密的安全性。
|
||||
{{< /caution >}}
|
||||
|
||||
<!--
|
||||
## Configuring the KMS provider
|
||||
|
|
@ -100,6 +146,7 @@ To configure a KMS provider on the API server, include a provider of type `kms`
|
|||
### KMS v1 {#configuring-the-kms-provider-kms-v1}
|
||||
|
||||
<!--
|
||||
* `apiVersion`: API Version for KMS provider. Leave this value empty or set it to `v1`.
|
||||
* `name`: Display name of the KMS plugin. Cannot be changed once set.
|
||||
* `endpoint`: Listen address of the gRPC server (KMS plugin). The endpoint is a UNIX domain socket.
|
||||
* `cachesize`: Number of data encryption keys (DEKs) to be cached in the clear.
|
||||
|
|
@ -108,32 +155,35 @@ To configure a KMS provider on the API server, include a provider of type `kms`
|
|||
* `timeout`: How long should `kube-apiserver` wait for kms-plugin to respond before
|
||||
returning an error (default is 3 seconds).
|
||||
-->
|
||||
* `name`: KMS 插件的显示名称。一旦设置,就无法更改。
|
||||
* `endpoint`: gRPC 服务器(KMS 插件)的监听地址。该端点是一个 UNIX 域套接字。
|
||||
* `cachesize`: 以明文缓存的数据加密密钥(DEK)的数量。一旦被缓存,
|
||||
就可以直接使用 DEK 而无需另外调用 KMS;而未被缓存的 DEK 需要调用一次 KMS 才能解包。
|
||||
* `timeout`: 在返回一个错误之前,`kube-apiserver` 等待 kms-plugin 响应的时间(默认是 3 秒)。
|
||||
|
||||
### KMS v2 {#configuring-the-kms-provider-kms-v2}
|
||||
|
||||
<!--
|
||||
* `apiVersion`: API Version for KMS provider (Allowed values: v2, v1 or empty. Any other value will result in an error.) Must be set to v2 to use the KMS v2 APIs.
|
||||
* `name`: Display name of the KMS plugin. Cannot be changed once set.
|
||||
* `endpoint`: Listen address of the gRPC server (KMS plugin). The endpoint is a UNIX domain socket.
|
||||
* `cachesize`: Number of data encryption keys (DEKs) to be cached in the clear.
|
||||
When cached, DEKs can be used without another call to the KMS;
|
||||
whereas DEKs that are not cached require a call to the KMS to unwrap.
|
||||
* `timeout`: How long should `kube-apiserver` wait for kms-plugin to respond before
|
||||
returning an error (default is 3 seconds).
|
||||
-->
|
||||
* `apiVersion`:针对 KMS 驱动的 API 版本(允许的值:v2、v1 或空值。任何其他值都将产生一个错误。)
|
||||
必须设置为 v2 才能使用 KMS v2 API。
|
||||
* `apiVersion`:针对 KMS 驱动的 API 版本。此项留空或设为 `v1`。
|
||||
* `name`:KMS 插件的显示名称。一旦设置,就无法更改。
|
||||
* `endpoint`:gRPC 服务器(KMS 插件)的监听地址。该端点是一个 UNIX 域套接字。
|
||||
* `cachesize`:以明文缓存的数据加密密钥(DEK)的数量。一旦被缓存,
|
||||
就可以直接使用 DEK 而无需另外调用 KMS;而未被缓存的 DEK 需要调用一次 KMS 才能解包。
|
||||
* `timeout`:在返回一个错误之前,`kube-apiserver` 等待 kms-plugin 响应的时间(默认是 3 秒)。
|
||||
|
||||
### KMS v2 {#configuring-the-kms-provider-kms-v2}
|
||||
|
||||
<!--
|
||||
* `apiVersion`: API Version for KMS provider. Set this to `v2`.
|
||||
* `name`: Display name of the KMS plugin. Cannot be changed once set.
|
||||
* `endpoint`: Listen address of the gRPC server (KMS plugin). The endpoint is a UNIX domain socket.
|
||||
* `timeout`: How long should `kube-apiserver` wait for kms-plugin to respond before
|
||||
returning an error (default is 3 seconds).
|
||||
-->
|
||||
* `apiVersion`:针对 KMS 驱动的 API 版本。此项设为 `v2`。
|
||||
* `name`:KMS 插件的显示名称。一旦设置,就无法更改。
|
||||
* `endpoint`:gRPC 服务器(KMS 插件)的监听地址。该端点是一个 UNIX 域套接字。
|
||||
* `timeout`:在返回一个错误之前,`kube-apiserver` 等待 kms-plugin 响应的时间(默认是 3 秒)。
|
||||
|
||||
<!--
|
||||
KMS v2 does not support the `cachesize` property. All data encryption keys (DEKs) will be cached in
|
||||
the clear once the server has unwrapped them via a call to the KMS. Once cached, DEKs can be used
|
||||
to perform decryption indefinitely without making a call to the KMS.
|
||||
-->
|
||||
KMS v2 不支持 `cachesize` 属性。一旦服务器通过调用 KMS 解密了数据加密密钥 (DEK),
|
||||
所有的 DEK 将会以明文形式被缓存。一旦被缓存,DEK 可以无限期地用于解密操作,而无需再次调用 KMS。
|
||||
|
||||
<!--
|
||||
See [Understanding the encryption at rest configuration.](/docs/tasks/administer-cluster/encrypt-data)
|
||||
-->
|
||||
|
|
@ -192,19 +242,24 @@ you use a proto file to create a stub file that you can use to develop the gRPC
|
|||
#### KMS v2 {#developing-a-kms-plugin-gRPC-server-kms-v2}
|
||||
|
||||
<!--
|
||||
* Using Go: Use the functions and data structures in the stub file:
|
||||
[api.pb.go](https://github.com/kubernetes/kubernetes/blob/release-1.25/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v2alpha1/api.pb.go)
|
||||
to develop the gRPC server code
|
||||
* Using Go: A high level
|
||||
[library](https://github.com/kubernetes/kms/blob/release-{{< skew currentVersion >}}/pkg/service/interface.go)
|
||||
is provided to make the process easier. Low level implementations
|
||||
can use the functions and data structures in the stub file:
|
||||
[api.pb.go](https://github.com/kubernetes/kms/blob/release-{{< skew currentVersion >}}/apis/v2/api.pb.go)
|
||||
to develop the gRPC server code
|
||||
|
||||
* Using languages other than Go: Use the protoc compiler with the proto file:
|
||||
[api.proto](https://github.com/kubernetes/kubernetes/blob/release-1.25/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v2alpha1/api.proto)
|
||||
[api.proto](https://github.com/kubernetes/kms/blob/release-{{< skew currentVersion >}}/apis/v2/api.proto)
|
||||
to generate a stub file for the specific language
|
||||
-->
|
||||
* 使用 Go:使用存根文件 [api.pb.go](https://github.com/kubernetes/kubernetes/blob/release-1.25/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v2alpha1/api.pb.go)
|
||||
* 使用 Go:提供了一个高级[库](https://github.com/kubernetes/kms/blob/release-{{< skew currentVersion >}}/pkg/service/interface.go)简化这个过程。
|
||||
底层实现可以使用存根文件
|
||||
[api.pb.go](https://github.com/kubernetes/kms/blob/release-{{< skew currentVersion >}}/apis/v2/api.pb.go)
|
||||
中的函数和数据结构开发 gRPC 服务器代码。
|
||||
|
||||
* 使用 Go 以外的其他语言:用 protoc 编译器编译 proto 文件:
|
||||
[api.proto](https://github.com/kubernetes/kubernetes/blob/release-1.25/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v2alpha1/api.proto)
|
||||
[api.proto](https://github.com/kubernetes/kms/blob/release-{{< skew currentVersion >}}/apis/v2/api.proto)
|
||||
为指定语言生成存根文件。
|
||||
|
||||
<!--
|
||||
|
|
@ -226,7 +281,7 @@ Then use the functions and data structures in the stub file to develop the serve
|
|||
|
||||
* message version: `v1beta1`
|
||||
|
||||
All messages from KMS provider have the version field set to current version v1beta1.
|
||||
All messages from KMS provider have the version field set to `v1beta1`.
|
||||
-->
|
||||
* kms 插件版本:`v1beta1`
|
||||
|
||||
|
|
@ -234,17 +289,12 @@ Then use the functions and data structures in the stub file to develop the serve
|
|||
|
||||
* 消息版本:`v1beta1`
|
||||
|
||||
所有来自 KMS 驱动的消息都把 version 字段设置为当前版本 v1beta1
|
||||
所有来自 KMS 驱动的消息都把 version 字段设置为 `v1beta1`。
|
||||
|
||||
<!--
|
||||
* protocol: UNIX domain socket (`unix`)
|
||||
|
||||
The plugin is implemented as a gRPC server that listens at UNIX domain socket.
|
||||
The plugin deployment should create a file on the file system to run the gRPC unix domain socket connection.
|
||||
The API server (gRPC client) is configured with the KMS provider (gRPC server) unix domain socket endpoint in order to communicate with it.
|
||||
An abstract Linux socket may be used by starting the endpoint with `/@`, i.e. `unix:///@foo`.
|
||||
Care must be taken when using this type of socket as they do not have concept of ACL (unlike traditional file based sockets).
|
||||
However, they are subject to Linux networking namespace, so will only be accessible to containers within the same pod unless host networking is used.
|
||||
The plugin is implemented as a gRPC server that listens at UNIX domain socket. The plugin deployment should create a file on the file system to run the gRPC unix domain socket connection. The API server (gRPC client) is configured with the KMS provider (gRPC server) unix domain socket endpoint in order to communicate with it. An abstract Linux socket may be used by starting the endpoint with `/@`, i.e. `unix:///@foo`. Care must be taken when using this type of socket as they do not have concept of ACL (unlike traditional file based sockets). However, they are subject to Linux networking namespace, so will only be accessible to containers within the same pod unless host networking is used.
|
||||
-->
|
||||
* 协议:UNIX 域套接字 (`unix`)
|
||||
|
||||
|
|
@ -258,25 +308,148 @@ Then use the functions and data structures in the stub file to develop the serve
|
|||
##### KMS v2 {#developing-a-kms-plugin-gRPC-server-notes-kms-v2}
|
||||
|
||||
<!--
|
||||
* kms plugin version: `v2alpha1`
|
||||
* KMS plugin version: `v2beta1`
|
||||
|
||||
In response to procedure call Status, a compatible KMS plugin should return `v2alpha1` as `StatusResponse.Version`,
|
||||
"ok" as `StatusResponse.Healthz` and a keyID (KMS KEK ID) as `StatusResponse.KeyID`
|
||||
In response to procedure call `Status`, a compatible KMS plugin should return `v2beta1` as `StatusResponse.version`,
|
||||
"ok" as `StatusResponse.healthz` and a `key_id` (remote KMS KEK ID) as `StatusResponse.key_id`.
|
||||
-->
|
||||
* kms 插件版本:`v2alpha1`
|
||||
* KMS 插件版本:`v2beta1`
|
||||
|
||||
作为对过程调用 Status 的响应,兼容的 KMS 插件应把 `v2alpha1` 作为 `StatusResponse.Version` 版本、
|
||||
“ok” 作为 `StatusResponse.Healthz` 并且 keyID(KMS KEK ID)作为 `StatusResponse.KeyID` 返回。
|
||||
作为对过程调用 `Status` 的响应,兼容的 KMS 插件应把 `v2beta1` 作为 `StatusResponse.Version` 版本、
|
||||
“ok” 作为 `StatusResponse.healthz` 并且 `key_id`(远程 KMS KEK ID)作为 `StatusResponse.key_id` 返回。
|
||||
|
||||
<!--
|
||||
The API server polls the `Status` procedure call approximately every minute when everything is healthy,
|
||||
and every 10 seconds when the plugin is not healthy. Plugins must take care to optimize this call as it will be
|
||||
under constant load.
|
||||
-->
|
||||
当一切健康时,API 服务器大约每分钟轮询一次 `Status` 过程调用,
|
||||
而插件不健康时每 10 秒钟轮询一次。使用这些插件时要注意优化此调用,因为此调用将经受持续的负载。
|
||||
|
||||
<!--
|
||||
* Encryption
|
||||
|
||||
The `EncryptRequest` procedure call provides the plaintext and a UID for logging purposes. The response must include
|
||||
the ciphertext, the `key_id` for the KEK used, and, optionally, any metadata that the KMS plugin needs to aid in
|
||||
future `DecryptRequest` calls (via the `annotations` field). The plugin must guarantee that any distinct plaintext
|
||||
results in a distinct response `(ciphertext, key_id, annotations)`.
|
||||
-->
|
||||
* 加密
|
||||
|
||||
`EncryptRequest` 过程调用提供明文和一个 UID 以用于日志记录。
|
||||
响应必须包括密文、使用的 KEK 的 `key_id`,以及可选的任意元数据,这些元数据可以
|
||||
帮助 KMS 插件在未来的 `DecryptRequest` 调用中(通过 `annotations` 字段)进行解密。
|
||||
插件必须保证所有不同的明文都会产生不同的响应 `(ciphertext, key_id, annotations)`。
|
||||
|
||||
<!--
|
||||
If the plugin returns a non-empty `annotations` map, all map keys must be fully qualified domain names such as
|
||||
`example.com`. An example use case of `annotation` is `{"kms.example.io/remote-kms-auditid":"<audit ID used by the remote KMS>"}`
|
||||
|
||||
The API server does not perform the `EncryptRequest` procedure call at a high rate. Plugin implementations should
|
||||
still aim to keep each request's latency at under 100 milliseconds.
|
||||
-->
|
||||
如果插件返回一个非空的 `annotations` 映射,则所有映射键必须是完全限定域名,
|
||||
例如 `example.com`。`annotation` 的一个示例用例是
|
||||
`{"kms.example.io/remote-kms-auditid":"<远程 KMS 使用的审计 ID>"}`。
|
||||
|
||||
当 API 服务器运行正常时,并不会高频执行 `EncryptRequest` 过程调用。
|
||||
插件实现仍应力求使每个请求的延迟保持在 100 毫秒以下。
|
||||
|
||||
<!--
|
||||
* Decryption
|
||||
|
||||
The `DecryptRequest` procedure call provides the `(ciphertext, key_id, annotations)` from `EncryptRequest` and a UID
|
||||
for logging purposes. As expected, it is the inverse of the `EncryptRequest` call. Plugins must verify that the
|
||||
`key_id` is one that they understand - they must not attempt to decrypt data unless they are sure that it was
|
||||
encrypted by them at an earlier time.
|
||||
-->
|
||||
* 解密
|
||||
|
||||
`DecryptRequest` 过程调用提供 `EncryptRequest` 中的 `(ciphertext, key_id, annotations)`
|
||||
和一个 UID 以用于日志记录。正如预期的那样,它是 `EncryptRequest` 调用的反向操作。插件必须验证
|
||||
`key_id` 是否为其理解的密钥ID - 除非这些插件确定数据是之前自己加密的,否则不应尝试解密。
|
||||
|
||||
<!--
|
||||
The API server may perform thousands of `DecryptRequest` procedure calls on startup to fill its watch cache. Thus
|
||||
plugin implementations must perform these calls as quickly as possible, and should aim to keep each request's latency
|
||||
at under 10 milliseconds.
|
||||
-->
|
||||
在启动时,API 服务器可能会执行数千个 `DecryptRequest` 过程调用以填充其监视缓存。
|
||||
因此,插件实现必须尽快执行这些调用,并应力求使每个请求的延迟保持在 10 毫秒以下。
|
||||
|
||||
<!--
|
||||
* Understanding `key_id` and Key Rotation
|
||||
|
||||
The `key_id` is the public, non-secret name of the remote KMS KEK that is currently in use. It may be logged
|
||||
during regular operation of the API server, and thus must not contain any private data. Plugin implementations
|
||||
are encouraged to use a hash to avoid leaking any data. The KMS v2 metrics take care to hash this value before
|
||||
exposing it via the `/metrics` endpoint.
|
||||
-->
|
||||
* 理解 `key_id` 和密钥轮换
|
||||
|
||||
`key_id` 是目前使用的远程 KMS KEK 的公共、非机密名称。
|
||||
它可能会在 API 服务器的常规操作期间记录,因此不得包含任何私有数据。
|
||||
建议插件实现使用哈希来避免泄漏任何数据。
|
||||
KMS v2 指标负责在通过 `/metrics` 端点公开之前对此值进行哈希。
|
||||
|
||||
<!--
|
||||
The API server considers the `key_id` returned from the `Status` procedure call to be authoritative. Thus, a change
|
||||
to this value signals to the API server that the remote KEK has changed, and data encrypted with the old KEK should
|
||||
be marked stale when a no-op write is performed (as described below). If an `EncryptRequest` procedure call returns a
|
||||
`key_id` that is different from `Status`, the response is thrown away and the plugin is considered unhealthy. Thus
|
||||
implementations must guarantee that the `key_id` returned from `Status` will be the same as the one returned by
|
||||
`EncryptRequest`. Furthermore, plugins must ensure that the `key_id` is stable and does not flip-flop between values
|
||||
(i.e. during a remote KEK rotation).
|
||||
-->
|
||||
API 服务器认为从 `Status` 过程调用返回的 `key_id` 是权威性的。因此,此值的更改表示远程 KEK 已更改,
|
||||
并且使用旧 KEK 加密的数据应在执行无操作写入时标记为过期(如下所述)。如果 `EncryptRequest`
|
||||
过程调用返回与 `Status` 不同的 `key_id`,则响应将被丢弃,并且插件将被认为是不健康的。
|
||||
因此,插件实现必须保证从 `Status` 返回的 `key_id` 与 `EncryptRequest` 返回的 `key_id` 相同。
|
||||
此外,插件必须确保 `key_id` 是稳定的,并且不会在不同值之间翻转(即在远程 KEK 轮换期间)。
|
||||
|
||||
<!--
|
||||
Plugins must not re-use `key_id`s, even in situations where a previously used remote KEK has been reinstated. For
|
||||
example, if a plugin was using `key_id=A`, switched to `key_id=B`, and then went back to `key_id=A` - instead of
|
||||
reporting `key_id=A` the plugin should report some derivative value such as `key_id=A_001` or use a new value such
|
||||
as `key_id=C`.
|
||||
-->
|
||||
插件不能重新使用 `key_id`,即使在先前使用的远程 KEK 被恢复的情况下也是如此。
|
||||
例如,如果插件使用了 `key_id=A`,切换到 `key_id=B`,然后又回到 `key_id=A`,
|
||||
那么插件应报告 `key_id=A_001` 或使用一个新值,如 `key_id=C`。
|
||||
|
||||
<!--
|
||||
Since the API server polls `Status` about every minute, `key_id` rotation is not immediate. Furthermore, the API
|
||||
server will coast on the last valid state for about three minutes. Thus if a user wants to take a passive approach
|
||||
to storage migration (i.e. by waiting), they must schedule a migration to occur at `3 + N + M` minutes after the
|
||||
remote KEK has been rotated (`N` is how long it takes the plugin to observe the `key_id` change and `M` is the
|
||||
desired buffer to allow config changes to be processed - a minimum `M` of five minutes is recommend). Note that no
|
||||
API server restart is required to perform KEK rotation.
|
||||
-->
|
||||
由于 API 服务器大约每分钟轮询一次 `Status`,因此 `key_id` 轮换并不立即发生。
|
||||
此外,API 服务器在三分钟内以最近一个有效状态为准。因此,
|
||||
如果用户想采取被动方法进行存储迁移(即等待),则必须安排迁移在远程 KEK 轮换后的 `3 + N + M` 分钟内发生
|
||||
(其中 `N` 表示插件观察 `key_id` 更改所需的时间,`M` 是允许处理配置更改的缓冲区时间 - 建议至少使用 5 分钟)。
|
||||
请注意,执行 KEK 轮换不需要进行 API 服务器重启。
|
||||
|
||||
{{< caution >}}
|
||||
<!--
|
||||
Because you don't control the number of writes performed with the DEK, we recommend rotating the KEK at least every 90 days.
|
||||
-->
|
||||
因为你未控制使用 DEK 执行的写入次数,所以建议至少每 90 天轮换一次 KEK。
|
||||
{{< /caution >}}
|
||||
|
||||
<!--
|
||||
* protocol: UNIX domain socket (`unix`)
|
||||
|
||||
The plugin is implemented as a gRPC server that listens at UNIX domain socket.
|
||||
The plugin deployment should create a file on the file system to run the gRPC unix domain socket connection.
|
||||
The API server (gRPC client) is configured with the KMS provider (gRPC server) unix domain socket endpoint in order to communicate with it.
|
||||
An abstract Linux socket may be used by starting the endpoint with `/@`, i.e. `unix:///@foo`.
|
||||
Care must be taken when using this type of socket as they do not have concept of ACL (unlike traditional file based sockets).
|
||||
However, they are subject to Linux networking namespace, so will only be accessible to containers within the same pod unless host networking is used.
|
||||
The plugin is implemented as a gRPC server that listens at UNIX domain socket.
|
||||
The plugin deployment should create a file on the file system to run the gRPC unix domain socket connection.
|
||||
The API server (gRPC client) is configured with the KMS provider (gRPC server) unix
|
||||
domain socket endpoint in order to communicate with it.
|
||||
An abstract Linux socket may be used by starting the endpoint with `/@`, i.e. `unix:///@foo`.
|
||||
Care must be taken when using this type of socket as they do not have concept of ACL
|
||||
(unlike traditional file based sockets).
|
||||
However, they are subject to Linux networking namespace, so will only be accessible to
|
||||
containers within the same pod unless host networking is used.
|
||||
-->
|
||||
* 协议:UNIX 域套接字 (`unix`)
|
||||
|
||||
|
|
@ -291,18 +464,20 @@ Then use the functions and data structures in the stub file to develop the serve
|
|||
### Integrating a KMS plugin with the remote KMS
|
||||
|
||||
The KMS plugin can communicate with the remote KMS using any protocol supported by the KMS.
|
||||
All configuration data, including authentication credentials the KMS plugin uses to communicate with the remote KMS,
|
||||
All configuration data, including authentication credentials the KMS plugin uses to communicate with the remote KMS,
|
||||
are stored and managed by the KMS plugin independently.
|
||||
The KMS plugin can encode the ciphertext with additional metadata that may be required before sending it to the KMS for decryption.
|
||||
The KMS plugin can encode the ciphertext with additional metadata that may be required before sending it to the KMS
|
||||
for decryption (KMS v2 makes this process easier by providing a dedicated `annotations` field).
|
||||
-->
|
||||
### 将 KMS 插件与远程 KMS 整合 {#integrating-a-kms-plugin-with-the-remote-kms}
|
||||
|
||||
KMS 插件可以用任何受 KMS 支持的协议与远程 KMS 通信。
|
||||
所有的配置数据,包括 KMS 插件用于与远程 KMS 通信的认证凭据,都由 KMS 插件独立地存储和管理。
|
||||
KMS 插件可以用额外的元数据对密文进行编码,这些元数据是在把它发往 KMS 进行解密之前可能要用到的。
|
||||
KMS 插件可以用额外的元数据对密文进行编码,这些元数据是在把它发往 KMS 进行解密之前可能要用到的
|
||||
(KMS v2 提供了专用的 `annotations` 字段简化了这个过程)。
|
||||
|
||||
<!--
|
||||
### Deploying the KMS plugin
|
||||
### Deploying the KMS plugin
|
||||
|
||||
Ensure that the KMS plugin runs on the same host(s) as the Kubernetes master(s).
|
||||
-->
|
||||
|
|
@ -380,19 +555,18 @@ defined in a CustomResourceDefinition, your cluster must be running Kubernetes v
|
|||
apiVersion: v2
|
||||
name: myKmsPluginFoo
|
||||
endpoint: unix:///tmp/socketfile.sock
|
||||
cachesize: 100
|
||||
timeout: 3s
|
||||
- kms:
|
||||
apiVersion: v2
|
||||
name: myKmsPluginBar
|
||||
endpoint: unix:///tmp/socketfile.sock
|
||||
cachesize: 100
|
||||
timeout: 3s
|
||||
```
|
||||
|
||||
<!--
|
||||
Setting `--encryption-provider-config-automatic-reload` to `true` collapses all health checks to a single health check endpoint. Individual health checks are only available when KMS v1 providers are in use and the encryption config is not auto-reloaded.
|
||||
|
||||
Following table summarizes the health check endpoints for each KMS version:
|
||||
The following table summarizes the health check endpoints for each KMS version:
|
||||
-->
|
||||
`--encryption-provider-config-automatic-reload` 设置为 `true` 会将所有健康检查集中到同一个健康检查端点。
|
||||
只有 KMS v1 驱动正使用且加密配置未被自动重新加载时,才能进行独立的健康检查。
|
||||
|
|
@ -400,12 +574,12 @@ Following table summarizes the health check endpoints for each KMS version:
|
|||
下表总结了每个 KMS 版本的健康检查端点:
|
||||
|
||||
<!--
|
||||
| KMS configurations | Without Automatic Reload | With Automatic Reload |
|
||||
| ------------------------- |------------------------------------| -----------------------|
|
||||
| KMS v1 only | Individual Healthchecks | Single Healthcheck |
|
||||
| KMS v2 only | Single Healthcheck | Single Healthcheck |
|
||||
| Both KMS v1 and v2 | Individual Healthchecks | Single Healthcheck |
|
||||
| No KMS | None | Single Healthcheck |
|
||||
| KMS configurations | Without Automatic Reload | With Automatic Reload |
|
||||
| ------------------ | ------------------------ | --------------------- |
|
||||
| KMS v1 only | Individual Healthchecks | Single Healthcheck |
|
||||
| KMS v2 only | Single Healthcheck | Single Healthcheck |
|
||||
| Both KMS v1 and v2 | Individual Healthchecks | Single Healthcheck |
|
||||
| No KMS | None | Single Healthcheck |
|
||||
-->
|
||||
| KMS 配置 | 没有自动重新加载 | 有自动重新加载 |
|
||||
| ------------ | ----------------------- | ------------------ |
|
||||
|
|
@ -429,6 +603,16 @@ These healthcheck endpoint paths are hard coded and generated/controlled by the
|
|||
这些健康检查端点路径是由服务器硬编码、生成并控制的。
|
||||
`Individual Healthchecks` 的索引序号对应于 KMS 加密配置被处理的顺序。
|
||||
|
||||
<!--
|
||||
At a high level, restarting an API server when a KMS plugin is unhealthy is unlikely to make the situation better.
|
||||
It can make the situation significantly worse by throwing away the API server's DEK cache. Thus the general
|
||||
recommendation is to ignore the API server KMS healthz checks for liveness purposes, i.e. `/livez?exclude=kms-providers`.
|
||||
-->
|
||||
一般而言,在 KMS 插件出现故障时重新启动 API 服务器并不太可能改善情况。
|
||||
这样做会由于丢弃 API 服务器的 DEK 缓存使情况显著恶化。因此,
|
||||
一般建议忽略出于存活性探测的目的而对 API 服务器 KMS 的健康检查,
|
||||
即 `/livez?exclude=kms-providers`。
|
||||
|
||||
<!--
|
||||
Until the steps defined in [Ensuring all secrets are encrypted](#ensuring-all-secrets-are-encrypted) are performed,
|
||||
the `providers` list should end with the `identity: {}` provider to allow unencrypted data to be read.
|
||||
|
|
@ -448,13 +632,15 @@ For details about the `EncryptionConfiguration` format, please check the
|
|||
<!--
|
||||
## Verifying that the data is encrypted
|
||||
|
||||
Data is encrypted when written to etcd. After restarting your `kube-apiserver`,
|
||||
any newly created or updated Secret or other resource types configured in `EncryptionConfiguration` should be encrypted when stored. To verify,
|
||||
When encryption at rest is correctly configured, resources are encrypted on write.
|
||||
After restarting your `kube-apiserver`, any newly created or updated Secret or other resource types
|
||||
configured in `EncryptionConfiguration` should be encrypted when stored. To verify,
|
||||
you can use the `etcdctl` command line program to retrieve the contents of your secret data.
|
||||
-->
|
||||
## 验证数据已经加密 {#verifying-that-the-data-is-encrypted}
|
||||
|
||||
写入 etcd 时数据被加密。重启 `kube-apiserver` 后,所有新建或更新的 Secret 或在
|
||||
当静态加密被正确配置时,资源将在写入时被加密。
|
||||
重启 `kube-apiserver` 后,所有新建或更新的 Secret 或在
|
||||
`EncryptionConfiguration` 中配置的其他资源类型在存储时应该已被加密。
|
||||
要验证这点,你可以用 `etcdctl` 命令行程序获取私密数据的内容。
|
||||
|
||||
|
|
@ -505,11 +691,13 @@ which indicates that the `kms` provider has encrypted the resulting data.
|
|||
<!--
|
||||
## Ensuring all secrets are encrypted
|
||||
|
||||
Because secrets are encrypted on write, performing an update on a secret encrypts that content.
|
||||
When encryption at rest is correctly configured, resources are encrypted on write.
|
||||
Thus we can perform an in-place no-op update to ensure that data is encrypted.
|
||||
-->
|
||||
## 确保所有 Secret 都已被加密 {#ensuring-all-secrets-are-encrypted}
|
||||
|
||||
因为 Secret 是在写入时被加密的,所以在更新 Secret 时也会加密该内容。
|
||||
当静态加密被正确配置时,资源将在写入时被加密。
|
||||
这样我们可以执行就地零干预更新来确保数据被加密。
|
||||
|
||||
<!--
|
||||
The following command reads all secrets and then updates them to apply server side encryption.
|
||||
|
|
@ -545,9 +733,9 @@ To switch from a local encryption provider to the `kms` provider and re-encrypt
|
|||
- secrets
|
||||
providers:
|
||||
- kms:
|
||||
apiVersion: v2
|
||||
name : myKmsPlugin
|
||||
endpoint: unix:///tmp/socketfile.sock
|
||||
cachesize: 100
|
||||
- aescbc:
|
||||
keys:
|
||||
- name: key1
|
||||
|
|
@ -579,7 +767,7 @@ To disable encryption at rest:
|
|||
<!--
|
||||
1. Place the `identity` provider as the first entry in the configuration file:
|
||||
-->
|
||||
1. 将 `identity` 驱动作为配置文件中的第一个条目:
|
||||
1. 将 `identity` 驱动作为配置文件中的第一个条目:
|
||||
|
||||
```yaml
|
||||
apiVersion: apiserver.config.k8s.io/v1
|
||||
|
|
@ -590,9 +778,9 @@ To disable encryption at rest:
|
|||
providers:
|
||||
- identity: {}
|
||||
- kms:
|
||||
apiVersion: v2
|
||||
name : myKmsPlugin
|
||||
endpoint: unix:///tmp/socketfile.sock
|
||||
cachesize: 100
|
||||
```
|
||||
|
||||
<!--
|
||||
|
|
@ -607,4 +795,3 @@ To disable encryption at rest:
|
|||
```shell
|
||||
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
|
||||
```
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue