おうちKubernetes構築日記その2 Kubernetes構築編

Contents
  1. あらすじ
  2. Control Plane 構築
  3. ネットワーク設定
  4. Dockerインストール
  5. kubeadmインストール
  6. Control Plane初期化
  7. Workerノード構築
  8. Swap無効化
  9. いろいろ
  10. Workerノード初期化
  11. flannel インストール
  12. おわりに

前回 からだいぶ時間があいてしまいましたが、その 2 の Kubernetes 構築編です。 前回組み立てたマシンたちに Kubernetes をインストールしました。

あらすじ

前回は Worker ノード用の Raspberry Pi 4 8GB を 4 台組み立てました。 今回、それとは別のサーバを 1 台 Control Plane としました。

nodes

構築には kubeadm を使いました。

Control Plane 構築

基本的にドキュメントに従って構築していきます。 kubeadm を使って簡単に構築できました。 kubeadm は 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

kubeadm token | Kubernetes

無事実行できたら、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 ですかねー。