高可用性Kubernetes Clusterを構築する-その2

前回に引き継き、Kubernetes Cluster(v1.13)を構築していきます。

最初のControl Plane Nodeのセットアップ

kubeadmで初期設定

1台目のControl Plane Nodeをセットアップします。セットアップ用に以下の内容のkubeadm-config.ymlファイルを作成します。 設定は前回の記事の構成で説明したホストの環境になっています。 advertiseAddressは、ネットワークインターフェイスが複数ある場合に、使用したいインターフェイスを指定します。 podSubnetの指定は、CNIドライバ依存です。今回はkube-routerを使用します。

apiVersion: kubeadm.k8s.io/v1beta1
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: "192.168.33.22"
  bindPort: 6443
---
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: stable
apiServer:
  certSANs:
  - "host1"
controlPlaneEndpoint: "host1:6443"
networking:
  podSubnet: 10.244.0.0/16

次に、kubeadm initコマンドで初期化します。コマンド実行時の最後に、他のノードをJoinする設定(kubeadm join ...)が出力されます。この出力される内容は記録しておいてください。

sudo kubeadm init --config=kubeadm-config.yml

[init] Using Kubernetes version: v1.13.2
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[kubelet-start] Writing kubelet environment file with flags to file \"/var/lib/kubelet/kubeadm-flags.env\"
[kubelet-start] Writing kubelet configuration to file \"/var/lib/kubelet/config.yaml\"
[kubelet-start] Activating the kubelet service
[certs] Using certificateDir folder \"/etc/kubernetes/pki\"
[certs] Generating \"etcd/ca\" certificate and key
[certs] Generating \"etcd/healthcheck-client\" certificate and key
[certs] Generating \"apiserver-etcd-client\" certificate and key
[certs] Generating \"etcd/server\" certificate and key
[certs] etcd/server serving cert is signed for DNS names [host2 localhost] and IPs [192.168.33.22 127.0.0.1 ::1]
[certs] Generating \"etcd/peer\" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [host2 localhost] and IPs [192.168.33.22 127.0.0.1 ::1]
[certs] Generating \"ca\" certificate and key
[certs] Generating \"apiserver-kubelet-client\" certificate and key
[certs] Generating \"apiserver\" certificate and key
[certs] apiserver serving cert is signed for DNS names [host2 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local host1 host1] and IPs [10.96.0.1 192.168.33.22]
[certs] Generating \"front-proxy-ca\" certificate and key
[certs] Generating \"front-proxy-client\" certificate and key
[certs] Generating \"sa\" key and public key
[kubeconfig] Using kubeconfig folder \"/etc/kubernetes\"
[kubeconfig] Writing \"admin.conf\" kubeconfig file
[kubeconfig] Writing \"kubelet.conf\" kubeconfig file
[kubeconfig] Writing \"controller-manager.conf\" kubeconfig file
[kubeconfig] Writing \"scheduler.conf\" kubeconfig file
[control-plane] Using manifest folder \"/etc/kubernetes/manifests\"
[control-plane] Creating static Pod manifest for \"kube-apiserver\"
[control-plane] Creating static Pod manifest for \"kube-controller-manager\"
[control-plane] Creating static Pod manifest for \"kube-scheduler\"
[etcd] Creating static Pod manifest for local etcd in \"/etc/kubernetes/manifests\"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory \"/etc/kubernetes/manifests\". This can take up to 4m0s
[apiclient] All control plane components are healthy after 19.009590 seconds
[uploadconfig] storing the configuration used in ConfigMap \"kubeadm-config\" in the \"kube-system\" Namespace
[kubelet] Creating a ConfigMap \"kubelet-config-1.13\" in namespace kube-system with the configuration for the kubelets in the cluster
[patchnode] Uploading the CRI Socket information \"/var/run/dockershim.sock\" to the Node API object \"host2\" as an annotation
[mark-control-plane] Marking the node host2 as control-plane by adding the label \"node-role.kubernetes.io/master=''\"
[mark-control-plane] Marking the node host2 as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: t5nhqp.gmv92atuy5ckcs1l
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstraptoken] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstraptoken] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstraptoken] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstraptoken] creating the \"cluster-info\" ConfigMap in the \"kube-public\" namespace
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes master has initialized successfully!

To start using your cluster, 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

You should now deploy a pod network to the cluster.
Run \"kubectl apply -f [podnetwork].yaml\" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

You can now join any number of machines by running the following on each node
as root:

  kubeadm join host1:6443 --token t5nhqp.gmv92atuy5ckcs1l --discovery-token-ca-cert-hash sha256:cb9ff5930d75ce0676d19f1ec14b93515d4f23e6294d60cba37da7a10348d164

終了したら、現在ログインしているアカウントでkubectlコマンドを使えるように初期設定します。

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

CNI Pluginの設定

CNI Pluginの初期化を行います。今回は、kube-routerを使います。kube-routerの設定の詳細はこちらを参照してください。

kubectl apply -f https://raw.githubusercontent.com/cloudnativelabs/kube-router/master/daemonset/kubeadm-kuberouter-all-features.yaml

