Kubernetesコアコンセプトと実践ガイド

Kubernetesアーキテクチャの主要コンポーネント

Kubernetesクラスターを構成する核心的な要素について、その役割と連携関係を理解します。

コントロールプレーンコンポーネント

  • APIサーバー:クラスター全体の統合的なエントリーポイント。すべての操作はこのコンポーネントを介して行われ、etcdとの連携により状態を管理します。
  • スケジューラー:新規Podの配置先ノードを決定する意思決定エンジン。リソース要件や制約条件に基づいて最適なノードを選択します。
  • コントローラーマネージャー:複数のコントローラープロセスを統合管理。ReplicaSetやDeploymentなどのコントローラーを実行し、望ましい状態を維持します。
  • etcd:分散型キーバリューストア。Raftコンセンサスアルゴリズムにより高い一貫性を保証し、WAL(Write-Ahead Logging)とスナップショット機能でデータ永続化を実現します。

ノードレベルコンポーネント

  • kubelet:各ノード上で動作するエージェント。CRI(Container Runtime Interface)を通じてコンテナランタイムと連携し、Podのライフサイクルを管理します。
  • kube-proxy:サービス抽象化を実現するネットワークプロキシ。IPTablesまたはIPVSルールを動的に生成・管理し、Pod間の通信経路を確立します。

アドオンツール

  • CoreDNS:クラスター内のサービスディスカバリーを担当。サービス名とIPアドレスの名前解決を提供します。
  • Ingressコントローラー:HTTP/HTTPSレイヤー7のルーティングを実現。NginxやTraefikなどの実装が存在します。
  • Prometheus:クラスターおよびアプリケーションの監視・メトリクス収集プラットフォーム。
  • ELKスタック:Elasticsearch、Logstash、Kibanaによるログ集約・分析基盤。

Pod:最小スケジュール単位

PodはKubernetesにおける基本的なデプロイ単位であり、1つ以上のコンテナをまとめて管理します。

Podの分類

  • 自律型Pod:手動で作成・管理されるPod。削除後は自動的に復旧されません。
  • コントローラー管理Pod:Deploymentなどのコントローラーにより管理され、常に指定されたレプリカ数が維持されます。

Pauseコンテナの役割

すべてのPodには隠しのPauseコンテナが含まれており、以下のリソースをPod内コンテナ間で共有します:

  • ネットワーク名前空間(IPアドレス、ポート範囲)
  • ストレージボリューム
  • IPC名前空間

注意点:Pod内のコンテナは同一ネットワークスタックを使用するため、ポート競合に注意が必要です。

ワークロードコントローラーの詳細

異なるユースケースに対応するための複数のコントローラータイプを理解しましょう。

DeploymentとReplicaSet

ステートレスアプリケーション向けの主要コントローラーです。

ReplicaSetの特性

  • 指定されたレプリカ数のPodを常に維持
  • ラベルセレクターを使用して管理対象Podを識別
  • 従来のReplicationControllerよりも柔軟なセレクターをサポート

Deploymentの機能

DeploymentはReplicaSetを管理することで間接的にPodを制御します(Deployment → ReplicaSet → Pod)。

# デプロイメントのスケーリング例
kubectl scale deployment webapp-deployment --replicas=5

# オートスケーリングの設定例
kubectl autoscale deployment webapp-deployment --min=2 --max=10 --cpu-percent=75

# イメージの更新例
kubectl set image deployment/webapp-deployment main-container=nginx:1.21

# ロールアウト操作例
kubectl rollout status deployment/webapp-deployment
kubectl rollout history deployment/webapp-deployment
kubectl rollout undo deployment/webapp-deployment --to-revision=3
kubectl rollout pause deployment/webapp-deployment

Deploymentは以下の機能を提供します:

  • 宣言的なアプリケーション管理
  • ローリングアップデートとロールバック
  • アップデート途中のPod数制御(maxUnavailable: 25%、maxSurge: 25%)
  • リビジョン履歴の管理(revisionHistoryLimitで制御可能)

