Kubernetes入門 第1回:3分構築と自己修復の衝撃

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サーバを作る

本記事のゴールは明確です。

  1. AlmaLinux 10の最小構成VMに、K8s環境を構築する
  2. Nginx WebサーバをK8s上にデプロイし、ブラウザからアクセスできることを確認する
  3. 稼働中のサーバーを意図的に破壊し、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 addrip 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-planeK8sのマスターノード(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

STATUSReady になっていれば、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

何が起きたか、整理します。

  1. abc12Terminating(終了処理中)になる
  2. 同時に xyz99 という新しいPodが Pending(スケジュール待ち)で作成される
  3. xyz99ContainerCreating(コンテナ起動中)を経て Running になる
  4. 最終的に abc12 が完全に削除される

注目すべきは、この一連の流れに人間の介入が一切なかったことです。

監視ツールのアラートもなく、運用担当者への電話もなく、深夜のSSH接続もなく、手順書の確認もありませんでした。

K8sは以下のループを自律的に実行しています。

  1. 観測:現在のPod数は? → 1台
  2. 比較:Desired State(replicas: 2)と一致するか? → No
  3. 実行:不足分を補うため、新しい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割は初動対応できます。


まとめ:今日あなたが手に入れたもの

本記事を通じて、あなたは以下を達成しました。

  1. K8sローカル環境の構築
    AlmaLinux 10上に、Docker + kind + kubectl の環境を整備しました。
  2. クラスターの作成と理解
    YAMLファイル1枚で「仮想データセンター」を召喚する体験をしました。
  3. 宣言的デプロイの実践
    「Nginxを2台」という状態をYAMLで宣言し、K8sがその通りに構築する様子を見ました。
  4. 自己修復(Self-healing)の目撃
    稼働中のPodを破壊し、K8sが自動で復旧させる様子をリアルタイムで観察しました。
  5. トラブルシューティングの基礎
    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 を実行すれば、いつでも同じ環境を再現できます。これもまた、宣言的インフラの恩恵です。