지난 시간, 앤서블(Ansible)의 힘을 빌려 5대의 서버를 하나의 쿠버네티스 클러스터로 묶는 데 성공했습니다. 외부 트래픽을 통신하기 위해서는 'MetalLB' 와 'Ingress Nginx'가 필요합니다.
MetalLB 란?
외부 접속 IP(LoadBalancer IP)를 할당받을 수 있게 해주는 필수 도구입니다.
MetalLB는 크게 두 가지 방식으로 작동하지만, 홈랩에서는 Layer 2 (ARP/NDP) 모드를 주로 사용합니다. 다른 하나는 BGP 모드입니다. 쓰려면, BGP 프로토콜을 지원하는 고가의 L3 스위치나 라우터가 필요합니다.
- IP Pool 설정: 사용자님이 MetalLB에게 192.168.219.200 ~ 210 대역을 쓸 수 있다고 알려줍니다.
- IP 할당 (Controller): 사용자가 서비스를 생성하면, MetalLB의 Controller가 IP 하나(예: .200)를 꺼내 해당 서비스에 할당합니다.
- 주소 광고 (Speaker): 각 노드에 설치된 MetalLB Speaker가 공유기(네트워크)를 향해 소리칩니다.
- "여기요! 192.168.219.200번 찾는 패킷 있으면 저(k8s-worker-1)한테 보내세요!"
- 트래픽 수신: 공유기는 이 외침(ARP 응답)을 듣고, .200으로 가는 트래픽을 해당 노드로 보냅니다.
MetalLB는 두 가지 파드(Pod)로 구성됩니다.
- Controller (Deployment):
- IP를 관리하는 관리자입니다.
- 서비스가 생기면 "너는 200번 써", "너는 201번 써" 하고 IP를 배분합니다.
- Speaker (DaemonSet):
- 모든 노드에 하나씩 설치되는 "확성기"입니다.
- 실제로 네트워크에 ARP(IPv4) 패킷을 쏘면서 "이 IP 여기 있어요"라고 광고하는 역할을 합니다.
앤서블 플레이북
- Helm 설치: 쿠버네티스용 패키지 매니저인 helm을 마스터 노드에 설치합니다.
- MetalLB 설치: 가짜 로드밸런서 역할을 할 MetalLB를 설치합니다.
- MetalLB 설정 (IP Pool): 192.168.219.200 ~ 210 대역을 사용하도록 설정합니다.
- Ingress Nginx 설치: 웹 트래픽을 도메인별로 분배해 줄 인그레스 컨트롤러를 설치합니다.
addons.yaml 은 이렇게 작성 할 수 있습니다.
---
- name: Install Kubernetes Addons (MetalLB & Ingress-Nginx)
hosts: masters
become: yes
environment:
KUBECONFIG: /etc/kubernetes/admin.conf
tasks:
# 0. Helm 설치 (패키지 매니저)
- name: Download Helm installer
get_url:
url: https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
dest: /tmp/get_helm.sh
mode: '0700'
- name: Install Helm
shell: /tmp/get_helm.sh
args:
creates: /usr/local/bin/helm
# 1. MetalLB 설치 (LoadBalancer)
- name: Add MetalLB Helm Repo
shell: |
helm repo add metallb https://metallb.github.io/metallb
helm repo update
- name: Install MetalLB via Helm
shell: |
helm upgrade --install metallb metallb/metallb \
--namespace metallb-system \
--create-namespace \
--timeout 10m \
--wait
# 2. MetalLB 설정 (L2 모드 & IP Pool)
- name: Create MetalLB IPAddressPool & L2Advertisement
copy:
dest: /root/metallb-config.yaml
content: |
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 192.168.219.200-192.168.219.210
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: example
namespace: metallb-system
register: metallb_config
- name: Apply MetalLB Configuration
shell: kubectl apply -f /root/metallb-config.yaml
when: metallb_config.changed
# 3. Ingress Nginx 설치 (Traffic Controller)
- name: Add Ingress-Nginx Helm Repo
shell: |
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
- name: Install Ingress-Nginx via Helm
shell: |
helm upgrade --install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--create-namespace \
--set controller.service.type=LoadBalancer \
--set controller.service.externalTrafficPolicy=Local \
--timeout 10m
실행
ansible-playbook addons.yml

실행 중 위와 같은 오류가 생겼습니다.

