Kubernetes DNS 소개

컨디션

$ sudo lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.2 LTS
Release:    16.04
Codename:   xenial

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.4", GitCommit:"7243c69eb523aa4377bce883e7c0dd76b84709a1", GitTreeState:"clean", BuildDate:"2017-03-07T23:53:09Z", GoVersion:"go1.7.4", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.4", GitCommit:"7243c69eb523aa4377bce883e7c0dd76b84709a1", GitTreeState:"clean", BuildDate:"2017-03-07T23:34:32Z", GoVersion:"go1.7.4", Compiler:"gc", Platform:"linux/amd64"}

소개하다.


Kubernetes 1.3부터 DNS는 플러그인 관리 시스템cluster add-on을 사용하여 내장된 자동 시작 서비스가 되었다.Kubernetes DNS는 Kubernetes 클러스터에 DNS Pod 및 Service를 스케줄링하고 컨테이너마다 DNS Service Ip를 사용하여 DNS 이름을 확인할 수 있도록 kubelet을 구성합니다.

DNS 이름이란?


클러스터에 정의된 각 서비스(DNS Service 자체 포함)에는 DNS 이름이 지정됩니다.기본적으로, Pod의 DNS 검색 목록에는 Pod의 고유한 네임스페이스와 클러스터의 기본 도메인이 포함되어 있습니다. 다음은 예를 들어 설명합니다.네임스페이스foo에 이름이 bar인 Service가 있다고 가정합니다.bar 명명 공간에서 실행되는Pod는 DNS 검색foo 키워드를 통해 이 서비스를 찾을 수 있고, 명명 공간quux에서 실행되는Pod는 키워드foo.bar를 통해 이 서비스를 찾을 수 있다.

지원되는 DNS 모드


다음 장에서 지원하는 기록 (record) 형식과layout을 상세하게 설명합니다.

Services


일반(headless가 아닌) 서비스에는 서비스의 집단 IP를 해석할 수 있는 DNS 레코드가 분배되어 있다.Headless (집단 IP 없음) 의 서비스에도 DNS 레코드가 할당되어 있으며, 이름 형식은 my-svc.my-namespace.svc.cluster.local 이다.일반 서비스와 달리 서비스가 선택한 Pod의 IP 목록이 확인됩니다.

SRV records


SRV records는 헤드리스나 일반 서비스의 일부인 포트 서비스의 이름을 지정하는 데 사용됩니다.각 명명된 포트의 경우 SRV record 형식은 my-svc.my-namespace.svc.cluster.local입니다.일반 서비스의 경우 포트 번호와 CNAME_my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster.local가 해석됩니다.headless 서비스에 대해 말하자면 이것은 여러 가지 결과를 해석할 수 있다. 하나는 서비스 백엔드의pod이고 하나는 포트 번호와 my-svc.my-namespace.svc.cluster.local포맷의pod의CNAME이다.

이전 버전과의 호환성


kube-dns의 이전 버전은 auto-generated-name.my-svc.my-namespace.svc.cluster.local (svc 층은 뒤에 추가된) 형식의 이름을 사용했습니다.그러나 이런 격식은 더 이상 지원되지 않는다.

Pods


pod에는 이름 형식my-svc.my-namespace.cluster.local의 DNS 레코드가 할당됩니다.예를 들어 하나의pod는 IP 주소pod-ip-address.my-namespace.pod.cluster.local, 이름 공간1.2.3.4, DNS 이름은cluster이다.local, 그럼 그 기록은 default입니다.pod가 생성되었을 때,hostname은pod의 1-2-3-4.default.pod.cluster.local 에 설정되어 있습니다. (yaml을 쓸 때 이 점을 잘 알 것입니다.)v1.2 릴리즈에서는 Pod의 hostname을 지정하는 데 사용되는 Pod 메모 metadata.name를 지정할 수 있습니다.이 Pod 주석은 지정되면 Pod의 이름보다 우선적으로pod의hostname이 됩니다.예를 들어 Pod의 주석이 pod.beta.kubernetes.io/hostname이면 Pod의hostname은 my-pod-name로 설정됩니다.  v1.2에는 Pod 메모pod.beta.kubernetes.io/hostname: my-pod-name를 지정하여 Pod의subdomain을 지정하는 베타 기능도 도입되었다.예를 들어 하나의 Pod는hostname 주석pod.beta.kubernetes.io/subdomain으로 설정되고subdomain 주석“foo”“bar”이며 명칭 공간은 “my-namespace”이면 최종 FQDN은 “foo.bar.my-namespace.svc.cluster.local”이다.v1.3 버전에서 PodSpec에는 hostnamesubdomain 필드가 있는데 Pod의hostname과subdomain을 지정하는 데 사용됩니다.그것의 우선순위는 위에서 언급한 pod.beta.kubernetes.io/hostnamepod.beta.kubernetes.io/subdomain보다 높다.예:
apiVersion: v1
kind: Service
metadata:
  name: default-subdomain
spec:
  selector:
    name: busybox
  clusterIP: None
  ports:
    - name: foo # Actually, no port is needed.
      port: 1234 
      targetPort: 1234
