雑に作るkubernetesクラスタ with cri-o & Cilium
概要
本家kubernetesの復習も兼ねて構築手順をまとめた記事です。
開発環境?
構築する環境はこんなかんじ
control-plane
- CPU: 2vCPU
- RAM: 2GB
- DISK: 60GB
- OS: Ubuntu 24.04
kubernetes version : v1.32
CRI-O version : v1.32
Cilium version : v1.17.2
簡易的なk8sクラスタなのでシングルノード構成で作ります
kubernetesの最低要件はこちらです
- 1台当たり2core,2GB以上
- すべてのノード間で通信可能であること
- swapがオフであること
- 特定のポートが開いていること
CRI(コンテナランタイムインターフェース)
コンテナを動かすためのインタフェースとなるものをインストールする。
kubernetesが公式で利用可能なランタイムは次のとおりですわ
- Docker
- containerd
- cri-o
今回は使ったことがないcri-oで組んでみる。
cri-oはdocker,containerdより軽量なkubernetes特化のコンテナランタイムらしい。
余談 : ずっと勘違いしてたけどcri-oって大文字じゃなくて小文字なのね
CNI(コンテナネットワークインターフェース)
コンテナ間のネットワークを管理するプラグインです。
今回使用するCiliumとは別でcalicoなんてものもあるらしい。
構築
kubernetesとCRIのインストール
基本的には公式ページに書かれてる手順と変わらないはず。
rootユーザかsudoで実行することを忘れずに!
面倒ならsudo su -
なりsudo -iu root
でユーザ変更してもろて
1. 必要なパッケージのインストール
apt update
apt install -y software-properties-common curl
2. バージョン宣言
KUBERNETES_VERSION=v1.32
CRIO_VERSION=v1.32
3. kubernetesとcri-oのリポジトリを登録
# kubernetes repos
curl -fsSL https://pkgs.k8s.io/core:/stable:/$KUBERNETES_VERSION/deb/Release.key |
gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/$KUBERNETES_VERSION/deb/ /" |
tee /etc/apt/sources.list.d/kubernetes.list
# cri-o repos
curl -fsSL https://download.opensuse.org/repositories/isv:/cri-o:/stable:/$CRIO_VERSION/deb/Release.key |
gpg --dearmor -o /etc/apt/keyrings/cri-o-apt-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/cri-o-apt-keyring.gpg] https://download.opensuse.org/repositories/isv:/cri-o:/stable:/$CRIO_VERSION/deb/ /" |
tee /etc/apt/sources.list.d/cri-o.list
4. 各種パッケージのインストール
apt-get update
apt-get install -y cri-o kubelet kubeadm kubectl
5. 各種設定
swapをオフにして、コンテナ間の通信等ができるようにする。
ipフォワーディングも有効化する
swapoff -a
modprobe br_netfilter
sysctl -w net.ipv4.ip_forward=1
6. CRIの有効化
systemctl enable --now crio
7. kubernetesの初期化(立ち上げ)
$ sudo kubeadm init
[init] Using Kubernetes version: v1.32.3
[preflight] Running pre-flight checks
[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
...
[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 172.16.1.31:6443 --token SECRET \
--discovery-token-ca-cert-hash sha256:SECRET
kubectlでアクセスするためにconfigをhomeディレクトリにコピーします。
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
特権ユーザでkubectlを使用する場合は次のコマンドで有効になります
export KUBECONFIG=/etc/kubernetes/admin.conf
8. 動作確認
systemctl status kubelet
でkubernetesのステータスを確認してみよう
● kubelet.service - kubelet: The Kubernetes Node Agent
Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; preset: enabled)
Drop-In: /usr/lib/systemd/system/kubelet.service.d
└─10-kubeadm.conf
Active: active (running) since Thu 2025-04-17 01:56:03 UTC; 4min 46s ago
Docs: https://kubernetes.io/docs/
Main PID: 3892 (kubelet)
Tasks: 12 (limit: 2320)
Memory: 33.3M (peak: 33.9M)
CPU: 9.830s
CGroup: /system.slice/kubelet.service
└─3892 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/>
Apr 17 02:00:04 kubernetes-test kubelet[3892]: E0417 02:00:04.257287 3892 kubelet.go:3002] "Container runtime network not ready" ...
ログに"Container runtime network not ready"と出ていることからわかるように、kubectl get nodes
を実行してもNotReady状態でスタックしていることが確認できます。
コンテナのネットワークを動作させるためのCNIが導入されていないため、このようにスタックします。
次にCNIのインストールを行います。
CNIのインストール+etc
1. Cilium CLIのインストール
Ciliumのdocsに書かれてるものと同じです
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
if [ "$(uname -m)" = "aarch64" ]; then CLI_ARCH=arm64; fi
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
sha256sum --check cilium-linux-${CLI_ARCH}.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/bin
rm cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
2. Ciliumのk8sへのインストール
cilium install
次のようなログが流れてCNIのインストールが完了します。
root@kubernetes-test:~# cilium install
ℹ️ Using Cilium version 1.17.2
🔮 Auto-detected cluster name: kubernetes
🔮 Auto-detected kube-proxy has been installed
3. Ciliumとkubernetes nodeのステータス確認
インストール実行してからしばらく待って各種ステータスを確認するとインストールが完了したことが確認できます。
root@kubernetes-test:~# cilium status
/¯¯\
/¯¯\__/¯¯\ Cilium: OK
\__/¯¯\__/ Operator: OK
/¯¯\__/¯¯\ Envoy DaemonSet: OK
\__/¯¯\__/ Hubble Relay: disabled
\__/ ClusterMesh: disabled
DaemonSet cilium Desired: 1, Ready: 1/1, Available: 1/1
DaemonSet cilium-envoy Desired: 1, Ready: 1/1, Available: 1/1
Deployment cilium-operator Desired: 1, Ready: 1/1, Available: 1/1
Containers: cilium Running: 1
cilium-envoy Running: 1
cilium-operator Running: 1
clustermesh-apiserver
hubble-relay
Cluster Pods: 2/2 managed by Cilium
Helm chart version: 1.17.2
Image versions cilium quay.io/cilium/cilium:v1.17.2@sha256:3c4c9932b5d8368619cb922a497ff2ebc8def5f41c18e410bcc84025fcd385b1: 1
cilium-envoy quay.io/cilium/cilium-envoy:v1.31.5-1741765102-efed3defcc70ab5b263a0fc44c93d316b846a211@sha256:377c78c13d2731f3720f931721ee309159e782d882251709cb0fac3b42c03f4b: 1
cilium-operator quay.io/cilium/operator-generic:v1.17.2@sha256:81f2d7198366e8dec2903a3a8361e4c68d47d19c68a0d42f0b7b6e3f0523f249: 1
root@kubernetes-test:~# kubectl get nodes,pods -A
NAME STATUS ROLES AGE VERSION
node/kubernetes-test Ready control-plane 12m v1.32.3
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system pod/cilium-dng7v 1/1 Running 0 5m38s
kube-system pod/cilium-envoy-ms74t 1/1 Running 0 5m38s
kube-system pod/cilium-operator-59944f4b8f-dbs2w 1/1 Running 0 5m38s
...
4. control-planeのtaintを解除(シングルノード構成等のみ)
デフォルトではcontrol-planeでのデプロイはできないようにtaintが付与されています。
ノードのロールにはworkerやetcd等がありますが、control-planeはその名の通りクラスタの管理を担う部分ですので、過剰に負荷がかからないようにデフォルトでtaintになるんですね~
taintの無効化
kubectl taint nodes <node> node-role.kubernetes.io/control-plane-
動作確認
1. テスト用のnamespaceとdeploymentの作成
pod間での通信ができるかどうか確認するために一時的なdeploymentを作成してみよう。
今回はevaluationネームスペースを作成してデプロイします。
以下のyamlをファイルに書き込んでkubectl apply -f <ファイル名>
でデプロイしてみよう。
-- example-deploy.yaml
apiVersion: v1
kind: Namespace
metadata:
name: evaluation
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ubuntu-deployment
namespace: evaluation
spec:
replicas: 1
selector:
matchLabels:
app: ubuntu
template:
metadata:
labels:
app: ubuntu
spec:
containers:
- name: ubuntu
image: ubuntu:latest
command: ["/bin/bash", "-c", "sleep infinity"]
tty: true
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-target
namespace: evaluation
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:stable-alpine
デプロイ
root@kubernetes-test:~# kubectl apply -f example-deploy.yaml
namespace/evaluation created
deployment.apps/ubuntu-deployment created
deployment.apps/nginx-target created
podへの接続&ネットワークテスト
pod間の通信が可能であるかの確認をするためには、まずIPアドレスの確認が必要です。
以下のコマンドでアドレスやpod名などの状態が確認ができます。
kubectl get pods -n evaluation -o wide
実行例
root@kubernetes-test:~# kubectl get pods -n evaluation -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-target-random 1/1 Running 0 5m3s 10.0.0.29 kubernetes-test <none> <none>
ubuntu-deployment-random 1/1 Running 0 5m3s 10.0.0.124 kubernetes-test <none> <none>
次にubuntuコンテナにシェルを作成し、操作可能な状態にしましょう。
pod名の部分は各自の環境に合わせて変更してください。
kubectl exec -n evaluation ubuntu-deployment-random --tty --stdin -- /bin/bash
実行したらシェルが取得できるので、apt update
を実行してcurl等好きなものを入れてください。
apt update -yqq; apt install curl -yqq
インストールが完了したら、nginxのpodにcurlをたたいてみましょう
root@ubuntu-deployment-76786b4fdf-6w55q:/# curl 10.0.0.29
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
これでpod間の通信が確認できました。
おまけ(service)
デプロイするたびにpodのIPは変化します。 デプロイのたびにIPを調べて変更するなんて馬鹿らしいので、kubernetesには名前解決する機能としてserviceがあります。
以下のyamlをファイルに書き込んで、kubectl apply -f
でserviceを作成してみてください。
apiVersion: v1
kind: Service
metadata:
name: nginx-service
namespace: evaluation
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
再度ubuntuのpodでシェルを取得してnginx-serviceにcurlすると名前解決できていることが確認できます。
root@kubernetes-test:~# kubectl apply -f example-service.yaml
service/nginx-service created
root@kubernetes-test:~# kubectl exec -n evaluation ubuntu-deployment-76786b4fdf-6w55q --tty --stdin -- /bin/bash
root@ubuntu-deployment-76786b4fdf-6w55q:/# curl nginx-service
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
... 以下略
まとめ
Kubernetesのクラスタを構築する時にはCNI,CRI,そしてKubernetes本体があれば構築できることがわかりました。今後何かしらKubernetesのトラブルシューティングだったりを記事にしたいですね。
ここまで読んでくれてありがとうございます!
Discussion