目次

読了時間: 約14分 | 文字数: 約5,200字

2026 年現在、クラウドネイティブなシステムを構築する上で Kubernetes(クベルテス、略して K8s)は事実上の標準となっている。しかし、「Kubernetes を使っている」という多くのチームが、その内部動作を理解しないまま YAML をコピーペーストしているのが実情だ。本稿では、Kubernetes の核心概念を整理し、「なぜその仕組みなのか」を理解するための基礎を固める。

なぜ Kubernetes が必要になったのか

コンテナの普及とその限界

2010 年代半ば、Docker の登場により「コンテナ」という技術が広まった。コンテナは以下の利点をもたらした:

  • 環境非依存性: 「開発環境では動いたのに本番で動かない」問題の解消
  • 軽量さ: 仮想マシンより起動が速く、リソース効率が良い
  • 再現性: イメージさえあれば誰でも同じ環境を再現可能

しかし、コンテナが普及するにつれて、新しい問題が浮上した。

分散システム運用の複雑さ

問題 1: 障害対応
「コンテナが落ちた…誰が再起動する?」

問題 2: スケーリング
「アクセスが 10 倍になった。コンテナを 10 個に増やしたい」

問題 3: ローリングアップデート
「新版本をダウンタイムなくデプロイしたい」

問題 4: サービスディスカバリー
「コンテナ A からコンテナ B にリクエストを送りたいが、IP が分からない」

問題 5: リソース管理
「100 個のコンテナを 5 台のサーバーにどう割り当てる?」

これらの問題を解決するコンテナオーケストレーションツールが必要になった。そして最終的に、Kubernetes が勝者となった。

Kubernetes の基本概念

1. クラスターとノード

クラスター: Kubernetes が管理するコンピューティングリソースの集合 ノード: クラスターを構成する個々のサーバー(物理 or 仮想)

                    ┌─────────────────────────────────┐
                    │         Kubernetes Cluster      │
                    │                                 │
    ┌───────────────┼───────────────┐                 │
    │   Control     │    Node 1     │    Node 2       │    Node 3       │
    │    Plane      │  ┌─────────┐  │  ┌─────────┐  │  ┌─────────┐  │
    │  (管理機能)   │  │ Pod     │  │  │ Pod     │  │  │ Pod     │  │
    │               │  │ Pod     │  │  │ Pod     │  │  │ Pod     │  │
    │  - API Server │  │ Pod     │  │  │ Pod     │  │  │ Pod     │  │
    │  - Scheduler  │  └─────────┘  │  └─────────┘  │  └─────────┘  │
    │  - Controller │               │               │               │
    │  - etcd       │               │               │               │
    └───────────────┴───────────────┴───────────────┴───────────────┘

Control Plane(管理プレーン): クラスター全体の意思決定を行う「頭脳」 Worker Node(ワーカーノード): 実際にコンテナを動かす「作業員」

2. ポッド——最小デプロイ単位

ポッド: Kubernetes における最小のデプロイ単位。1 つ以上のコンテナを含む。

apiVersion: v1
kind: Pod
metadata:
  name: my-app-pod
spec:
  containers:
  - name: app
    image: myapp:1.0
    ports:
    - containerPort: 8080
  - name: sidecar
    image: logger:1.0
    # メインコンテナのログを収集する補助コンテナ

重要なポイント:

  • ポッド内のコンテナは同じ IP アドレスを共有する
  • ポッド内のコンテナはlocalhostで通信できる
  • ポッドは使い捨てとして設計される(不変インフラ)

3. デプロイメント——ポッドの管理

デプロイメント: ポッドのレプリカ数とバージョンを管理する。自己修復機能を持つ。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-deployment
spec:
  replicas: 3  # 常に 3 つのポッドを維持
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: app
        image: myapp:1.0

デプロイメントの機能:

  • 自己修復: ポッドが落ちたら自動で再起動
  • スケーリング: レプリカ数を変更可能
  • ローリングアップデート: ダウンタイムなくバージョンアップ
# 4 つにスケールアップ
kubectl scale deployment my-app-deployment --replicas=4

# バージョン 2.0 にアップデート
kubectl set image deployment/my-app-deployment app=myapp:2.0

# ロールバック
kubectl rollout undo deployment/my-app-deployment

4. サービス——安定したネットワークエンドポイント

サービス: 動的に変わるポッドの IP を抽象化し、安定したエンドポイントを提供する。

