Kubernetes1.10 Cluster内DNSの挙動確認

# はじめに

Kubernetesの公式ページに、多くのチュートリアルが掲載されています。
Kubernetesの勉強の一環で、チュートリアルを消化していきます。
今回は Kubernetesクラスタ内部で使用するDNSを勉強していきます。

https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/



# 通常のServiceの名前解決

Kubernetesクラスタのすべてのサービスは、DNS名が割り当てられています。KubernetesがPodを作成した時に、Pod内部の /etc/resolv.conf に、ネームスペースとデフォルトドメインが含まれた search list が自動的に設定されます。

## 同一ネームスペース内で名前解決(PodtoService)

Service名が foo1 で Namespaceが bar のものを作成して、動作を確認します。

まず、Namsespace bar を作成します

```
[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubectl create namespace bar
namespace "bar" created
```

kubensコマンドを使用して、bar ネームスペースへ切り替えます

```
[root@sugi-kubernetes110-master01 ~(default kubernetes-admin)]# kubens bar
Context "kubernetes-admin@kubernetes" modified.
Active namespace is "bar".
[root@sugi-kubernetes110-master01 ~(bar kubernetes-admin)]# 
```

CentOSのPodを作成するために、以下のマニフェストファイルを生成します。

```
cat <<'EOF' > /root/kube_yaml/dns/centos_pod.yaml
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: centos
spec:
  selector:
    matchLabels:
      app: centos
  replicas: 2
  template:
    metadata:
      labels:
        app: centos
    spec:
      containers:
      - name: centos
        image: centos
        command: [ "sleep", "3600" ]
EOF
```

CentOSのPodを作成します

```
kubectl create -f /root/kube_yaml/dns/centos_pod.yaml
```

Pod一覧を確認します

```
[root@sugi-kubernetes110-master01 ~(bar kubernetes-admin)]# kubectl get pod -o wide 
NAME                     READY     STATUS        RESTARTS   AGE       IP            NODE
centos-749b5dff6-hhhnr   1/1       Running       0          32s       10.244.1.26   sugi-kubernetes110-node01.localdomain
centos-749b5dff6-xwdfw   1/1       Running       0          32s       10.244.2.24   sugi-kubernetes110-node02.localdomain
```

次に Service foo1 を作成します

```
cat <<'EOF' > /root/kube_yaml/dns/foo1_service.yaml
apiVersion: v1
kind: Service
metadata:
  name: foo1
  labels:
    app: foo1
spec:
  ports:
  - protocol: TCP
    name: foo1portname
    port: 6379
    targetPort: 6380
  selector:
    app: foo1
EOF
```

Serviceを作成します

```
kubectl create -f /root/kube_yaml/dns/foo1_service.yaml
```

Service一覧を確認します

```
[root@sugi-kubernetes110-master01 ~(bar kubernetes-admin)]# kubectl get svc -o wide --all-namespaces
NAMESPACE     NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)         AGE       SELECTOR
bar           foo1         ClusterIP   10.109.77.128   <none>        6379/TCP        3m        app=foo1
default       kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP         3d        <none>
kube-system   kube-dns     ClusterIP   10.96.0.10      <none>        53/UDP,53/TCP   3d        k8s-app=kube-dns
```

Serviceの詳細を確認します

```
[root@sugi-kubernetes110-master01 ~(bar kubernetes-admin)]# kubectl describe svc foo1 
Name:              foo1
Namespace:         bar
Labels:            app=foo1
Annotations:       <none>
Selector:          app=foo1
Type:              ClusterIP
IP:                10.109.77.128
Port:              foo1portname  6379/TCP
TargetPort:        6380/TCP
Endpoints:         <none>
Session Affinity:  None
Events:            <none>
```

CentOSのshellへログインします

```
kubectl exec -it centos-749b5dff6-hhhnr bash
```

nslookup及びdigをインストールします

```
yum install bind-utils
```

resolv.confを確認します
kube-dns サービスの ClusterIPを nameserverとして使用しています。
また、searchには、 namespace名.svc.デフォルトドメイン名 という形で定義されています。

```
[root@centos-749b5dff6-hhhnr /]# cat /etc/resolv.conf 
nameserver 10.96.0.10
search bar.svc.cluster.local svc.cluster.local cluster.local localdomain
options ndots:5
```

foo1 を nslookupすると、名前解決が出来ます
barネームスペースのfoo1サービスに紐づけされている ClusterIP が名前解決出来ます

