Contents
1. OS とカーネル要件の確認・設定
1-1. カーネルが cgroup v2 を使用しているか確認
|
1 2 3 4 |
$ uname -r # 例: 6.5.0-26-generic $ grep -E 'cgroup|cgroup2' /proc/filesystems nodev cgroup2 # ← cgroup2 が表示されていれば有効 |
Tip:もし
cgroup2が見当たらない場合は、ブートパラメータにsystemd.unified_cgroup_hierarchy=1を追加し、再起動してください。
1-2. 必要なカーネルモジュールと sysctl の永続化
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# ① カーネルモジュールの自動ロード設定(sudo が必要) cat <<'EOF' | sudo tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF # ② sysctl パラメータをファイルに書き込み 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 fs.inotify.max_user_watches = 524288 EOF # ③ 設定を反映 sudo sysctl --system |
2. コンテナランタイムと Kubernetes コンポーネントのインストール
2-1. 前提:Helm が未インストールの場合
|
1 2 3 4 |
curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash # helm のバージョン確認 helm version --short |
※ Helm は
sudoが不要なユーザー領域にインストールされますが、システム全体で使用したい場合は/usr/local/bin/helmへ配置してください。
2-2. Podman + CRI‑O(cgroup v2 対応)
a. 必要パッケージの取得とリポジトリ設定(Ubuntu 例)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# Podman 本体 sudo apt-get update && sudo apt-get install -y podman # CRI‑O の apt リポジトリを追加(signed-by を使用) OS=ubuntu VERSION=1.30 # Kubernetes バージョンに合わせて選択可 CRIO_KEYRING=/usr/share/keyrings/crio-archive-keyring.gpg curl -fsSL https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/$OS/Release.key \ | gpg --dearmor > $CRIO_KEYRING cat <<EOF | sudo tee /etc/apt/sources.list.d/cri-o.list deb [signed-by=$CRIO_KEYRING] https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/$OS/ ./ EOF sudo apt-get update sudo apt-get install -y cri-o |
b. CRI‑O の有効化と Podman 連携
|
1 2 3 4 5 6 7 8 9 10 |
# /etc/crio/crio.conf に runtime 設定を追記 sudo sed -i '/^\[crio.runtime\]/a runtime = "podman"' /etc/crio/crio.conf # cgroup driver を systemd に統一 sudo sed -i 's/^cgroup_manager = .*/cgroup_manager = "systemd"/' /etc/crio/crio.conf sudo sed -i 's/^conmon_cgroup = .*/conmon_cgroup = "pod"`/g' /etc/crio/crio.conf # 起動 & 自動起動有効化 sudo systemctl enable crio --now |
Tip:
crio statusで状態を確認し、systemd cgroup driverが有効になっていることを必ずチェックしてください。
2-3. (代替)containerd のインストール手順
|
1 2 3 4 5 6 7 8 |
sudo apt-get install -y containerd sudo mkdir -p /etc/containerd containerd config default | sudo tee /etc/containerd/config.toml # systemd cgroup を有効化 sudo sed -i 's/^ SystemdCgroup = false/ SystemdCgroup = true/' /etc/containerd/config.toml sudo systemctl restart containerd |
2-4. Kubernetes パッケージ(v1.30 系)と cgroup driver の統一
a. apt リポジトリの追加(signed‑by を使用)
|
1 2 3 4 5 6 7 8 9 |
K8S_KEYRING=/usr/share/keyrings/kubernetes-archive-keyring.gpg curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor > $K8S_KEYRING cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list deb [signed-by=$K8S_KEYRING] https://apt.kubernetes.io/ kubernetes-xenial main EOF sudo apt-get update |
b. バージョン指定でインストール
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
K8S_VERSION=1.30.0-00 # 必要に応じて最新の 1.30.x を確認 sudo apt-get install -y kubeadm=$K8S_VERSION kubelet=$K8S_VERSION kubectl=$K8S_VERSION sudo apt-mark hold kubeadm kubelet kubectl # アップデート抑止 # kubelet の cgroup driver 設定(/etc/default/kubelet は非推奨、代わりに /var/lib/kubelet/config.yaml を使用) cat <<'EOF' | sudo tee /var/lib/kubelet/config.yaml apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration cgroupDriver: systemd EOF sudo systemctl daemon-reload && sudo systemctl restart kubelet |
重要:
/var/lib/kubelet/config.yamlが存在しない場合はkubeadm init時に自動生成されますが、手動で作成しておくと後続のアップグレード時に設定が失われにくくなります。
3. クラスタ初期化(control‑plane)とネットワーク設定
3-1. スワップ無効化 & 永続化
|
1 2 3 |
sudo swapoff -a sudo sed -i '/\bswap\b/s/^/#/' /etc/fstab # fstab のスワップ行をコメントアウト |
3-2. 必要な sysctl 設定(再掲)
|
1 2 3 4 5 6 7 |
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 |
3-3. kubeadm init の実行例
|
1 2 3 4 5 6 7 8 9 10 |
# control‑plane の IP アドレスはマスターノードのプライベートアドレスを指定してください MASTER_IP=$(hostname -I | awk '{print $1}') sudo kubeadm init \ --pod-network-cidr=192.168.0.0/16 \ --service-cidr=10.96.0.0/12 \ --control-plane-endpoint="${MASTER_IP}:6443" \ --cri-socket=/var/run/crio/crio.sock \ --upload-certs |
ポイント
---cgroup-driverフラグは Kubernetes v1.24 以降廃止され、代わりに kubelet の設定ファイルで管理します。上記ではsystemdが既に設定済みです。
- 初期化が成功するとkubeadm join ...コマンドが出力されますので、ワーカーノードへコピーしてください。
3-4. kubeconfig の取得(ローカルから kubectl 使用可能に)
|
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 |
4. Pod ネットワーク(Calico)構築
4-1. Calico の最新安定版マニフェスト取得と eBPF 有効化
※ 本手順は Calico v3.x 系の最新版(例: v3.27.0)を対象にしています。v4 系が正式リリースされた場合は公式ドキュメントをご確認ください。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 1) マニフェスト取得 CALICO_VERSION=v3.27.0 # 必要に応じて最新版へ置き換え curl -L https://raw.githubusercontent.com/projectcalico/calico/${CALICO_VERSION}/manifests/calico.yaml \ -o calico.yaml # 2) eBPF モードを有効化(カスタム設定が必要な場合は ConfigMap を編集) sed -i '/# - name: FELIX_IPINIPMTU/a\ - name: FELIX_EXPERIMENTAL_BPFENABLED\n value: "true"' calico.yaml # 3) IPPool の CIDR が kubeadm と一致しているか確認 grep -A2 'ipPool' -n calico.yaml | grep -i '192.168.0.0/16' # 4) デプロイ kubectl apply -f calico.yaml |
4-2. ネットワーク動作確認
|
1 2 3 4 5 6 7 8 9 10 |
# テスト用 Pod(nginx)をデプロイ kubectl run test-nginx --image=nginx --restart=Never -l app=test-nginx # Pod が Running になるまで待機 kubectl wait pod/test-nginx --for=condition=Ready --timeout=60s # 同一ノード上の busybox から ping テスト POD_IP=$(kubectl get pod test-nginx -o jsonpath='{.status.podIP}') kubectl run busybox --rm -i --tty --image=busybox -- /bin/sh -c "ping -c 3 $POD_IP" |
期待結果:
pingがすべて成功し、ステータスコード0が返ること。
5. GitOps 基盤 – Argo CD の Helm インストールと OIDC 設定
5-1. Helm による Argo CD デプロイ(事前に Helm がインストール済みであること)
|
1 2 3 4 5 6 7 |
# Helm リポジトリ追加 helm repo add argo-cd https://argoproj.github.io/argo-helm helm repo update # 名前空間作成 kubectl create namespace argocd |
a. OIDC 用シークレットの事前作成(環境変数に依存しない)
|
1 2 3 4 |
# 例:Keycloak のクライアントシークレットを Kubernetes Secret に保存 kubectl -n argocd create secret generic argo-oidc-secret \ --from-literal=clientSecret=$(openssl rand -base64 32) |
b. values.yaml(OIDC 設定込み)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# values.yaml server: extraArgs: - --insecure # テスト環境のみ。本番は TLS を必ず有効化 config: url: https://argocd.example.com ingress: enabled: true hosts: - argocd.example.com annotations: kubernetes.io/ingress.class: nginx cert-manager.io/cluster-issuer: letsencrypt-prod dex: connectors: - type: oidc id: keycloak name: Keycloak config: issuer: https://keycloak.example.com/auth/realms/k8s clientID: argo-cd-client # Secret は先ほど作成した Kubernetes Secret を参照 clientSecret: ${{ .Values.dex.secrets.clientSecret }} secrets: - name: clientSecret secretRef: name: argo-oidc-secret key: clientSecret |
ポイント
-clientSecretは環境変数ではなく Helm のvalues.yamlに埋め込むか、Kubernetes Secret から注入します。これによりデプロイ時のエラーを防げます。
- 本番環境では--insecureフラグは削除し、TLS 証明書(cert‑manager 等)で保護してください。
c. Helm インストール
|
1 2 3 4 5 |
helm install argo-cd argo-cd/argo-cd \ -n argocd \ -f values.yaml \ --set dex.secrets[0].secretRef.name=argo-oidc-secret |
5-2. Argo CD の外部アクセス確認
|
1 2 3 4 5 |
# LoadBalancer がある環境の場合(例) kubectl -n argocd get svc argo-cd-server -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' # Ingress が有効な場合は DNS で解決できるか確認 dig +short argocd.example.com |
6. 運用・保守
6-1. クラスタヘルスチェック
|
1 2 3 4 |
kubectl get componentstatuses # Deprecated だが残っているコンポーネントの概要 kubectl get nodes -o wide kubectl describe node <node-name> |
エラー時は以下で詳細ログを取得:
|
1 2 3 4 5 6 |
# kubelet の journal sudo journalctl -u kubelet -f # CRI‑O のステータス crio status |
6-2. ワーカーノード追加手順
|
1 2 3 4 5 6 |
# (1) コントロールプレーンで join 用コマンド取得 JOIN_CMD=$(sudo kubeadm token create --print-join-command) # (2) ワーカー側で実行(CRI ソケットは環境に合わせる) sudo $JOIN_CMD --cri-socket=/var/run/crio/crio.sock |
6-3. クラスタアップグレード(例:1.30 → 1.31 がリリースされた場合)
|
1 2 3 4 5 6 7 8 9 10 |
# 計画の確認 sudo kubeadm upgrade plan # 実行(マスター側) sudo kubeadm upgrade apply v1.31.0 # パッケージ更新 sudo apt-get install -y kubelet=1.31.0-00 kubectl=1.31.0-00 sudo systemctl restart kubelet |
Tip:アップグレード前に必ず
kubectl get nodesで全ノードがReadyか確認し、バックアップ(etcd スナップショット等)を取得してください。
6-4. ポリシーエンフォースメント – OPA Gatekeeper の導入
|
1 2 3 4 |
# Helm で Gatekeeper インストール helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts helm install gatekeeper gatekeeper/gatekeeper -n kube-system --create-namespace |
a. Privileged コンテナ禁止の例(ConstraintTemplate + Constraint)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# constrainttemplate.yaml apiVersion: templates.gatekeeper.sh/v1beta1 kind: ConstraintTemplate metadata: name: k8sdisallowprivileged spec: crd: spec: names: kind: K8sDisallowPrivileged targets: - target: admission.k8s.gatekeeper.sh rego: | package k8sdisallowprivileged violation[{"msg": msg}] { input.review.object.spec.containers[_].securityContext.privileged == true msg := "Privileged containers are not allowed" } |
|
1 2 3 4 5 6 7 8 |
# constraint.yaml apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sDisallowPrivileged metadata: name: disallow-privileged spec: enforcementAction: deny |
|
1 2 3 |
kubectl apply -f constrainttemplate.yaml kubectl apply -f constraint.yaml |
効果:Pod が
securityContext.privileged: trueを指定すると API サーバーでリクエストが拒否されます。
7. まとめ
| 項目 | 実施内容 |
|---|---|
| OS / カーネル | Ubuntu 24.04 LTS または Rocky Linux 9.4、cgroup v2 有効化 |
| カーネルモジュール・sysctl | overlay, br_netfilter の永続ロード & 必要 sysctl 設定 |
| コンテナランタイム | Podman + CRI‑O(または containerd)を systemd cgroup driver で統一 |
| Kubernetes 本体 | v1.30 系、apt リポジトリは signed‑by キーリング方式、kubelet config.yaml に cgroupDriver: systemd 設定 |
| ネットワーク | Calico(v3.x)+ eBPF モード有効化、Pod CIDR 192.168.0.0/16 を使用 |
| GitOps | Argo CD を Helm でデプロイ、OIDC (Keycloak) は Secret 経由で clientSecret 注入 |
| 運用ツール | helm, gatekeeper, kubeadm upgrade などの標準フロー |
| セキュリティ | スワップ無効化、OPA Gatekeeper によるポリシー強制、TLS/Ingress の適切な設定 |
次のステップ
- 本手順を実環境で試す前に、各コンポーネント(Kubernetes, Calico, Argo CD など)の公式ドキュメントを再度確認し、バージョン差異がないか検証してください。
- プロダクション導入時は バックアップ戦略(etcd スナップショット、GitOps 設定のリポジトリ)と 監視基盤(Prometheus + Grafana, Alertmanager)の構築を併せて計画してください。