Kubernetes
Kubernetes完全ガイド — コンテナオーケストレーションの全容
はじめに
Kubernetes(K8s)は、Googleが社内システム「Borg」の運用経験を基に2014年にオープンソースとして公開したコンテナオーケストレーションプラットフォームである。現在はCloud Native Computing Foundation(CNCF)が管理しており、コンテナ化されたアプリケーションのデプロイ、スケーリング、運用を自動化するデファクトスタンダードとなっている。
本記事では、Kubernetesのアーキテクチャ、コアリソース、ネットワーキング、ストレージ、セキュリティ、オブザーバビリティ、運用ベストプラクティスまで、Kubernetesの全容を体系的に解説する。
第1章: Kubernetesアーキテクチャ
1.1 クラスタ構成
┌─────────────────────────── Kubernetes Cluster ───────────────────────────┐
│ │
│ ┌─────────────── Control Plane ──────────────┐ │
│ │ │ │
│ │ ┌──────────┐ ┌──────────────┐ │ │
│ │ │ kube-api │ │ etcd │ │ │
│ │ │ server │ │ (分散KVS) │ │ │
│ │ └──────────┘ └──────────────┘ │ │
│ │ ┌──────────────┐ ┌───────────────────┐ │ │
│ │ │ kube-scheduler│ │ controller-manager│ │ │
│ │ └──────────────┘ └───────────────────┘ │ │
│ │ ┌──────────────────────┐ │ │
│ │ │ cloud-controller-mgr │ (クラウド連携) │ │
│ │ └──────────────────────┘ │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ ┌───── Worker Node 1 ─────┐ ┌───── Worker Node 2 ─────┐ │
│ │ ┌────────┐ ┌──────────┐ │ │ ┌────────┐ ┌──────────┐ │ │
│ │ │kubelet │ │kube-proxy│ │ │ │kubelet │ │kube-proxy│ │ │
│ │ └────────┘ └──────────┘ │ │ └────────┘ └──────────┘ │ │
│ │ ┌─────────────────────┐ │ │ ┌─────────────────────┐ │ │
│ │ │ Container Runtime │ │ │ │ Container Runtime │ │ │
│ │ │ (containerd/CRI-O) │ │ │ │ (containerd/CRI-O) │ │ │
│ │ └─────────────────────┘ │ │ └─────────────────────┘ │ │
│ │ ┌─Pod─┐ ┌─Pod─┐ ┌Pod┐ │ │ ┌─Pod─┐ ┌─Pod─┐ │ │
│ │ │ C1 │ │C1 C2│ │C1 │ │ │ │ C1 │ │C1 C2│ │ │
│ │ └─────┘ └─────┘ └───┘ │ │ └─────┘ └─────┘ │ │
│ └─────────────────────────┘ └─────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────┘
1.2 コントロールプレーンコンポーネント
| コンポーネント | 役割 |
|---|---|
| kube-apiserver | Kubernetes APIのフロントエンド。すべての操作はAPIサーバーを経由 |
| etcd | クラスタの状態を保存する分散キーバリューストア |
| kube-scheduler | 新しいPodを最適なNodeに割り当てる |
| kube-controller-manager | コントローラーの実行(ReplicaSet, Deployment, Node等) |
| cloud-controller-manager | クラウドプロバイダー固有のコントローラー |
1.3 ワーカーノードコンポーネント
| コンポーネント | 役割 |
|---|---|
| kubelet | ノード上のPodのライフサイクル管理 |
| kube-proxy | ネットワークルールの管理(Service → Pod のルーティング) |
| Container Runtime | コンテナの実行(containerd, CRI-O) |
1.4 kubectlの基本操作
# クラスタ情報
$ kubectl cluster-info
$ kubectl get nodes -o wide
$ kubectl api-resources
# リソースの取得
$ kubectl get pods -n default
$ kubectl get pods -A # 全ネームスペース
$ kubectl get pods -o wide # 詳細表示
$ kubectl get pods -o yaml # YAML出力
$ kubectl get pods -l app=nginx # ラベルセレクタ
$ kubectl get pods --field-selector status.phase=Running
# リソースの詳細
$ kubectl describe pod my-pod
$ kubectl describe node worker-01
# リソースの作成・適用
$ kubectl apply -f deployment.yaml
$ kubectl create namespace staging
# ログとデバッグ
$ kubectl logs my-pod
$ kubectl logs my-pod -c sidecar # 特定コンテナ
$ kubectl logs -f my-pod # フォロー
$ kubectl logs --previous my-pod # 前回のコンテナ
# コンテナに接続
$ kubectl exec -it my-pod -- /bin/sh
$ kubectl exec -it my-pod -c sidecar -- /bin/sh
# ポートフォワード
$ kubectl port-forward svc/my-service 8080:80
$ kubectl port-forward pod/my-pod 5432:5432
# リソースの削除
$ kubectl delete -f deployment.yaml
$ kubectl delete pod my-pod --grace-period=0 --force
# コンテキスト管理
$ kubectl config get-contexts
$ kubectl config use-context production
$ kubectl config set-context --current --namespace=staging
第2章: コアリソース — Pod
2.1 Podの基本
# pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
namespace: default
labels:
app: nginx
environment: production
annotations:
description: "Nginx web server"
spec:
containers:
- name: nginx
image: nginx:1.25-alpine
ports:
- containerPort: 80
name: http
resources:
requests:
cpu: "100m" # 0.1 CPU コア
memory: "128Mi" # 128 MiB
limits:
cpu: "500m" # 0.5 CPU コア
memory: "256Mi" # 256 MiB
env:
- name: NGINX_PORT
value: "80"
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/conf.d
livenessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 10
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 5
periodSeconds: 5
startupProbe:
httpGet:
path: /healthz
port: 80
failureThreshold: 30
periodSeconds: 10
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "nginx -s quit; sleep 10"]
volumes:
- name: config-volume
configMap:
name: nginx-config
restartPolicy: Always
terminationGracePeriodSeconds: 30
serviceAccountName: nginx-sa
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
2.2 プローブの種類
| プローブ | 目的 | 失敗時の動作 |
|---|---|---|
| livenessProbe | コンテナが生存しているか | コンテナを再起動 |
| readinessProbe | トラフィックを受け付けられるか | Serviceのエンドポイントから除外 |
| startupProbe | 起動が完了したか | 完了するまでliveness/readinessを無効化 |
# プローブのタイプ
# HTTP GET
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: Custom-Header
value: "probe"
# TCP Socket
livenessProbe:
tcpSocket:
port: 3306
# Exec
livenessProbe:
exec:
command:
- /bin/sh
- -c
- pg_isready -U postgres
# gRPC (Kubernetes 1.24+)
livenessProbe:
grpc:
port: 50051
2.3 マルチコンテナパターン
# Sidecarパターン(ログ収集)
spec:
containers:
- name: app
image: myapp:v1
volumeMounts:
- name: logs
mountPath: /var/log/app
- name: log-shipper
image: fluentd:v1.16
volumeMounts:
- name: logs
mountPath: /var/log/app
readOnly: true
volumes:
- name: logs
emptyDir: {}
# Init Containerパターン(前処理)
spec:
initContainers:
- name: wait-for-db
image: busybox:1.36
command: ['sh', '-c', 'until nc -z db-service 5432; do echo waiting; sleep 2; done']
- name: migrate
image: myapp-migrate:v1
command: ['./migrate', 'up']
containers:
- name: app
image: myapp:v1
第3章: ワークロードリソース
3.1 Deployment
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
namespace: production
labels:
app: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web-app
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # ローリングアップデート中に追加できるPod数
maxUnavailable: 0 # 更新中に使用不可にできるPod数
template:
metadata:
labels:
app: web-app
version: v2
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values: [web-app]
topologyKey: kubernetes.io/hostname
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: web-app
containers:
- name: web-app
image: myregistry/web-app:v2.1.0
ports:
- containerPort: 8080
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "1000m"
memory: "512Mi"
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
# デプロイ操作
$ kubectl apply -f deployment.yaml
$ kubectl rollout status deployment/web-app
$ kubectl rollout history deployment/web-app
# ロールバック
$ kubectl rollout undo deployment/web-app
$ kubectl rollout undo deployment/web-app --to-revision=2
# スケーリング
$ kubectl scale deployment/web-app --replicas=5
# イメージの更新
$ kubectl set image deployment/web-app web-app=myregistry/web-app:v2.2.0
# 一時停止/再開
$ kubectl rollout pause deployment/web-app
$ kubectl rollout resume deployment/web-app
3.2 StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: postgres-headless
replicas: 3
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16-alpine
ports:
- containerPort: 5432
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: fast-ssd
resources:
requests:
storage: 100Gi
StatefulSetの特徴:
- Pod名が順序付き(postgres-0, postgres-1, postgres-2)
- 順序付きデプロイ/スケーリング/削除
- 安定したネットワークID(
<pod-name>.<service-name>.<namespace>.svc.cluster.local) - 永続ストレージ(VolumeClaimTemplates)
3.3 DaemonSet
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
namespace: kube-system
spec:
selector:
matchLabels:
app: fluentd
template:
metadata:
labels:
app: fluentd
spec:
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
containers:
- name: fluentd
image: fluentd:v1.16
resources:
limits:
memory: "200Mi"
requests:
cpu: "100m"
memory: "200Mi"
volumeMounts:
- name: varlog
mountPath: /var/log
- name: containers
mountPath: /var/lib/docker/containers
readOnly: true
volumes:
- name: varlog
hostPath:
path: /var/log
- name: containers
hostPath:
path: /var/lib/docker/containers
3.4 Job / CronJob
# Job
apiVersion: batch/v1
kind: Job
metadata:
name: db-migration
spec:
backoffLimit: 3
activeDeadlineSeconds: 600
template:
spec:
containers:
- name: migrate
image: myapp-migrate:v1
command: ["./migrate", "up"]
restartPolicy: Never
---
# CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: backup-job
spec:
schedule: "0 2 * * *" # 毎日午前2時
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: backup-tool:v1
command: ["./backup.sh"]
restartPolicy: OnFailure
3.5 HPA(Horizontal Pod Autoscaler)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-app
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "1000"
behavior:
scaleUp:
stabilizationWindowSeconds: 30
policies:
- type: Pods
value: 4
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
第4章: Service とネットワーキング
4.1 Serviceの種類
# ClusterIP(デフォルト — クラスタ内部のみ)
apiVersion: v1
kind: Service
metadata:
name: web-app-service
spec:
type: ClusterIP
selector:
app: web-app
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
---
# NodePort(ノードのポートで公開)
apiVersion: v1
kind: Service
metadata:
name: web-app-nodeport
spec:
type: NodePort
selector:
app: web-app
ports:
- port: 80
targetPort: 8080
nodePort: 30080 # 30000-32767
---
# LoadBalancer(クラウドLBで公開)
apiVersion: v1
kind: Service
metadata:
name: web-app-lb
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: nlb
spec:
type: LoadBalancer
selector:
app: web-app
ports:
- port: 443
targetPort: 8080
---
# Headless Service(StatefulSet用)
apiVersion: v1
kind: Service
metadata:
name: postgres-headless
spec:
clusterIP: None
selector:
app: postgres
ports:
- port: 5432
4.2 Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/rate-limit: "100"
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- www.example.com
- api.example.com
secretName: tls-secret
rules:
- host: www.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-frontend
port:
number: 80
- host: api.example.com
http:
paths:
- path: /v1
pathType: Prefix
backend:
service:
name: api-v1
port:
number: 80
- path: /v2
pathType: Prefix
backend:
service:
name: api-v2
port:
number: 80
4.3 NetworkPolicy
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-network-policy
namespace: production
spec:
podSelector:
matchLabels:
app: api-server
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
environment: production
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: postgres
ports:
- protocol: TCP
port: 5432
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
第5章: 設定管理とストレージ
5.1 ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
# キー-値ペア
DATABASE_HOST: "postgres.production.svc.cluster.local"
DATABASE_PORT: "5432"
LOG_LEVEL: "info"
# ファイルとしてマウント可能な設定
nginx.conf: |
server {
listen 80;
server_name _;
location / {
proxy_pass http://backend:8080;
}
}
# ConfigMapの使用
spec:
containers:
- name: app
image: myapp:v1
# 環境変数として
envFrom:
- configMapRef:
name: app-config
# 個別の環境変数として
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DATABASE_HOST
# ボリュームとしてマウント
volumeMounts:
- name: config
mountPath: /etc/nginx/conf.d
volumes:
- name: config
configMap:
name: app-config
items:
- key: nginx.conf
path: default.conf
5.2 Secret
# Secretの作成
$ kubectl create secret generic db-secret \
--from-literal=username=admin \
--from-literal=password='S3cr3tP@ss'
# ファイルから
$ kubectl create secret generic tls-secret \
--from-file=tls.crt=./server.crt \
--from-file=tls.key=./server.key
# Docker Registry用
$ kubectl create secret docker-registry regcred \
--docker-server=myregistry.example.com \
--docker-username=user \
--docker-password=pass
# Secret定義(base64エンコード)
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
username: YWRtaW4= # echo -n "admin" | base64
password: UzNjcjN0UEBzcw== # echo -n "S3cr3tP@ss" | base64
# stringDataを使用(自動的にbase64エンコード)
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
stringData:
username: admin
password: S3cr3tP@ss
5.3 PersistentVolume / PersistentVolumeClaim
# StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: ebs.csi.aws.com
parameters:
type: gp3
iops: "5000"
throughput: "250"
reclaimPolicy: Retain
allowVolumeExpansion: true
volumeBindingMode: WaitForFirstConsumer
---
# PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-data
spec:
accessModes:
- ReadWriteOnce
storageClassName: fast-ssd
resources:
requests:
storage: 100Gi
第6章: セキュリティ
6.1 RBAC(Role-Based Access Control)
# Role(ネームスペーススコープ)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: production
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list"]
---
# RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: production
subjects:
- kind: User
name: developer@example.com
apiGroup: rbac.authorization.k8s.io
- kind: ServiceAccount
name: monitoring-sa
namespace: monitoring
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
---
# ClusterRole(クラスタスコープ)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: node-reader
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
6.2 Pod Security
# Pod Security Standards (PSS) — ネームスペースレベル
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
---
# SecurityContext
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: myapp:v1
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
第7章: オブザーバビリティと運用
7.1 リソース監視
# リソース使用状況
$ kubectl top nodes
$ kubectl top pods -n production
$ kubectl top pods --sort-by=cpu
# イベント確認
$ kubectl get events -n production --sort-by=.lastTimestamp
$ kubectl get events --field-selector type=Warning
# デバッグ
$ kubectl describe pod problematic-pod
$ kubectl logs problematic-pod --previous
$ kubectl debug -it problematic-pod --image=busybox --target=app
7.2 Prometheus + Grafana スタック
# ServiceMonitor(Prometheus Operator)
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: web-app-monitor
labels:
release: prometheus
spec:
selector:
matchLabels:
app: web-app
endpoints:
- port: metrics
path: /metrics
interval: 15s
---
# PrometheusRule(アラート定義)
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: web-app-alerts
spec:
groups:
- name: web-app
rules:
- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m]))
/ sum(rate(http_requests_total[5m])) > 0.01
for: 5m
labels:
severity: critical
annotations:
summary: "High error rate detected"
- alert: HighLatency
expr: |
histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))
> 2
for: 5m
labels:
severity: warning
7.3 ベストプラクティス
# 本番環境のDeploymentチェックリスト
spec:
replicas: 3 # ✅ 複数レプリカ
strategy:
type: RollingUpdate # ✅ ローリングアップデート
rollingUpdate:
maxSurge: 1
maxUnavailable: 0 # ✅ ゼロダウンタイム
template:
spec:
topologySpreadConstraints: # ✅ AZ分散
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
containers:
- name: app
image: myapp:v2.1.0@sha256:abc # ✅ イメージダイジェスト
resources: # ✅ リソース制限
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "1000m"
memory: "512Mi"
readinessProbe: ... # ✅ ヘルスチェック
livenessProbe: ... # ✅ ヘルスチェック
securityContext: # ✅ セキュリティ
runAsNonRoot: true
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
serviceAccountName: web-app-sa # ✅ 専用ServiceAccount
まとめ
Kubernetesはコンテナオーケストレーションのデファクトスタンダードである:
- アーキテクチャ: Control Plane(API Server, etcd, Scheduler, Controller Manager)+ Worker Node(kubelet, kube-proxy)
- ワークロード: Deployment、StatefulSet、DaemonSet、Job/CronJob、HPA
- ネットワーキング: Service(ClusterIP/NodePort/LoadBalancer)、Ingress、NetworkPolicy
- 設定管理: ConfigMap、Secret、PV/PVC、StorageClass
- セキュリティ: RBAC、Pod Security Standards、SecurityContext、NetworkPolicy
- オブザーバビリティ: Prometheus/Grafana、ログ管理、イベント監視
- 運用: ローリングアップデート、ロールバック、リソース管理
参考文献
- Kubernetes公式ドキュメント: https://kubernetes.io/docs/
- "Kubernetes in Action" - Marko Lukša
- "Kubernetes Up & Running" - Brendan Burns, Joe Beda, Kelsey Hightower
- "Production Kubernetes" - Josh Rosso et al.
- CNCF Landscape: https://landscape.cncf.io/
- Kubernetes Patterns: https://k8spatterns.io/