Kubernetesクラスタにおけるデータストアとしてetcdがある。
Kubernets The Hard Wayでetcdのセットアップを行ったので、その設定詳細について確認する。
また、Kubernetesにおける etcdクラスタについては以下のドキュメントが参考になる。
kubernetes.io
ユニットファイル
etcdの起動はsystemdで管理しており、そのunitファイルがリポジトリに格納されている
これらの内容は以下の通り。詳細なオプション説明については以下が参考になる。
etcd.io
ところで、etcd v3.4までは To start etcd automatically using custom settings at startup in Linux, using a systemd unit is highly recommended.
と説明記載あったが、v3.5からは削除されたことが気になる。
また、各種オプションの説明についてもv3.4までの方がより詳細な説明が記載されており、v3.5は情報量が落ちている。これらの説明がv3.5では他に移動したのか、意図して削除したのか気になる。基本的には利用バージョンのドキュメントを参照しつつも、自分のように新しく学ぶ段階ではv3.4のドキュメントも参照するとよさそう。
name
etcdメンバを識別するためのHuman-readableな名前。Kubernetes The Hard Wayではcontroller
と設定されている。
このオプションはinitial-cluster
オプションで利用する。
特に複数のetcdメンバーから構成されるetcdクラスタを構築するときに重要になる。
etcdクラスタの構築方法がstatic bootstrappingであってもdiscovery bootstrappingであっても、クラスタ内でユニークな名前となるように設定した方がよさそう。シングルメンバetcdクラスタの場合はおそらくnameは重要ではない。
initial-advertise-peer-urls
etcdがクラスタに接続するときに利用するURL。Kubernetes The Hard Wayではシングルノードetcdで動作するので利用しない。
プロダクションレディなKubernetesではコントロールプレーンの全ノードに対するドメイン名になるのだろうか。
listen-peer-urls
etcdクラスタの接続を許可するURL。Kubernetes The Hard Wayではシングルノードetcdで動作するので利用しないし、 http://127.0.0.1:2380
の設定なので他ノードから接続できない。
initial-advertise-peer-urls
とは異なり、どのアドレスでリッスンするかを指定するので、ドメイン名は指定できない。全許可なら http://0.0.0.0:2380
のような設定になるし、コントロールプレーン用のネットワークが 192.168.128.0/24
だったりしたら http://192.168.128.0:2480
のような設定になるはず?
v3.4までのドキュメントには invalid exampleやv3.5以降より具体的な説明が記載されていたのでわかりやすかった。
listen-client-urls
etcdクライアントが接続するURL。Kubernetesにおいてetcdのclientとは kube-apiserverのことで、kube-apiserver以外のコンポーネントのユニットファイルにはetcdの接続URLは記載されていないし、Kubernetesコンポーネント図にはetcdとkube-apiserverのみ接続線が図示されている。
Kubernetes The Hard Wayの設定においては http://127.0.0.1:2379
が指定されているので、コントロールプレーンノードにおいてetcdとkube-apiserverが必ず動作し、kube-apiserverはローカルetcdに接続することが想定されていると理解できる。
advertise-client-urls
etcdクライアント(kube-apiserver)がetcdクラスタに接続するときに利用するURL。Kubernetes The Hard Wayにおいては http://127.0.0.1:2379
の設定になっており、kube-apiserverのローカルでetcdが動作すればよいという設計になっていることがわかる。
listen-client-urls
とadvertise-client-urls
の関係は listen-peer-urls
とinitial-advertise-peer-urls
の関係に等しく、etcdがどのURLで接続許可するかとkube-apiserverがどのURLで接続するのかを設定できる。ただ、Kubernetesにおいて、etcdとkube-apiserverが同居しないコントロールプレーンの設計が存在しうるのか気になるところ。
initial-cluster-token
etcdクラスタを識別するためのトークン。Kubernetes The Hard Wayでは複数のクラスタを同時に構築することは想定していないので etcd-cluster-0
で固定。
複数クラスタを同じ設定で構築する場合もinitial-cluster-tokenはそれぞれユニークな値を指定することで、クラスタを識別できるようになるしetcdメンバが混在すること防ぐことができる。
initial-cluster
etcdクラスタにおける初期メンバ一覧。Kubernetes The Hard Wayにおいてはシングルメンバのetcdクラスタなのであまり意味はない。
マルチメンバかつstatic bootstrappingの場合は事前に全メンバがわかっているので、メンバの名前と接続用のURLを記載できる。
ドキュメントには --initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380
のような記載例が提示されておりイメージしやすい。
etcdクラスタメンバが動的に構成される場合はこのようにメンバのIP一覧を事前に列挙することはできないので、Discoveryの仕組みを利用する。
initial-cluster-state
etcdクラスタの初期構築(new)か、既存のetcdクラスタへの追加(existing)なのかを指定する。
もし間違った値を指定した場合もetcdクラスタを壊さず安全に停止してくれるらしいが、この値の指定がどのような意味を持つのかよくわかっていない。とりあえず既存クラスタにjoinするように動作し、joinできなかったら新規クラスタを構築するような動作はできないのだろうか。
バックアップ・リストア
Kuberneteのetcdクラスタ運用において、バックアッププランはちゃんと作成しておけよと注意書きがあるのでここだけ検証しておく。
Kubernetes The Hard Wayでは --data-dir=/var/lib/etcd
を指定しているのでこのディレクトリをバックアップしてもよい(volume snapshot)し、etcdctl snapshot save snapshot.db
のコマンドでスナップショットを作成してもよい(built-in snapshot)。
Kubernetesのドキュメントには --endpointの指定もあるが、これは指定するなら --endpints=http://127.0.0.1:2379
のようになる。これがデフォルト値なので変更なしなら指定しなくてよい。運用系の操作なので2380ポートかと思ったが、etcdctlからの操作はクライアント接続でありgRPCプロトコルなので2379ポートらしい。また、クライアント接続なので --listen-client-urls
で指定したURLからでないと接続できない。
root@khw-server:~# etcdctl snapshot save snapshot.db
{"level":"info","ts":1726459074.9597218,"caller":"snapshot/v3_snapshot.go:119","msg":"created temporary db file","path":"snapshot.db.part"}
{"level":"info","ts":"2024-09-16T12:57:54.988563+0900","caller":"clientv3/maintenance.go:200","msg":"opened snapshot stream; downloading"}
{"level":"info","ts":1726459074.99662,"caller":"snapshot/v3_snapshot.go:127","msg":"fetching snapshot","endpoint":"127.0.0.1:2379"}
{"level":"info","ts":"2024-09-16T12:57:55.494366+0900","caller":"clientv3/maintenance.go:208","msg":"completed snapshot read; closing"}
{"level":"info","ts":1726459075.562186,"caller":"snapshot/v3_snapshot.go:142","msg":"fetched snapshot","endpoint":"127.0.0.1:2379","size":"1.2 MB","took":0.594269111}
{"level":"info","ts":1726459075.573733,"caller":"snapshot/v3_snapshot.go:152","msg":"saved","path":"snapshot.db"}
Snapshot saved at snapshot.db
root@khw-server:~# etcdctl --write-out=table snapshot status snapshot.db
+----------+----------+------------+------------+
| HASH | REVISION | TOTAL KEYS | TOTAL SIZE |
+----------+----------+------------+------------+
| 45051425 | 163644 | 927 | 1.2 MB |
+----------+----------+------------+------------+
このファイルを別サーバに転送してリストアする。
etcdctlのスナップショットリストアはetcdメンバにバックアップデータを投入するのではなく、データディレクトリに展開する役目を持つ。このため、リストアする際はetcdメンバを停止させ、データディレクトリを空にした上で実行する。その上でetcdを起動すればリストアできる。
$ etcdctl --data-dir /tmp/etcd/ snapshot restore snapshot.db
Deprecated: Use `etcdutl snapshot restore` instead.
2024-09-16T13:18:39+09:00 info snapshot/v3_snapshot.go:265 restoring snapshot {"path": "snapshot.db", "wal-dir": "/tmp/etcd/member/wal", "data-dir": "/tmp/etcd/", "snap-dir": "/tmp/etcd/member/snap", "initial-memory-map-size": 0}
2024-09-16T13:18:39+09:00 info membership/store.go:141 Trimming membership information from the backend...
2024-09-16T13:18:39+09:00 info membership/cluster.go:421 added member {"cluster-id": "cdf818194e3a8c32", "local-member-id": "0", "added-peer-id": "8e9e05c52164694d", "added-peer-peer-urls": ["http://localhost:2380"]}
2024-09-16T13:18:39+09:00 info snapshot/v3_snapshot.go:293 restored snapshot {"path": "snapshot.db", "wal-dir": "/tmp/etcd/member/wal", "data-dir": "/tmp/etcd/", "snap-dir": "/tmp/etcd/member/snap", "initial-memory-map-size": 0}
# etcdを別ターミナルで起動する
$ etcdctl get /registry/secrets/default/kubernetes-the-hard-way | hexdump -C
00000000 2f 72 65 67 69 73 74 72 79 2f 73 65 63 72 65 74 |/registry/secret|
00000010 73 2f 64 65 66 61 75 6c 74 2f 6b 75 62 65 72 6e |s/default/kubern|
00000020 65 74 65 73 2d 74 68 65 2d 68 61 72 64 2d 77 61 |etes-the-hard-wa|
00000030 79 0a 6b 38 73 3a 65 6e 63 3a 61 65 73 63 62 63 |y.k8s:enc:aescbc|
00000040 3a 76 31 3a 6b 65 79 31 3a b8 f6 3b 4f 4d 76 b4 |:v1:key1:..;OMv.|
00000050 ea 1d 0f 0f c4 f5 0d ad 19 bb 4e ef 97 bd 35 df |..........N...5.|
00000060 50 ef db a6 23 29 58 f1 5a 73 d7 b9 83 a3 e0 b1 |P...#)X.Zs......|
00000070 a0 e4 24 3c 7d 5b ab de 5d 62 a6 e1 59 48 84 f2 |..$<}[..]b..YH..|
00000080 40 58 1f ec 5a 9b e2 a5 15 c8 58 b3 78 36 2f eb |@X..Z.....X.x6/.|
00000090 90 0e 31 86 53 c5 1d 17 78 43 4d 10 69 55 61 42 |..1.S...xCM.iUaB|
000000a0 df 5c 76 70 64 3f 47 db 09 14 a4 bb ca 7e 26 0e |.\vpd?G......~&.|
000000b0 c7 2b c6 97 54 68 4d 35 54 11 96 38 25 81 d6 98 |.+..ThM5T..8%...|
000000c0 6a 46 77 0b e6 12 32 db cf 84 98 11 01 5b cf 49 |jFw...2......[.I|
000000d0 7a 75 92 48 54 57 e0 6b 14 9f 48 05 2a 3b d0 23 |zu.HTW.k..H.*;.#|
000000e0 ed a0 09 56 37 0b fa 48 5c 87 99 bd 34 e3 41 e0 |...V7..H\...4.A.|
000000f0 76 29 87 35 eb 8c fc 09 ff e8 ad 8e ac 6e 57 c5 |v).5.........nW.|
00000100 7b 3e cf ea 93 31 c5 4d 48 88 b9 d8 b3 7f 5c 85 |{>...1.MH.....\.|
00000110 a1 97 a6 0b 65 52 3f b1 35 4b 26 eb b9 de 3d 42 |....eR?.5K&...=B|
00000120 73 e3 93 c8 74 08 37 7b 74 6b bf 91 e8 8e 21 1a |s...t.7{tk....!.|
00000130 8d 76 33 2c 15 13 76 cf 2f 1e 38 24 eb 91 9a dc |.v3,..v./.8$....|
00000140 98 0f a8 5d 53 36 83 e4 58 22 9f 82 8c 2b 2e 3e |...]S6..X"...+.>|
00000150 3c 79 98 ab 12 d2 44 19 fb 0a |<y....D...|
0000015a