콘텐츠로 이동






ESXi VMXNET3 환경의 MetalLB webhook timeout 해결

발생현상

MetalLB 설치 후 IPAddressPool 생성 시 admission webhook timeout이 발생했다.

Calico VXLAN 패킷에서 checksum 오류를 확인했다. Offload 설정을 변경하자 checksum 오류는 줄었지만, webhook timeout은 지속됐다.

최종적으로 VMware 가상 NIC를 VMXNET3에서 E1000E로 교체한 뒤 webhook 통신이 복구됐다.

1. 환경과 증상

구성 환경

항목 구성
가상화 플랫폼 VMware ESXi
Linux 커널 5.14.0-687.54.1.el9_8.x86_64
기존 가상 NIC VMXNET3
NIC 드라이버 vmxnet3, 1.9.0.0-k-NAPI
CNI Calico
Pod CIDR 10.233.64.0/18
캡슐화 VXLAN Always
VXLAN 설정 UDP4789, VNI 4096, MTU 1450
MetalLB v0.16.1, Helm 설치
네임스페이스 metallb
광고 방식 L2

발생 오류

kubectl apply -f pool.yml
failed calling webhook "ipaddresspoolvalidationwebhook.metallb.io":
failed to call webhook:
Post "[https://metallb-webhook-service.metallb.svc:443/validate-metallb-io-v1beta1-ipaddresspool?timeout=10s](https://metallb-webhook-service.metallb.svc:443/validate-metallb-io-v1beta1-ipaddresspool?timeout=10s)":
context deadline exceeded

L2Advertisement 생성도 동일하게 실패했다.

failed calling webhook "l2advertisementvalidationwebhook.metallb.io"
context deadline exceeded

당시 통신 상태:

경로 결과
Ingress → 애플리케이션 정상
Worker → MetalLB controller Pod 정상
Master → MetalLB controller Pod Timeout
Master → MetalLB webhook Service Timeout

문제가 발생한 경로는 다음과 같다.

kubectl apply
  → kube-apiserver
  → MetalLB webhook Service
  → worker의 MetalLB controller Pod

2. 진단 과정

Pod와 Service 확인

kubectl -n metallb get pods -o wide

kubectl -n metallb get svc metallb-webhook-service -o yaml

kubectl -n metallb get endpointslices \
  -l kubernetes.io/service-name=metallb-webhook-service \
  -o yaml
항목 확인 결과
Controller 상태 1/1 Running, 재시작 없음
Controller Pod IP 10.233.103.150
Webhook Service IP 10.233.37.54
Service 포트 TCP443
Endpoint 포트 TCP9443
Endpoint 상태 ready: true, serving: true
10.233.37.54:443
  → 10.233.103.150:9443

Controller 로그에서도 인증서 준비와 webhook 기동 완료를 확인했다.

certs are ready in /tmp/k8s-webhook-server/serving-certs
CA certs are injected to webhooks
Starting webhook server
Serving webhook server ... port: 9443

노드별 접속 테스트

Master와 worker에서 동일한 Pod IP로 접속했다.

