kubeadmでHAクラスタ構築(参考訳:v1.10)
このドキュメントについて
これはv1.10の古いドキュメント Creating HA Clusters with kubeadmに対する参考訳です。正確には先のページの更新版に対する翻訳(6月上旬時点)です。v1.11へのバージョンアップに伴い手順が一部変わりました。現行バージョンとは一部手順が異なるものの、見直すこともあるかと思い、残しておきます。
なお、現行バージョンのドキュメントは v1.11のドキュメント をご覧ください。
Creating HA clusters with kubeadm
このガイドでご案内するのは、 kubeadm を用い、高可用性 Kubernetes クラスタをどのようにインストールしてセットアップするかです。
このドキュメントではセットアップ手順の流れを紹介しますが、 kubeadm 以外のハードウェアのプロビジョニング、複数のシステムの設定、負荷分散は扱いません。
メモ: このガイドは可能性のあるソリューションの1つであり、高可用性クラスタを構成するには他にも多くの方法があります。皆さんにとって適切なソリューションがあれば、そちらをお使いください。まだコミュニティに採用されていない良いソリューションがあれば、どうぞ自由にご提案ください。
準備
- 3台のマシンでマスタに合致する kubeadm 最小環境 を構成
- 3台のマシンでワーカーに合致する kubeadm 最小環境 を構成
- オプション: 少なくとも3台のマシンで kubeadm 最小環境 etcd を稼働するための専用ノードを構築(詳細は後述)
- マシンごとに 1GB 以上のメモリ (アプリケーションが必要としないなら、少なくとも可)
- クラスタ内の全てのマシンがネットワーク上で完全に疎通(パブリックか、プライベートネットワークも構わない)
マスタ上にインストールする準備
増す手向けのホストをプロビジョン(作成)したら、 インストール・ガイド に従って kubeadm と依存関係をインストールします。ステップの最後では、各マスタ上に全ての依存関係のインストールが完了しているでしょう。
HA etcd クラスタのセットアップ
高可用性オプションでは、etcd クラスタをどこで動かすか決める必要があります。クラスタを構成するのは、少なくとも3つのメンバです。私たちが推奨するのは以下のモデルです:
- それぞれの計算ノード(仮想マシン)で etcd クラスタを稼働
- マスタ・ノード上で etcd クラスタを稼働
より高い性能と優れたハードウェア分離を提供するオプションのためには、より費用がかかり、追加のサポート要素も必要となります。
オプション 1: CoreOS のハードウェア推奨環境 を満たす3つの仮想マシンを作成。簡単に扱うため、それぞれ etcd0
、 etcd1
、etcd2
と呼ぶ。
オプション 2: こちらは次のステップにスキップできます。マスタ・ノード上で etcd を稼働するため、このガイドは etcd0
、 etcd1
、 etcd2
を master0
、master1
、master2
に置き換えます。
etcd CA 証明書を作成
-
cfssl
とcfssljson
のインストール:curl -o /usr/local/bin/cfssl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 curl -o /usr/local/bin/cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 chmod +x /usr/local/bin/cfssl*
-
etcd0
に SSH し、以下の通りに実行:mkdir -p /etc/kubernetes/pki/etcd cd /etc/kubernetes/pki/etcd cat >ca-config.json <<EOF { "signing": { "default": { "expiry": "43800h" }, "profiles": { "server": { "expiry": "43800h", "usages": [ "signing", "key encipherment", "server auth", "client auth" ] }, "client": { "expiry": "43800h", "usages": [ "signing", "key encipherment", "client auth" ] }, "peer": { "expiry": "43800h", "usages": [ "signing", "key encipherment", "server auth", "client auth" ] } } } } EOF
cat >ca-csr.json <<EOF { "CN": "etcd", "key": { "algo": "rsa", "size": 2048 } } EOF
オプション:
ca-csr.json
にnames
セクションを追加できます。
例についての詳細は CFSSL wiki をご覧ください。 -
次に、CA 証明書を生成します:
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
etcd クライアントと証明書の生成
クライアント証明書を正視します。 etcd0
であれば、次のように実行します:
cat >client.json <<EOF
{
"CN": "client",
"key": {
"algo": "ecdsa",
"size": 256
}
}
EOF
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client client.json | cfssljson -bare client
client.pem
と client-key.pem
の両方が作成されます。
SSH アクセスの作成
マシン間に証明書をコピーするため、 scp
での SSH 接続を有効化する必要があります。
-
まず、
etcd1
とetcd2
のための新しいタブをシェルで開きます。3つのマシンに SSH したのを確認し、それから以下のコマンドを実行します(tmux 動機を使えばより素早く行えます。iTerm でcmd+shift+i
を入力します)
:export PEER_NAME=$(hostname) export PRIVATE_IP=$(ip addr show eth1 | grep -Po 'inet \K[\d.]+')
eth1
にはプライベート・ネットワーク用の IPv4 アドレス向けネットワーク・インターフェースを割り当てます。ここはネットワークのセットアップに依存して様々に変わるため、この先に進む前にecho $PRIVATE_IP
を実行してご確認ください。 -
次は、box に対する SSH 鍵を生成します:
bash
ssh-keygen -t rsa -b 4096 -C "<email>"
<email>
の部分は自分のメールアドレスに置き換えるか、何か他のものを書くか、空白文字にします。ここに入力した内容が~/.ssh
のファイルに書かれます。 etcd1
とetcd2
向け公開鍵の内容を表示します:
bash
cat ~/.ssh/id_rsa.pub
最後に、それぞれの出力内用を
etcd0
の~/.ssh/authorized_keys
ファイルに追加します。これにより、対象マシンにetcd1
とetcd2
から SSH を可能にします。
etcd サーバとピア証明書の生成
-
証明書を生成するために、
etcd0
で生成された root CA が各 etcd マシンで必要になります。etcd1
とetcd2
で以下のように実行します:mkdir -p /etc/kubernetes/pki/etcd cd /etc/kubernetes/pki/etcd scp root@<etcd0-ip-address>:/etc/kubernetes/pki/etcd/ca.pem . scp root@<etcd0-ip-address>:/etc/kubernetes/pki/etcd/ca-key.pem . scp root@<etcd0-ip-address>:/etc/kubernetes/pki/etcd/client.pem . scp root@<etcd0-ip-address>:/etc/kubernetes/pki/etcd/client-key.pem . scp root@<etcd0-ip-address>:/etc/kubernetes/pki/etcd/ca-config.json .
<etcd0-ip-address>
の場所にはetcd0
に対する適切なパブリックあるいはプライベート IPv4 アドレスを書きます。 -
これが完了したら、全ての etcd マシン上で以下のコマンドを実行します:
cfssl print-defaults csr > config.json sed -i '0,/CN/{s/example\.net/'"$PEER_NAME"'/}' config.json sed -i 's/www\.example\.net/'"$PRIVATE_IP"'/' config.json sed -i 's/example\.net/'"$PEER_NAME"'/' config.json
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server config.json | cfssljson -bare server cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=peer config.json | cfssljson -bare peer
こちらのデフォルト設定は、ピア名としてのマシンのホスト名や IP アドレスに応じて置き換えます。証明書は適切に作成しているか確認します。エラーがあれば、
config.json
を再調整し、再びcfssl
コマンドを実行します。
以上の結果、次のファイルが作成されます: peer.pem
、 peer-key.pem
、 server.pem
、 server-key.pem
.
etcd_mode
etcd を適切に動かすために、対象となる手順のタブをクリックします。
systemd
-
まず、etcd バイナリをインストールします:
ETCD_VERSION="v3.1.12" curl -sSL https://github.com/coreos/etcd/releases/download/${ETCD_VERSION}/etcd-${ETCD_VERSION}-linux-amd64.tar.gz | tar -xzv --strip-components=1 -C /usr/local/bin/
Kubernetes v1.10 では適切な etcd のバージョンが v3.1.12 なのでご注意ください。Kubernetes の他のバージョンの場合は、changelog をご覧ください。
また、多くの Linux ディストリビューションでは既に etcd がインストールされている場合もあるためご注意ください。その場合はシステムのデフォルトを置き換えます。
-
次に、systemd が使う環境ファイルを生成:
touch /etc/etcd.env echo "PEER_NAME=${PEER_NAME}" >> /etc/etcd.env echo "PRIVATE_IP=${PRIVATE_IP}" >> /etc/etcd.env
-
それから systemd unit ファイルをコピー:
cat >/etc/systemd/system/etcd.service <<EOF [Unit] Description=etcd Documentation=https://github.com/coreos/etcd Conflicts=etcd.service Conflicts=etcd2.service [Service] EnvironmentFile=/etc/etcd.env Type=notify Restart=always RestartSec=5s LimitNOFILE=40000 TimeoutStartSec=0 ExecStart=/usr/local/bin/etcd --name <name> --data-dir /var/lib/etcd --listen-client-urls http://localhost:2379 --advertise-client-urls http://localhost:2379 --listen-peer-urls http://localhost:2380 --initial-advertise-peer-urls http://localhost:2380 --cert-file=/etc/kubernetes/pki/etcd/server.pem --key-file=/etc/kubernetes/pki/etcd/server-key.pem --client-cert-auth --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.pem --peer-cert-file=/etc/kubernetes/pki/etcd/peer.pem --peer-key-file=/etc/kubernetes/pki/etcd/peer-key.pem --peer-client-cert-auth --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.pem --initial-cluster <etcd0>=https://<etcd0-ip-address>:2380,<etcd1>=https://<etcd1-ip-address>:2380,<etcd2>=https://<etcd2-ip-address>:2380 --initial-cluster-token my-etcd-token --initial-cluster-state new [Install] WantedBy=multi-user.target EOF
<etcd0-ip-address>
、<etcd1-ip-address>
、<etcd2-ip-address>
を適切な IPv4 アドレスに置き換えてください。<name>
は適切な etcd メンバ名に置き換えます。実際の各マシンのホスト名にあわせ、必要に応じて--listen-client-urls
、--advertise-client-urls
、--listen-peer-urls
、--initial-advertise-peer-urls
を置き換えます。各マシンの実際のホスト名にあわせて<etcd0>
、<etcd1>
、<etcd2>
を置き換えます。各マシン間は DNS を用いて接続できるようにする必要があるため、/etc/hosts
にレコードを追加します。 -
最後に etcd を起動:
systemctl daemon-reload systemctl start etcd
-
起動が成功しているかどうかを確認:
systemctl status etcd
Static Pods(静的な Pod)
メモ: サポートしているのは kubelet のインストールに必要な、全ての依存関係が入っているノードのみです。マスタ・ノード上に etcd を動かす場合、このセットアップは既に完了しています。専用ノードで etcd を動かす場合は、systemd を用いるか、あるいは専用 etcd マシン向けの インストール・ガイド をご覧ください。
マニフェスト・ファイルを生成するため、以下の手順を実行します:
cat >/etc/kubernetes/manifests/etcd.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
labels:
component: etcd
tier: control-plane
name: <podname>
namespace: kube-system
spec:
containers:
- command:
- etcd --name <name>
- --data-dir /var/lib/etcd
- --listen-client-urls http://localhost:2379
- --advertise-client-urls http://localhost:2379
- --listen-peer-urls http://localhost:2380
- --initial-advertise-peer-urls http://localhost:2380
- --cert-file=/certs/server.pem
- --key-file=/certs/server-key.pem
- --client-cert-auth
- --trusted-ca-file=/certs/ca.pem
- --peer-cert-file=/certs/peer.pem
- --peer-key-file=/certs/peer-key.pem
- --peer-client-cert-auth
- --peer-trusted-ca-file=/certs/ca.pem
- --initial-cluster etcd0=https://<etcd0-ip-address>:2380,etcd1=https://<etcd1-ip-address>:2380,etcd2=https://<etcd2-ip-address>:2380
- --initial-cluster-token my-etcd-token
- --initial-cluster-state new
image: k8s.gcr.io/etcd-amd64:3.1.10
livenessProbe:
httpGet:
path: /health
port: 2379
scheme: HTTP
initialDelaySeconds: 15
timeoutSeconds: 15
name: etcd
env:
- name: PUBLIC_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: PRIVATE_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: PEER_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
volumeMounts:
- mountPath: /var/lib/etcd
name: etcd
- mountPath: /certs
name: certs
hostNetwork: true
volumes:
- hostPath:
path: /var/lib/etcd
type: DirectoryOrCreate
name: etcd
- hostPath:
path: /etc/kubernetes/pki/etcd
name: certs
EOF
置き換えを確認します:
* <podname>
は実行するノード名です(例: etcd0
、 etcd1
、 etcd2
)
* <etcd0-ip-address>
、 <etcd1-ip-address>
、 <etcd2-ip-address>
は etcd を稼働するホストのパブリック IPv4 です
lb_mode
etcd を適切に動かすために、対象となる手順のタブをクリックします。
クラウド"
クラウド事業者のソリューション例:
ロードバランサから master0
の port 6443 に対して径路があるかを確認します。これは kubeadm がロードバランサの IP アドレスでヘルスチェックを行うためです。そのため master0
のセットアップを個別に第一に行う必要があり、他のマスタで apiserver を実行しなければ、 kubeadm が継続して応答しない場合もああります。
可能であれば、「最小コネクション」(least connections)のような小さな負荷分散アルゴリズムを用い、ヘルスチェックを使って応答しないノードは振り分け先からは除外します。ほとんどの事業者ではこの機能を提供しています。
オンサイト
オンサイト環境では、物理ロードバランサを利用できない場合があります。そのかわりに、仮想 IP で正常なマスタ・ノードを示せられます。そのためには、ロードバランサを使うもの、使わないものを含め、 Keepalived、Pacemaker などを含む多くのソリューションがあります。
ここでは例として keepalived をベースとした簡単なセットアップを紹介します。環境への依存や必要とするものにより、異なったソリューションがあります。以下の設定は負荷分散を使わない アクティブ/パッシブ のフェイルオーバです。必要であれば、HAProxy 、 Nginx などをマスタ・ノード上でセットアップし、簡単に負荷分散も追加できます(本ガイドでは扱いません)。
keepalived のインストールは、ディストリビューションのパッケージ・マネージャを使うなどします。以下の設定はバージョン
1.3.5
が対象ですが、おそらく他のバージョンでも動作するでしょう。対象ノードが起動時に自動的に起動するよう、設定が有効かどうか(chkconfig、systemd 等)ご確認ください。-
全てのマスタ・ノード上で設定ファイル /etc/keepalived/keepalived.conf を作成し、以下の内容にします:
! keepalived用設定ファイル global_defs { router_id LVS_DEVEL } vrrp_script check_apiserver { script "/etc/keepalived/check_apiserver.sh" interval 3 weight -2 fall 10 rise 2 } vrrp_instance VI_1 { state <STATE> interface <INTERFACE> virtual_router_id 51 priority <PRIORITY> authentication { auth_type PASS auth_pass 4be37dc3b4c90194d1600c483e10ad1d } virtual_ipaddress { <VIRTUAL-IP> } track_script { check_apiserver } }
セクション中の
vrrp_instance VI_1
は、皆さんの環境にあわせて数行を書き換えます:
* `state` は `MASTER` (1つめのマスタ・ノード上) か `BACKUP` (その他のマスタ・ノード上) のどちらかです。
* `interface` は仮想 IP を割り当てる既存のパブリック/インターフェースです(通常は1番目のインターフェース)。
* `priority` には1つめのマスタ・ノードが他より高くなるべきです。例:101 であれば、他のノードは 100 など低い値に。
* `auth_pass` には何らかのランダムな文字列を入れます。
* `virtual_ipaddresses` にはマスタ・ノード用の仮想 IP を含めるべきです。
-
全てのマスタ・ノード上にヘルスチェック用のスクリプト /etc/keepalived/check_apiserver.sh_ をインストールします:
#!/bin/sh errorExit() { echo "*** $*" 1>&2 exit 1 } curl --silent --max-time 2 --insecure https://localhost:6443/ -o /dev/null || errorExit "Error GET https://localhost:6443/" if ip addr | grep -q <VIRTUAL-IP>; then curl --silent --max-time 2 --insecure https://<VIRTUAL-IP>:6443/ -o /dev/null || errorExit "Error GET https://<VIRTUAL-IP>:6443/" fi
<VIRTUAL-IP>
は皆さんの仮想 IP から選んで置き換えます。 Keepalived を再起動します。Kubernetes サービスをまだ起動していなければ、全てのマスタ・ノード上でのヘルスチェック失敗がログに記録されます。1つめのマスタ・ノードが立ち上がれば、間もなく止まります。
etcd 証明書の取得
etcd を専用ノード上で動かす場合は、オプション1 の手順に従ってください。etcd をマスタ上で動かす場合は オプション2 の手順に従いますが、マスタ上で etcd 証明書を既に生成済みの場合は省略できます。
SSH アクセスの作成 セクションの手順に従い、各マスタ・ノード用の SSH 鍵を生成します。この作業が終われば、各マスタでは SSH 鍵が
~/.ssh/id_rsa.pub
に置かれ、etcd0
の~/.ssh/authorized_keys
ファイルにそれぞれ登録されます。-
次の通りに実行します:
mkdir -p /etc/kubernetes/pki/etcd scp root@<etcd0-ip-address>:/etc/kubernetes/pki/etcd/ca.pem /etc/kubernetes/pki/etcd scp root@<etcd0-ip-address>:/etc/kubernetes/pki/etcd/client.pem /etc/kubernetes/pki/etcd scp root@<etcd0-ip-address>:/etc/kubernetes/pki/etcd/client-key.pem /etc/kubernetes/pki/etcd
kubeadm init
を master0
で実行 {#kubeadm-init-master0}
-
kubeadm を実行できるようにするため、まず設定ファイルを書く必要があります:
cat >config.yaml <<EOF apiVersion: kubeadm.k8s.io/v1alpha1 kind: MasterConfiguration api: advertiseAddress: <private-ip> etcd: endpoints: \- https://<etcd0-ip-address>:2379 \- https://<etcd1-ip-address>:2379 \- https://<etcd2-ip-address>:2379 caFile: /etc/kubernetes/pki/etcd/ca.pem certFile: /etc/kubernetes/pki/etcd/client.pem keyFile: /etc/kubernetes/pki/etcd/client-key.pem networking: podSubnet: <podCIDR> apiServerCertSANs: \- <load-balancer-ip> apiServerExtraArgs: apiserver-count: "3" EOF
以下の該当箇所は書き換えます:
<private-ip>
はマスタ・サーバのプライベート IP アドレスです。<etcd0-ip>
、<etcd1-ip>
、<etcd2-ip>
は3つの etcd ノードの IP アドレスです。<podCIDR>
にはポッドの CIDER です。詳細については CNI ネットワークのセクション にあるドキュメントをご覧ください。CNI プロバイダによっては設定が不要な場合もあります。-
<load-balancer-ip>
はロードバランサで設定する仮想 IP です。詳細については マスタ・ロードバランサのセットアップ のセクションをご覧ください。メモ: Kubernetes 1.9 以上を使っている場合は、
apiserver-count: 3
を特別な引数endpoint-reconciler-type: lease
に書き換えられます。より詳しい情報は ドキュメント をご覧ください。 -
これが終われば、kubeadm を実行します:
kubeadm init --config=config.yaml
master1
と master2
上で kubeadm init
を実行
他のマスタ上で kubeadm を実行する前に、 master0
から K8s の CA 証明書をコピーする必要があります。そのためには2つの選択肢があります:
オプション1:scp でコピー
-
SSH アクセスの作成 セクションにある手順に従いますが、
etcd0
ではなくmaster0
のauthorized_keys
ファイルに追加します。 -
それから、こちらを実行します:
scp root@<master0-ip-address>:/etc/kubernetes/pki/* /etc/kubernetes/pki rm apiserver.*
オプション 2: コピー&ペースト
/etc/kubernetes/pki/ca.crt
、 /etc/kubernetes/pki/ca.key
、 /etc/kubernetes/pki/sa.key
、/etc/kubernetes/pki/sa.pub
の各ファイルの内容をコピーし、 master1
と master2
上で各ファイルを手動作成します。
こちらが終われば、前の手順 に従い、kubeadm でコントロール・プレーンをインストールします。
master1
と master2
をロードバランサに追加
kubeadm を他のマスタにプロビジョンしたら、それぞれロードバランサ・プールに追加できます。
CNI ネットワークのインストール
こちら にある手順に従い、ポッド・ネットワークをインストールします。マスタの設定ファイルで指定した pod CIDR のいずれかを適切に設定します。
ワーカーのインストール
次はワーカー・ノードのプロビジョンとセットアップをします。そのためには、少なくとも3台の仮想マシンのプロビジョンが必要です。
- ワーカー・ノードを設定するには、HA ワークロードを行わない こちらと同じ手順に従い に従います。
ワーカーの設定変更
-
kube-apiserver にロードバランサを経由して接続できるよう、kube-proxy を再設定します:
kubectl get configmap -n kube-system kube-proxy -o yaml > kube-proxy-cm.yaml sed -i 's#server:.*#server: https://<masterLoadBalancerFQDN>:6443#g' kube-proxy-cm.yaml kubectl apply -f kube-proxy-cm.yaml --force # restart all kube-proxy pods to ensure that they load the new configmap kubectl delete pod -n kube-system -l k8s-app=kube-proxy
-
kube-apiserver にロードバランサを経由して接続できるよう、kubelet を再設定します:
sudo sed -i 's#server:.*#server: https://<masterLoadBalancerFQDN>:6443#g' /etc/kubernetes/kubelet.conf sudo systemctl restart kubelet