Service와 파드용 DNS

Service와 파드용 DNS (DNS for Services and Pods)

쿠버네티스는 Service와 파드에 대한 DNS 레코드를 만들어요. IP 주소 대신 일관된 DNS 이름으로 Service에 접촉할 수 있어요.

쿠버네티스는 DNS를 프로그래밍하는 데 사용되는 파드와 Service에 대한 정보를 게시해요. kubelet은 파드의 DNS를 구성해서 실행 중인 컨테이너가 IP가 아닌 이름으로 Service를 조회할 수 있게 해요.

클러스터에 정의된 Service에는 DNS 이름이 할당돼요. 기본적으로 클라이언트 파드의 DNS 검색 목록에는 파드 자신의 네임스페이스와 클러스터의 기본 도메인이 포함돼요.

출처: 문서

본문

Service의 네임스페이스

DNS 쿼리는 그것을 만드는 파드의 네임스페이스에 따라 다른 결과를 반환할 수 있어요. 네임스페이스를 지정하지 않은 DNS 쿼리는 파드의 네임스페이스로 제한돼요. 다른 네임스페이스의 Service에 접근하려면 DNS 쿼리에서 그것을 지정해요.

예를 들어 test 네임스페이스의 파드를 고려해 봐요. data Service는 prod 네임스페이스에 있어요.

data 에 대한 쿼리는 파드의 test 네임스페이스를 사용하므로 결과 없음을 반환해요.

data.prod 에 대한 쿼리는 네임스페이스를 지정하므로 의도한 결과를 반환해요.

DNS 쿼리는 파드의 /etc/resolv.conf 를 사용해 확장될 수 있어요. kubelet은 각 파드에 대해 이 파일을 구성해요. 예를 들어 data 만에 대한 쿼리는 data.test.svc.cluster.local 로 확장될 수 있어요. search 옵션의 값은 쿼리를 확장하는 데 사용돼요. DNS 쿼리에 대해 더 알아보려면 resolv.conf 매뉴얼 페이지를 참고해요.

nameserver 10.32.0.10
search <namespace>.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

요약하면 test 네임스페이스의 파드는 data.prod 또는 data.prod.svc.cluster.local 을 성공적으로 해석할 수 있어요.

DNS 레코드

어떤 객체가 DNS 레코드를 얻나요?

  • Services
  • Pods

다음 섹션은 지원되는 DNS 레코드 유형과 레이아웃을 자세히 설명해요. 우연히 동작하는 다른 레이아웃·이름·쿼리는 구현 세부 사항으로 간주되며 경고 없이 변경될 수 있어요. 더 최신의 사양은 Kubernetes DNS-Based Service Discovery를 참고해요.

서비스 (Services)

A/AAAA 레코드

"일반"(헤드리스가 아닌) Service는 Service의 IP 패밀리 또는 패밀리들에 따라 my-svc.my-namespace.svc.cluster-domain.example 형태의 이름으로 DNS A 및/또는 AAAA 레코드가 할당돼요. 이것은 Service의 클러스터 IP로 해석돼요.

헤드리스 Service(클러스터 IP 없음)도 my-svc.my-namespace.svc.cluster-domain.example 형태의 이름으로 DNS A 및/또는 AAAA 레코드가 할당돼요. 일반 Service와 달리 이것은 Service가 선택한 모든 파드의 IP 집합으로 해석돼요. 클라이언트는 그 집합을 소비하거나 집합에서 표준 라운드로빈 선택을 사용할 것으로 기대돼요.

SRV 레코드

SRV 레코드는 일반 또는 헤드리스 서비스의 일부인 명명된 포트에 대해 생성돼요.

  • 각 명명된 포트에 대해 SRV 레코드는 _port-name._port-protocol.my-svc.my-namespace.svc.cluster-domain.example 형태예요.
  • 일반 Service의 경우 이것은 포트 번호와 도메인 이름 my-svc.my-namespace.svc.cluster-domain.example 으로 해석돼요.
  • 헤드리스 Service의 경우 이것은 Service를 뒷받침하는 각 파드에 대해 하나씩 여러 답변으로 해석되며, hostname.my-svc.my-namespace.svc.cluster-domain.example 형태의 파드의 포트 번호와 도메인 이름을 포함해요.

파드 (Pods)

A/AAAA 레코드

DNS 사양 구현 이전의 Kube-DNS 버전은 다음 DNS 해석을 가졌어요:

<pod-IPv4-address>.<namespace>.pod.<cluster-domain>

예를 들어 default 네임스페이스의 파드가 IP 주소 172.17.0.3을 가지고 클러스터의 도메인 이름이 cluster.local 이라면, 파드는 다음과 같은 DNS 이름을 가져요:

172-17-0-3.default.pod.cluster.local

CoreDNS 같은 일부 클러스터 DNS 메커니즘은 다음에 대한 A 레코드도 제공해요:

<pod-ipv4-address>.<service-name>.<my-namespace>.svc.<cluster-domain.example>

예를 들어 cafe 네임스페이스의 파드가 IP 주소 172.17.0.3을 가지고 barista 라는 Service의 엔드포인트이며 클러스터의 도메인 이름이 cluster.local 이라면, 파드는 이 Service 범위 DNS A 레코드를 가져요.

