kubernetes内のetcdをバックアップ・リストアする

Kubernetes Cluster内のetcdをバックアップ、リストアする方法を確認します。

環境情報

前提として、対象のetcdはシングル構成で、1台のkubernetesのマスターノードで動作しています。kubernetes環境は、kubeadmにて作成しました。

バージョンは下記。

バックアップ

まず、バックアップを実行します。以下は公式ドキュメント。

Backing up an etcd cluster

なお、作業はすべてKubernetes Clusterのマスターノード上で作業しています。

確認用のデータを作成

検証のためconfigmapにデータを入れておきます。

$ kubectl create namespace backup
namespace/backup created
$
$ kubectl -n backup create configmap sample1 --from-literal=key1=value1
configmap/sample1 created
$
$ kubectl -n backup get configmap
NAME               DATA   AGE
kube-root-ca.crt   1      2m5s
sample1            1      45s

認証用情報の確認

バックアップ・リストアのどちらの処理でも、etcdのコマンドラインツールであるetcdctlを利用します。kubernetes内のetcdへの接続にはx509証明書を必要とするため、証明書情報を事前に確認しておきます。

それら情報はetcd起動時のオプションとして指定されており、kubeadm作成環境のetcdはStatic Podとして起動されているため、そのマニフェストファイルを見に行くことになります。

まず、Static Podのマニフェストファイル格納pathを確認します。kubeletのプロセスを表示して、利用しているコンフィグファイルのPathを調べます。

$ ps -aef | grep /usr/bin/kubelet | grep -v grep
root         505       1  4 06:13 ?        00:00:38 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.2

/var/lib/kubelet/config.yaml が参照されているコンフィグとなるため、ファイル内を確認。

$ sudo cat /var/lib/kubelet/config.yaml | grep static
staticPodPath: /etc/kubernetes/manifests

Static Pod用Path配下にあるetcd向けのマニフェストファイル内の記述を確認。

$ sudo cat /etc/kubernetes/manifests/etcd.yaml 
apiVersion: v1
kind: Pod
...
spec:
  containers:
  - command:
    - etcd
    - --advertise-client-urls=https://10.146.0.2:2379
    - --cert-file=/etc/kubernetes/pki/etcd/server.crt           # certファイル
    - --client-cert-auth=true
    - --data-dir=/var/lib/etcd
    - --initial-advertise-peer-urls=https://10.146.0.2:2380
    - --initial-cluster=kubeadm-master=https://10.146.0.2:2380
    - --key-file=/etc/kubernetes/pki/etcd/server.key            # keyファイル
    - --listen-client-urls=https://127.0.0.1:2379,https://10.146.0.2:2379
    - --listen-metrics-urls=http://127.0.0.1:2381
    - --listen-peer-urls=https://10.146.0.2:2380
    - --name=kubeadm-master
    - --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt
    - --peer-client-cert-auth=true
    - --peer-key-file=/etc/kubernetes/pki/etcd/peer.key
    - --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
    - --snapshot-count=10000
    - --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt         # cacertファイル
    image: k8s.gcr.io/etcd:3.4.13-0
...

確認できた証明書情報を利用して接続確認。

$ sudo ETCDCTL_API=3 etcdctl endpoint health \
--endpoints=https://[127.0.0.1]:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
https://[127.0.0.1]:2379 is healthy: successfully committed proposal: took = 1.25967ms

etcdctd をインストールしていない場合、 sudo apt-get install etcd-client でインストールできます。

スナップショットの取得

etcd clusterを構成するメンバーを確認。今回はシングル構成です。

$ sudo ETCDCTL_API=3 etcdctl member list \
--endpoints=https://[127.0.0.1]:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
7a2c7e572714edd4, started, kubeadm-master, https://10.146.0.2:2380, https://10.146.0.2:2379

GitHub - MEMBER LIST

スナップショット(バックアップ)を取得します。スナップショットデータを出力するpathを指定してあげます。

$ sudo ETCDCTL_API=3 etcdctl snapshot save /tmp/backup.db \
--endpoints=https://[127.0.0.1]:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
Snapshot saved at /tmp/backup.db

GitHub - SNAPSHOT SAVE

確認。

$ sudo ETCDCTL_API=3 etcdctl --write-out=table snapshot status /tmp/backup.db \
--endpoints=https://[127.0.0.1]:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
+----------+----------+------------+------------+
|   HASH   | REVISION | TOTAL KEYS | TOTAL SIZE |
+----------+----------+------------+------------+
| dac52cbc |    89884 |       1095 |     4.4 MB |
+----------+----------+------------+------------+

GitHub - SNAPSHOT STATUS

確認用のデータを作成

確認のためにconfigmapにデータを入れておきます。

$ kubectl -n backup create configmap sample2 --from-literal=key2=value2
configmap/sample2 created
$
$ kubectl -n backup get configmap
NAME               DATA   AGE
kube-root-ca.crt   1      35m
sample1            1      34m
sample2            1      15s