Horizontal Pod Autoscaler(HPA)

メトリクスに基づいてPod数を自動調整する独立リソース。

  • CPU利用率に基づくスケーリング(v1)
  • カスタムメトリクス(メモリ、HTTPリクエスト数など)に基づくスケーリング(v2)
  • 適用対象:Deployment、ReplicaSet、StatefulSet

DaemonSet

特定のノード(または全ノード)で常に1つのPodを実行するコントローラー。

主な用途:

  • ログ収集エージェント(Fluentd、Filebeat)
  • 監視エージェント(Node Exporter、Datadog Agent)
  • クラスターストレージデーモン(Ceph、Portworx)

JobとCronJob

バッチ処理ワークロード向けのコントローラー。

Jobの特性

  • 1回限りのタスク実行を保証
  • RestartPolicyはNeverまたはOnFailureのみ有効
  • spec.completionsで成功要件数を指定
  • spec.parallelismで並行実行数を制御
  • spec.activeDeadlineSecondsでタイムアウトを設定

CronJobの特性

# CronJob定義例
apiVersion: batch/v1
kind: CronJob
metadata:
  name: backup-job
spec:
  schedule: "0 2 * * *"  # 毎日午前2時
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: backup-tool:latest
            command: ["/bin/sh", "-c", "backup.sh"]
          restartPolicy: OnFailure
  concurrencyPolicy: Forbid  # 前回ジョブが完了するまで次回実行を禁止
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 1

StatefulSet

ステートフルアプリケーション向けコントローラー。

  • 安定したストレージ:PVCを通じてPod再スケジュール後も同じデータにアクセス
  • 安定したネットワークID:Headless ServiceによりPod名とホスト名が維持
  • 順序付きデプロイ:0からN-1の順でPodが起動
  • 順序付き削除:N-1から0の順でPodが削除
  • DNS形式:$(podname).(headless-service).$(namespace).svc.cluster.local

Podのライフサイクルと状態管理

Podフェーズ

  • Pending:Podが承認されたが、コンテナ作成前の状態(イメージダウンロード中やスケジューリング中)
  • Running:少なくとも1つのコンテナが実行中、開始中、または再起動中
  • Succeeded:すべてのコンテナが正常終了し、再起動予定なし
  • Failed:すべてのコンテナが終了し、少なくとも1つが異常終了
  • Unknown:Pod状態を取得できない(通常はノード通信障害)

アプリケーションの分類

  • ステートレス:データ永続化が不要。例:Webサーバー、APIゲートウェイ
  • ステートフル:データ永続化が必須。例:MySQL、MongoDB、Kafka

初期化コンテナとヘルスチェック

Init Container

メインアプリケーションコンテナの前に実行される特殊コンテナ。

  • 必ず成功完了するまで実行
  • 複数定義可能(順次実行)
  • Pod再起動時は全Init Containerが再実行
  • ユースケース:設定ファイル生成、データベースマイグレーション、依存サービス待機

プローブ(Probe)

kubeletによるコンテナの定期的な診断チェック。

プローブタイプ

  • ExecAction:コンテナ内でコマンド実行。終了コード0で成功
  • HTTPGetAction:指定URLへのHTTP GETリクエスト。200-399のステータスコードで成功
  • TCPSocketAction:指定ポートへのTCP接続確認。接続成功で成功

プローブの用途

  • Readiness Probe:Podがトラフィックを受け入れる準備ができたか判定。失敗時はServiceからエンドポイント削除
  • Liveness Probe:コンテナが動作中か判定。失敗時はコンテナ再起動

リソース制限と要求

Kubernetesはcgroupを通じてリソースを制限します。

リクエストとリミット

# Podのリソース定義例
apiVersion: v1
kind: Pod
metadata:
  name: resource-demo
