ゼロから始めるKubernetesチュートリアル:k8s入門ガイド
はじめに:Kubernetesとは何か? なぜ学ぶのか?
現代のソフトウェア開発において、アプリケーションは複雑化し、マイクロサービスアーキテクチャが主流になりつつあります。アプリケーションを構成する個々のサービスは、それぞれ独立して開発・デプロイ・スケールされる必要が出てきました。また、デプロイ環境も多様化し、オンプレミス、プライベートクラウド、パブリッククラウドなど、様々なインフラ上で動作させることが求められています。
このような背景から、アプリケーションのデプロイ、スケーリング、管理を自動化し、効率的に行うための技術が不可欠となりました。そこで登場したのが「コンテナ」技術、特にDockerです。コンテナは、アプリケーションとその実行に必要なすべての要素(コード、ランタイム、ライブラリ、環境変数など)を一つにまとめてパッケージ化し、どの環境でも一貫して動作することを可能にします。
しかし、コンテナ技術だけでは、複雑なアプリケーションの運用には限界があります。例えば、以下のような課題です。
- 大量のコンテナを効率的に管理したい(起動、停止、再起動)
- サービスの負荷に応じてコンテナ数を自動的に増減させたい(スケーリング)
- コンテナがクラッシュした場合に自動的に復旧させたい(自己修復)
- 新しいバージョンのアプリケーションに安全に更新したい(ローリングアップデート)
- 複数のコンテナ間の連携を容易にしたい
- 異なる環境(開発、ステージング、本番)で同じようにデプロイしたい
これらの課題を解決し、コンテナ化されたアプリケーションのデプロイ、スケーリング、管理、自動化を行うためのプラットフォームが「Kubernetes(クバネティス、またはk8s)」です。KubernetesはGoogleが開発し、現在はCloud Native Computing Foundation(CNCF)がメンテナンスしているオープンソースのコンテナオーケストレーションシステムです。
Kubernetesを学ぶことで、コンテナを使ったアプリケーション開発と運用を効率化し、より堅牢でスケーラブルなシステムを構築できるようになります。クラウドネイティブな開発に携わる上で、Kubernetesの知識はもはや必須と言えるでしょう。
このチュートリアルでは、全くのゼロからKubernetesの基本を学び、実際にローカル環境でアプリケーションを動かすところまでをステップバイステップで解説します。約5000語というボリュームで、Kubernetesのコアな概念から実践的な使い方までを網羅的に説明します。
さあ、Kubernetesの世界へ飛び込みましょう!
Kubernetesの基本概念
Kubernetesは独自の専門用語が多く、最初は戸惑うかもしれません。しかし、これらの概念を理解することが、Kubernetesを使いこなすための第一歩です。主要な概念を一つずつ見ていきましょう。
マスターノードとワーカーノード
Kubernetesクラスタは、大きく分けて「マスターノード」と「ワーカーノード」から構成されます。
-
マスターノード (Master Node) / コントロールプレーン (Control Plane)
クラスタ全体を管理し、様々な指示を出す司令塔の役割を担います。ユーザーからのAPIリクエストを受け付け、クラスタの状態を管理し、アプリケーションのデプロイやスケーリングなどを調整します。マスターノードは通常、高可用性を実現するために複数台で構成されます。
マスターノードの主要なコンポーネントは以下の通りです。- API Server: Kubernetes APIを公開し、ユーザーや他のコンポーネントからのリクエストを受け付けます。クラスタのすべての通信はこのAPI Serverを経由します。
- etcd: クラスタの状態や設定情報を保持する分散型KVS(Key-Value Store)です。クラスタの「真実の情報源」となります。
- Scheduler: 新しく作成されたPod(後述)を、どのワーカーノードで実行するかを決定します。ノードのリソース状況(CPU、メモリなど)や制約条件などを考慮します。
- Controller Manager: 様々なコントローラーを実行するコンポーネントです。各コントローラーはクラスタの現在の状態をetcdから取得し、ユーザーが定義した「理想の状態」との差分を監視し、その差分を埋めるように動作します。例えば、レプリケーションコントローラーはPodの数を監視し、指定された数になるようにPodを起動・停止します。
- Cloud Controller Manager (CCM): クラウドプロバイダー固有の制御ロジック(例: ロードバランサーの作成、ストレージボリュームのプロビジョニング)を実行します。これはパブリッククラウド上でKubernetesクラスタを構築する場合に利用されます。
-
ワーカーノード (Worker Node)
実際にアプリケーション(コンテナ)が動作する物理マシンまたは仮想マシンです。マスターノードからの指示を受け、Podを起動・停止したり、ストレージやネットワークを管理したりします。ワーカーノード上では以下の主要なコンポーネントが動作します。- Kubelet: 各ワーカーノード上で実行されるエージェントです。マスターノードのAPI Serverと通信し、割り当てられたPodの定義情報を受け取って、そのPodをノード上で実行・管理します。コンテナランタイムと連携してコンテナを起動したり、Podの状態をAPI Serverに報告したりします。
- Kube-proxy: 各ワーカーノード上で動作するネットワークプロキシおよびロードバランサーです。Service(後述)の概念を実現し、クラスタ内外からのネットワークトラフィックを適切なPodにルーティングします。
- Container Runtime: コンテナイメージを実行するソフトウェアです。Dockerが最も有名ですが、containerdやCRI-Oなど、Kubernetesのコンテナランタイムインターフェース(CRI)に準拠した様々なランタイムを利用できます。Kubeletはこのコンテナランタイムと連携してコンテナを管理します。
Pod
Kubernetesにおいて、デプロイおよび管理される最小の実行単位が「Pod」です。Podは1つまたは複数の密接に関連したコンテナの集まりです。なぜコンテナ単体ではなくPodという単位が必要なのでしょうか?
- 密接な関連性: 同じPod内のコンテナは、同じネットワーク名前空間とストレージボリュームを共有します。これにより、コンテナ間での通信やデータの共有が容易になります。例えば、Webサーバーコンテナと、そのログを収集・送信するサイドカーコンテナを同じPod内に配置するといった使い方ができます。
- 単一IPアドレス: Podにはクラスタ内で一意なIPアドレスが割り当てられます。同じPod内のコンテナは、
localhost
を通じて互いに通信できます。 - アトミックな単位: Podは単一の単位としてスケジュール、デプロイ、スケーリングされます。Pod内のすべてのコンテナは、同じノード上で一緒に起動・停止します。
Podは「使い捨て」の設計思想に基づいています。Podがクラッシュしたり、ノードが故障したりすると、新しいPodが別の適切なノードで自動的に再作成されます。PodのIPアドレスもその都度変わる可能性があります。そのため、Pod単体でアプリケーションを運用することは少なく、通常はより上位の抽象化レイヤーである「Controller」によって管理されます。
Controller (Deployment, ReplicaSetなど)
前述のように、Podは単体で運用するには揮発性があります。Kubernetesでは、「Controller」がPodの数を維持したり、デプロイプロセスを管理したりすることで、アプリケーションの可用性やスケーラビリティを保証します。Controllerは、etcdに保存された「理想の状態」(例えば、「このPodのインスタンスを3つ常に実行しておきたい」)と、クラスタの「現在の状態」を比較し、差分を解消するように動作します。
代表的なControllerには以下のようなものがあります。
- ReplicaSet: 指定された数のPodレプリカ(複製)が常に実行されていることを保証します。Podが停止したりノードが落ちたりした場合、ReplicaSetは自動的に新しいPodを起動して指定された数を維持しようとします。ReplicaSetは単独で使われることは少なく、通常はDeploymentによって管理されます。
- Deployment: アプリケーションのデプロイメントを宣言的に管理するためのControllerです。Deploymentを使用すると、アプリケーションの新しいバージョンへのローリングアップデートや、問題が発生した場合のロールバックなどを容易に行えます。Deploymentは内部的にReplicaSetを作成・管理することで、Podの更新やスケーリングを実現します。ほとんどの場合、ステートレスなアプリケーションをデプロイする際にはDeploymentを使用します。
- StatefulSet: ステートフルなアプリケーション(例: データベース)を管理するためのControllerです。各Podに安定したネットワーク識別子(ホスト名)と永続ストレージを付与し、Podのデプロイ順序や終了順序を制御できます。
- DaemonSet: 全ての(または指定した条件を満たす)ワーカーノード上に、Podのレプリカを1つずつ実行することを保証するControllerです。例えば、各ノード上でログコレクターや監視エージェントを実行する際に使用します。
この入門チュートリアルでは、最も一般的で重要なControllerであるDeploymentを中心に扱います。
Service
Podは起動・停止によってIPアドレスが変動するため、PodのIPアドレスに直接アクセスすることは現実的ではありません。また、同じ機能を持つ複数のPod(Deploymentによって管理されるPodレプリカ)に対して、どのようにトラフィックを振り分けるべきでしょうか?
これらの課題を解決するのが「Service」です。Serviceは、特定のPod群(通常はPodのラベルによって識別される)への安定したアクセスポイントを提供します。Serviceには固定のクラスタIPアドレスやDNS名が割り当てられ、クライアントはPodのIPアドレスを知ることなく、Service経由でPodにアクセスできます。Serviceは背後にあるPodへのロードバランシングも行います。
Serviceにはいくつかのタイプがあります。
- ClusterIP: クラスタ内部からのみアクセス可能な仮想IPアドレスをServiceに割り当てます。クラスタ内の他のPodやServiceから、このServiceにアクセスする場合に使用します。デフォルトのタイプです。
- NodePort: 各ワーカーノード上の特定のポートをServiceに割り当てます。クラスタ外部から、任意のワーカーノードの
<NodeIP>:<NodePort>
でServiceにアクセスできるようになります。開発やテストで外部からアクセスしたい場合に便利ですが、ポートの管理が煩雑になる可能性があります。 - LoadBalancer: クラウドプロバイダーのロードバランサーをプロビジョニングし、その外部IPアドレスでServiceにアクセスできるようにします。本番環境でインターネットからアプリケーションにアクセス可能にする際に一般的に使用されます。(対応するクラウドプロバイダーのKubernetesサービスが必要です)
- ExternalName: Serviceをクラスタ内部のPodではなく、外部のDNS名にマッピングします。CNameレコードのように動作します。
Namespace
Namespaceは、Kubernetesクラスタ内のリソース(Pod, Deployment, Serviceなど)を論理的に分割するための仕組みです。複数のチームやプロジェクトが同じクラスタを共有する場合に、リソースの競合を防ぎ、管理しやすくするために利用されます。例えば、「開発環境」「ステージング環境」「本番環境」といったようにNamespaceを分けてリソースを管理することができます。
リソースは常にどこかのNamespaceに属します。デフォルトでは default
Namespaceが使用されます。kube-system
NamespaceにはKubernetes自身のコンポーネントが配置されます。Namespaceを適切に利用することで、リソースの分離、アクセス制御(RBACと組み合わせる)、リソースクォータの設定などが可能になります。
Kubernetesを始める準備
Kubernetesの概念を学んだところで、実際にKubernetesを動かせる環境を準備しましょう。本番環境でKubernetesを使用する場合、Google Kubernetes Engine (GKE)、Amazon Elastic Kubernetes Service (EKS)、Azure Kubernetes Service (AKS) などのマネージドサービスを利用するのが一般的ですが、学習目的であれば、ローカル環境に手軽にKubernetesクラスタを構築できるツールがいくつかあります。ここでは代表的なツールをいくつか紹介し、MinikubeまたはDocker Desktopを使った方法を解説します。
ローカル環境でのKubernetes環境構築ツール
- Minikube: ローカルマシン上の単一ノードでKubernetesクラスタを簡単にセットアップできるツールです。仮想マシン(VirtualBox, VMware Fusionなど)やDockerコンテナ、Podmanなど様々なドライバーに対応しています。手軽にKubernetesを試すのに最適です。
- Docker Desktop: Docker Desktop for Windows/Macには、Kubernetesクラスタを内蔵する機能があります。Dockerを使用しているユーザーにとっては、追加のツールなしでKubernetes環境を用意できるため非常に便利です。単一ノードのクラスタです。
- Kind (Kubernetes IN Docker): DockerコンテナとしてKubernetesノードを起動することで、ローカルマシン上にマルチノードのKubernetesクラスタをセットアップできるツールです。主にKubernetes自体の開発やテスト、CI環境での利用を想定していますが、ローカルでの学習にも利用できます。
- k3s: Rancher Labsが開発した、軽量でリソース消費の少ないKubernetesディストリビューションです。エッジコンピューティングやIoTデバイスでの利用、あるいは開発・テスト環境に適しています。単一のバイナリで動作するためインストールが容易です。
今回は、最も手軽に始められるMinikubeまたはDocker Desktop for Mac/Windowsの内蔵Kubernetes機能を使用する方法を中心に説明します。どちらか一方を利用すればOKです。
Minikubeのセットアップ
Minikubeを使うには、まず仮想化ソフトウェア(VirtualBox、VMware Fusion、Hyper-Vなど)またはコンテナランタイム(Docker、Podman)が必要です。既にDockerがインストールされていれば、Dockerドライバーを使うのが手軽です。
1. インストール
お使いのOSに合わせてMinikubeをインストールします。最新の手順はMinikube公式ドキュメントを確認してください。
-
macOS (Homebrewを使用):
bash
brew install minikube -
Windows (Chocolateyを使用):
powershell
choco install minikube kubernetes-cli
(kubernetes-cli、つまりkubectl
も一緒にインストールされます) -
Linux (aptを使用):
bash
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
2. Minikubeの起動
インストール後、Minikubeクラスタを起動します。ドライバーを指定しない場合、適切なものが自動的に選択されますが、Dockerドライバーを使うのが簡単です。
bash
minikube start --driver=docker
(仮想マシンを使用する場合は --driver=virtualbox
などと指定します)
初回起動時は、Kubernetesの各種イメージのダウンロードなどが行われるため、少し時間がかかります。
起動が完了すると、Minikubeクラスタが動作している状態になります。
3. Minikubeの停止と削除
- 停止:
bash
minikube stop - 削除:
bash
minikube delete
Docker Desktop with Kubernetesのセットアップ
Docker Desktop (WindowsまたはMac) が既にインストールされている場合、設定からKubernetesを有効化するだけで利用できます。
1. Docker Desktopを起動
2. 設定画面を開く
Docker Desktopのメニューから「Settings (または Preferences)」を開きます。
3. Kubernetesタブを選択
左側のメニューから「Kubernetes」を選択します。
4. Kubernetesを有効化
「Enable Kubernetes」のチェックボックスをオンにします。「Show system containers (advanced)」もチェックしておくと、KubernetesのシステムPodが見えるようになります。
「Apply & Restart」ボタンをクリックすると、Docker Desktopが再起動し、Kubernetesコンポーネントが起動します。
ステータスが「Kubernetes is running」になれば準備完了です。
kubectl
コマンドラインツールのインストールと設定
kubectl
(キューブコントロール、またはキューブシーティーエル) は、Kubernetesクラスタと対話するためのコマンドラインツールです。クラスタの状態を取得したり、リソースを作成・更新・削除したりする際に使用します。
MinikubeやDocker Desktopをインストールすると、多くの場合 kubectl
も一緒にインストールされるか、あるいはMinikube自体が内蔵の kubectl
を提供します。もしインストールされていない場合は、別途インストールが必要です。
1. kubectl
のインストール
公式ドキュメントに従ってインストールしてください。
- macOS (Homebrew):
bash
brew install kubernetes-cli - Windows (Chocolatey):
Minikubeと一緒にインストールされているはずですが、単独でインストールする場合:
powershell
choco install kubernetes-cli - Linux (apt):
bash
sudo apt-get update && sudo apt-get install -y apt-transport-https
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubectl
2. kubectl
の設定確認
kubectl
は設定ファイル (通常は $HOME/.kube/config
) を見て、どのKubernetesクラスタ(コンテキスト)に接続するかを判断します。MinikubeやDocker Desktopは、起動時にこの設定ファイルを自動的に更新してくれます。
現在のコンテキストを確認します。
bash
kubectl config current-context
Minikubeを使っている場合は minikube
と表示されるはずです。Docker Desktopの場合は docker-desktop
と表示されるはずです。
もしMinikubeを起動しているのに minikube
になっていない場合は、以下のコマンドでコンテキストを切り替えます。
bash
kubectl config use-context minikube
3. クラスタ接続の確認
kubectl get nodes
コマンドで、クラスタ内のノード一覧が表示されれば、正しく接続できています。
bash
kubectl get nodes
MinikubeやDocker Desktopの場合、minikube
または docker-desktop
という名前のノードが1つ表示されるはずです。ステータスが Ready
になっていればOKです。
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane,master 5m v1.27.4
(バージョンやAGEは環境によって異なります)
これでKubernetesを操作するための準備が整いました。
最初のアプリケーションをデプロイする
それでは、実際にKubernetesクラスタに簡単なアプリケーションをデプロイしてみましょう。ここでは、Webサーバーとしてよく使われるNginxのコンテナイメージを使います。
Kubernetesでは、アプリケーションの構成をYAML形式のファイルで定義するのが一般的です。この「宣言的」なアプローチは、Kubernetesの強力な特徴の一つです。YAMLファイルに「こうなってほしい」という理想の状態を記述し、それをKubernetesに適用することで、Kubernetesがその状態を実現するように自動的に調整してくれます。
Nginxアプリケーションのデプロイ
Nginxをデプロイするために、まずDeploymentを作成します。Deploymentは、何個のPodを起動し、どのコンテナイメージを使用するかなどを定義します。
以下の内容で nginx-deployment.yaml
というファイルを作成してください。
“`yaml
nginx-deployment.yaml
apiVersion: apps/v1 # DeploymentリソースのAPIバージョン
kind: Deployment # リソースの種類がDeploymentであること
metadata: # リソースに関するメタデータ
name: nginx-deployment # Deploymentの名前
labels: # このDeploymentに付与するラベル
app: nginx
spec: # Deploymentの仕様
replicas: 3 # このDeploymentで管理するPodのレプリカ数(3つ起動)
selector: # このDeploymentが管理するPodを識別するためのセレクター
matchLabels: # ラベルが一致するPodを選択
app: nginx # ‘app: nginx’ というラベルを持つPodを選択
template: # Podのテンプレート(この定義に基づいてPodが作成される)
metadata: # Podのメタデータ
labels: # Podに付与するラベル(このラベルがselectorのmatchLabelsと一致する必要がある)
app: nginx
spec: # Podの仕様
containers: # Pod内で実行するコンテナのリスト
– name: nginx # コンテナの名前
image: nginx:latest # 使用するコンテナイメージ(Docker Hubから取得)
ports: # コンテナが公開するポート
– containerPort: 80 # NginxがデフォルトでListenするポート
“`
このYAMLファイルについて簡単に説明します。
apiVersion: apps/v1
: 使用するKubernetes APIのバージョンを指定します。Deploymentはapps/v1
グループに属します。kind: Deployment
: 作成したいリソースの種類がDeploymentであることを示します。metadata
: リソースの名前 (name
) やラベル (labels
) などの情報を定義します。ここで定義したapp: nginx
というラベルは、このDeployment自身を識別するために使われます(後述のServiceなどが参照する可能性があります)。spec
: リソースの具体的な仕様を定義します。replicas: 3
: NginxのPodを3つ起動し、常に3つのPodが動作している状態を維持することをKubernetesに指示しています。selector
: このDeploymentがどのPodを管理対象とするかを定義します。matchLabels: { app: nginx }
は、「ラベルapp: nginx
を持つPodを管理対象とする」という意味です。このセレクターの設定は非常に重要で、後述のPodテンプレートのラベルと一致している必要があります。template
: このDeploymentが新しくPodを作成する際に使用するテンプレートです。metadata.labels
: ここで定義したラベル (app: nginx
) が、作成される各Podに付与されます。このラベルがDeploymentのselector.matchLabels
と一致していることで、Deploymentは自身が管理すべきPodを識別できます。spec.containers
: Pod内で実行するコンテナのリストです。name: nginx
: コンテナの名前です。Pod内で一意である必要があります。image: nginx:latest
: 使用するコンテナイメージです。Docker Hubなどのコンテナレジストリから自動的に取得されます。:latest
は最新バージョンを指定します。ports
: コンテナが公開するポートを指定します。ここではNginxのデフォルトポートである80番を指定しています。これはドキュメントとしての意味合いが強く、必須ではありませんが、Serviceなどから参照される場合があります。
このYAMLファイルを使って、DeploymentをKubernetesクラスタに適用します。
bash
kubectl apply -f nginx-deployment.yaml
kubectl apply -f <ファイル名>
コマンドは、指定されたYAMLファイルの内容を読み込み、Kubernetesクラスタにその状態を実現するように指示します。リソースが存在しない場合は新しく作成し、既に存在する場合は差分を適用して更新します。
コマンドを実行すると、以下のような出力が得られるはずです。
deployment.apps/nginx-deployment created
DeploymentとPodの確認
Deploymentが作成されたら、正しくPodが起動しているか確認してみましょう。
まず、Deploymentのステータスを確認します。
bash
kubectl get deployments
出力例:
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 0/3 0 0 5s
最初は READY
が 0/3
などになっているかもしれません。しばらく待つと、KubernetesがPodの作成を開始し、Dockerイメージのダウンロードなどが行われます。再度コマンドを実行すると、徐々にPodが起動し、READY
が 3/3
になるはずです。
bash
kubectl get deployments
出力例(しばらく待った後):
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 30s
READY
が 3/3
になっていれば、3つのPodが正常に起動し、稼働可能な状態であることを示します。UP-TO-DATE
は最新の設定が適用されているPod数、AVAILABLE
は利用可能なPod数です。
次に、Podのステータスを確認します。
bash
kubectl get pods
出力例:
NAME READY STATUS RESTARTS AGE
nginx-deployment-67d8d665b6-abcde 1/1 Running 0 1m
nginx-deployment-67d8d665b6-fghij 1/1 Running 0 1m
nginx-deployment-67d8d665b6-klmno 1/1 Running 0 1m
STATUS
が Running
になっており、READY
が 1/1
(Pod内の全コンテナが準備完了)になっていれば正常です。nginx-deployment-
に続くランダムな文字列 (67d8d665b6-abcde
など) は、ReplicaSetおよびPodの名前の一部で、Deploymentが管理していることを示します。
Podの詳細情報を確認したい場合は、kubectl describe pod <pod名>
コマンドを使います。
bash
kubectl describe pod nginx-deployment-67d8d665b6-abcde
(↑ <pod名>
の部分は、kubectl get pods
で表示された実際のPod名に置き換えてください)
このコマンドは、Podがどのノードで実行されているか、コンテナの定義、イベント履歴(スケジューリング、イメージプル、コンテナ起動など)といった詳細な情報を提供してくれます。トラブルシューティングの際に非常に役立ちます。
特定のPodのコンテナログを確認したい場合は、kubectl logs <pod名>
コマンドを使います。
bash
kubectl logs nginx-deployment-67d8d665b6-abcde
Nginxの場合、アクセスログやエラーログが出力されることがあります。
Serviceの作成とアプリケーションへのアクセス
DeploymentによってNginx Podが3つ起動しましたが、このままではクラスタ外部からこれらのNginxにアクセスすることはできません。また、どのPodにアクセスすれば良いか(IPアドレスは変動します)もわかりません。そこで、Serviceを作成します。
今回は、ローカル環境で簡単にアクセスできるように、NodePortタイプのServiceを作成します。NodePortサービスは、各ワーカーノード上の特定のポートを開放し、そのポートに送られたトラフィックをServiceの背後にあるPodに転送します。
以下の内容で nginx-service.yaml
というファイルを作成してください。
“`yaml
nginx-service.yaml
apiVersion: v1 # ServiceリソースのAPIバージョン (Core v1グループ)
kind: Service # リソースの種類がServiceであること
metadata: # リソースに関するメタデータ
name: nginx-service # Serviceの名前
spec: # Serviceの仕様
selector: # このServiceがトラフィックを転送するPodを識別するためのセレクター
app: nginx # ラベルが ‘app: nginx’ であるPodを選択
ports: # Serviceが公開するポートのリスト
– protocol: TCP # プロトコル (TCPまたはUDP)
port: 80 # Serviceのクラスタ内部IPで公開されるポート番号
targetPort: 80 # Serviceがトラフィックを転送するPodのポート番号
nodePort: 30080 # 各ワーカーノード上で開放されるポート番号 (30000-32767の範囲)
type: NodePort # ServiceのタイプをNodePortに設定
“`
このYAMLファイルについて説明します。
apiVersion: v1
: ServiceはCore APIグループに属するため、v1
を指定します。kind: Service
: 作成したいリソースの種類がServiceであることを示します。metadata.name: nginx-service
: Serviceの名前です。spec.selector: { app: nginx }
: このServiceがトラフィックを転送するPodを識別するためのセレクターです。DeploymentのPodテンプレートで指定したラベルapp: nginx
を持つPodがServiceの対象となります。Serviceは、このラベルを持つPodを自動的に検出して、それらのPod間でトラフィックをロードバランシングします。spec.ports
: Serviceが公開するポート設定です。protocol: TCP
: TCPプロトコルを使用します。port: 80
: Serviceのクラスタ内部IPで公開されるポート番号です。クラスタ内の他のPodやServiceからこのServiceにアクセスする際に、このポート番号を使用します。targetPort: 80
: トラフィックの転送先であるPodのポート番号です。NginxコンテナがListenしている80番ポートを指定しています。nodePort: 30080
:type: NodePort
の場合に指定します。各ワーカーノード上で開放されるポート番号です。この例では30080番ポートを使用していますが、通常は自動的に割り当てられます(明示的に指定することも可能ですが、30000-32767の範囲である必要があります)。
spec.type: NodePort
: ServiceのタイプをNodePortに設定しています。
このYAMLファイルを使ってServiceを適用します。
bash
kubectl apply -f nginx-service.yaml
出力例:
service/nginx-service created
Serviceが作成されたら、そのステータスを確認します。
bash
kubectl get services
出力例:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 15m
nginx-service NodePort 10.107.14.180 <none> 80:30080/TCP 30s
nginx-service
という名前でServiceが作成されていることがわかります。TYPE
が NodePort
、CLUSTER-IP
はクラスタ内部IP、PORT(S)
が 80:30080/TCP
となっています。これは、「クラスタ内部からはServiceのClusterIPの80番ポートでアクセスでき、クラスタ外部からは各ノードの30080番ポートでアクセスできる。どちらの場合も、トラフィックはPodの80番ポートに転送される」という意味です。EXTERNAL-IP
はNodePortタイプでは表示されません(LoadBalancerタイプの場合に表示されます)。
アプリケーションへのアクセス
NodePort Serviceが作成されたので、クラスタ外部からNginxにアクセスできるようになりました。アクセス方法は、Minikubeを使用しているか、Docker Desktopを使用しているかで少し異なります。
-
Minikubeを使用している場合:
Minikubeクラスタにアクセスするための便利なコマンドがあります。
bash
minikube service nginx-service
このコマンドを実行すると、ブラウザが自動的に開き、Nginx Serviceにアクセス可能なURL(例:http://192.168.49.2:30080
)が表示されます。ブラウザにNginxのデフォルトページが表示されれば成功です。 -
Docker Desktop with Kubernetesを使用している場合:
Docker Desktopの場合、クラスタはローカルホストで動作しています。NodePort Serviceのポート番号はkubectl get services
コマンドの出力で確認したPORT(S)
の:<NodePort>
の部分です(この例では30080)。
ブラウザを開き、以下のURLにアクセスしてください。
http://localhost:30080
ブラウザにNginxのデフォルトページが表示されれば成功です。
これで、Kubernetesクラスタにアプリケーションをデプロイし、外部からアクセスできるようになりました!
リソースの削除
作成したリソース(DeploymentとService)を削除して、クラスタをクリーンな状態に戻しましょう。kubectl delete
コマンドを使います。YAMLファイルで定義したリソースを削除する場合も、apply
と同じように -f
オプションでファイルを指定できます。
bash
kubectl delete -f nginx-deployment.yaml
deployment.apps "nginx-deployment" deleted
bash
kubectl delete -f nginx-service.yaml
service "nginx-service" deleted
リソースが削除されたことを確認します。
bash
kubectl get deployments
(何も表示されないはずです)
bash
kubectl get services
(kubernetes
以外のServiceは表示されないはずです)
また、Podも自動的に削除されます。
bash
kubectl get pods
(何も表示されないはずです)
これで、作成したリソースは全て削除されました。
応用編:さらに理解を深める
基本的なKubernetesの概念とデプロイ手順を理解したところで、さらにKubernetesの便利な機能を見ていきましょう。
ConfigMap と Secret:設定情報の管理
アプリケーションの設定情報(データベース接続情報、APIキーなど)や、コンテナイメージには含めたくない機密情報(パスワード、証明書など)をどのように管理するべきでしょうか? コンテナイメージに直接含めるのは、イメージの再ビルドが必要になったり、セキュリティ上の問題があったりするため推奨されません。
Kubernetesでは、このような設定情報や機密情報を管理するために ConfigMap
と Secret
というリソースを提供しています。これらはクラスタ内部に保存され、Podから簡単に参照できるようになります。
- ConfigMap: 設定ファイル、コマンドライン引数、環境変数など、非機密な設定情報をキー-バリューペアまたはファイルとして保存します。
- Secret: パスワード、トークン、証明書など、機密情報を保存します。Secretはデフォルトでbase64エンコードされて保存されますが、これは暗号化ではないため、より高いセキュリティが必要な場合はetcdの暗号化などを検討する必要があります。
ConfigMapの例:
アプリケーションのログレベルを設定するConfigMapを作成してみましょう。
以下の内容で app-configmap.yaml
ファイルを作成します。
“`yaml
app-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data: # キー-バリュー形式で設定情報を記述
log_level: INFO
feature_flag_a: “true”
# 設定ファイルをまとめて格納する場合
app.properties: |
db.host=database
db.port=5432
db.name=mydatabase
“`
このConfigMapをクラスタに適用します。
bash
kubectl apply -f app-configmap.yaml
ConfigMapが作成されたことを確認します。
bash
kubectl get configmaps
PodからこのConfigMapを参照するには、環境変数としてマウントしたり、ボリュームとしてファイルシステムにマウントしたりする方法があります。
環境変数としてマウントする例(Podのspecの一部):
yaml
containers:
- name: my-app
image: my-app-image
env: # 環境変数として設定
- name: APP_LOG_LEVEL # 環境変数名
valueFrom: # 値は別のリソースから取得
configMapKeyRef: # ConfigMapのキーから取得
name: app-config # 参照するConfigMapの名前
key: log_level # 参照するキーの名前
- name: FEATURE_A
valueFrom:
configMapKeyRef:
name: app-config
key: feature_flag_a
ファイルとしてボリュームにマウントする例(Podのspecの一部):
yaml
containers:
- name: my-app
image: my-app-image
volumeMounts: # ボリュームをマウント
- name: config-volume # ボリュームの名前
mountPath: /etc/app/config # コンテナ内のマウントパス
volumes: # Podにアタッチするボリュームの定義
- name: config-volume # ボリュームの名前
configMap: # ConfigMapをボリュームとして使用
name: app-config # 参照するConfigMapの名前
この場合、コンテナ内の /etc/app/config/log_level
, /etc/app/config/feature_flag_a
, /etc/app/config/app.properties
といったパスにConfigMapのデータがファイルとして配置されます。
Secretの例:
データベースのパスワードを保存するSecretを作成してみましょう。SecretのデータはBase64でエンコードする必要があります。例えば、パスワードが mypassword123
の場合、Base64エンコードすると bXlwYXNzd29yZDEyMw==
となります。
“`bash
echo -n ‘mypassword123’ | base64
出力: bXlwYXNzd29yZDEyMw==
“`
以下の内容で db-secret.yaml
ファイルを作成します。
“`yaml
db-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque # Secretのタイプ(Opaqueは一般的なタイプ)
data: # Base64エンコードされたデータを記述
username: YWRtaW4= # ‘admin’ をBase64エンコード
password: bXlwYXNzd29yZDEyMw== # ‘mypassword123’ をBase64エンコード
“`
このSecretをクラスタに適用します。
bash
kubectl apply -f db-secret.yaml
Secretが作成されたことを確認します。kubectl get secrets
で一覧が表示されます。kubectl describe secret <secret名>
で詳細を確認できますが、データはBase64エンコードされたまま表示されます。デコードされた値を見たい場合は、kubectl get secret <secret名> -o yaml
でYAML形式で取得し、データ部分をBase64デコードする必要があります。
bash
kubectl get secrets
bash
kubectl get secret db-credentials -o yaml
PodからSecretを参照する方法も、ConfigMapと同様に環境変数としてマウントしたり、ボリュームとしてファイルシステムにマウントしたりします。
環境変数としてマウントする例(Podのspecの一部):
yaml
containers:
- name: my-app
image: my-app-image
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef: # Secretのキーから取得
name: db-credentials # 参照するSecretの名前
key: username # 参照するキーの名前
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
この方法でSecretを参照すると、Kubernetesは自動的にBase64デコードされた値をコンテナの環境変数に設定してくれます。
ボリュームとしてマウントする例(Podのspecの一部):
yaml
containers:
- name: my-app
image: my-app-image
volumeMounts:
- name: credentials-volume
mountPath: /etc/app/credentials # コンテナ内のマウントパス
readOnly: true # 機密情報なので読み取り専用に設定することが推奨
volumes:
- name: credentials-volume
secret: # Secretをボリュームとして使用
secretName: db-credentials # 参照するSecretの名前
この場合、コンテナ内の /etc/app/credentials/username
および /etc/app/credentials/password
というパスに、Base64デコードされたデータがファイルとして配置されます。
ConfigMapとSecretを適切に利用することで、アプリケーションコードやコンテナイメージから設定情報や機密情報を分離し、管理を容易にし、セキュリティを向上させることができます。
Volume と永続ストレージ:データの永続化
Podは揮発性であり、再起動されると状態が失われます。アプリケーションがデータを保持する必要がある場合(例: データベースのデータ、ファイルアップロードの保存先)、Podのライフサイクルとは独立した永続ストレージが必要です。Kubernetesでは「Volume」の概念を使用してこれを実現します。
Volumeは、Pod内のコンテナからアクセスできるディレクトリです。Podが作成される際にVolumeも作成され、Podが消滅するまで存在します。ただし、Podが消滅するとVolumeも消滅するVolumeタイプもあります(例: emptyDir
)。永続的にデータを保持するためには、Podのライフサイクルから独立したVolumeタイプを使用する必要があります。
永続ストレージに関わる主要な概念は以下の通りです。
- Volume: Podにアタッチされるストレージです。様々なタイプがあります。
emptyDir
: Podが作成されると同時に作成され、Podがノードから削除されると同時に消滅する一時的なボリュームです。Pod内のコンテナ間でファイルを共有するのに使えます。hostPath
: ワーカーノードのファイルシステム上のパスをPodにマウントします。ノード固有のパスに依存するため、ポータビリティに欠け、推奨されません(学習や特定の用途以外)。- クラウドプロバイダー固有のボリュームタイプ(AWS EBS, GCE Persistent Disk, Azure Diskなど)
- ネットワークストレージタイプ(NFS, iSCSIなど)
- PersistentVolume (PV): クラスタ管理者がプロビジョニングまたは動的にプロビジョニングした、クラスタ内の物理ストレージを表す抽象化リソースです。ストレージの種類(NFS、クラウドストレージなど)やサイズ、アクセスモードなどを定義します。
- PersistentVolumeClaim (PVC): ユーザーがPersistentVolumeストレージを「要求」するためのリソースです。アプリケーション開発者は、必要なストレージのサイズやアクセスモード(ReadWriteOnce, ReadOnlyMany, ReadWriteMany)を指定してPVCを作成します。Kubernetesは、その要求を満たす適切なPVを自動的に見つけてPVCにバインドします。ストレージの詳細(どこにあるか、どんな種類か)を知る必要がなく、ストレージの利用を抽象化できます。
多くのアプリケーション開発者は、直接PVを操作するのではなく、PVCを作成してストレージを要求し、そのPVCをPodから参照してVolumeとしてマウントする、という流れになります。
PVC/PVを使った永続ストレージの利用例:
永続的なデータを保存したいアプリケーションのために、1GiBの読み書き可能なストレージを要求するPVCを作成してみましょう。
以下の内容で my-pvc.yaml
ファイルを作成します。
“`yaml
my-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-persistent-volume-claim
spec:
accessModes: # アクセスモードの指定
– ReadWriteOnce # 1つのノードから読み書き可能
resources: # 要求するリソース
requests:
storage: 1Gi # 1GiBのストレージを要求
このPVCをクラスタに適用します。
bash
kubectl apply -f my-pvc.yaml
“`
PVCが作成され、Pending状態になるはずです(対応するPVが存在しないため)。ローカル環境(MinikubeやDocker Desktop)では、多くの場合StorageClass(ストレージの動的プロビジョニングを可能にするKubernetesリソース)がデフォルトで設定されており、PVCを作成すると自動的に対応するPVがプロビジョニングされます。
PVCとPVの状態を確認します。
bash
kubectl get pvc
kubectl get pv
PVCのSTATUSがPending
からBound
に変わっていれば、対応するPVとバインドされています。
次に、このPVCをVolumeとして使用するPodを作成します。
以下の内容で app-with-volume.yaml
ファイルを作成します。
“`yaml
app-with-volume.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-with-volume
spec:
replicas: 1
selector:
matchLabels:
app: app-with-volume
template:
metadata:
labels:
app: app-with-volume
spec:
containers:
– name: my-app
image: busybox # 例としてbusyboxイメージを使用
command: [“/bin/sh”, “-c”, “while true; do date >> /app-data/current_date.txt; sleep 5; done”] # 5秒おきに現在日時をファイルに書き込む
volumeMounts: # ボリュームをコンテナ内にマウント
– name: persistent-storage # PodのVolume名を指定
mountPath: /app-data # コンテナ内のマウントパス
volumes: # Podにアタッチするボリュームの定義
– name: persistent-storage # ボリュームの名前
persistentVolumeClaim: # PVCをボリュームとして使用
claimName: my-persistent-volume-claim # 使用するPVCの名前を指定
このDeploymentをクラスタに適用します。
bash
kubectl apply -f app-with-volume.yaml
“`
Podが起動したら、ログを確認してみましょう。
“`bash
kubectl get pods -l app=app-with-volume # ラベルでPodを絞り込み
表示されたPod名のログを確認
kubectl logs
“`
ログに現在日時が5秒おきに書き込まれていることが確認できるはずです。これは、PodがPVC経由でPVに永続的にデータを書き込んでいるためです。もしこのPodが再起動しても、同じPVCにバインドされた新しいPodが起動すれば、以前書き込んだデータは失われずに引き継がれます。
永続ストレージは、データベース、メッセージキュー、ファイルサーバーなど、データを永続化する必要のあるアプリケーションにとって不可欠な要素です。
Rolling Update と Rollback:アプリケーションの更新
アプリケーションの新しいバージョンをデプロイする際、サービスを停止することなく安全に行いたいものです。KubernetesのDeploymentは、この「ローリングアップデート」を標準でサポートしています。
ローリングアップデートでは、新しいバージョンのPodを徐々に起動しながら、古いバージョンのPodを徐々に終了させていきます。これにより、サービスが停止することなく、トラフィックを新しいバージョンのPodにスムーズに切り替えることができます。もし新しいバージョンに問題があった場合でも、すぐに古いバージョンに戻す「ロールバック」も簡単に行えます。
先ほどデプロイしたNginxのバージョンを更新してみましょう。現在のDeploymentは nginx:latest
を使用しています。これを特定のバージョン nginx:1.14.2
に変更してみます。
nginx-deployment.yaml
ファイルを編集し、image
の行を以下のように変更します。
yaml
containers:
- name: nginx
image: nginx:1.14.2 # バージョンを1.14.2に変更
ports:
- containerPort: 80
変更したYAMLファイルを再度 kubectl apply -f
コマンドで適用します。
bash
kubectl apply -f nginx-deployment.yaml
Kubernetesは、YAMLファイルの変更を検知し、ローリングアップデートを開始します。
アップデートの状況は kubectl rollout status
コマンドで確認できます。
bash
kubectl rollout status deployment nginx-deployment
出力例:
Waiting for deployment "nginx-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 1 old replicas are pending termination...
deployment "nginx-deployment" successfully rolled out
ローリングアップデートの進行状況が表示され、完了すると successfully rolled out
と表示されます。
この間、裏側では新しいReplicaSetが作成され、新しいバージョンのPodが起動し、古いReplicaSetのPodが終了するという処理が自動的に行われています。
Podのイメージバージョンを確認してみましょう。
bash
kubectl get pods -o wide # -o wideオプションで詳細情報(ノード名、IPなど)も表示
表示されるPodが全て nginx:1.14.2
イメージを使用していることを確認できます。
さて、もしこの新しいバージョンに問題が見つかったとしましょう。元のバージョン (nginx:latest
) に戻したい場合は、kubectl rollout undo
コマンドを使います。
bash
kubectl rollout undo deployment nginx-deployment
このコマンドを実行すると、Kubernetesは一つ前のリビジョン(バージョン)に戻すためのローリングアップデートを自動的に開始します。
ロールバックの状況も kubectl rollout status
で確認できます。
bash
kubectl rollout status deployment nginx-deployment
ロールアウト履歴を確認したい場合は、kubectl rollout history
コマンドを使います。
bash
kubectl rollout history deployment nginx-deployment
出力例:
REVISION CHANGE-CAUSE
1 <none>
2 <none> # kubectl apply での変更
3 <none> # kubectl rollout undo でのリビジョン戻し
各リビジョンでどのような変更が行われたかを確認できます。特定の過去のリビジョンに戻したい場合は、kubectl rollout undo deployment nginx-deployment --to-revision=<リビジョン番号>
のように指定します。
Deploymentのローリングアップデートとロールバック機能は、ダウンタイムなしでのアプリケーション更新と、問題発生時の迅速な復旧を可能にする、非常に強力な機能です。
Horizontal Pod Autoscaler (HPA):自動スケーリング
ウェブサイトへのアクセスが増加した際など、アプリケーションの負荷に応じてPodの数を自動的に増減させたい場合があります。KubernetesのHorizontal Pod Autoscaler (HPA) は、PodのCPU使用率やメモリ使用率、カスタムメトリクスなどを監視し、設定された閾値に基づいてDeploymentやReplicaSet、StatefulSetなどのPod数を自動的に調整する機能です。
先ほどデプロイしたNginx Deploymentに対してHPAを設定してみましょう。NginxはCPUをあまり消費しないため、この例ではCPU使用率によるスケーリングはあまり効果的ではありませんが、HPAの基本的な使い方を理解できます。
まず、DeploymentがPodのCPU使用率などのメトリクスを報告できるように、KubernetesクラスタにMetrics Serverが導入されている必要があります。MinikubeやDocker Desktopでは、Metrics Serverはデフォルトで有効になっていることが多いです。もしMetrics Serverが動作していない場合は、以下のコマンドで有効化できます。(Minikubeの場合)
bash
minikube addons enable metrics-server
HPAオブジェクトを作成するには、kubectl autoscale
コマンドを使うのが簡単です。Deployment nginx-deployment
のPod数が、CPU使用率が50%を超えた場合に増え、最小1個、最大5個のPodの間で自動調整されるように設定してみましょう。
bash
kubectl autoscale deployment nginx-deployment --cpu-percent=50 --min=1 --max=5
HPAが作成されたことを確認します。
bash
kubectl get hpa
出力例:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-deployment Deployment/nginx-deployment <unknown>/50% 1 5 3 10s
最初はTARGETSが <unknown>/50%
になっているかもしれません。Metrics Serverがメトリクスを収集し、HPAがそれを読み込むまでに少し時間がかかります。しばらく待つか、トラフィックを発生させてCPU使用率を上げると、TARGETSに現在のCPU使用率が表示され、必要に応じてREPLICASの数が変化するはずです。
例えば、Nginx Podに負荷をかけると、CPU使用率が上がり、HPAが検知してPod数を増やし始めます。Pod数が増えると全体のCPU使用率が下がり、再び閾値を下回るとHPAはPod数を減らします(設定されたMINPODSまで)。
HPAは、クラウドネイティブなアプリケーションにおいて、変化する負荷に自動的に対応し、リソースを効率的に利用するために非常に重要なコンポーネントです。
よくあるトラブルシューティング
Kubernetesを使っていると、意図した通りにリソースが動作しないことがあります。ここでは、よくあるトラブルとその調査方法を紹介します。Kubernetesのトラブルシューティングでは、kubectl describe
と kubectl logs
コマンドが非常に役立ちます。
Podが起動しない、Pending状態のまま
Podが Pending
状態から Running
に遷移しない場合、KubernetesがPodを適切なノードにスケジュールできていないか、イメージを取得・起動できないなどの問題が発生している可能性が高いです。
調査方法:
kubectl describe pod <pod名>
を実行:
該当Podの詳細情報を確認します。特に重要なのは出力の一番下にあるEvents
セクションです。FailedScheduling
: スケジューラーがこのPodを実行できるノードを見つけられなかったことを意味します。ノードのリソース(CPU、メモリ)不足、ノードのラベルやテイント(特定のPodしか実行できない/できないようにする設定)との不一致などが原因として考えられます。describeの出力に「message」として理由が表示されます。Failed
: コンテナの起動に失敗したことを意味します。イメージの取得に失敗した (ErrImagePull
,ImagePullBackOff
)、コンテナ起動コマンドに問題がある、必要なConfigMap/Secret/Volumeが見つからないなどが原因として考えられます。
kubectl logs <pod名>
を実行:
コンテナ自体は起動したがすぐに終了してしまう場合(例えば、アプリケーションが起動時エラーで落ちる)、ログを確認することで原因がわかることがあります。kubectl get events
を実行:
クラスタ全体のイベントログを確認できます。特定の時間帯やリソースに関連するイベントを絞り込むことも可能です。kubectl get events --field-selector involvedObject.name=<Pod名>
のように使います。- ノードのリソース状況を確認:
kubectl top nodes
コマンド(Metrics Serverが動作している必要あり)やkubectl describe node <ノード名>
で、ノードのリソース使用状況を確認し、リソース不足が発生していないか確認します。
Serviceにアクセスできない
Serviceを作成したが、期待通りにアプリケーションにアクセスできない場合、様々な原因が考えられます。
調査方法:
kubectl get services
でServiceが存在すること、タイプ、ポートを確認:
Serviceの名前、タイプ(ClusterIP, NodePortなど)、ポートマッピング(PORT(S)
列)が正しいか確認します。kubectl describe service <service名>
で詳細を確認:Selector
: Serviceのセレクターが、アクセスしたいPodのラベルと一致しているか確認します。Serviceは、このセレクターに一致するラベルを持つPodにのみトラフィックを転送します。Endpoints
セクションに、Serviceの対象となっているPodのIPアドレスとポートが表示されているか確認します。ここにPodが表示されていない場合、セレクターがPodと一致していない可能性があります。Events
: Serviceに関連するイベントがないか確認します。
- Podが正常に動作しているか確認:
Serviceの背後にあるPod自体が正常にRunning
状態で、READY
になっているか確認します。Podがクラッシュしたり、起動途中の場合、Service経由ではアクセスできません。kubectl get pods -l <Serviceのセレクター>
で対象Podを確認します。 - ネットワークポリシーを確認:
KubernetesのNetworkPolicyが設定されている場合、Pod間の通信が制限されている可能性があります。 - Serviceタイプに応じたアクセス方法を確認:
ClusterIP
: クラスタ内部からのみアクセス可能です。kubectl exec
などでPodに入り、curl <ServiceのClusterIP>:<Port>
などでアクセスできるか試します。NodePort
: 各ノードの<NodeIP>:<NodePort>
でアクセス可能です。ファイアウォールなどでNodePortがブロックされていないか確認します。ローカル環境では、minikube service <service名>
またはlocalhost:<NodePort>
でアクセスできるか試します。LoadBalancer
: クラウドプロバイダーによってプロビジョニングされた外部IPアドレスでアクセス可能です。EXTERNAL-IPが割り当てられているか確認します(少し時間がかかる場合があります)。クラウドプロバイダー側のファイアウォール設定を確認します。
- Kube-proxyを確認:
各ノードで動作しているkube-proxyがServiceの設定を正しく反映できているか確認します。これは通常、より高度なトラブルシューティングになります。
kubectlコマンドがうまく動作しない
kubectl
コマンド自体がエラーを出す場合、設定や認証情報に問題がある可能性があります。
調査方法:
- クラスタへの接続を確認:
kubectl cluster-info
コマンドでクラスタの情報を取得できるか確認します。
bash
kubectl cluster-info
エラーが出る場合は、kubectl config current-context
で現在のコンテキストが正しいか確認し、必要であればkubectl config use-context <コンテキスト名>
で切り替えます。 - 認証情報(kubeconfig)を確認:
~/.kube/config
ファイルの内容を確認し、接続先のクラスタ情報や認証情報が正しく設定されているか確認します。クラウドプロバイダーのKubernetesサービスを使用している場合は、認証情報の設定(例: AWS IAM Authenticator for Kubernetes)が必要な場合があります。 - API Serverへのアクセスを確認:
ローカル環境の場合は、MinikubeやDocker DesktopのKubernetesコンポーネントが正常に起動しているか確認します。クラウド環境の場合は、ネットワーク設定(ファイアウォールなど)によってクライアントマシンからAPI Serverへのアクセスがブロックされていないか確認します。
これらの基本的な調査ステップを踏むことで、多くのトラブルの原因を特定し、解決に繋げることができます。原因が特定できない場合は、Kubernetesの公式ドキュメントやコミュニティ(Stack Overflow, Kubernetes Slackなど)で情報を探したり、質問したりするのも有効です。
次のステップ
このチュートリアルで、Kubernetesの基本的な概念、ローカル環境でのセットアップ、DeploymentとServiceによるアプリケーションのデプロイ、そして応用的な機能(ConfigMap, Secret, Volume, HPA, Rolling Update)について学びました。しかし、Kubernetesにはまだまだ多くの機能と可能性が秘められています。
今後さらにKubernetesを活用していくために、以下のテーマについて学習を進めることをお勧めします。
- Helm: Kubernetesアプリケーションのパッケージマネージャーです。Chartという形式でアプリケーションリソース一式を定義し、簡単にデプロイ、管理、バージョン管理できるようになります。複雑なアプリケーションもChartを使えば手軽にデプロイできます。
- CI/CDとの連携: Jenkins, GitLab CI, GitHub Actions, CircleCIなどのCI/CDツールとKubernetesを連携させることで、アプリケーションの自動ビルド、テスト、コンテナイメージ作成、Kubernetesクラスタへの自動デプロイといったパイプラインを構築できます。
- 本番環境での利用: クラウドプロバイダー(GKE, EKS, AKS)のマネージドKubernetesサービスを使い、可用性、スケーラビリティ、セキュリティが考慮された本番環境でのKubernetes運用について学びます。ネットワーク(VPC, CNI)、ストレージ(CSI)、セキュリティ(RBAC, PodSecurityPolicyなど)、監視・ロギングなどのプラクティスを習得します。
- 監視・ロギング: Prometheus/Grafanaによるメトリクス監視、Elasticsearch/Fluentd/Kibana (EFK) または Elasticsearch/Logstash/Kibana (ELK) スタックによるコンテナログの収集・分析といった、Kubernetes環境における監視・ロギングの仕組みについて学びます。
- その他のKubernetesリソース:
StatefulSet
: ステートフルなアプリケーション(データベースなど)のデプロイとスケーリングを管理します。DaemonSet
: 各ノードにPodのコピーを1つずつ配置します(ログ収集エージェントなど)。Job
/CronJob
: バッチ処理やスケジュールされたタスクを実行します。Ingress
: クラスタ内のServiceへの外部からのHTTP/HTTPSトラフィックを管理し、URLベースのルーティングなどを実現します。LoadBalancer Serviceよりも柔軟なルーティングが可能です。
- Operatorパターン: 特定のステートフルなアプリケーション(例: データベース)の管理タスク(バックアップ、フェイルオーバー、アップグレードなど)を自動化するために、KubernetesのAPIを拡張するカスタムコントローラー(Operator)について学びます。
- サービスメッシュ: マイクロサービス間の通信を管理・制御するためのレイヤーです。IstioやLinkerdなどが有名です。通信の暗号化、トラフィックルーティング、監視、サーキットブレーカーなどの機能を提供します。
- Kubernetes関連の資格: Cloud Native Computing Foundation (CNCF) が提供する認定資格(Certified Kubernetes Administrator (CKA), Certified Kubernetes Application Developer (CKAD) など)は、Kubernetesの知識とスキルを証明するのに役立ちます。資格取得を目指すことは、体系的な学習の良いモチベーションになります。
まとめ
このチュートリアルでは、「ゼロから始める」方を対象に、Kubernetesの基本的な仕組みと使い方を丁寧に解説しました。
- Kubernetesは、コンテナ化されたアプリケーションのデプロイ、スケーリング、管理を自動化するコンテナオーケストレーションプラットフォームです。
- マスターノード(コントロールプレーン)とワーカーノードで構成されるクラスタで動作します。
- アプリケーションの最小単位はPodであり、通常はDeploymentなどのControllerによって管理されます。
- Serviceは、Pod群への安定したアクセスポイントを提供し、ロードバランシングを行います。
- ConfigMapやSecretで設定情報や機密情報を外部化し、VolumeとPVC/PVでデータの永続化を実現します。
- Deploymentのローリングアップデートとロールバック機能により、安全なアプリケーション更新が可能です。
- HPAは負荷に応じてPod数を自動調整し、効率的なリソース利用を可能にします。
kubectl
コマンドを使ってクラスタを操作し、YAMLファイルでリソースを宣言的に定義します。
Kubernetesは強力で多機能なツールですが、その学習曲線は比較的急峻と言われます。しかし、一度基本を理解すれば、マイクロサービスやクラウドネイティブな開発において、その強力さが手放せなくなるはずです。
この記事が、あなたがKubernetesの世界に足を踏み入れるための一助となれば幸いです。焦らず、一つずつ概念と実践を積み重ねていきましょう。そして、次に学ぶべきステップにも触れましたので、ぜひ継続して学習を進めてください。
Kubernetesの旅は始まったばかりです。頑張ってください!