Gentooでkubernetesのセットアップに失敗した
事前準備
- 固定 IP 化
- swap を無効化
- docker のインストールと自動起動
cgroup で CPU とメモリーが有効になっている必要がある
Gentoo で OpenRC だと /etc/rc.conf で設定する。
Gentoo側は Cgroup v1 と v2 の設定が選べる(hybrit になるようだ)。 Kubernetes での Cgroup v2 サポートは Docker で Docker Engine 20.10 から実装された模様
2021/10/10 時点の 私の Gentoo の Docker のバージョンを確認した所、20.10.7 だった。 kubernetes は 1.22 から Cgroup v2 をサポートした模様 参考 Kubernetes 1.22 における新機能は?
なぜ失敗しているのか?
kubeletやkubeadmのコンパイルは上手くいく。そういう観点でパッケージメンテナの作業は成功している。 kubeletも起動している。kubeadm –dry-runも正常に終了する。が実際にkubeadmで構築する段階で失敗している。 ここまま検証するより、一度、正常に動作しているkubenetesと比較した方が検証が進みやすそうだったので、構築できたk3s.ioを用いて検証を続けている。
kubernetes をインストールする
gentoo は標準でパッケージが用意されていたので、それでどこまで行けるか確認してみる。
パッケージインストール
app-admin/helm がマスクされていたのでマスクを外す。
cat << EOF | sudo tee -a /etc/portage/package.accept_keywords
app-admin/helm **
EOF
cat /etc/portage/package.accept_keywords
sudo emerge --ask --quiet --verbose --verbose-conflicts app-admin/helm sys-cluster/kubeadm sys-cluster/kubectl sys-cluster/kubelet \
app-emulation/flannel net-firewall/conntrack-tools sys-apps/ethtool net-firewall/ebtables net-misc/socat
kubeadm init を –dry-run で実行、エラーが起きない事を確認する
sudo kubeadm init --dry-run --pod-network-cidr=10.244.0.0/16
cgroup でエラーが起きた
CGROUPS_MEMORY: missing
memory と /proc/cgroup を確認すると memory の enabled を見ると 0 、off になっているようだ。 memory を有効にすることを考える。
cat /proc/cgroups
#subsys_name hierarchy num_cgroups enabled
cpuset 0 16 1
cpu 0 16 1
cpuacct 2 1 1
blkio 3 1 1
memory 0 16 0
devices 4 1 1
freezer 5 1 1
net_cls 6 1 1
perf_event 7 1 1
net_prio 8 1 1
pids 9 1 1
https://zenn.dev/asataka/scraps/89b2d304e00d1e を参考にすると、カーネルパラメータに追加する必要が有る模様。
console=serial0,115200 console=tty1 root=PARTUUID=xxxx rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles cgroup_enable=memory cgroup_memory=1
なるほど。Gentoo ではどこで設定するか。 /etc/grub? /boot/grub? あたりを探すが見つからず。 GenPi64 の場合、他ラズパイと同様に /boot/cmdline.txt があった。
cgroup_enable=memory cgroup_memory=1
を追記する。下記のように memory が有効になった。
sudo cat /proc/cgroups
#subsys_name hierarchy num_cgroups enabled
cpuset 2 4 1
cpu 3 4 1
cpuacct 4 4 1
blkio 5 4 1
memory 6 4 1
devices 7 1 1
freezer 8 4 1
net_cls 9 4 1
perf_event 10 4 1
net_prio 11 4 1
pids 12 4 1
conntrack が見つからない
[ERROR FileExisting-conntrack]: conntrack not found in system path
パッケージを追加する
sudo emerge --ask net-firewall/conntrack-tools
kubelet を自動起動する方法
[WARNING Service-Kubelet]: kubelet service is not enabled, please run 'rc-update add kubelet default'
というエラーが出た。親切だ… kubelet を自動起動しろとの指示。 しかも Gentoo なので rc-update でやれと出してくれてる。
sudo rc-update add kubelet default
他エラー、下記は出ていても kubeadm init –dry-run は成功する。
[WARNING FileExisting-ebtables]: ebtables not found in system path
[WARNING FileExisting-ethtool]: ethtool not found in system path
[WARNING FileExisting-socat]: socat not found in system path
足りないパッケージを追加する。
sudo emerge sys-apps/ethtool net-firewall/ebtables net-misc/socat
[WARNING SystemVerification]: missing optional cgroups: hugetlb について調査
カーネルで CONFIG_HUGETLBFS が有効にされていなかった。使う場合、カーネルをリコンパイルする必要があると思われる(私は未検証)
zcat /proc/config.gz | grep HUGE
CONFIG_SYS_SUPPORTS_HUGETLBFS=y
CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
CONFIG_HAVE_ARCH_HUGE_VMAP=y
# CONFIG_TRANSPARENT_HUGEPAGE is not set
# CONFIG_HUGETLBFS is not set
その際には
- CONFIG_HUGETLBFS
- CONFIG_HUGETLB_PAGE
を有効にする必要がある。 参考 G.1 HugePages の概要
Linuxシステムによっては、HugePagesがデフォルトでサポートされていません。
このようなシステムの場合、CONFIG_HUGETLBFSおよびCONFIG_HUGETLB_PAGE構成オプションを使用してLinuxカーネルを構築します。
CONFIG_HUGETLBFSは「File Systems」の下にあり、CONFIG_HUGETLB_PAGEはCONFIG_HUGETLBFSを選択すると選択されます。
また /boot/cmdline.txt によるカーネルパラメータに
cgroup_enable=hugetlb
を追記し、 /proc/cmdline と /proc/sys/vm/nr_hugepages あたりを確認する。 参考 HugePages の利用
kubeadm init を –dry-run でエラーが消えた。ので、実際に実行する。
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
エラーが出てしまった…
kuberet が起動できてない模様。
kaoru@kubernetes-master ~> sudo kubeadm init --pod-network-cidr=10.244.0.0/16
[init] Using Kubernetes version: v1.22.2
[preflight] Running pre-flight checks
[WARNING SystemVerification]: missing optional cgroups: hugetlb
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [kubernetes kubernetes-master kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 10.10.254.20]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [kubernetes-master localhost] and IPs [10.10.254.20 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [kubernetes-master localhost] and IPs [10.10.254.20 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[kubelet-check] Initial timeout of 40s passed.
[kubelet-check] It seems like the kubelet isn't running or healthy.
[kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get "http://localhost:10248/healthz": dial tcp [::1]:10248: connect: connection refused.
[kubelet-check] It seems like the kubelet isn't running or healthy.
[kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get "http://localhost:10248/healthz": dial tcp [::1]:10248: connect: connection refused.
[kubelet-check] It seems like the kubelet isn't running or healthy.
[kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get "http://localhost:10248/healthz": dial tcp [::1]:10248: connect: connection refused.
[kubelet-check] It seems like the kubelet isn't running or healthy.
[kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get "http://localhost:10248/healthz": dial tcp [::1]:10248: connect: connection refused.
[kubelet-check] It seems like the kubelet isn't running or healthy.
[kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get "http://localhost:10248/healthz": dial tcp [::1]:10248: connect: connection refused.
Unfortunately, an error has occurred:
timed out waiting for the condition
This error is likely caused by:
- The kubelet is not running
- The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)
If you are on a systemd-powered system, you can try to troubleshoot the error with the following commands:
- 'systemctl status kubelet'
- 'journalctl -xeu kubelet'
Additionally, a control plane component may have crashed or exited when started by the container runtime.
To troubleshoot, list all containers using your preferred container runtimes CLI.
Here is one example how you may list all Kubernetes containers running in docker:
- 'docker ps -a | grep kube | grep -v pause'
Once you have found the failing container, you can inspect its logs with:
- 'docker logs CONTAINERID'
error execution phase wait-control-plane: couldn't initialize a Kubernetes cluster
To see the stack trace of this error execute with --v=5 or higher
Gentoo の起動スクリプト /etc/init.d/kubelet を見ると、ログは /var/log/kubelet/kubelet.log にある。
I1015 22:27:25.265522 3462 server.go:440] "Kubelet version" kubeletVersion="v1.22.2"
I1015 22:27:25.266567 3462 server.go:600] "Standalone mode, no API client"
I1015 22:27:25.266900 3462 server.go:656] "Failed to get the kubelet's cgroup. Kubelet system container metrics may be missing." err="mountpoint for cpu not found"
I1015 22:27:25.267137 3462 server.go:663] "Failed to get the container runtime's cgroup. Runtime system container metrics may be missing." err="failed to get container name for docker process: mountpoint for cpu not found"
E1015 22:27:25.267444 3462 server.go:294] "Failed to run kubelet" err="failed to run Kubelet: mountpoint for cpu not found"
cgroup cpu へのアクセスができない模様。sudo をつけて起動しているが、そういうことでも無いのか…?
/proc/cgroups を見ると有効になっているようであるが。
cat /proc/cgroups
#subsys_name hierarchy num_cgroups enabled
cpuset 0 45 1
cpu 0 45 1
cpuacct 2 1 1
blkio 3 1 1
memory 0 45 1
devices 4 1 1
freezer 5 1 1
net_cls 6 1 1
perf_event 7 1 1
net_prio 8 1 1
pids 9 1 1
cgroup v2 にしたのが良くないのだろか。
/etc/rc.conf を修正、下記をコメントアウト
rc_cgroup_mode="hybrid"
rc_cgroup_controllers="cpuset cpu memory hugetlb"
kubelet が起動した。kubeadm reset で設定を一旦削除して、kubeadm init し直す。
sudo kubeadm reset
kubeadm init し直してみる。が、エラー。
結論を先に言うと
kubeadm init –v=5 と –v=5 のように出力を増やし、状況を確認した方が良い。
Unfortunately, an error has occurred:
timed out waiting for the condition
This error is likely caused by:
- The kubelet is not running
- The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)
If you are on a systemd-powered system, you can try to troubleshoot the error with the following commands:
- 'systemctl status kubelet'
- 'journalctl -xeu kubelet'
Additionally, a control plane component may have crashed or exited when started by the container runtime.
To troubleshoot, list all containers using your preferred container runtimes CLI.
Here is one example how you may list all Kubernetes containers running in docker:
- 'docker ps -a | grep kube | grep -v pause'
Once you have found the failing container, you can inspect its logs with:
- 'docker logs CONTAINERID'
error execution phase wait-control-plane: couldn't initialize a Kubernetes cluster
To see the stack trace of this error execute with --v=5 or higher
というエラー。 required cgroups disabled というと cgroup にうまくアクセスできていない…?
/var/log/kubelet/kubelet.log を見ると、
Nodes topology is not available, providing CPU topology
CPU topology が取得できていない模様。NUMA 関連か。これで調べると
Cannot read number of sockets correctly, number of sockets set to 0 (ARM64)
ARM64 だと CPU 情報を取得する際に NUMA の情報を取得できない模様。
kubernetes が CPU のトポロジー情報をデフォルトで使い始めたのは 1.18 かららしい Control Topology Management Policies on a node
この機能をオフにするのを試みる。
/etc/kubernetes/kubelet.env
に
KUBELET_ARGS="--cgroup-driver=systemd --fail-swap-on=false --feature-gates='TopologyManager=false'"
と
--feature-gates='TopologyManager=false'
を追加した。駄目だった。 kubeadm reset してから kubeadm init するとこのファイルは再生成される。 それでは kubeadm init のオプションにつけてみる。
sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --feature-gates="TopologyManager=false"
とすると
unrecognized feature-gate key: TopologyManager
というエラー。オプションが見つからない、との事。このオプションが消えてしまったのだろうか。
「–feature-gates オプション自体が駄目なのか?」と
sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --feature-gates=RootlessControlPlane=true
と関係ないフィーチャーオプションをやってみた( kubeadm initのページを参考にした ) これはできるので、 –feature-gates オプション自体は動いてる。
–config で config ファイルを指定できるので、その方法を検証する。
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
で作成すると、設定ファイルが /etc/kubernetes 配下に書き出されている。
また ログを –v=5 で増やした所、下記の出力を見つけた。
I1020 12:13:06.853760 25943 kubelet.go:203] the value of KubeletConfiguration.cgroupDriver is empty; setting it to "systemd"
現状、私は systemd で起動していない。OpenRC なので… systemd ではない時の選択肢は cgroupfs なので、これに変えたい。
/etc/kubernetes/ 配下に関係しそうなファイルがあったが、これは kubernetes v1.22 時点で kubeadm init 時には読み込まれなかった。 例えば /etc/kubernetes/kubelet.env には
KUBELET_ARGS="--cgroup-driver=systemd --fail-swap-on=false --feature-gates='TopologyManager=false'"
という設定があるが、これを cgroup に切り替えて kubeadm init –v=5 を行っても駄目だった。
事前にシェル変数に KUBELET_ARGS を設定しても駄目だった。
–config=configfile.yaml での設定を試みる。
sudo kubeadm init phase kubeconfig kubelet
を実行すると、設定ファイルは /etc/kubernetes/kubelet.conf に出力される。
基本的には
- kube init –config に与える設定ファイルを作る
- kube init –config で起動
- /var/lib/kubelet/config.yaml に設定が書き出されるので反映しているか値を確認 を繰り返す。
kubernetes v 1.22 で systemd から dockerfs に切り替えるのは
kind: ClusterConfiguration
apiVersion: kubeadm.k8s.io/v1beta3
kubernetesVersion: v1.22.2
---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: cgroupfs
という設定ファイルを作り kubeadm init –config でファイルを読み込ませる事で解消した。 エラーは解消したが、まだ起動はしない。
kubelet がリッスンしている IP アドレスが 127.0.0.1 であるのがまずいのか?
IP アドレスを 127.0.0.1 ではなくイーサネットワークの IP アドレスにする
/etc/init.d/kubelet で command_args=" --address 10.10.254.20 " とする。
これでポート 10250 10255 の IP アドレスが変わった。
36035 , 10248 はまだ。
sudo netstat -anp | grep kub
tcp 0 0 127.0.0.1:36035 0.0.0.0:* LISTEN 23680/kubelet
tcp 0 0 127.0.0.1:10248 0.0.0.0:* LISTEN 23680/kubelet
tcp 0 0 10.10.254.20:10250 0.0.0.0:* LISTEN 23680/kubelet
tcp 0 0 10.10.254.20:10255 0.0.0.0:* LISTEN 23680/kubelet
kubelet のログを確認すると エラーが出てる
ひとつひとつ見ていきたい
I0101 09:00:31.090940 2015 server.go:656] "Failed to get the kubelet's cgroup. Kubelet system container metrics may be missing." err="mountpoint for memory not found"
/boot/cmdline.txt に hugeTLB 関連のオプションを最後に追加していた。 これはカーネルで有効になっていない問題だったので削除した所、エラーはでなくなった。
I0101 09:00:31.091170 2015 server.go:663] "Failed to get the container runtime's cgroup. Runtime system container metrics may be missing." err="failed to get container n
ame for docker process: mountpoint for memory not found"
W0101 09:00:34.721791 2015 sysinfo.go:203] Nodes topology is not available, providing CPU topology
I0101 09:00:34.769152 2015 server.go:488] "No api server defined - no events will be sent to API server"
cni.go:239] "Unable to update cni config" err="no networks found in /etc/cni/net.d"
kubelet.go:1453] "No API server defined - no node status update will be sent"
ただkubeadmでinitできない状況は変わりがない。
参考
おうち Kubernetes 構築日記その 2 Kubernetes 構築編 ネットワーク設定のための iptables の設定が参考になった。
Control Plane 初期化 dry-run が参考になる。
kubeadm init kubeadm init のコマンドラインオプションが参考になった。
フィーチャーゲート kubernetes オフィシャルの情報で、フィーチャーが導入されたバージョンなどを確認できる。