```
[root@centos-749b5dff6-hhhnr /]# nslookup foo1
Server:         10.96.0.10
Address:        10.96.0.10#53

Name:   foo1.bar.svc.cluster.local
Address: 10.109.77.128

```

IPアドレスはわかりましたが、ClusterIPに紐づくポート番号が、上記では確認できません。
KubernetesのDNSでは、サービスのIPアドレスに紐づくポート番号を通知するため、SRV レコードを使用しています。

KubernetesでSRVレコードを使用するために、Serviceの定義を下記のように name と protocol フィールドの指定が必要です

```
略
spec:
  ports:
  - protocol: TCP
    name: foo1portname
    port: 6379
    targetPort: 6380
略
```

これに対してnslookupでsrvレコードを取得するには、以下のようにコマンドから対話形式で実行できます

```
[root@centos-749b5dff6-hhhnr /]# nslookup 
> set type=SRV
> _foo1portname._tcp.foo1
Server:         10.96.0.10
Address:        10.96.0.10#53

_foo1portname._tcp.foo1.bar.svc.cluster.local   service = 10 100 6379 foo1.bar.svc.cluster.local.
> exit
[root@centos-749b5dff6-hhhnr /]# 
```

名前解決の結果を確認すると、「ervice = 10 100 6379 foo1.bar.svc.cluster.local.」となっています。
数字の意味は下記の内容となっています。

- 10 : プライオリティ
- 100 : ウェイト
- 6379 : ポート番号 (Serviceのportで指定した番号)

整理すると、Pod内のアプリケーションが別のPodにアクセスしたい場合、以下の2パターンが考えられます

- ServiceのIPアドレスを知りたい場合 : 「サービス名」を使用してKubernetesのDNSに問い合わせすることで、IPアドレスを正引きすることが出来ます。
- ServiceのIPアドレスと、ポート番号を知りたい場合 : 「サービス名」「ポート名」「プロトコル」を使用してKubernetesのDNSに問い合わせすることで、IPアドレスとポート番号を取得することが出来ます。

## 別のネームスペースから名前解決

quux という名前のネームスペースを作成

```
[root@sugi-kubernetes110-master01 ~(bar kubernetes-admin)]# kubectl create namespace quux
namespace "quux" created
```

ネームスペースの切り替え

```
[root@sugi-kubernetes110-master01 ~(bar kubernetes-admin)]# kubens quux
Context "kubernetes-admin@kubernetes" modified.
Active namespace is "quux".
[root@sugi-kubernetes110-master01 ~(quux kubernetes-admin)]# 
```

CentOSのPodを作成

```
cat <<'EOF' > /root/kube_yaml/dns/centos_pod.yaml
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: centos
spec:
  selector:
    matchLabels:
      app: centos
  replicas: 1
  template:
    metadata:
      labels:
        app: centos
    spec:
      containers:
      - name: centos
        image: centos
        command: [ "sleep", "3600" ]
EOF
```

Deploymentを作成

```
[root@sugi-kubernetes110-master01 ~(quux kubernetes-admin)]# kubectl create -f /root/kube_yaml/dns/centos_pod.yaml
deployment.apps "centos" created
```

確認

```
[root@sugi-kubernetes110-master01 ~(quux kubernetes-admin)]# kubectl get pods -o wide
NAME                     READY     STATUS    RESTARTS   AGE       IP            NODE
centos-749b5dff6-plkc8   1/1       Running   0          24s       10.244.2.25   sugi-kubernetes110-node02.localdomain
```

bashにログイン

```
[root@sugi-kubernetes110-master01 ~(quux kubernetes-admin)]# kubectl exec centos-749b5dff6-plkc8 -it bash
[root@centos-749b5dff6-plkc8 /]# 
```

bind-utilsをインストール

```
yum install -y bind-utils
```

resolv.confを確認します
quux ネームスペースなので、search lust には quux が含まれています

```
[root@centos-749b5dff6-plkc8 /]# cat /etc/resolv.conf 
nameserver 10.96.0.10
search quux.svc.cluster.local svc.cluster.local cluster.local localdomain
options ndots:5
```

barネームスペースの foo1 は、suffixを省略すると名前解決できません

```
[root@centos-749b5dff6-plkc8 /]# nslookup foo1   
Server:         10.96.0.10
Address:        10.96.0.10#53

** server can't find foo1: NXDOMAIN

```

