はじめに
Pod は一時的な存在です。Deployment はロールアウト、再起動、スケーリングの過程で Pod を置き換えるため、クライアントは個々の Pod の IP アドレスに直接接続すべきではありません。Service を使用すると、クライアントに対して安定した名前と仮想 IP を提供でき、ラベルを使用してトラフィックを現在稼働中の適切な Pod へルーティングできます。
この実験では、小規模な Web Deployment を作成し、ClusterIP Service で公開します。また、Service がどのようにバックエンドの Pod を選択しているかを確認し、クライアント Pod から Service をテストし、最後に Deployment をスケーリングして Service のエンドポイントが更新される様子を観察します。
Web Deployment の作成
このステップでは、名前空間を準備し、後で Service によって公開される Deployment を作成します。
/home/labex/project から開始します。
mkdir -p /home/labex/project
cd /home/labex/project
Kubernetes API サーバーに接続できるか確認します。VM が起動した直後でノードの準備ができていない場合は、数秒待ってから再度コマンドを実行してください。
kubectl get nodes --request-timeout=5s
期待される出力例:
NAME STATUS ROLES AGE VERSION
labex-v135 Ready control-plane ... v1.35...
クラスターのネットワーク Pod が Ready になるまで待ちます。この実験では Service を介して Pod 間でトラフィックを送信するため、アクセスをテストする前にクラスターのネットワークが正常である必要があります。
kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s
期待される出力:
pod/calico-node-... condition met
ckad-prep-service という名前空間を作成し、現在の名前空間として設定します。
kubectl create namespace ckad-prep-service
kubectl config set-context --current --namespace=ckad-prep-service
1 つの NGINX Pod を持つ web-front という名前の Deployment を作成します。--port=80 フラグは Pod テンプレートにコンテナポートを記録しますが、これ自体で Service が作成されるわけではありません。
kubectl create deployment web-front --image=nginx:1.25 --port=80
Deployment が利用可能になるまで待ち、Pod のラベルを確認します。Service がバックエンドの Pod を見つけるために使用するため、app=web-front というラベルが重要です。
kubectl rollout status deployment/web-front --timeout=120s
kubectl get pods -l app=web-front --show-labels
期待される出力例:
deployment "web-front" successfully rolled out
NAME READY STATUS RESTARTS AGE LABELS
web-front-... 1/1 Running 0 ... app=web-front,...
ClusterIP Service による Deployment の公開
このステップでは、Deployment 用の Service を作成し、Service と Pod を接続するフィールドを確認します。
kubectl expose deployment を使用して ClusterIP Service を作成します。Service のポートは 80 で、--target-port=80 は一致する Pod のポート 80 にトラフィックを転送するように指示します。
kubectl expose deployment web-front --name=web-front --port=80 --target-port=80
期待される出力:
service/web-front exposed
Service を確認します。
kubectl get service web-front
期待される出力例:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
web-front ClusterIP ... <none> 80/TCP ...
次に、Service のセレクターとポートマッピングを確認します。セレクターは Service が Pod を見つけるための仕組みであり、ポートマッピングはクライアントのトラフィックがコンテナに到達するための仕組みです。
kubectl get service web-front -o jsonpath='{.spec.selector.app}{" "}{.spec.ports[0].port}{":"}{.spec.ports[0].targetPort}{"\n"}'
期待される出力:
web-front 80:80
Kubernetes は選択されたバックエンドのアドレスを EndpointSlice に保存します。この Service 用に作成された EndpointSlice をリスト表示します。
kubectl get endpointslice -l kubernetes.io/service-name=web-front
期待される出力例:
NAME ADDRESSTYPE PORTS ENDPOINTS AGE
web-front-... IPv4 80 ... ...
クラスター内部からの Service テスト
このステップでは、一時的なクライアント Pod を作成し、Service に対して HTTP リクエストを送信します。ClusterIP Service はクラスター内部からのアクセスを想定しているため、別の Pod からテストするのが最も直接的な検証方法です。
実行し続けるクライアント Pod を作成します。
kubectl run service-client --image=busybox:1.36 --restart=Never --command -- sleep 3600
クライアント Pod が Ready になるまで待ちます。
kubectl wait --for=condition=Ready pod/service-client --timeout=120s
期待される出力:
pod/service-client condition met
クライアント Pod 内で wget を使用して http://web-front にリクエストを送信します。名前 web-front は、名前空間内の Service に解決されます。
kubectl exec service-client -- wget -qO- http://web-front | head -n 5
期待される出力例(デフォルトの NGINX ページの冒頭):
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
これにより、クライアントが安定した Service 名に到達し、Service がトラフィックを現在のバックエンド Pod に転送したことが証明されました。
バックエンドのスケーリングとエンドポイントの再確認
このステップでは、Deployment をスケーリングし、バックエンドのエンドポイントが変更されても Service が同じ安定した入り口を維持することを確認します。
Deployment を 2 つのレプリカにスケーリングします。
kubectl scale deployment web-front --replicas=2
kubectl rollout status deployment/web-front --timeout=120s
期待される出力例:
deployment.apps/web-front scaled
deployment "web-front" successfully rolled out
Pod をリスト表示します。同じ app=web-front ラベルを持つ 2 つの実行中のバックエンド Pod が表示されるはずです。
kubectl get pods -l app=web-front
期待される出力例:
NAME READY STATUS RESTARTS AGE
web-front-... 1/1 Running 0 ...
web-front-... 1/1 Running 0 ...
Service の背後にあるエンドポイントの数をカウントします。以下のコマンドは、各エンドポイントアドレスに対して 1 行を出力し、その行数をカウントします。
kubectl get endpointslice -l kubernetes.io/service-name=web-front -o jsonpath='{range .items[*].endpoints[*]}{.addresses[0]}{"\n"}{end}' | wc -l
期待される出力:
2
同じクライアント Pod から再度 Service にリクエストを送信します。
kubectl exec service-client -- wget -qO- http://web-front | grep '<title>Welcome to nginx'
期待される出力:
<title>Welcome to nginx!</title>
まとめ
Deployment を ClusterIP Service で公開し、クラスター内部からの完全なアクセスパスを検証しました。バックエンドの Deployment を作成し、セレクターとポートマッピングを持つ Service を作成し、Service 用に生成された EndpointSlice を確認し、クライアント Pod からのアクセスをテストしました。さらに、Deployment をスケーリングして、Service が更新されたバックエンドセットに対してルーティングを継続することを確認しました。


