32
29

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ってなんだっけ

Last updated at Posted at 2025-05-13

はじめに

昨今の流れとして、システム開発においてローカル環境ではDocker、開発・本番環境は、ECS、EKS等を触る開発者は多いんじゃないでしょうか!

そんな自分がこんなことを思いました。

  • k8sディレクトリにパッと見てわからないyamlファイルによってKubernetesの環境がセットアップされているな
  • 開発環境のメモリがひっ迫してる!とか言ってるけどなんでそんなことが起きるのかわからんけど、とりあえずkubectl delete deployment {deploymentName}って言われてるからしてみたけど結局何したかったんだっけ

のように、Kubernetesを使っているというのはわかっているが、

  • そもそもKubernetesってなんだっけ
  • コマンドは理解しているけど、それって結局何を表示してるんだっけ

そんな自分の疑問を解消するために今回は記事を作成しました!
電車の中で次の駅にいくまでに軽く読んでもらえるとうれしいです!

Kubernetesは、略称としてはk8sとも呼ばれており、由来としては、頭文字Kと末尾のsの間に8文字あるため。
(本記事でも下記よりk8sと略します。)

簡単な自己紹介

  • エンジニア2年目
  • Go / TypeScriptをメイン
  • Dockerの概要は把握済み
  • k8sは開発中にコマンドを叩いて、実行とログの見方は把握済み
  • AWSとかのインフラ系はなんとなくくらいしかわからない

ゴール

「k8sとは」 を説明できること

対象読者

  • コンテナ・イメージという言葉がある程度頭の中に思い浮かぶ方
  • k8sについての概要を喋れるようになりたい方

実行環境

  • Ubuntu 22.04.5 LTS
  • kind v0.22.0 go1.20.13 linux/amd64
  • Docker version 28.1.1, build 4eba377
  • Kubectl
    • Client Version: v1.29.15
    • Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
    • Server Version: v1.29.2

1. k8sってそもそも何?何がしたいの?

k8sの目的は、

「理想の状態を宣言するだけで、システムを自動で保ち続けること」

上記の目的を達成するために、k8sでは、以下のような機能が提供されています。

課題 機能提供
サービスが落ちたらどうする? 自動復旧するよ(再スケジュール、再起動)
リクエストが増えたら? 自動スケーリングでPodを増やすよ
アップデートしたいけど止めたくない ローリングアップデート、ロールバック
チームで環境を統一したい 全構成をyamlで宣言(IaC)
サーバー台数が増えた スケジューラーが自動で分散配置するよ
マルチ環境(開発・本番)で差異が出ちゃう! 再現性のある構成管理でどこでも同じ動作に!

また、目的を達成する手段としてコンテナ技術との相性がよかったため、k8sではコンテナ技術を用いることになりました。

下記がコンテナ技術の得意なことをまとめた表となります。

ゴール コンテナが得意なこと
環境を再現可能にしたい コンテナは常に同じ環境を再構成できる
瞬時に起動・停止したい VMよりはるかに高速に扱える
小さな構成単位で分けたい アプリ単位に細かくデプロイできる
分散運用したい ネットワーク越しでも一貫して管理できる

そのため、k8sを一言で表すと、

  • コンテナの管理を行うソフトウェア
  • コンテナのオーケストレーションソフトウェア

と言われる理由となっています。

2. 用語解説編

これから紹介する単語の意味を下記の表にまとめました。

用語 解説(一言)
クラスタ コンテナ(ノード)のまとまり
コントロールプレーン 司令塔。クラスタ全体を管理する
ワーカーノード 作業者。アプリケーションの実行場所
ポッド - Pod 最小の実行単位。複数コンテナを中に入れられる
ネームスペース - Namespace クラスタ内部の空間わけ
デプロイメント - Deployment Podの理想状態を宣言する
サービス - Service Podへの通信経路を提供する


クラスタ

複数ノードをまとめて管理するための単位のこと。