foo1.bar と付与することで、名前解決が出来ます。

```
[root@centos-749b5dff6-plkc8 /]# nslookup foo1.bar
Server:         10.96.0.10
Address:        10.96.0.10#53

Name:   foo1.bar.svc.cluster.local
Address: 10.109.77.128
```

同等に、SRVレコードも取得できます

```
[root@centos-749b5dff6-plkc8 /]# nslookup 
> set type=SRV
> _foo1portname._tcp.foo1.bar
Server:         10.96.0.10
Address:        10.96.0.10#53

_foo1portname._tcp.foo1.bar.svc.cluster.local   service = 10 100 6379 foo1.bar.svc.cluster.local.
```

異なるネームスペースのServiceとアクセスが出来るかは別の設定に依存します。
ネットワークプラグインによって、NetworkPolicyで分離されていれば通信ができません。
なお、私が検証している環境は、Flannelを使用しています。これは現在NetworkPolixyは実装されていないので、別のネームスペース間でも接続が出来ます。



# Headlessサービスの名前解決

Headlessサービスとは、Serviceを利用したLoadbalanceが不要な時に使用します。Serviceを作成するときに、spec.clusterIP を none にすると作成することが出来ます。
Headlessサービスを使用すると、KuberenetesのLoadbalanceサービスを使用せずに、独自に実装した方法でサービスディスカバリーを行う事が出来ます。

Headlessサービスでは、kube-proxyは何も介さず、ロードバランスもプロキシも稼働しません。
このときDNSがどのように割り当てられるかは、ServiceのSelector定義に依存します。


## selectorsあり

Serviceのselectorを有りにすると、Podからサービスの名前解決を行った際に、Serviceに属している全てのPodのIPアドレスを名前解決する方式となります。
通常のサービスは、上の項目でも検証した通り、Serviceに紐づくClusterIPが名前解決されます。
Headlessは特殊な方式なので、通常は使用しないと思います。

どういう時に使用することが有るか考えると以下のパターンが考えられるでしょうか。

- ClusterIPサービスのロードバランスに偏りがあり、クライアント側で任意にロードバランスしたい
- Kubernetesのポリシーには違反するが、複数あるPodのうち1個のみ使用してアクセスしたい



selectorsありでHeadlessサービスを作成すると、endpoints controllerは、Endpointオブジェクトを作成し、DNSレコードを変更します。

Headless selectorありの動作を確認するために、以下のDeploymentとServiceを作成します。

```
cat <<'EOF' > /root/kube_yaml/dns/nginx-deployment.yaml
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        ports:
        - containerPort: 80
EOF
```

Deploymentを作成します

```
kubectl apply -f /root/kube_yaml/dns/nginx-deployment.yaml
```

Serviceを作成するために、以下にマニフェストファイルを作成します

```
cat <<'EOF' > /root/kube_yaml/dns/nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    app: nginx
spec:
  ports:
  - protocol: TCP
    name: nginx-service-portname
    port: 15315
    targetPort: 80
  clusterIP: None
  selector:
    app: nginx
EOF
```

Serviceを作成します

```
kubectl apply -f /root/kube_yaml/dns/nginx-service.yaml
```

一覧を確認します

```
[root@sugi-kubernetes110-master01 dns(bar kubernetes-admin)]# kubectl get svc -o wide
NAME            TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)     AGE       SELECTOR
nginx-service   ClusterIP   None         <none>        15315/TCP   7s        app=nginx
```

詳細を確認します

```
[root@sugi-kubernetes110-master01 dns(bar kubernetes-admin)]# kubectl describe svc nginx-service 
Name:              nginx-service
Namespace:         bar
Labels:            app=nginx
Annotations:       kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"nginx"},"name":"nginx-service","namespace":"bar"},"spec":{"clusterIP"...
Selector:          app=nginx
Type:              ClusterIP
IP:                None
Port:              nginx-service-portname  15315/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.27:80,10.244.2.26:80
Session Affinity:  None
Events:            <none>
```

以下のendpoint一覧を確認します
Serviceと連携して、自動的に作成されています

```
[root@sugi-kubernetes110-master01 dns(bar kubernetes-admin)]# kubectl get endpoints 
NAME            ENDPOINTS                       AGE
nginx-service   10.244.1.27:80,10.244.2.26:80   1m
```

endpointで使用されているIPアドレスは、Podに自動付与されているIPアドレスとなっている

