Tanzu Kubernetes GridのEtcdのデータを暗号化する (Encryption at Rest)

Tanzu Kubernetes Gridで作成するKubernetesクラスタは "Encryption at Rest" の設定が入っていないので、 Etcdには平文でデータが保存されます。

vSphere with Tanzuで作成されるTanzu Kubernetes Grid Clusterは"Encryption at Rest"が設定されています。

試しに、普通のTanzu Kubernetes Grid ClusterにSecretを作成して、Etcdの中を覗いてみます。

kubectl create secret generic secret1 -n default --from-literal=mykey=mydata
kubectl exec -n kube-system -ti $(kubectl get pod -n kube-system -l component=etcd --template '{{(index .items 0).metadata.name}}') -- /bin/sh
 
# etcdctl --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd/peer.key --cacert=/etc/kubernetes/pki/etcd/ca.crt get /registry/secrets/default/secret1
/registry/secrets/default/secret1
k8s


v1Secret?
?
secret1default"*$027a1469-b37a-4881-b18d-8b09ee8937582?⑇z?`
kubectl-createUpdatev?⑇FieldsV1:.
,{"f:data":{".":{},"f:mykey":{}},"f:type":{}}
mykeymydataOpaque"

mydataがしっかり見えてますね。

"Encryption at Rest"の設定は↓のドキュメントが詳しいです。

https://tanzu.vmware.com/developer/guides/kubernetes/platform-security-secret-management/#encryption-at-rest-static-key

このドキュメントの内容をTanzu Kubernetes Gridに適用します。

ポイントとしては

  • EncryptionConfigurationの設定ファイルを用意する
  • kube-apiserverのencryption-provider-configオプションにEncryptionConfigurationの設定ファイルのパスを渡す

をCluster APIのKubeadmControlPlaneに設定する必要があります。

これを実現するのに ytt のoverlayを使用します。

$HOME/.tanzu/tkg/providers/infrastructure-vsphere/ytt/vsphere-overlay.yamlに次の設定を記述または追記します。

#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.subset({"kind": "KubeadmControlPlane"})
---
spec:
  kubeadmConfigSpec:
    clusterConfiguration:
      apiServer:
        extraArgs:
          #@overlay/match missing_ok=True
          encryption-provider-config: /etc/kubernetes/etcd-encryption/encryption.yaml
        #@overlay/match missing_ok=True
        extraVolumes:
        - name: encryption-provider-config
          hostPath: /etc/kubernetes/etcd-encryption/encryption.yaml
          mountPath: /etc/kubernetes/etcd-encryption/encryption.yaml
          readOnly: true
          pathType: File         
    files:
    #@overlay/append
    - content: |
        apiVersion: apiserver.config.k8s.io/v1
        kind: EncryptionConfiguration
        resources:
        - resources:
          - secrets
          providers:
          - secretbox:
              keys:
              - name: secret-key-1
                secret: ***************************
          # identity is a required (default) provider
          - identity: {}
      owner: "root:root"
      path: "/etc/kubernetes/etcd-encryption/encryption.yaml"
      permissions: "0644"  

***************************の箇所にはhead -c 32 /dev/urandom | base64の出力結果を設定します。

これでtanzu cluster create --dry-runでoverlay適用結果を確認します。

ここではCluster名blueberryで、定義を次のようにblueberry.yaml設定します。設定値は環境によって異なります。