目的

「コンテナ化されたアプリケーションを、安定して自動的に動かし続けるための土台を提供すること」

コントロールプレーンやワーカーノードは、このクラスタという“くくり”の中で役割分担しながら協調動作する。

関係性は下記のとおり。

クラスタ
|
├── コントロールプレーン
└── ワーカーノード

コントロールプレーンとワーカーノード

コントロールプレーン(司令塔)

k8sクラスタ全体を管理・制御すること

ワーカーノード(作業者)

実際にアプリケーションを動作させること

このように役割を2つに分けることによって

  • 役割分担による責務の明確化
  • 安定性・可用性の確保
  • スケーラビリティの確保

を確保するようにしているそうです。

結局何がいいかは、

  • アプリケーション側に問題があったとしても、制御側が守られる
  • ワーカーノードを簡単に増減させることも容易
    ということが言えます。

コントロールプレーンとワーカーノードの構成要素

[コントロールプレーン]

構成要素 役割
kube-apiserver すべての操作を受け付けるKubernetesのフロントAPI。CLIや他コンポーネントはここにアクセスする。
etcd Kubernetesの全設定情報・状態情報を保存する分散キーバリューストア。超重要なデータベース。
kube-scheduler 新しく作られたPodを「どのノードに配置するか」自動で決定。
kube-controller-manager 状態を維持する各種コントローラー(例:NodeController, ReplicationController)を統合して動かす。
cloud-controller-manager(任意) クラウド特有の処理(例:LB設定、ボリューム作成)を切り離して制御。クラウド連携に使う。

[ワーカーノード]

構成要素 役割
kubelet 各ノード上でPodを管理するエージェント。APIServerから指示を受けてコンテナを起動・監視。各ノードで常駐する「システムプロセス」
kube-proxy サービス(Service)への通信を各Podにルーティング。iptablesやIPVSで制御。
Container Runtime 実際にコンテナを起動・停止するソフト。Kubernetesはこれを通じてコンテナを実行。

となります。

実際にこれらの構成要素が構築されているかは、コマンドで見ることができます。(下のログは加工したもの)

user@user:~$ kubectl get pods -A
NAMESPACE            NAME                                         READY   STATUS    RESTARTS       AGE
-- コントロールプレーン
kube-system          kube-apiserver-kind-control-plane            1/1     Running   0              6d4h
kube-system          kube-scheduler-kind-control-plane            1/1     Running   15 (8h ago)    6d4h
kube-system          kube-controller-manager-kind-control-plane   1/1     Running   13 (18h ago)   6d4h
kube-system          etcd-kind-control-plane                      1/1     Running   0              6d4h

-- ワーカーノード
kube-system          kube-proxy-n9h7d                             1/1     Running   0              6d4h
kube-system          coredns-76f75df574-d2qxw                     1/1     Running   0              6d4h
kube-system          coredns-76f75df574-fjnnm                     1/1     Running   0              6d4h

-- kind特有のpod
kube-system          kindnet-nqgtx                                1/1     Running   0              6d4h
local-path-storage   local-path-provisioner-7577fdbbfb-l8hvz      1/1     Running   0              6d4h

クラスタの説明の際に出した関係性の詳細が下記のようになります。

クラスタ
│
├── コントロールプレーン(クラスタ全体の制御を行う司令塔)
│   ├─ kube-apiserver
│   ├─ etcd
│   ├─ kube-scheduler
│   └─ kube-controller-manager
│
└── ワーカーノード(実際にコンテナを実行する場所)
    ├─ kubelet
    ├─ kube-proxy
    └─ container runtime

ポッド - Pod

k8sでアプリケーションを動かす最小の実行単位のこと。

目的

「複数のコンテナを"一緒に動かすべき1単位"としてまとめて、それを扱えるようにすること」

