Creating multi master cluster with kubeadm(ver1.14以上)
前回kubeadmでマルチマスターのクラスタ構築をしたが、kubeadm1.14で証明書の発行と配布がされるようになったので試してみた。
document
https://kubernetes.io/docs/setup/independent/install-kubeadm/ https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/ kubeadmのトラブルシューティング
始める前に
- 以下のいずれかを実行している1台以上のマシンを用意
- Ubuntu 16.04+
- CentOS 7
- マシンごとに2 GB以上のRAM(それ以下にすると、アプリケーション用のスペースが狭まる)
- 2 CPU以上
- クラスタ内のすべてのマシン間の完全なネットワーク接続(パブリックまたはプライベートネットワークは問題なし)
- ノードごとに固有のホスト名、MACアドレス、およびproduct_uuid。
- マシンでは特定のポートを開けとく
- スワップ無効(kubeletを正しく動作させるためにスワップを無効にする。)
今回の構成
ホスト名 | 役割 |
---|---|
dev-proxy01 | ロードバランサー(HAProxy) |
dev-master01 | MasterNode |
dev-master02 | MasterNode |
dev-master03. | MasterNode |
dev-worker01 | WorkerNode |
dev-worker02 | WorkerNode |
dev-worker03 | WorkerNode |
クライアントに必要なもの
cfsslとkubectlをインストールする
HAProxyロードバランサーのインストール
3つのKubernetesマスターノードを配置するので、 トラフィックを分散させるためにそれらの前にHAPRoxyロードバランサーを配置する必要がある。
- LBにするサーバにSSHで接続します。
- OS update
$ sudo yum update -y
- HAProxyをインストール
$ sudo yum install haproxy
- 3つのKubernetesマスターノード間でトラフィックを負荷分散するようにHAProxyを設定。
$ sudo vim /etc/haproxy/haproxy.cfg global ... default ... #--------------------------------------------------------------------- # main frontend which proxys to the backends #--------------------------------------------------------------------- frontend kubernetes bind 10.64.20.226:6443 option tcplog mode tcp default_backend kubernetes-master-nodes #--------------------------------------------------------------------- # static backend for serving up images, stylesheets and such #--------------------------------------------------------------------- backend static balance roundrobin server static 127.0.0.1:4331 check #--------------------------------------------------------------------- # round robin balancing between the various backends #--------------------------------------------------------------------- backend kubernetes-master-nodes mode tcp balance roundrobin option tcp-check server dev-master01 10.64.20.223:6443 check server dev-master02 10.64.20.225:6443 check server dev-master03 10.64.20.222:6443 check
- HAProxyを再起動。
$ sudo systemctl restart haproxy
cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg exclude=kube* EOF # Set SELinux in permissive mode (effectively disabling it) setenforce 0 sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes systemctl enable --now kubelet
以下は各kubeノードで実行
sudo visudo
で一般ユーザにroot権限を付与
sudo yum -y install vim
Dockerのインストール
$ sudo yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 $ sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo $ sudo yum install docker-ce docker-ce-cli containerd.io $ sudo systemctl start docker & sudo systemctl enable docker
kubeadmのインストール
まず事前準備として、全ノードで Docker、CLI 等の関連パッケージのインストールと、 クラスタ内で利用するオーバーレイネットワーク用にカーネルパラメータを変更しておきます。
# 必要な依存パッケージのインストール $ sudo yum -y update # リポジトリの登録と更新 $ sudo su - $ cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg exclude=kube* EOF # SELinux disabling it) setenforce 0 sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config # Kubernetes 関連パッケージのインストール yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes systemctl enable --now kubelet # オーバーレイネットワーク用にカーネルパラメータを変更 # RHEL / CentOS 7の一部のユーザーは、iptablesがバイパスされているために # トラフィックが誤ってルーティングされるという問題を報告しています。 # あなたのnet.bridge.bridge-nf-call-iptables設定で1に設定されていることを確認する必要がある cat <<EOF > /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF sysctl --system
kubeadmを使ったHAクラスタの作成
クラスターの初期化とkubeadmでTLS証明書を調査する
マスターノードに1台ログインして以下を実行
- ディレクトリを作成
mkdir /etc/kubernetes/kubeadm
kubeadm-configを作成する。
kubernetesVersion
使用するKubernetesバージョンに設定する必要があります。この例ではstable
を使用。controlPlaneEndpoint
ロードバランサのアドレスまたはDNSとポートを一致させる必要があり。kubeadm、kubelet、kubectl
およびKubernetesのバージョンを一致させることがお勧め。- IPはproxyサーバのIPです。
$ vim /etc/kubernetes/kubeadm/kubeadm-config.yaml apiVersion: kubeadm.k8s.io/v1beta1 kind: ClusterConfiguration kubernetesVersion: stable # REPLACE with `loadbalancer` IP controlPlaneEndpoint: "10.64.20.226:6443" networking: podSubnet: 10.64.0.0/18
- 指定されたupload-certsと設定でクラスタを初期化します。
# kubeadm init \ --config=/etc/kubernetes/kubeadm/kubeadm-config.yaml \ --experimental-upload-certs
この出力をテキストファイルにコピーし。後で他のコントロールプレーンノードをクラスタに参加させるために必要になるのでメモ。
certificate-key
は kubeadm certs secret の復号化を可能にするのでメモ。
You can now join any number of the control-plane node running the following command on each as root: kubeadm join 10.64.20.226:6443 --token ruf1ng.rcjtrdkczkto9t5d \ --discovery-token-ca-cert-hash sha256:d17549120dec4b237497d95a7131b6387f00b1612b58be6341b7ea451f0939d0 \ --experimental-control-plane --certificate-key d54f93a776345163398ec944fc67021517e96f11e3a59fb3d659ba5ab8f60b17
- 利用するユーザで以下を実行。 kubeconfigコマンドを実行する推奨のkubectlアクセス用。
mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
- kube-systemネームスペースのkubeadm-certシークレットを調べる。 etcd、kube-apiserver、およびサービスアカウントの証明書が表示されます。
kubectl get secrets -n kube-system kubeadm-certs -o yaml
ownerReferences: - apiVersion: v1 blockOwnerDeletion: true controller: true kind: Secret name: bootstrap-token-6o49ct uid: c6d15490-55b0-11e9-84b0-fa163e4b8c32
kubeadm
で利用可能なトークンリスト一覧を取得する。6o49ct
が上記のステップの所有者参照であることに注意してください。 これは結合トークンではなく、kubeadm-certsでttlを有効にするプロキシです。 参加するときには、依然としてruf1ng
トークンを使用する必要があります。
$ kubeadm token list TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS 6o49ct.fxxdtesig28iohi5 1h 2019-04-03T12:35:34+09:00 <none> Proxy for managing TTL for the kubeadm-certs secret <none> ruf1ng.rcjtrdkczkto9t5d 23h 2019-04-04T10:35:35+09:00 authentication,signing <none> system:bootstrappers:kubeadm:default-node-token
- CNI-plugin である
calico
を 前のconfigで設定したpodSubnet
にマッチする podのCIDRでインストールする。
kubectl apply -f https://gist.githubusercontent.com/joshrosso/ed1f5ea5a2f47d86f536e9eee3f1a2c2/raw/dfd95b9230fb3f75543706f3a95989964f36b154/calico-3.5.yaml
- NodeのSTATUSが
Ready
であることを確認する。
$ kubectl get nodes NAME STATUS ROLES AGE VERSION dev-master01 Ready master 16m v1.14.0
kube-system
PodがRunningであることを確認する。
$ kubectl get pods -n kube-system NAME READY STATUS RESTARTS AGE calico-node-blstp 1/1 Running 0 13m coredns-fb8b8dccf-7nmlh 1/1 Running 0 16m coredns-fb8b8dccf-jr9nc 1/1 Running 0 16m etcd-dev-master01 1/1 Running 0 15m kube-apiserver-dev-master01 1/1 Running 0 15m kube-controller-manager-dev-master01 1/1 Running 0 15m kube-proxy-sz8cz 1/1 Running 0 16m kube-scheduler-dev-master01 1/1 Running 0 15m
2台目のMaster Nodeを追加する
- メモっておいた以下のコマンドを実行する。
kubeadm join 10.64.20.226:6443 --token ruf1ng.rcjtrdkczkto9t5d \ --discovery-token-ca-cert-hash sha256:d17549120dec4b237497d95a7131b6387f00b1612b58be6341b7ea451f0939d0 \ --experimental-control-plane --certificate-key d54f93a776345163398ec944fc67021517e96f11e3a59fb3d659ba5ab8f60b17
- 上のコマンドが完了したあとは、2台目のMaster Nodeがいることを確認する
$ kubectl get nodes NAME STATUS ROLES AGE VERSION dev-master01 Ready master 39m v1.14.0 dev-master02 Ready <none> 15m v1.14.0
- ROLESがnoneだったので、LABELを付与
$ kubectl label node dev-master02 node-role.kubernetes.io/master= node/dev-master02 labeled $ kubectl get nodes NAME STATUS ROLES AGE VERSION dev-master01 Ready master 41m v1.14.0 dev-master02 Ready master 16m v1.14.0
- Podが作成されていることを確認する
$ kubectl get pods -n kube-system NAME READY STATUS RESTARTS AGE calico-node-blstp 1/1 Running 0 38m calico-node-vprt5 1/1 Running 0 17m coredns-fb8b8dccf-7nmlh 1/1 Running 0 41m coredns-fb8b8dccf-jr9nc 1/1 Running 0 41m etcd-dev-master01 1/1 Running 0 41m etcd-dev-master02 1/1 Running 0 17m kube-apiserver-dev-master01 1/1 Running 0 41m kube-apiserver-dev-master02 1/1 Running 0 17m kube-controller-manager-dev-master01 1/1 Running 1 40m kube-controller-manager-dev-master02 1/1 Running 0 17m kube-proxy-bdwgx 1/1 Running 0 17m kube-proxy-sz8cz 1/1 Running 0 41m kube-scheduler-dev-master01 1/1 Running 1 40m kube-scheduler-dev-master02 1/1 Running 0 17m
新しいTokenを使って3台目のMaster Nodeを追加
ここで3番目のMaster Nodeを最後のMasterとして追加するが、 最初に既存のkubeadmトークンをすべて削除する。 新規で構築する場合は不要だが、これは、Kubernetesクラスターが既に実行されているときにマスターを追加する方法です。
- まず、動いているMasterから全てのTokenを表示
$ kubeadm token list TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS 6o49ct.fxxdtesig28iohi5 1h 2019-04-03T12:35:34+09:00 <none> Proxy for managing TTL for the kubeadm-certs secret <none> ruf1ng.rcjtrdkczkto9t5d 23h 2019-04-04T10:35:35+09:00 authentication,signing <none> system:bootstrappers:kubeadm:default-node-token
- 全ての存在するTokenを削除 kubeadm-certsシークレットの有効期限が切れて削除されたため、以前に記録されたjoinコマンドは機能しません。 暗号化キーは無効になり、joinトークンは機能しなくなります。
kubeadm token delete 6o49ct.fxxdtesig28iohi5 kubeadm token delete ruf1ng.rcjtrdkczkto9t5d
削除されたことを確認
$ kubeadm token list TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS
$ kubeadm token create --ttl 10m --print-join-command kubeadm join 10.64.20.226:6443 --token y5hs8z.nu2my2jhq44b74i5 --discovery-token-ca-cert-hash sha256:d17549120dec4b237497d95a7131b6387f00b1612b58be6341b7ea451f0939d0
- kubeadm initのupload-certsフェーズを実行。
$ sudo su - # kubeadm init phase upload-certs --experimental-upload-certs [upload-certs] Storing the certificates in ConfigMap "kubeadm-certs" in the "kube-system" Namespace [upload-certs] Using certificate key: d0e3299a47812ebe52497e4d47676786c39460b0e137844c87862059f5436f7d
kubeadm join 10.64.20.226:6443 \ --experimental-control-plane \ --certificate-key d0e3299a47812ebe52497e4d47676786c39460b0e137844c87862059f5436f7d \ --token y5hs8z.nu2my2jhq44b74i5 \ --discovery-token-ca-cert-hash sha256:d17549120dec4b237497d95a7131b6387f00b1612b58be6341b7ea451f0939d0
以下は出力の抜粋
This node has joined the cluster and a new control plane instance was created: * Certificate signing request was sent to apiserver and approval was received. * The Kubelet was informed of the new secure connection details. * Control plane (master) label and taint were applied to the new node. * The Kubernetes control plane instances scaled up. * A new etcd member was added to the local/stacked etcd cluster. To start administering your cluster from this node, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config Run 'kubectl get nodes' to see this node join the cluster.
上の出力にあるように kubectl
コマンドを実行できるようにする
$ kubectl get nodes The connection to the server localhost:8080 was refused - did you specify the right host or port? $ mkdir -p $HOME/.kube $ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config $ sudo chown $(id -u):$(id -g) $HOME/.kube/config
Master Nodeとして追加されたことを確認
$ kubectl get nodes NAME STATUS ROLES AGE VERSION dev-master01 Ready master 80m v1.14.0 dev-master02 Ready master 56m v1.14.0 dev-master03 Ready master 74s v1.14.0
workerノードのクラスタ組み込み
さきほどの kubeadm join
のコマンドを --experimental-control-plane
をつけないで 実行。
1台ずつpodが組み込まれて完了したことを確認してから実行していくこと。
実行したら error execution phase preflight: unable to fetch the kubeadm-config ConfigMap: failed to get config map: Unauthorized
とエラーが出た。
# kubeadm join 10.64.20.226:6443 --certificate-key d0e3299a47812ebe52497e4d47676786c39460b0e137844c87862059f5436f7d --token y5hs8z.nu2my2jhq44b74i5 --discovery-token-ca-cert-hash sha256:d17549120dec4b237497d95a7131b6 387f00b1612b58be6341b7ea451f0939d0 [preflight] Running pre-flight checks [WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/ [preflight] Reading configuration from the cluster... [preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml' error execution phase preflight: unable to fetch the kubeadm-config ConfigMap: failed to get config map: Unauthorized
この場合はTokenの期限が切れていることが原因
[root@dev-master03 ~]# kubeadm token list TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS y5hs8z.nu2my2jhq44b74i5 <invalid> 2019-04-03T11:57:38+09:00 authentication,signing <none> system:bootstrappers:kubeadm:default-node-token ym6spi.2e7jfvyaqvtg4wce 1h 2019-04-03T13:49:27+09:00 <none> Proxy for managing TTL for the kubeadm-certs secret <none>
再度作り直す
[root@dev-master03 ~]# kubeadm token delete y5hs8z.nu2my2jhq44b74i5 bootstrap token with id "y5hs8z" deleted [root@dev-master03 ~]# kubeadm token create --ttl 10m --print-join-command kubeadm join 10.64.20.226:6443 --token 9drkxn.oyse1f63s715af4g --discovery-token-ca-cert-hash sha256:d17549120dec4b237497d95a7131b6387f00b1612b58be6341b7ea451f0939d0 [root@dev-master03 ~]# kubeadm token list TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS 9drkxn.oyse1f63s715af4g 9m 2019-04-03T12:48:20+09:00 authentication,signing <none> system:bootstrappers:kubeadm:default-node-token ym6spi.2e7jfvyaqvtg4wce 1h 2019-04-03T13:49:27+09:00 <none> Proxy for managing TTL for the kubeadm-certs secret <none>
作り直したTokenを使用してjoinされることを確認
kubeadm join 10.64.20.226:6443 \ --certificate-key d0e3299a47812ebe52497e4d47676786c39460b0e137844c87862059f5436f7d \ --token 9drkxn.oyse1f63s715af4g \ --discovery-token-ca-cert-hash sha256:d17549120dec4b237497d95a7131b6387f00b1612b58be6341b7ea451f0939d0
出力はこんな感じ
[preflight] Running pre-flight checks [WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/ [preflight] Reading configuration from the cluster... [preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml' [kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.14" ConfigMap in the kube-system namespace [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml" [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env" [kubelet-start] Activating the kubelet service [kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap... This node has joined the cluster: * Certificate signing request was sent to apiserver and a response was received. * The Kubelet was informed of the new secure connection details. Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
Nodeとして追加されていることを確認
$ kubectl get nodes NAME STATUS ROLES AGE VERSION dev-master01 Ready master 131m v1.14.0 dev-master02 Ready master 106m v1.14.0 dev-master03 Ready master 51m v1.14.0 dev-worker01 Ready <none> 6m53s v1.14.0 dev-worker02 Ready <none> 3m54s v1.14.0 dev-worker03 Ready <none> 3m42s v1.14.0
ROLESがnoneなのでworkerと付与してもいい。 こんな感じで。
$ kubectl label node dev-worker01 node-role.kubernetes.io/worker= node/dev-worker01 labeled $ kubectl label node dev-worker02 node-role.kubernetes.io/worker= node/dev-worker02 labeled $ kubectl label node dev-worker03 node-role.kubernetes.io/worker= node/dev-worker03 labeled $ kubectl get nodes NAME STATUS ROLES AGE VERSION dev-master01 Ready master 158m v1.14.0 dev-master02 Ready master 134m v1.14.0 dev-master03 Ready master 79m v1.14.0 dev-worker01 Ready worker 34m v1.14.0 dev-worker02 Ready worker 31m v1.14.0 dev-worker03 Ready worker 31m v1.14.0
etcdの冗長化はされないので、するなら別にしないとだめ。 みなさんどうされているか、よければおしえてください。
[hoge@dev-master01 ~]$ kubectl get componentstatus NAME STATUS MESSAGE ERROR scheduler Healthy ok controller-manager Healthy ok etcd-0 Healthy {"health":"true"}