Edited at

kubeadm で kubernetes v1.8 + Flannel をインストール

More than 1 year has passed since last update.


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 ノード


/etc/hosts

192.168.33.10 manager



host1 ノード


/etc/hosts

192.168.33.11 host1



host2 ノード


/etc/hosts

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 指定を追記します。


kube-flannel.yaml

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 に登録する必要がある。


/etc/hosts

kubernetesで使用するIPアドレス ホスト名



問題2

Flannel が VXLAN トンネルを張る際にデフォルトの NIC を使う。マシン同士が疎通可能ならそれでも問題はないが、今回のような環境 (NAT) だと VXLAN が張れないので flanneld 起動時に使用する NIC を指定する必要がある。今回は下記のように flannel を適用する際に使用した kube-flannel.yaml を直接編集した。


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 でハマって諦めた人用にメモとして残しておく。