Kubernetes入門
第1回:3分構築と自己修復の衝撃
1.1 導入:インフラの「常識」をアップデートする
1.1.1 VM運用者がKubernetesに抱く「3つの誤解」と「1つの真実」
vSphereのvCenterコンソール、あるいはHyper-Vマネージャーを日々眺めているあなたへ。Kubernetes(以下K8s)という言葉を聞くたびに、こんな思いが頭をよぎっていないでしょうか。
誤解その1:「コンテナは本番では使えない、開発者のおもちゃだ」
かつてDockerが登場した頃、確かにそういう時代がありました。しかし2026年現在、世界中の金融機関、通信キャリア、官公庁システムがK8s上で稼働しています。あなたが毎日使っているスマホアプリのバックエンドも、おそらくK8sです。
誤解その2:「学習コストが高すぎて、VMの知識が無駄になる」
逆です。VMで培った「リソース分離」「可用性設計」「ネットワークセグメンテーション」の知識は、K8sでそのまま活きます。むしろ、その土台がない人より圧倒的に有利なスタート地点に立っています。
誤解その3:「導入には大規模なインフラ投資が必要だ」
今日、あなたのノートPC1台、あるいは検証用VMたった1台で、本番さながらのK8sクラスターを構築できます。しかも3分で。
そして、1つの真実があります。
K8sは「サーバーを管理するツール」ではなく、「あるべき姿を宣言すると、システムが勝手にその状態を維持してくれる仕組み」である。
この真実を、今日、あなた自身の手で体験してもらいます。
1.1.2 なぜ2026年のインフラエンジニアにK8sが必要なのか
正直に言いましょう。K8sを学ばなくても、VMは動き続けます。あなたの仕事がすぐになくなることもありません。
しかし、こんな経験はないでしょうか。
- 深夜2時、監視アラートで叩き起こされる。SSHでログインし、プロセスを再起動し、正常性を確認し、報告書を書く。翌朝、同じことがまた起きる。
- 手順書通りに構築したはずなのに、本番環境だけ動かない。「検証環境では動いたのに…」と頭を抱える。
- 「このサーバー、誰がいつ何の設定を変えたんだ?」という考古学的調査に半日を費やす。
K8sは、これらの苦労を「過去のもの」にするために設計されました。
| VM運用の現実 | K8sが提供する解決策 |
|---|---|
| 障害発生→手動復旧→報告書 | 障害発生→自動復旧→ログに記録(人間は寝ていてOK) |
| 手順書+職人芸の構築 | YAMLファイル(設計図)による宣言的構築 |
| 「誰が変えた?」の調査 | Gitで変更履歴を完全管理 |
今日の記事を読み終える頃、あなたは「サーバーが落ちても勝手に直る」という体験を、自分の目で見届けることになります。
1.1.3 今回のミッション:監視設定なしで「勝手に直る」Webサーバを作る
本記事のゴールは明確です。
- AlmaLinux 10の最小構成VMに、K8s環境を構築する
- Nginx WebサーバをK8s上にデプロイし、ブラウザからアクセスできることを確認する
- 稼働中のサーバーを意図的に破壊し、K8sが自動で復旧させる様子を目撃する
所要時間は、慣れれば15分。初回でも30分あれば十分です。
VMの世界では「監視ツールがアラートを上げ、運用者が対応する」のが常識でした。しかしK8sの世界では、システム自身が「あるべき姿」を知っており、逸脱を検知したら自分で修復します。
このSelf-healing(自己修復)こそ、K8sの真髄です。
それでは、手を動かしていきましょう。
1.2 環境準備:AlmaLinux 10(最小構成)の土台作り
1.2.1 最小構成OSへの必須パッケージ導入
AlmaLinux 10のMinimal Installは、本当に「最小」です。ネットワーク診断ツールすら入っていません。まずは土台を整えます。
システム更新と基本ツールの導入
[Execution User: root (sudo)]
# システムを最新状態に更新
sudo dnf upgrade -y
# 必須ユーティリティをインストール
sudo dnf install -y \
curl \
tar \
git \
bash-completion \
iproute \
conntrack-tools
VMエンジニアへの補足:iproute は従来の net-tools(ifconfig, route)に代わる現代的なネットワーク管理ツールです。ip addr や ip route コマンドを提供します。conntrack-tools はK8sのネットワーク機能(Service)が内部で使用する接続追跡機能に必要です。
一般ユーザー(developer)の作成
K8sの操作は、セキュリティのベストプラクティスとして一般ユーザーで行います。
[Execution User: root (sudo)]
# 作業用ユーザーを作成
sudo useradd -m -s /bin/bash developer
# パスワードを設定(対話形式)
sudo passwd developer
# 必要に応じてsudo権限を付与(OS設定変更時のみ使用)
sudo usermod -aG wheel developer
1.2.2 Docker CE(コンテナエンジン)のセットアップ
K8sはコンテナを動かす基盤です。コンテナを実行するエンジンとして、Docker CEをインストールします。
Docker公式リポジトリの追加
[Execution User: root (sudo)]
# 古いDocker関連パッケージがあれば削除(クリーンな状態を確保)
sudo dnf remove -y docker docker-client docker-client-latest \
docker-common docker-latest docker-latest-logrotate \
docker-logrotate docker-engine podman buildah
# Docker公式リポジトリを追加
sudo dnf config-manager --add-repo \
https://download.docker.com/linux/rhel/docker-ce.repo
なぜRHEL用リポジトリを使うのか?
AlmaLinux 10はRHEL 10のバイナリ互換ディストリビューションです。Docker社はRHEL用パッケージを提供しており、AlmaLinuxでもそのまま利用できます。
Docker CEのインストールと起動
[Execution User: root (sudo)]
# Docker CE本体と関連ツールをインストール
sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Dockerサービスを起動し、自動起動を有効化
sudo systemctl enable --now docker
# 動作確認
sudo docker version
一般ユーザーにDocker操作権限を付与
毎回 sudo docker と打つのは面倒ですし、K8sツール(kind)が正常に動作しない原因にもなります。
[Execution User: root (sudo)]
# developerユーザーをdockerグループに追加
sudo usermod -aG docker developer
重要: グループ変更を反映するため、一度ログアウトして再ログインするか、以下のコマンドで新しいシェルを起動してください。
# developerユーザーとしてログインし直す
su - developer
権限が正しく設定されたか確認します。
[Execution User: developer]
# sudoなしでDockerが動作することを確認
docker run --rm hello-world
「Hello from Docker!」というメッセージが表示されれば成功です。
1.2.3 K8s操作ツール(kind / kubectl)のインストール
いよいよK8sツールの導入です。ここからは一般ユーザー developer で作業します。
kindのインストール
kind(Kubernetes IN Docker)は、Docker コンテナを「仮想ノード」として使い、ローカル環境にK8sクラスターを構築するツールです。VMエンジニアの感覚で言えば、「Docker上にネストされた仮想データセンターを作るツール」です。
[Execution User: developer]
# kindのバイナリをダウンロード(v0.26.0)
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.26.0/kind-linux-amd64
# 実行権限を付与
chmod +x ./kind
# PATHの通った場所に移動
mkdir -p ~/.local/bin
mv ./kind ~/.local/bin/kind
# PATHに追加(永続化)
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
# バージョン確認
kind version
出力例:
kind v0.26.0 go1.23.x ...
kubectlのインストール
kubectlは、K8sクラスターを操作するコマンドラインツールです。VMで言えば、vSphere ClientやHyper-Vマネージャーに相当する「K8sの操作盤」です。
[Execution User: developer]
# kubectlのバイナリをダウンロード(v1.32系の最新安定版)
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
# チェックサムファイルをダウンロード
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl.sha256"
# チェックサム検証
echo "$(cat kubectl.sha256) kubectl" | sha256sum --check
# 実行権限を付与して配置
chmod +x kubectl
mv kubectl ~/.local/bin/
# バージョン確認
kubectl version --client
「kubectl: OK」と表示されれば問題ありません。
出力例:
Client Version: v1.32.x
Kustomize Version: v5.x.x
bash補完の設定(推奨)
kubectlには多くのサブコマンドがあります。Tab補完を有効にすると作業効率が劇的に向上します。
[Execution User: developer]
# bash補完スクリプトを生成して読み込み設定
kubectl completion bash >> ~/.bashrc
source ~/.bashrc
これで、kubectl get p[Tab] と打てば kubectl get pods と補完されるようになります。
1.3 実践:K8sクラスターの展開とWebサーバ起動
環境が整いました。ここからが本番です。
1.3.1 クラスタ定義ファイル(kind-config.yaml)の作成
kindでは、YAMLファイルでクラスターの構成を「宣言」します。これこそがK8sの思想である宣言的アプローチです。
「こういう状態であってほしい」を書くと、kindがその通りに構築してくれます。VMで言えば、vSphereのテンプレートに近い概念ですが、より柔軟で再現性が高いものです。
[Execution User: developer]
# 作業ディレクトリを作成
mkdir -p ~/k8s-lab
cd ~/k8s-lab
# クラスタ定義ファイルを作成
cat << 'EOF' > kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: my-first-cluster
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
# ホストVMの80番ポートを、クラスタ内のNodePort 30080へ転送
- containerPort: 30080
hostPort: 80
protocol: TCP
# HTTPS用(将来の拡張用)
- containerPort: 30443
hostPort: 443
protocol: TCP
EOF
VMエンジニアへの読み解きポイント:
| YAML項目 | VMでの対応概念 |
|---|---|
kind: Cluster | リソースタイプの宣言(VM作成, vSwitch作成などに相当) |
nodes: | クラスターを構成するノード一覧 |
role: control-plane | K8sのマスターノード(vCenterサーバーに相当) |
extraPortMappings | 仮想スイッチのポートフォワーディング設定 |
extraPortMappings は特に重要です。kindで作られるK8sクラスターはDockerコンテナの中に隔離されています。ホストVM(AlmaLinux)の80番ポートへのアクセスを、クラスター内部へ橋渡しする設定です。
1.3.2 仮想データセンター(K8sクラスター)の召喚
いよいよクラスターを作成します。
[Execution User: developer]
# K8sクラスターを作成
kind create cluster --config kind-config.yaml
実行すると、以下のような進捗が表示されます。
Creating cluster "my-first-cluster" ...
✓ Ensuring node image (kindest/node:v1.32.x) 🖼
✓ Preparing nodes 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
Set kubectl context to "kind-my-first-cluster"
You can now use your cluster with:
kubectl cluster-info --context kind-my-first-cluster
Have a nice day! 👋
所要時間は環境によりますが、初回でも2〜3分程度です。
VM環境でESXiホストを構築し、vCenterをデプロイし、クラスターを構成し、共有ストレージを接続し…という作業を思い出してください。あの作業が、たった1コマンドで完了しました。
クラスターの状態確認
[Execution User: developer]
# クラスター情報を表示
kubectl cluster-info
# ノード一覧を表示
kubectl get nodes
出力例:
NAME STATUS ROLES AGE VERSION
my-first-cluster-control-plane Ready control-plane 60s v1.32.x
STATUS が Ready になっていれば、K8sクラスターは正常に稼働しています。
1.3.3 Webサーバ(Nginx)の爆速デプロイ
クラスターができました。次は、その上でWebサーバを動かします。
Deployment(デプロイメント)の作成
K8sでは、「Podを何個、どんな設定で動かすか」をDeploymentというリソースで宣言します。
[Execution User: developer]
# Nginx Deploymentの定義ファイルを作成
cat << 'EOF' > nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-web
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
EOF
重要な概念:replicas: 2
この1行が、K8sの自己修復機能の鍵です。「Nginxは常に2台動いているべき」というDesired State(あるべき姿)を宣言しています。
VMの世界では、「2台構成のWebサーバを維持する」ために、監視ツール、フェイルオーバー設定、手順書、そして深夜対応要員が必要でした。K8sでは、この1行で済みます。
Serviceの作成(外部公開設定)
Deploymentだけでは、クラスター外部からアクセスできません。Serviceというリソースで、ネットワーク経路を作ります。
[Execution User: developer]
# Service定義ファイルを作成
cat << 'EOF' > nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
nodePort: 30080
EOF
VMエンジニア向けの解説:Serviceは「ロードバランサー+DNS」のような役割を果たします。nodePort: 30080 は、先ほど kind-config.yaml で設定したポートマッピングと対応しています。
K8sへの適用
YAMLファイルができたら、kubectl apply でK8sに「この状態にしてください」と指示します。
[Execution User: developer]
# DeploymentとServiceをK8sに適用
kubectl apply -f nginx-deployment.yaml
kubectl apply -f nginx-service.yaml
出力例:
deployment.apps/nginx-web created
service/nginx-service created
デプロイ状況の確認
[Execution User: developer]
# Podの状態を確認
kubectl get pods -o wide
出力例:
NAME READY STATUS RESTARTS AGE IP NODE
nginx-web-5d4f4b7c9-abc12 1/1 Running 0 30s 10.244.0.5 my-first-cluster-control-plane
nginx-web-5d4f4b7c9-def34 1/1 Running 0 30s 10.244.0.6 my-first-cluster-control-plane
2つのPodが Running 状態であることを確認してください。
ブラウザでアクセス確認
ホストVMのIPアドレス(または localhost)にブラウザでアクセスします。
[Execution User: developer]
# コマンドラインでも確認可能
curl http://localhost/
Nginxのウェルカムページが表示されれば成功です。
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
おめでとうございます。 K8s上で動くWebサーバが完成しました。
1.4 破壊と再生:K8sの「自己修復」を目撃する
ここからが、本記事のクライマックスです。
VMの世界で「稼働中のサーバを強制停止する」ことは、障害対応以外ではあり得ない行為でした。しかしK8sでは、これが「システムの正常性を確認するテスト」として日常的に行われます。
1.4.1 稼働中サーバ(Pod)の強制削除
まず、現在動いているPodの名前を確認します。
[Execution User: developer]
kubectl get pods
出力例:
NAME READY STATUS RESTARTS AGE
nginx-web-5d4f4b7c9-abc12 1/1 Running 0 5m
nginx-web-5d4f4b7c9-def34 1/1 Running 0 5m
では、1つのPodを強制削除します。実際の運用で言えば、「サーバが突然クラッシュした」状況のシミュレーションです。
[Execution User: developer]
# 1つ目のPodを強制削除(Pod名は自分の環境に合わせて変更)
kubectl delete pod nginx-web-5d4f4b7c9-abc12
出力:
pod "nginx-web-5d4f4b7c9-abc12" deleted
1.4.2 復活のプロセスを詳細観察する
Podを削除した直後、別のターミナルで以下のコマンドを実行しておくと、リアルタイムで状況を監視できます。
[Execution User: developer]
# Pod状態の変化をリアルタイム監視(-w = watch)
kubectl get pods -w
出力例(時系列):
NAME READY STATUS RESTARTS AGE
nginx-web-5d4f4b7c9-def34 1/1 Running 0 5m
nginx-web-5d4f4b7c9-abc12 1/1 Terminating 0 5m
nginx-web-5d4f4b7c9-xyz99 0/1 Pending 0 0s
nginx-web-5d4f4b7c9-xyz99 0/1 ContainerCreating 0 1s
nginx-web-5d4f4b7c9-xyz99 1/1 Running 0 3s
nginx-web-5d4f4b7c9-abc12 0/1 Terminating 0 5m
nginx-web-5d4f4b7c9-abc12 0/1 Terminating 0 5m
何が起きたか、整理します。
abc12がTerminating(終了処理中)になる- 同時に
xyz99という新しいPodがPending(スケジュール待ち)で作成される xyz99がContainerCreating(コンテナ起動中)を経てRunningになる- 最終的に
abc12が完全に削除される
注目すべきは、この一連の流れに人間の介入が一切なかったことです。
監視ツールのアラートもなく、運用担当者への電話もなく、深夜のSSH接続もなく、手順書の確認もありませんでした。
K8sは以下のループを自律的に実行しています。
- 観測:現在のPod数は? → 1台
- 比較:Desired State(replicas: 2)と一致するか? → No
- 実行:不足分を補うため、新しいPodを作成
これが、K8sのReconciliation Loop(調整ループ)です。
1.4.3 VM運用へのフィードバック:「Desired State」の概念解説
ここで、VMエンジニアの皆さんに最も伝えたいことがあります。
従来のVM運用は「命令型(Imperative)」でした。
- 「このサーバを起動しろ」
- 「このプロセスを再起動しろ」
- 「このファイルをコピーしろ」
手順書は「やるべきこと」の羅列であり、実行者(人間またはスクリプト)がその順番通りに命令を実行していきます。
K8sの運用は「宣言型(Declarative)」です。
- 「Nginxは2台あるべき」
- 「メモリは128MBまで使ってよい」
- 「ポート80で待ち受けるべき」
YAMLファイルには「こうあるべき」という最終状態だけが書かれています。そこに至る手順は、K8sが考えます。
この違いが意味すること:
| 命令型(VM運用) | 宣言型(K8s運用) |
|---|---|
| 障害時:「何をすべきか」を人間が判断 | 障害時:「あるべき姿」との差分をシステムが自動補正 |
| 構築手順書が必要 | YAMLファイル(設計図)があれば再現可能 |
| 「やったこと」を記録 | 「あるべき姿」をGitで管理 |
| 環境ごとに微妙な差異が発生 | 同じYAMLなら同じ結果 |
これが、K8sが「インフラを宣言的に管理する」と言われる理由です。
そして、この思想を理解した瞬間、あなたのインフラエンジニアとしてのキャリアは次のステージに進みます。
1.5 トラブルシューティングの第一歩
構築やデプロイがうまくいかない時、VMエンジニアはまず /var/log/messages を見たり、systemctl status を叩いたりするでしょう。
K8sにも同様の「まず叩くべきコマンド」があります。ここでは厳選した3つを紹介します。
kubectl describe:詳細情報の取得
「なぜPodが起動しないのか」を調べる最初の一手です。
[Execution User: developer]
# Podの詳細情報を表示
kubectl describe pod <Pod名>
# 例:
kubectl describe pod nginx-web-5d4f4b7c9-xyz99
出力の末尾にある Events: セクションが特に重要です。「イメージのダウンロードに失敗した」「リソースが足りない」といったエラー原因がここに記録されます。
kubectl logs:コンテナログの確認
アプリケーションが起動したものの動作がおかしい時は、ログを確認します。
[Execution User: developer]
# Podのログを表示
kubectl logs <Pod名>
# リアルタイムでログを追跡(tail -f相当)
kubectl logs -f <Pod名>
kubectl get events:クラスター全体のイベント
複数のリソースにまたがる問題を調査する時に有効です。
[Execution User: developer]
# 直近のイベントを時系列で表示
kubectl get events --sort-by='.lastTimestamp'
トラブルシューティングのフローチャート
問題発生
↓
kubectl get pods で状態確認
↓
STATUS が Pending/CrashLoopBackOff など異常なら
↓
kubectl describe pod <Pod名> でイベント確認
↓
原因がアプリ側なら kubectl logs <Pod名> でログ確認
↓
原因がクラスター側なら kubectl get events で全体確認
このフローを覚えておけば、K8sトラブルの8割は初動対応できます。
まとめ:今日あなたが手に入れたもの
本記事を通じて、あなたは以下を達成しました。
- K8sローカル環境の構築
AlmaLinux 10上に、Docker + kind + kubectl の環境を整備しました。 - クラスターの作成と理解
YAMLファイル1枚で「仮想データセンター」を召喚する体験をしました。 - 宣言的デプロイの実践
「Nginxを2台」という状態をYAMLで宣言し、K8sがその通りに構築する様子を見ました。 - 自己修復(Self-healing)の目撃
稼働中のPodを破壊し、K8sが自動で復旧させる様子をリアルタイムで観察しました。 - トラブルシューティングの基礎
describe,logs,get eventsという3つの武器を手に入れました。
次回予告:第2回「設計図としてのYAML入門」
今回は用意されたYAMLをそのまま使いました。次回は、YAMLの構造を理解し、自分で書けるようになることを目指します。
- YAMLの基本文法とK8sリソースの関係
- Deployment、Service、ConfigMapの設計思想
- VMの設定ファイル(.vmx, XML)との比較
「設計図を読める」から「設計図を書ける」へ。次のステップでお会いしましょう。
環境のクリーンアップ(任意)
検証が終わったら、クラスターを削除してリソースを解放できます。
[Execution User: developer]
# クラスターを削除
kind delete cluster --name my-first-cluster
再度 kind create cluster --config kind-config.yaml を実行すれば、いつでも同じ環境を再現できます。これもまた、宣言的インフラの恩恵です。
