cilium에서는 egress gateway를 지원하는데 별도의 파드가 뜨는 방식이 아닌 노드를 egress 노드로 만들어서 해당 노드에 설정되어있는 아이피로 변환시키는 방법을 사용합니다.
한번 직접 테스트를 해보도록 하겠습니다.
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
- role: worker
networking:
disableDefaultCNI: true # kind cni 설치 안하기
kubeProxyMode: "none" # kube-proxy 설치 안하게 하기
바로 kind로 클러스터 생성하고 cilium도 설치해 줍니다.
API_SERVER=$( kubectl get nodes -l node-role.kubernetes.io/control-plane -o yaml | yq '.items[0].status.addresses[] | select(.type=="InternalIP").address' )
helm install cilium cilium/cilium --version 1.17.1 \
--namespace kube-system \
--set k8sServiceHost=${API_SERVER} \
--set k8sServicePort=6443 \
--set egressGateway.enabled=true \
--set bpf.masquerade=true \
--set kubeProxyReplacement=true
cilium 상태를 확인해주겠습니다.
# 정상이 될때까지 기다리기
cilium status --wait
상태가 정상이 되었다면 이제 테스트 용도의 파드를 생성하겠습니다.
이 파드가 뜨지 않은 곳을 egress 노드로 만들기 위해 테스트 파드 부터 띄우겠습니다.
kubectl create -f https://raw.githubusercontent.com/cilium/cilium/1.17.1/examples/kubernetes-dns/dns-sw-app.yaml
이제 egress gateway노드로 만들 노드를 설정합니다.
파드가 뜨지 않은 노드에 egress gateway라는 라벨을 붙여줍니다.
kubectl label nodes aya-worker egress-node=true
이제 이 테스트 파드에서 외부로 호출을 테스트하기 위해 테스트용 컨테이너를 하나 띄우겠습니다.
kind로 만든 클러스터와 통신이 되게 하기 위해 network를 kind로 설정하여 생성합니다.
docker run -d --rm --name nginx --network kind nginx:latest
이제 어디서(출발지) 어떤 곳으로 가려고 할때 (목적지) egress gateway 노드의 아이피로 변환할 것인지 정책을 추가합니다.
apiVersion: cilium.io/v2
kind: CiliumEgressGatewayPolicy
metadata:
name: egress-sample
spec:
selectors:
- podSelector:
matchLabels:
# default 네임스페이스에 있는
io.kubernetes.pod.namespace: default
# 아래의 라벨이 붙은 파드들로부터
org: empire
class: mediabot
# (옵션) 위의 조건에 맞는 파드들 중에서도 특정 노드에 뜬 파드를 고를 수 있음
# 선택하지 않는 경우 모든 노드의 뜬 파드들이 골라짐
nodeSelector:
matchLabels:
node.kubernetes.io/name: node1
# 어떤 곳으로 갈 때 egress gateway를 거치게 된다.
destinationCIDRs:
- "0.0.0.0/0"
# egress gateway는 아래의 라벨에 매칭 되는 곳을 egress gateway 노드로 사용한다
egressGateway:
nodeSelector:
matchLabels:
node.kubernetes.io/name: node2
# 정책에 의해 매칭된 트래픽의 출발지 주소를 변경할 아이피를 고정한다.
# 이 아이피는 노드의 인터페이스에 설정되어있어야 한다.
egressIP: 10.168.60.100
# 혹은 인터페이스를 설정할 수도 있는데
# 이렇게 되는경우 이 인터페이스에 할당된 첫 번째 ip로 변환된다.
# interface: enp0s8
위의 설정에서 destinationCIDRs를 먼저 생성한 nginx컨테이너의 아이피로 변경하고 egressIP에 egress노드의 아이피로 변경하여 생성합니다.
docker inspect nginx | jq '.[0].NetworkSettings.Networks.kind.IPAddress' -r
환경에 맞춰서 구성한 설정의 예시입니다.
apiVersion: cilium.io/v2
kind: CiliumEgressGatewayPolicy
metadata:
name: egress-sample
spec:
selectors:
- podSelector:
matchLabels:
io.kubernetes.pod.namespace: default
org: empire
class: mediabot
destinationCIDRs:
- "192.168.97.6/32"
egressGateway:
nodeSelector:
matchLabels:
egress-node: "true"
egressIP: 192.168.97.3
잘 구성이 되었습니다.
cilium 파드에들어가서 룰을 확인해보면 egress 노드가 설정된 곳에서는 egress IP가 보이고 egresss 노드가 설정되어잇지 않은 곳에서는 gateway로 가서 나가도록 설정이 되는 것을 확인할 수 있습니다.
# egress 노드에서 확인
root@aya-worker:/home/cilium# cilium bpf egress list
Source IP Destination CIDR Egress IP Gateway IP
10.0.0.56 192.168.97.6/32 192.168.97.3 192.168.97.3
# egress 노드가 아닌 곳에서 확인
root@aya-worker2:/home/cilium# cilium bpf egress list
Source IP Destination CIDR Egress IP Gateway IP
10.0.0.56 192.168.97.6/32 0.0.0.0 192.168.97.3
실제로 nginx를 호출했을 때 다음과 같이 egressIP로 변경되어 로그에 찍히는것을 확인할 수 있습니다.
192.168.97.3은 aya-worker로 egress노드의 아이피입니다.
hubble로 확인해보기
마지막으로 hubble로도 확인해보도록 하겠습니다.
helm upgrade cilium cilium/cilium --version 1.17.1 \
--namespace kube-system \
--reuse-values \
--set hubble.relay.enabled=true \
--set hubble.ui.enabled=true
여기 UI에 나오는 값은 identity로 정해진게 보이는 듯 한데 world를 다른걸로 바꿀 방법이 안보인다. ㅠㅠ
'K8S > cilium' 카테고리의 다른 글
Maglev: Google의 로드밸런싱 알고리즘 (0) | 2024.10.03 |
---|---|
cilium의 메트릭 정보 켜보기 (0) | 2024.10.03 |
cilium 선택적 서비스 노드 노출하기 (0) | 2024.09.28 |
Cilium 최적화하기: irqbalance 중지 후 cpu pinning하기 (1) | 2024.09.26 |
cilium 테스트용 로컬 환경 구성하기 (1) | 2024.08.26 |