5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【本気で学ぶKubernetes】はじめてのK8sデプロイ。nginxを動かしてみる!

Last updated at Posted at 2025-12-04

はじめに

こんにちは!

本記事は「本気で学ぶKubernetes」シリーズの第4回です。このシリーズでは、Kubernetesの基礎から実践まで、段階的に学んでいきます。

このシリーズは、第1回から順に読むことで体系的に学べる構成にしています。
まだご覧になっていない方は、ぜひ最初からご覧ください!

Kubernetesとは?クラスタ構成の全体像をつかむ

前回は、kubectlやminikubeなどの基本ツールとコマンドを学習しました。クラスタの起動や簡単なリソースの作成もやってみました。

今回は、実際にYAMLマニフェストファイルを書いて、nginxのWebサーバーをKubernetes上にデプロイします。

この記事は人間がKubernetesの公式ドキュメントを読み漁りながら、人間の手で書いていますのでご安心ください!

前提知識

  • Kubernetes、Pod、Deployment、Serviceの基本概念を理解している方
  • kubectlとminikubeの基本的な使い方を知っている方
  • YAMLファイルの基本的な書き方を知っている方

今回作成する構成とゴール

構成図

今回は以下のような構成を作成します。
後の記事でフロー図の正しい書き方も触れていければと思います。

k8s-構成図.png

nginxのDeploymentマニフェスト作成

ここからは実際にnginxのDeploymentマニフェストを作成していきます。

まず作業用のディレクトリを作成します。

mkdir -p k8s-nginx-demo
cd k8s-nginx-demo

次に、nginx-deployment.yamlというファイルを作成します。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

このマニフェストでは、replicas: 3で3つのPodを起動します。
そして各Podはnginxコンテナを1つ持ち、それぞれポート80で待ち受けています。selector.matchLabelstemplate.metadata.labelsパラメータの両方にapp: nginxを指定することで、DeploymentがどのPodを管理すべきかを判断できるようなっています。

出典: Kubernetes公式ドキュメント - Deployments

Serviceマニフェスト作成

次に、外部からnginxにアクセスできるようにServiceを作成します。

nginx-service.yamlというファイルを作成します。

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30080

このServiceはtype: NodePortでローカル環境から直接アクセスできるようにしています。selectorapp: nginxを指定することで、先ほど作成したDeploymentのPodにトラフィックを転送します。Serviceの80番ポートへのリクエストが、Podの80番ポート(targetPort)に転送される仕組みです。

出典: Kubernetes公式ドキュメント - Service

いざ実践

まず、minikubeクラスタを起動します。

# クラスタの起動
minikube start

# 😄  Darwin 14.5 (arm64) 上の minikube v1.37.0
# ...(省略)...
# 🏄  終了しました!kubectl がデフォルトで「minikube」クラスターと「default」ネームスペースを使用するよう設定されました

# クラスタの状態確認
minikube status

# minikube
# type: Control Plane
# host: Running
# kubelet: Running
# apiserver: Running
# kubeconfig: Configured

クラスタが起動したら、今回の作業用にネームスペースを作成します。

Kubernetesではネームスペースを使ってリソースを論理的に分離できます。
今回はnginx-demoという名前でネームスペースを作成していきます。

# 現在のコンテキストを確認
kubectl config current-context

# minikube

# ネームスペースを作成
kubectl create namespace nginx-demo

# namespace/nginx-demo created

# ネームスペースの一覧を確認
kubectl get namespaces

# NAME              STATUS   AGE
# default           Active   10m
# kube-node-lease   Active   10m
# kube-public       Active   10m
# kube-system       Active   10m
# nginx-demo        Active   5s    ← 今作成したネームスペース

# デフォルトのネームスペースを nginx-demo に変更
kubectl config set-context --current --namespace=nginx-demo

# Context "minikube" modified.

これで、以降のkubectlコマンドはすべてnginx-demoネームスペース内で実行されるようになります。

出典: Kubernetes公式ドキュメント - Namespaces

Deploymentのデプロイ

作成したマニフェストを使ってDeploymentをデプロイします。

# Deploymentの適用
kubectl apply -f nginx-deployment.yaml

# deployment.apps/nginx-deployment created

# Deploymentの確認
kubectl get deployments

# NAME               READY   UP-TO-DATE   AVAILABLE   AGE
# nginx-deployment   3/3     3            3           10s

次に、ReplicaSetを確認します。

# ReplicaSetの確認
kubectl get rs

# NAME                          DESIRED   CURRENT   READY   AGE
# nginx-deployment-86dcfdf4c6   3         3         3       30s

ReplicaSetはDeploymentによって自動的に作成され、指定された数のPodレプリカが常に実行されていることを保証します。

出典: Kubernetes公式ドキュメント - ReplicaSet

最後に、実際に作成されたPodを確認します。

# Podの確認
kubectl get pods