---
apiVersion: v1
kind: Pod
metadata:
  name: busybox1
  labels:
    name: busybox
spec:
  hostname: busybox-1
  subdomain: default-subdomain
  containers:
  - image: busybox
    command:
      - sleep
      - "3600"
    name: busybox
---
apiVersion: v1
kind: Pod
metadata:
  name: busybox2
  labels:
    name: busybox
spec:
  hostname: busybox-2
  subdomain: default-subdomain
  containers:
  - image: busybox
    command:
      - sleep
      - "3600"
    name: busybox

만약headless 서비스에서 여러 개의pod가 같은 명칭 공간에 있고 subdomain 이름도 같으면, 집단의KubeDNS는 모든Pod에 완전하고 합격된hostname을 되돌려줍니다.Pod을 지정하면hostname 설정busybox-1,subdomain 설정default-subdomain,같은 명칭 공간에서의headless 서비스 이름default-subdomain,pod 자신의 FQDN은 “busybox-1.default-subdomain.my-namespace.svc.cluster.local”이다.Kubernetes v1.2리에 Endpoint 대상은 주석endpoints.beta.kubernetes.io/hostnames-map도 사용했다.그것의 값은 json 형식의 map[string(IP)][endpoints.HostRecord]입니다. 예를 들어 '{"10.245.1.6": {HostName: "my-webserver"} "입니다.만약 Endpoint가headless 서비스에 사용된다면,... svc 형식의 기록을 만들 것입니다.json 포맷의 경우'bar'라는 헤드리스 서비스에 Endpoint가 사용되고 그 중 하나가'10.245.1.6'이면 “my-webserver.bar.my-namespace.svc.cluster.local”라는 기록을 만들고 이 기록을 조회하면'10.245.1.6'을 받는다.이 Endpoint 주석은 일반적으로 터미널 사용자가 지정할 필요는 없지만 내부 서비스 컨트롤러에 의해 사용되어 위의 기능을 실현할 수 있습니다.v1.3에서 Endpoint 객체는 모든 Endpoint에 hostname과 IP를 지정할 수 있습니다.hostname 필드는 endpoints.beta.kubernetes.io/hostnames-map 메모의 값을 덮어씁니다.v1.3에서 다음 주석은 기용되었다. pod.beta.kubernetes.io/hostname,pod.beta.kubernetes.io/subdomain,endpoints.beta.kubernetes.io/hostnames-map.

DNS가 작동하는지 테스트하는 방법


테스트 환경을 위한 간단한 Pod 생성


busybox라는 이름을 만듭니다.yaml 파일, 다음을 사용합니다.
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  containers:
  - image: busybox
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
    name: busybox
  restartPolicy: Always

이 파일을 사용하여pod를 만들려면 다음과 같이 하십시오.
kubectl create -f busybox.yaml

pod가 런닝에 들어갈 때까지 기다립니다.


pod 상태 가져오기
$ kubectl get pods busybox

당신은 다음과 같은 것을 볼 수 있습니다.
NAME      READY     STATUS    RESTARTS   AGE
busybox   1/1       Running   0          7m

DNS가 작동하는지 확인


pod가running상태일 때exec nslookup상태를 조회할 수 있습니다.
$ kubectl exec -ti busybox -- nslookup kubernetes.default

너는 반드시 유사한 결과를 보아야 한다.
Server:    10.0.0.10
Address 1: 10.0.0.10

Name:      kubernetes.default
Address 1: 10.0.0.1

이러한 결과가 나타나면 DNS가 정상적으로 작동하는 것입니다.

문제 해결

nslookup가 실패하면 다음 옵션을 확인합니다.

로컬 DNS 구성 확인


pod resolv.conf 파일을 검사합니다.
$ kubectl exec busybox cat /etc/resolv.conf

검색 경로와name sever가 다음과 같이 설정되어 있는지 확인하십시오. (검색 경로가 클라우드 공급자에 따라 다를 수 있음을 주의하십시오.)
search default.svc.cluster.local svc.cluster.local cluster.local google.internal c.gce_project_id.internal
nameserver 10.0.0.10
options ndots:5

신속 진단


다음 오류는 kube-dns add-on이나 관련 서비스에 문제가 있음을 나타냅니다.
$ kubectl exec -ti busybox -- nslookup kubernetes.default
Server:    10.0.0.10
Address 1: 10.0.0.10

nslookup: can't resolve 'kubernetes.default'

혹은
$ kubectl exec -ti busybox -- nslookup kubernetes.default
Server:    10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local

nslookup: can't resolve 'kubernetes.default'

DNS pod가 실행 중인지 확인

kubectl get pods 명령을 사용하여 DNS pod가 실행 중인지 확인합니다.
$ kubectl get pods --namespace=kube-system -l k8s-app=kube-dns

다음과 같은 결과가 있을 것입니다.
NAME                                                       READY     STATUS    RESTARTS   AGE
...
kube-dns-v19-ezo1y                                         3/3       Running   0           1h
...

관련pod가 실행되지 않았거나pod상태가failed/completed일 경우, DNSadd-on을 기본적으로 배치하지 않았기 때문에 수동으로 배치해야 합니다.

