はじめに
KubernetesでNamespaceを作成し、その中に配置したNginxをService経由で利用します。
本記事では、以下を確認します。
- Namespaceによるリソースの整理
- ClusterIP Serviceによるクラスタ内部への公開
- Serviceの接続先の確認
- クラスタ内での名前解決とHTTP通信
- NodePort Serviceの作成
- port-forwardによるローカルからの接続確認
1. 前提条件
前の記事で作成したkindのtrainingクラスタを使用します。
操作前に、接続先を確認してください。
kubectl config current-context
想定するコンテキストは以下です。
kind-training
必要に応じて切り替えます。
kubectl config use-context kind-training
本記事では、対象の名前空間を-n kcnaで明示します。出力例のPod名、IPアドレス、NodePort番号などは、環境によって異なります。
2. Namespaceを作成する
学習用のNamespaceとして、kcnaを作成します。
kubectl create namespace kcna
kubectl get namespaces
kcnaのSTATUSがActiveになっていることを確認します。
Namespaceの役割
Namespaceは、Deployment・Pod・Serviceなどのリソースをクラスタ内で論理的に分ける仕組みです。
たとえば、異なるNamespaceには、同じ名前のDeploymentやServiceを作成できます。
ただし、Namespaceを分けただけでは、Namespace間の通信は遮断されません。通信制限には、NetworkPolicyと、それを実装するネットワーク機能などが必要です。
参考:Kubernetes公式ドキュメント:Namespaces
3. Namespaceにアプリケーションを配置する
kcnaに、NginxのPodを2つ管理するDeploymentを作成します。
kubectl -n kcna create deployment app \
--image=nginx:1.27 --replicas=2
起動完了を待ち、Podとラベルを確認します。
kubectl -n kcna rollout status deployment/app
kubectl -n kcna get pods --show-labels
出力例:
NAME READY STATUS RESTARTS AGE LABELS
app-7c4db8785b-d6h2j 1/1 Running 0 23s app=app,pod-template-hash=7c4db8785b
app-7c4db8785b-j9hwx 1/1 Running 0 23s app=app,pod-template-hash=7c4db8785b
コマンドの解説
| 項目 | 意味 |
|---|---|
-n kcna |
操作対象のNamespaceを指定 |
create deployment app |
appというDeploymentを作成 |
--image=nginx:1.27 |
コンテナイメージとタグを指定 |
--replicas=2 |
希望するPod数を2つに指定 |
--show-labels |
リソースのラベルを表示 |
今回のコマンドで作成されるPodには、app=appラベルが付与されます。このラベルは、次に作成するServiceが対象のPodを選ぶ際にも使用されます。
4. ClusterIP Serviceを作成する
Deployment appを対象とするServiceを作成します。
kubectl -n kcna expose deployment app \
--port=80 --target-port=80 --name=app-svc
コマンドの解説
| 項目 | 意味 |
|---|---|
expose deployment app |
Deploymentの情報をもとにServiceを作成 |
--port=80 |
Serviceが受け付けるポート |
--target-port=80 |
転送先となるPodのポート |
--name=app-svc |
Service名 |
--typeを省略しているため、Serviceの種類は既定のClusterIPになります。
ClusterIPは、クラスタ内部から利用するためのServiceです。Podが置き換わってIPアドレスが変わっても、利用側はServiceの名前やClusterIPを使って接続できます。
Serviceと接続先を確認する
kubectl -n kcna get svc,endpoints app-svc
出力例:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/app-svc ClusterIP 10.96.86.216 <none> 80/TCP 4m10s
NAME ENDPOINTS AGE
endpoints/app-svc 10.244.1.14:80,10.244.2.10:80 4m10s
| 表示 | 意味 |
|---|---|
svc |
Serviceの省略名 |
CLUSTER-IP |
Serviceに割り当てられた仮想IPアドレス |
EXTERNAL-IP: <none> |
外部向けのIPアドレスが割り当てられていない |
ENDPOINTS |
接続先となるPodのIPアドレスとポート |
この例では、Serviceの10.96.86.216:80への通信が、接続先となる2つのPodへ転送されます。
EndpointSliceで確認する
Endpoints APIは、Kubernetes v1.33以降では非推奨です。EndpointSliceでもServiceの接続先を確認できます。
kubectl -n kcna get endpointslices \
-l kubernetes.io/service-name=app-svc
詳細を確認する場合は、以下を実行します。
kubectl -n kcna describe endpointslices \
-l kubernetes.io/service-name=app-svc
5. クラスタ内からService名で接続する
確認用の一時Podを起動し、Serviceの名前解決とHTTP通信を確認します。
kubectl -n kcna run tester --rm -it --restart=Never \
--image=busybox:1.36 -- sh -c \
'nslookup app-svc; wget -qO- http://app-svc | head -n 5'
名前解決の結果に続いて、NginxのHTMLの先頭部分が表示されることを確認します。
HTMLの出力例:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
Pod起動コマンドの解説
| 項目 | 意味 |
|---|---|
run tester |
testerというPodを作成 |
--rm |
接続して実行した処理の終了後、Podを削除 |
-i |
標準入力を開いておく |
-t |
仮想端末を割り当てる |
--restart=Never |
終了したコンテナを再起動しない |
--image=busybox:1.36 |
基本的なコマンドを含む軽量イメージを使用 |
-- |
以降をコンテナで実行するコマンド・引数として扱う |
sh -c '...' |
コンテナ内のシェルで文字列をコマンドとして実行 |
コンテナ内で実行するコマンド
| コマンド・オプション | 意味 |
|---|---|
nslookup app-svc |
Service名の名前解決を確認 |
wget |
HTTPでデータを取得 |
-q |
進行状況などの表示を抑制 |
-O - |
取得内容をファイルではなく標準出力へ出力 |
http://app-svc |
Service名でHTTP接続。ポート省略時は80 |
head -n 5 |
出力の先頭5行を表示 |
NamespaceとService名の関係
確認用PodとServiceが同じkcnaにあるため、短い名前のapp-svcで接続できます。
別のNamespaceから接続する場合は、Namespaceを含めた名前を使用します。
app-svc.kcna
既定のクラスタドメインを使用する環境では、完全な名前は以下です。
app-svc.kcna.svc.cluster.local
参考:Kubernetes公式ドキュメント:DNS for Services and Pods
6. NodePort Serviceを作成する
同じDeploymentを対象として、NodePort Serviceを作成します。
kubectl -n kcna expose deployment app \
--type=NodePort --port=80 --target-port=80 --name=app-np
作成したServiceを確認します。
kubectl -n kcna get svc app-np
出力例:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
app-np NodePort 10.96.100.118 <none> 80:31451/TCP 40s
コマンドと表示内容の解説
| 項目 | 意味 |
|---|---|
--type=NodePort |
ノードのポートでも接続を受け付けるServiceを作成 |
--port=80 |
Serviceのポート |
--target-port=80 |
転送先Podのポート |
80:31451/TCP |
Serviceポートが80、NodePortが31451、プロトコルがTCP |
NodePort番号は未指定のため、クラスタが自動で割り当てます。標準の割り当て範囲は30000~32767です。
この操作は、既存のapp-svcを変更するものではありません。同じPod群を対象とする、2つ目のService app-npを作成しています。
kindでのNodePortへの接続
NodePortは、基本的にノードIP:NodePort番号で利用します。
ただし、kindのノードはコンテナとして動作するため、ノードIPへ直接接続できるかは、ホストOSやネットワーク構成によって異なります。
Linux上のDockerではホストからノードIPへ接続できる場合があります。一方、Docker Desktopなどでは、ホストから利用するためにextraPortMappingsが必要になる場合があります。
したがって、「kindではNodePortに直接接続できない」と一律に判断することはできません。
参考:kind公式ドキュメント:NodePort with Port Mappings
7. port-forwardでローカルから接続する
ここでは、NodePortへの直接接続とは別に、kubectl port-forwardを使ってアプリケーションへ接続します。
この手順はNodePort番号への疎通確認ではありません。 Serviceを指定して対象Podを選び、ローカルのポートからPodへ転送します。ClusterIP Serviceでも同じ方法を利用できます。
7.1 ローカルポートの使用状況を確認する
接続確認にはローカルの8080番ポートを使用します。
ss -ltnp 'sport = :8080'
8080番ポートで待ち受けているソケットがないことを確認してください。使用中の場合は、別のローカルポートを選びます。
| オプション | 意味 |
|---|---|
-l |
待ち受け中のソケットを表示 |
-t |
TCPを対象とする |
-n |
IPアドレス・ポートを数値で表示 |
-p |
使用しているプロセス情報を表示 |
プロセス情報は、実行ユーザーの権限によって表示されない場合があります。
7.2 ターミナル1で転送を開始する
kubectl -n kcna port-forward svc/app-np 8080:80
出力例:
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
8080:80は、ローカルの8080番ポートへの通信を、Serviceの80番ポートに対応する対象Podへ転送する指定です。
このターミナルは、転送を実行したままにします。
7.3 ターミナル2でHTTP接続を確認する
同じホスト上の別ターミナルで、以下を実行します。
curl -sS http://localhost:8080 | head -n 5
出力例:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
| 項目 | 意味 |
|---|---|
curl -s |
進行状況などの表示を抑制 |
curl -S |
-sと併用した場合もエラーを表示 |
head -n 5 |
HTMLの先頭5行を表示 |
接続時には、ターミナル1に以下のようなメッセージが表示されます。
Handling connection for 8080
7.4 転送を終了する
確認が終わったら、ターミナル1でCtrl+Cを押します。
終了するのはport-forwardの処理です。Deployment・Pod・Serviceは残ります。
なお、port-forwardは、kubectlを実行しているホスト上で待ち受けます。SSHでRocky Linuxに接続して作業している場合、この手順のlocalhostはRocky Linux側を指します。
参考:Kubernetes公式ドキュメント:Use Port Forwarding to Access Applications in a Cluster
8. 今回使用した仕組みの違い
| 仕組み | 役割 |
|---|---|
| Namespace | リソースを論理的に整理する |
| ClusterIP Service | クラスタ内部向けの接続先を提供する |
| NodePort Service | ClusterIPに加え、ノードのポートでも接続を受け付ける |
| ServiceのDNS名 | IPアドレスを直接指定せずにServiceへ接続する |
| port-forward | ローカルポートから対象Podへ一時的に接続する |
本記事では、ClusterIP経由のクラスタ内通信と、port-forward経由のローカルからの通信を確認しました。NodePort番号への直接接続は、別途ネットワーク構成に合わせて確認する必要があります。