[Kubernetes]ExternalIPの動作を確認する

#はじめに
[「ClusterIPの動作を確認する」](https://qiita.com/dingtianhongjie/items/82d1c56e9712e19aecb0)では、ClusterIPはクラスタ内でのみ通信するServiceだとしました。しかし、ClusterIPにはExteralIPを設定することができ、これを設定することで、クラスタ外のノードと通信することができます。
今回はこのExternalIPの動作を確認したいと思います。

#設定
ExternalIPはマニフェストのtypeに設定するのではありません。typeはClusterIPです。ややこしいですね。
作成したマニフェストは以下になります。ClusterIPのマニフェストに「spec.externalIPs」を追加します。

```sampleExternalIP.yaml
apiVersion: v1
kind: Service
metadata:
  name: external-ip
spec:
  type: ClusterIP
  externalIPs:
    - 10.20.30.20
  ports:
    - name: cluster-port
      protocol: TCP
      port: 8080
      targetPort: 80
  selector:
    app: nginx-dep
```

設定するIPアドレスは、クラスタを構成するノードのIPアドレスです。全てを指定する必要はありません。ここでは、worker01のみを指定しています。

```
$ kubectl get node -o wide
NAME           STATUS   ROLES    AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION                CONTAINER-RUNTIME
k8s-master     Ready    master   39d   v1.17.3   10.20.30.10   <none>        CentOS Linux 7 (Core)   3.10.0-1062.12.1.el7.x86_64   docker://19.3.6
k8s-worker01   Ready    <none>   39d   v1.17.3   10.20.30.20   <none>        CentOS Linux 7 (Core)   3.10.0-1062.12.1.el7.x86_64   docker://19.3.6
k8s-worker02   Ready    <none>   39d   v1.17.3   10.20.30.30   <none>        CentOS Linux 7 (Core)   3.10.0-1062.12.1.el7.x86_64   docker://19.3.6
```

##ExternalIPの作成
このマニフェストをapplyして、作成したServiceを確認します。

```
$ kubectl apply -f sampleExternalIP.yaml
service/external-ip created
$ kubectl get svc
NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
cluster-ip    ClusterIP   10.101.47.213   <none>        8080/TCP   31h
external-ip   ClusterIP   10.98.225.181   10.20.30.20   8080/TCP   7s
kubernetes    ClusterIP   10.96.0.1       <none>        443/TCP    39d
$ kubectl describe svc external-ip
Name:              external-ip
Namespace:         default
Labels:            <none>
Annotations:       kubectl.kubernetes.io/last-applied-configuration:
                     {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"external-ip","namespace":"default"},"spec":{"externalIPs":["10.20...
Selector:          app=nginx-dep
Type:              ClusterIP
IP:                10.98.225.181
External IPs:      10.20.30.20
Port:              cluster-port  8080/TCP
TargetPort:        80/TCP
Endpoints:         192.168.69.236:80,192.168.79.92:80
Session Affinity:  None
Events:            <none>
```

#動作確認
クラスタには[以前](https://qiita.com/dingtianhongjie/items/82d1c56e9712e19aecb0)作成したPod（Deployment）があります。このPodに対して、外部からの疎通を確認します。

```
$ kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP               NODE           NOMINATED NODE   READINESS GATES
nginx-6c4975c9f5-v5ljf   1/1     Running   1          31h   192.168.69.236   k8s-worker02   <none>           <none>
nginx-6c4975c9f5-x4bwq   1/1     Running   1          31h   192.168.79.92    k8s-worker01   <none>           <none>
```
検証で使用しているクラスタは、PC上のVertualBOXで構築しています。クラスタを構成するVMの他に、GatewayとなるVMもありますので、ここからHTTPのリクエストを送信して疎通を確認します。
検証環境は[こちら](https://qiita.com/dingtianhongjie/items/39c7e8e703a6f0722385)を参照してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/b12962af-8d47-a79f-f5cc-322fc9f88e56.png)


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

疎通の確認と、バランシングされていることがわかりますね。
また、ExternalIPを設定したノードはworker01（10.20.30.20）のみですが、worker02にデプロイされているPod1にもバランシングされていることがわかります。

ExternalIPに設定して”いない”worker02（10.20.30.30）からは疎通できないことも確認しておきます。

```
[gateway ~]$ for i in 1 2 3 4 5 ;do curl -s http://10.20.30.30:8080 | grep pod; sleep 5; done
[gateway ~]$
```

Errorが出るわけではないのでわかりづらいですが、何も応答がなくプロンプトが返ってきます。

#まとめ
今回はExternalIPの動作を確認しました。これだけだとNodePortと同じように思えるのですが、NodePortの動作を確認するときに違いを確かめてみたいと思います。