JavaScriptを有効にしてください

ラズパイにKubernetesクラスタを構築する(Ubuntu 20.04.3)

 ·  ☕ 9 分で読めます · 👀... ページ閲覧数

概要

セットアップしたラズパイを利用してkubernetesクラスタを構築していく。

kubernetes公式
を参考に進める。

ubuntu 20.04.3 LTS(64bit版)

事前準備

セットアップしたラズパイ君にはDockerが入っていなかったりするので、クラスタを構築するための準備する。
(ラズパイのセットアップで一緒に書けばよかったなーと思うものもある。。)

TimeZoneの設定

1
sudo timedatectl set-timezone Asia/Tokyo

Dockerセットアップ

インストール手順。Docker公式あたりを参考に。。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
$ sudo apt-get update
$ sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

$ echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# パッケージデータベース更新
$ sudo apt update

$ sudo apt-get install docker-ce docker-ce-cli

$ apt-cache madison docker-ce

ログインしていないdockerグループにユーザーを追加する必要がある場合は、次を使用して明示的にそのユーザー名を宣言します。

ラズパイセットアップで作成したユーザをdockerグループに追加する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 追加(ユーザがubuntuの場合)
$ sudo adduser ubuntu docker

# "docker"が追加されたことを確認
$ groups ubuntu
# groups ubuntu
# ubuntu : adm dialout cdrom floppy sudo audio dip video plugdev netdev lxd ubuntu docker

# dockerコマンドがそのまま利用できることを確認する
$ docker -v
# Docker version 20.10.7, build 20.10.7-0ubuntu5~20.04.2

Swapの無効化

kubeletを利用するために、Swapを無効化しておく必要がある。

以下、公式より

Swapがオフであること。kubeletが正常に動作するためにはswapは必ずオフでなければなりません。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$ sudo swapoff -a

$ free -h
              total        used        free      shared  buff/cache   available
Mem:          3.7Gi       804Mi       186Mi       4.0Mi       2.7Gi       2.9Gi
Swap:            0B          0B          0B

$ sudo systemctl --type swap --all
  UNIT LOAD ACTIVE SUB DESCRIPTION
0 loaded units listed.
To show all installed unit files use 'systemctl list-unit-files'.

/etc/fstabファイル修正しないとかしらと思ったが、swapの設定ないのでそのままにした。
rebootして再確認したが結果変わらずだったので問題なさそう。

iptablesの設定

bridgeのトラフィック設定追加

…の前に、br_netfilterがロードされているか確認する。
コマンドの結果が下記のようであればOK(参考:OracleHP)。
ロードされていない時はmodprobe br_netfilterコマンド実行してロードする。

1
2
3
$ lsmod | grep br_netfilter
# br_netfilter           28672  0
# bridge                225280  1 br_netfilter

公式の手順をそのままコピペ。

1
2
3
4
5
6
7

# rootで実行
sudo cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system

一応iptables見てみる(下記はコマンドの結果抜粋)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20