# NAME                                READY   STATUS    RESTARTS   AGE
# nginx-deployment-86dcfdf4c6-7xqzt   1/1     Running   0          50s
# nginx-deployment-86dcfdf4c6-k9n2p   1/1     Running   0          50s
# nginx-deployment-86dcfdf4c6-xm5lr   1/1     Running   0          50s

3つのPodが起動していることが確認できました!

Pod名の最後の部分(7xqztなど)はランダムに生成され、これがPodの一意な識別子になります。

詳細情報を確認したい場合は、describeコマンドを使います。

# Deploymentの詳細情報
kubectl describe deployment nginx-deployment

# Name:                   nginx-deployment
# Namespace:              nginx-demo
# CreationTimestamp:      Mon, 02 Dec 2024 10:30:00 +0900
# Labels:                 app=nginx
# Annotations:            deployment.kubernetes.io/revision: 1
# Selector:               app=nginx
# Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
# ...(省略)...

Serviceのデプロイ

次に、Serviceを作成して外部からアクセスできるようにします。

# Serviceの適用
kubectl apply -f nginx-service.yaml

# service/nginx-service created

# Serviceの確認
kubectl get svc

# NAME            TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
# nginx-service   NodePort   10.97.242.218   <none>        80:30080/TCP   5s

minikubeでServiceにアクセスします。

# minikubeを使ってServiceにアクセス
minikube service nginx-service -n nginx-demo

# |-------------|---------------|-------------|---------------------------|
# | NAMESPACE   |     NAME      | TARGET PORT |            URL            |
# |-------------|---------------|-------------|---------------------------|
# | nginx-demo  | nginx-service |          80 | http://192.168.49.2:30080 |
# |-------------|---------------|-------------|---------------------------|
# 🏃  nginx-service サービス用のトンネルを起動しています。
# 🎉  デフォルトブラウザーで nginx-demo/nginx-service サービスを開いています...
# ❗  Docker ドライバーを darwin 上で使用しているため、実行するにはターミナルを開く必要があります。

ブラウザが自動的に開き、nginxのWelcomeページが表示されます!

nginx-top.png

これで、KubernetesクラスタにnginxのWebサーバーがデプロイされて外部からアクセスできるようになりました!

ロードバランシングを確認してみる

Serviceは複数のPodにトラフィックを分散します。実際にどのPodにアクセスしているのかを見ていきます。

さらに各Podのnginxが表示する内容を変えて、リロードするたびに別のPodにアクセスされていることを合わせて確認していきます。

Pod名を取得

まず、現在動いているPodの名前を確認します。

kubectl get pods

# NAME                                READY   STATUS    RESTARTS   AGE
# nginx-deployment-6f9664446b-7c2kq   1/1     Running   0          10m
# nginx-deployment-6f9664446b-7fsbv   1/1     Running   0          10m
# nginx-deployment-6f9664446b-vtnrp   1/1     Running   0          10m

各Podのindex.htmlを書き換え

それぞれのPodに入って、表示される内容を変更します。
先ほど表示したPodのNameに対して、index.htmlをそれぞれ書き換えていきます。

# 1つ目のPod
kubectl exec nginx-deployment-6f9664446b-7c2kq -- bash -c 'echo "<h1>Pod 1</h1>" > /usr/share/nginx/html/index.html'

# 2つ目のPod
kubectl exec nginx-deployment-6f9664446b-7fsbv -- bash -c 'echo "<h1>Pod 2</h1>" > /usr/share/nginx/html/index.html'

# 3つ目のPod
kubectl exec nginx-deployment-6f9664446b-tchsp -- bash -c 'echo "<h1>Pod 3</h1>" > /usr/share/nginx/html/index.html'

curlで複数回アクセスして確認

curlコマンドで複数回アクセスしてみます。
ポート番号はサービス用のトンネル起動時のポートを利用してください。

# Service経由で複数回アクセス
for i in {1..10}; do curl -s http://localhost:50514; done
# <h1>Pod 2</h1>
# <h1>Pod 3</h1>
# <h1>Pod 3</h1>
# <h1>Pod 1</h1>
# <h1>Pod 1</h1>
# <h1>Pod 2</h1>
# <h1>Pod 2</h1>
# <h1>Pod 1</h1>
# <h1>Pod 3</h1>
# <h1>Pod 1</h1>

表示がPod 1Pod 2Pod 3と順番に切り替わっていることが確認できましたね!
これは、Serviceが3つのPodに対してトラフィックを分散しているためです。

Podの自動復旧を試してみる

ここからはPodの自動復旧を試してみます。

まず、現在のPod一覧を確認します。

kubectl get pods

# NAME                                READY   STATUS    RESTARTS   AGE
# nginx-deployment-6f9664446b-7c2kq   1/1     Running   0          4m56s
# nginx-deployment-6f9664446b-7fsbv   1/1     Running   0          4m56s
# nginx-deployment-6f9664446b-vtnrp   1/1     Running   0          4m56s

それでは、1つのPodを削除してみます。

# 1つ目のPodを削除
kubectl delete pod nginx-deployment-6f9664446b-vtnrp

