筆者は先日Certified Kubernetes Administrator(以下CKA)を受験しました。
CKAではkubeadmによるクラスタの作成やバージョンアップが出題されます。
勉強用にCompute Engine上でKubernetesクラスタを作成したので手順を残します。
構成
- コントローラー 1台
- ワーカー 1台
- k8sバージョン 1.25(※)
(※)最新版は1.26です。
k8sのバージョンアップもCKAの出題範囲のため、続編で1.25から1.26へのバージョンアップを練習してみます。
コントローラー、ワーカーの構築
k8sのインストール最低要件は以下のとおりです。
- メモリ 2GB以上 (ただし追加のアプリを動作させる余裕ほぼなし)
- CPU 2コア以上
2 GB or more of RAM per machine (any less will leave little room for your apps).
2 CPUs or more.
e2-smallでギリギリ達成しますが、余裕をもたせてe2-mediumとします。
以下がインスタンス設定のスクリーンショットです。
ほぼデフォルト値のままですが、1点変更します。
料金節約のため、Spot VMを使用します。
Spot VMはGoogle側の都合で突然に強制停止される可能性があります。
かわりに利用料金が大幅に安くなります。
勉強や実験用でなく、安定的にkubeadmクラスタを運用したい場合には、通常のインスタンスを使用してください。
インスタンスが起動したら、SSHで接続します。
コントローラー、ワーカー共通
ここからはk8sのドキュメントに沿って操作します。
OS設定
sudo modprobe br_netfilter
以下内容で /etc/sysctl.d/k8s.conf
を作成する。
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
sudo sysctl --system
kubeadmのインストール
ドキュメントの通りです。
続編で1.25から1.26へのバージョンアップを練習するので、あえて1.25を指定してインストールします。
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
sudo curl -fsSLo /etc/apt/keyrings/kubernetes-archive-keyring.gpg
echo "deb [signed-by=/etc/apt/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
sudo apt-get install -y kubelet=1.25.0-00 kubeadm=1.25.0-00 kubectl=1.25.0-00
sudo apt-mark hold kubelet kubeadm kubectl
CRIのインストール
CRIにCRI-Oを使うことにします。
CRI-Oのドキュメントに従い作業します。
なお、rootユーザーでコマンドを実行する想定になっています。
- バージョン等の指定
export OS=Debian_11
export OS=1.25
- インストール
echo "deb [signed-by=/usr/share/keyrings/libcontainers-archive-keyring.gpg] https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
echo "deb [signed-by=/usr/share/keyrings/libcontainers-crio-archive-keyring.gpg] https://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
mkdir -p /usr/share/keyrings
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/Release.key | gpg --dearmor -o /usr/share/keyrings/libcontainers-archive-keyring.gpg
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/Release.key | gpg --dearmor -o /usr/share/keyrings/libcontainers-crio-archive-keyring.gpg
apt-get update
apt-get install cri-o cri-o-runc
- サービス有効化
systemctl enable crio
systemctl start crio
コントローラーでの作業
CNIにCalicoを使うことにします。
Calicoのドキュメントに記載のとおり --pod-network-cidr
オプションを指定します。
sudo kubeadm init --pod-network-cidr=192.168.0.0/16
成功すると以下のような出力を得られます。
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 10.128.0.4:6443 --token z2ktxh.p4pbda2f3r81gaxo \
--discovery-token-ca-cert-hash sha256:47b511ec98be374763eb1dc571c22bfadd9400be6ccde52b5e55f6b0e03e27c3
指示どおり、設定ファイルをコピーします。
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
ノードの情報を取得してみます。
kubectl get node
以下のような出力を得られれば、コントローラーは正常に稼動しています。
NAME STATUS ROLES AGE VERSION
controller Ready control-plane 85m v1.25.0
ワーカーでの作業
ワーカーをクラスターに参加させます。
kubeadm init
実行時に出力された kubeadm join
のコマンドを実行します。
sudo kubeadm join 10.128.0.4:6443 --token z2ktxh.p4pbda2f3r81gaxo \
--discovery-token-ca-cert-hash sha256:47b511ec98be374763eb1dc571c22bfadd9400be6ccde52b5e55f6b0e03e27c3
ふたたびノードの情報を取得してみます。
kubectl get node
以下のような出力を得られれば、ワーカーは正常にクラスターに参加できています。
NAME STATUS ROLES AGE VERSION
controller Ready control-plane 90m v1.25.0
worker Ready <none> 20s v1.25.0
Calicoのセットアップ
公式ドキュメントに記載のとおりです。
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/tigera-operator.yaml
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/custom-resources.yaml
calico~ namespaceが作成されます。
$ kubectl get namespace
NAME STATUS AGE
calico-apiserver Active 53s
calico-system Active 97s
default Active 103m
kube-node-lease Active 103m
kube-public Active 103m
kube-system Active 103m
tigera-operator Active 106s
calico-system namespace内で、複数Podが動作します。
$ kubectl -n calico-system get pod
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-5f9dc85578-lzp7t 1/1 Running 0 2m25s
calico-node-hg8b7 1/1 Running 0 2m26s
calico-node-vkjq6 1/1 Running 0 2m26s
calico-typha-88f68649f-kd2gk 1/1 Running 0 2m26s
csi-node-driver-5zh6x 2/2 Running 0 2m25s
csi-node-driver-ftw9b 2/2 Running 0 2m25s
k8sワークロードのデプロイ
適当なワークロードをデプロイし動作確認します。
今回は traefik/whoami
を使用してみます。
以下のようにPod, Serviceが作成されます。
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
whoami-deploy-6d757cc7f6-9fk6b 1/1 Running 0 7m16s
whoami-deploy-6d757cc7f6-srfwl 1/1 Running 0 7m16s
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 14h
whoami-service NodePort 10.97.181.224 <none> 80:31859/TCP 6m7s
NodePort Serviceのため workerのIP
と kubectl get serviceで表示されたポート
の組み合わせで、アクセスできます。
$ curl http://10.128.0.5:31859
Hostname: whoami-deploy-6d757cc7f6-9fk6b
IP: 127.0.0.1
IP: ::1
IP: 192.168.171.69
IP: fe80::46a:9bff:fe48:c6ef
RemoteAddr: 10.128.0.5:42205
GET / HTTP/1.1
Host: 10.128.0.5:31859
User-Agent: curl/7.74.0
Accept: */*
料金見積もり
以下条件で合計4.3ドル/月でした。
Compute Engine
項目 | 見積もり条件 |
---|---|
スペック | SPOT VM, e2-medium |
インスタンス数 | 2 |
稼動時間 | 2時間/日、7日/週 |
小計 3.22ドル/月
ネットワーク転送 (GCPからインターネット方向)
GCPからインターネットに出る通信(egress)が課金対象です。
利用者から見ると、作成したk8sクラスタからファイルをダウンロードするなどです。
10GBあるとして、
小計 1.08ドル/月
(k8sクラスタを構築し、少々操作する程度ならば、1GBにも達しないでしょう)