kubeadm について
kubeadm は kubernetes をデプロイするためのツール。公式ドキュメントでも紹介されているツールで、まだベーダ版だが kubernetes クラスタを構築する際には今後はこのツールを使っていくことになる。他には Minikube というツールもあるが、こちらはローカルで kubernetes を構築するためのもので、主に開発者に使われることを想定している。
環境
自分の試した環境は以下のとおり。
- ホストOS: MacOS Sierra
- ゲストOS: Ubuntu 16.04.2 LTS
- VirtualBox 5.1.14
- Vagrant 1.9.1
用意した VM は3つ。マスターノード用に 2vCPU, 4GB の VM が1つ、ワーカーノード用に 1vCPU, 2GB の VM が2つ、それぞれのホスト名は manager, host1, host2 とする。各 VM のデフォルトの NIC はホストへの NAT になっていて、インターネットへのアクセスに使用する。これとは別に private_network を用意し、それぞれの IP アドレスを下記の通り 192.168.33.10, 192.168.33.11, 192.168.33.12 とする。Kubernetes のすべての通信はこの NIC を使用する。
+---------------------------------------------+
| NAT |
+--+-------------------+-------------------+--+
| | |
+---------+-------+ +--------+--------+ +-------+---------+
| enp0s3 10.0.2.15| | enp0s3 10.0.2.15| | enp0s3 10.0.2.15|
| | | | | |
| | | | | |
| | | | | |
| manager | | host1 | | host2 |
| | | | | |
| | | | | |
| enp0s8 | | enp0s8 | | enp0s8 |
| 192.168.33.10 | | 192.168.33.11 | | 192.168.33.12 |
+---------+-------+ +--------+--------+ +-------+---------+
| | |
+--+-------------------+-------------------+--+
| 192.168.33.0/24 |
+---------------------------------------------+
kubeadm インストール
この章で実施している内容をマスター、ワーカーの各ノードで実行する。基本的には公式ドキュメントの最新情報を確認して欲しいが、いくつか補完する。
/etc/hosts
ファイルの編集
各ノードの /etc/hosts
に下記の通り、ホスト名に対応する IP アドレスを追記する。このときループバックアドレス以外の別の IP アドレス (e.g. 10.0.2.15) とホスト名を紐付ける記述はしてはいけない。
manager ノード
192.168.33.10 manager
host1 ノード
192.168.33.11 host1
host2 ノード
192.168.33.12 host2
Docker インストール
Ubuntu 公式リポジトリの docker を使うのが手間がなくて良いが、出来るだけ新しいものを使いたいので自分は docker リポジトリのものを使った。公式ドキュメントでは17.09を指定しているが、kubeadm が公式にサポートしているのは17.03で、kubeadm 実行時に warning も出るので自分は17.03を使った。
Ubuntu リポジトリの Docker を使う場合
$ apt-get update
$ apt-get install -y docker.io
Docker リポジトリの Docker を使う場合
$ apt-get update
$ apt-get install -y \
apt-transport-https \
ca-certificates \
curl \
software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
$ add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
$(lsb_release -cs) \
stable"
$ apt-get update && apt-get install -y docker-ce=17.03.0~ce-0~ubuntu-xenial
kubeadm, kubectl, kubelet インストール
$ apt-get update && apt-get install -y apt-transport-https
$ curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
$ cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
$ apt-get update
$ apt-get install -y kubelet kubeadm kubectl
kubeadm 実行
今回マスターノードが使用する IP アドレスは 192.168.33.10 で、このアドレスを指定するには --apiserver-advertise-address
を使用する。またマニュアルには flannel 使用時には --pod-network-cidr
を指定するようにと記載があるため、そのように指定する。
$ sudo kubeadm init --apiserver-advertise-address=192.168.33.10 --pod-network-cidr=10.244.0.0/16
デプロイ後に表示される kubeadm join
コマンドはメモしておくこと。後で、このコマンドと引数を使ってワーカーノードをクラスタに追加します。
kubeadm join --token 07953d.ad9fc560f05ae297 192.168.33.10:6443 --discovery-token-ca-cert-hash sha256:23b6e03c9d4c3cd752c29f3fb0bb0f04923dd69e39020d995b976f93607316e1
kube config ファイルをコピーする。
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
これで基本的なプロセスのデプロイは完了。 kubectl
コマンドでノードの状態や pod の情報を取得してみる。
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
manager NotReady master 18m v1.8.4
$ kubectl get pods --all-namespaces -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE
kube-system etcd-manager 1/1 Running 0 18m 192.168.33.10 manager
kube-system kube-apiserver-manager 1/1 Running 0 18m 192.168.33.10 manager
kube-system kube-controller-manager-manager 1/1 Running 0 18m 192.168.33.10 manager
kube-system kube-dns-545bc4bfd4-pc5qh 0/3 Pending 0 19m <none> <none>
kube-system kube-proxy-8fzzd 1/1 Running 0 19m 192.168.33.10 manager
kube-system kube-scheduler-manager 1/1 Running 0 18m 192.168.33.10 manager
マスターノードのステータスはまだ NotReady です。これは kube-dns がまだ動いていない、NW が未設定であるためです。
flannel のデプロイ
通常は下記のコマンドを実行すれば終わりですが、問題2 でも取り上げている内容の通り kube-flannel.yml の修正が必要になります。
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/kube-flannel.yml
kube-flannel.yml をダウンロードし、flanneld の起動オプションに NIC 指定を追記します。
command: [ "/opt/bin/flanneld", "--ip-masq", "--kube-subnet-mgr", "--iface=enp0s8"]
編集し終わったら kubectl apply
で NW 設定を適用します。
$ kubectl apply -f kube-flannel.yml
これでノードのステータスは Ready になります。
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
manager Ready master 35m v1.8.4
$ kubectl get pods --all-namespaces -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE
kube-system etcd-manager 1/1 Running 0 34m 192.168.33.10 manager
kube-system kube-apiserver-manager 1/1 Running 0 34m 192.168.33.10 manager
kube-system kube-controller-manager-manager 1/1 Running 0 33m 192.168.33.10 manager
kube-system kube-dns-545bc4bfd4-pc5qh 3/3 Running 0 34m 10.244.0.8 manager
kube-system kube-flannel-ds-tggqx 1/1 Running 0 1m 192.168.33.10 manager
kube-system kube-proxy-8fzzd 1/1 Running 0 34m 192.168.33.10 manager
kube-system kube-scheduler-manager 1/1 Running 0 34m 192.168.33.10 manager
ワーカーノードをクラスタに追加
マスターノードの準備が終わったので、あとは各ノードでメモしておいた join コマンドをそのまま実行していくだけです。
$ sudo kubeadm join --token 07953d.ad9fc560f05ae297 192.168.33.10:6443 --discovery-token-ca-cert-hash sha256:23b6e03c9d4c3cd752c29f3fb0bb0f04923dd69e39020d995b976f93607316e1
完了。
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
host1 Ready <none> 13m v1.8.4
host2 Ready <none> 13s v1.8.4
manager Ready master 52m v1.8.4
問題
今回の構築でいくつか問題にハマったので共有します。
問題1
各 pod の IP アドレスが各ノードのデフォルトインターフェースのアドレスになっている。下記を見てわかる通り manager も host1 もホストに対して NAT をしている NIC がデフォルトのため同じ IP アドレス (10.0.2.15) になってしまっている。この状態だとマスターノードから各ノード上の pod のログが取れないなど色々と支障が出る。
$ kubectl get pods --all-namespaces -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE
kube-system etcd-manager 1/1 Running 0 5m 10.0.2.15 manager
kube-system kube-apiserver-manager 1/1 Running 0 5m 10.0.2.15 manager
kube-system kube-controller-manager-manager 1/1 Running 0 5m 10.0.2.15 manager
kube-system kube-dns-545bc4bfd4-m2cm4 3/3 Running 0 6m 10.244.0.6 manager
kube-system kube-flannel-ds-cljpz 1/1 Running 0 2m 10.0.2.15 manager
kube-system kube-flannel-ds-p9lfd 1/1 Running 0 10s 10.0.2.15 host1
kube-system kube-proxy-cphtp 1/1 Running 0 6m 10.0.2.15 manager
kube-system kube-proxy-hs6b2 1/1 Running 0 10s 10.0.2.15 host1
kube-system kube-scheduler-manager 1/1 Running 0 5m 10.0.2.15 manager
この解決策の1つとして kubelet を起動する際に --node-ip
というオプションで任意の IP アドレスを渡すことができるが、kubeadm では対応してない。指定されていない場合は /etc/hosts
に設定されているホスト名の IP アドレスが使用されるため、あらかじめ各ノードで kubernetes 用に使用する IP アドレスを /etc/hosts
に登録する必要がある。
kubernetesで使用するIPアドレス ホスト名
問題2
Flannel が VXLAN トンネルを張る際にデフォルトの NIC を使う。マシン同士が疎通可能ならそれでも問題はないが、今回のような環境 (NAT) だと VXLAN が張れないので flanneld 起動時に使用する NIC を指定する必要がある。今回は下記のように flannel を適用する際に使用した kube-flannel.yaml を直接編集した。
command: [ "/opt/bin/flanneld", "--ip-masq", "--kube-subnet-mgr", "--iface=xxx" ]
問題3
任意の pod が起動してるノードから、その pod への通信は通るが、別のノードからその pod への通信が通らない。これは Docker v1.13 以降と Flannel の組み合わせのバグで、自分がハマっていたときには未修正だったが、修正はすでにされている。kube-flannel.ymlもこの修正が入ったイメージ (v0.9.1-amd64) が指定されているので、今からやる人は特にハマらないはず。しかし、自分がハマった時は、tcpdump祭りで見つけられず、泣きながら iptables のルールを読んで、flannel のソースコード読んで原因を突き止めたので、v0.9.0 でハマって諦めた人用にメモとして残しておく。