```
[root@sugi-kubernetes110-master01 dns(bar kubernetes-admin)]# kubectl get pods -o wide
NAME                     READY     STATUS    RESTARTS   AGE       IP            NODE
nginx-5c9845d857-5tvlt   1/1       Running   0          9m        10.244.1.27   sugi-kubernetes110-node01.localdomain
nginx-5c9845d857-vlgl2   1/1       Running   0          9m        10.244.2.26   sugi-kubernetes110-node02.localdomain
```

nslookupを実行するために、CentOSのPodを作成し、bashにログインします

```
kubectl create -f /root/kube_yaml/dns/centos_pod.yaml
kubectl exec centos-749b5dff6-bpcrb -it bash
```

nslookupをインストールします

```
yum install -y bind-utils
```

nslookupでHeadlessServiceの名前解決を実施すると全てのPodのIPアドレスがreturnされていることを確認できます。

```
[root@centos-749b5dff6-bpcrb /]# nslookup nginx-service
Server:         10.96.0.10
Address:        10.96.0.10#53

Name:   nginx-service.bar.svc.cluster.local
Address: 10.244.1.27
Name:   nginx-service.bar.svc.cluster.local
Address: 10.244.2.26
```



## selectorsなし (ServiceType : ExternalNameの別の名称)

selectorなしでHeadlessサービスを作成すると、Endpointオブジェクトは作成されません。DNSのCNAMEとして、ServiceのExternalNameが登録されます。

動作を確認するため以下のマニフェストファイルを作成します

```
cat <<'EOF' > /root/kube_yaml/dns/nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-headless-noselector
  labels:
    app: nginx
spec:
  type: ExternalName
  externalName: 10.132.253.39
EOF
```

Serviceの作成

```
kubectl apply -f /root/kube_yaml/dns/nginx-service.yaml
```

Serviceの一覧確認

```
[root@sugi-kubernetes110-master01 ~(bar kubernetes-admin)]# kubectl get svc
NAME                        TYPE           CLUSTER-IP   EXTERNAL-IP     PORT(S)     AGE
nginx-headless-noselector   ExternalName   <none>       10.132.253.39   <none>      5s
nginx-service               ClusterIP      None         <none>          15315/TCP   53m
```

詳細を確認

```
[root@sugi-kubernetes110-master01 ~(bar kubernetes-admin)]# kubectl describe svc nginx-headless-noselector 
Name:              nginx-headless-noselector
Namespace:         bar
Labels:            app=nginx
Annotations:       kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"nginx"},"name":"nginx-headless-noselector","namespace":"bar"},"spec":...
Selector:          <none>
Type:              ExternalName
IP:                
External Name:     10.132.253.39
Session Affinity:  None
Events:            <none>
```

podからserviceの名前解決を実施すると、上記のExternalIPの名前解決が出来ます
IPアドレスを指定すると、Aレコードが返ってきます

```
[root@centos-749b5dff6-bpcrb /]# nslookup nginx-headless-noselector 
Server:         10.96.0.10
Address:        10.96.0.10#53

Name:   nginx-headless-noselector.bar.svc.cluster.local
Address: 10.132.253.39
```

別のパターン
IPアドレスの代わりに、hostnameを指定

```
cat <<'EOF' > /root/kube_yaml/dns/nginx-service-name.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-headless-noselector
  labels:
    app: nginx
spec:
  type: ExternalName
  externalName: www.google.co.jp
EOF
```

apply

```
kubectl apply -f /root/kube_yaml/dns/nginx-service-name.yaml
```

nslookupすると、CNAMEレコードとして 「www.google.co.jp」が返ってきて、それを名前解決しています

```
[root@centos-749b5dff6-bpcrb /]# nslookup nginx-headless-noselector 
Server:         10.96.0.10
Address:        10.96.0.10#53

Non-authoritative answer:
nginx-headless-noselector.bar.svc.cluster.local canonical name = www.google.co.jp.
Name:   www.google.co.jp
Address: 172.217.27.67

```

digの結果

```
[root@centos-749b5dff6-bpcrb /]# dig nginx-headless-noselector.bar.svc.cluster.local

; <<>> DiG 9.9.4-RedHat-9.9.4-51.el7_4.2 <<>> nginx-headless-noselector.bar.svc.cluster.local
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53443
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;nginx-headless-noselector.bar.svc.cluster.local. IN A

;; ANSWER SECTION:
nginx-headless-noselector.bar.svc.cluster.local. 20 IN CNAME www.google.co.jp.
www.google.co.jp.       20      IN      A       172.217.27.67

;; Query time: 1 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Wed May 02 15:01:32 UTC 2018
;; MSG SIZE  rcvd: 122

```



