(株)日立製作所 研究開発グループ サービスコンピューティング研究部の井出です。
Kubernetes 構築ツールである Kubespray を用いて Ubuntu 上に containerd ベースの Kubernetes クラスタを構築する方法を紹介します。バージョンはそれぞれ Kubespray 2.17.0、Kubernetes 1.21.5、Ubuntu 20.04、containerd 1.4.9 の想定です。
Kubernetes v1.21 から Kuernetes クラスタの構築に Docker を使うことが非推奨となり、2022 年 4 月リリースの v1.24 からは Docker を用いた Kubernetes クラスタの構築ができなくなる予定です。本件は、まだユーザへの影響度を検討している最中なので、影響の大きさ如何では対応が延期されるかもしれませんが、今のうちに containerd 等を用いた Kubernetes クラスタの構築を試しておくことは有用でしょう。
記事の流れは以下の通りです。
- ip_vsの不足エラーを回避してUbunutu上でKubesprayを実行する
- Kubesprayでcontainerdを用いたKubernetesクラスタを立てる
- containerd でコンテナイメージ取得時に Docker Hub の認証情報を付与する
- まとめ
1. ip_vsのエラーを回避してUbunutu上でKubesprayを実行する
KVM 用など、特定の Ubuntu サーバ上で Kubespray を実行すると、IP Virtual Server が無いとのエラーが出る場合があります。
FATAL: Module ip_vs not found in directory /lib/modules/5.4.0-1023-kvm
これは、linux-image-kvm
などの Kernel に ip_vs
モジュールが含まれていないことが原因です。
uname -a
#Linux foobar 5.4.0-1023-kvm #23-Ubuntu SMP Sat Sep 5 00:49:48 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
modinfo ip_vs
#modinfo: ERROR: Module ip_vs not found.
sudo modprobe ip_vs
#modprobe: FATAL: Module ip_vs not found in directory /lib/modules/5.4.0-1023-kvm
これを解決する場合、 ip_vs
モジュールをビルドして/lib/modules/$KERNEL
に置いても良いですが、Kernel の変更が可能なら、以下のようにlinux-image-generic
の Kernel を入れると楽です。
sudo apt update
sudo apt install linux-image-5.8.0-63-generic
再起動すると Kernel が切り替わりip_vs
を利用可能となります。
sudo reboot
uname -a
#Linux k8s-master00 5.8.0-63-generic #71~20.04.1-Ubuntu SMP Thu Jul 15 17:46:08 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
# ip_vs が使えることを確認
modinfo ip_vs
filename: /lib/modules/5.8.0-63-generic/kernel/net/netfilter/ipvs/ip_vs.ko
license: GPL
srcversion: C19F642DDCE359C9EDF97ED
depends: nf_conntrack,nf_defrag_ipv6,libcrc32c
retpoline: Y
intree: Y
name: ip_vs
vermagic: 5.8.0-63-generic SMP mod_unload modversions
sig_id: PKCS#7
signer: Build time autogenerated kernel key
sig_key: 1B:03:37:42:D8:09:C6:B8:56:26:E7:0A:BC:AB:2C:A2:BB:4C:5D:11
sig_hashalgo: sha512
signature: 86:00:C1:ED:91:71:34:50:0E:3C:49:9A:CB:59:AB:14:6B:1E:27:E9:
(略)
parm: conn_tab_bits:Set connections' hash size (int)
その後は、以降の手順で Kubespray 内の Ansible を実行すると良いでしょう。
2. Kubesprayでcontainerdを用いたKubernetesクラスタを立てる
Kubespray のコンテナランタイムは Docker がデフォルトですが、設定により containerd と CRI-O に切り替えることが可能です(設定方法: containerd、CRI-O)。
そこで、Kubespray で containerd を用いた Kubernetes クラスタを構築する手順を以下に示します。
ただし、Docker Hub へのアクセスが多い環境では、Too Many Request でコンテナイメージの取得に失敗する可能性があるため、先に 3-2. kubelet で認証情報を付与する を実施下さい。
また、OS や CNI の組合せ次第では起動に失敗するため、Ubuntu 20.04 + Calico 以外を利用される場合、KubesprayのCIテスト結果を確認するとよいでしょう。
まず、Kubespray のリポジトリをクローンし、目的のバージョンの tag に移動します
git clone https://github.com/kubernetes-sigs/kubespray.git
cd kubespray
git checkout v2.17.0
デフォルトの設定を任意の名前 (以下では mycluster) でコピーします。
cp -rfp inventory/sample/ inventory/mycluster
Ansible 等のツールをインストールします。
sudo pip3 install -r requirements.txt
# pip3 がない場合は以下で pip3 をインストール
# sudo apt update && sudo apt install python3-pip -y
inventory/mycluster/hosts.ini
に Node の設定を記載します。
Master 2 台、Node 5 台(うち 2 台 Master 兼用)で構築する場合、例えば以下となります。
IP アドレスやユーザ名、ファイルパスは適宜読み替えて下さい。
[all]
k8s-master00 ansible_host=192.168.0.10
k8s-master01 ansible_host=192.168.0.11
k8s-node00 ansible_host=192.168.0.12
k8s-node01 ansible_host=192.168.0.13
k8s-node02 ansible_host=192.168.0.14
[all:vars]
ansible_user=ubuntu ;ユーザ名
ansible_ssh_private_key_file=/home/ubuntu/.ssh/privatekey.pem ;ssh 秘密鍵
[kube-master]
k8s-master00
k8s-master01
[etcd] ;奇数にすること。偶数だと起動エラー(split brain対策)
k8s-master00
k8s-master01
k8s-node00
[kube-node]
k8s-master00
k8s-master01
k8s-node00
k8s-node01
k8s-node02
[k8s-cluster:children]
kube-node
kube-master
containerd を利用するために設定を 2 箇所変更します(Kubespray v2.18 からはデフォルトで変更されているようです)。
-container_manager: docker
+container_manager: containerd
-etcd_deployment_type: docker
+etcd_deployment_type: host
Ansible を実行し、Kubernetes クラスタを構築します(15 分ほどかかります)。
ansible-playbook -i inventory/mycluster/hosts.ini cluster.yml -b -v
2-2. 動作確認
kubectl で Node リソースを取得できるか試します。
kubectl がない場合は snap や asdf で kubectl を取得できます。例えば snap なら以下です。
sudo snap install kubectl
Master サーバから kubectl の認証ファイル(/etc/kubernetes/admin.conf
)を取得し、~/.kube
配下に格納後、IP アドレスを修正します。
ssh -i <ssh_private_key> <user>@<master_server> "sudo cat /etc/kubernetes/admin.conf" > /tmp/kube.config
sed 's|server: https://127.0.0.1:6443|server: https://<master_server>:6443|g' /tmp/kube.config > ~/.kube/kube.config
その後、kubectl を実行すると構築した Kubernetes クラスタの Node リソースが取得できるようになります。
kubectl get nodes
# NAME STATUS ROLES AGE VERSION
# k8s-master00 Ready control-plane,master 20m v1.21.5
# k8s-master01 Ready control-plane,master 19m v1.21.5
# k8s-node00 Ready <none> 17m v1.21.5
# k8s-node01 Ready <none> 17m v1.21.5
# k8s-node02 Ready <none> 17m v1.21.5
3. containerd で Docker Hub の認証をする
Docker Hub は、匿名アカウントによる同一 IP アドレスからのイメージ取得数を制限します。これを回避するにはイメージの取得リクエストに Docker Hub の認証情報を付与する必要があります。
では containerd の場合、どのように認証情報を付与すれば良いのでしょうか? 結論から言うと、Kubernetes の場合は認証情報の付与も Kubernetes が行うので、Docker でも contained でも設定方法は変わりません。
Kubernetes にてコンテナイメージの取得時にアカウント情報を付与するには Pod のimagePullSecret
が有名ですが、クラスタ全体に認証を適用させる場合は、以下 2 種の方法が便利です。
- kubelet で認証情報を付与する
- ServiceAccount の imagePullSecrets を使う
以降でそれぞれ紹介します。
3-1. kubelet で認証情報を付与する
Kubernetes クラスタの構築時に便利な方法です。また、Kubernetes のマニフェストで認証情報を意識したくない場合にも使えます。
kubelet は$HOME/.docker/config.json
($HOME
は kubelet 起動ユーザのホームディレクトリなので一般に/root
となる)など、特定パスに置かれた Docker の設定ファイルを参照し、イメージ取得時に認証情報を付与してくれます(参考)。
このため、以下のような設定ファイルを各 Node に配置すれば裏で認証処理を行ってくれるようになります。このファイルは適当なサーバで docker login をすれば、$HOME/.docker/config.json
として生成されるため、それをコピーしてくると良いでしょう。
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "<username:password をbase64エンコードした値>"
}
}
}
[追記] なお、kubelet の認証設定ならば、/var/lib/kubelet/.dockercfg
などの設定ファイルも認識されますが、Kubespray v2.18 以降は$HOME/.docker/config.json
に認証設定を配置した方が良いと思われます。というのも、Kubespray v2.18 以降、ansible の実行時に containerd の cli である nerdctl を用いた pull テストが追加されたため、nerdctl からも認証設定を認識させる必要があるためです。
3-2. ServiceAccount の imagePullSecrets を使う
ServiceAccount リソースに imagePullSecrets を設定すると、ServiceAccount 配下の Pod へ動的にimagePullSecret
を付与してくれます。Node ごとに認証設定を行うことが困難な場合などに便利な方法です。
以下のようにdefault
Service Account 等にimagePullSecrets
を設定しておくと便利です(参考)。
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}'
ただし、この方法は一度 Kubernetes が起動してからしか適用できないため、Kubernetes を構成するコンテナのイメージ取得には利用できません。起動済みクラスタでアクセス制限の問題が発生し始めたときなどに活用すると良いでしょう。
4. まとめ
本記事では、Kubespray にて Ubuntu 上に containerd を用いた Kubernetes クラスタを構築する方法を紹介しました。
Docker の非推奨化を受け、今後は containerd 活用の機会も増えていくと思います。本記事が皆様のお役に立てば幸いです。