ここで大事なのが、1つのPod内に複数のコンテナを入れられるというところ。
通常のコンテナ運用(Dockerなど)では、1サービス=1コンテナであり、
それぞれのコンテナが独立して動作するのが一般的だと思います。

Docker単体の場合

システム
├── api-service
│   └── コンテナ: api-service:latest
├── logger-service
│   └── コンテナ: logger:latest
├── db
    └── コンテナ: mysql:8.0

一方Podの場合は、

クラスタ
├── api-pod
│   ├── コンテナ: api-service:latest
│   └── コンテナ: logger:latest
├── db-pod
    └── コンテナ: mysql:8.0

上記の差分は、api-serviceloggerがそれぞれ独立しているかapi-podというpodの中に属しているかの差になります。

api-serviceを増やしたい!ってなったとき

api-serviceへのトラフィックが高負荷になった。などが原因で、もう一つコンテナを増やしたいとなった場合、

Docker単体の場合では、

  • api-service自体をもう一つ増やす
  • (loggerをもう一つ増やす)
  • 増やしたapi-serviceの向き先を指定する

のような手順が必要になりますが、Podの構成を取っている場合、

  • api-podのpod数を増やす

だけで終了します。

Podという単位を用いることによって、スケーリングの際の手間が削減されます。
また、Pod内部では、localhostで通信ができるため、通信トラフィックがPod内部限定に限定されるのもメリットとなります。


ネームスペース - Namespace

k8sにおける「名前空間」を指します。

目的

「名前空間で論理的に区切って管理すること」

例えば、同一クラスタ内で同名のPodやServiceを環境ごとに使いたい場合、利用されます。

1つのクラスタ内部でのNamespaceの切り方

開発用のクラスタ
├── namespace: developer-1
│   ├── pod: api-server
│   └── pod: frontend
├── namespace: developer-2
│   ├── pod: api-server
│   └── pod: frontend
│   └── pod: cli
├── namespace: developer-3
│   ├── pod: api-server
...

上記の例のように、Namespaceでクラスタ内部を区切ることで、

  • 同一のPodだとしても複数立てることができる
  • 開発者ごとに独立した環境を用意することができる

などがメリットとして享受することができます。


デプロイメント - Deployment

Podの数と状態を自動で管理してくれる仕組みのこと。

目的

「アプリケーションを常に望ましい数・構成・状態で動かし続けること」

ユーザーが定義した理想状態に沿って、Podの数と状態を自動管理してくれます。
どうやって定義するかは下記に示します。

deployment.yamlの例

下記の内容のyamlをkubectl apply -f deployment.yamlというコマンドを打つことで、選択されているクラスタ内部にDeploymentを作成することができます。

下記は、api-serviceのDeploymentを作成する際のサンプルファイルとなります。

apiVersion: apps/v1        # Deploymentリソースを作成するためのAPIバージョン(apps/v1)
kind: Deployment          # リソースの種類を宣言 ほかにもPod/Service/ConfigMapなどがある
metadata:
  name: api-service              # Deploymentの名前(kubectlするときの識別名)
  labels:
    app: api-service             # ラベル。PodやServiceとの紐づけで用いる
spec:
  replicas: 3                    # Podは3つ起動してねという宣言
  selector:
    matchLabels:                 # metadata.labelで指定したものがここに入る。このラベルに一致するPodをこのDeploymentが管理する。
      app: api-service
  template:
    metadata:
      labels:
        app: api-service
    spec:
      containers:                 # Podに含めるコンテナ定義
        - name: api               # コンテナ名
          image: my-api:1.0       # イメージ
          ports: 
            - containerPort: 8080 # コンテナ内部でapiが待ち受けているポート。Serviceと連携する際に指定されることが多い
          env:                    # 環境変数として渡す(例:開発or本番など)
            - name: ENVIRONMENT   # 環境変数名 
              value: "dev"        # 環境変数の値

サービス - Service

Podへの安定した通信経路を提供する仕組みのこと。

