[Kubernetes]NodePortサービスの動作を確認する


はじめに

今回はServiceの一つであるNodePortの動作を確認したいと思います。
前回はExternalIPの動作を確認しました。動作的にはNodePortとExternalIPはよく似ていますので、違いを中心に確認したいと思います。

NodePortの設定と概要

以下のマニフェストを作成しました。

sampleNodePort.yaml
apiVersion: v1
kind: Service
metadata:
  name: node-port
spec:
  type: NodePort
  ports:
    - name: node-port
      protocol: TCP
      port: 8080
      targetPort: 80
      nodePort: 30001
  selector:
    app: nginx-dep

NodePortは、全てのworkerノードを入口として外部と通信をします。そのため、ExternalIPでは外部と通信するためのノードのIPアドレスをマニフェストに記載しましたが、NodePortにはその項目がありません。
その代わりに通信を受け付けるためのポート(nodePort)を指定します。マニフェストで指定しなかった場合は、デフォルトの「30000-32767」の範囲で自動で割り当てられます。マニフェストで設定する場合にも、この範囲で指定します。

「port」「targetPort」はClusterIPと同様です。NodePortは内部にClusterIPを包含しているようなイメージです。

NodePortの作成

このマニフェストをapplyします。

$ kubectl apply -f sampleNodePort.yaml
service/node-port created
$ kubectl get svc -o wide
NAME          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE    SELECTOR
cluster-ip    ClusterIP   10.101.47.213    <none>        8080/TCP         3d6h   app=nginx-dep
external-ip   ClusterIP   10.98.225.181    10.20.30.20   8080/TCP         47h    app=nginx-dep
kubernetes    ClusterIP   10.96.0.1        <none>        443/TCP          41d    <none>
node-port     NodePort    10.101.179.255   <none>        8080:30001/TCP   13s    app=nginx-dep
$ kubectl describe svc node-port
Name:                     node-port
Namespace:                default
Labels:                   <none>
Annotations:              kubectl.kubernetes.io/last-applied-configuration:
                            {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"node-port","namespace":"default"},"spec":{"ports":[{"name":"node-...
Selector:                 app=nginx-dep
Type:                     NodePort
IP:                       10.101.179.255
Port:                     node-port  8080/TCP
TargetPort:               80/TCP
NodePort:                 node-port  30001/TCP
Endpoints:                192.168.69.246:80,192.168.79.106:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

動作確認

外部との疎通

外部(gateway)から疎通できることを確認します。

[gateway ~]$ for i in 1 2 3 4 5 ;do curl -s http://k8s-worker01:30001 | grep pod; sleep 5;done
pod1
pod1
pod1
pod2
pod2
[gateway ~]$ for i in 1 2 3 4 5 ;do curl -s http://k8s-worker02:30001 | grep pod; sleep 5;done
pod1
pod1
pod2
pod1
pod2

2つのworkerノード(worker01/worker02)のどちらからでも疎通できることと、バランシングされていることが確認できますね。

内部での疎通

NodePortのClusterIPとしての動作も確認してみます。
テスト用のPodとして、以下を使用します。

test_pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
    - name: centos
      image: centos:latest
      command:
      - sh
      - -c
      args:
      - for i in 1 2 3 4 5 ; do curl -s http://node-port.default.svc.cluster.local:8080 ; sleep 5; done ;exit 0

FQDNで指定していますが、ClusterIPと同じ規則です。また、ポート番号は「nodePort」ではなく「port」を指定します。

[Kubernetes]クラスタ内DNSの動作を確認する

このマニフェストをapplyして、30秒ほど待ってlogを確認します。

$ kubectl apply -f test_pod.yaml
pod/test-pod created
$ kubectl logs test-pod | grep pod
pod2
pod1
pod2
pod2
pod1

ClusterIPとしてもちゃんと動作していますね。

まとめ

今回はNodePortの動作を確認しました。
ExternalIPとの違いは、外部との通信の入口となるノードがマニフェストで指定したノードのみ(ExternalIP)か、全ノード(NodePort)かの違いでしょうか。
動作的にはよく似ていますが、ExternalIPはClusterIPそのものを外部と通信できるようにしたもので、NodePortはClusterIPに1つレイヤーを被せた感じですね。その効果のほどまではわからないので、2つの違いを意識しながらこれからも検証したいと思います。