nftables masquerade 로 공유기 만들기 — 포트포워딩·conntrack, 그리고 NAT 는 방화벽이 아니다
집 공유기가 하는 일을 리눅스 한 대로 재현한다. 사설 주소로 인터넷에 나가지 못하는 이유, nftables masquerade(SNAT)와 포트포워딩(DNAT), conntrack 표, 그리고 NAT 만으로는 집 안이 지켜지지 않는다는 것을 직접 확인한다. 네트워크 처음 배우는 사람 기준.
nginx 리버스 프록시, 쿠버네티스 배포, RabbitMQ 큐·DLQ, Fluentd·OpenSearch 로그, tcpdump·nftables 네트워크 실습까지 서버와 인프라를 직접 만지며 남긴 기록.
집 공유기가 하는 일을 리눅스 한 대로 재현한다. 사설 주소로 인터넷에 나가지 못하는 이유, nftables masquerade(SNAT)와 포트포워딩(DNAT), conntrack 표, 그리고 NAT 만으로는 집 안이 지켜지지 않는다는 것을 직접 확인한다. 네트워크 처음 배우는 사람 기준.
리눅스 한 대 안에 가상 PC 두 대와 라우터를 만들어 서로 다른 네트워크를 잇는다. "Network is unreachable", 게이트웨이, ip_forward, 돌아오는 길, ARP, TTL 이 왜 필요한지 하나씩 빼 보며 확인한다. 네트워크 처음 배우는 사람 기준.
패킷이 뭔지 몰라도 따라 할 수 있게 썼다. curl 한 번이 만드는 TCP 패킷 10개를 tcpdump 로 잡아 한 줄씩 읽고, "Connection refused" 와 "Connection timed out" 이 패킷으로는 어떻게 다른지 직접 만들어 본다.
2초짜리 작업 20건을 한꺼번에 넣었더니 사용자는 최대 20초를 기다렸다. 처리 시간은 건마다 2.02초로 일정했고, 나머지는 전부 큐에서 줄 선 시간이었다. 로그에 wait_ms 를 남기고 OpenSearch Dashboards 로 둘을 나눠 보니 병목이 워커 수로 드러났고, 워커를 6개로 늘리자 큐 대기 p50 이 10.0초에서 2.0초가 됐다.
Fluentd 집계기 출력을 OpenSearch 로 바꿨더니 request_id 가 text 로 잡혀 trace-8th-0001 을 찾는데 다른 요청까지 44건이 나왔고, event 로 집계하자 "Text fields are not optimised" 로 거절됐다. 인덱스 템플릿으로 타입을 정하고, 집계기와 OpenSearch 를 지워도 로그가 남는지 쟀다.
OpenStack에서 볼륨을 만들어 인스턴스에 붙인 뒤, 인스턴스 안에서 lsblk로 확인하고 mkfs.ext4로 포맷해 fstab에 등록까지 — 재부팅해도 마운트가 풀리지 않게 만드는 순서.
ingress-nginx 는 요청마다 X-Request-ID 를 만들어 주는데, 앱 로그에는 그 번호가 한 줄도 없었다. 번호를 web 로그와 RabbitMQ 메시지의 correlation_id, worker 로그까지 넘겼더니 재시도 두 번에 DLQ 까지 간 요청 하나가 번호 하나로 15줄, 파드 5개에 걸쳐 이어졌다.
작업 하나의 로그 34줄이 파드 4개에 흩어져 있었고, web 로그의 56.9% 는 /healthz 였다. 노드마다 Fluentd forwarder 를 DaemonSet 으로 띄워 한곳의 aggregator 로 모았더니 지운 파드의 로그도 남았다. 대신 aggregator 가 바뀌자 쌓여 있던 581건이 사라졌다.
실패를 다시 할 것과 끝낼 것으로 나누고, TTL 과 데드레터만으로 5초·15초 재시도와 DLQ 를 만든다. 워커를 강제로 죽였더니 작업은 사라지지 않았지만 72.9초 뒤에야 돌아왔고, 평범하게 내렸더니 python 이 PID 1 이라 SIGTERM 을 무시해 31.2초가 걸렸다.
동기 호출을 RabbitMQ 큐로 바꿨더니 죽은 주소가 섞여도 접수가 24ms 에 끝났다. 대신 결과 조회가 404 를 내며 실패했다. 파드가 여럿일 때 상태를 메모리에 두면 생기는 일과, 큐가 대기를 없애는 게 아니라 옮긴다는 점까지 실측으로 짚는다.