目的

「Podの数やIPが変わっても、安定したアクセス経路を提供すること」

k8sでは、Podが再起動されたりスケーリングされるとIPが変わるため、
そのままだと接続先が不安定になります。
Serviceを使えば、一貫した名前・ポートでPodにアクセスできるようになります。

service.yamlの例

下記の内容のyamlをkubectl apply -f service.yamlというコマンドで適用することで、
Deploymentによって作られた複数のPodに対するエンドポイントを作成できます。

下記は、api-service Pod 群にアクセスするためのService定義ファイルです。

apiVersion: v1                       # Serviceリソースを作成するためのAPIバージョン(apps/v1)
kind: Service                        # リソースの種類を宣言 ほかにもPod/Service/ConfigMapなどがある
metadata:
  name: api-service                  # Serviceの名前。DNS名としても使える
spec:
  selector:                          # どのPodとつなぐかをラベルで指定。ここでは先ほど作成したapi-serviceに接続
    app: api-service
  ports:
    - port: 80                       # Serviceが外部から受け付けるポート
      targetPort: 8080               # 実際にPodの中で待ち受けているポート番号
  type: ClusterIP                    # 通常の内部通信向け。クラスタ外もしくはインターネット上からアクセスするならNodePortやLoadBalancerを使う

3. k8sの全体像

ここまで用語を理解してきたら、k8sの全体像がぼんやりとわかるようになったのではないでしょうか。

以下は、クラスタ内の構成をNamespaceごとに整理したものです。
kubectl get pods --A の出力をイメージしながら見ると、わかりやすいかもしれません。

クラスタ
├── namespace: kube-system/
│   ├── pod: kube-apiserver-control-plane
│   ├── pod: kube-scheduler-control-plane
│   ├── pod: kube-controller-manager-control-plane
│   ├── pod: etcd-control-plane
│   ├── pod: kube-proxy
│   ├── pod: coredns
│   └── pod: kindnet
│
├── namespace: dev/
│   ├── pod: api-service
│   └── pod: logger
│
├── namespace: prod/
│   ├── pod: api-service
│   └── pod: logger

4. k8s環境でよく使うコマンド

コマンドの目的 / 説明 コマンド例
現在のクラスタ情報を表示 kubectl cluster-info
ノード一覧の確認 kubectl get nodes
全NamespaceのPodを一覧表示 kubectl get pods --all-namespaces
現在のコンテキスト(クラスタ)を確認 kubectl config current-context
DeploymentやServiceなどを適用 kubectl apply -f <ファイル名>
リソースを削除 kubectl delete -f <ファイル名>, kubectl delete <リソースの種類> <リソース名>
Deployment、Service、Podの一覧 kubectl get deployments, kubectl get services, kubectl get pods
詳細な情報を確認(イベントやエラーなど) kubectl describe <リソースの種類> <リソース名>
Podのログを確認 kubectl logs -f <Pod名>
Pod内部に入るコマンド kubectl exec -it <Pod名> -- <シェルコマンド>
Podの数を変更(Deployment単位) kubectl scale deployment <Deployment名> --replicas=<数>
Namespaceの一覧を取得 kubectl get namespaces
特定NamespaceのPod一覧 kubectl get pods -n <Namespace名>

現在のクラスタ情報を表示

kubectl cluster-info

user@user:~$ kubectl cluster-info
Kubernetes control plane is running at https://127.0.0.1:46603
CoreDNS is running at https://127.0.0.1:46603/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
user@user:~$

ノード一覧の確認

kubectl get nodes

user@user:~$ kubectl get nodes
NAME                 STATUS   ROLES           AGE    VERSION
kind-control-plane   Ready    control-plane   7d2h   v1.29.2
user@user:~$

全NamespaceのPodを一覧表示

kubectl get pods --all-namespaces

