开发者社区 > 博文 > K8S集群中使用JDOS KMS服务对敏感数据安全加密
分享
  • 打开微信扫码分享

  • 点击前往QQ分享

  • 点击前往微博分享

  • 点击复制链接

K8S集群中使用JDOS KMS服务对敏感数据安全加密

  • ttbelieve
  • 2023-08-22
  • IP归属:北京
  • 5280浏览

    基本概念

    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

    新建 EncryptionConfiguration

    该配置是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

    新建 jdcloud kms plugin 服务

    该服务是启动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

    修改 kube apiserver配置

    ...
        - --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

    修改后保存

    验证

    在默认的命名空间里创建一个名为 secret1 的 Secret:

    kubectl create secret generic secret1 -n default --from-literal=mykey=mydata

    用 etcdctl 命令行,从 etcd 读取出 Secret:

    etcdctl.sh get /kubernetes.io/secrets/default/secret1 [...] | hexdump -C

    结果为加密数据

    验证 Secret 在被 API server 获取时已被正确解密:

    kubectl describe secret secret1 -n default

    该结果为明文,mykey: mydata

    产品能力

    在K8S集群中,京东内部一直比较重视对敏感数据加密,特别是云舰面对越来越多的金融行业客户,加密服务基本是云舰中的标准配置。

    经过产品能力打磨和内部实现,KMS 加密服务和K8S自动化集群以及一键配置创建都在云舰内实现了很好的产品化能力,可以随集群创建,一键启用KMS加密服务。

    参考:

    1.  使用 KMS 驱动进行数据加密