172-17-0-3.barista.cafe.svc.cluster.local

파드의 hostname과 subdomain 필드

현재 파드가 생성될 때 그 호스트 이름(파드 내부에서 관찰되는)은 파드의 metadata.name 값이에요.

Pod 스펙에는 선택적 hostname 필드가 있으며, 다른 호스트 이름을 지정하는 데 사용할 수 있어요. 지정되면 파드의 이름보다 우선해 파드의 호스트 이름이 돼요(다시 파드 내부에서 관찰되는). 예를 들어 spec.hostname"my-host" 로 설정된 파드가 있다면, 파드의 호스트 이름은 "my-host" 로 설정돼요.

Pod 스펙에는 또한 선택적 subdomain 필드가 있어 파드가 네임스페이스의 하위 그룹의 일부임을 나타낼 수 있어요. 예를 들어 spec.hostname"foo" 로 설정되고 spec.subdomain"bar" 로 설정된, 네임스페이스 "my-namespace" 의 파드는 호스트 이름이 "foo" 로 설정되고 완전히 정규화된 도메인 이름(FQDN)이 "foo.bar.my-namespace.svc.cluster.local" 로 설정돼요(다시 파드 내부에서 관찰되는).

파드와 같은 네임스페이스에 subdomain과 같은 이름의 헤드리스 Service가 존재하면, 클러스터의 DNS 서버는 파드의 완전히 정규화된 호스트 이름에 대한 A 및/또는 AAAA 레코드도 반환해요.

예시:

apiVersion: v1
kind: Service
metadata:
  name: busybox-subdomain
spec:
  selector:
    name: busybox
  clusterIP: None
  ports:
  - name: foo # name is not required for single-port Services
    port: 1234
---
apiVersion: v1
kind: Pod
metadata:
  name: busybox1
  labels:
    name: busybox
spec:
  hostname: busybox-1
  subdomain: busybox-subdomain
  containers:
  - image: busybox:1.28
    command:
      - sleep
      - "3600"
    name: busybox
---
apiVersion: v1
kind: Pod
metadata:
  name: busybox2
  labels:
    name: busybox
spec:
  hostname: busybox-2
  subdomain: busybox-subdomain
  containers:
  - image: busybox:1.28
    command:
      - sleep
      - "3600"
    name: busybox

위 Service "busybox-subdomain"spec.subdomain"busybox-subdomain" 으로 설정한 파드들이 있다면, 첫 번째 파드는 자신의 FQDN을 "busybox-1.busybox-subdomain.my-namespace.svc.cluster-domain.example" 로 볼 거예요. DNS는 그 이름에서 A 및/또는 AAAA 레코드를 제공해 파드의 IP를 가리켜요. "busybox1""busybox2" 두 파드 모두 자신의 주소 레코드를 가질 거예요.

EndpointSlice는 IP와 함께 모든 엔드포인트 주소에 대한 DNS 호스트 이름을 지정할 수 있어요.

참고:

파드의 setHostnameAsFQDN 필드

파드가 완전히 정규화된 도메인 이름(FQDN)을 갖도록 구성되면, 그 호스트 이름은 짧은 호스트 이름이에요. 예를 들어 완전히 정규화된 도메인 이름 busybox-1.busybox-subdomain.my-namespace.svc.cluster-domain.example 을 가진 파드가 있다면, 기본적으로 그 파드 안의 hostname 명령은 busybox-1 을 반환하고 hostname --fqdn 명령은 FQDN을 반환해요.

Pod 스펙에서 setHostnameAsFQDN: true 를 설정하면 kubelet이 파드의 FQDN을 그 파드의 네임스페이스 호스트 이름에 기록해요. 이 경우 hostnamehostname --fqdn 둘 다 파드의 FQDN을 반환해요.

참고:

Linux에서 커널의 hostname 필드(struct utsnamenodename 필드)는 64자로 제한돼요.

파드가 이 기능을 활성화하고 FQDN이 64자보다 길면 시작에 실패해요. 파드는 Pending 상태(코드에서 ContainerCreating 으로 kubectl 이 봄)로 남아 "Failed to construct FQDN from Pod hostname and cluster domain" 같은 오류 이벤트를 생성해요. FQDN long-FQDN 이 너무 깁니다(64자가 최대인데 70자가 요청됨).

이 시나리오에서 사용자 경험을 개선하는 한 가지 방법은 사용자가 Deployment 같은 최상위 객체를 만들 때 FQDN 크기를 제어하는 admission webhook 컨트롤러를 만드는 것이에요.

파드의 DNS 정책

DNS 정책은 파드별로 설정할 수 있어요. 현재 쿠버네티스는 다음 파드별 DNS 정책을 지원해요. 이 정책들은 Pod Spec의 dnsPolicy 필드에 지정돼요.

참고:

아래 예시는 hostNetworktrue 로 설정되어 있어 DNS 정책이 "ClusterFirstWithHostNet" 으로 설정된 파드를 보여줘요.

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  containers:
  - image: busybox:1.28
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
    name: busybox
  restartPolicy: Always
  hostNetwork: true
  dnsPolicy: ClusterFirstWithHostNet

