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

#はじめに
今回はServiceの一つであるNodePortの動作を確認したいと思います。
[前回](https://qiita.com/dingtianhongjie/items/8f3c320c4eb5cf25d9de)は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を包含しているようなイメージです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/c1b2644f-ce16-230c-df1d-4ded0360b9d8.png)

#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の動作を確認する](https://qiita.com/dingtianhongjie/items/44fbfd721ba943730129)

このマニフェストを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つの違いを意識しながらこれからも検証したいと思います。