Kube-systemを削除します。

kubectl -n kube-system delete ds kube-proxy
sudo docker run --privileged -v /lib/modules:/lib/modules --net=host k8s.gcr.io/kube-proxy-amd64:v1.10.2 kube-proxy --cleanup

初期化後Kubenetesのpodsを確認し、各Podが起動できているか確認します。 RADYとSTATUSの列を確認して、以下のようになっていれば起動しています。

kubectl get pod -n kube-system -w
NAME                            READY   STATUS    RESTARTS   AGE
coredns-86c58d9df4-fd8wh        1/1     Running   0          3m9s
coredns-86c58d9df4-s2mqx        1/1     Running   0          3m9s
etcd-host2                      1/1     Running   0          2m22s
kube-apiserver-host2            1/1     Running   0          2m5s
kube-controller-manager-host2   1/1     Running   0          2m9s
kube-router-9dmtt               1/1     Running   0          2m16s
kube-scheduler-host2            1/1     Running   0          2m31s

証明書ファイルを他のホストにコピー

以下のように、作成された証明書ファイルを他のControl Plane Nodeにコピーします。 証明書は権限がルートしか参照できないものもあるので、ルートユーザで行います。 ルートユーザから他のホストにUSER環境変数で指定しているユーザでログインできるようにしています。 この例は、suでrootになり、USER環境変数vagrantユーザを指定してscpでコピーしています。

sudo su
export USER=vagrant # customizable
CONTROL_PLANE_IPS="192.168.33.23 192.168.33.24"
for host in ${CONTROL_PLANE_IPS}; do
    scp /etc/kubernetes/pki/ca.crt "${USER}"@$host:
    scp /etc/kubernetes/pki/ca.key "${USER}"@$host:
    scp /etc/kubernetes/pki/sa.key "${USER}"@$host:
    scp /etc/kubernetes/pki/sa.pub "${USER}"@$host:
    scp /etc/kubernetes/pki/front-proxy-ca.crt "${USER}"@$host:
    scp /etc/kubernetes/pki/front-proxy-ca.key "${USER}"@$host:
    scp /etc/kubernetes/pki/etcd/ca.crt "${USER}"@$host:etcd-ca.crt
    scp /etc/kubernetes/pki/etcd/ca.key "${USER}"@$host:etcd-ca.key
    scp /etc/kubernetes/admin.conf "${USER}"@$host:
done

残りホストにログインして設定

残りのhost3, host4にログインし、先ほどコピーした証明書をインストールします。

sudo su
USER=vagrant # customizable
mkdir -p /etc/kubernetes/pki/etcd
mv /home/${USER}/ca.crt /etc/kubernetes/pki/
mv /home/${USER}/ca.key /etc/kubernetes/pki/
mv /home/${USER}/sa.pub /etc/kubernetes/pki/
mv /home/${USER}/sa.key /etc/kubernetes/pki/
mv /home/${USER}/front-proxy-ca.crt /etc/kubernetes/pki/
mv /home/${USER}/front-proxy-ca.key /etc/kubernetes/pki/
mv /home/${USER}/etcd-ca.crt /etc/kubernetes/pki/etcd/ca.crt
mv /home/${USER}/etcd-ca.key /etc/kubernetes/pki/etcd/ca.key
mv /home/${USER}/admin.conf /etc/kubernetes/admin.conf

クラスタに参加

最初のノード設定時にkubeadm initコマンド実行で表示されたjoinコマンドの表示を使用して、以下のようにrootユーザでhost3, host4で実行してクラスタに参加します。 クラスタ用のControl Plane Nodeの場合、--experimental-control-planeオプションをつけて実行します。 あと、--apiserver-advertise-addressオプションは、ネットワークカードが複数ある環境の場合に、接続するネットワークを指定するコマンドです。 ホスト毎にIPアドレスを自ホストの接続するアドレスに変えます。 今回、virtualbox環境で実行しているため、複数のネットワークカードがあります。このためオプションを指定しています。

sudo kubeadm config images pull
kubeadm join host1:6443\
 --token t5nhqp.gmv92atuy5ckcs1l\
 --discovery-token-ca-cert-hash sha256:cb9ff5930d75ce0676d19f1ec14b93515d4f23e6294d60cba37da7a10348d164\
 --experimental-control-plane\
 --apiserver-advertise-address=192.168.33.23

コマンド実行が終わったら、kubectlのコマンド設定を行って、kubectlを動くようにし、以下コマンドでうまく動いているか確認します。

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
kubectl get node

同じ作業を、host4に実行します。終了すれば、Control plane nodeの構築は完了です。

MasterノードにもPodがスケジュールされるようにする

今回はサーバ台数が少ないので、Control Plane Nodeにpodがスケジュールリングされるようにします。

kubectl taint nodes --all node-role.kubernetes.io/master-

以上で終了です。

注:ちゃんとpodをデプロイして動くかどうかの十分な検証はこれからです・・。

参考