Kubernetes the hard way (GCP版)の続きです。
前回の記事はこちら
Chap7. Bootstrapping the etcd Cluster(etcdクラスターのブートストラップ)
このチャプターでは、Control Planeを構成するコンポーネントの一つであるetcdのクラスターのブートストラップを行います。
etcdバイナリのダウンロードとインストール
このチャプターでの作業はControl Planeの各ノードにsshでログインした上で行います。
(筆者はtmuxを使わずに、各ノードごとにターミナルのウィンドウを開いて作業をしました。)
最初にetcd のバイナリをダウンロードします。
(CLIツールであるetcdctlも含まれているので、別でインストールを行う必要はありません。)
wget -q --show-progress --https-only --timestamping \ "https://github.com/etcd-io/etcd/releases/download/v3.4.0/etcd-v3.4.0-linux-amd64.tar.gz"
バイナリを解凍して、etcdの本体とetcdctl (CLIツール)を/usr/local/bin
に移動することでセットアップ前の準備は完了となります。
{ tar -xvf etcd-v3.4.0-linux-amd64.tar.gz sudo mv etcd-v3.4.0-linux-amd64/etcd* /usr/local/bin/ }
etcdサーバーの設定
バイナリのダウンロードが完了したら、etcdサーバーの設定を行っていきます。
最初に、ノード内で必要なディレクトリ (/etc/etcd
, /var/lib/etcd
) を作成して、Chap4で作成したAPI Server用の証明書ファイル類を配置します。
...@controller-0:~$ { > sudo mkdir -p /etc/etcd /var/lib/etcd > sudo cp ca.pem kubernetes-key.pem kubernetes.pem /etc/etcd/ > }
次に、Control Plane(インスタンス)のPrivate IPとホスト名を変数として取得します。
インスタンスのメタデータに関しては、メタデータサーバーから取得できるようになっています。
インスタンスからメタデータサーバへのAPIアクセスに関しては、追加で認証処理を行うことなくメタデータを取得することが可能です。
...@controller-0:~$ INTERNAL_IP=$(curl -s -H "Metadata-Flavor: Google" \ > http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip) ...@controller-0:~$ echo $INTERNAL_IP 10.240.0.10 ...@controller-0:~$ hostname -s controller-0 ...@controller-0:~$ ETCD_NAME=$(hostname -s)
最後にetcdをサービスとして登録するために、etcdのサービスファイル (etcd.service
) を作成します。
先ほど取得したノードのPrivate IPとホスト名はここで利用します。
他にも下記のような項目が設定されています。
--client-cert-auth
: etcdへの通信時にTLSクライアント認証を有効化する--peer-client-cert-auth
: ピア同士の通信時にTLSクライアント認証を有効化する--cert-file
/--key-file
: etcdへの通信時に利用するTLS証明書ファイル・秘密鍵ファイル--peer-cert-file
/--peer-key-file
: ピア同士の通信に利用されるTLS証明書ファイル・秘密鍵ファイル--listen-client-urls
(port: 2379) : etcdへの通信時に接続を受け付けるURL--listen-peer-urls
(port: 2380) : ピア同士の通信時に接続を受け付けるURL--advertise-client-urls
(port: 2379) : etcdへの通信時に外部に広告するURL--initial-advertise-peer-urls
(port: 2380) : ピア同士の通信時に全てのピアに広告するURL
上記の設定項目に関する説明は下記のリンクに記載されています。
...@controller-0:~$ cat <<EOF | sudo tee /etc/systemd/system/etcd.service > [Unit] > Description=etcd > Documentation=https://github.com/coreos > > [Service] > Type=notify > ExecStart=/usr/local/bin/etcd \\ > --name ${ETCD_NAME} \\ > --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://${INTERNAL_IP}:2380 \\ > --listen-peer-urls https://${INTERNAL_IP}:2380 \\ > --listen-client-urls https://${INTERNAL_IP}:2379,https://127.0.0.1:2379 \\ > --advertise-client-urls https://${INTERNAL_IP}:2379 \\ > --initial-cluster-token etcd-cluster-0 \\ > --initial-cluster controller-0=https://10.240.0.10:2380,controller-1=https://10.240.0.11:2380,controller-2=https://10.240.0.12:2380 \\ > --initial-cluster-state new \\ > --data-dir=/var/lib/etcd > Restart=on-failure > RestartSec=5 > > [Install] > WantedBy=multi-user.target > EOF [Unit] Description=etcd Documentation=https://github.com/coreos [Service] Type=notify ... RestartSec=5 [Install] WantedBy=multi-user.target
etcdサーバーの起動
サービスファイルの作成が完了したら、systemctl
コマンドでetcdのサービスを起動します。
作成したサービスファイルをsystemdに反映させるために、daemon-reload
コマンドを実行してからサービスを起動します。
{ sudo systemctl daemon-reload sudo systemctl enable etcd sudo systemctl start etcd }
注意点として、etcdのメンバーを単独で起動するとサービスの起動は失敗します。
サービスのステータス確認時にfailed
の状態になった場合は、systemctl reset-failed
コマンドで異常状態のリセットを行います。
...@controller-0:~$ { > sudo systemctl daemon-reload > sudo systemctl enable etcd > sudo systemctl start etcd > } Created symlink /etc/systemd/system/multi-user.target.wants/etcd.service → /etc/systemd/system/etcd.service. Job for etcd.service failed because a timeout was exceeded. See "systemctl status etcd.service" and "journalctl -xe" for details. ...@controller-0:~$ journalctl -xe Feb 29 03:58:45 controller-0 etcd[3667]: raft2020/02/29 03:58:45 INFO: f98dc20bce6225a0 became candidate at term 85 Feb 29 03:58:45 controller-0 etcd[3667]: raft2020/02/29 03:58:45 INFO: f98dc20bce6225a0 received MsgVoteResp from f98dc20bce6225a0 at term 85 Feb 29 03:58:45 controller-0 etcd[3667]: raft2020/02/29 03:58:45 INFO: f98dc20bce6225a0 [logterm: 1, index: 3] sent MsgVote request to 3a57933972cb5131 at term 85 Feb 29 03:58:45 controller-0 etcd[3667]: raft2020/02/29 03:58:45 INFO: f98dc20bce6225a0 [logterm: 1, index: 3] sent MsgVote request to ffed16798470cab5 at term 85 Feb 29 03:58:47 controller-0 etcd[3667]: raft2020/02/29 03:58:47 INFO: f98dc20bce6225a0 is starting a new election at term 85 Feb 29 03:58:47 controller-0 etcd[3667]: raft2020/02/29 03:58:47 INFO: f98dc20bce6225a0 became candidate at term 86 Feb 29 03:58:47 controller-0 etcd[3667]: raft2020/02/29 03:58:47 INFO: f98dc20bce6225a0 received MsgVoteResp from f98dc20bce6225a0 at term 86 Feb 29 03:58:47 controller-0 etcd[3667]: raft2020/02/29 03:58:47 INFO: f98dc20bce6225a0 [logterm: 1, index: 3] sent MsgVote request to 3a57933972cb5131 at term 86 Feb 29 03:58:47 controller-0 etcd[3667]: raft2020/02/29 03:58:47 INFO: f98dc20bce6225a0 [logterm: 1, index: 3] sent MsgVote request to ffed16798470cab5 at term 86 Feb 29 03:58:48 controller-0 etcd[3667]: raft2020/02/29 03:58:48 INFO: f98dc20bce6225a0 is starting a new election at term 86 Feb 29 03:58:48 controller-0 etcd[3667]: raft2020/02/29 03:58:48 INFO: f98dc20bce6225a0 became candidate at term 87 Feb 29 03:58:48 controller-0 etcd[3667]: raft2020/02/29 03:58:48 INFO: f98dc20bce6225a0 received MsgVoteResp from f98dc20bce6225a0 at term 87 Feb 29 03:58:48 controller-0 etcd[3667]: raft2020/02/29 03:58:48 INFO: f98dc20bce6225a0 [logterm: 1, index: 3] sent MsgVote request to 3a57933972cb5131 at term 87 Feb 29 03:58:48 controller-0 etcd[3667]: raft2020/02/29 03:58:48 INFO: f98dc20bce6225a0 [logterm: 1, index: 3] sent MsgVote request to ffed16798470cab5 at term 87 // 単独でサービスを起動しているため、他のメンバーへの通信に失敗する Feb 29 03:58:49 controller-0 etcd[3667]: health check for peer 3a57933972cb5131 could not connect: dial tcp 10.240.0.12:2380: connect: connection refused Feb 29 03:58:49 controller-0 etcd[3667]: health check for peer ffed16798470cab5 could not connect: dial tcp 10.240.0.11:2380: connect: connection refused Feb 29 03:58:49 controller-0 etcd[3667]: health check for peer ffed16798470cab5 could not connect: dial tcp 10.240.0.11:2380: connect: connection refused Feb 29 03:58:49 controller-0 etcd[3667]: health check for peer 3a57933972cb5131 could not connect: dial tcp 10.240.0.12:2380: connect: connection refused
検証
全てのControl Planeでetcdのセットアップを実行してから、正常にクラスターが構成されているか検証を行います。
検証では、etcdctl
を利用してetcdクラスターのメンバー一覧を取得します。
導入したetcdのバージョンがv3.4.0以下の場合は、環境変数をセットする必要があります。(ETCDCTL_API=3
)
...@controller-1:~$ sudo 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 3a57933972cb5131, started, controller-2, https://10.240.0.12:2380, https://10.240.0.12:2379, false f98dc20bce6225a0, started, controller-0, https://10.240.0.10:2380, https://10.240.0.10:2379, false ffed16798470cab5, started, controller-1, https://10.240.0.11:2380, https://10.240.0.11:2379, false
正常にetcdクラスターのメンバー一覧を取得できたので、etcdクラスタのセットアップは完了となります。
今回は、Chap7の内容をまとめました。
etcdで利用されている分散合意アルゴリズム (Raft) については関連リンクだけ記載しておきます。