Kubernetes 안의 VPN 클라이언트 IP: 보존할까 SNAT할까?
Kubernetes 안에서 VPN 클라이언트의 실제 주소를 보존할지 소스 NAT를 쓸지 세 가지 조건으로 고르고, 그다음 반환 경로와 pod 교체를 검증합니다.
터널과 backend 사이 어딘가에서 클라이언트 주소는 살아남거나 교체되며, 두 결과 모두 정당화할 수 있습니다. 선택은 받는 서비스의 소유자 몫이지 CNI를 설치한 사람 몫이 아닙니다. 클라이언트별 인가, 쿼터, 감사 기록이 중요하면 주소는 모든 홉을 통과해야 합니다. 공유 귀속으로 충분하면 소스 NAT는 그렇지 않으면 영원히 유지해야 할 라우팅 문제를 없앱니다.
클라이언트 주소가 실제로 사라지는 곳
원격 클라이언트의 패킷은 터널 범위 안의 내부 소스, 예를 들어 10.90.0.42를 가지고 VPN pod에 도착합니다. pod가 그 패킷을 ClusterIP나 pod IP로 전달할 때 세 가지 다른 메커니즘이 소스를 다시 쓸 수 있습니다. 노드의 CNI masquerade 규칙은 pod가 클러스터 CIDR 밖으로 보내는 트래픽을 담당합니다. 목적지 노드의 kube-proxy conntrack 항목은 Service 홉 자체를 담당합니다. 연결을 끝내는 프록시는 패킷을 아예 전달하지 않으므로 결국 보이는 소스는 프록시의 것입니다.
각각 다른 계층에 살기 때문에 Service 필드 하나로 전체 경로가 고쳐지는 일은 거의 없습니다.
VPN의 공개 Service에서 externalTrafficPolicy는 바깥 연결만 결정합니다. Local는 받은 노드에 원격 주소를 남기고, Cluster는 kube-proxy가 패킷을 다른 노드로 넘겨 거기서 masquerade 하게 합니다. 그 설정이 클라이언트가 접속하는 리스너를 지배합니다. VPN 프로세스가 나중에 클러스터로 보내는 복호화된 패킷에 대해서는 아무 말도 하지 않습니다.
논쟁을 끝내는 세 가지 조건
이 주제가 나올 때마다 같은 세 질문을 같은 순서로 던집니다. 첫 질문으로 논의가 끝나는 경우가 많기 때문입니다. 답은 개별 워크로드에 맞춰야 하고 클러스터 전체에 맞추면 안 됩니다. 한 회사 안의 두 클러스터가 서로 다른 답에 도달할 수 있고 둘 다 옳을 수 있습니다.
| Question | Preserve | SNAT |
|---|---|---|
| Does the backend enforce policy per client? | Yes, the address is the identity | Only if a trusted proxy supplies identity |
| Can the cluster route 10.90.0.0/24 back to a stable gateway? | Required | Not needed |
| Is the workload a forwarder or a proxy? | Forwarder | Proxy is fine |
backend가 첫 질문에 예, 둘째에 아니오라고 답하면 필요한 것은 manifest 편집이 아니라 네트워크 작업입니다. 셋째 줄이 프록시라고 하면 그 주소는 애초에 살아남지 못했을 것이고, 반대로 가장하는 데는 일주일의 패킷 캡처가 듭니다.
preserve 모드가 네트워크에 요구하는 것
소스를 보존한다는 것은 목적지 노드가 활성 VPN 게이트웨이를 통해 10.90.0.42로 트래픽을 되돌려 보내야 한다는 뜻입니다. VPN 풀은 클러스터 CIDR이 아니므로 어떤 CNI도 기본적으로 이를 라우팅하지 않습니다. 경로를 직접 추가하고, 그것이 가리키는 게이트웨이 끝점이 재스케줄링을 견디는지 확인합니다.
ip route add 10.90.0.0/24 via 10.244.3.17 dev eth0
sysctl -w net.ipv4.conf.eth0.rp_filter=2
그다음 홉은 pod 주소이고 pod 주소는 움직입니다. 경로를 Service VIP나 제자리에 남는 노드 주소로 돌리거나, 퇴출 때마다 게이트웨이를 쫓아다닐 것을 받아들이십시오. 역경로 필터링도 함정입니다. strict 모드는 도착한 인터페이스와 반환 경로가 맞지 않는 패킷을 버리는데, 이것이 바로 보존된 VPN 흐름의 모양입니다.
느슨한 검증은 동작하는 반환 경로와 backend를 떠난 뒤 사라지는 응답 사이의 차이인 경우가 많습니다. VPN 노드의 masquerade 규칙도 터널 범위를 제외해야 합니다. 그렇지 않으면 어떤 경로를 세웠든 전달된 패킷은 pod 주소로 나갑니다. 이 제외는 iptables를 손으로 고치는 대신 CNI 자체 설정에서 표현하십시오. 에이전트는 재시작 때 체인을 다시 쓰고, 손으로 쓴 규칙은 다음 업그레이드까지만 유지됩니다.
NetworkPolicy는 접근 제어이지 라우팅이 아닙니다. 정책을 조여도 masquerade가 이미 바꾼 주소는 돌아오지 않습니다.
SNAT의 비용과 그것을 적어 두는 방법
클러스터 쪽 소스 NAT는 더 싼 설계이고 실수가 아닙니다. backend는 VPN pod나 노드 주소를 보고 로그는 서로 맞으며 반환 경로가 존재할 필요가 없습니다. 잃는 것은 두 클라이언트를 네트워크 계층에서 구별하는 능력이므로 쿼터, 차단, 감사 흔적은 다른 곳에서 와야 합니다.
보통 그 다른 곳은 애플리케이션입니다. 세션 토큰, 서명된 헤더, 또는 직접 관리하는 프록시가 쓰는 PROXY 프로토콜 줄입니다. 이것들은 프록시가 경로에 있고 헤더를 클라이언트 쪽에서 설정할 수 없을 때만 수신자에게 믿을 수 있는 신원을 줍니다. runbook에서 어느 것이 적용되는지 분명히 적으십시오. 다음 엔지니어는 로그의 주소가 클라이언트라고 가정할 것이기 때문입니다. 그렇지 않고, 사고 한 번이면 그 가정은 비싸집니다.
적어 두는 한 이 교환은 정직하게 남습니다.
동작하는 경로와 운 좋은 경로를 가르는 점검
캐시된 연결이 아니라 새 연결로 시험하고 양방향으로 시험하십시오. 여러 장애가 간헐적으로 보이는 것은 새 흐름이 다시 쓴 경로를 타기 때문일 뿐입니다.
승인된 요청 하나가 진행되는 동안 tuple을 세 지점에서 잡으십시오. 캡슐화 해제 직후, VPN pod의 egress 인터페이스, 그리고 backend입니다. 소스가 둘째와 셋째 캡처 사이에서 바뀌면 원인은 pod 아래에 있습니다. 둘째보다 먼저 바뀌면 pod 자신이 변환하고 있습니다.
다음으로 VPN pod를 삭제하고 재스케줄링되는 동안 테스트를 반복하십시오. 퇴출에서 끊기는 보존 경로는 미완성이고, 더 이상 존재하지 않는 주소에 고정된 NAT 규칙도 마찬가지입니다. 마지막으로 거부될 것으로 예상하는 소스에서 요청 하나를 보내고, 거부가 빠진 경로가 아니라 정책에서 오는지 확인하십시오.