#初めに
「kubernetes the hard way を PC でやってみる」の9回目、「Bootstrapping the etcd Cluster」についてです。( 目次 )
そろそろ疲れてきましたね。私も疲れてミスを多発させた回でした。
kubernetes では etcd という キーバリューストアに設定や情報を格納します
その etcd のセットアップに関して、 Control plane ノード3台を使った高可用構成の etcd を構成します。
(なお、 世界的にいろいろあって master ノードとは言わなくなったようです)
やることは以下の通りです。
- etcd の入手
- etcd サービスの構成
- etcd の検証
図で言うと赤い枠の部分になります(3台分)
また、末尾につまづいたエラーとその調査・対応方法も記載しておきます。
etcd の入手
etcd の最新版は git hub 上で確認することができます。
以下の URL アクセス後、右側の列の Releases 欄に最新版が記載されています。
https://github.com/etcd-io/etcd
2020/07 時点では、 v3.4.10 でした。
Releases 欄の バージョン部分をクリックすると insatallation guide に遷移します。 そのページ下部にダウンロードできるリンクがあります。
私が実施した際は、 v3.4.7 で、 URL としては以下の通りでした。
https://github.com/etcd-io/etcd/releases/download/v3.4.7/etcd-v3.4.7-linux-amd64.tar.gz
これを wget でダウンロードします。
# wget -q --show-progress --https-only --timestamping \
> "https://github.com/etcd-io/etcd/releases/download/v3.4.7/etcd-v3.4.7-linux-amd64.tar.gz"
etcd-v3.4.7-linux-amd64.tar.gz 100%[================================================================================================================================>] 16.51M 5.42MB/s in 3.0s
# ls -l
total 16908
-rw-r--r-- 1 root root 17310840 Apr 1 20:07 etcd-v3.4.7-linux-amd64.tar.gz
ダウンロード完了後、 展開します。
# tar zxf etcd-v3.4.7-linux-amd64.tar.gz
# ls
etcd-v3.4.7-linux-amd64 etcd-v3.4.7-linux-amd64.tar.gz
# cd etcd-v3.4.7-linux-amd64/
# ls
Documentation etcd etcdctl README-etcdctl.md README.md READMEv2-etcdctl.md
※※ここからは Control Plane ノード3台で実施です※※
(もちろん、最初から Control Plane ノード 3台で実施してもよいです。)
3台で一度に実施する場合、 kubernetes the hard way の Prerequisites の
Running Commands in Parallel with tmux で紹介されている tmux を使うと、一度に3台コントロールできます。
https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/docs/01-prerequisites.md
なれると面白いです。
展開して得られた etcd
を、 /usr/local/bin
にコピーします。
# cp -p etcd* /usr/local/bin
#etcd サービスの構成
etcd を systemd 配下のサービスとして稼働させるための準備を行います。
関連ディレクトリを作成し、 etcd で利用する各種証明書類を配置します。
(具体的には CAの証明書、 kubernetes (API サーバー用の) 秘密鍵・証明書です)
証明書類は マスターノードの作業ユーザーのホームディレクトリに配置していたはずです。 (なければ持ってくる)
# mkdir -p /etc/etcd /var/lib/etcd
# ls
admin.kubeconfig ca-key.pem ca.pem encryption-config.yaml kube-controller-manager.kubeconfig kubernetes-key.pem kubernetes.pem kube-scheduler.kubeconfig service-account-key.pem service-account.pem snap
# cp ca.pem kubernetes-key.pem kubernetes.pem /etc/etcd
次に、 systemd 配下で etcd をサービスとして稼働させるための unit ファイルを作成します。
kubernetes the hard way では、 tmux を使って3台の control plane で同時に操作しています。
その際、コマンド出力を変数に入れることにより、各ノードで違う部分をうまくカバーするようにしています。
例)
HOSTNAME=$( hostname )
echo $HOSTNAME
これを3台の control plane で実施すればそれぞれのホスト名が変数に格納されます。
ここでは、 そこまでせず各ノード上で以下のファイルを作成します。
それを使って 3台のノードに一度でファイルを作成しているようでした。
(と言いつつ、一部べた書きの部分もあった)
ここでは、それは行わず、下で紹介するファイルを3ノード分作成しました。
(当然、ホスト名などの部分はノードごとに読み替える必要はあります)
下に記載している etcd.service ファイルでは、
kubernetes.pem, kubernetes-key.pem ( APIサーバー用に作った秘密鍵と証明書)を利用しています。
kubernetes の世界では、 etcd にアクセスするのは API Server のみなので、上記 API サーバー用の 鍵と証明書
並びに CA の証明書が無ければ通信できませんね。 詳しくは 第6回を参照ください。
また、同様に etcd 間の通信も同じ証明書と鍵を使っています。
なお、サーバーの IP アドレス等忘れていると思いますので再掲します。
ポートも2種類使われていますね。ここはまぁよく見ておいた方が良いかもしれません。
ノード | IPアドレス |
---|---|
k8smaster0 | 192.168.199.200 |
k8smaster1 | 192.168.199.201 |
k8smaster2 | 192.168.199.202 |
下記の例は k8smaster0 のファイルの例です、他のノードではそれぞれ IP 部分などに修正が必要です。
# cat /etc/systemd/system/etcd.service
[Unit]
Description=etcd
Documentation=https://github.com/coreos
[Service]
Type=notify
ExecStart=/usr/local/bin/etcd \
--name k8smaster0 \
--cert-file=/etc/etcd/kubernetes.pem \
--key-file=/etc/etcd/kubernetes-key.pem \
--peer-cert-file=/etc/etcd/kubernetes.pem \
--peer-key-file=/etc/etcd/kubernetes-key.pem \
--trusted-ca-file=/etc/etcd/ca.pem \
--peer-trusted-ca-file=/etc/etcd/ca.pem \
--peer-client-cert-auth \
--client-cert-auth \
--initial-advertise-peer-urls https://192.168.199.200:2380 \
--listen-peer-urls https://192.168.199.200:2380 \
--listen-client-urls https://192.168.199.200:2379,https://127.0.0.1:2379 \
--advertise-client-urls https://192.168.199.200:2379 \
--initial-cluster-token etcd-cluster-0 \
--initial-cluster k8smaster0=https://192.168.199.200:2380,k8smaster1=https://192.168.199.201:2380,k8smaster2=https://192.168.199.202:2380 \
--initial-cluster-state new \
--data-dir=/var/lib/etcd
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
さて、注意事項ですが、 kubernetes the hard way では上記の部分は "" が2つ並んでいます。
上記の例では "" は1個です。 なぜでしょう?
kubernetes the hard way では、 cat コマンドでテキストファイルに流し込んでいるため、
"" を "" でエスケープしているんですね。結果としてできたファイル内には "" が1つになり、
コマンド途中での改行の意味での "" になっています。
ここでは、 cat コマンドでファイルを作成していませんので、 "" は初めから1個にしています。
それに気づかず漫然とテキストファイルにコピペすると次のステップでエラーが出ます。
systemd 配下のファイルを変更したときは、 daemon をリロードします。
# systemctl daemon-reload
リロード完了後、 unit-files を確認(badになっていない)します。
確認後、 自動起動設定を行います。
# systemctl list-unit-files | grep etcd
etcd.service disabled enabled
# systemctl enable etcd
Created symlink /etc/systemd/system/multi-user.target.wants/etcd.service → /etc/systemd/system/etcd.service.
# systemctl list-unit-files | grep etcd
etcd.service enabled enabled
問題なければ起動します。
# systemctl start etcd
root@k8smaster0:/# echo $?
0
起動後には、ログを確認しておきましょう。
少し長いですが、
heartbeat = 100ms, election = 1000ms とタイムアウト値が設定されており、
それを超えると失敗します。
(略4)の後に Leader election が開始されています。
(略5)の後に、36549770f2856ae8 の etcd が Leader に選出されていることがわかります。
May 09 04:49:25 k8smaster0 systemd[1]: Starting etcd...
(略1)
May 09 04:49:25 k8smaster0 etcd[2229]: setting maximum number of CPUs to 2, total number of available CPUs is 2
May 09 04:49:25 k8smaster0 etcd[2229]: peerTLS: cert = /etc/etcd/kubernetes.pem, key = /etc/etcd/kubernetes-key.pem, trusted-ca = /etc/etcd/ca.pem, client-cert-auth = true, crl-file =
May 09 04:49:25 k8smaster0 etcd[2229]: name = k8smaster0
May 09 04:49:25 k8smaster0 etcd[2229]: data dir = /var/lib/etcd
May 09 04:49:25 k8smaster0 etcd[2229]: member dir = /var/lib/etcd/member
May 09 04:49:25 k8smaster0 etcd[2229]: heartbeat = 100ms
May 09 04:49:25 k8smaster0 etcd[2229]: election = 1000ms
May 09 04:49:25 k8smaster0 etcd[2229]: snapshot count = 100000
May 09 04:49:25 k8smaster0 etcd[2229]: advertise client URLs = https://192.168.199.200:2379
(略2)
May 09 04:49:25 k8smaster0 etcd[2229]: starting peer 13f2e6747ca8e776...
May 09 04:49:25 k8smaster0 etcd[2229]: started HTTP pipelining with peer 13f2e6747ca8e776
May 09 04:49:25 k8smaster0 etcd[2229]: started streaming with peer 13f2e6747ca8e776 (writer)
May 09 04:49:25 k8smaster0 etcd[2229]: started streaming with peer 13f2e6747ca8e776 (writer)
May 09 04:49:25 k8smaster0 etcd[2229]: started peer 13f2e6747ca8e776
May 09 04:49:25 k8smaster0 etcd[2229]: added peer 13f2e6747ca8e776
(略3)
May 09 04:49:25 k8smaster0 etcd[2229]: starting server... [version: 3.4.7, cluster version: to_be_decided]
(略4)
May 09 04:49:25 k8smaster0 etcd[2229]: raft2020/05/09 04:49:25 INFO: 36549770f2856ae8 is starting a new election at term 1
May 09 04:49:25 k8smaster0 etcd[2229]: raft2020/05/09 04:49:25 INFO: 36549770f2856ae8 became candidate at term 2
(略5)
May 09 04:49:25 k8smaster0 etcd[2229]: raft2020/05/09 04:49:25 INFO: 36549770f2856ae8 has received 2 MsgVoteResp votes and 0 vote rejections
May 09 04:49:25 k8smaster0 etcd[2229]: raft2020/05/09 04:49:25 INFO: 36549770f2856ae8 became leader at term 2
May 09 04:49:25 k8smaster0 etcd[2229]: raft2020/05/09 04:49:25 INFO: raft.node: 36549770f2856ae8 elected leader 36549770f2856ae8 at term 2
May 09 04:49:25 k8smaster0 etcd[2229]: published {Name:k8smaster0 ClientURLs:[https://192.168.199.200:2379]} to cluster fddffde8fce80533
May 09 04:49:25 k8smaster0 etcd[2229]: ready to serve client requests
May 09 04:49:25 k8smaster0 systemd[1]: Started etcd.
May 09 04:49:25 k8smaster0 etcd[2229]: ready to serve client requests
May 09 04:49:25 k8smaster0 etcd[2229]: serving client requests on 192.168.199.200:2379
May 09 04:49:25 k8smaster0 etcd[2229]: serving client requests on 127.0.0.1:2379
May 09 04:49:25 k8smaster0 etcd[2229]: setting up the initial cluster version to 3.4
May 09 04:49:25 k8smaster0 etcd[2229]: set the initial cluster version to 3.4
May 09 04:49:25 k8smaster0 etcd[2229]: enabled capabilities for version 3.4
#etcd の検証
etcd が起動したら、 確認をしておきます。
# ETCDCTL_API=3 etcdctl member list \
> --endpoints=https://127.0.0.1:2379 \
> --cacert=/etc/etcd/ca.pem \
> --cert=/etc/etcd/kubernetes.pem \
> --key=/etc/etcd/kubernetes-key.pem
13f2e6747ca8e776, started, k8smaster2, https://192.168.199.202:2380, https://192.168.199.202:2379, false
25ceda074dba0436, started, k8smaster1, https://192.168.199.201:2380, https://192.168.199.201:2379, false
36549770f2856ae8, started, k8smaster0, https://192.168.199.200:2380, https://192.168.199.200:2379, false
ETCDCTL_API=3 についてですが、 etcd には API v2 と v3 があり、2020/7 時点では主に v3 が使われているようなのですが
なぜかデフォルトでは v2 になるらしく、環境変数で v3 を指定します。
各サーバーが "started" であることが見て取れます。
なお、リーダーは k8smaster0 です。 ( 前述のログと、36549770f2856ae8 から)
kubernetes the hard way に記載の上記の方法では出力にヘッダーがついていないので不親切です。
その場合は -w table
オプションを付けましょう
# ETCDCTL_API=3 etcdctl -w table member list --endpoints=https://127.0.0.1:2379 --cacert=/etc/etcd/ca.pem --cert=/etc/etcd/kubernetes.pem --key=/etc/etcd/kubernetes-key.pem
+------------------+---------+------------+------------------------------+------------------------------+------------+
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS | IS LEARNER |
+------------------+---------+------------+------------------------------+------------------------------+------------+
| 13f2e6747ca8e776 | started | k8smaster2 | https://192.168.199.202:2380 | https://192.168.199.202:2379 | false |
| 25ceda074dba0436 | started | k8smaster1 | https://192.168.199.201:2380 | https://192.168.199.201:2379 | false |
| 36549770f2856ae8 | started | k8smaster0 | https://192.168.199.200:2380 | https://192.168.199.200:2379 | false |
+------------------+---------+------------+------------------------------+------------------------------+------------+
また、etcd のレスポンスが問題ないかも確認することが可能です。
# ETCDCTL_API=3 etcdctl check perf --endpoints=https://127.0.0.1:2379 --cacert=/etc/etcd/ca.pem --cert=/etc/etcd/kubernetes.pem --key=/etc/etcd/kubernetes-key.pem
60 / 60 Boooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo! 100.00% 1m0s
PASS: Throughput is 150 writes/s
PASS: Slowest request took 0.188862s
PASS: Stddev is 0.010128s
PASS
これで PASS しなければ問題です。
#エラー並びに調査・対応方法
##1. systemd 設定ファイルエラー
今回、 etcd 用のサービス設定ファイルを作成しましたが、
コピー&ペーストでミスっているのに気づかず、エラーになりました。
(※以下は、 etcd.service ファイルを作成し、 systemctl daemon-reload
した後です)
# systemctl enable etcd
Failed to enable unit: File etcd.service: Invalid argument
# systemctl is-enabled etcd
Failed to get unit file state for etcd.service: Invalid argument
# systemctl list-unit-files | grep etcd
etcd.service bad
まぁこのような場合 etcd.service ファイルが間違っているに違いないのですが、
systemd 関連でエラーが出た場合は、 ログを確認しましょう
# journalctl -u etcd
May 03 01:29:06 k8smaster01 systemd[1]: /etc/systemd/system/etcd.service:7: Missing '='.
結局これは、 etcd.services を作るときに "" の数を間違い、
適切に改行されていなかったために出たエラーでした。
systemctl daemon-reload
後は、 systemctl list-unit-files | grep xxxx
で
bad
になっていないことを確認しましょう。
##2. etcd 起動時エラー
なぜか知りませんが、この回はやたらとつまらないミスが多くエラーを多発させました。。。
etcd 起動時にエラーになった、という話ですが、これもログを見ればすぐに解決するお話です。
# systemctl start etcd
Job for etcd.service failed because the control process exited with error code.
See "systemctl status etcd.service" and "journalctl -xe" for details.
#
# journalctl -xe
May 09 04:46:10 k8smaster0 etcd[1379]: Go Version: go1.12.17
May 09 04:46:10 k8smaster0 etcd[1379]: Go OS/Arch: linux/amd64
May 09 04:46:10 k8smaster0 etcd[1379]: setting maximum number of CPUs to 2, total number of available CPUs is 2
May 09 04:46:10 k8smaster0 etcd[1379]: peerTLS: cert = /etc/etcd/kubernetes.pem, key = /etc/etcd/kubernetes-key.pem, trusted-ca = /etc/etcd/ca.pem, client-cert-auth = true, crl-file =
May 09 04:46:10 k8smaster0 etcd[1379]: open /etc/etcd/kubernetes.pem: no such file or directory
May 09 04:46:10 k8smaster0 systemd[1]: etcd.service: Main process exited, code=exited, status=1/FAILURE
ログに no such file or directory と出ていますね。。。
##3.etcd connection refused
さて、厄介な問題でした。解決方法も反則的です(販促的です)。 解決方法といっていいのかすら怪しいです。
etcd 起動時のログに以下のような出力が記録されることがあります。
journalctl -u etcd -f
May 03 02:41:10 k8smaster01 etcd[2078]: raft2020/05/03 02:41:10 INFO: 25ceda074dba0436 is starting a new election at term 1
May 03 02:41:10 k8smaster01 etcd[2078]: raft2020/05/03 02:41:10 INFO: 25ceda074dba0436 became candidate at term 2
May 03 02:41:10 k8smaster01 etcd[2078]: raft2020/05/03 02:41:10 INFO: 25ceda074dba0436 received MsgVoteResp from 25ceda074dba0436 at term 2
May 03 02:41:10 k8smaster01 etcd[2078]: raft2020/05/03 02:41:10 INFO: 25ceda074dba0436 [logterm: 1, index: 3] sent MsgVote request to 13f2e6747ca8e776 at term 2
May 03 02:41:10 k8smaster01 etcd[2078]: raft2020/05/03 02:41:10 INFO: 25ceda074dba0436 [logterm: 1, index: 3] sent MsgVote request to 7b1c68dc0b42688a at term 2
May 03 02:41:11 k8smaster01 etcd[2078]: sync duration of 1.040853586s, expected less than 1s
May 03 02:41:12 k8smaster01 etcd[2078]: raft2020/05/03 02:41:12 INFO: 25ceda074dba0436 is starting a new election at term 2
May 03 02:41:12 k8smaster01 etcd[2078]: raft2020/05/03 02:41:12 INFO: 25ceda074dba0436 became candidate at term 3
May 03 02:41:12 k8smaster01 etcd[2078]: raft2020/05/03 02:41:12 INFO: 25ceda074dba0436 received MsgVoteResp from 25ceda074dba0436 at term 3
May 03 02:41:12 k8smaster01 etcd[2078]: raft2020/05/03 02:41:12 INFO: 25ceda074dba0436 [logterm: 1, index: 3] sent MsgVote request to 13f2e6747ca8e776 at term 3
May 03 02:41:12 k8smaster01 etcd[2078]: raft2020/05/03 02:41:12 INFO: 25ceda074dba0436 [logterm: 1, index: 3] sent MsgVote request to 7b1c68dc0b42688a at term 3
May 03 02:41:14 k8smaster01 etcd[2078]: health check for peer 13f2e6747ca8e776 could not connect: dial tcp 192.168.199.202:2380: connect: connection refused
May 03 02:41:14 k8smaster01 etcd[2078]: health check for peer 13f2e6747ca8e776 could not connect: dial tcp 192.168.199.202:2380: connect: connection refused
May 03 02:41:14 k8smaster01 etcd[2078]: health check for peer 7b1c68dc0b42688a could not connect: dial tcp 192.168.199.203:2380: connect: connection refused
May 03 02:41:14 k8smaster01 etcd[2078]: health check for peer 7b1c68dc0b42688a could not connect: dial tcp 192.168.199.203:2380: connect: connection refused
May 03 02:41:14 k8smaster01 etcd[2078]: raft2020/05/03 02:41:14 INFO: 25ceda074dba0436 is starting a new election at term 3
上記のようなログが延々繰り返される状態です。
ポイントとしては以下の通りです。
sync duration of 1.040853586s, expected less than 1s
とあり、election timeout の 1000ms を超えてしまっています。
そのため、Leader 選出がうまくいっていません。
さらに、 health chek については Connection Refused
が出力されています。
Connection Refused は、簡単に言うと peer (etcd) への接続ができないということです。
NW 通信が異常な場合に発生します。ただし、ここでは Leader 選出が行われていないため、etcd が起動完了していないためだと思われます。(ここは確証が取れませんでした)
何度か繰り返すうちに、たまたまうまく動いたタイミングがあったので先に進んだのですが、
結局 kube-scheduler (次回記載予定) の Leader election も etcd の応答が遅く失敗する、ということで詰まりました。
さて、対応ですが、この時は timeout 値を変更する、という案は思いつきませんでした。(よって確認していません。。)
残念ながら詳細なログを消してしまったのですが、 以下の順で対応しました。
-
etcd を 3台構成ではなく 1台構成に変える (etcd をいったん初期化する)
・ etcd 停止
・ /var/lib/etcd/member ディレクトリ削除 (削除しないと etcd が初期状態に戻りません。ここに状態を記録しているようです)
・ etcd.services ファイル修正 ( #2, #3 エントリーの削除)
・ etcd サービスの無効化( #2, #3 のみ )
・ etcd 起動(#1 のみ) -
I/O が遅いことが分かったので SSD を追加購入
I/Oが遅い、という判断ですが、 Control plane ノードの リソース使用状況(CPU, Memory, Disk I/O) を見ていると
I/O だけに負荷がかかっていることが確認できました。
(もう少し詳しく言うと、 CPU の状態を見たときに usr, sys, idle, wait の CPU使用状況の割合でほぼ wait 100% になっていました)
そのため、 ノート PC の SATA の Disk では無理、と判断し、急遽 SSD を購入しました。
思っていたよりは安くなっていました(256GB で 5000円ぐらいだった気が…)
(※ SSD を入れるという物理手術をしていますので、実際には OS の入れ直しからすべてやり直しています)
今回はここまでとして、次回は Bootstrapping the Kubernetes Control Plane の部分を実施します。
いよいよ本格的になってきますね!
← 8.Encryption Config and Key
↑ 目次
→ 10.Control Plane