spec:
  containers:
  - name: app-container
    image: nginx:latest
    resources:
      requests:
        cpu: "100m"      # 0.1コア
        memory: "128Mi"  # 128メガバイト
      limits:
        cpu: "500m"      # 0.5コア
        memory: "512Mi"  # 512メガバイト
  • requests:スケジューリング時に保証される最小リソース量
  • limits:コンテナが使用可能な最大リソース量
  • CPUは圧縮可能リソース(超過時はスロットリング)
  • メモリは非圧縮可能リソース(超過時はOOM Killer)

ネットワークアーキテクチャ

通信パターン

  • 同一Pod内:localhost経由で直接通信(Pauseコンテナのネットワーク名前空間共有)
  • Pod間通信:CNIプラグインによるオーバーレイネットワーク(Flannel、Calico、Ciliumなど)
  • Pod-Service間:kube-proxyが管理するIPTables/IPVSルール経由
  • 外部-Service間:NodePort、LoadBalancer、Ingressを通じてアクセス

Flannelの動作原理

  • 各ノードに一意のサブネットを割り当て
  • etcdにサブネット情報を保存
  • UDP/VXLANでカプセル化通信
  • ホスト間のルーティングテーブルを動的に管理

リソースマニフェスト

YAML形式の定義ファイルでKubernetesオブジェクトを宣言的に管理します。

必須フィールド

フィールド説明
apiVersionstring使用するKubernetes APIのバージョン(例: v1, apps/v1)
kindstring作成するオブジェクトの種類(Pod, Deploymentなど)
metadata.namestringオブジェクトの一意識別名
specobjectオブジェクトの詳細仕様

コンテナ定義の主要フィールド

フィールド説明
containers[].namestringコンテナ名(Pod内で一意)
containers[].imagestring使用するコンテナイメージ
containers[].imagePullPolicystringAlways, Never, IfNotPresentのいずれか
containers[].command[]listコンテナ起動コマンド(ENTRYPOINT上書き)
containers[].args[]listコンテナ起動引数(CMD上書き)
containers[].env[]list環境変数定義
containers[].ports[]list公開ポート定義
containers[].resourcesobjectリソース要求と制限
containers[].volumeMounts[]listボリュームマウント設定

Podレベル設定

フィールド説明
spec.restartPolicystringAlways(デフォルト), OnFailure, Never
spec.nodeSelectorobjectノード選択ラベル(key: value形式)
spec.hostNetworkbooleantrueでホストネットワークを直接使用
spec.volumes[]listPodレベルボリューム定義

ServiceとIngress

Serviceのタイプ

  • ClusterIP:クラスター内のみアクセス可能な仮想IP(デフォルト)
  • NodePort:各ノードの特定ポートでServiceを公開
  • LoadBalancer:クラウドプロバイダーのロードバランサーと連携
  • ExternalName:外部サービスをクラスター内で参照可能に

Headless Service

spec.clusterIPを"None"に設定することで、kube-proxyによるロードバランシングをバイパスします。DNS経由で直接Pod IPにアクセス可能になります。

kube-proxyの動作モード

  • iptablesモード:IPTablesルールでパケット転送(Kubernetes 1.10以前のデフォルト)
  • ipvsモード:IPVSカーネルレベルロードバランサーを使用(1.11以降推奨)
  • nftablesモード:iptablesの後継となるnftablesを使用(実験的)

Ingressの役割

HTTP/HTTPSレイヤー7のルーティングを提供します。

# Ingress定義例
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: webapp-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080
      - path: /static
        pathType: Prefix
        backend:
          service:
            name: frontend-service
            port:
              number: 80

ストレージ管理

ConfigMap

設定データをPodに注入するためのリソース。

# ディレクトリから作成
kubectl create configmap webapp-config --from-file=./config/

# ファイルから作成
kubectl create configmap db-settings --from-file=./config/database.conf

# リテラル値から作成
kubectl create configmap feature-flags --from-literal=cache.enabled=true --from-literal=log.level=debug

