Kubernetes入門ガイド2026 — コンテナオーケストレーションを基礎から解説
「Kubernetesって難しそう」と感じていませんか?確かに学習曲線は急ですが、基本概念を理解すれば、アプリケーションのデプロイ・スケーリング・運用が劇的に楽になります。この記事では、Kubernetesの基礎から実践的な使い方まで、2026年の最新情報とともに解説します。
Kubernetesとは何か?
Kubernetes(k8s)は、コンテナ化されたアプリケーションを自動でデプロイ、スケール、管理するオープンソースプラットフォームです。
なぜKubernetesが必要か?
Dockerだけの場合:
# 手動で各サーバーにデプロイ
ssh server1 "docker run myapp"
ssh server2 "docker run myapp"
ssh server3 "docker run myapp"
# コンテナが落ちたら手動で再起動
ssh server1 "docker ps | grep myapp || docker run myapp"
# ロードバランシング設定も手動
# スケールアウトも手動
# アップデートも手動で1台ずつ
Kubernetesの場合:
# デプロイ設定を宣言するだけ
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3 # 3台で動かしたい
template:
spec:
containers:
- name: myapp
image: myapp:v1.0
kubectl apply -f deployment.yaml
# あとは自動で:
# - 3台のコンテナ起動
# - 障害時の自動再起動
# - ロードバランシング
# - ローリングアップデート
基本概念
1. Pod(最小単位)
Podは1つ以上のコンテナをまとめたもの。Kubernetesの最小デプロイ単位です。
# pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
# Pod作成
kubectl apply -f pod.yaml
# Pod確認
kubectl get pods
# Pod詳細
kubectl describe pod nginx-pod
# ログ確認
kubectl logs nginx-pod
# Pod削除
kubectl delete pod nginx-pod
複数コンテナを含むPod:
apiVersion: v1
kind: Pod
metadata:
name: app-with-sidecar
spec:
containers:
# メインアプリケーション
- name: app
image: myapp:1.0
ports:
- containerPort: 8080
# サイドカー(ログ収集)
- name: log-collector
image: fluent/fluentd:v1.16
volumeMounts:
- name: logs
mountPath: /var/log
volumes:
- name: logs
emptyDir: {}
2. ReplicaSet(複製管理)
ReplicaSetは指定した数のPodを常に維持します。
# replicaset.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx-replicaset
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
kubectl apply -f replicaset.yaml
# 3つのPodが起動
kubectl get pods
# nginx-replicaset-abc123
# nginx-replicaset-def456
# nginx-replicaset-ghi789
# 1つ削除しても自動で補充される
kubectl delete pod nginx-replicaset-abc123
# 即座に新しいPodが起動
3. Deployment(デプロイ管理)
DeploymentはReplicaSetのバージョン管理ができます。アップデート・ロールバックが簡単。
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v1.0
ports:
- containerPort: 8080
env:
- name: DATABASE_URL
value: "postgresql://db:5432/mydb"
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
# デプロイ
kubectl apply -f deployment.yaml
# 状態確認
kubectl get deployments
kubectl get pods
# アップデート(イメージ変更)
kubectl set image deployment/myapp-deployment myapp=myapp:v2.0
# ローリングアップデート進行状況
kubectl rollout status deployment/myapp-deployment
# アップデート履歴
kubectl rollout history deployment/myapp-deployment
# ロールバック
kubectl rollout undo deployment/myapp-deployment
4. Service(ネットワーク)
ServiceはPodへのアクセス方法を定義します。Podは動的に生成・削除されるため、固定IPが必要。
ClusterIP(内部通信)
# service-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
type: ClusterIP # デフォルト
selector:
app: myapp
ports:
- port: 80 # Serviceのポート
targetPort: 8080 # Podのポート
kubectl apply -f service-clusterip.yaml
# クラスタ内から http://myapp-service でアクセス可能
NodePort(外部公開)
# service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-nodeport
spec:
type: NodePort
selector:
app: myapp
ports:
- port: 80
targetPort: 8080
nodePort: 30001 # 30000-32767の範囲
# ノードのIP:30001でアクセス可能
curl http://node-ip:30001
LoadBalancer(クラウド環境)
# service-loadbalancer.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-lb
spec:
type: LoadBalancer
selector:
app: myapp
ports:
- port: 80
targetPort: 8080
AWS/GCP/Azureでは自動的にロードバランサーが作成されます。
5. Ingress(HTTPルーティング)
IngressはL7ロードバランサー。URLパスやホスト名でルーティング。
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- host: admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 3000
# Ingress Controllerをインストール(NGINX Ingress)
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.9.5/deploy/static/provider/cloud/deploy.yaml
# Ingress作成
kubectl apply -f ingress.yaml
# 確認
kubectl get ingress
6. ConfigMap(設定管理)
ConfigMapは環境変数や設定ファイルを外部化します。
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
data:
APP_NAME: "My Application"
LOG_LEVEL: "info"
config.json: |
{
"database": {
"host": "db.example.com",
"port": 5432
}
}
# deployment.yaml(ConfigMapを使用)
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
containers:
- name: myapp
image: myapp:v1.0
# 環境変数として読み込み
envFrom:
- configMapRef:
name: myapp-config
# ファイルとしてマウント
volumeMounts:
- name: config
mountPath: /app/config
volumes:
- name: config
configMap:
name: myapp-config
items:
- key: config.json
path: config.json
7. Secret(機密情報管理)
SecretはパスワードやAPIキーを安全に保存します。
# Secret作成(コマンド)
kubectl create secret generic db-secret \
--from-literal=username=admin \
--from-literal=password=secretpassword
# Secret作成(YAML)
echo -n 'admin' | base64 # YWRtaW4=
echo -n 'secretpassword' | base64 # c2VjcmV0cGFzc3dvcmQ=
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
username: YWRtaW4=
password: c2VjcmV0cGFzc3dvcmQ=
# deployment.yaml(Secretを使用)
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
containers:
- name: myapp
image: myapp:v1.0
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
8. Volume(永続化)
PersistentVolumeとPersistentVolumeClaimでデータを永続化します。
# pvc.yaml(PersistentVolumeClaim)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myapp-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
# deployment.yaml(PVCを使用)
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: myapp-pvc
実践: Webアプリをデプロイ
構成
- Frontend: React (Nginx)
- Backend: Node.js
- Database: PostgreSQL
1. PostgreSQLデプロイ
# postgres.yaml
apiVersion: v1
kind: Secret
metadata:
name: postgres-secret
type: Opaque
data:
password: cG9zdGdyZXM= # "postgres" in base64
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
- name: POSTGRES_DB
value: myapp
ports:
- containerPort: 5432
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: postgres-pvc
---
apiVersion: v1
kind: Service
metadata:
name: postgres
spec:
selector:
app: postgres
ports:
- port: 5432
2. Backendデプロイ
# backend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
replicas: 3
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: myapp-backend:v1.0
env:
- name: DATABASE_URL
value: postgresql://postgres@postgres:5432/myapp
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
ports:
- containerPort: 3000
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
selector:
app: backend
ports:
- port: 3000
3. Frontendデプロイ
# frontend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 2
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: myapp-frontend:v1.0
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"
---
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
selector:
app: frontend
ports:
- port: 80
4. Ingress設定
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- myapp.example.com
secretName: myapp-tls
rules:
- host: myapp.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: backend
port:
number: 3000
- path: /
pathType: Prefix
backend:
service:
name: frontend
port:
number: 80
デプロイ実行
# すべてデプロイ
kubectl apply -f postgres.yaml
kubectl apply -f backend.yaml
kubectl apply -f frontend.yaml
kubectl apply -f ingress.yaml
# 確認
kubectl get pods
kubectl get services
kubectl get ingress
# ログ確認
kubectl logs -f deployment/backend
# スケールアウト
kubectl scale deployment/backend --replicas=5
# ローリングアップデート
kubectl set image deployment/backend backend=myapp-backend:v2.0
Auto Scaling(自動スケーリング)
Horizontal Pod Autoscaler(HPA)
CPU使用率に応じてPod数を自動調整。
# hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: backend-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: backend
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
kubectl apply -f hpa.yaml
# 確認
kubectl get hpa
# 負荷テスト
kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://backend; done"
# HPAが自動でスケール
watch kubectl get hpa
Namespaceで環境分離
# Namespace作成
kubectl create namespace dev
kubectl create namespace staging
kubectl create namespace production
# Namespace指定してデプロイ
kubectl apply -f deployment.yaml -n dev
# デフォルトNamespace変更
kubectl config set-context --current --namespace=dev
# すべてのNamespaceのPod確認
kubectl get pods --all-namespaces
Helmでパッケージ管理
HelmはKubernetesのパッケージマネージャー。複雑なアプリを簡単にデプロイできます。
# Helmインストール
brew install helm # macOS
# または
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# チャート検索
helm search hub wordpress
# PostgreSQLインストール
helm repo add bitnami https://charts.bitnami.com/bitnami
helm install my-postgres bitnami/postgresql
# 自作チャート作成
helm create myapp
# インストール
helm install myapp ./myapp
# アップグレード
helm upgrade myapp ./myapp
# ロールバック
helm rollback myapp
# アンインストール
helm uninstall myapp
ローカル開発環境
Minikube(学習用)
# インストール(macOS)
brew install minikube
# 起動
minikube start
# ダッシュボード
minikube dashboard
# 停止
minikube stop
Kind(Kubernetes in Docker)
# インストール
brew install kind
# クラスタ作成
kind create cluster --name dev
# 確認
kubectl cluster-info --context kind-dev
# 削除
kind delete cluster --name dev
k3s(軽量Kubernetes)
# インストール(Linux)
curl -sfL https://get.k3s.io | sh -
# 確認
sudo k3s kubectl get nodes
監視とロギング
Promethe us + Grafana
# Helmでインストール
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/kube-prometheus-stack
# Grafana UI アクセス
kubectl port-forward svc/prometheus-grafana 3000:80
# http://localhost:3000
# user: admin, password: prom-operator
ELKスタック(Elasticsearch + Logstash + Kibana)
helm repo add elastic https://helm.elastic.co
helm install elasticsearch elastic/elasticsearch
helm install kibana elastic/kibana
トラブルシューティング
# Pod状態確認
kubectl get pods
kubectl describe pod <pod-name>
# ログ確認
kubectl logs <pod-name>
kubectl logs -f <pod-name> # リアルタイム
kubectl logs <pod-name> --previous # 前回のログ
# Podに接続
kubectl exec -it <pod-name> -- /bin/sh
# イベント確認
kubectl get events --sort-by='.lastTimestamp'
# リソース使用状況
kubectl top nodes
kubectl top pods
# デバッグPod起動
kubectl run debug --image=busybox --rm -it -- /bin/sh
ベストプラクティス
1. リソース制限を設定
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
2. Health Checkを設定
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
3. ラベルを活用
metadata:
labels:
app: myapp
tier: backend
environment: production
version: v1.0
4. 機密情報はSecretで管理
# ❌ 悪い例
env:
- name: API_KEY
value: "secret-api-key-12345"
# ✅ 良い例
env:
- name: API_KEY
valueFrom:
secretKeyRef:
name: api-secrets
key: api-key
5. PodDisruptionBudget設定
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: myapp-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: myapp
まとめ
Kubernetesの基本概念:
- Pod: コンテナの集まり(最小単位)
- Deployment: Podのバージョン管理
- Service: ネットワークアクセス
- Ingress: HTTPルーティング
- ConfigMap/Secret: 設定・機密情報
- Volume: データ永続化
学習ステップ:
- Minikubeでローカル環境構築
- 基本リソース(Pod/Deployment/Service)を理解
- 実際のアプリをデプロイ
- Helmで効率化
- 監視・ロギング整備
Kubernetes開発に役立つツールを探しているなら、DevToolBoxもチェックしてみてください。YAMLフォーマッターやJSON変換など、開発効率を上げるツールが揃っています。