以下のドキュメントを参考にmasterの冗長化をやってみたのでメモしておきます。http://kubernetes.io/docs/admin/high-availability/
ただし、”Kubernetesの高可用性サポートは、エンドツーエンド(e2e)テストでは継続的にテストされていません。”とか書いてあるので利用には注意が必要です。
ドキュメントを参考にmasterのha構成を作りますが、ドキュメントに書かれているpodのyamlは使わず、前回作成した環境 に設定を追加していきます。
構成 システム構成は以下の通り。
参考: http://kubernetes.io/images/docs/ha.svg
Worker NodeからはLoad Balancerを介してMaster Nodeに接続します。通信は全てhttpなのでLBはnginxを使います。LBはawsで構築するならelbとか置いたり環境に合わせて用意すれば良いと思います。Master Nodeは全てアクティブで3Node用意します。Master Nodeはetcdが状態を保持するので、このetcdを3台のクラスタにします。etcdがクラスタになっているのでmasterが1台落ちても動作するという仕組みになっています。今回はこの仕組みの動作確認までをやってみます。
クラスタはmaster3台とminion2台で作って、間にLBを1台はさみます。LBがSPOFなのは無視します。
ip
hostname
service
192.168.33.11
centos-lb-1
nginx
192.168.33.21
centos-master-1
etcd kube-apiserver kube-controller-manager kube-scheduler flanneld
192.168.33.22
centos-master-2
etcd kube-apiserver kube-controller-manager kube-scheduler flanneld
192.168.33.23
centos-master-3
etcd kube-apiserver kube-controller-manager kube-scheduler flanneld
192.168.33.31
centos-minion-1
kube-proxy kubelet flanneld docker
192.168.33.32
centos-minion-2
kube-proxy kubelet flanneld docker
下準備 今回もVagrantで上記の構成を作成します。
Vagrant.configure("2" ) do |config| config.vm.box = "centos/7" config.vm.provision "shell" , inline: <<-SHELL yum install -y wget cat << EOT > /etc/yum.repos.d/virt7-docker-common-release.repo [virt7-docker-common-release] name=virt7-docker-common-release baseurl=http://cbs.centos.org/repos/virt7-docker-common-release/x86_64/os/ gpgcheck=0 EOT yum -y install --enablerepo=virt7-docker-common-release kubernetes flannel echo "192.168.33.11 centos-lb-1 192.168.33.21 centos-master-1 192.168.33.22 centos-master-2 192.168.33.23 centos-master-3 192.168.33.31 centos-minion-1 192.168.33.32 centos-minion-2" >> /etc/hosts setenforce 0 sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/sysconfig/selinux SHELL config.vm.define :lb1 do |node| node.vm.network :private_network , ip: "192.168.33.11" node.vm.provider "virtualbox" do |vb| vb.memory = "1024" end end config.vm.define :master1 do |node| node.vm.network :private_network , ip: "192.168.33.21" node.vm.provider "virtualbox" do |vb| vb.memory = "2048" end end config.vm.define :master2 do |node| node.vm.network :private_network , ip: "192.168.33.22" node.vm.provider "virtualbox" do |vb| vb.memory = "2048" end end config.vm.define :master3 do |node| node.vm.network :private_network , ip: "192.168.33.23" node.vm.provider "virtualbox" do |vb| vb.memory = "2048" end end config.vm.define :minion1 do |node| node.vm.network :private_network , ip: "192.168.33.31" node.vm.provider "virtualbox" do |vb| vb.memory = "2048" end end config.vm.define :minion2 do |node| node.vm.network :private_network , ip: "192.168.33.32" node.vm.provider "virtualbox" do |vb| vb.memory = "2048" end end end
前回同様にkubernetesのレポジトリなどを設定しておきます。firewalldが起動してあるのであれば、ここで停止しておきます。
サーバを起動します。
masterの設定 まずはmasterでetcdのクラスタが作りたいので、centos-master-[123]でetcdの設定をします。 centos-master-1から設定します。root$ yum install etcd -y
以下の様にetcdの設定ファイルに記述します。 ETCD_NAMEでノード毎に名前をつけて、クラスタのメンバー情報を記述します。
root$ grep -v "^#" /etc/etcd/etcd.conf ETCD_NAME=master1 ETCD_DATA_DIR="/var/lib/etcd/default.etcd" ETCD_LISTEN_PEER_URLS="http://centos-master-1:2380" ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379" ETCD_INITIAL_ADVERTISE_PEER_URLS="http://centos-master-1:2380" ETCD_INITIAL_CLUSTER="master1=http://centos-master-1:2380,master2=http://centos-master-2:2380,master3=http://centos-master-3:2380" ETCD_INITIAL_CLUSTER_STATE="new" ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" ETCD_ADVERTISE_CLIENT_URLS="http://0.0.0.0:2379"
設定が終わったらetcdを起動します。root$ systemctl start etcd
centos-master-[23]はcentos-master-1で作成したetcdに追加するのでETCD_INITIAL_CLUSTER_STATEは設定せずに起動します。
master2設定ファイルは次の通りです。master3も同様に設定します。root$ grep -v "^#" /etc/etcd/etcd.conf ETCD_NAME=master2 ETCD_DATA_DIR="/var/lib/etcd/default.etcd" ETCD_LISTEN_PEER_URLS="http://centos-master-2:2380" ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379" ETCD_INITIAL_ADVERTISE_PEER_URLS="http://centos-master-2:2380" ETCD_INITIAL_CLUSTER="master1=http://centos-master-1:2380,master2=http://centos-master-2:2380,master3=http://centos-master-3:2380" ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" ETCD_ADVERTISE_CLIENT_URLS="http://0.0.0.0:2379"
master2, master3のetcdを起動します。起動するだけでクラスタにメンバーとして追加されます。root$ systemctl start etcd
起動後、etcdが正しく動作しているか確認します。正しく設定できている場合は次の様にクラスタのメンバーが表示されることが確認できるはずです。
root$ etcdctl member list 7e58aa0ad17c572: name=master2 peerURLs=http://centos-master-2:2380 clientURLs=http://0.0.0.0:2379 isLeader=false 3708325235b44bf0: name=master3 peerURLs=http://centos-master-3:2380 clientURLs=http://0.0.0.0:2379 isLeader=false a49d68bfe3a3090b: name=master1 peerURLs=http://centos-master-1:2380 clientURLs=http://0.0.0.0:2379 isLeader=true root$ etcdctl cluster-health member 7e58aa0ad17c572 is healthy: got healthy result from http://0.0.0.0:2379 member 3708325235b44bf0 is healthy: got healthy result from http://0.0.0.0:2379 member a49d68bfe3a3090b is healthy: got healthy result from http://0.0.0.0:2379 cluster is healthy
master1がLeaderとなっていることが確認できます。
試しに、ETCDのクラスタに読み書きしてみます。
root@centos-master-1$ etcdctl set foo bar bar root@centos-master-2$ etcdctl get foo bar
正しく動作している場合は、centos-master-1でfoo=barと書き込みするとcentos-master-2でfooをgetするとbarと書き込んだ内容が表示されます。
etcdのクラスタ設定は完了したのでmasterの設定をしていきます。
etcdにkubernetesの設定をします。
root$ etcdctl mkdir /kube-centos/network root$ etcdctl mk /kube-centos/network/config '{ "Network": "172.30.0.0/16", "SubnetLen": 24, "Backend": { "Type": "vxlan" } }'
centos-master-[123]で以下の設定をします。
root$ cat /etc/kubernetes/config KUBE_ETCD_SERVERS="--etcd-servers=http://centos-master-N:2379" KUBE_LOGTOSTDERR="--logtostderr=true" KUBE_LOG_LEVEL="--v=0" KUBE_ALLOW_PRIV="--allow-privileged=false" KUBE_MASTER="--master=http://centos-master-N:8080"
api-serverの設定。api-serverが接続するetcdはローカルのetcdのみにしておきます。
root$ cat /etc/kubernetes/apiserver KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0" KUBE_ETCD_SERVERS="--etcd-servers=http://127.0.0.1:2379" KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16" KUBE_API_ARGS=""
flanneldの設定。ここもflanneldが参照するetcdはローカルのものだけ指定します。
root$ cat /etc/sysconfig/flanneld FLANNEL_ETCD_ENDPOINTS="http://centos-master-N:2379" FLANNEL_ETCD_PREFIX="/kube-centos/network" FLANNEL_OPTIONS="--iface=eth1"
masterで使うサービスを起動します。root$ for SERVICES in etcd kube-apiserver kube-controller-manager kube-scheduler flanneld; do systemctl restart $SERVICES ; systemctl enable $SERVICES ; systemctl status $SERVICES ; done
LBの設定 centos-lb-1にnginxをインストールします。
root$ yum install -y epel-release root$ yum install -y nginx root$ systemctl enable nginx
次の2つのProxy設定を追加します。
minionのflanneldがmasterのetcdに接続するための設定
minionのkubeletがapi-serverに接続するための設定
root$ cat /etc/nginx/conf.d/api-server.conf upstream api_server { server centos-master-1:8080; server centos-master-2:8080 backup; server centos-master-3:8080 backup; } server { listen 8080; location / { proxy_pass http://api_server; } }
root$ cat /etc/nginx/conf.d/etcd.conf upstream etcd { server centos-master-1:2379; server centos-master-2:2379 backup; server centos-master-3:2379 backup; } server { listen 2379; location / { proxy_pass http://etcd; } }
設定追加後、nginxを起動します。
root$ systemctl start nginx
curlで他のノードから接続するとapi-serverのレスポンスが返ってくることが確認できます。root$ curl centos-lb-1:8080
minionの設定 centos-minion-[12]でminionの設定をします。
まず、minionで使うdockerをインストールします。
root$ yum install -y docker
kubeletの設定をします。ここで、api-serverにはlb経由で接続する設定をしておきます。KUBELET_API_SERVERという設定項目なのに–api-serversと複数形になっているところが謎ですね。KUBELET_HOSTNAMEはhost毎に読み替える必要があります。
KUBELET_ADDRESS="--address=0.0.0.0" KUBELET_HOSTNAME="--hostname-override=centos-minion-1" KUBELET_API_SERVER="--api-servers=http://centos-lb-1:8080" KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest" KUBELET_ARGS=""
flanneldも同様にlbに接続するように設定します。
root$ cat /etc/sysconfig/flanneld FLANNEL_ETCD_ENDPOINTS="http://centos-lb-1:2379" FLANNEL_ETCD_PREFIX="/kube-centos/network" FLANNEL_OPTIONS="--iface=eth1"
minionを登録します。
root$ kubectl config set -cluster default-cluster --server=http://centos-lb-1:8080 root$ kubectl config set -context default-context --cluster=default-cluster --user=default-admin root$ kubectl config use-context default-context
動作確認 まず、nodeが登録されているか確認します。正しく登録されている場合は以下の様に表示されるはずです。
root$ kubectl get nodes NAME STATUS AGE centos-minion-1 Ready 3m centos-minion-2 Ready 3m
前回と同様にdashboardをインストールして動作確認をしてみます。dashboardのyamlはapiserverの部分だけlbのアドレスに書き換えます。
root$ wget https://rawgit.com/kubernetes/dashboard/master/src/deploy/kubernetes-dashboard.yaml root$ vi kubernetes-dashboard.yaml - --apiserver-host=http://192.168.33.11:8080 root$ kubectl create --v=10 -f kubernetes-dashboard.yaml --server http://centos-lb-1:8080
しばらくすると起動するので待ちます。実行直後、Terminatingと表示されましたがすぐに起動を確認できました。
root$ kubectl get pods --all-namespaces -o wide NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE kube-system kubernetes-dashboard-3331431211-5hvh3 0/1 Pending 0 38s <none> centos-minion-2 kube-system kubernetes-dashboard-3331431211-80k42 0/1 Terminating 0 38s <none> centos-minion-2 kube-system kubernetes-dashboard-3331431211-yte49 0/1 Terminating 0 38s <none> centos-minion-1 root$ kubectl get pods --all-namespaces -o wide NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE kube-system kubernetes-dashboard-3331431211-5hvh3 1/1 Running 0 7m 172.30.60.2 centos-minion-2
lbのアドレスhttp://192.168.33.11:8080/ui
に接続するとdashboardが表示されます。
master1を停止 master1を停止してpodを作ってみます。
$ vagrant halt master1 ==> master1: Attempting graceful shutdown of VM... $ vagrant status Current machine states: lb1 running (virtualbox) master1 poweroff (virtualbox) master2 running (virtualbox) master3 running (virtualbox) minion1 running (virtualbox) minion2 running (virtualbox)
root$ etcdctl member list 7e58aa0ad17c572: name=master2 peerURLs=http://centos-master-2:2380 clientURLs=http://0.0.0.0:2379 isLeader=true 3708325235b44bf0: name=master3 peerURLs=http://centos-master-3:2380 clientURLs=http://0.0.0.0:2379 isLeader=false a49d68bfe3a3090b: name=master1 peerURLs=http://centos-master-1:2380 clientURLs=http://0.0.0.0:2379 isLeader=false
master1が落ちたのでmaster2がLeaderになっていることが確認できます。
適当なpodをデプロイしてみます。
$ cat nginx-pod.yaml apiVersion: v1 kind: Pod metadata: name: nginx-pod spec: containers: - name: nginx-container image: nginx ports: - containerPort: 80 root$ kubectl create --v=10 -f nginx-pod.yaml --server http://centos-lb-1:8080 pod "nginx-pod" created
しばらくするとpodがrunningになる。
root$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE nginx-pod 1/1 Running 0 4m 172.30.20.2 centos-minion-1
master1を落としてもmaster2でmasterの機能が動作していることが確認できました。なかなかいい感じですね。
おわり。
参考
http://kubernetes.io/docs/admin/high-availability/
http://kubernetes.io/docs/admin/high-availability/etcd.yaml
http://kubernetes.io/docs/admin/high-availability/kube-scheduler.yaml
http://kubernetes.io/docs/admin/high-availability/kube-controller-manager.yaml
http://kubernetes.io/docs/admin/high-availability/kube-apiserver.yaml
https://coreos.com/etcd/docs/latest/clustering.html
https://coreos.com/etcd/docs/latest/etcd-live-cluster-reconfiguration.html
http://kubernetes.io/docs/user-guide/kubectl/kubectl_api-versions/