cluster mesh 설치
cluster mesh 를 통해 여러 개의 독립적인 쿠버네티스 클러스터를 하나의 논리적인 네트워크로 연결하여 통합 관리할 수 있습니다.
실습으로 간단히 알아볼 예정이므로 kind 라는 로컬 쿠버네티스 클러스터를 구성할 수 있는 도구를 활용할 예정입니다.
kind
kind is a tool for running local Kubernetes clusters using Docker container “nodes”. kind was primarily designed for testing Kubernetes itself, but may be used for local development or CI. If you have go 1.17+ and docker, podman or nerdctl installed go
kind.sigs.k8s.io
https://kind.sigs.k8s.io/docs/user/quick-start/#installation 페이지를 참고하여, 각 운영체제에 맞게 kind 를 설치해줍니다.
# west 클러스터 설정
kind create cluster --name west --image kindest/node:v1.33.2 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 30000 # sample apps
hostPort: 30000
- containerPort: 30001 # hubble ui
hostPort: 30001
- role: worker
extraPortMappings:
- containerPort: 30002 # sample apps
hostPort: 30002
networking:
podSubnet: "10.0.0.0/16"
serviceSubnet: "10.2.0.0/16"
disableDefaultCNI: true
kubeProxyMode: none
EOF
# east 클러스터 설정
kind create cluster --name east --image kindest/node:v1.33.2 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 31000 # sample apps
hostPort: 31000
- containerPort: 31001 # hubble ui
hostPort: 31001
- role: worker
extraPortMappings:
- containerPort: 31002 # sample apps
hostPort: 31002
networking:
podSubnet: "10.1.0.0/16"
serviceSubnet: "10.3.0.0/16"
disableDefaultCNI: true
kubeProxyMode: none
EOF
Cluster 객체를 통해 control-plane 노드와 worker 노드를 생성합니다. 아래 클러스터 주소 지정 요구사항을 참고하여 노드를 생성 시, podCIDR 대역과 serviceSubnet 이 겹치지 않도록 설정해야 합니다.
클러스터 주소 지정 요구 사항
- 모든 클러스터는 동일한 데이터 경로 모드를 설정해야 합니다. (캡슐화 또는 네이티브 라우팅 모드)
- 모든 클러스터의 PodCIDR 범위는 충돌하지 않고 고유한 IP 주소여야 합니다.
- 모든 클러스터의 노드는 각 노드에 구성된 InternalIP를 사용하여 서로 IP 연결을 유지해야 합니다.
- 클러스터 간 네트워크는 클러스터 간 통신을 허용해야 합니다.
# west 클러스터 설정
cilium install --version 1.17.6 --set ipam.mode=kubernetes \
--set kubeProxyReplacement=true --set bpf.masquerade=true \
--set endpointHealthChecking.enabled=false --set healthChecking=false \
--set operator.replicas=1 --set debug.enabled=true \
--set routingMode=native --set autoDirectNodeRoutes=true --set ipv4NativeRoutingCIDR=10.0.0.0/16 \
--set ipMasqAgent.enabled=true --set ipMasqAgent.config.nonMasqueradeCIDRs='{10.1.0.0/16}' \
--set cluster.name=west --set cluster.id=1 \
--context kind-west
# east 클러스터 설정
cilium install --version 1.17.6 --set ipam.mode=kubernetes \
--set kubeProxyReplacement=true --set bpf.masquerade=true \
--set endpointHealthChecking.enabled=false --set healthChecking=false \
--set operator.replicas=1 --set debug.enabled=true \
--set routingMode=native --set autoDirectNodeRoutes=true --set ipv4NativeRoutingCIDR=10.1.0.0/16 \
--set ipMasqAgent.enabled=true --set ipMasqAgent.config.nonMasqueradeCIDRs='{10.0.0.0/16}' \
--set cluster.name=east --set cluster.id=2 \
--context kind-east
CNI 네트워크 플러그인 cilium 을 설정해줍니다.
cluster mesh 로 각각의 클러스터들을 묶기 위해서 cluster.name 옵션곽 cluster.id 값을 유니크하게 지정해주어야 합니다.
네트워크 설정 시, 보통은 podCIDR 대역을 노드의 라우팅 테이블에 넣어주어야 하는데 native routing 모드이고 cluster mesh 를 구성할 때 자동으로 라우팅을 주입해줍니다. 노드 OS 라우팅 테이블에 라우팅이 되어 있지 않은데도 통신이 정상적으로 됩니다.
하지만 하나 체크할 것이 있습니다. cilium 에서 내부 통신할 때, 인증서 기반으로 통신을 하는데 지금 개별 설치를 진행했기 때문에 한 쪽에 있는 인증서 정보로 맞춰주는 작업이 필요합니다.
# east 에 있는 ca 정보를 삭제하고,
keast delete secret -n kube-system cilium-ca
# west 에 있는 ca 정보를 복사해서 east ca 에 복사합니다.
kubectl --context kind-west get secret -n kube-system cilium-ca -o yaml | \
kubectl --context kind-east create -f -
cluster mesh 구성
일단 cluster mesh 로 서로 간의 정보를 주고 받는 컨트롤 플레인의 역할을 설정해주어야 합니다. 여기서는 간단한 실습 환경을 구성하기 위해 서비스 타입을 NodePort 로 진행합니다.
cilium clustermesh enable --service-type NodePort --enable-kvstoremesh=false --context kind-west
cilium clustermesh enable --service-type NodePort --enable-kvstoremesh=false --context kind-east

