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-systemPodが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"}