KMS 加密驱动使用封套加密模型来加密 etcd 中的数据。 数据使用数据加密秘钥(DEK)加密;每次加密都生成一个新的 DEK。 这些 DEK 经一个秘钥加密秘钥(KEK)加密后在一个远端的 KMS 中存储和管理。 KMS 驱动使用 gRPC 与一个特定的 KMS 插件通信。这个 KMS 插件作为一个 gRPC 服务器被部署在 Kubernetes 主服务器的同一个主机上,负责与远端 KMS 的通信。

    现在基本云厂商都提供KMS服务。这里以阿里云为例。

    (1)开通密钥管理服务
    image.png

    (2)创建密钥
    image.png
    (3)然后部署kms-plugin

    1. apiVersion: apps/v1
    2. kind: Deployment
    3. metadata:
    4. name: ack-kms-plugin
    5. namespace: kube-system
    6. spec:
    7. selector:
    8. matchLabels:
    9. name: ack-kms-plugin
    10. template:
    11. metadata:
    12. labels:
    13. name: ack-kms-plugin
    14. spec:
    15. affinity:
    16. nodeAffinity:
    17. preferredDuringSchedulingIgnoredDuringExecution:
    18. - preference: {}
    19. weight: 100
    20. requiredDuringSchedulingIgnoredDuringExecution:
    21. nodeSelectorTerms:
    22. - matchExpressions:
    23. - key: node
    24. operator: In
    25. values:
    26. - master
    27. restartPolicy: Always
    28. tolerations:
    29. - key: node-role.kubernetes.io/master
    30. effect: NoSchedule
    31. volumes:
    32. - name: kmssocket
    33. hostPath:
    34. path: /var/run/kmsplugin
    35. type: DirectoryOrCreate
    36. containers:
    37. - name: ack-kms-plugin
    38. image: registry.{{ .Region }}.aliyuncs.com/acs/ack-kms-plugin:v1.0.2
    39. imagePullPolicy: Always
    40. command:
    41. - ack-kms-plugin
    42. - --gloglevel=5
    43. - --key-id={{ .KeyId }}
    44. - --path-to-unix-socket=/var/run/kmsplugin/grpc.sock
    45. livenessProbe:
    46. exec:
    47. command:
    48. - ack-kms-plugin
    49. - health
    50. - --path-to-unix-socket=/var/run/kmsplugin/grpc.sock
    51. initialDelaySeconds: 30
    52. failureThreshold: 3
    53. timeoutSeconds: 5
    54. periodSeconds: 300
    55. env:
    56. - name: ACCESS_KEY_ID #not required if you want plugin help to pull the sts credentials
    57. value: {{ .AK }}
    58. - name: ACCESS_KEY_SECRET #not required if you want plugin help to pull the sts credentials
    59. value: {{ .AK_Secret }}
    60. - name: CREDENTIAL_INTERVAL #not required if you want plugin help to pull the sts credentials
    61. value: {{ .Credential_Interval }}
    62. volumeMounts:
    63. - name: kmssocket
    64. mountPath: /var/run/kmsplugin
    65. readOnly: false

    其中需要更改的地方:

    • {{ .Region }}:阿里巴巴云区域 ID, 如果您的群集部署在 ECS 上, 您可以通过curl http://100.100.100.200/latest/meta-data/region-id
    • {{ .KeyId }}:Kms 服务列表中用于秘密加密的阿里云 Kms 密钥 ID
    • {{ .AK }}:授权的角色ID
    • {{ .AK_Secret }}:授权的角色密钥
    • {{ .Credential_Interval }}:凭据轮询间隔

    (4)创建kms插件配置文件/etc/kubernetes/kmsplugin/encryptionconfig.yaml

    1. apiVersion: apiserver.config.k8s.io/v1
    2. kind: EncryptionConfiguration
    3. resources:
    4. - resources:
    5. - secrets
    6. providers:
    7. - kms:
    8. name: grpc-kms-provider
    9. endpoint: unix:///var/run/kmsplugin/grpc.sock
    10. cachesize: 1000
    11. timeout: 3s
    12. - identity: {}

    (5)修改kube-apiserver配置清单文件/etc/kubernetes/manifests/kube-apiserver.yaml
    在启动参数里加入:

    1. ......
    2. spec:
    3. containers:
    4. - command:
    5. - kube-apiserver
    6. - --encryption-provider-config=/etc/kubernetes/kmsplugin/encryptionconfig.yaml
    7. ......

    然后再配置挂载,如下:

    1. ...
    2. volumeMounts:
    3. - name: kms-sock
    4. mountPath: /var/run/kmsplugin
    5. - name: kms-config
    6. mountPath: /etc/kubernetes/kmsplugin
    7. ...
    8. volumes:
    9. - name: kms-sock
    10. hostPath:
    11. path: /var/run/kmsplugin
    12. - name: kms-config
    13. hostPath:
    14. path: /etc/kubernetes/kmsplugin

    (6)重启kube-apiserver
    (7)验证
    现在,群集应使用信封加密方案,使用阿里云 KMS 的给定密钥加密密钥 (KEK) 对 中的秘密进行加密
    1. 创建新机密

    1. $ kubectl create secret generic secret1 -n default --from-literal=mykey=mydata
    1. 使用 etcdtl,读取主节点中的 etcd中的机密
      ps: [.local-ip] 应替换为主节点 IP 之一。

      1. $ ETCDCTL_API=3 etcdctl --cacert=/etc/kubernetes/pki/etcd/ca.pem --cert=/etc/kubernetes/pki/etcd/etcd-client.pem --key=/etc/kubernetes/pki/etcd/etcd-client-key.pem --endpoints=https://{{.local-ip}}:2379 get /registry/secrets/default/secret1
    2. 验证存储的机密是否前缀,指示我们的 kms 提供商已加密生成的数据。k8s:enc:kms:v1:grpc-kms-provider
      4. 验证密钥是否已正确解密:

      1. $ kubectl get secrets secret1 -o yaml