NodePort 서비스 타입으로 생성하면 clustermesh 와 관련된 서비스와 파드 정보가 생성된 것을 확인할 수 있습니다.
cilium clustermesh connect --context kind-west --destination-context kind-east
이후 해당 명령어로 kind-west 와 kind-east 컨텍스트 정보를 연결하면 cluster mesh 구성이 완료됩니다.


OS 레벨 단에도 라우팅 정보가 자동으로 잘 들어간 것을 볼 수 있습니다.
cluster mesh 통신 확인
pod 통신 확인
cat << EOF | kubectl apply --context kind-west -f -
apiVersion: v1
kind: Pod
metadata:
name: curl-pod
labels:
app: curl
spec:
containers:
- name: curl
image: nicolaka/netshoot
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
cat << EOF | kubectl apply --context kind-east -f -
apiVersion: v1
kind: Pod
metadata:
name: curl-pod
labels:
app: curl
spec:
containers:
- name: curl
image: nicolaka/netshoot
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
west 와 east 사이에 pod 통신을 확인하기 위해서 예제 pod 를 생성합니다.


kind-west 에서 kind-east 의 curl-pod 로 ping 요청을 해보니 통신도 정상적으로 수행됩니다!
(NAT 없이 요청이 잘 되는 것을 볼 수 있습니다.)
Service 통신 확인
# west
cat << EOF | kubectl apply --context kind-west -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: webpod
spec:
replicas: 2
selector:
matchLabels:
app: webpod
template:
metadata:
labels:
app: webpod
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- sample-app
topologyKey: "kubernetes.io/hostname"
containers:
- name: webpod
image: traefik/whoami
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: webpod
labels:
app: webpod
annotations:
service.cilium.io/global: "true"
spec:
selector:
app: webpod
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
EOF
# east
cat << EOF | kubectl apply --context kind-east -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: webpod
spec:
replicas: 2
selector:
matchLabels:
app: webpod
template:
metadata:
labels:
app: webpod
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- sample-app
topologyKey: "kubernetes.io/hostname"
containers:
- name: webpod
image: traefik/whoami
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: webpod
labels:
app: webpod
annotations:
service.cilium.io/global: "true"
spec:
selector:
app: webpod
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
EOF
west 와 east 사이에 service 통신을 확인하기 위해서 예제 pod 및 service 를 생성합니다.
service 생성 시, metadata.annotations 에 service.cilium.io/global: "true" 옵션을 활성화해야 service mesh 로 동작하게 됩니다.



west 나 east 의 어떠한 서비스 IP 로 호출하더라도 모든 west 와 east 의 pod 엔드포인트 IP 가 호출될 수 있음을 확인할 수 있습니다.
Service Session Affinity 설정
west 와 east 두 지역에 모두 통신이 가능함은 확인하였지만, 한 지역(west, east) 으로 트래픽을 우선하게 보내도록 할 수도 있습니다.
# Session Affinity Local 설정
kwest annotate service webpod service.cilium.io/affinity=local --overwrite
kwest describe svc webpod | grep Annotations -A3
keast annotate service webpod service.cilium.io/affinity=local --overwrite
keast describe svc webpod | grep Annotations -A3

affinity 설정을 보면 자기 자신의 pod endpoint ip 들이 preferred 설정된 것을 볼 수 있습니다. 자기 자신의 pod 대역들에게 우선으로 트래픽을 보낸다는 뜻입니다.
'인프라 > 쿠버네티스' 카테고리의 다른 글
| [cilium] k8s / cilium 성능 테스트 (0) | 2025.08.30 |
|---|---|
| [cilium] Ingress / Gateway API (0) | 2025.08.23 |
| [cilium] BGP 설정 방법 (1) | 2025.08.15 |
| [cilium] cilium 의 LoadBalancer 서비스 (2) | 2025.08.09 |
| [cilium] Overlay Network (1) | 2025.08.09 |