Kubernetes(クバネティス、略してK8s)とは、たくさんのコンテナを複数のサーバーにまたがって配置し、落ちたら自動で立て直し、負荷に合わせて数を増減させる「コンテナのオーケストレーション(まとめて管理する)」基盤です。「コンテナをこういう状態で3つ動かしておいて」とYAMLであるべき状態を宣言すると、Kubernetesがその状態を保ち続けます。

入門の段階でつまずきやすいのは、リソースの種類が多く、どれが何をするのかが見えにくいことです。この記事では、よく使う8つのリソースを1枚の表にまとめ、Docker Composeの書き方と対応づけて説明します。記事中のYAMLは、Kubernetes 1.36 のAPIスキーマで実際に検証ツールにかけて、正しく書けていることを確認しました。わざと間違えたYAMLで出るエラーも載せています。

Kubernetesの主要リソース早見表

リソース ひとことで言うと Docker Composeでいうと
Pod コンテナを動かす最小単位(1つ以上のコンテナの組) 1つのコンテナ
ReplicaSet 同じPodを指定した数だけ保つ deploy.replicas
Deployment ReplicaSetを管理し、ローリングアップデートやロールバックを行う services: の1サービス
Service Podの集まりに固定の名前とIPを与え、振り分ける サービス名での名前解決
Ingress 外部からのHTTP(S)を、ホスト名やパスでServiceに振り分ける 前段に置くNginxなどのリバースプロキシ
ConfigMap 設定値をまとめて、Podに環境変数やファイルとして渡す environment: / configs:
Secret パスワードやトークンなど秘密の値を渡す secrets: / .env
Namespace クラスターの中を区切るフォルダのようなもの プロジェクト名(-p)

普段の開発で自分で書くのは、Deployment・Service・ConfigMap・Secret・Ingressの5つが中心です。PodとReplicaSetは、Deploymentが自動で作ります。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Kubernetes入門|主要リソースとYAMLの書き方、kubectl早見表」

なぜKubernetesが必要なのか

コンテナ1つ、サーバー1台なら docker run やDocker Composeで十分です。サービスが大きくなると、次のような仕事が増えていきます。

増えていく仕事 Kubernetesがしてくれること
コンテナが落ちたら起動し直す 自己修復:あるべき数に戻るまで自動で作り直す
どのサーバーに置くか決める スケジューリング:CPU・メモリの空きを見て配置する
新しいバージョンに入れ替える ローリングアップデート:少しずつ入れ替え、止めずに更新する
失敗したら戻す ロールバック:1コマンドで前のバージョンに戻す
アクセスが増えたら増やす スケール:数の変更、負荷に応じた自動増減(HPA)
入れ替わるコンテナへ振り分ける サービスディスカバリ:Serviceの名前で常に今のPodに届く

「手順を実行する」のではなく「あるべき状態を宣言する」のがKubernetesの考え方です。Podを手で消しても、Deploymentに replicas: 3 と書いてあれば、すぐに3つ目が作り直されます。

クラスターの構成

┌──────────── クラスター ────────────┐
│ コントロールプレーン                  │
│  API Server / etcd / Scheduler /    │  ← kubectl はここに命令する
│  Controller Manager                 │
├─────────────────────────────────────┤
│ ワーカーノード1   ワーカーノード2      │
│  kubelet          kubelet           │
│  [Pod][Pod]       [Pod]             │  ← コンテナが実際に動く
└─────────────────────────────────────┘
部品 役割
API Server すべての操作の窓口。kubectl もここに話しかける
etcd クラスターの状態(あるべき状態)を保存するデータベース
Scheduler 新しいPodをどのノードに置くか決める
Controller Manager 「あるべき状態」と「今の状態」の差を埋め続ける
kubelet 各ノードで、指示されたPodを実際に起動・監視する

マネージドサービス(EKS・GKE・AKS)では、コントロールプレーンの運用はクラウド側が担当し、利用者はワーカーノードとアプリに集中できます。

Docker Composeとの対応

Docker Composeを使ったことがあれば、次の対応で理解が早くなります。

# compose.yaml
services:
  web:
    image: nginx:1.30
    ports:
      - "8080:80"
    environment:
      APP_MODE: production
    deploy:
      replicas: 3
Docker Compose Kubernetes 補足
services.web Deployment web + Service web Kubernetesでは「動かす」と「つなぐ」が別のリソース
image spec.template.spec.containers[].image 同じ
ports: "8080:80" Service の port / targetPort、外部公開は Ingress や type: LoadBalancer
environment env / ConfigMap
.env、secrets Secret
deploy.replicas spec.replicas
healthcheck livenessProbe / readinessProbe 目的別に分かれている
depends_on 直接の対応なし readinessProbeやinitContainersで「準備ができるまで待つ」を表す
volumes(名前付き) PersistentVolumeClaim
docker compose up -d kubectl apply -f .
docker compose logs -f web kubectl logs -f deploy/web
docker compose exec web sh kubectl exec -it deploy/web -- sh

