LabHub
배우기 러닝패스 코스

Kubernetesネットワーク — 本物のクラスタで

短い名前はタダではない

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

한 줄 요약

짧은 이름이 편한 만큼의 값은 밖으로 나가는 이름을 찾을 때 청구됩니다. 점이 5개 미만인 이름은 전부 search 를 먼저 돌기 때문입니다.

쿠버네티스에서 web 이라고만 써도 같은 네임스페이스의 서비스를 찾을 수 있습니다. 편합니다. 그런데 그 편의에는 값이 붙어 있고, 그 값은 밖으로 나가는 이름을 찾을 때 청구됩니다.

フロー図: 밖으로 나가는 이름을 찾을 때・요청 한 번에 왕복 네 번이고 그중 셋은 버려집니다.・밖으로 나가는 요청이 많은 파드에만・실제 질의는 8개

search 와 ndots

파드의 /etc/resolv.conf 는 이렇게 생겼습니다.

search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.43.0.10
options ndots:5

search 는 짧은 이름 뒤에 차례로 붙여 볼 꼬리표들이고, ndots:5점이 5개 미만인 이름은 아직 완성된 이름이 아닐 수 있으니 search 를 먼저 시도하라는 뜻입니다.

web 은 점이 0개니까 당연히 search 를 씁니다. 문제는 example.com 입니다. 점이 하나뿐이라 이것도 5 미만이고, 그래서 이 순서로 물어봅니다.

example.com.default.svc.cluster.local   → NXDOMAIN
example.com.svc.cluster.local           → NXDOMAIN
example.com.cluster.local               → NXDOMAIN
example.com.                            → 드디어 응답

요청 한 번에 왕복 네 번이고 그중 셋은 버려집니다.

왜 지표에 안 잡히나

DNS 조회는 애플리케이션 코드가 아니라 그 아래 라이브러리에서 일어납니다. 그래서 애플리케이션 트레이스에 구간이 잡히지 않는 경우가 많고, 사용자에게는 "조금 느린 요청" 으로만 보입니다. CoreDNS 의 부하만 조용히 올라가다가, 파드 수가 늘어난 어느 날 한계에 닿습니다.

고칠 수 있지만 공짜는 아니다

파드마다 dnsConfigndots 를 낮출 수 있습니다. 다만 그 파드는 이제 짧은 이름으로 클러스터 서비스를 찾지 못합니다. 그래서 밖으로 나가는 요청이 많은 파드에만 주는 것이 맞습니다. 클러스터 안 통신이 많은 파드에 주면 오히려 손해입니다.

왜 왕복이 네 번인가

파드의 /etc/resolv.conf 는 이렇게 생겼습니다.

search labhub-prod.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.96.0.10
options ndots:5

ndots:5점이 5개 미만인 이름은 완성된 이름이 아니라고 보고 search 를 먼저 붙여 본다 는 뜻입니다. api.example.com 은 점이 2개이므로 여기 걸립니다.

1. api.example.com.labhub-prod.svc.cluster.local  → NXDOMAIN
2. api.example.com.svc.cluster.local              → NXDOMAIN
3. api.example.com.cluster.local                  → NXDOMAIN
4. api.example.com                                → 응답    ← 네 번째에 성공

IPv6 가 켜져 있으면 각 질의마다 A 와 AAAA 를 함께 물으므로 실제 질의는 8개 입니다. 바깥 API 를 자주 부르는 서비스에서 CoreDNS 부하의 대부분이 이것입니다.

세 가지 대응과 각각의 값

방법 효과 대가
이름 끝에 점 (example.com.) search 를 완전히 건너뛴다 코드를 고쳐야 한다
파드에 ndots: 1 그 파드의 모든 이름에 적용 짧은 이름이 안 된다
NodeLocal DNSCache 노드에서 캐시, CoreDNS 부하 급감 설치·운영 부담

첫 줄이 가장 싸고 안전합니다. ndots 를 전역으로 낮추지 않는 이유kubectl 로 확인할 수 있습니다 — 짧은 이름으로 서비스를 부르는 코드가 전부 깨집니다.

# 파드 단위로만, 그 파드가 짧은 이름을 안 쓴다는 것을 확인하고
spec:
  dnsConfig:
    options:
      - name: ndots
        value: "1"

DNS 문제를 진단하는 명령

# 파드 안에서 — 어느 단계에서 실패하는지 본다
nslookup api.example.com
nslookup api.example.com.        # 끝점을 찍으면 되는가?

# search 가 실제로 어떻게 붙는지
dig +search +short api.example.com

# CoreDNS 가 무엇을 받고 있나
kubectl -n kube-system logs -l k8s-app=kube-dns --tail=50 | grep NXDOMAIN

CoreDNS 로그가 비어 있으면 Corefilelog 플러그인이 없는 것입니다. 조사할 때만 켜고 끕니다 — 켜 두면 로그량이 큽니다.

증상별로 보면 이렇습니다. 간헐적 실패 는 대개 conntrack 이나 UDP 패킷 유실이고, 전부 실패 는 CoreDNS 나 네트워크 정책이며, 느리기만 한 것 은 위의 search 왕복입니다.

실무에서 진짜 중요한 것

바깥 도메인을 자주 부르는 곳에는 끝점을 찍습니다. example.com. 처럼 마침표를 붙이면 완성된 이름으로 취급되어 search 를 통째로 건너뜁니다. 코드 한 글자로 왕복 네 번이 한 번이 되고, ndots 를 건드리지 않으므로 짧은 이름도 그대로 삽니다.

신호는 CoreDNS 의 질의 수에서 찾습니다. 헛질의도 정상 응답(NXDOMAIN)이라 오류율은 오르지 않습니다. 질의 수가 서비스 호출 수보다 몇 배 많으면 그것이 이 비용을 내고 있다는 뜻입니다.

ndots 는 절대 전역으로 낮추지 않습니다. 짧은 이름으로 클러스터 안 서비스를 부르는 코드가 전부 깨집니다. 바꾸려면 파드 단위로, 그 파드가 짧은 이름을 안 쓴다는 것을 확인하고 해야 합니다.

트레이드오프를 아는 것이 이 주제의 전부입니다. 다음 실습에서 질의 수를 직접 세어 보면, 이 이야기가 숫자로 손에 잡힙니다.