파드의 DNS 구성

Pod의 DNS Config는 사용자에게 파드의 DNS 설정에 대한 더 많은 제어권을 주어요.

dnsConfig 필드는 선택 사항이며 어떤 dnsPolicy 설정과도 함께 동작할 수 있어요. 하지만 파드의 dnsPolicy 가 "None" 으로 설정되면 dnsConfig 필드를 반드시 지정해야 해요.

사용자가 dnsConfig 필드에 지정할 수 있는 속성은 다음과 같아요:

  • nameservers: 파드의 DNS 서버로 사용될 IP 주소 목록. 최대 3개의 IP 주소를 지정할 수 있어요. 파드의 dnsPolicy 가 "None" 으로 설정되면 목록은 최소 하나의 IP 주소를 포함해야 하고, 그 외에는 이 속성은 선택적이에요. 나열된 서버는 지정된 DNS 정책에서 생성된 기본 네임서버에 중복 주소를 제거해 결합돼요.
  • searches: 파드에서 호스트 이름 조회를 위한 DNS 검색 도메인 목록. 이 속성은 선택적이에요. 지정되면 제공된 목록은 선택된 DNS 정책에서 생성된 기본 검색 도메인 이름에 병합돼요. 중복 도메인 이름은 제거돼요. 쿠버네티스는 최대 32개의 검색 도메인을 허용해요.
  • options: 각 객체가 name 속성(필수)과 value 속성(선택)을 가질 수 있는 선택적 객체 목록. 이 속성의 내용은 지정된 DNS 정책에서 생성된 옵션에 병합돼요. 중복 항목은 제거돼요.

다음은 커스텀 DNS 설정이 있는 파드 예시예요:

apiVersion: v1
kind: Pod
metadata:
  namespace: default
  name: dns-example
spec:
  containers:
    - name: test
      image: nginx
  dnsPolicy: "None"
  dnsConfig:
    nameservers:
      - 192.0.2.1 # this is an example
    searches:
      - ns1.svc.cluster-domain.example
      - my.dns.search.suffix
    options:
      - name: ndots
        value: "2"
      - name: edns0

위 파드가 생성되면 컨테이너 test/etc/resolv.conf 파일에 다음 내용을 얻어요:

nameserver 192.0.2.1
search ns1.svc.cluster-domain.example my.dns.search.suffix
options ndots:2 edns0

IPv6 설정의 경우 검색 경로와 네임 서버는 다음과 같이 설정해야 해요:

kubectl exec -it dns-example -- cat /etc/resolv.conf

출력은 다음과 비슷해요:

nameserver 2001:db8:30::a
search default.svc.cluster-domain.example svc.cluster-domain.example cluster-domain.example
options ndots:5

DNS 검색 도메인 목록 한도

쿠버네티스 자체는 검색 도메인 목록의 길이가 32를 초과하거나 모든 검색 도메인의 총 길이가 2048을 초과할 때까지 DNS 구성을 제한하지 않아요. 이 한도는 노드의 리졸버 구성 파일, 파드의 DNS Config, 병합된 DNS Config 각각에 적용돼요.

참고:

이전 버전의 일부 컨테이너 런타임은 DNS 검색 도메인 수에 대한 자체 제한을 가질 수 있어요. 컨테이너 런타임 환경에 따라 DNS 검색 도메인이 많은 파드는 보류(pending) 상태에 갇힐 수 있어요.

containerd v1.5.5 이하와 CRI-O v1.21 이하가 이 문제가 있는 것으로 알려져 있어요.

Windows 노드의 DNS 해석

  • ClusterFirstWithHostNet 은 Windows 노드에서 실행되는 파드에 지원되지 않아요. Windows는 . 이 있는 모든 이름을 FQDN으로 취급하고 FQDN 해석을 건너뛰어요.
  • Windows에는 사용할 수 있는 여러 DNS 리졸버가 있어요. 이들은 약간 다른 동작을 가지므로, Resolve-DNSName powershell cmdlet을 이름 쿼리 해석에 사용하는 것이 권장돼요.
  • Linux에는 이름의 완전 정규화 해석이 실패한 후 사용되는 DNS 접미사 목록이 있어요. Windows에는 DNS 접미사를 1개만 가질 수 있는데, 그것은 그 파드의 네임스페이스와 연관된 DNS 접미사예요(예: mydns.svc.cluster.local). Windows는 FQDN, Service, 또는 이 단일 접미사로 해석할 수 있는 네트워크 이름을 해석할 수 있어요. 예를 들어 default 네임스페이스에서 생성된 파드는 DNS 접미사 default.svc.cluster.local 을 가질 거예요. Windows 파드 안에서 kubernetes.default.svc.cluster.localkubernetes 둘 다 해석할 수 있지만, 부분 정규화된 이름(kubernetes.default 또는 kubernetes.default.svc)은 해석할 수 없어요.

더 알아보기 (Learn more)

DNS 구성 관리에 대한 지침은 DNS 서비스 구성을 확인해요.