user@user:~$ kubectl get pods --all-namespaces
NAMESPACE            NAME                                         READY   STATUS    RESTARTS       AGE
default              api-7649b9df7c-sfqdf                         1/1     Running   0              7d2h
default              cli-6bc58b99f5-km86s                         1/1     Running   0              7d2h
default              frontend-5c499498dd-vc5r2                    1/1     Running   0              7d2h
kube-system          coredns-76f75df574-d2qxw                     1/1     Running   0              7d2h
kube-system          coredns-76f75df574-fjnnm                     1/1     Running   0              7d2h
kube-system          etcd-kind-control-plane                      1/1     Running   0              7d2h
kube-system          kindnet-nqgtx                                1/1     Running   0              7d2h
kube-system          kube-apiserver-kind-control-plane            1/1     Running   0              7d2h
kube-system          kube-controller-manager-kind-control-plane   1/1     Running   16 (91m ago)   7d2h
kube-system          kube-proxy-n9h7d                             1/1     Running   0              7d2h
kube-system          kube-scheduler-kind-control-plane            1/1     Running   18 (91m ago)   7d2h
local-path-storage   local-path-provisioner-7577fdbbfb-l8hvz      1/1     Running   0              7d2h
user@user:~$

現在のコンテキスト(クラスタ)を確認

kubectl config current-context

user@user:~$ kubectl config current-context
kind-kind
user@user:~$

DeploymentやServiceなどを適用

kubectl apply -f deployment.yaml

user@user:~/Documents/workspace/k8s$ kubectl apply -f deployment.yaml
deployment.apps/api-service created
user@user:~/Documents/workspace/k8s$
kubectl apply -f service.yaml

user@user:~/Documents/workspace/k8s$ kubectl apply -f service.yaml
service/api-service created
user@user:~/Documents/workspace/k8s$

リソースを削除

kubectl delete -f deployment.yaml

user@user:~/Documents/workspace/k8s$ kubectl delete -f deployment.yaml
deployment.apps "api-service" deleted
user@user:~/Documents/workspace/k8s$
kubectl delete pod <pod-name>

user@user:~/Documents/workspace/k8s$ kubectl delete pod api-service-6d57cc4f85-fgz5x
pod "api-service-6d57cc4f85-fgz5x" deleted
user@user:~/Documents/workspace/k8s$

Deployment、Service、Podの一覧

kubectl get deployments

user@user:~/Documents/workspace/k8s$ kubectl get deployments
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
api        1/1     1            1           7d2h
cli        1/1     1            1           7d2h
frontend   1/1     1            1           7d2h
user@user:~/Documents/workspace/k8s$
kubectl get services

user@user:~/Documents/workspace/k8s$ kubectl get services
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
api          ClusterIP   10.244.1.15    <none>         443/TCP          7d2h
cli          ClusterIP   10.244.1.16    <none>         4401/TCP         7d2h
frontend     ClusterIP   10.244.1.17    <none>        3000:32000/TCP   7d2h
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP          7d2h
user@user:~/Documents/workspace/k8s$
kubectl get pods

user@user:~/Documents/workspace/k8s$ kubectl get pods
NAME                        READY   STATUS         RESTARTS   AGE
api-7649b9df7c-sfqdf        1/1     Running        0          7d2h
cli-6bc58b99f5-km86s        1/1     Running        0          7d2h
frontend-5c499498dd-vc5r2   1/1     Running        0          7d2h
user@user:~/Documents/workspace/k8s$

詳細な情報を確認(イベントやエラーなど)

kubectl describe pod <pod-name>

user@user:~/Documents/workspace/k8s$ kubectl describe pod api-service-5d9b6c7b77-abcde
Name:           api-service-5d9b6c7b77-abcde
Namespace:      dev
Priority:       0
Node:           worker-node-1/10.1.2.3
Start Time:     Mon, 13 May 2025 10:05:00 +0900
Labels:         app=api-service
Status:         Running
IP:             10.244.1.15
Containers:
  api:
    Container ID:   docker://a1b2c3...
    Image:          my-api:1.0
    Port:           8080/TCP
    State:          Running
    Started:        Mon, 13 May 2025 10:05:02 +0900
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Events:                      <none>
user@user:~/Documents/workspace/k8s$
kubectl describe deployment <deployment-name>