# ConfigMapの使用例
apiVersion: v1
kind: Pod
metadata:
  name: configmap-demo
spec:
  containers:
  - name: app
    image: nginx:latest
    env:
    - name: CACHE_ENABLED
      valueFrom:
        configMapKeyRef:
          name: feature-flags
          key: cache.enabled
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
  volumes:
  - name: config-volume
    configMap:
      name: db-settings

更新動作

  • ボリュームマウントの場合:約10秒で自動反映
  • 環境変数の場合:ConfigMap更新後もPod再起動が必要
  • アノテーション変更によるローリングアップデートで強制反映可能

Secret

機密情報(パスワード、トークン、鍵)を安全に管理します。

Secretのタイプ

  • Opaque:Base64エンコードされた汎用データ(デフォルト)
  • kubernetes.io/dockerconfigjson:Dockerレジストリ認証情報
  • kubernetes.io/service-account-token:ServiceAccount用トークン(自動マウント)
# DockerレジストリSecret作成
kubectl create secret docker-registry regcred \
  --docker-server=private.registry.io \
  --docker-username=admin \
  --docker-password=secretpass \
  --docker-email=admin@example.com

# Secretの使用例
apiVersion: v1
kind: Pod
metadata:
  name: secret-demo
spec:
  containers:
  - name: db-client
    image: mysql-client:latest
    env:
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: password

Volumeタイプ

emptyDir

Podのライフサイクルに紐づく一時的なストレージ。

  • Pod作成時に空のディレクトリを生成
  • コンテナクラッシュ時もデータ保持(Pod削除時に消滅)
  • 用途:一時作業領域、チェックポイントデータ、コンテナ間データ共有

hostPath

ノードのファイルシステムをPodにマウントします。

タイプ動作
DirectoryOrCreate指定パスが存在しない場合、空ディレクトリを作成(パーミッション755)
Directory指定パスがディレクトリであることを要求
FileOrCreate指定パスが存在しない場合、空ファイルを作成(パーミッション644)
File指定パスがファイルであることを要求

PersistentVolume(PV)とPersistentVolumeClaim(PVC)

  • PV:クラスター管理者がプロビジョニングするストレージリソース
  • PVC:ユーザーが要求するストレージ
  • Binding:PVとPVCの一対一のマッピング
  • StorageClass:動的プロビジョニングのためのストレージテンプレート
# PVC定義例
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-data
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: fast-ssd

# Podでの使用例
apiVersion: v1
kind: Pod
metadata:
  name: mysql-pod
spec:
  containers:
  - name: mysql
    image: mysql:8.0
    volumeMounts:
    - name: data-volume
      mountPath: /var/lib/mysql
  volumes:
  - name: data-volume
    persistentVolumeClaim:
      claimName: mysql-data

スケジューリングメカニズム

ノードアフィニティ

Podを特定のノードに割り当てるためのルール。

# ノードアフィニティ例
apiVersion: v1
kind: Pod
metadata:
  name: affinity-demo
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: node-type
            operator: In
            values: ["compute", "gpu"]
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: zone
            operator: In
            values: ["asia-northeast1-a"]
  containers:
  - name: app
    image: nginx:latest

Podアフィニティ/アンチアフィニティ

Pod間の配置関係を制御します。

  • PodAffinity:特定のPodと同じノードに配置
  • PodAntiAffinity:特定のPodと異なるノードに配置(高可用性確保に有効)

Taint(汚染)とToleration(容認)

ノードが特定のPodを排斥または許可するメカニズム。

Taintの設定

# Taintの付与
kubectl taint nodes node1 workload=high-priority:NoSchedule

# Taintの削除
kubectl taint nodes node1 workload:NoSchedule-

# Taintの効果
# NoSchedule: 新規Podのスケジューリングを拒否
# PreferNoSchedule: 可能な限りスケジューリングを回避
# NoExecute: 新規スケジューリング拒否 + 既存Podの追い出し