問題:ポッドは再起動で IP が変わる
→ サービス経由でアクセスすれば、裏側のポッドが入れ替わっても影響なし

            ┌─────────────────┐
            │   Service       │
            │  10.0.0.100:80  │
            └────────┬────────┘
                     │
        ┌────────────┼────────────┐
        ↓            ↓            ↓
   ┌─────────┐  ┌─────────┐  ┌─────────┐
   │  Pod 1  │  │  Pod 2  │  │  Pod 3  │
   │ 10.244.1│  │ 10.244.2│  │ 10.244.3│
   └─────────┘  └─────────┘  └─────────┘
apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  selector:
    app: my-app
  ports:
  - port: 80
    targetPort: 8080
  type: ClusterIP  # クラスター内からのみアクセス可能

サービスタイプ:

タイプ用途
ClusterIPクラスター内からのアクセス(デフォルト)
NodePort各ノードの IP で外部公開
LoadBalancerクラウドの LB を自動プロビジョニング
ExternalName外部サービスへのポインタ

5. ConfigMap と Secret——設定管理

ConfigMap: 環境変数や設定ファイルをポッドに注入する。 Secret: パスワードや API キーなどの機密情報を保存する(Base64 エンコード)。

# ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  DATABASE_HOST: "db.example.com"
  LOG_LEVEL: "info"

# Secret
apiVersion: v1
kind: Secret
metadata:
  name: app-secret
type: Opaque
data:
  DATABASE_PASSWORD: cGFzc3dvcmQxMjM=  # Base64
# ポッドで使用
apiVersion: v1
kind: Pod
metadata:
  name: my-app-pod
spec:
  containers:
  - name: app
    image: myapp:1.0
    envFrom:
    - configMapRef:
        name: app-config
    - secretRef:
        name: app-secret

Kubernetes のアーキテクチャ

コアコンポーネント

┌─────────────────────────────────────────────────────────────┐
│                    Control Plane                            │
├─────────────────────────────────────────────────────────────┤
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │  API Server  │  │  Scheduler   │  │  Controller  │      │
│  │              │  │              │  │   Manager    │      │
│  └──────┬───────┘  └──────────────┘  └──────────────┘      │
│         │                                                  │
│  ┌──────▼───────┐                                          │
│  │     etcd     │  ← クラスターの「真実の源泉」            │
│  └──────────────┘                                          │
└─────────────────────────────────────────────────────────────┘
                            │
                            │ API 通信
                            ↓
┌─────────────────────────────────────────────────────────────┐
│                      Worker Node                            │
├─────────────────────────────────────────────────────────────┤
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │   kubelet    │  │  kube-proxy  │  │    Pod       │      │
│  │              │  │              │  │  (Container) │      │
│  └──────────────┘  └──────────────┘  └──────────────┘      │
└─────────────────────────────────────────────────────────────┘

各コンポーネントの役割:

コンポーネント役割
API Serverクラスターへの唯一のアクセス窓口。認証・認可・バリデーション
Scheduler新規ポッドをどのノードに割り当てるか決定
Controller Manager様々なコントローラーを動作させ、状態を望ましい状態に維持
etcd分散 KV ストア。クラスターの全状態を保存
kubelet各ノードで動作し、ポッドのライフサイクルを管理
kube-proxyサービスのネットワーク機能を担当

実践:Kubernetes でのアプリケーションデプロイ

最小のデプロイ例

# 1. 名前空間を作成
kubectl create namespace my-app

# 2. デプロイメントを作成
kubectl create deployment my-app --image=nginx:1.21 -n my-app

# 3. サービスを作成
kubectl expose deployment my-app --port=80 --type=LoadBalancer -n my-app

# 4. 状態を確認
kubectl get pods -n my-app
kubectl get services -n my-app

本番構成の YAML 例

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  namespace: production
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0  # ダウンタイムゼロ
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
      - name: web
        image: myregistry/web-app:1.2.3
        ports:
        - containerPort: 8080
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5

So What?——実務への応用

  • ポッドは使い捨て: 個々のポッドに愛着を持たない。常に「どのポッドでも落ちる」前提で設計
  • デプロイメントで管理: 直接ポッドを作らず、デプロイメント経由で作る(自己修復のため)
  • サービスで抽象化: アプリケーションはポッド IP ではなく、サービス名で通信する
  • リソース制限を必ず設定: 制限がないと 1 つのポッドが全リソースを消費する可能性
  • ヘルスチェックを実装: livenessProbe/readinessProbe で異常検知とトラフィック制御
  • 名前空間で分離: 環境(dev/staging/prod)やチームごとに名前空間を使い分ける

Kubernetes は複雑だが、その複雑さは「分散システムの運用の複雑さ」を抽象化しているに過ぎない。基本概念を理解すれば、YAML を書くだけの作業から脱却できる。

参考リンク

免責事項 — 掲載情報は執筆時点のものです。料金・機能は変更される場合があります。最新情報は各公式サイトをご確認ください。