user@user:~/Documents/workspace/k8s$ kubectl describe deployment api-service
Name:                   api-service
Namespace:              dev
CreationTimestamp:      Mon, 13 May 2025 10:00:00 +0900
Labels:                 app=api-service
Selector:               app=api-service
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:           RollingUpdate
Containers:
  api:
    Image:              my-api:1.0
    Port:               8080/TCP
    Environment:
      ENVIRONMENT:      dev
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
Events:   <none>
user@user:~/Documents/workspace/k8s$

Podのログを確認

-f--followの略であり、ログをリアルタイムで追いかけるオプション。
-fを入れない場合は、現在までのログを一回分だけ出力するようになる。

kubectl logs -f <pod-name>

Pod内部に入るコマンド

/bin/shの部分はそれぞれのイメージ事に設定してください。

kubectl exec -it <pod-name> -- /bin/sh

Podの数を変更(Deployment単位)

kubectl scale deployment api-service --replicas=5

user@user:~/Documents/workspace/k8s$ kubectl scale deployment api-service --replicas=5
deployment.apps/api-service scaled
user@user:~/Documents/workspace/k8s$

Namespaceの一覧を取得

kubectl get namespaces

user@user:~/Documents/workspace/k8s$ kubectl get namespaces
NAME                 STATUS   AGE
default              Active   7d2h
kube-node-lease      Active   7d2h
kube-public          Active   7d2h
kube-system          Active   7d2h
local-path-storage   Active   7d2h
user@user:~/Documents/workspace/k8s$

特定NamespaceのPod一覧

-A--all-namespacesのオプションとなり、全てのNamespaceのPodを出力できる。

kubectl get pods -n <<namespace名>>


user@user:~/Documents/workspace/k8s$  kubectl get pods -n default
NAME                        READY   STATUS             RESTARTS   AGE
api-7649b9df7c-sfqdf        1/1     Running            0          7d2h
cli-6bc58b99f5-km86s        1/1     Running            0          7d2h
frontend-5c499498dd-vc5r2   1/1     Running            0          7d2h
user@user:~/Documents/workspace/k8s$

5. k8sのメリット・デメリット

k8sを利用する際のメリット・デメリットは以下のようになります。

項目 内容
メリット - 自動化・可用性・拡張性が高い
- コンテナを理想の数・状態で維持してくれる
- 開発から本番まで同じ構成が使える
デメリット - 学習コストが高い
- 構成に柔軟性があるため、リソース設定を誤るとAWS,GCPなどのクラウドサービスではコストが爆増する危険がある

メリットに関しては、本記事内部で多数紹介しましたが、デメリットに関しては、ここまで記事を読んだ方であれば、k8sを使うのにも前提知識として用語や思想を知らないと使えはするが、知っているとはならないと感じたはずです。

また、deployment.yaml, service.yamlで記述したように、Pod内部での通信や、Pod外からの通信のポート解放、それ以上のネットワークの知識を求められることも多いため、デメリットとして上げさせていただきました。

6. まとめ

ここまで読んできてk8sとは何か。 を説明する材料になったでしょうか!
電車の中で読みきれるほどの文章ではなかった気がする。

簡単にまとめると、

  • 理想の状態を示すと、システムを自動でその状態に保ち続けてくれる
  • その目的を達成するためにk8sはスケーリングや、Podの再起動などの機能が搭載されている
  • 理想状態は、yamlで記述する
  • k8sがコンテナを使っている理由は、起動・停止が高速で、環境再現性が高いなどの理由

参考になっていれば幸いです!

32
29
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
32
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?