Kubernetes の Service で ExternalName　Service と　Non-Selector Service　を試す

作業メモ。

[Kubernetes完全ガイド impress top gearシリーズ](https://www.amazon.co.jp/dp/B07HFS7TDT/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)を読みながら手元で確認した時のメモ。

# 環境

```bash
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.3", GitCommit:"2bba0127d85d5a46ab4b778548be28623b32d0b0", GitTreeState:"clean", BuildDate:"2018-05-28T20:03:09Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"11+", GitVersion:"v1.11.5-eks-6bad6d", GitCommit:"6bad6d9c768dc0864dab48a11653aa53b5a47043", GitTreeState:"clean", BuildDate:"2018-12-06T23:13:14Z", GoVersion:"go1.10.3", Compiler:"gc", Platform:"linux/amd64"}
```

Kubernetes 環境としては EKS を利用。

# ExternalName Service を試す

[Type ExternalName](https://kubernetes.io/docs/concepts/services-networking/service/#externalname)

Service 名の名前解決に対して外部ドメイン宛の CNAME を返す。
Service 名と別の名前で名前解決したい、クラスタ内からのエンドポイントを切り替えやすくする場合に使う。
例えば、外部サービス a.example.com へアクセスする場合、このドメインをアプリケーションの設定にファイルに書き込んでしまうと外部サービスが b.example.com に変わった場合、アプリケーションの設定ファイルを変える必要がある。上記のよう場合に ExternalName Service を使って予めクラスタ内からは hoge.service へのリクエストの場合に a.exampl.com の CNAME を返すように設定しておくことで b.example.com に変わった場合でも ExternalName Service の設定変更のみで対応する事ができる。

ExternalName を使う場合、 **type: ExternalName** を指定する。

```externalname.yaml
kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  type: ExternalName
  externalName: my.database.example.com
```

上記では Service 名 **my-service** へのリクエストの際に **my.database.example.com** へ接続するような設定となっている。

試す。


```bash
# ExternalName Service を作成
$kubectl apply -f externalname.yaml
service "my-service" created

# EXTERNAL-IP 列が指定した CNAME のドメイン名になっている
$kubectl get service my-service
NAME         TYPE           CLUSTER-IP   EXTERNAL-IP               PORT(S)   AGE
my-service   ExternalName   <none>       my.database.example.com   <none>    29s

# CNAME が返却される
$ kubectl run testpod --image=centos:6 --restart=Never -i --rm -- dig my-service.default.svc.cluster.local

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.68.rc1.el6_10.1 <<>> my-service.default.svc.cluster.local
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54487
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;my-service.default.svc.cluster.local. IN A

;; ANSWER SECTION:
my-service.default.svc.cluster.local. 5 IN CNAME my.database.example.com.

;; Query time: 112 msec
;; SERVER: 10.100.0.10#53(10.100.0.10)
;; WHEN: Sun Dec 30 03:57:29 2018
;; MSG SIZE  rcvd: 127

```

# Non-Selector Service を試す

[Services without selectors](https://kubernetes.io/docs/concepts/services-networking/service/#services-without-selectors)

Service 名で名前解決を行うと自分で指定したメンバに対してロードバランスを行う。
別 Cluster/Namespace にアクセスする、k8s で管理していないリソースにアクセスするなどに有効。


Non-Selector Service の場合、**typeL ClusterIP** を指定するが、Selector は指定しない。
また、Selector を指定しない代わりに Endpoints リソースを作成して、サービスがどこにリクエストを分散するか定義する

```sample-none-selector.yaml
---
kind: Service
apiVersion: v1
metadata:
  name: sample-none-selector
spec:
  type: ClusterIP
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 80
---
kind: Endpoints
apiVersion: v1
metadata:
  name: sample-none-selector
subsets:
  - addresses:
    - ip: 192.168.1.1
    - ip: 192.168.1.2
    ports:
      - protocol: TCP
        port: 80
```

試す。

```bash
# Service/Endpoints を作成
$kubectl apply -f sample-none-selector.yaml
service "sample-none-selector" created
endpoints "sample-none-selector" created

# Endpoint 一覧を確認.今までの Service のように Endpoints リソースを作成せず、Service と Selector を指定した場合、自動的に Endpoint も作成されていたことが分かる
$kubectl get endpoints
NAME                   ENDPOINTS                                                AGE
guestbook              172.31.12.56:3000,172.31.25.46:3000,172.31.31.209:3000   10d
kubernetes             172.31.14.120:443,172.31.17.167:443                      10d
redis-master           172.31.18.238:6379                                       10d
redis-slave            172.31.16.35:6379,172.31.8.239:6379                      10d
sample-headless        172.31.25.247:80,172.31.28.56:80,172.31.7.49:80          6h
sample-none-selector   192.168.1.1:80,192.168.1.2:80                            30s

# 明示的に指定した IP が設定されている
$kubectl get endpoints sample-none-selector
NAME                   ENDPOINTS                       AGE
sample-none-selector   192.168.1.1:80,192.168.1.2:80   3m

```