はじめに
医療ITエンジニアの三浦です。
最近はHAProxyを使ったBlue/Greenデプロイメントを試していますが、今回はその先のKubernetes環境を構築してみます。
Ubuntu 26.04 LTSに、コンテナランタイムのcontainerd、Kubernetes v1.37、CNIのCalico v3.33.0を導入し、最後にNginxをデプロイして外部からアクセスするところまで確認します。
最初はメモリ1GBのVPSで試しましたが、kubeadm init の事前チェックで [ERROR Mem] が発生して初期化できませんでした。今回は4GBのサーバーで検証しています。
Kubernetesとkubeadmとは
Kubernetesはコンテナ化したアプリケーションの配置・実行・管理を行うオーケストレーション基盤です。kubeadm は、そのKubernetesクラスターを初期化するためのツールです。
今回はControl Plane 1台で動作させるシングルノード構成です。実運用向けの冗長化や監視、バックアップなどは対象外とします。
検証環境・前提条件
- OS:Ubuntu Server 26.04 LTS
- メモリ:4GB(今回の検証環境。Kubernetes公式の基本要件は2GB以上)
- Kubernetes:v1.37系
- コンテナランタイム:containerd(UbuntuのAPTパッケージ)
- CNI:Calico v3.33.0
- ノード構成:Control Plane 1台
- 作業ユーザー:
sudoを実行できる一般ユーザー
注意:サーバーのIPアドレス、PodネットワークのCIDR、ファイアウォールの設定は環境に合わせてください。
192.168.0.0/16は既存LANやVPNと重複しないことが前提です。公開VPSではKubernetes API(TCP 6443)をインターネットに無制限公開しないでください。
1. OSの事前準備
まず、パッケージを更新し、必要なツールをインストールします。
sudo apt update
sudo apt upgrade -y
sudo apt install -y ca-certificates curl gpg
Swapの無効化
kubeletのデフォルト構成に合わせ、Swapを無効化します。
sudo swapoff -a
swapon --show
swapon --show で何も表示されなければ無効です。再起動後も維持するため、/etc/fstab にSwapのエントリがある場合はコメントアウトしてください。zramやsystemdのSwapユニットを使っている場合は、それらの設定も確認します。
カーネルモジュールの設定
sudo tee /etc/modules-load.d/k8s.conf > /dev/null <<'EOF_MODULES'
overlay
br_netfilter
EOF_MODULES
sudo modprobe overlay
sudo modprobe br_netfilter
ネットワーク設定
sudo tee /etc/sysctl.d/99-kubernetes.conf > /dev/null <<'EOF_SYSCTL'
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
EOF_SYSCTL
sudo sysctl --system
sysctl net.ipv4.ip_forward net.bridge.bridge-nf-call-iptables
両方とも 1 になっていることを確認します。
2. containerdのインストール
Kubernetesからコンテナを実行するため、containerdをインストールします。
sudo apt install -y containerd
containerd --version
設定ファイルを生成し、cgroup driverをsystemdに合わせます。
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml > /dev/null
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
containerd 1.xと2.xでは設定ファイル内のプラグインの階層が異なりますが、デフォルト設定にあるSystemdCgroupをtrueにする点は共通です。また、disabled_pluginsにcriが指定されていないことを確認します。
sudo grep -n -E 'SystemdCgroup|disabled_plugins' /etc/containerd/config.toml
sudo systemctl enable --now containerd
sudo systemctl restart containerd
sudo systemctl status containerd --no-pager
active (running)であればOKです。
3. Kubernetesのインストール
Kubernetes v1.37の公式APTリポジトリを登録します。現在はマイナーバージョンごとにリポジトリが分かれています。
K8S_VERSION=v1.37
sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL "https://pkgs.k8s.io/core:/stable:/${K8S_VERSION}/deb/Release.key" \
| sudo 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:/${K8S_VERSION}/deb/ /" \
| sudo tee /etc/apt/sources.list.d/kubernetes.list
kubelet、kubeadm、kubectlをインストールし、通常のAPT更新で意図せずバージョンが上がらないよう固定します。
sudo apt update
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
sudo systemctl enable --now kubelet
kubeadm version
kubectl version --client
この段階ではクラスターが初期化されていないため、kubeletが正常起動できず再試行する場合があります。
4. Control Planeの初期化
kubeadm initを実行します。PodネットワークはCalicoの設定に合わせて192.168.0.0/16を指定します。
sudo kubeadm init \
--pod-network-cidr=192.168.0.0/16 \
--cri-socket=unix:///run/containerd/containerd.sock
複数NICがある場合などは、必要に応じて--apiserver-advertise-address=<Control PlaneのIPアドレス>も指定してください。
成功するとYour Kubernetes control-plane has initialized successfully!と表示されます。
kubectlの設定
一般ユーザーからクラスターを操作できるように設定します。
mkdir -p "$HOME/.kube"
sudo cp /etc/kubernetes/admin.conf "$HOME/.kube/config"
sudo chown "$(id -u):$(id -g)" "$HOME/.kube/config"
kubectl get nodes
この時点ではCNIを導入していないため、ノードがNotReadyでも問題ありません。なお、admin.confは管理者権限を持つため、第三者に渡したり公開リポジトリに登録したりしないようにします。
5. Calicoのインストール
Pod間通信を実現するCNIとしてCalico v3.33.0を導入します。今回はTigera Operator方式を使用します。
Kubernetes v1.36以降では、CalicoのCRDにv3_projectcalico_org.yamlを使用します。v1.34・v1.35向けの-v1beta1付きファイルとは異なる点に注意してください。
# CRD
kubectl create -f \
https://raw.githubusercontent.com/projectcalico/calico/v3.33.0/manifests/v3_projectcalico_org.yaml
# Tigera Operator
kubectl create -f \
https://raw.githubusercontent.com/projectcalico/calico/v3.33.0/manifests/tigera-operator.yaml
# Calicoのカスタムリソース
kubectl create -f \
https://raw.githubusercontent.com/projectcalico/calico/v3.33.0/manifests/custom-resources.yaml
custom-resources.yamlのIPプールが192.168.0.0/16になっていることを前提としています。CIDRを変更した場合は、マニフェストをダウンロードして内容を変更してから適用してください。
kubectl get pods -A
kubectl get tigerastatus
kubectl get nodes
Calicoの準備が整うと、ノードがReadyになります。VPSのファイアウォールでは、ノード間のCalico通信も必要に応じて許可します。
6. Control PlaneへのPod配置(シングルノード検証用)
通常、Control Planeには一般アプリケーションのPodが配置されないようtaint(テイント)が設定されています。今回は1台構成なので解除します。
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
注意:このコマンドは全ノードが対象です。複数ノードの本番クラスターでは安易に実行しないでください。
7. Nginxをデプロイして動作確認
Deploymentの作成
kubectl create deployment nginx \
--image=nginx:stable \
--replicas=2
kubectl rollout status deployment/nginx
kubectl get pods -o wide
NodePortで公開
外部からアクセスするため、ServiceをNodePortで作成します。今回はポート30080に固定します。
kubectl create service nodeport nginx --tcp=80:80 --node-port=30080
kubectl get svc nginx
PORT(S)が80:30080/TCPと表示されればOKです。30080が使用済みの場合は起動できません。今回は単一ポートのServiceなのでこの方法を使用しますが、複数ポートを扱う場合や構成管理を行う場合はYAML定義をおすすめします。
外部からアクセス
ブラウザで次のURLを開きます。
http://<サーバーのIPアドレス>:30080
NginxのWelcomeページが表示されれば成功です。アクセスできない場合は、Podの状態、ServiceのEndpoint、UbuntuのUFW、VPS事業者側のファイアウォールでTCP 30080が許可されているかを確認してください。検証用ポートは可能な限り接続元IPを限定します。
8. 後片付け
動作確認が終わったら、NginxのDeploymentとServiceを削除します。
kubectl delete deployment/nginx service/nginx
kubectl get pods
kubectl get svc
Kubernetes標準のkubernetes Serviceは残ります。containerdにNginxのイメージがキャッシュされる場合がありますが、通常はそのままで問題ありません。
まとめ
今回はUbuntu 26.04 LTSにcontainerdとKubernetes v1.37を導入し、CalicoでPodネットワークを構成して、NginxをNodePortで公開するところまで確認しました。
最初に試したメモリ1GBのVPSでは、kubeadm initの事前チェックで[ERROR Mem]が発生し、Control Planeを初期化できませんでした。4GBの環境に変更したところ、今回の検証を完了できました。
今後はGateway APIやNGINX Gateway Fabricを導入し、HAProxyと組み合わせたBlue/Greenデプロイメントやカナリアリリースも試していきたいと思います。