Kubernetesの基本的な動作を理解するために、ノードの外部からアクセス可能なWebサービスを作ってみました。
CRIプラグインはContainerdを、CNIプラグインはFlannelを使用しています。
マニフェストはとてもシンプルですが、Kubernetesで最も大事な4つのコンポーネントであるPodとDeploymentとService、ReplicaSet(※)を使っています。
WellKnownポートは使えませんので実用化するには他の仕組みも必要になりますが、Kubernetesの基本的な構成と動きを見るには良いサンプルではないでしょうか。
Kubernetesを理解するための最初の一歩としてご利用いただければ幸いです。
※ReplicaSetは、より上位レベルの概念であるDeploymentに含まれていますので、直接定義は行いません
作成するKubernete環境について
下図は、本記事で作成するWebサービスの構成図です。
起動するPodはtest-podと名前を付けます。
Podのレプリカは3つ動かすようにしました。Pod群にはapp=web-podsというラベルを付けます。
web-podsの制御(レプリカ数の調整やPod内のコンテナのアップデートなど)を行うために、デプロイメント(Deployment)を作成してweb-podsを割り当てます。
デプロイメントにはdeploy-testと名前を付けます。
test-podは8080番ポートを開放しているWebサービスでして、それをクラスタ外からアクセス可能にするために、サービス(Service)を作成してweb-podsおよび8080ポートを設定します。
ノード外に公開するポート(nodePort)は、30000~32767の範囲で自動的に割り当てられます。
もちろん同範囲内で番号を指定することもできます。
サービスに設定したweb-podsの8080ポートはnodePortに紐づきますので、以下のURLでノードの外からPodのサービスにアクセスすることが可能になるわけです。
http://<ノードA or BのIPアドレス>:<nodePort番号>/
上のURLでアクセスしますと、Kubernetesによってキチンとweb-pods内のPodに振り分けて接続してくれます。
ノードの外部からアクセス可能なWebサービスの設定
ではこれから、ノードの外部からアクセス可能なWebサービスを作成していきます。
Webサービスは、Kubernetes公式サイト内の例題などで利用されています以下のイメージを利用します。
k8s.gcr.io/echoserver
作成は、以下の手順で行います。
- デプロイメントのマニフェストファイルを作成する
- サービスのマニフェストファイルを作成する
- マニフェストファイルを使用してkubectlコマンドで各オブジェクトを作成する
デプロイメントのマニフェストファイルを作成する
作成したデプロイメントのマニフェストファイルの内容は、以下の通りです。
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-test
spec:
selector:
matchLabels:
app: web-pods
replicas: 3
template:
metadata:
labels:
app: web-pods
spec:
containers:
- name: test-pod
image: k8s.gcr.io/echoserver:1.4
ファイルの内容を簡単に説明します。
apiVersion: apps/v1
kind: Deployment ←このファイルはデプロイメント用であることを指定
metadata:
name: deploy-test ←デプロイメントの名前を指定
spec: ←デプロイメントに含めるPodを指定するセクション
selector:
matchLabels:
app: web-pods ←デプロイメントに含めるPodのラベルを指定
replicas: 3
template: ←以降は起動するPodのテンプレート(マニフェスト)を設定
metadata:
labels:
app: web-pods ←Podに「app=web-pods」とラベルを付ける
spec:
containers: ←Pod内で実行するコンテナを設定
- name: test-pod
image: k8s.gcr.io/echoserver:1.4
このマニフェストによって、イメージ「k8s.gcr.io/echoserver:1.4」で作成されたコンテナが動くPodが3つ起動されます。
3つのPodには、「app=web-pods」というラベルが付きます。
サービスのマニフェストファイルを作成する
作成したサービスのマニフェストファイルの内容は、以下の通りです。
apiVersion: v1
kind: Service
metadata:
name: service-test-np
spec:
type: NodePort
selector:
app: web-pods
ports:
- port: 8080
nodePort: 30808
ファイルの内容を簡単に説明します。
apiVersion: v1
kind: Service ←このファイルはデプロイメント用であることを指定
metadata:
name: service-test-np ←サービスの名前を指定
spec: ←サービスに含めるPodを指定するセクション
type: NodePort ←nodeportを使用することを指定
selector:
app: web-pods ←サービスに含めるPodのラベルを指定
ports:
- port: 8080 ←サービスとリンク付けるPodのポートを指定
nodePort: 30808 ←公開するnodeportを指定
このマニフェストによって、ラベル「app=web-pods」が付与されたPodの8080番ポートがnodePort30808番で公開されることになります。
マニフェストファイルを使用してkubectlコマンドで各オブジェクトを作成する
※以下のオペレーションはKubernetesの管理ユーザとして設定した一般ユーザで行っています
作成した2つのマニフェストを使用して、kubectlコマンドで各オブジェクトを作成します。
デプロイメントのマニフェストは「test01-deploy.yaml」、サービスのマニフェストは「test01-service-nodeport.yaml」のファイルに保存したとして進めていきます。
まずデプロイメントからです。
$ kubectl apply -f test01-deploy.yaml
正常に終了した場合は以下のように出力されます。
deployment.apps/deploy-test created
次にサービスです。
$ kubectl apply -f test01-service-nodeport.yaml
正常に終了した場合は以下のように出力されます。
service/service-test-np created
以下のコマンドで作成したオブジェクトを確認します。
$ kubectl get all
オブジェクト作成が正常に終了した場合は、以下のように表示されます。
NAME READY STATUS RESTARTS AGE
pod/deploy-test-64988f78fc-d68g7 1/1 Running 0 3m5s
pod/deploy-test-64988f78fc-lx54m 1/1 Running 0 3m5s
pod/deploy-test-64988f78fc-rg5h6 1/1 Running 0 3m5s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 14d
service/service-test-np NodePort 10.96.249.239 <none> 8080:30808/TCP 63s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deploy-test 3/3 3 3 3m5s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deploy-test-64988f78fc 3 3 3 3m5s
PodとServiceとDeployment、Replicasetの4種類が表示されています。
もしかしたら一番最初のPodの「STATUS」部分が「ContainerCreating」と表示されているかもしれませんが、しばらくして再度確認しますと、「Running」になるはずです。
作成した環境の動作確認
Kubernetesのマスターやノード以外のパソコンから、ブラウザで以下のURLにアクセスしてみます。
http://<ノードのIPアドレス:30808>/
以下のような内容が表示されると思います。
CLIENT VALUES:
client_address=10.244.2.0
command=GET
real path=/
query=nil
request_version=1.1
request_uri=http://192.168.1.158:8080/
SERVER VALUES:
server_version=nginx: 1.10.0 - lua: 10001
HEADERS RECEIVED:
accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
accept-encoding=gzip, deflate
accept-language=ja-JP,ja;q=0.9,en-US;q=0.8,en;q=0.7
connection=keep-alive
host=192.168.1.158:30808
upgrade-insecure-requests=1
user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36
BODY:
-no body in request-
内容は環境によって異なると思いますので、上のようなフォーマットで何かが表示されることをご確認ください。
2つのノードのどちらのIPアドレスからアクセスしても同じような内容が表示されます。
まとめ
Podのみ作成した場合、デプロイメントのみ作成した場合でもWebサービスにアクセスすることはできます。
しかしその場合は、クラスタ内部からのみアクセス可能です。
つまり、クラスタIPとして割り当てられたIPアドレスやPodに割り当てられたIPアドレスにマスターやノード、クラスタ内部から接続することで、Webサービスにアクセスできます。
サービスによっては内部からのみアクセス可能にしたいものもあると思いますので、押さえておきたいポイントです。
本記事でご紹介しましたNodePortを利用する方法は、Kubernetesで構築したサービスに外部からアクセスする方法の中の1つでして、他にもいくつかあります。
その中でも一番シンプルな方法をご紹介しました。
お役に立てれば幸いです。
最後までお読みいただきありがとうございました。
コメント