마스커레이딩
마스커레이딩 (Masquerading)
Pod에 사용되는 IPv4 주소는 보통 RFC1918 사설 주소 블록에서 할당되어 공개적으로 라우팅되지 않아요. Cilium은 클러스터를 떠나는 모든 트래픽의 소스 IP 주소를 노드의 IPv4 주소로 자동 마스커레이드합니다. 이 글에서는 구성 방법과 eBPF 기반·iptables 기반 구현 모드를 알아볼게요.
출처: Masquerading
본문
Pod에 사용되는 IPv4 주소는 보통 RFC1918 사설 주소 블록에서 할당되므로 공개적으로 라우팅되지 않습니다. 노드의 IP 주소는 네트워크에서 이미 라우팅 가능하므로, Cilium은 클러스터를 떠나는 모든 트래픽의 소스 IP 주소를 노드의 IPv4 주소로 자동 마스커레이드해요.
이 동작은 호스트를 떠나는 IPv4 트래픽에 대해 enable-ipv4-masquerade: false , IPv6 트래픽에 대해 enable-ipv6-masquerade: false 옵션으로 비활성화할 수 있습니다.
구성
라우팅 가능한 CIDR 설정
기본 동작은 로컬 노드의 IP 할당 CIDR 안의 목적지를 제외하는 것입니다. Pod IP가 더 넓은 네트워크에 걸쳐 라우팅 가능하다면, 그 네트워크를 ipv4-native-routing-cidr: 10.0.0.0/8 (IPv6 주소는 ipv6-native-routing-cidr: fd00::/100 ) 옵션으로 지정할 수 있으며, 이 경우 해당 CIDR 안의 모든 목적지는 마스커레이드되지 않아요.
퍼블릭 클라우드 환경에서 ipv4-native-routing-cidr 를 구성하지 않으면 Cilium은 VPC CIDR 범위를 네이티브 라우팅 범위로 자동 감지합니다. 엔드포인트가 NAT 없이 직접 통신하는 것이 가능하므로, Cilium은 네트워크에서 네이티브로 라우팅 가능한 트래픽의 소스 주소를 마스커레이드하지 않아요. 결과적으로 마스커레이딩이 활성화되면 같은 VPC 안의 다른 비-클러스터 리소스(예: 가상 머신)로의 Pod 트래픽은 소스 IP 주소를 마스커레이드하지 않고 직접 라우팅됩니다.
마스커레이딩 인터페이스 설정
마스커레이딩 인터페이스 구성은 #masq-modes Implementation Modes를 참고하세요.
원격 노드로의 트래픽 마스커레이드
BPF 마스커레이딩 모드에서 원격 노드로의 트래픽을 마스커레이드하려면 enable-remote-node-masquerade: "true" 옵션을 사용하세요. 이 옵션은 IPv4 트래픽을 SNAT하려면 enable-bpf-masquerade: "true" 와 함께 enable-ipv4-masquerade: "true" 또는 IPv6 주소를 위해 enable-ipv6-masquerade: "true" 가 필요합니다. 이 옵션은 Endpoint에서 원격 노드의 주소로 향하는 트래픽에만 영향을 주며, 서로 다른 노드의 Endpoint 간 트래픽에는 영향을 주지 않아요.
이 플래그는 현재 노드 InternalIP 주소로의 트래픽을 마스커레이드합니다. 이것은 미래에 바뀔 수 있어요. 이 주제에 대한 자세한 논의는 GitHub issue 35823과 GitHub issue 17177을 참고하세요.
이 옵션은 Pod에서 Node로의 트래픽에 대한 Cilium의 인그레스 호스트 방화벽 정책 적용 능력을 제한할 수 있어요. 이 옵션을 사용한다면, Endpoint가 Node와 통신하는 것을 막는 기본 거부 정책을 수립하고, 원격 노드(예: remote-node Entity)의 트래픽을 허용하는 정책 문 사용을 최소화하는 것을 고려하세요. 의심스러우면 이 옵션을 비활성화하세요.
구현 모드
eBPF 기반
Note
IPv6 BPF 마스커레이딩은 베타 기능입니다. 문제가 발생하면 피드백을 제공하고 GitHub 이슈를 올려주세요. IPv4 BPF 마스커레이딩은 프로덕션 준비가 되어 있어요.
eBPF 기반 구현은 가장 효율적인 구현입니다. bpf.masquerade=true helm 옵션으로 활성화할 수 있어요.
기본적으로 BPF 마스커레이딩은 BPF Host-Routing 모드도 활성화합니다. 이 모드의 이점과 한계는 eBPF Host-Routing을 참고하세요.
현재 구현은 BPF NodePort 기능에 의존합니다. 이 의존성은 미래에 제거될 것입니다 (GitHub issue 13732).
마스커레이딩은 eBPF 마스커레이딩 프로그램을 실행하는 장치에서만 수행될 수 있어요. 이는 Pod에서 외부 주소로 보내는 패킷이, 출력 장치가 프로그램을 실행한다면 (출력 장치 IPv4 주소로) 마스커레이드된다는 뜻입니다. 지정하지 않으면 프로그램은 BPF NodePort 장치 감지 메커니즘이 선택한 장치에 자동으로 연결됩니다. 수동으로 변경하려면 devices helm 옵션을 사용하세요. cilium status 를 사용해 프로그램이 어떤 장치에서 실행 중인지 확인할 수 있어요:
$ kubectl -n kube-system exec ds/cilium -- cilium-dbg status | grep Masquerading
Masquerading: BPF (ip-masq-agent) [eth0, eth1] 10.0.0.0/16
위 출력에서 프로그램은 eth0 과 eth1 장치에서 실행 중입니다.
eBPF 기반 마스커레이딩은 다음 L4 프로토콜의 패킷을 마스커레이드할 수 있어요:
- TCP
- UDP
- ICMP
Note
ICMP의 경우 지원은 Echo request, Echo reply, 그리고 "목적지 도달 불가, 단편화 필요, 그리고 DF 플래그 설정(Destination unreachable, fragmentation required, and DF flag set)" 오류 메시지로 제한됩니다.
기본적으로 ipv4-native-routing-cidr 범위 밖의 IP 주소로 향하는 Pod의 모든 패킷은 마스커레이드되며, 다른 클러스터 노드로 향하는 패킷은 예외입니다 (IPv6는 ipv6-native-routing-cidr 와 동일). 앞선 출력은 cilium status 의 제외 CIDR( 10.0.0.0/16 )을 보여 줍니다.
Note
eBPF 마스커레이딩이 활성화되면 Pod에서 클러스터 노드의 External IP로의 트래픽도 마스커레이드되지 않습니다. eBPF 구현은 이 측면에서 iptables 기반 마스커레이딩과 다릅니다. 이 한계는 GitHub issue 17177에서 추적됩니다.
더 세밀한 제어를 허용하기 위해 Cilium은 eBPF에서 ip-masq-agent를 구현하며, ipMasqAgent.enabled=true helm 옵션으로 활성화할 수 있어요.
eBPF 기반 ip-masq-agent는 구성 파일에 설정된 nonMasqueradeCIDRs , masqLinkLocal , masqLinkLocalIPv6 옵션을 지원합니다. Pod에서 nonMasqueradeCIDRs 의 어떤 CIDR에 속하는 목적지로 보내는 패킷은 마스커레이드되지 않습니다. 구성 파일이 비어 있으면 에이전트는 다음 non-masquerade CIDR을 프로비저닝합니다:
10.0.0.0/8172.16.0.0/12192.168.0.0/16100.64.0.0/10192.0.0.0/24192.0.2.0/24192.88.99.0/24198.18.0.0/15198.51.100.0/24203.0.113.0/24240.0.0.0/4
또한 masqLinkLocal 이 설정되지 않거나 false이면 169.254.0.0/16 이 non-masquerade CIDR 목록에 추가됩니다. IPv6의 경우 masqLinkLocalIPv6 가 설정되지 않거나 false이면 fe80::/10 이 추가됩니다.
에이전트는 Fsnotify를 사용해 구성 파일의 업데이트를 추적하므로, 원래의 resyncInterval 옵션은 필요 없습니다.
아래 예시는 ConfigMap으로 에이전트를 구성하고 검증하는 방법을 보여 줍니다.
apiVersion: v1
kind: ConfigMap
metadata:
name: ip-masq-agent
data:
config: |
nonMasqueradeCIDRs:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
masqLinkLocal: true
$ kubectl create -n kube-system -f https://raw.githubusercontent.com/cilium/cilium/1.20.2/examples/kubernetes-ip-masq-agent/rfc1918.yaml
$ # Wait ~60s until the ConfigMap is propagated into the configuration file
$ kubectl -n kube-system exec ds/cilium -- cilium-dbg bpf ipmasq list
IP PREFIX/ADDRESS
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
대안으로 Helm으로 Cilium을 설치할 때 --set ipMasqAgent.config.nonMasqueradeCIDRs='{10.0.0.0/8,172.16.0.0/12,192.168.0.0/16}' 와 --set ipMasqAgent.config.masqLinkLocal=false (또는 IPv6의 경우 해당 옵션)를 전달해 ip-masq-agent 를 위와 같이 구성할 수 있습니다.
iptables 기반
이것은 모든 커널 버전에서 동작하는 레거시 구현입니다.
기본 동작은 비-Cilium 네트워크 장치에서 떠나는 모든 트래픽을 마스커레이드하는 것입니다. 이는 보통 올바른 동작으로 이어져요. 마스커레이딩이 수행될 네트워크 인터페이스를 제한하려면 egress-masquerade-interfaces: eth0 옵션을 사용할 수 있어요.
Note
eth+ 를 지정하면 인터페이스 접두사도 지정할 수 있으며, eth 접두사와 일치하는 모든 인터페이스가 마스커레이딩에 사용됩니다.
라우팅 계층이 목적지 CIDR에 따라 다른 소스 주소를 선택하는 고급 경우에는 enable-masquerade-to-route-source: "true" 옵션을 사용해 기본 인터페이스 주소 대신 소스 주소로 마스커레이드할 수 있어요. 경로로 겹치는 목적지 CIDR이 있는 경우, 생성된 iptables 규칙은 라우팅 테이블의 최장 프리픽스 일치 조회를 시뮬레이션하기 위해 목적지 네트워크 마스크를 내림차순으로 정렬됩니다.
enable-masquerade-to-route-source: "true" 옵션을 사용하면, egress-masquerade-interfaces 가 비어 있을 때 Cilium이 기본적으로 devices 필드에 나열된 인터페이스를 egress 마스커레이드 인터페이스로 사용합니다. egress-masquerade-interfaces 가 설정되면, devices 보다 우선해 어떤 네트워크 인터페이스가 마스커레이딩을 수행할지 선택합니다. egress-masquerade-interfaces 를 eth+ ens+ 처럼 설정해 여러 인터페이스와 일치시킬 수 있어요.