Tolerationの設定

# PodでのToleration定義例
apiVersion: v1
kind: Pod
metadata:
  name: tolerant-pod
spec:
  tolerations:
  - key: "workload"
    operator: "Equal"
    value: "high-priority"
    effect: "NoSchedule"
    tolerationSeconds: 3600  # NoExecute時の猶予時間(秒)
  containers:
  - name: app
    image: nginx:latest

スケジューラーの動作フロー

  1. Filtering(Predicate):条件を満たさないノードを除外
    • リソース要件チェック(PodFitsResources)
    • ノードセレクターマッチング(PodSelectorMatches)
    • ポート競合チェック(PodFitsHostPorts)
    • ストレージ競合チェック(NoDiskConflict)
  2. Scoring(Priority):適格ノードに優先度を付けてソート
    • リソース使用率(LeastRequestedPriority)
    • リソースバランス(BalancedResourceAllocation)
    • イメージローカル性(ImageLocalityPriority)
  3. Binding:最も高いスコアのノードにPodを割り当て

セキュリティモデル

認証(Authentication)

クライアントIDの検証方法。

  • クライアント証明書:TLSクライアント証明書による認証(最も一般的)
  • ベアラートークン:サービスアカウントトークン(JWT形式)
  • HTTP基本認証:ユーザー名/パスワード(非推奨)

認可(Authorization)

RBAC(Role-Based Access Control)がデファクトスタンダードです。

RBACリソース

  • Role:名前空間レベルの権限定義
  • ClusterRole:クラスターレベルの権限定義
  • RoleBinding:Roleを特定のユーザー/グループ/SAに紐付け(名前空間内)
  • ClusterRoleBinding:ClusterRoleをクラスター全体に紐付け
# Role定義例
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: production
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

# RoleBinding定義例
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: production
subjects:
- kind: User
  name: jane
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

ServiceAccount

PodからAPIサーバーにアクセスするためのID。

  • 各名前空間にデフォルトのServiceAccountが存在
  • Pod作成時に自動マウント(/var/run/secrets/kubernetes.io/serviceaccount/)
  • 必要に応じてカスタムServiceAccountを作成・割り当て可能

アドミッションコントローラー

オブジェクト永続化前にリクエストを検証・変更するプラグイン。

  • NamespaceLifecycle:終了中の名前空間へのオブジェクト作成を拒否
  • LimitRanger:デフォルトリソース制限の適用
  • ResourceQuota:名前空間レベルのリソース使用量制限
  • PodSecurityPolicy:Podのセキュリティコンテキスト制限
  • MutatingAdmissionWebhook:外部Webhookによるリクエスト変更

パッケージ管理:Helm

HelmはKubernetesアプリケーションのパッケージマネージャーです。

  • Chart:アプリケーションのパッケージ化定義
  • Release:クラスターにデプロイされたChartのインスタンス
  • Repository:Chartの公開・共有のためのリポジトリ
# Chartインストール例
helm install my-app ./my-chart --namespace production

# リリースアップグレード例
helm upgrade my-app ./my-chart --set image.tag=2.0

# リリースロールバック例
helm rollback my-app 1

# リポジトリ追加例
helm repo add stable https://charts.helm.sh/stable

高可用性設計

  • コントロールプレーンは最低3ノードの奇数構成を推奨(クォーラム維持のため)
  • etcdはSSDストレージ上に配置し、バックアップを定期実施
  • マスターノードは物理的に分散配置(異なるラック/ゾーン)
  • LoadBalancerまたはVIPでAPIサーバーの冗長化
  • kubeadmによる証明書の有効期限はデフォルト1年→10年に延長可能
# 証明書有効期限の確認
kubeadm certs check-expiration

# 証明書の手動更新
kubeadm certs renew all

タグ: Kubernetes コンテナオーケストレーション kubelet kube-proxy etcd

8月28日 15:15 投稿