# pod "nginx-deployment-6f9664446b-vtnrp" deleted from nginx-demo namespace

# すぐにPod一覧を確認
kubectl get pods

# NAME                                READY   STATUS    RESTARTS   AGE
# nginx-deployment-6f9664446b-7c2kq   1/1     Running   0          5m51s
# nginx-deployment-6f9664446b-7fsbv   1/1     Running   0          5m51s
# nginx-deployment-6f9664446b-tchsp   1/1     Running   0          9s   ← 新しいPodが作成される

削除したPodの代わりに、新しいPodが自動的に作成されました!

今回の構成ではDeploymentでreplicas: 3を設定していました。これに基づいて、常に3つのPodが動作するように制御されます。

# ReplicaSetを確認
kubectl get rs

# NAME                          DESIRED   CURRENT   READY   AGE
# nginx-deployment-86dcfdf4c6   3         3         3       10m

スケーリングを試してみる

Kubernetesでは、実行中のPod数を動的に変更できます。

例えば、アクセスが急増してサーバーの負荷が高くなった時はPod数を増やして負荷分散し、夜間などアクセスが少ない時間帯はPod数を減らしてリソースを節約するといった運用が可能です。

今回はkubectl scaleコマンドを使って手動でスケーリングしてみますが、本番環境では後述するHorizontal Pod Autoscaler (HPA)を使って負荷に応じて自動的にスケールする設定も可能です。

スケールアウト(Podの数を増やす)

# Pod数を5つに増やす
kubectl scale deployment nginx-deployment --replicas=5

# deployment.apps/nginx-deployment scaled

# 確認
kubectl get pods

# NAME                                READY   STATUS    RESTARTS   AGE
# nginx-deployment-86dcfdf4c6-def34   1/1     Running   0          5m
# nginx-deployment-86dcfdf4c6-ghi56   1/1     Running   0          5m
# nginx-deployment-86dcfdf4c6-jkl78   1/1     Running   0          3s   ← 新しく追加
# nginx-deployment-86dcfdf4c6-mno90   1/1     Running   0          3s   ← 新しく追加
# nginx-deployment-86dcfdf4c6-xm5lr   1/1     Running   0          20m

kubectl get rs

# NAME                          DESIRED   CURRENT   READY   AGE
# nginx-deployment-86dcfdf4c6   5         5         5       25m

スケールイン(Podの数を減らす)

# Pod数を2つに減らす
kubectl scale deployment nginx-deployment --replicas=2

# deployment.apps/nginx-deployment scaled

# 数秒後に実行します
kubectl get pods

# NAME                                READY   STATUS    RESTARTS   AGE
# nginx-deployment-86dcfdf4c6-def34   1/1     Running   0          9m
# nginx-deployment-86dcfdf4c6-xm5lr   1/1     Running   0          24m

このように、kubectl scaleコマンドで簡単にPod数を増減できます。

実際の運用でのスケーリング例

実際の運用では、こんな場面でスケーリングを使います。

スケールアウトするケース

  • アクセスが急増してCPU使用率が80%を超えた
  • テレビCMやSNS拡散でトラフィックが10倍になった
  • セール開始時刻に合わせて事前にPod数を増やす

本番環境では、トラフィックの増減に応じてPod数を自動的に調整する「Horizontal Pod Autoscaler (HPA)」という機能もあります。

出典: Kubernetes公式ドキュメント - Deploymentのスケーリング

リソースのクリーンアップ

作業が一通り終わったので、作成したリソースを削除します。

# Serviceの削除
kubectl delete -f nginx-service.yaml

# service "nginx-service" deleted from nginx-demo namespace

# Deploymentの削除
kubectl delete -f nginx-deployment.yaml

# deployment.apps "nginx-deployment" deleted from nginx-demo namespace

# リソースが削除されたことを確認します
kubectl get all

# No resources found in nginx-demo namespace.

Deploymentを削除すると、関連するReplicaSetとPodも自動的に削除されます。

最後に、作成したネームスペースも忘れずに削除しておきましょう。

# デフォルトネームスペースに戻します
kubectl config set-context --current --namespace=default

# Context "minikube" modified.

# ネームスペースを削除します
kubectl delete namespace nginx-demo

# namespace "nginx-demo" deleted

ネームスペースを削除すると、その中のすべてのリソース(Pod、Service、Deploymentなど)も一緒に削除されます。

もしminikubeクラスタ自体を停止したい場合は、以下のコマンドを実行します。

# クラスタの停止(データは保持される)
minikube stop

# クラスタの完全削除(全データ削除)
minikube delete

まとめと次回予告

今回はマニフェストファイルを作成して、nginxのWebサーバーをKubernetes上にデプロイするところまで実施しました。
PodへのラウンドロビンのアクセスやPodのスケーリングについてコマンドベースで確認でき、Kubernetes上で稼動する仕組みとその解像度がかなり高くなって来たと思います。

次回はClusterIP / NodePort / LBについて再度焦点を当てて概念や仕組みを確認していければと思います。

それでは、また明日!

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?