リストア

上記で取得したスナップショットデータを利用して、リストアを試してみます。下記は参考ドキュメントです。

Restoring an etcd cluster

ETCD - backup and restore management

etcdデータのリストア

取得済スナップショットを利用して、新しいetcdデータベースを作成(リストア)します。

$ sudo ETCDCTL_API=3 etcdctl snapshot restore /tmp/backup.db \
--name=master \
--initial-cluster-token=etcd-cluster \
--initial-cluster=master=https://127.0.0.1:2380 \
--initial-advertise-peer-urls=https://127.0.0.1:2380 \
--data-dir=/var/lib/etcd-backup \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
--skip-hash-check
2021-01-16 15:42:21.252916 I | mvcc: restore compact to 87044
2021-01-16 15:42:21.261913 I | etcdserver/membership: added member a874c87fd42044f [https://127.0.0.1:2380] to cluster c9be114fc2da2776
  • 利用オプションのメモ
    • initial-cluster-token
      • etcd clusterを識別する一意の値。適当文字列を設定。
    • data-dir
      • データベース作成先のPath。

GitHub - SNAPSHOT RESTORE [options]


--skip-hash-check オプションをつけないと、以下のエラーメッセージにてリストアができませんでした。

Error:  expected sha256 [171 197 141 218 193 152 67 217 195 129 215 113 196 222 94 143 213 0 209 239 53 156 23 153 157 242 84 122 177 65 77 87], got [173 176 46 105 167 240 81 218 121 14 129 145 117 104 50 178 76 149 101 236 22 153 10 108 71 20 230 90 229 239 37 209]

etcdコンテナの起動設定変更

Static Podとして起動されるetcd用マニフェストファイルの記述を変更して、上記でリストアしたデータベースを利用するように変更します。変更点はコメントアウト部分を参照。

/etc/kubernetes/manifests/etcd.yaml

apiVersion: v1
kind: Pod
metadata:
  annotations:
    kubeadm.kubernetes.io/etcd.advertise-client-urls: https://10.146.0.2:2379
  creationTimestamp: null
  labels:
    component: etcd
    tier: control-plane
  name: etcd
  namespace: kube-system
spec:
  containers:
  - command:
    - etcd
    - --advertise-client-urls=https://10.146.0.2:2379
    - --cert-file=/etc/kubernetes/pki/etcd/server.crt
    - --client-cert-auth=true
    - --data-dir=/var/lib/etcd-backup           # リストアしたPathを指定
    - --initial-cluster-token=etcd-cluster      # リストア時に指定した値を指定
    - --initial-advertise-peer-urls=https://10.146.0.2:2380
    - --initial-cluster=kubeadm-master=https://10.146.0.2:2380
    - --key-file=/etc/kubernetes/pki/etcd/server.key
    - --listen-client-urls=https://127.0.0.1:2379,https://10.146.0.2:2379
    - --listen-metrics-urls=http://127.0.0.1:2381
    - --listen-peer-urls=https://10.146.0.2:2380
    - --name=master
    - --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt
    - --peer-client-cert-auth=true
    - --peer-key-file=/etc/kubernetes/pki/etcd/peer.key
    - --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
    - --snapshot-count=10000
    - --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
    image: k8s.gcr.io/etcd:3.4.13-0
    imagePullPolicy: IfNotPresent
    livenessProbe:
      failureThreshold: 8
      httpGet:
        host: 127.0.0.1
        path: /health
        port: 2381
        scheme: HTTP
      initialDelaySeconds: 10
      periodSeconds: 10
      timeoutSeconds: 15
    name: etcd
    resources:
      requests:
        cpu: 100m
        ephemeral-storage: 100Mi
        memory: 100Mi
    startupProbe:
      failureThreshold: 24
      httpGet:
        host: 127.0.0.1
        path: /health
        port: 2381
        scheme: HTTP
      initialDelaySeconds: 10
      periodSeconds: 10
      timeoutSeconds: 15
    volumeMounts:
    - mountPath: /var/lib/etcd-backup           # リストアしたPathに合わせて修正
      name: etcd-data
    - mountPath: /etc/kubernetes/pki/etcd
      name: etcd-certs
  hostNetwork: true
  priorityClassName: system-node-critical
  volumes:
  - hostPath:
      path: /etc/kubernetes/pki/etcd
      type: DirectoryOrCreate
    name: etcd-certs
  - hostPath:
      path: /var/lib/etcd-backup                # リストアしたPathに合わせて修正
      type: DirectoryOrCreate
    name: etcd-data
status: {}

Podが更新されるのを、しばらく待ちます。

確認

configmapのデータを見ることで、リストアできていることを確認します。

$ kubectl -n kube-system get pod | grep etcd
etcd-kubeadm-master                        1/1     Running   0          81s

$ kubectl -n backup get configmap
NAME               DATA   AGE
kube-root-ca.crt   1      9h
sample1            1      9h