はじめに
Dockerでコンテナを起動できるようになると、「複数のサーバーでコンテナを動かすにはどうするのか」「コンテナを一定数動かし続けるにはどうすればよいのか」といった疑問が出てきます。
こうしたコンテナの配置や管理を自動化するための仕組みが、Kubernetesです。
この記事では、Dockerを触ったことがある方に向けて、Kubernetesの基本概念から、NginxをPod・Deploymentとして作成し、状態を確認するところまでを解説します。
学習の流れは次のとおりです。
- Kubernetesの役割と基本用語を理解する
- ローカルのKubernetesクラスタへ接続する
- YAMLファイルからPodを作成する
- Deploymentで3つのPodを作成する
- ブラウザでNginxへ接続する
- Podの数を変更し、実習で作成したリソースを削除する
Dockerの基本操作を先に確認したい場合は、Docker入門をご覧ください。
1. Kubernetesとは
Kubernetesは、コンテナ化したアプリケーションの配置や実行状態の管理などを自動化する、オープンソースのプラットフォームです。「K8s」と略されることもあります。
例えば、Webアプリケーションを3つのPodで動かしたい場合、Kubernetesに「このアプリケーションのPodを3つ維持する」という設定を渡します。Kubernetesのコントローラーは現在の状態を確認し、設定された状態に近づけるために動作します。
このように、実現したい状態を設定で示す方法を、宣言的な管理と呼びます。
Dockerとの関係
DockerとKubernetesは、役割が異なります。
| 項目 | 主な役割 |
|---|---|
| Docker | イメージの作成や、コンテナの実行に使う |
| Kubernetes | クラスタ上でコンテナ化したアプリケーションの配置や実行状態を管理する |
KubernetesはDocker専用の管理ツールではありません。各Nodeでは、containerdなどのコンテナランタイムがコンテナを実行します。Dockerで作成した対応形式のイメージも利用できます。kubernetes.io
Kubernetesを使うメリット
- 構成をファイルで管理できる: 使用するイメージやPodの数などをYAMLに記述できます。
- 複数のNodeにアプリケーションを配置できる: KubernetesがPodの配置先を決定します。
- 指定したPodの数を維持できる: Deploymentなどの管理下では、Podが失われた場合に代わりのPodを作成します。
- アプリケーションの更新を管理できる: Deploymentを使うと、Podの設定変更に伴う更新を管理できます。
ただし、Podを増やすだけで高可用性が完成するわけではありません。Nodeの配置、アプリケーションの設計、データの保存方法なども関係します。
まずは、ローカル環境で「設定した状態に合わせてPodが作られる」という動きを理解しましょう。
2. クラスタと主要コンポーネント
Kubernetesの実行環境を、クラスタと呼びます。クラスタは、全体を管理するコントロールプレーンと、Podを実行するNodeなどで構成されます。
Nodeは、物理サーバーや仮想マシンなど、Kubernetesの管理下で動作する実行環境です。
コントロールプレーン
コントロールプレーンは、クラスタの状態を管理し、Podの配置などを決定します。古い資料では「マスター」と呼ばれることがあります。
| コンポーネント | 主な役割 |
|---|---|
| kube-apiserver | クラスタを操作するためのAPIを提供する |
| etcd | クラスタの状態や設定を保存する |
| kube-scheduler | 新しく作るPodの配置先Nodeを決める |
| kube-controller-manager | 各種コントローラーを動かし、現在の状態を望ましい状態へ近づける |
Node側のコンポーネント
| コンポーネント | 主な役割 |
|---|---|
| kubelet | Node上でPodの仕様に従ってコンテナの実行を管理する |
| コンテナランタイム | コンテナを実際に実行する |
| kube-proxy | Serviceへの通信を実現するネットワーク処理を担う。構成によっては別の仕組みが代替する |
最初から内部実装まで覚える必要はありません。「APIで設定を受け取り、配置を決め、Node上でコンテナを動かす」という役割分担を押さえてください。
ローカルのシングルノード環境では、コントロールプレーンとアプリケーションの実行を同じNodeが担うこともあります。Kubernetes
3. 最初に覚えたいリソース
Kubernetesでは、PodやDeploymentなどをリソースとして扱います。
| リソース | 役割 |
|---|---|
| Node | Podを配置する実行環境 |
| Namespace | クラスタ内のリソースを名前で区分する仕組み |
| Pod | 1つ以上のコンテナをまとめて実行する、基本となる単位 |
| ReplicaSet | 指定した数のPodを維持する |
| Deployment | ReplicaSetを管理し、Podの構成変更に伴う更新などを扱う |
| Service | Podへの安定した接続先などを提供する |
Podはコンテナを実行する単位
Podには、1つ以上のコンテナが含まれます。同じPod内のコンテナは、ネットワークなどの実行環境を共有します。
今回の実習では、1つのPodにNginxのコンテナを1つ配置します。
Deployment・ReplicaSet・Podの関係
Deploymentを作成すると、その管理下にReplicaSetが作られ、ReplicaSetがPodの数を維持します。
例えば、Deploymentに replicas: 3 と指定すると、通常の作成直後の構成では、1つのReplicaSetが3つのPodを管理します。
アプリケーションを更新した場合などは、複数世代のReplicaSetが残ることがあります。DeploymentとReplicaSetが常に1対1とは限りません。
通常のアプリケーションの配置では、ReplicaSetを直接作成するより、Deploymentを使います。Kubernetes
Namespaceで実習用リソースを分ける
Namespaceは、PodやDeploymentなどの名前を区分するために使います。独立した別クラスタを作る仕組みではありません。また、NodeはNamespaceに所属しないリソースです。
この記事では、学習用に k8s-intro というNamespaceを作成します。
4. ローカルのKubernetes環境を準備する
この記事では、MacまたはWindowsでDocker Desktopを使用する環境を想定します。Docker Desktopが動作し、インターネットからコンテナイメージを取得できる状態で進めてください。
Docker DesktopでKubernetesを用意する
Docker Desktopの画面はバージョンによって異なります。現在の公式手順では、次の流れで作成します。
- Docker Desktopを起動する
- 「Kubernetes」の画面を開く
- 「Create cluster」を選択する
- クラスタの作成方式を選ぶ
- 「Create」を実行し、準備が完了するまで待つ
作成方式としてKubeadmとkindが表示される場合、最初はシングルノード構成のKubeadmで進められます。kindで作成したクラスタでも、この記事の基本操作は共通です。Docker Docs
古い画面では、設定内の「Kubernetes」から「Enable Kubernetes」を有効にする形式の場合があります。
画面が異なる場合は、Docker公式のKubernetes設定手順を確認してください。
kubectlが使えることを確認する
kubectl は、KubernetesのAPIを操作するためのコマンドラインツールです。
ターミナルで次のコマンドを実行します。
kubectl version --client
クライアントのバージョン情報が表示されれば、コマンド自体は利用できます。ただし、この確認だけではクラスタに接続できているかは分かりません。
kubectl が見つからない場合は、Kubernetes公式のツール導入手順を確認してください。
接続先を確認する
クラスタへの接続設定を、コンテキストと呼びます。まず、登録されている設定を確認します。
kubectl config get-contexts
Docker Desktopの docker-desktop が登録されていることを確認し、切り替えます。
kubectl config use-context docker-desktop
kubectl config current-context
次のように表示されれば、接続先はDocker Desktopです。
docker-desktop
続けて、クラスタへの接続とNodeの状態を確認します。
kubectl cluster-info
kubectl get nodes
kubectl cluster-info で接続先の情報が表示され、Nodeの STATUS が Ready になっていることを確認してください。Nodeの名前や数は、作成方式によって異なります。
以降は、学習用のローカルクラスタで実行します。
作業場所とNamespaceを作成する
作業用ディレクトリを作成します。
mkdir k8s-intro
cd k8s-intro
次に、実習用のNamespaceを作成します。
kubectl create namespace k8s-intro
kubectl get namespaces
一覧に k8s-intro があり、`STATUS` が Active なら準備完了です。
k8s-intro がすでに存在する場合は、以前の実習用かを確認してから使用してください。
5. マニフェストからPodを作成する
Kubernetesのリソースを定義するファイルを、マニフェストと呼びます。この記事ではYAML形式を使用します。
pod.yamlを作成する
エディターで pod.yaml を作成し、次の内容を保存してください。
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
namespace: k8s-intro
labels:
app: nginx-pod-demo
spec:
containers:
- name: nginx
image: nginx:stable-alpine
ports:
- containerPort: 80
各項目の役割は次のとおりです。
| 項目 | 役割 |
|---|---|
apiVersion | このリソースで使用するAPIのバージョン |
kind | 作成するリソースの種類 |
metadata.name | リソースの名前 |
metadata.namespace | 作成先のNamespace |
metadata.labels | リソースを識別・選択するためのラベル |
spec | 実現したい状態の定義 |
spec.containers | Pod内で実行するコンテナの定義 |
image | 使用するコンテナイメージ |
containerPort | コンテナが使用するポートの情報 |
apiVersion は、手元のKubernetesのバージョン番号をそのまま書く項目ではありません。Podでは v1、後で作成するDeploymentでは apps/v1 を使います。
今回はNginx公式イメージの stable-alpine タグを使います。このタグの参照先は更新されるため、厳密な再現性が必要な場合はバージョンやダイジェストを固定してください。
また、`containerPort: 80` を記述するだけでは、PCの80番ポートや8080番ポートへ公開されません。ブラウザでの確認は、後ほど port-forward を使って行います。
Podを作成する
次のコマンドで、マニフェストをクラスタへ反映します。
kubectl apply -f pod.yaml
初回作成時の出力例です。
pod/nginx-pod created
-f は、読み込むファイルを指定するオプションです。今回はYAML内にNamespaceを記述しているため、Podは k8s-intro に作成されます。
Podの状態を確認する
kubectl get pods -n k8s-intro
-n は、操作対象のNamespaceを指定するオプションです。
起動が完了した場合の出力例です。経過時間などは環境によって異なります。
NAME READY STATUS RESTARTS AGE
nginx-pod 1/1 Running 0 30s
| 表示 | 意味 |
|---|---|
NAME | Podの名前 |
READY | Readyになった通常コンテナの数/通常コンテナの総数 |
STATUS | 現在の状態を示す表示 |
RESTARTS | コンテナの再起動回数 |
AGE | 作成からの経過時間 |
起動直後は ContainerCreating になることがあります。状態の変化を続けて見る場合は、次のようにします。
kubectl get pods -n k8s-intro -w
確認を終えるときは Ctrl + C を押します。これは表示の監視を終了する操作であり、Podは停止しません。
配置先のNodeやPodのIPを確認するには、`-o wide` を付けます。
kubectl get pods -n k8s-intro -o wide
実習用のPodを削除する
確認できたら、単体で作成したPodを削除します。
kubectl delete -f pod.yaml
kubectl get pods -n k8s-intro
ほかにPodがなければ、次のように表示されます。
No resources found in k8s-intro namespace.
今回のPodにはReplicaSetなどの管理元がないため、削除しても代わりのPodは作成されません。YAMLをPCに保存してあるだけでは、自動的に再作成されない点を押さえてください。
6. Deploymentで3つのPodを作成する
次は、Deploymentを使ってNginxのPodを3つ作成します。
deployment.yamlを作成する
同じディレクトリに deployment.yaml を作成し、次の内容を保存してください。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: k8s-intro
spec:
replicas: 3
selector:
matchLabels:
app: nginx-deployment-demo
template:
metadata:
labels:
app: nginx-deployment-demo
spec:
containers:
- name: nginx
image: nginx:stable-alpine
ports:
- containerPort: 80
Podのマニフェストとの主な違いは、次の項目です。
| 項目 | 役割 |
|---|---|
replicas: 3 | 維持するPodの数を3つにする |
selector.matchLabels | 管理対象のPodを選ぶ条件 |
template.metadata.labels | 作成するPodに付けるラベル |
template.spec | 作成するPodの仕様 |
selector.matchLabels で指定した条件を、`template.metadata.labels` が満たす必要があります。今回の例では、両方を app: nginx-deployment-demo にそろえています。Kubernetes
また、Deployment自体の名前は metadata.name、作成されるPodのコンテナ名は template.spec.containers 内の name です。別の項目として読み分けてください。
Deploymentを作成する
kubectl apply -f deployment.yaml
初回作成時の出力例です。
deployment.apps/nginx-deployment created
作成直後は、イメージ取得やコンテナ起動に時間がかかる場合があります。次のコマンドで、Deploymentの展開完了を待ちます。
kubectl rollout status deployment/nginx-deployment -n k8s-intro --timeout=120s
完了時には、次のように表示されます。
deployment "nginx-deployment" successfully rolled out
120秒でタイムアウトしても、それだけでDeploymentが削除されたり、処理が取り消されたりするわけではありません。起動しない場合は、後述のエラー確認へ進んでください。
Deploymentを確認する
kubectl get deployments -n k8s-intro
出力例です。
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 1m
READY が 3/3 なら、指定した3つのPodがReadyになっています。`UP-TO-DATE` は現在のPodテンプレートに対応するPod数、`AVAILABLE` は利用可能と判定されたPod数です。
今回の設定では、HTTP応答を調べるReadiness Probeは定義していません。アプリケーションへのHTTP接続も、次の節で別途確認します。
ReplicaSetを確認する
kubectl get replicasets -n k8s-intro
出力例です。名前の末尾は環境やPodテンプレートによって異なります。
NAME DESIRED CURRENT READY AGE
nginx-deployment-7b6f8d9c5b 3 3 3 1m
ReplicaSetのマニフェストを直接作成していなくても、Deploymentによって作成されています。`DESIRED` は望ましいPod数、`CURRENT` は現在のPod数、`READY` はReadyになったPod数です。
Podを確認する
kubectl get pods -n k8s-intro -l app=nginx-deployment-demo
-l は、ラベルの条件で対象を絞り込むオプションです。
出力例です。Pod名の末尾は自動生成されるため、同じ名前にはなりません。
NAME READY STATUS RESTARTS AGE
nginx-deployment-7b6f8d9c5b-2q7kl 1/1 Running 0 1m
nginx-deployment-7b6f8d9c5b-6m8np 1/1 Running 0 1m
nginx-deployment-7b6f8d9c5b-x4r9s 1/1 Running 0 1m
これで、Deployment・ReplicaSet・Podの3種類を確認できました。
単体で作成したPodとは異なり、ReplicaSetの管理下でPodが失われると、望ましい数を維持するために代わりのPodが作成されます。ただし、必要なNodeの空き容量やイメージ取得などの条件が満たされなければ、すぐに起動できるとは限りません。
7. ブラウザでNginxの動作を確認する
Podを作成しただけでは、PCの localhost:8080 へ自動的に公開されません。
今回は、動作確認用に kubectl port-forward を使います。
kubectl port-forward deployment/nginx-deployment 8080:80 -n k8s-intro
これは、Deploymentに対応するPodのうち1つを選び、PCの8080番ポートから、そのPodの80番ポートへ転送する操作です。3つのPodへの負荷分散を確認するコマンドではありません。Kubernetes
このターミナルを開いたまま、ブラウザで次のURLへアクセスします。
Nginxの初期ページが表示されれば、選択されたPod内のNginxがHTTPリクエストに応答しています。
確認が終わったら、コマンドを実行しているターミナルで Ctrl + C を押します。ポート転送は終了しますが、DeploymentやPodは動作を続けます。
8080番ポートが使用中の場合は、次のようにPC側の番号を変更してください。
kubectl port-forward deployment/nginx-deployment 8081:80 -n k8s-intro
この場合の接続先は http://localhost:8081/ です。
8. YAMLを変更してPodの数を変える
宣言的な管理を確認するため、Podの数を3つから2つへ変更してみましょう。
deployment.yaml の replicas を、次のように変更して保存します。ほかの項目はそのままで構いません。
replicas: 2
同じファイルを、もう一度反映します。
kubectl apply -f deployment.yaml
kubectl rollout status deployment/nginx-deployment -n k8s-intro --timeout=120s
kubectl get deployments -n k8s-intro
kubectl get pods -n k8s-intro -l app=nginx-deployment-demo
変更が反映されると、Deploymentの READY が 2/2 になり、稼働するPodも2つになります。削除処理の途中では、一時的に Terminating のPodが表示される場合があります。
ファイルを編集しただけでは、クラスタの設定は変わりません。`kubectl apply` で設定を渡すと、コントローラーがその設定に合わせて動作します。
9. うまく動かないときの確認方法
クラスタへ接続できない
connection refused などが表示される場合は、Docker DesktopとKubernetesの起動状態を確認します。
kubectl config current-context
kubectl cluster-info
kubectl get nodes
接続先が docker-desktop か、Nodeが Ready になっているかを確認してください。
Podが見つからない
今回のPodは k8s-intro に作成しています。
kubectl get pods -n k8s-intro
-n を省略すると、現在のコンテキストに設定されたNamespaceが対象になります。通常は default ですが、設定によって異なります。
一覧に何も表示されない場合は、Namespaceの指定と kubectl apply の実行結果を確認してください。
PodがRunningにならない
まず、Pod名と状態を確認します。
kubectl get pods -n k8s-intro
次に、実際のPod名を指定して詳細を表示します。以下の POD_NAME は、一覧に表示された名前に置き換えてください。
kubectl describe pod POD_NAME -n k8s-intro
出力の末尾にある Events に、配置やイメージ取得などの失敗理由が表示されることがあります。
| 状態の例 | 主に確認すること |
|---|---|
Pending | Nodeの空き容量や配置条件を、Eventsで確認する |
ContainerCreating | 作成処理を待ち、長引く場合はEventsを確認する |
ErrImagePull / ImagePullBackOff | イメージ名・タグ・認証・レジストリへの接続を確認する |
CrashLoopBackOff | コンテナが繰り返し終了する理由を、ログで確認する |
コンテナのログは、次のように表示します。
kubectl logs POD_NAME -n k8s-intro
これらの表示だけで原因を断定せず、Eventsとログを読み合わせてください。
YAMLのエラーが出る
YAMLではインデントに半角スペースを使用します。タブを使っていないか、同じ階層の項目がそろっているかを確認してください。
Deploymentでは、`selector.matchLabels` とPodテンプレートのラベルの対応も確認します。今回の例では、両方を app: nginx-deployment-demo にします。
10. 実習で作成したリソースを削除する
まず、`port-forward` が動作している場合は Ctrl + C で終了します。
Deploymentを削除します。
kubectl delete -f deployment.yaml
通常、この操作でDeploymentが管理するReplicaSetと、そのReplicaSetが管理するPodも削除されます。
確認します。
kubectl get deployments,replicasets,pods -n k8s-intro
削除が完了していれば、対象のリソースは表示されません。
この記事の実習専用に作成したNamespaceで、ほかの用途に使っていないことを確認し、削除します。
kubectl delete namespace k8s-intro
Namespaceを削除すると、その中に残っているPodなどのリソースも削除対象になります。
PC上の pod.yaml と deployment.yaml は残ります。再度試す場合はNamespaceを作成し直し、必要なマニフェストを反映してください。
なお、これらは実習用リソースの削除であり、Docker DesktopのKubernetesクラスタ自体を停止する操作ではありません。
11. まとめ
この記事では、Kubernetesの基本概念を確認し、PodとDeploymentをマニフェストから作成しました。
- Kubernetesは、コンテナ化したアプリケーションの配置や実行状態を管理する
- マニフェストに「望ましい状態」を記述し、`kubectl apply` で反映する
- Podは、コンテナをまとめて実行する基本単位
- DeploymentはReplicaSetを管理し、ReplicaSetが指定した数のPodを維持する
kubectl getで状態を確認し、`describe` やlogsで詳細を調べるcontainerPortの指定だけでは、PC側へポートは公開されないport-forwardを使うと、動作確認用にPodへ接続できる
まずは、Podを1つ作成する場合と、Deploymentで複数のPodを管理する場合の違いを押さえてください。
次は、Podへの安定した接続先を用意するServiceを学ぶと、アプリケーションの起動と通信経路の役割をつなげて理解できます。
参考資料
- 提供された参考PDF「10. Kubernetes超入門」(主にp.1〜13)。56aec0bc-bcaa-4cbe-bd71-b775e13a1dc1_10.kubernetes超入門.pdf
- Kubernetes公式:Kubernetes Components
- Kubernetes公式:Objects In Kubernetes
- Kubernetes公式:Namespaces
- Kubernetes公式:Pods
- Kubernetes公式:ReplicaSet
- Kubernetes公式:Deployments
- Kubernetes公式:Port Forwarding
- Docker公式:Kubernetesの設定
- Docker Hub:Nginx公式イメージ
※参考PDFの古い名称・イメージ指定などは見直し、環境準備は現在の公式手順で補足しています。実習用Namespaceの作成、ポート転送、Pod数の変更、エラーの確認、削除手順は、本稿の実習補足です。