depends_on がない点が大きな違いです。Kubernetesでは、アプリ自身が「接続先がまだ準備中なら待って再試行する」ように作り、準備が整ったかどうかはreadinessProbeで伝えます。

YAMLの例:Deployment+Service

nginxを3つ動かし、Service web で振り分ける最小構成に、プローブ・リソース指定・ConfigMap/Secretの読み込みを加えた例です。

# app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels:
    app: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web            # ① このラベルのPodを管理する
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: web          # ② ①と一致させる
    spec:
      containers:
        - name: web
          image: nginx:1.30
          ports:
            - containerPort: 80
          env:
            - name: APP_MODE
              valueFrom:
                configMapKeyRef:
                  name: web-config
                  key: APP_MODE
            - name: DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: web-secret
                  key: DB_PASSWORD
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              memory: 256Mi
          readinessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 3
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 10
            periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  type: ClusterIP
  selector:
    app: web              # ③ ②のラベルを持つPodに振り分ける
  ports:
    - port: 80            # Serviceが受けるポート
      targetPort: 80      # Podのコンテナのポート
# config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: web-config
data:
  APP_MODE: production
---
apiVersion: v1
kind: Secret
metadata:
  name: web-secret
type: Opaque
stringData:
  DB_PASSWORD: change-me
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
spec:
  rules:
    - host: app.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web
                port:
                  number: 80

①②③の3か所のラベルがつながっていることが、Kubernetesの配線そのものです。

書く場所 役割
① spec.selector.matchLabels Deploymentが「自分のPod」と見なす条件
② spec.template.metadata.labels 作られるPodに付くラベル
③ Service の spec.selector Serviceが転送先にするPodの条件

検証ツールにかけた結果

Pythonの kubernetes-validate(KubernetesのOpenAPI定義から作られたJSONスキーマで検証するツール)で、上の2ファイルを確認しました。

$ pip install kubernetes-validate
$ kubernetes-validate --strict app.yaml config.yaml
INFO app.yaml passed for resource deployment/web against version 1.36
INFO app.yaml passed for resource service/web against version 1.36
INFO config.yaml passed for resource configmap/web-config against version 1.36
INFO config.yaml passed for resource secret/web-secret against version 1.36
INFO config.yaml passed for resource ingress/web against version 1.36

よくある書き間違いを2つ入れると、次のように検出されました。

# replicas を replica と書いた(--strict なしでは通ってしまう)
ERROR ... spec: Additional properties are not allowed ('replica' was unexpected)

# containerPort を "80"(文字列)と書いた
ERROR ... spec.template.spec.containers.0.ports.0.containerPort: '80' is not of type 'integer'

--strict を付けないと、replica のようなつづりの間違いは「知らない項目」として見逃され、検証を通過しました。この場合、Kubernetesは初期値の1台で動かします。検証には --strict を付けるのがおすすめです。

一方、②のラベルを app: webx に変えて①と食い違わせたYAMLは、スキーマ検証を通過しました。スキーマは「型と項目名」しか見ないためです。公式ドキュメントでは、selectorとテンプレートのラベルが一致しないDeploymentはAPIサーバーが受け付けない仕様になっています。クラスターがあれば kubectl apply --dry-run=server -f app.yaml で、APIサーバーのチェックまで事前に確認できます。

kubectlの基本コマンド早見表

やりたいこと コマンド
YAMLを反映する(作成・更新) kubectl apply -f app.yaml(フォルダなら -f k8s/)
一覧を見る kubectl get pods / kubectl get deploy,svc
もっと詳しく一覧 kubectl get pods -o wide
全Namespaceで見る kubectl get pods -A
詳細とイベントを見る kubectl describe pod <Pod名>
ログを見る kubectl logs -f deploy/web(前回落ちたコンテナは --previous)
コンテナに入る kubectl exec -it deploy/web -- sh
手元のPCから接続する kubectl port-forward svc/web 8080:80
数を変える kubectl scale deploy/web --replicas=5
イメージを更新する kubectl set image deploy/web web=nginx:1.31
更新の進み具合 kubectl rollout status deploy/web
更新の履歴 / 戻す kubectl rollout history deploy/web / kubectl rollout undo deploy/web
全Podを順に再起動 kubectl rollout restart deploy/web
削除する kubectl delete -f app.yaml
反映前の差分を見る kubectl diff -f app.yaml
項目の説明を見る kubectl explain deployment.spec.strategy
使うNamespaceを切り替える kubectl config set-context --current --namespace=dev
最近のイベント kubectl get events --sort-by=.lastTimestamp

