前回からだいぶ時間があいてしまいましたが、その2のKubernetes構築編です。 前回組み立てたマシンたちにKubernetesをインストールしました。
あらすじ
前回はWorkerノード用のRaspberry Pi 4 8GBを4台組み立てました。 今回、それとは別のサーバを1台Control Planeとしました。
構築にはkubeadmを使いました。
Control Plane 構築
基本的にドキュメントに従って構築していきます。 kubeadmを使って簡単に構築できました。 kubeadmはKubernetesクラスタを構築するためのツールです。
公式ドキュメント的にはこの辺の内容になります。
- Installing kubeadm | Kubernetes
- Creating a single control-plane cluster with kubeadm | Kubernetes
- Container runtimes | Kubernetes
今回Control Planeとして使うサーバのOSはDebian Busterです。
ネットワーク設定
Kubernetesからiptablesでブリッジのトラフィックを制御できるようにします。
modprobe br_netfilter
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system
Dockerインストール
コンテナを実行するためにDockerをインストールします。 最初はcri-oでやってみたんですが、Kubernetesの最新バージョンに対応していなかったのと、構築でエラーが出たのでさっさと諦めてDockerにしました。
ドキュメントに従ってインストールしていきます。
Container runtimes | Kubernetes
# 普通のDockerインストール
apt remove docker docker-engine docker.io runc
apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/debian \
$(lsb_release -cs) \
stable"
apt update
apt install docker-ce docker-ce-cli containerd.io
# Dockerデーモンの設定
cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
mkdir -p /etc/systemd/system/docker.service.d
systemctl daemon-reload
systemctl restart docker
/etc/docker/daemon.json
のcgroup driverはkubeletと同じにする必要があります。
Dockerのデフォルトはcgroupfs
ですが、kubeadmで構築するとkubeletはsystemd
に設定されるのでsystemd
にあわせます。
systemdのUnitファイルにはいろいろ書いてありますが、kubeletのcgroup driverを変更する場合は/var/lib/kubelet/config.yaml
での設定が推奨のようです。
kubeadmインストール
kubeadm、kubelet、kubectlをインストールします。
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
echo 'deb https://apt.kubernetes.io/ kubernetes-xenial main' > /etc/apt/sources.list.d/kubernetes.list
apt update
apt install -y kubeadm kubelet kubectl
apt-mark hold kubelet kubeadm kubectl
Control Plane初期化
kubeadmでControl Planeを初期化します。
kubeadm init \
--dry-run \
--control-plane-endpoint=kube-master.cf.nownabe.in \
--pod-network-cidr=10.4.0.0/14 \
--service-cidr=10.2.0.0/15 \
--service-dns-domain "kube.cf.nownabe.in"
これはdry runコマンドなので、大丈夫そうなら--dry-run
を消して実行します。
うまくいったら次のようなメッセージが表示されます。
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 control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
kubeadm join kube-master.cf.nownabe.in:6443 --token XXXX \
--discovery-token-ca-cert-hash sha256:XXXX \
--control-plane
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join kube-master.cf.nownabe.in:6443 --token XXXX \
--discovery-token-ca-cert-hash sha256:XXXX
Control Planeは今回この1ノードだけなので、次にやることはこの3つですね。
- 設定コピーしてkubectl使えるようにする
- Podネットワークadd-onデプロイ
- Workerノード追加
設定を/etc/kubernetes/admin.conf
からコピーして、別のマシンからkubectl get po
してみました。
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"13+", GitVersion:"v1.13.11-dispatcher", GitCommit:"2e298c7e992f83f47af60cf4830b11c7370f6668", GitTreeState:"clean", BuildDate:"2019-09-19T22:20:12Z", GoVersion:"go1.11.13", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.3", GitCommit:"2e7996e3e2712684bc73f0dec0200d64eec7fe40", GitTreeState:"clean", BuildDate:"2020-05-20T12:43:34Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
$ kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-66bff467f8-7sr7t 0/1 ContainerCreating 0 21h
kube-system coredns-66bff467f8-sh24v 0/1 ContainerCreating 0 21h
kube-system etcd-sv-1.cf.nownabe.in 1/1 Running 0 21h
kube-system kube-apiserver-sv-1.cf.nownabe.in 1/1 Running 0 21h
kube-system kube-controller-manager-sv-1.cf.nownabe.in 1/1 Running 0 21h
kube-system kube-proxy-t4hgb 1/1 Running 0 21h
kube-system kube-scheduler-sv-1.cf.nownabe.in 1/1 Running
おおー、動いてますね!! 🎉 クライアントのkubectlがやたら古いのが気になりますが、ちゃんとapiserverは動いてそうです。
Workerノード構築
Control Planeができたので、Raspberry PiをWorkerノードとして構築してクラスタに追加していきます。
Raspberry PiにインストールしたOSはRaspberry Pi OS Busterです。
Swap無効化
Raspberry Pi OSではデフォルトだとSwapが有効になっているので無効化します。
dphys-swapfile swapoff
systemctl stop dphys-swapfile
systemctl disable dphys-swapfile
いろいろ
Dockerインストールしたりkubeadmインストールしたりします。 ここはControl Planeとほぼ同じなのでコマンドだけ。
modprobe br_netfilter
modprobe overlay
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system
apt remove docker docker-engine docker.io runc
curl -fsSL get.docker.com | sh
cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
systemctl restart docker
apt 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 https://apt.kubernetes.io/ kubernetes-xenial main
EOF
apt update
apt install -y kubeadm kubelet kubectl
apt-mark hold kubelet kubeadm kubectl
Workerノード初期化
kubeadmで初期化し、クラスタに参加します。 Control Planeをkubeadmで初期化したときに表示されたコマンドを実行するだけです。
kubeadm join kube-master.cf.nownabe.in:6443 --token XXXX \
--discovery-token-ca-cert-hash sha256:XXXX
もしトークンの期限が切れていてエラーになる場合は、Control Planeでトークンを再発行します。
kubeadm token create --print-join-command
トークンの一覧もコマンドで確認できます。
kubeadm token list
無事実行できたら、kubectlで確認してみましょう。 ちゃんと追加されてますね!やった! 👏
$ kubectl get nodes --output wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
kube-worker-1.cf.nownabe.in Ready <none> 31d v1.18.5 10.0.1.101 <none> Raspbian GNU/Linux 10 (buster) 4.19.118-v8+ docker://19.3.12
kube-worker-2.cf.nownabe.in Ready <none> 30d v1.18.4 10.0.1.102 <none> Raspbian GNU/Linux 10 (buster) 4.19.118-v8+ docker://19.3.11
kube-worker-3.cf.nownabe.in Ready <none> 23d v1.18.4 10.0.1.103 <none> Raspbian GNU/Linux 10 (buster) 4.19.118-v8+ docker://19.3.12
kube-worker-4.cf.nownabe.in Ready <none> 23d v1.18.4 10.0.1.104 <none> Raspbian GNU/Linux 10 (buster) 4.19.118-v8+ docker://19.3.12
sv-1.cf.nownabe.in Ready master 31d v1.18.3 10.0.1.1 <none> Debian GNU/Linux 10 (buster) 4.19.0-9-amd64 docker://19.3.11
flannel インストール
最後にNetwork Add-onとしてflannelをインストールしました。 最初にCalico、次にCiliumをインストールしようとしたんですが上手く行かずにflannelになりました。 調べてからインストールすればよかったんですが、Armの64bitに対応できてませんでした。
flannelのインストールは公式で用意されているマニフェストYAMLをapplyでOKです。
curl -O https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kubectl apply -f kube-flannel.yml
するとこんな感じでDaemon Setとしてflannelがデプロイされます。
$ kubectl get po --output wide --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system coredns-66bff467f8-8dspl 1/1 Running 0 20d 10.4.4.2 kube-worker-3.cf.nownabe.in <none> <none>
kube-system coredns-66bff467f8-vfx8d 1/1 Running 0 30d 10.4.2.2 kube-worker-2.cf.nownabe.in <none> <none>
kube-system etcd-sv-1.cf.nownabe.in 1/1 Running 0 31d 10.0.1.1 sv-1.cf.nownabe.in <none> <none>
kube-system kube-apiserver-sv-1.cf.nownabe.in 1/1 Running 0 31d 10.0.1.1 sv-1.cf.nownabe.in <none> <none>
kube-system kube-controller-manager-sv-1.cf.nownabe.in 1/1 Running 193 31d 10.0.1.1 sv-1.cf.nownabe.in <none> <none>
kube-system kube-flannel-ds-amd64-dpw88 1/1 Running 10 31d 10.0.1.1 sv-1.cf.nownabe.in <none> <none>
kube-system kube-flannel-ds-arm-mld8c 1/1 Running 0 23d 10.0.1.104 kube-worker-4.cf.nownabe.in <none> <none>
kube-system kube-flannel-ds-arm-q2z9v 1/1 Running 0 31d 10.0.1.101 kube-worker-1.cf.nownabe.in <none> <none>
kube-system kube-flannel-ds-arm-qfqcs 1/1 Running 2 23d 10.0.1.103 kube-worker-3.cf.nownabe.in <none> <none>
kube-system kube-flannel-ds-arm-wgg4d 1/1 Running 2 30d 10.0.1.102 kube-worker-2.cf.nownabe.in <none> <none>
kube-system kube-proxy-429jm 1/1 Running 0 31d 10.0.1.1 sv-1.cf.nownabe.in <none> <none>
kube-system kube-proxy-55tgl 1/1 Running 0 23d 10.0.1.104 kube-worker-4.cf.nownabe.in <none> <none>
kube-system kube-proxy-f4msl 1/1 Running 0 23d 10.0.1.103 kube-worker-3.cf.nownabe.in <none> <none>
kube-system kube-proxy-fp6d2 1/1 Running 0 30d 10.0.1.102 kube-worker-2.cf.nownabe.in <none> <none>
kube-system kube-proxy-hntn9 1/1 Running 0 31d 10.0.1.101 kube-worker-1.cf.nownabe.in <none> <none>
kube-system kube-scheduler-sv-1.cf.nownabe.in 1/1 Running 190 31d 10.0.1.1 sv-1.cf.nownabe.in <none> <none>
1ヶ月ブログ書くの先延ばしにしてたこともばっちりわかって素晴らしいですね 🙌
おわりに
Kubernetes構築編は以上です。 無事にKubernetesが構築できて満足です 😆
Networkに関してはflannelだけだとNetwork Policyが使えないので、またそのうちなんとかしたいと思います。
次からはいろいろ機能追加していきたいので、まずはGitOpsですかねー。