curl -vk --noproxy '*' \
  --connect-timeout 3 --max-time 5 \
  [https://10.233.103.150:9443/](https://10.233.103.150:9443/)

Master 결과:

Trying 10.233.103.150:9443...
Connection timed out after 3001 milliseconds

Worker 결과:

Connected to 10.233.103.150 port 9443
SSL connection using TLSv1.3
HTTP/1.1 404 Not Found

Worker에서는 TCP 연결, TLS handshake, HTTP 응답까지 정상 진행됐다. / 경로의 404는 연결 실패가 아니다.

Master에서는 Service IP 접속도 실패했다.

curl -vk --noproxy '*' \
  --connect-timeout 3 --max-time 5 \
  [https://10.233.37.54:443/](https://10.233.37.54:443/)

Calico 경로 확인

kubectl get ippools.crd.projectcalico.org -o yaml
spec:
  cidr: 10.233.64.0/18
  ipipMode: Never
  vxlanMode: Always
  natOutgoing: true

라우트와 VXLAN 매핑도 확인했다.

ip route get 10.233.103.150
ip -d link show vxlan.calico
ip neigh show dev vxlan.calico
bridge fdb show dev vxlan.calico

Master의 목적지 경로:

10.233.103.150 via 10.233.103.128 dev vxlan.calico
src 10.233.106.128

라우트와 Neighbor/FDB는 존재했지만, 실제 통신은 실패했다.

패킷과 오류 카운터 확인

Worker에서 패킷을 캡처한 뒤 Master에서 curl을 실행했다.

sudo tcpdump -lni any -nn -vv \
  '(host 192.168.100.11 and udp port 4789) or
   (host 10.233.103.150 and tcp port 9443)'
eth0 In
192.168.100.11 → 192.168.0.22:4789
[bad udp cksum]

내부 TCP:
10.233.106.128 → 10.233.103.150:9443
Flags [S], incorrect checksum

SYN 재전송은 확인됐지만 SYN-ACK은 없었다.

nstat -az | grep -E 'UdpInErrors|UdpInCsumErrors'
ip -s link show vxlan.calico
항목 요청 전 요청 후
UdpInErrors 1608 1610
UdpInCsumErrors 1608 1610
VXLAN RX packets 12 12

캡처 결과와 커널 카운터 증가를 함께 확인해 VXLAN 수신 checksum 문제를 좁혔다.

추가 확인 결과:

  • Kubernetes·Calico NetworkPolicy 없음.
  • Calico HostEndpoint 없음.
  • 해당 환경에서 방화벽과 SELinux 미사용.
  • Worker의 IP forwarding 활성화.
  • 역방향 검사 드롭 카운터 증가 없음.

3. 조치와 해결

Offload 변경: 해결되지 않음

변경 전 설정을 저장했다.

sudo ethtool -k eth0 > /tmp/eth0-offload-before.txt
sudo ethtool -k vxlan.calico > /tmp/vxlan-offload-before.txt

테스트 과정에서 다음 기능을 비활성화했다.

sudo ethtool -K eth0 \
  tx-udp_tnl-segmentation off \
  tx-udp_tnl-csum-segmentation off

sudo ethtool -K eth0 \
  tx-checksum-ip-generic off

sudo ethtool -K vxlan.calico \
  tx-checksum-ip-generic off

적용 상태를 확인했다.

sudo ethtool -k eth0 | grep -E \
  'tx-checksum-ip-generic|tx-udp_tnl'

sudo ethtool -k vxlan.calico | grep \
  tx-checksum-ip-generic

변경 후 결과:

항목 요청 전 요청 후
UdpInErrors 1610 1610
UdpInCsumErrors 1610 1610
VXLAN RX packets 23 25

vxlan.calico에서 내부 SYN도 관찰됐다.

vxlan.calico In
10.233.106.128 → 10.233.103.150:9443
Flags [S]

그러나 Pod 방향 전달은 확인되지 않았고, curl과 webhook timeout도 지속됐다.

Offload 변경은 checksum 오류를 개선했지만, 장애를 해결하지 못했다.

가상 NIC 교체: 통신 복구

최종 조치는 VMware 가상 NIC 교체였다.

VMXNET3 → E1000E

작업 순서:

  1. vSphere 콘솔 접근 확보.
  2. 기존 MAC, Port Group, IP, 라우팅, NetworkManager 프로파일 기록.
  3. VM 정상 종료.
  4. 가상 NIC를 E1000E로 교체.
  5. Port Group 연결 확인 후 부팅.
  6. 인터페이스와 노드 상태 확인.
  7. MetalLB Pool 설정 재적용.

변경 전후 확인 명령:

ip -br addr
ip route
nmcli -f NAME,UUID,DEVICE connection show

sudo ethtool -i <실제-인터페이스>

kubectl get nodes -o wide
kubectl -n kube-system get pods -o wide
kubectl -n metallb get pods -o wide

NIC 교체 후 pool.yml을 다시 적용했다.

kubectl apply -f pool.yml

이번에는 timeout 대신 설정 검증 오류가 반환됐다.

l2advertisement.metallb.io/vip-l2 created

admission webhook "ipaddresspoolvalidationwebhook.metallb.io"
denied the request:

parsing address pool vip-pool:
invalid CIDR "192.168.0.100"
변경 전 NIC 교체 후
Webhook 호출 timeout Webhook 검증 응답 반환
요청·응답 통신 실패 Pool 주소 형식 오류 확인

이 응답으로 API Server와 webhook 사이의 왕복 통신 복구를 확인했다.

4. Pool 설정 수정

통신 복구 후 확인된 오류는 Pool 주소 형식이었다.

addresses:
  - "192.168.0.100"

이번에는 IP 범위로 수정했다.

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: vip-pool
  namespace: metallb
spec:
  addresses:
    - "192.168.0.100-192.168.0.110"
  autoAssign: true
***
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: vip-l2
  namespace: metallb
spec:
  ipAddressPools:
    - vip-pool
kubectl apply -f pool.yml

kubectl -n metallb get ipaddresspool,l2advertisement

이번 장애에서 관찰한 오류와 조치를 구분하면 다음과 같다.

구분 관찰 결과 조치 결과
VXLAN checksum 오류 UDP 수신 오류 카운터 증가 Offload 변경 후 증가 중단
Webhook timeout Master에서 controller Pod 접속 실패 VMXNET3 → E1000E 교체 후 복구
Pool 형식 오류 invalid CIDR 반환 IP 범위 형식으로 수정

이번 환경의 webhook timeout 해결책은 VMware 가상 NIC 교체였다.

정확한 내부 버그는 식별하지 못했지만, Offload 변경만으로는 해결되지 않았고 E1000E 교체 후 통신이 복구됐다.

Reference