$ sudo iptables -nvL --line-number
Chain FORWARD (policy DROP 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
4        0     0 DOCKER-USER  all  --  *      *       0.0.0.0/0            0.0.0.0/0
5        0     0 DOCKER-ISOLATION-STAGE-1  all  --  *      *       0.0.0.0/0            0.0.0.0/0
6        0     0 ACCEPT     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
7        0     0 DOCKER     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0
8        0     0 ACCEPT     all  --  docker0 !docker0  0.0.0.0/0            0.0.0.0/0
9        0     0 ACCEPT     all  --  docker0 docker0  0.0.0.0/0            0.0.0.0/0

Chain DOCKER-ISOLATION-STAGE-1 (1 references)
num   pkts bytes target     prot opt in     out     source               destination
1        0     0 DOCKER-ISOLATION-STAGE-2  all  --  docker0 !docker0  0.0.0.0/0            0.0.0.0/0
2        0     0 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain DOCKER-ISOLATION-STAGE-2 (1 references)
num   pkts bytes target     prot opt in     out     source               destination
1        0     0 DROP       all  --  *      docker0  0.0.0.0/0            0.0.0.0/0
2        0     0 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0

問題なさそう。

iptablesがnftablesバックエンドを使用しないようにする

wiki.nfttables

nftables is the modern Linux kernel packet classification framework. New code should use it instead of the legacy {ip,ip6,arp,eb}_tables (xtables) infrastructure. For existing codebases that have not yet converted, the legacy xtables infrastructure is still maintained as of 2021. Automated tools assist the xtables to nftables conversion process.

Linux kernel packet classificationはlegacy(iptablesなど)ではなくmodern(nfttables)を利用するようにしてねー。まだモダンに切り替えられていないものもあるからlegacyもメンテナンスしてるよ(2021年時点)ー。ということらしい。

ラズパイに入れたubuntu20.04はどちらがデフォルトなのかしらと思って調べてみたら、how-to-install-nftables-on-ubuntu-20-04-ltsという記事があった。

nftablesのサービスステータスとnftコマンドを試してみたところ、セットアップされてなさそう。

1
2
3
4
5
6
7

$ sudo systemctl status nftables.service
Unit nftables.service could not be found.

$ nft -h
Command 'nft' not found, but can be installed with:
sudo apt install nftables

iptablesコマンドはちゃんと使えた(legacyですよと教えてくれる)。
nfttables利用していないことが確認できたのでOK。

1
2
3
$ iptables
iptables v1.8.4 (legacy): no command specified
Try `iptables -h' or 'iptables --help' for more information.

kubernetesクラスタセットアップ

kubelet, kubeadm, kubectlのインストール

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17

$ sudo apt-get install -y apt-transport-https ca-certificates curl
$ sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg

$ echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

$ sudo apt-get update

# インストール
# インストール可能なバージョンを確認したい時は apt-cache policy kubelet から確認する
$ sudo apt-get install -y kubelet=1.22.2-00 kubeadm=1.22.2-00 kubectl=1.22.2-00

# 意図せずupdateしないように固定化する
$ sudo apt-mark hold kubelet kubeadm kubectl
# kubelet set on hold.
# kubeadm set on hold.
# kubectl set on hold.

Masterノードの構築

試しにやってみる。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=192.168.0.11
[init] Using Kubernetes version: v1.22.2
[preflight] Running pre-flight checks
[preflight] The system verification failed. Printing the output from the verification:
KERNEL_VERSION: 5.4.0-1044-raspi
CONFIG_NAMESPACES: enabled
CONFIG_NET_NS: enabled
CONFIG_PID_NS: enabled
CONFIG_IPC_NS: enabled
CONFIG_UTS_NS: enabled
CONFIG_CGROUPS: enabled
CONFIG_CGROUP_CPUACCT: enabled
CONFIG_CGROUP_DEVICE: enabled
CONFIG_CGROUP_FREEZER: enabled
CONFIG_CGROUP_PIDS: enabled
CONFIG_CGROUP_SCHED: enabled
CONFIG_CPUSETS: enabled
CONFIG_MEMCG: enabled
CONFIG_INET: enabled
CONFIG_EXT4_FS: enabled
CONFIG_PROC_FS: enabled
CONFIG_NETFILTER_XT_TARGET_REDIRECT: enabled (as module)
CONFIG_NETFILTER_XT_MATCH_COMMENT: enabled (as module)
CONFIG_FAIR_GROUP_SCHED: enabled
CONFIG_OVERLAY_FS: enabled (as module)
CONFIG_AUFS_FS: enabled (as module)
CONFIG_BLK_DEV_DM: enabled
CONFIG_CFS_BANDWIDTH: enabled
CONFIG_CGROUP_HUGETLB: not set - Required for hugetlb cgroup.
CONFIG_SECCOMP: enabled
CONFIG_SECCOMP_FILTER: enabled
DOCKER_VERSION: 20.10.7
DOCKER_GRAPH_DRIVER: overlay2
OS: Linux
CGROUPS_CPU: enabled
CGROUPS_CPUACCT: enabled
CGROUPS_CPUSET: enabled
CGROUPS_DEVICES: enabled
CGROUPS_FREEZER: enabled
CGROUPS_MEMORY: missing
CGROUPS_PIDS: enabled
CGROUPS_HUGETLB: missing
	[WARNING SystemVerification]: missing optional cgroups: hugetlb
error execution phase preflight: [preflight] Some fatal errors occurred:
	[ERROR SystemVerification]: missing required cgroups: memory
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher

エラー出た。

memoryの有効化

askubuntu.comに対応方法が書いてあるため、参考に対応する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 一番右の値が"1"(有効)になればOK
$ cat /proc/cgroups | grep memory
memory	0	109	0

# 念の為バックアップとっておく
$ sudo cp -a /boot/firmware/cmdline.txt /tmp/

# ファイルの中身を書き換える
$ sudo vi /boot/firmware/cmdline.txt
# net.ifnames=0 dwc_otg.lpm_enable=0 console=serial0,115200 cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait fixrtc

$ sudo shutdown -r now

# 再起動後、接続し直す
cat /proc/cgroups | grep memory
memory	9	99	1

設定後、再度試してみたがkubeletが正しく起動できていないようで、エラーが出た

kubelet の状態を見てみると起動に失敗してる。

1
2
3
4
5
6
7
8
9
systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
     Loaded: loaded (/lib/systemd/system/kubelet.service; enabled; vendor preset: enabl>
    Drop-In: /etc/systemd/system/kubelet.service.d
             └─10-kubeadm.conf
     Active: activating (auto-restart) (Result: exit-code) since Mon 2021-10-25 02:07:1>
       Docs: https://kubernetes.io/docs/home/
    Process: 7628 ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_A>
   Main PID: 7628 (code=exited, status=1/FAILURE)

そういえばipv6を有効化にしたままだったので無効化する

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# バックアップとっておく
sudo cp -p /etc/sysctl.conf /etc/sysctl.conf_`date +%Y%m%d`

# 末尾に追記する
$ sudo vi /etc/sysctl.conf
# Custom Configure
# Not Use ipv6
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.eth0.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

$ sudo sysctl -p
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.eth0.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

# inet6 の表示がされなくなることを確認
$ ip a

CRI-Oのセットアップ[containerdを利用する場合は不要]

(containerdを利用する場合は不要。気づかずセットアップしてしまったのでメモだけ残す)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
export OS=xUbuntu_20.04
export VERSION=1.22:/1.22.2

echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
echo "deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.list

curl -L https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$VERSION/$OS/Release.key | apt-key add -
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/Release.key | apt-key add -

apt-get update
apt-get install cri-o cri-o-runc

公式の手順ではVERSIONの指定はVERSION=1.18:1.18.3のようになっているが、自分のインストールしたいバージョンの場合VERSION=1.22:/1.22.2のように指定しないとエラーでた。エラーでた時はURLから正しい指定方法を確認するのが良さそう。

また、一部keyがなくてエラーが出たのでimportした。

1
2

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 4D64390375060AA4

CRI-Oにcontainerdを利用するため不要だった。
自動起動したくないので止めておく。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 自動起動対象になっているか確認する(symlinkがあれば対象になってる)
$ sudo ls -l /etc/systemd/system/ | grep crio
lrwxrwxrwx 1 root root   32 Mar 13 03:02 cri-o.service -> /lib/systemd/system/crio.service

# 自動起動無効化する
$ sudo systemctl disable crio
Removed /etc/systemd/system/cri-o.service.
Removed /etc/systemd/system/multi-user.target.wants/crio.service.

# symlinkがremoveされてる
$ sudo ls -l /etc/systemd/system/ | grep crio

# 一応ソケットファイルもmoveしておく
$ sudo mv /var/run/crio/crio.sock /var/run/crio/crio.sock_`date +%Y%m%d`

Masterノードの構築(再)

念の為コントロールプレーンリセットしておく。
CRI-Oを稼働させたままの状態でkubeadm reset実行したら、こんなエラーでた。
Found multiple CRI sockets, please use --cri-socket to select one: /var/run/dockershim.sock, /var/run/crio/crio.sock

複数のCRIソケットファイルがあるので選択しないとダメとのこと。
(恥ずかしながらこの時CRI-Oセットアップする必要なかったことに気がついた。。)

1
kubeadm reset --cri-socket /var/run/dockershim.sock

dockershim.sockは非推奨となっているのでcontainerd使うことにした。
dockerをインストールするとcontainerdもインストールされるとのことで、確認する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13

$ ls /run/containerd/containerd.sock

$ systemctl status containerd
● containerd.service - containerd container runtime
     Loaded: loaded (/lib/systemd/system/containerd.service; enabled; vendor preset: enabled)
     Active: active (running) since Sun 2022-03-13 17:44:36 JST; 14min ago
       Docs: https://containerd.io
   Main PID: 763 (containerd)
      Tasks: 14
     Memory: 66.0M
     CGroup: /system.slice/containerd.service
             └─763 /usr/bin/containerd

よかった。。すでに動いてた。そのままCRIにcontainerdを設定してinitすれば良い。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=192.168.0.11 --cri-socket /run/containerd/containerd.sock
.
.
.
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes control-plane has initialized successfully!

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

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

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/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.0.11:6443 --token ebsz3c.ow8d4kqexul4dfnv \
	--discovery-token-ca-cert-hash sha256:b839bb8a8d798785e9481d652e2bf8f791e490e43cd78797238ee21be600b763

ようやく初期化できたー!ほっ。
ローカルユーザでもクラスタ操作できるように設定しておく。

1
2
3
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

試しにnode一覧表示する。master nodeがcontainerdで、指定したバージョンで起動してる。よかったー。

1
2
3
kubectl get node -o wide
NAME         STATUS   ROLES                  AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
k8s-master   Ready    control-plane,master   24m   v1.22.2   192.168.0.11   <none>        Ubuntu 20.04.3 LTS   5.4.0-1055-raspi   containerd://1.5.5

worker Node追加

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15

$ sudo kubeadm join 192.168.0.11:6443 --token ebsz3c.ow8d4kqexul4dfnv --discovery-token-ca-cert-hash sha256:b839bb8a8d798785e9481d652e2bf8f791e490e43cd78797238ee21be600b763
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

追加してもNotReadyのまま。wokerの情報を取得できてないっぽい。
そういえば仮想ネットワークの設定がまだだったので設定する。

flannelのセットアップ

flannelを利用する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# download manifest
$ wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

# CIDRはデフォ値(`10.244.0.0/16`)のままでOK。特に修正するところなかった。
# 適用
$ kubectl apply -f kube-flannel.yml
#Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
#podsecuritypolicy.policy/psp.flannel.unprivileged created
#clusterrole.rbac.authorization.k8s.io/flannel created
#clusterrolebinding.rbac.authorization.k8s.io/flannel created
#serviceaccount/flannel created
#configmap/kube-flannel-cfg created
#daemonset.apps/kube-flannel-ds created

nodeがNotReady -> Readyになった

1
2
3
4
5

$ kubectl get node -w
NAME         STATUS     ROLES                  AGE     VERSION
k8s-master   Ready      control-plane,master   6h28m   v1.22.2
k8s-node1    Ready      <none>                 21m     v1.22.2
共有

BAMBi
著者
BAMBi
サーバサイド~インフラがメインでフロントも好きです。趣味はアニメ鑑賞、ゲーム、つまみ細工です。