TT Lab
요금제

한국어

시작하기
블로그

블로그

공인 접속이 끊긴 날: MetalLB L2 광고가 떠돌고, 첫 처방은 아무도 광고하지 않게 만들었다

상태: 해결 (2026-10-14), 기록 기준. 그날의 숫자(광고 노드가 바뀐 횟수, speaker 재시작 수)는 작업 메모에서, 지금 설정과 노드 라벨은 2026-10-16 클러스터 읽기로 확인했습니다. 공유기 안에서 무슨 일이 있었는지는 공유기 로그를 보지 못해 추정으로 적습니다. 작성 규칙: 기록에 있는 사실만, 짐작은 「추정」, 재지 못한 것은 「미실측」.

목차

한 줄 요약

영향 바깥에서 사이트 접속 불가(80·443 에서 No route to host). 첫 처방 뒤 잠시 사내망에서도 불가
원인 게이트웨이 IP 를 ARP 로 답해 주는 노드(광고 노드)가 계속 바뀌었고, 그중에는 공유기가 닿지 못하는 노드도 있었다(추정)
첫 처방의 실수 광고 노드를 컨트롤 플레인 셋으로 고정 → 셋 다 exclude-from-external-load-balancers 라벨이 있어 아무도 광고하지 않음
고친 것 유선으로 붙은 워커 둘로 고정. 바깥 세 지점에서 200 확인
재발 방지 광고 노드를 고를 때 제외 라벨을 먼저 본다. 진단 순서를 정해 둔다. MetalLB 문서에 이 함정을 적는 PR 을 보냈다

1. 구성: 공유기 → 게이트웨이 IP → 그 IP 를 「가진」 노드 하나

사이트로 오는 요청은 집 공유기의 포트 포워딩을 거칩니다. 공유기는 80·443 을 클러스터의 게이트웨이 서비스 IP 로 넘기고, 그 IP 는 MetalLB 가 L2 모드로 나눠 준 LoadBalancer 주소입니다.

L2 모드에서 그 IP 는 어느 한 기계의 랜 카드에 붙어 있는 주소가 아닙니다. 공유기가 「이 IP 의 MAC 주소는?」 하고 ARP 로 물으면, MetalLB speaker 가 도는 노드 하나가 「나」 라고 답합니다. MetalLB 문서는 이 노드를 정하는 방법을 이렇게 설명합니다(문서 기준).

공유기는 게이트웨이 IP 의 주인을 ARP 로 묻는다 바깥 사용자 공유기 포트 포워딩 80·443 → 게이트웨이 IP(MetalLB L2) 그 IP 에 답하는 노드(광고 노드)는 한 번에 하나뿐이다. ① 그날: 광고가 노드 사이를 떠돌았다 CP 1 CP 2 CP 3 워커 A 워커 B 그 밖 크래시 루프 광고 노드가 1,275번 바뀌었고, 노트북 노드에도 앉았다 ② 첫 처방: 컨트롤 플레인 셋에 고정 — 틀렸다 CP 1 제외 라벨 CP 2 제외 라벨 CP 3 제외 라벨 워커 A 워커 B 그 밖 고른 노드가 모두 광고를 거절 → 아무도 답하지 않음 ③ 지금: 유선으로 붙은 워커 둘에 고정 CP 1 CP 2 CP 3 워커 A 광고 중 워커 B 대기 그 밖 하나가 죽으면 남은 하나가 넘겨받는다(memberlist)
그림: 광고 노드가 떠돌던 때, 첫 처방, 지금

2. 증상: 밖에서만 안 된다

「안에서는 된다」 는 신호가 가장 헷갈렸습니다. 게이트웨이도, 그 뒤의 웹 파드도 건강했습니다. 끊긴 곳은 그 앞, 공유기와 광고 노드 사이였습니다.

3. 진단: 광고 노드가 천 번 넘게 바뀌었다

게이트웨이 서비스의 이벤트에는 speaker 가 광고를 시작할 때마다 announcing from node "…" 가 남습니다(MetalLB 문제 해결 문서가 권하는 확인 방법이기도 합니다). 그날 이 이벤트를 세어 보니 광고 노드가 1,275번 바뀌어 있었습니다(작업 메모).

No route to host 가 나온 경로는 이렇게 추정합니다. 공유기는 포워딩할 대상 IP 의 MAC 을 ARP 로 묻는데, 그 순간 광고 노드가 공유기에서 닿지 않는 곳(무선이나 가상 네트워크 뒤의 노트북 노드 등)이거나 막 넘겨받는 중이면 답이 오지 않습니다. 답이 없으면 공유기는 「호스트에 닿을 수 없음」 ICMP 를 돌려주고, 클라이언트는 그것을 No route to host 로 보여 줍니다. 공유기의 ARP 표와 로그는 보지 못했습니다(미확인).

