DNSについて (続き)

kubernetesのdocumentのDNS for Services and Podsでは、次のような記述がある。

Pod’s hostname and subdomain fields

Currently when a pod is created, its hostname is the Pod’s metadata.name value.

The Pod spec has an optional hostname field, which can be used to specify the Pod’s hostname. When specified, it takes precedence over the Pod’s name to be the hostname of the pod. For example, given a Pod with hostname set to “my-host”, the Pod will have its hostname set to “my-host”.

The Pod spec also has an optional subdomain field which can be used to specify its subdomain. For example, a Pod with hostname set to “foo”, and subdomain set to “bar”, in namespace “my-namespace”, will have the fully qualified domain name (FQDN) “foo.bar.my-namespace.svc.cluster.local”.

一例として、headlessサービスでhostname、subdomainの両方を設定しているものが書いてあるけど、普通のサービスだったらとか、hostname指定しなかった場合とかの挙動が分からなかったので、試してみた。

先に結論から言うと、headlessサービスでhostonameとsubdomainの両方の設定をしてある必要がありました。

以下、メモ。

普通のサービス + hostname指定 + subdomain指定

マニフェストは下記。

$ cat normal_hostname_subdomain.yaml
apiVersion: v1                                                                  
kind: Service                                                                   
metadata:                                                                       
  name: my-service                                                              
spec:                                                                           
  selector:                                                                     
    name: busybox                                                               
  ports:                                                                        
  - name: foo                                                                   
    port: 1234                                                                  
    targetPort: 5678                                                            
---                                                                             
apiVersion: v1                                                                  
kind: Pod                                                                       
metadata:                                                                       
  name: busybox1                                                                
  labels:                                                                       
    name: busybox                                                               
spec:                                                                           
  hostname: busybox-1                                                           
  subdomain: my-service                                                         
  containers:                                                                   
  - name: busybox                                                               
    image: busybox                                                              
    command:                                                                    
    - sleep                                                                     
    - "3600"                                                                    
---                                                                             
apiVersion: v1                                                                  
kind: Pod                                                                       
metadata:                                                                       
  name: busybox2                                                                
  labels:                                                                       
    name: busybox                                                               
spec:                                                                           
  hostname: busybox-2                                                           
  subdomain: my-service                                                         
  containers:                                                                   
  - name: busybox                                                               
    image: busybox                                                              
    command:                                                                    
    - sleep                                                                     
    - "3600" 

デプロイ。

$ kubectl apply -f normal_hostname_subdomain.yaml
service "my-service" created
pod "busybox1" created
pod "busybox2" created

$ kubectl get pod
NAME       READY     STATUS    RESTARTS   AGE
busybox1   1/1       Running   0          54s
busybox2   1/1       Running   0          54s

$ kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP    12d
my-service   ClusterIP   10.101.236.136   <none>        1234/TCP   1m

同じクラスタ内の別Podで名前解決してみる。

$ kubectl run -it --rm --restart=Never --image=busybox nslookup -- /bin/sh
If you don't see a command prompt, try pressing enter.
/ # nslookup my-service
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      my-service
Address 1: 10.101.236.136 my-service.default.svc.cluster.local
/ # nslookup busybox1.my-service
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

nslookup: can't resolve 'busybox1.my-service'
/ # nslookup busybox-1.my-service
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

nslookup: can't resolve 'busybox-1.my-service'

ということで、名前解決はできません。

headlessサービス + hostname指定なし + subdomain指定

利用したマニフェスト

$ cat headless_no_subdomain.yaml
File Edit Options Buffers Tools Text Help                                       
apiVersion: v1                                                                  
kind: Service                                                                   
metadata:                                                                       
  name: my-service                                                              
spec:                                                                           
  selector:                                                                     
    name: busybox                                                               
  clusterIP: None                                                               
  ports:                                                                        
  - name: foo                                                                   
    port: 1234                                                                  
    targetPort: 5678                                                            
---                                                                             
apiVersion: v1                                                                  
kind: Pod                                                                       
metadata:                                                                       
  name: busybox1                                                                
  labels:                                                                       
    name: busybox                                                               
spec:                                                                           
  subdomain: my-service                                                         
  containers:                                                                   
  - name: busybox                                                               
    image: busybox                                                              
    command:                                                                    
    - sleep                                                                     
    - "3600"                                                                    
---                                                                             
apiVersion: v1                                                                  
kind: Pod                                                                       
metadata:                                                                       
  name: busybox2                                                                
  labels:                                                                       
    name: busybox                                                               
spec:                                                                                                                              
  subdomain: my-service                                                         
  containers:                                                                   
  - name: busybox                                                               
    image: busybox                                                              
    command:                                                                    
    - sleep                                                                     
    - "3600"      

同じように、デプロイして別のPodから名前解決をしてみる。

$ kubectl apply -f headless_no_subdomain.yaml
service "my-service" created
pod "busybox1" created
pod "busybox2" created

$ kubectl get pod
NAME       READY     STATUS    RESTARTS   AGE
busybox1   1/1       Running   0          17s
busybox2   1/1       Running   0          17s

$ kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP    12d
my-service   ClusterIP   None         <none>        1234/TCP   22s

$ kubectl run -it --rm --restart=Never --image=busybox nslookup -- /bin/sh
If you don't see a command prompt, try pressing enter.

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

Name:      my-service
Address 1: 172.17.0.4
Address 2: 172.17.0.5

/ # nslookup busybox1.my-service
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

nslookup: can't resolve 'busybox1.my-service'

ということで、busybox1.my-serviceは名前解決できず。 同様に、hostnameを指定して、subdomainを指定しない場合もだめ。hostnameもsubdomainも指定しない場合もだめでした。

以上より、kubernetesのドキュメントにあるように*1名前解決可能にする条件は以下となる。

  1. headlessサービスであること
  2. Podのhostnameとsubdomainを設定すること

*1:The Pod spec also has an optional subdomain field which can be used to specify its subdomain. For example, a Pod with hostname set to “foo”, and subdomain set to “bar”, in namespace “my-namespace”, will have the fully qualified domain name (FQDN) “foo.bar.my-namespace.svc.cluster.local”