metallb controller 가 CrashLoopBackOff 상태가 되었습니다. 다행히도 고쳤습니다... 정리해보자면
1. 현상 (Symptoms)
- MetalLB Controller 파드가 Running 상태가 되어도 로그가 Starting...에서 멈춘 채 진행되지 않음 (Webhook 호출 실패).
- 클러스터 내부에서 Service IP(10.96.0.1)로 curl 요청을 보내면 응답 없이 무한 대기(Hang/Timeout) 발생.
- Ping(ICMP)은 정상적으로 통신되지만, HTTP/TCP 데이터 통신만 불가능함.
- 방화벽(firewalld, nftables)을 모두 끄고, iptables를 초기화해도 증상이 동일함.
2. 원인 (Root Cause)
"미니 PC 랜카드(NIC)의 체크섬 오프로딩(Checksum Offloading) 버그"
- 배경: 사용 중인 하드웨어(Beelink, GMKtec 등)에 탑재된 리얼텍(Realtek) 또는 인텔(Intel) 컨슈머용 NIC는 CPU 부하를 줄이기 위해 '패킷 검증(Checksum)'을 하드웨어가 대신 수행하는 기능(Offloading)이 켜져 있습니다.
- 문제점: Rocky Linux(RHEL 계열 커널) 환경에서 Calico CNI가 사용하는 터널링 프로토콜(IPIP/VXLAN) 로 감싸진 패킷을 처리할 때, 이 랜카드가 체크섬 계산을 틀리게 하는 버그가 있습니다.
- 결과:
- 송신 측(Node)은 "잘 보냈다"고 생각하고 패킷을 보냄.
- 수신 측(Master)은 패킷을 받았으나 **"데이터가 깨졌다(Bad Checksum)"**고 판단.
- 수신 측 커널이 아무런 에러 메시지 없이 해당 패킷을 조용히 폐기(Silent Drop).
- 애플리케이션(Curl, MetalLB)은 응답이 오지 않아 무한정 기다림.
3. 해결 과정 (Troubleshooting Steps)
- 좀비 프로세스 제거: 웹훅 설정(ValidatingWebhookConfiguration)이 남아 통신을 방해하는지 확인 및 삭제.
- 네트워크 초기화: iptables -F, conntrack -F 등을 통해 꼬인 네트워크 규칙과 캐시 초기화.
- 방화벽 해제: Rocky Linux의 숨겨진 방화벽 nftables 비활성화 및 iptables 정책 ACCEPT로 변경.
- MTU 조절: 터널링 오버헤드를 고려해 MTU를 1440 -> 1200으로 줄였으나 해결되지 않음 (단순 크기 문제가 아님을 확인).
- 최종 해결: 랜카드의 TX Checksum Offloading 기능을 비활성화(ethtool -K eth0 tx off) 하자마자 즉시 통신 재개.
# 1. ethtool 설치 (혹시 없을 수 있으므로)
ansible all -m package -a "name=ethtool state=present" -b
# 2. 체크섬 오프로딩 끄기 (TX Checksumming Off)
ansible all -m shell -a "ethtool -K eth0 tx off" -b
# 3. rp_filter 보안 해제 (0 또는 2로 설정)
ansible all -m shell -a "sysctl -w net.ipv4.conf.all.rp_filter=2 && sysctl -w net.ipv4.conf.default.rp_filter=2" -b
# 4. NetworkManager 설정으로 체크섬 기능 영구 비활성화 (Rocky Linux)
ansible all -m shell -a "nmcli connection modify eth0 ethtool.feature-tx off" -b
# 5. rp_filter 설정 영구 저장
ansible all -m shell -a "echo 'net.ipv4.conf.default.rp_filter = 2' > /etc/sysctl.d/99-k8s-override.conf && echo 'net.ipv4.conf.all.rp_filter = 2' >> /etc/sysctl.d/99-k8s-override.conf && sysctl --system" -b

성공!
통신 테스트
# Ingress Nginx 서비스 상태 확인
kubectl get svc -n ingress-nginx


http://192.168.219.200 으로 접속하면 404 가 나온다. 이게 이렇게 그리울 수가..
'project > 본투비엔지니어' 카테고리의 다른 글
| [본투비엔지니어] 나에게 베어본만 주어진다면?? (10) (0) | 2026.02.01 |
|---|---|
| [본투비엔지니어] 나에게 베어본만 주어진다면?? (9) (0) | 2026.01.31 |
| [본투비엔지니어] 나에게 베어본만 주어진다면?? (7) (0) | 2026.01.29 |
| [본투비엔지니어] 나에게 베어본만 주어진다면?? (6) (0) | 2026.01.29 |
| [본투비엔지니어] 나에게 베어본만 주어진다면?? (5) (0) | 2026.01.28 |