# Podの名前解決

## Aレコードの自動登録

Podは次の形式でDNSのAレコードが自動的に構成されています

```
pod-ip-address.my-namespace.pod.cluster.local
```

例えば、barネームスペースに以下の3種類のPodが存在する場合、

```
[root@sugi-kubernetes110-master01 ~(bar kubernetes-admin)]# kubectl get pods -o wide
NAME                     READY     STATUS    RESTARTS   AGE       IP            NODE
centos-749b5dff6-bpcrb   1/1       Running   0          57m       10.244.1.28   sugi-kubernetes110-node01.localdomain
nginx-5c9845d857-5tvlt   1/1       Running   0          1h        10.244.1.27   sugi-kubernetes110-node01.localdomain
nginx-5c9845d857-vlgl2   1/1       Running   0          1h        10.244.2.26   sugi-kubernetes110-node02.localdomain
```

「10-244-1-28.bar.pod.cluster.local.」で名前解決ができます
(search list に含まれていないsuffixなので注意)

```
[root@centos-749b5dff6-bpcrb /]# nslookup 10-244-1-28.bar.pod.cluster.local.
Server:         10.96.0.10
Address:        10.96.0.10#53

Name:   10-244-1-28.bar.pod.cluster.local
Address: 10.244.1.28
```



## PodのDNSポリシー

PodのDNSポリシーは、Pod単位で設定を行うことが出来ます。現在、Kubernetesでは以下のポリシーが選択可能です。
マニフェストファイル内で`dnsPolicy`フィールドで指定を行うことが出来ます。

- default (※) : kube-dnsで解決出来ない名前解決の場合、Podが稼働しているNodeに設定している、DNSサーバ(upstream nameserverと表現されている)を使用して名前解決を行います。次の「ClusterFirst」では、stub-domainやupstreamDNSサーバを個別に指定することが出来ますが、defaultポリシーでは設定をすることが出来ません。


- ClusterFirst : kube-dnsで解決出来ない名前解決の場合、Podが稼働しているNodeに設定している、DNSサーバ(upstream nameserverと表現されている)を使用して名前解決を行います。Cluster管理者は、stub-domainやupstreamDNSサーバを個別に指定することができます。https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/#impacts-on-pods
- ClusterFirstWithHostNet : hostNetworkで稼働しているPodは、「ClusterFirstWithHostNet」をDNSポリシーとして指定する必要があります。
- None : Kubernetes version 1.9 で追加された機能です。KubernetesのDNS自動設定を無視することが出来ます dnsConfig による設定のみ行う事が出来ます。https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pods-dns-config

※ defaultは、デフォルトDNSポリシーではありません。DNSポリシーを指定しない場合、 "ClusterFirst"が選択されます。



次のマニフェストファイルは、DNSポリシーを"ClusterFirstWithHostNet"と指定したものです。spec.hostNetworkをtrueにしています。

```
cat <<'EOF' > /root/kube_yaml/dns/busybox-hostnw.yaml
apiVersion: v1
kind: Pod
metadata:
  name: busybox
spec:
  containers:
  - image: busybox
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
    name: busybox
  restartPolicy: Always
  hostNetwork: true
  dnsPolicy: ClusterFirstWithHostNet
EOF
```

作成

```
kubectl apply -f /root/kube_yaml/dns/busybox-hostnw.yaml
```

確認します。busyboxのIPが、nodeのIPとなっています

```
[root@sugi-kubernetes110-master01 dns(bar kubernetes-admin)]# kubectl get pods -o wide
NAME                     READY     STATUS    RESTARTS   AGE       IP                NODE
busybox                  1/1       Running   0          10s       192.168.120.223   sugi-kubernetes110-node01.localdomain
centos-749b5dff6-bpcrb   1/1       Running   2          2h        10.244.1.28       sugi-kubernetes110-node01.localdomain
nginx-5c9845d857-5tvlt   1/1       Running   0          2h        10.244.1.27       sugi-kubernetes110-node01.localdomain
nginx-5c9845d857-vlgl2   1/1       Running   0          2h        10.244.2.26       sugi-kubernetes110-node02.localdomain
```