4. 첫 처방이 틀렸다

광고 노드가 떠도는 게 문제라면, 가장 흔들리지 않는 노드에 묶으면 됩니다. 처음 떠올린 곳은 컨트롤 플레인 셋이었습니다. 재부팅도 드물고 워크로드도 적습니다. L2Advertisement 의 nodeSelectors 를 그 셋으로 좁혔습니다.

결과는 더 나빠졌습니다. 사내망에서도 사이트가 끊겼습니다. 이번에는 광고하는 노드가 아예 없었기 때문입니다.

원인은 노드 라벨 하나였습니다.

라벨 값이 비어 있어도 키가 있으면 제외입니다. 2026-10-16 에 읽어 보니 컨트롤 플레인 셋 모두 이 라벨을 값 없이 달고 있었습니다.

# 광고 노드를 고르기 전에 이것부터
kubectl get nodes -L node.kubernetes.io/exclude-from-external-load-balancers

nodeSelectors 가 고른 노드가 모두 제외 라벨을 달고 있으면, 서비스는 외부 IP 를 받은 채로 아무 데서도 응답하지 않습니다. 에러도 이벤트도 눈에 띄게 남지 않습니다. 이것을 문서에 적어 두려고 MetalLB 에 PR 을 보냈습니다 — metallb/metallb#3156(2026-10-16 기준 열려 있음).

5. 고친 것: 유선으로 붙은 워커 둘

컨트롤 플레인을 빼면 남는 기준은 「공유기와 같은 유선 랜에 있고, 자주 재부팅하지 않는 워커」입니다. 그런 미니 PC 두 대로 고정했습니다.

apiVersion: metallb.io/v1beta1
kind: L2Advertisement
spec:
  ipAddressPools: [<게이트웨이 풀>]
  nodeSelectors:
    - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values: [<워커 A>, <워커 B>]

두 대로 둔 이유는 하나가 죽어도 다른 하나가 넘겨받게 하려는 것입니다. 한 대로 묶으면 그 노드를 재부팅할 때마다 사이트가 끊깁니다. 워커 하나를 재부팅한 뒤 바깥의 세 지점에서 HTTP 200 을 확인했습니다.

6. 그런데 사내망에서는 여전히 안 보였다: 헤어핀

고친 뒤에도 집 안에서 공인 주소(도메인)로 접속하면 열리지 않았습니다. 이것은 다른 문제입니다. 사내망 → 공인 IP → 다시 사내망으로 꺾여 들어오는 경로(헤어핀 NAT, NAT 루프백)를 이 공유기가 지원하지 않습니다. 그래서 집 안에서 「안 된다」는 바깥 상태를 알려 주지 못하고, 반대로 집 안에서 「된다」도 바깥을 보장하지 않습니다.

확인은 두 갈래로 나눕니다.

# 안: 공인 DNS 를 건너뛰고 게이트웨이 IP 로 바로 — 이름(SNI·Host)은 그대로 둔다
curl -sS -o /dev/null -w '%{http_code}\n' --resolve <도메인>:443:<게이트웨이 IP> https://<도메인>/

# 밖: 여러 나라에서 HTTP 요청을 보내 주는 외부 점검 서비스(check-host.net 등)로

7. 다음에 「접속이 안 돼요」 를 들으면

  1. 게이트웨이 IP 로 직접(--resolve). 여기서 안 되면 클러스터 안 문제입니다.
  2. 바깥 점검 서비스. 1은 되는데 2가 안 되면 공유기와 광고 노드 사이입니다.
  3. 게이트웨이 서비스의 이벤트에서 지금 광고 노드와 바뀐 횟수를 봅니다(kubectl get events --field-selector involvedObject.name=<서비스>).
  4. speaker 로그에서 memberlist 가입 실패, 재시작 수를 봅니다.
  5. 광고 노드를 바꿔야 하면 제외 라벨을 먼저 확인합니다.

8. 남은 것과 한계

티티 한마디. 「안에서는 되는데요?」 가 제일 무서운 말이에요. 안과 밖은 길이 달라서, 한쪽의 초록불이 다른 쪽을 말해 주지 않거든요. 그리고 노드를 고를 땐 이름보다 라벨부터! 라벨 하나가 조용히 「난 빠질게」 하고 있을 수 있어요.

참고

모든 자료는 2026-10-16 에 열람했습니다.

로그인하면 좋아요를 누를 수 있습니다

댓글

아직 댓글이 없습니다.

로그인하면 댓글을 쓸 수 있습니다