困ったらまず kubectl describe の一番下の Events を見ます。イメージが取得できない、メモリ不足で配置できない、プローブが失敗している、といった理由がここに出ます。

Podの状態とよくある原因

STATUS 意味 よくある原因
Pending 配置先のノードが決まらない requestsが大きすぎる、ノードの空き不足
ContainerCreating 起動準備中 イメージの取得中、Secret/ConfigMapの読み込み待ち
ImagePullBackOff / ErrImagePull イメージを取得できない イメージ名・タグの誤り、非公開レジストリの認証
CrashLoopBackOff 起動してすぐ終了を繰り返す アプリのエラー、設定不足。kubectl logs --previous で確認
OOMKilled(Last State) メモリ上限を超えて強制終了 limits.memory が小さい、メモリリーク
Running だが READY 0/1 readinessProbeが通っていない ヘルスチェックのパスやポートの誤り

ローリングアップデート

Deploymentのイメージを変えると、新しいPodを少しずつ増やし、前のバージョンのPodを少しずつ減らして入れ替えます。

設定 意味 初期値
maxSurge 更新中に replicas を超えて作ってよい数 25%
maxUnavailable 更新中に使えなくなってよい数 25%

上のYAMLでは maxSurge: 1、maxUnavailable: 0 にしています。「1つ新しいPodを作り、readinessProbeが通ってから前のPodを1つ消す」を繰り返すので、常に3つ以上が応答できる状態を保ちます。

kubectl set image deploy/web web=nginx:1.31
kubectl rollout status deploy/web     # 完了まで待って結果を表示
kubectl rollout undo deploy/web       # 問題があれば1つ前に戻す

readinessProbeがないと、起動しただけでまだ準備ができていないPodにもアクセスが振り分けられます。ローリングアップデートを止めずに行うには、readinessProbeが重要です。

プローブ:liveness・readiness・startup

プローブ 確認すること 失敗したとき
readinessProbe リクエストを受けられるか Serviceの振り分け先から外す(再起動はしない)
livenessProbe 生きているか(固まっていないか) コンテナを再起動する
startupProbe 起動が完了したか 成功するまで liveness/readiness を始めない。起動の遅いアプリ向け
確認の方法 書き方
HTTP httpGet: {path: /healthz, port: 8080}(200〜399で成功)
TCP tcpSocket: {port: 5432}
コマンド exec: {command: ["cat", "/tmp/ready"]}
gRPC grpc: {port: 9090}

livenessProbeにDBへの接続確認を入れないのがポイントです。DBが一時的に止まると全Podが再起動を繰り返し、DBが戻っても復旧に時間がかかります。livenessは「プロセス自身が応答できるか」だけ、外部への依存はreadinessで見ると役割がはっきりします。

requestsとlimits

項目 意味 使われ方
requests 最低限確保したい量 Schedulerが配置先を決める基準。空きが足りないノードには置かれない
limits 使ってよい上限 CPUは超えると抑えられる(遅くなる)、メモリは超えると強制終了(OOMKilled)
単位 意味
cpu: 100m 0.1コア(1000m = 1コア)
memory: 128Mi 128メビバイト(Mi・Gi は1024単位、M・G は1000単位)

requestsを書かないと、ノードに詰め込みすぎて性能が不安定になることがあります。まずは実際の使用量(kubectl top pods、metrics-serverが必要)を見て、requestsを平常時の使用量、limits.memoryを余裕を持った上限に設定するのが始めやすい方法です。

Namespaceで区切る

kubectl create namespace dev
kubectl apply -f app.yaml -n dev
kubectl get pods -n dev

同じNamespaceの中なら、Service web には http://web で届きます。別のNamespaceからは http://web.dev.svc.cluster.local(サービス名.Namespace名.svc.cluster.local)で指定します。チームや環境(dev/stg)ごとに分け、権限(RBAC)やリソースの上限(ResourceQuota)をNamespace単位でかけられます。

ConfigMapとSecretの注意点

  • Secretは初期状態では暗号化ではなくBase64で保存されています。kubectl get secret web-secret -o yaml で見える値は、誰でも元に戻せます
  • SecretのYAMLをそのままGitにコミットしないのが基本です。クラウドのシークレット管理サービスと連携する仕組みや、暗号化してから保存するツールを組み合わせます
  • 環境変数として読み込んだ値は、ConfigMapを変えてもPodを作り直すまで反映されません。kubectl rollout restart deploy/web で入れ替えます

Ingressと、これからのGateway API

Ingressは、1つの入口(ロードバランサー)で、ホスト名やパスごとに複数のServiceへ振り分けるリソースです。Ingressを動かすには、別途Ingressコントローラーのインストールが必要です。