AVI_ENABLE: "false"
CLUSTER_CIDR: 100.96.0.0/11
CLUSTER_NAME: blueberry
CLUSTER_PLAN: dev
ENABLE_CEIP_PARTICIPATION: "false"
ENABLE_MHC: "true"
IDENTITY_MANAGEMENT_TYPE: none
INFRASTRUCTURE_PROVIDER: vsphere
SERVICE_CIDR: 100.64.0.0/13
TKG_HTTP_PROXY_ENABLED: "false"
VSPHERE_CONTROL_PLANE_DISK_GIB: "20"
VSPHERE_CONTROL_PLANE_ENDPOINT: 192.168.10.100
VSPHERE_CONTROL_PLANE_MEM_MIB: "4096"
VSPHERE_CONTROL_PLANE_NUM_CPUS: "2"
VSPHERE_DATACENTER: /Datacenter
VSPHERE_DATASTORE: /Datacenter/datastore/datastore1
VSPHERE_FOLDER: /Datacenter/vm/tkg
VSPHERE_NETWORK: VM Network
VSPHERE_PASSWORD: ....
VSPHERE_RESOURCE_POOL: /Datacenter/host/Cluster/Resources/tkg
VSPHERE_SERVER: administrator@vsphere.local
VSPHERE_SSH_AUTHORIZED_KEY: ssh-rsa AAAA....
VSPHERE_TLS_THUMBPRINT: 04:FD:....
VSPHERE_USERNAME: administrator@vsphere.local
VSPHERE_WORKER_DISK_GIB: "20"
VSPHERE_WORKER_MEM_MIB: "4096"
VSPHERE_WORKER_NUM_CPUS: "2"

出力結果に次の内容が含まれていることを確認します。

$ tanzu cluster create -f blueberry.yaml --dry-run

# ...
---
apiVersion: controlplane.cluster.x-k8s.io/v1alpha3
kind: KubeadmControlPlane
metadata:
  name: blueberry-control-plane
  namespace: default
spec:
  infrastructureTemplate:
    apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3
    kind: VSphereMachineTemplate
    name: blueberry-control-plane
  kubeadmConfigSpec:
    clusterConfiguration:
      apiServer:
        extraArgs:
          cloud-provider: external
          encryption-provider-config: /etc/kubernetes/etcd-encryption/encryption.yaml
          tls-cipher-suites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
        extraVolumes:
        - hostPath: /etc/kubernetes/etcd-encryption/encryption.yaml
          mountPath: /etc/kubernetes/etcd-encryption/encryption.yaml
          name: encryption-provider-config
          readOnly: true
        timeoutForControlPlane: 8m0s
      # ...
   files:
    - content: |
        ...
      owner: root:root
      path: /etc/kubernetes/manifests/kube-vip.yaml
    - content: |
        apiVersion: apiserver.config.k8s.io/v1
        kind: EncryptionConfiguration
        resources:
        - resources:
          - secrets
          providers:
          - secretbox:
              keys:
              - name: secret-key-1
                secret: ***************************
          # identity is a required (default) provider
          - identity: {}
      owner: root:root
      path: /etc/kubernetes/etcd-encryption/encryption.yaml
    # ...

問題なければ--dry-runオプションを外して、クラスタを作成します。

tanzu cluster create -f blueberry.yaml -y

クラスタが作成されたら、次のコマンドを実行してクラスタにアクセスできるようにします。

tanzu cluster kubeconfig get --admin blueberry
kubectl config use-context blueberry-admin@blueberry

Etcdのデータが暗号化されているかどうか確認します。

kubectl create secret generic secret1 -n default --from-literal=mykey=mydata
kubectl exec -n kube-system -ti $(kubectl get pod -n kube-system -l component=etcd --template '{{(index .items 0).metadata.name}}') -- /bin/sh 

# etcdctl --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd/peer.key --cacert=/etc/kubernetes/pki/etcd/ca.crt get /registry/secrets/default/secret1
/registry/secrets/default/secret1
k8s:enc:secretbox:v1:secret-key-1:l|??ص?P ?F?M??
                                                ׋?օ????I?h?T?+?P???4?L??@??R,?
                                                                              _Q[-?5g,@?T????o??'?*???^?c?Ѳky??͉?????ܮ??
*???EfQ??>?,ӣ??+?L?NG#.??X??P????|?6?ˇ???#??????2??6P?h???\|?P?i?5L??9?xD/=?J?#?b???-Þ??d?o????
                                                                                               @?{?xX?/?%??̻?ej?X?ՙ:???--e
                                                                                                                         ?q?C>???

ちゃんと暗号化されていますね🔓