DNS pod에서 오류 확인

kubectl log 명령을 사용하여 DNS 데몬의 로그를 봅니다.
$ kubectl logs --namespace=kube-system $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name) -c kubedns
$ kubectl logs --namespace=kube-system $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name) -c dnsmasq
$ kubectl logs --namespace=kube-system $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name) -c healthz

만약 수상한 로그가 있다면, 줄마다 시작하는 W, E, F 자모는 각각 경고, 오류, 고장을 나타낸다.이 오류 로그의 항목을 검색하거나kubernetes issues 페이지를 통해 예상치 못한 오류를 보고하십시오.

DNS 서비스 시작 여부

kubectl get service 명령을 사용하여 DNS 서비스가 시작되었는지 확인합니다.
$ kubectl get svc --namespace=kube-system

당신은 다음과 같은 것을 볼 수 있습니다.
NAME                    CLUSTER-IP     EXTERNAL-IP   PORT(S)             AGE
...
kube-dns                10.0.0.10              53/UDP,53/TCP        1h
...

이 서비스는 기본적으로 만들어지거나 수동으로 만들어졌지만 이 서비스가 상기 명령에 나타나지 않았습니다. debugging 서비스 페이지 페이지를 보십시오. 더 많은 정보를 얻으십시오.

DNS Endpoint 가 노출되었습니까?

kubectl get endpoints 명령을 사용하여 DNS Endpoint가 노출되었는지 확인할 수 있습니다.
$ kubectl get ep kube-dns --namespace=kube-system

너는 아래의 결과를 보게 될 것이다.
NAME       ENDPOINTS                       AGE
kube-dns   10.180.3.17:53,10.180.3.17:53    1h

Endpoint가 보이지 않으면 debugging 서비스 페이지 페이지를 보십시오.더 많은 Kubernetes DNS 예시를 보려면 Kubernetes Github 창고에서 cluster-dns examples를 보십시오.

어떻게 일하는가


실행 중인 Kubernetes DNS pod에는 kubedns, dnsmasq, 헬스츠라는 건강검진 용기 3개가 포함되어 있습니다.kubedns 프로세스는 Kubernetes 마스터의 서비스와 Endpoint의 변화를 감시하고 메모리에서lookup 구조를 유지하여 서비스 DNS 요청에 사용합니다.dnsmasq 컨테이너는 DNS 캐시를 추가하여 성능을 향상시킵니다.헬스 용기는 단일 건강 검사인 엔도핀을 제공하고,dnsmasq와kubedns의 건강 정도를 검사합니다.DNS pod는 정적 IP를 가진 서비스 형태로 노출되어 있습니다.생성되면kubelet은 --cluster-dns=10.0.0.10 표지를 사용하여 DNS 설정 정보를 용기마다 전달합니다.DNS 이름에도 도메인이 필요합니다.이 지역은 설정할 수 있습니다.kubelet에서 --cluster-domain= 파라미터를 사용합니다.Kubernetes 클러스터의 DNS 서비스(SkyDNS 라이브러리 기반)는 forward lookup(A recoreds), 서비스 lookup(SRV records), 역방향 IP 주소 찾기(PTR recoreds)를 지원합니다.

Node에서 DNS 상속


pod를 실행할 때 kubelet은 그룹의 DNS 서비스를 미리 고려하고 node 로컬 DNS 설정에서 경로를 검색합니다.만약 node가 DNS 이름을 해석할 수 있다면pod도 할 수 있습니다.만약pod에서 다른 DNS를 사용하기를 원한다면,kubelet의 --resolv-conf 인자를 사용할 수 있습니다.이 설정은pod가 node에서 DNS를 계승하지 않는다는 것을 의미합니다.이 값을 다른 파일 경로로 설정하면 파일이 아닌 DNS를 구성하는 데 사용됩니다/etc/resolv.conf.

알려진 문제


Kubernetes 설치는 기본적으로 그룹 DNS 설정을 사용해서 Kubernetes node resolv.conf 파일을 설정하지 않습니다. 이 프로세스는 발행판의 설정에 의존하기 때문입니다.리눅스의libc는 3개의 DNSnameserver와 6개의 DNS 검색 기록이 제한되어 있으며, Kubernetes는nameserver와 3개의 검색 기록을 소모해야 한다.이것은 로컬 설정이 3개의nameserver를 사용했거나 3개 이상의 검색 기록을 사용했다면 이 설정을 잃어버릴 수 있음을 의미합니다.노드는 실행 dnsmasq 할 수 있는 임시 방안이 있습니다. 더 많은nameserver 옵션을 제공할 수 있지만, 더 많은 검색 옵션을 제공할 수 없습니다.kubelet--resolv-conf 옵션을 사용할 수 있습니다.만약 Alpine 3.3 이상의 버전을 사용한다면 DNS가 정상적으로 작동하지 못할 수도 있습니다. 이것은 이미 알고 있는 문제입니다.이곳에서 더 많은 정보를 얻을 수 있습니다.

References


  Docs for the DNS cluster addon

좋은 웹페이지 즐겨찾기