shを起動してログインします

```
kubectl exec busybox -it sh
```

コンテナ内のNWは、host側のNWが見えています

```
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq qlen 1000
    link/ether 00:50:56:98:70:ab brd ff:ff:ff:ff:ff:ff
    inet 192.168.120.223/24 brd 192.168.120.255 scope global ens192
       valid_lft forever preferred_lft forever
    inet6 fe80::f59f:2d01:78d0:bcb9/64 scope link 
       valid_lft forever preferred_lft forever
    inet6 fe80::98a0:413d:6b71:8fbd/64 scope link tentative flags 08 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue 
    link/ether 02:42:3e:8b:64:af brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever
4: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue 
    link/ether 62:c4:05:0d:c1:d3 brd ff:ff:ff:ff:ff:ff
    inet 10.244.1.0/32 scope global flannel.1
       valid_lft forever preferred_lft forever
    inet6 fe80::60c4:5ff:fe0d:c1d3/64 scope link 
       valid_lft forever preferred_lft forever
5: cni0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue qlen 1000
    link/ether 0a:58:0a:f4:01:01 brd ff:ff:ff:ff:ff:ff
    inet 10.244.1.1/24 scope global cni0
       valid_lft forever preferred_lft forever
    inet6 fe80::9ca5:24ff:fe55:9672/64 scope link 
       valid_lft forever preferred_lft forever
31: vetha1c264dc@docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master cni0 
    link/ether 1e:a2:df:06:57:ba brd ff:ff:ff:ff:ff:ff
    inet6 fe80::1ca2:dfff:fe06:57ba/64 scope link 
       valid_lft forever preferred_lft forever
32: veth224aaf36@docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master cni0 
    link/ether a2:17:d4:7c:55:ea brd ff:ff:ff:ff:ff:ff
    inet6 fe80::a017:d4ff:fe7c:55ea/64 scope link 
       valid_lft forever preferred_lft forever
```

resolv.confの確認

```
/ # cat /etc/resolv.conf 
nameserver 10.96.0.10
search bar.svc.cluster.local svc.cluster.local cluster.local localdomain
options ndots:5
```



nslookupも通常のPodと同様に見えています

```
/ # nslookup foo1
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      foo1
Address 1: 10.107.131.250 foo1.bar.svc.cluster.local
```



## PodのDNS Config

Kubernetes v1.9 から、PodのDNS設定をコントロールすることが出来ます。Kubernetes 1.10 からは default で機能が有効になっていますが、1.9 では、 kubelete の 引数に `--feature-gates=CustomPodDNS=true,...`を与えてプロセスを起動する必要があります。

Deploymentのマニフェストファイルを作成します

```
cat <<'EOF' > /root/kube_yaml/dns/dnsconfig_centos_pod.yaml
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: dnsconfig-centos
spec:
  selector:
    matchLabels:
      app: dnsconfig-centos
  replicas: 1
  template:
    metadata:
      labels:
        app: dnsconfig-centos
    spec:
      containers:
      - name: dnsconfig-centos
        image: centos
        command: [ "sleep", "3600" ]
      dnsPolicy: "None"
      dnsConfig:
        nameservers:
          - 1.2.3.4
        searches:
          - ns1.svc.cluster.local
          - my.dns.search.suffix
        options:
          - name: ndots
            value: "2"
          - name: edns0
EOF
```

Deploymentを作成

```
kubectl apply -f /root/kube_yaml/dns/dnsconfig_centos_pod.yaml
```

bashを起動

```
kubectl exec dnsconfig-centos-d9c4f576f-k9kj8 -it bash
```

以下のようにPodのresolv.configが設定されています
もちろん、下記の設定ではクラスタ内の名前解決もできませんし、外部の名前解決も出来ません。

```
[root@dnsconfig-centos-d9c4f576f-k9kj8 /]# cat /etc/resolv.conf 
nameserver 1.2.3.4
search ns1.svc.cluster.local my.dns.search.suffix
options ndots:2 edns0
```





# 参考URL

Kubernetes "サービス"の概要についての自習ノート
https://qiita.com/MahoTakara/items/d18d8f9b36416353066c

Kubernetes Blog
https://kubernetes.io/blog/2017/04/configuring-private-dns-zones-upstream-nameservers-kubernetes

stub-domain, upstreamDNS
https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/#impacts-on-pods

DNS Config
https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pods-dns-config