---
title: Tanzu Kubernetes GridのEtcdのデータを暗号化する (Encryption at Rest)
tags: ["Kubernetes", "vSphere", "TKG", "Tanzu", "Cluster API", "ytt"]
categories: ["Dev", "CaaS", "Kubernetes", "TKG", "vSphere"]
date: 2021-07-07T03:28:27Z
updated: 2021-07-07T03:28:27Z
---

Tanzu Kubernetes Gridで作成するKubernetesクラスタは　"[Encryption at Rest](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/)" の設定が入っていないので、
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](https://carvel.dev/ytt/) のoverlayを使用します。

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

```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`設定します。設定値は環境によって異なります。

```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"
```

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

```yaml
$ 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>???
```

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