KMS,Key Management Service,即密钥管理服务,在 K8S 集群中,以驱动和插件的形式启用对 Secret,Configmap 进行加密。以保护敏感数据,
驱动和插件需要使用者按照需求进行定制和实现自己的 KMS 插件,插件可以是 gRPC 服务器或者启用一个云服务商提供的 KMS 插件。
本文中演示使用的 KMS 服务是京东云舰中的 KMS 加密服务。
目前 KMS 分为 V1,V2,本文基于 V1 进行演示。
内部可以利用 kms 加密实现自己的加密算法,甚至国密算法。
当用户新建 secret 资源时,kube-apiserver 会通过 gRPC 调用 kms-plugin,而 kms-plugin 与加密服务器通信,进行数据加密。
此时如果通过直接获取 etcd 中的原始数据,内容为密文数据。
当用户获取 secret 资源内容时,kube-apiserver 会通过 gRPC 调用 kms-plugin,而 kms-plugin 与加密服务器通信,进行数据解密,将明文展示给用户
需要一套已经运行的 Kubernetes 集群服务,如果是多台 master 节点,需要同时配置。
/etc/kubernetes/kms/jdcloud
该配置是 kms 基本的加密配置,包括加密资源对象,socket 地址等等。
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets # 这里表示,只加密secret
providers:
- kms:
name: myKmsPlugin
endpoint: unix:///var/run/k8s-kms-plugin/kms-plugin.sock # 如果不以pod(jdcloud-kms-plugin.yaml)启动,需要sock文件放到master节点。
cachesize: 100
timeout: 3s
- identity: {}
以上内容保存在/etc/kubernetes/kms/jdcloud/apiserver-encryption.conf
新建 jdcloud kms plugin 配置
kms server 的上联信息配置
{
"AccessKey": "xxx", # 部署前,该参数需要预先知道,
"SecretKey": "yyy", # 部署前,该参数需要预先知道。
"KmsEndpoint": "kms.internal.cn-north-1.jdcloud-api.com", # 部署前,该参数需要预先知道。
"KmsKeyId": "abcd", # 部署前,该参数需要预先知道。
"KmsSchema": "http",
"GRPCSocketPath": "/var/run/k8s-kms-plugin/kms-plugin.sock"
}
以上内容保存在/etc/kubernetes/kms/jdcloud/jdcloud-kms-plugin.json
该服务是启动 socket 服务,并按照配置和上联的 kms server 进行通信,加密和解密数据,并通过 socket 服务和 K8S APIServer 交互。
该 pod 需要在 kube-apiserver 启动之前启动,否则与 apiserver 可能产生循环依赖。
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
component: jdcloud-kms-plugin
tier: control-plane
name: jdcloud-kms-plugin-node-01
namespace: kube-system
spec:
containers:
- command:
- /k8s-kms-plugin
- -f=/etc/kubernetes/kms/jdcloud/jdcloud-kms-plugin.json # 指定json
image: hub-pub.jdcloud.com/k8s/jdcloudsec/k8s-kms-plugin:v1.0.1
imagePullPolicy: IfNotPresent
name: jdcloud-kms-plugin
resources:
requests:
cpu: 250m
volumeMounts:
- mountPath: /etc/kubernetes/kms/jdcloud/jdcloud-kms-plugin.json # 注意路径
name: jdcloud-kms-plugin-configfile
readOnly: true
- mountPath: /var/run/k8s-kms-plugin/
name: k8s-kms-plugin-unixsock-directory
readOnly: false
hostNetwork: true
priorityClassName: system-cluster-critical
volumes:
- hostPath:
path: /etc/kubernetes/kms/jdcloud/jdcloud-kms-plugin.json # 注意路径
type: File
name: jdcloud-kms-plugin-configfile
- hostPath:
path: /var/run/k8s-kms-plugin/
type: DirectoryOrCreate
name: k8s-kms-plugin-unixsock-directory
status: {}
以上内容保存在/etc/kubernetes/manifests/jdcloud-kms-plugin.yaml
...
- --encryption-provider-config=/etc/kubernetes/kms/jdcloud/apiserver-encryption.conf
image: hub-pub.jdcloud.com/k8s/kube-apiserver:v1.19.9-109
imagePullPolicy: IfNotPresent
livenessProbe:
...
- mountPath: /etc/kubernetes/kms/jdcloud/apiserver-encryption.conf
name: apiserver-encryption-conf
readOnly: true
- mountPath: /var/run/k8s-kms-plugin/
name: k8s-kms-plugin-unixsock-directory
readOnly: false
...
- hostPath:
path: /etc/kubernetes/kms/jdcloud/apiserver-encryption.conf
type: File
name: apiserver-encryption-conf
- hostPath:
path: /var/run/k8s-kms-plugin/
type: DirectoryOrCreate
name: k8s-kms-plugin-unixsock-directory
修改后保存
kubectl create secret generic secret1 -n default --from-literal=mykey=mydata
etcdctl.sh get /kubernetes.io/secrets/default/secret1 [...] | hexdump -C
结果为加密数据
kubectl describe secret secret1 -n default
该结果为明文,mykey: mydata
在 K8S 集群中,京东内部一直比较重视对敏感数据加密,特别是云舰面对越来越多的金融行业客户,加密服务基本是云舰中的标准配置。
经过产品能力打磨和内部实现,KMS 加密服务和 K8S 自动化集群以及一键配置创建都在云舰内实现了很好的产品化能力,可以随集群创建,一键启用 KMS 加密服务。
作者:京东科技 王晓飞
来源:京东云开发者社区 转载请注明来源