2026年時点では、Ingressの後継として設計された Gateway API(HTTPRoute など)が標準的な選択肢になっています。Kubernetesコミュニティが提供していたコントローラー「ingress-nginx」は2026年3月にメンテナンスを終えており、新しく構築する場合は、Gateway APIに対応したコントローラーや、クラウドが提供するロードバランサー連携を選ぶとよいでしょう。Ingressリソース自体は引き続き利用できます。

ローカルで試す方法

ツール 特徴 始め方
kind Dockerコンテナをノードとして使う。起動が速く、CIでもよく使われる kind create cluster
minikube 入門向け。minikube dashboard などの便利機能が多い minikube start
Docker Desktop 設定画面でKubernetesを有効にするだけ Settings → Kubernetes
k3d / k3s 軽量なKubernetes(k3s)を使う k3d cluster create
# kind の例
kind create cluster --name dev
kubectl apply -f config.yaml -f app.yaml
kubectl get pods
kubectl port-forward svc/web 8080:80   # ブラウザで http://localhost:8080
kind delete cluster --name dev

まずkindかminikubeで、この記事のYAMLを apply → Podを1つ削除して自動で戻ることを確認 → イメージを変えてローリングアップデート、の順に触ってみると、Kubernetesの動きが体でわかります。

マネージドKubernetes:EKS・GKE・AKS

サービス 提供元 特徴
Amazon EKS AWS IAMやALBなどAWSサービスとの連携。ノード管理を任せるAuto Modeもある
Google Kubernetes Engine(GKE) Google Cloud Kubernetesを開発したGoogleのサービス。ノード管理まで任せるAutopilotモード
Azure Kubernetes Service(AKS) Microsoft Azure Entra IDとの連携。構成を自動化するAKS Automatic

どれもKubernetesのAPIは共通なので、この記事のYAMLとkubectlの知識はそのまま使えます。違いが出るのは、ロードバランサー・ストレージ・認証など、クラウドの機能とつなぐ部分です。

Kubernetesは約4か月ごとに新しいマイナーバージョンが出て、各バージョンのサポート期間は約1年です(2026年9月時点の最新は1.37)。マネージドサービスでも定期的なバージョンアップが必要になるため、運用の計画に含めておきます。

Kubernetesを使うかどうかの判断表

状況 おすすめ
サーバー1台、コンテナ数個 Docker Compose
数台規模、とにかく手間を減らしたい クラウドのコンテナ実行サービス(Amazon ECS、Cloud Run、Azure Container Appsなど)
多数のサービス、チームが複数、細かく制御したい Kubernetes(マネージド)
学習・検証 kind / minikube

Kubernetesは強力な分、覚えることも多い仕組みです。規模と必要な機能に合わせて選ぶのが、無理のない進め方です。

よくある質問

Q. DockerとKubernetesの違いは何ですか? A. Dockerはコンテナを作って動かすための道具、Kubernetesはたくさんのコンテナを複数のサーバーで管理するための基盤です。KubernetesはDockerなどで作ったコンテナイメージを受け取って動かします。

Q. PodではなくDeploymentを書くのはなぜですか? A. Podを直接作ると、落ちたときやノードが止まったときに作り直されません。Deploymentにすると、指定した数を保ち、更新とロールバックもできるためです。

Q. Serviceに接続できません。どこを見ればいいですか? A. kubectl get endpoints web(または kubectl get endpointslices)で、振り分け先のPodが登録されているかを確認します。空なら、ServiceのselectorとPodのラベルが一致していないか、readinessProbeが通っていないことが多いです。

Q. 入門にはどのくらいのPCスペックが必要ですか? A. kindやminikubeで小さなアプリを動かすなら、メモリ8GB程度から試せます。Docker Desktopなどに割り当てるメモリを増やしておくと安定します。

まとめ

  • Kubernetesは、あるべき状態をYAMLで宣言し、その状態を自動で保つコンテナ管理基盤
  • 自分で書くのは Deployment・Service・ConfigMap・Secret・Ingress が中心
  • selectorとラベルの一致が配線そのもの。検証ツールは --strict を付けて使う
  • 困ったら kubectl describe のEvents と kubectl logs --previous
  • readinessは振り分けの判断、livenessは再起動の判断。役割を分けて設定する
  • requestsは配置の基準、limitsは上限。メモリ上限を超えるとOOMKilled
  • まずは kind・minikube で、自己修復とローリングアップデートを体験する

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Kubernetes入門|主要リソースとYAMLの書き方、kubectl早見表」

株式会社RJCでは、コンテナからKubernetesへと広がるインフラの技術も、手を動かしながら仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?