Contents
1. 前提条件と環境準備
1‑1. ハードウェア・ネットワーク要件
| コンポーネント | 推奨最低スペック |
|---|---|
| コントロールプレーン | CPU 2 vCPU、メモリ 4 GiB、ディスク OS 用 20 GB(etcd 用は別途 SSD 推奨) |
| ワーカーノード | CPU 1 vCPU、メモリ 2 GiB、ディスク OS 用 20 GB |
| ネットワーク | 全ノード間で以下のポートを開放 ・API サーバー 6443/tcp・etcd 2379‑2380/tcp・kubelet 10250/tcp、10251/tcp、10252/tcp・NodePort 30000‑32767/tcp内部 Pod CIDR は 10.96.0.0/12(デフォルト)か、Calico 用に 192.168.0.0/16 などの重複しないプライベートアドレスを選択 |
根拠
Kubernetes の主要コンポーネントは高頻度で相互通信します。CPU・メモリが不足すると kubelet が NotReady になるほか、ディスク I/O が低いと etcd のレプリケーション遅延が発生しやすくなります。
参考
- Kubernetes 公式ドキュメント(Production prerequisites)
- Zenn 記事「K8s on Ubuntu」
1‑2. OS の更新、swap 無効化、ブリッジパケット転送設定
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# パッケージ情報の取得とアップデート sudo apt update && sudo apt upgrade -y # swap を即時・永続的に無効化 sudo swapoff -a sudo sed -i '/\bswap\b/ s/^/#/' /etc/fstab # br_netfilter と ip_forward の有効化 cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf br_netfilter EOF cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 EOF # 設定の反映 sudo sysctl --system |
ポイント
br_netfilter がロードされていないと CNI プラグインが iptables ルールを作成できず、Pod の通信が遮断されます。また、swap が有効なままだと kubelet がリソース管理を正しく行えません。
2. コンテナランタイムと Kubernetes パッケージのインストール
2‑1. containerd のインストール(Docker リポジトリは使用しない)
Ubuntu の公式パッケージに含まれる containerd.io は、Kubernetes が推奨するバージョンです。以下の手順でインストールし、cgroup ドライバーを systemd に統一します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# 必要ツールのインストール sudo apt install -y curl gnupg2 ca-certificates lsb-release # containerd の公式パッケージを取得(Docker リポジトリは不要) sudo apt update sudo apt install -y containerd.io # デフォルト設定ファイル生成と systemd cgroup への変更 sudo mkdir -p /etc/containerd containerd config default | sudo tee /etc/containerd/config.toml sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml # 起動・自動起動設定 sudo systemctl restart containerd sudo systemctl enable containerd |
解説
containerd は軽量で、Kubernetes と同様に systemd cgroup がデフォルトです。Docker のリポジトリを混在させるとバージョンの不整合が起きやすくなるため、公式 Ubuntu リポジトリだけで完結させます。
2‑2. kubeadm / kubelet / kubectl のインストール(バージョン固定)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# Kubernetes 用 GPG 鍵と APT リポジトリの追加 curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg \ https://packages.cloud.google.com/apt/doc/apt-key.gpg cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] \ https://apt.kubernetes.io/ kubernetes-xenial main EOF sudo apt update # 例として v1.29.0 をインストールし、バージョン固定 K8S_VERSION=1.29.0-00 sudo apt install -y kubelet=$K8S_VERSION kubeadm=$K8S_VERSION kubectl=$K8S_VERSION sudo apt-mark hold kubelet kubeadm kubectl |
ポイント
kubeadm init と各ノードの kubelet が同一バージョンであることがクラスタ安定性の前提です。apt-mark hold により自動アップグレードを防ぎ、計画的にバージョン変更できるようにします。
3. コントロールプレーンノードの初期化
3‑1. kubeadm init の実行例(改行位置修正)
|
1 2 3 4 5 6 7 8 |
# ホストのプライマリ IP を取得 HOST_IP=$(hostname -I | awk '{print $1}') sudo kubeadm init \ --apiserver-advertise-address=$HOST_IP \ --pod-network-cidr=192.168.0.0/16 \ # Calico 用 CIDR(IP‑in‑IP がデフォルト) --control-plane-endpoint=${HOST_IP}:6443 |
注意:上記の
\は行継続文字です。コメント行の後に空白が入らないように配置してください。
kubeconfig の設定
|
1 2 3 4 |
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 nodes が実行可能になります。
4. CNI プラグイン(Calico)の導入
4‑1. Calico のデフォルトモードは IP‑in‑IP
Calico は複数のトンネリング方式を提供しますが、IP‑in‑IP がデフォルトです。VXLAN や BGP を利用したい場合はマニフェスト内の ipPools 設定や CALICO_IPV4POOL_IPIP フラグを書き換えて有効化します。
|
1 2 3 4 5 6 7 |
# Calico マニフェスト取得 & 適用 curl -O https://projectcalico.org/manifests/calico.yaml kubectl apply -f calico.yaml # 起動確認(Running が出るまで待つ) kubectl get pods -n kube-system -w |
ポイント
--pod-network-cidr=192.168.0.0/16 とマニフェストの CALICO_IPV4POOL_CIDR が一致していれば、Pod 同士の通信がすぐに可能になります。
5. ワーカーノードの参加とクラスタ検証
5‑1. kubeadm join コマンド取得(トークン管理)
コントロールプレーン側で次のコマンドを実行し、出力された kubeadm join … をワーカーに貼り付けます。トークンはデフォルトで 24 h 有効です。
|
1 2 |
sudo kubeadm token create --print-join-command |
例:
|
1 2 3 |
kubeadm join 192.168.1.10:6443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:11223344556677889900aabbccddeeff... |
トークン更新手順
|
1 2 3 4 5 6 7 8 |
# 新規トークン作成(有効期限は 24 h) sudo kubeadm token create # CA 証明書ハッシュ取得(再利用可能) openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt \ | openssl rsa -pubin -outform der 2>/dev/null \ | openssl dgst -sha256 -hex | sed 's/^.* //' |
5‑2. クラスタ状態の基本チェック
| コマンド | 確認項目 |
|---|---|
kubectl get nodes |
全ノードが Ready か |
kubectl get pods -A |
kube-system のポッドがすべて Running/Completed か |
journalctl -u kubelet -f |
kubelet のリアルタイムログ |
ctr containers list |
containerd が正しくコンテナを管理しているか |
よくあるトラブルと対処例
- Node が NotReady
- 原因:cgroup driver 不一致、swap 有効、ネットワークプラグイン未起動。
-
対策:
/var/lib/kubelet/config.yamlのcgroupDriver: systemdを確認し、swapoff -aとsysctl --systemを再実行。Calico が Running かも確認。 -
NetworkPluginNotReady
- 原因:Calico マニフェスト未適用、または
--pod-network-cidrと不一致。 -
対策:
kubectl describe pod calico-node -n kube-systemのイベントでエラー内容を確認し、CIDR 設定が合っているか検証。 -
etcd 証明書期限切れ
- 原因:/etc/kubernetes/pki/etcd/*.crt が期限迫る。
- 対策:
sudo kubeadm certs renew all && sudo systemctl restart etcdを実行し、再度kubectl get componentstatusesで確認。
6. セキュリティと運用ベストプラクティス
6‑1. API サーバーの認可設定(RBAC のみ有効化)
|
1 2 3 4 5 6 7 8 9 |
# /etc/kubernetes/manifests/kube-apiserver.yaml の抜粋 spec: containers: - command: - kube-apiserver ... - --authorization-mode=Node,RBAC # RBAC と Node 限定を有効化 - --enable-admission-plugins=NodeRestriction,PodSecurityAdmission # PSP は非推奨 |
解説
RBAC が無効だと system:admin 権限がデフォルトで付与され、最小権限の原則が崩れます。PodSecurityPolicy は v1.25 以降 非推奨 となり、代替として Pod Security Admission(PSA)を使用します。
6‑2. Pod Security の現行ベストプラクティス
|
1 2 3 |
apiVersion: policy/v1beta1 kind: PodSecurityPolicy # ← 非推奨 → 削除すべきリソース |
上記は削除し、代わりに Namespace に対して PSA ラベルを設定します。
|
1 2 3 |
# 例:restricted レベルを全 Namespace のデフォルトに適用 kubectl label ns default pod-security.kubernetes.io/enforce=restricted --overwrite |
6‑3. etcd バックアップ(スナップショット)
|
1 2 3 4 5 6 7 |
export ETCDCTL_API=3 sudo ETCDCTL_ENDPOINTS=https://127.0.0.1:2379 \ ETCD_CA_FILE=/etc/kubernetes/pki/etcd/ca.crt \ ETCD_CERT_FILE=/etc/kubernetes/pki/etcd/server.crt \ ETCD_KEY_FILE=/etc/kubernetes/pki/etcd/server.key \ etcdctl snapshot save /var/backups/etcd-snapshot-$(date +%Y%m%d%H%M).db |
取得したスナップショットは 暗号化された S3 バケット、もしくは 外部 NFS など安全なストレージに保管し、世代管理(例:7 日分保持)を自動化します。
6‑4. クラスタのアップグレード手順
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# 現行バージョン確認 kubectl version --short # アップグレード可能なパスを表示 sudo kubeadm upgrade plan # コントロールプレーンを v1.30 へ更新(例) sudo kubeadm upgrade apply v1.30.0 # kubelet と kubectl のバイナリも同時にアップデートし、再度 hold 設定 K8S_NEW=1.30.0-00 sudo apt install -y kubelet=$K8S_NEW kubectl=$K8S_NEW sudo apt-mark hold kubelet kubectl # ワーカーノードをローリングで更新 for node in $(kubectl get nodes -o name | grep -v master); do kubectl drain $node --ignore-daemonsets --delete-local-data ssh ${node##*/} "sudo apt install -y kubelet=$K8S_NEW && sudo systemctl restart kubelet" kubectl uncordon $node done |
ポイント
kubeadm upgrade が API サーバーやコントロールプレーンのマニフェストを自動で置き換える一方、kubelet と kubectl は手動でバージョン合わせが必要です。ノードごとのローリングアップグレードはサービス停止時間を最小化します。
7. まとめ
- ハードウェア・ネットワーク要件 を満たし、OS の前提条件(swap 無効、br_netfilter 有効)を設定。
- containerd を公式 Ubuntu パッケージでインストールし、
systemdcgroup に統一。 - kubeadm/kubelet/kubectl は公式リポジトリからバージョン固定で導入。
kubeadm initの正しい書式でコントロールプレーンを起動し、admin.confを配置してkubectlが利用可能に。- Calico はデフォルトの IP‑in‑IP モードで導入し、Pod CIDR と一致させるだけでネットワークが機能。
- ワーカーノードはトークンベースで参加させ、
kubectl get nodes等で正常性を確認。 - RBAC を必ず有効化し、PodSecurityPolicy は廃止。代わりに Pod Security Admission を使用。
- 定期的な etcd スナップショット と計画的な アップグレード手順 で運用リスクを最小化。
以上の手順・設定を守れば、Ubuntu 22.04 上に 安定かつセキュアな本番向き Kubernetes クラスタ を構築できます。