はじめに
インフラやSREの領域に触れていると、Kubernetesという言葉を耳にする機会が増えてきました。
「マルチサーバで強くなる」「運用が楽になる」といったイメージはありつつも、何をどう解決しているのかは理解の浅いままでした。
そこで今回は、実際に手を動かしながら、Pod / Deployment / Service までを一通り触ってみました。
同じくk8s初心者の方に、「なんとなくわかった!」という感覚を届けられたら嬉しいです。
参考にした資料
サイボウズ株式会社さんが公開している新人研修のKubernetes入門を参考に、AIと理解しながら進めていきました。
Kubernetesとは
上記資料で書かれていた定義がわかりやすかったです。
Kubernetesは、コンテナを複数のサーバー上で協調動作・管理するためのシステム(コンテナオーケストレーション)です。
運用・管理を自動化したい → コンテナオーケストレーション
今回の到達点
- ローカルにKubernetesクラスタを構築する
- YAMLでPod・Deploymentを定義してデプロイする
- セルフヒーリング(Podが死んでも自動復活)を体験する
- Serviceでブラウザからnginxにアクセスする
コードはこちらにまとめています👇
https://github.com/hirune05/k8s_training
環境構築
必要なツール
| ツール | 役割 |
|---|---|
| Docker | コンテナ基盤 |
| kind | ローカルにK8sクラスタを作るツール |
| kubectl | K8sを操作するCLI |
kindクラスタを作る
kindは、DockerコンテナをKubernetesのノードとして動かすツールです。「Docker in Docker」とも呼ばれます。PCのローカル環境だけでKubernetesの動作環境(クラスタ)を再現できます。
kindクラスタを以下のコマンドで作成します。
kind create cluster --name k8s-training
クラスタが作れたか確認:
kubectl get nodes
STATUS: Ready が表示されれば成功です!
NAME STATUS ROLES AGE VERSION
k8s-training-control-plane Ready control-plane 1m v1.32.2
学習の流れ
Step 1:Podを作る
Podとは?
PodはKubernetesでアプリをデプロイする最小単位です。コンテナの入れ物のようなイメージで、1つのPodに複数のコンテナを入れることもできます。
┌──────────────── Pod ────────────────┐
│ ┌─────────────┐ ┌─────────────┐ │
│ │ コンテナA │ │ コンテナB │ │
│ │ (nginx) │ │ (ログ収集) │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────┘
まずYAMLファイル(manifest)を書いてみます。
# nginx-pod.yaml
apiVersion: v1 # KubernetesのAPIバージョン
kind: Pod # 作るリソースの種類
metadata:
name: my-first-pod # Podの名前
labels:
component: nginx # Podにつけるタグ
spec:
containers:
- name: nginx # コンテナの名前
image: nginx:latest # 使うDockerイメージ
kubectl apply でこのファイルをKubernetesに適用してPodを作成します。
kubectl apply -f nginx-pod.yaml
Podの状態確認:
kubectl get pod
STATUS: Running なら成功!
NAME READY STATUS RESTARTS AGE
my-first-pod 1/1 Running 0 30s
Pod内に入ってnginxの動作確認:
kubectl exec -it my-first-pod -- bash
Pod内から以下を実行
curl -i localhost:80
200 OK でnginxが動いていることを確認できました!
HTTP/1.1 200 OK
Server: nginx/1.25.4
...
Step 2:Deploymentで複数Pod & セルフヒーリング
Step 1 のようにPodを直接デプロイすることはあまりやりません。Deploymentを使うのが実践での基本だそうです。
| Pod直接 | Deployment | |
|---|---|---|
| Podが落ちたとき | ❌ 落ちたら終わり | ✅ 自動で作り直す(セルフヒーリング) |
| 複数起動 | ❌ 1個ずつ手動 | ✅ replicasで指定 |
| アップデート | ❌ 一度止めて入れ替え | ✅ ローリングアップデート(サービスを止めずに更新) |
# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
component: nginx
spec:
replicas: 3 # Podを3個維持する
selector:
matchLabels:
component: nginx # このラベルのPodを管理対象にする
template: # 作成するPodのテンプレート
metadata:
labels:
component: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ここで学んだこと:selectorとtemplateの関係
selector:
matchLabels:
component: nginx # ②このラベルのPodを管理する
template:
metadata:
labels:
component: nginx # ③作るPodにこのラベルをつける
②と③がペアになっていて、「③のラベルをつけたPodを②で拾って管理する」という仕組みです。
applyして状態を確認すると、
kubectl apply -f nginx-deployment.yaml
kubectl get pod
このように3個のPodが立ち上がりました🎉
NAME READY STATUS RESTARTS AGE
nginx-deployment-764cfd9df8-d45b6 1/1 Running 0 14s
nginx-deployment-764cfd9df8-vjpn6 1/1 Running 0 14s
nginx-deployment-764cfd9df8-zxsfr 1/1 Running 0 14s
セルフヒーリングを体験する:
Podを1個わざと消す
kubectl delete pod nginx-deployment-764cfd9df8-d45b6
すぐに確認すると...
kubectl get pod
消した瞬間に新しいPodが自動で作られています!
Deploymentが「3個あるべきなのに2個になった!」と検知して復元してくれました。これがセルフヒーリングです。
NAME READY STATUS RESTARTS AGE
nginx-deployment-764cfd9df8-lvb5m 1/1 Running 0 3s ← 新しいPodが!
nginx-deployment-764cfd9df8-vjpn6 1/1 Running 0 25m
nginx-deployment-764cfd9df8-zxsfr 1/1 Running 0 25m
なぜこれが重要なのか? 本番環境では、ハードウェア障害やOOMキラーでPodが予期せず落ちることがよくあります。Deploymentがあれば、深夜に障害が発生しても自動復旧するため、オペレーターが即座に対応しなくて済みます。
Step 3:Serviceでブラウザからアクセス
PodのIPアドレスは起動するたびに変わります。そこで登場するのがServiceです。
Serviceの役割:
- IPが変わっても、ラベルでPodを探して通信を届ける
- 複数Podへのリクエストをロードバランシングする
- 外部からのアクセス窓口になる
# nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: NodePort
selector:
component: nginx # このラベルのPodにトラフィックを流す
ports:
- port: 80 # Service自身のポート(クラスタ内部向け)
targetPort: 80 # Podの何番ポートに転送するか
nodePort: 30080 # 外からアクセスするポート(30000〜32767)
applyして状態確認すると
kubectl apply -f nginx-service.yaml
kubectl get service
ポート30080のサービスが確認できました。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-service NodePort 10.96.99.185 <none> 80:30080/TCP 30s
kindではNodePortだけだとlocalhostに繋がらない
kindはノードがDockerコンテナのため、localhost:30080 では直接繋がりません。port-forward を使います:
kubectl port-forward service/nginx-service 30080:80
このコマンドを実行したまま http://localhost:30080 をブラウザで開くと…
「Welcome to nginx!」が表示されました!🎉
全体像を振り返る
今回触った3つのリソースの関係を整理するとこうなります。
[ブラウザ]
↓ localhost:30080
[Service] ← selectorでPodを探す
↓ ロードバランシング
[Pod] [Pod] [Pod] ← Deploymentが3個を維持
- Pod :アプリの実行単位
- Deployment :Podの数と状態を管理する
- Service :Podへの安定した通信窓口を提供する
おわりに
k8sについて、以前は「マルチサーバを管理するツール」くらいの認識でした。
しかし、今回の演習を通じて、セルフヒーリングやServiceによる抽象化など、状態を自動で維持する仕組みを実感できました。
今回はkindで基本を触った段階ですが、今後実務で出会ったときに、ちゃんと理解して関われるようになりたいです。
