DevOps/Study

Cilium Study [1기] 5주차 ClusterMesh

juyeon22 2025. 8. 17. 00:42

Cilium Study [1기] 5주차 ClusterMesh

안녕하세요 이번 게시물에서는 ClusterMesh 라는 주제에 대한 정보를 전달 드리고자 합니다.

1. 실습 환경 구성

Kind를 이용해서 실습 환경을 구성합니다.

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

docker exec -it west-control-plane sh -c 'apt update && apt install tree psmisc lsof wget net-tools dnsutils tcpdump ngrep iputils-ping git -y'
docker exec -it west-worker sh -c 'apt update && apt install tree psmisc lsof wget net-tools dnsutils tcpdump ngrep iputils-ping git -y'

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

docker exec -it east-control-plane sh -c 'apt update && apt install tree psmisc lsof wget net-tools dnsutils tcpdump ngrep iputils-ping git -y'
docker exec -it east-worker sh -c 'apt update && apt install tree psmisc lsof wget net-tools dnsutils tcpdump ngrep iputils-ping git -y'

# alias 설정
alias kwest='kubectl --context kind-west'
alias keast='kubectl --context kind-east'
# cilium CLI 설치
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
if [ "$(uname -m)" = "aarch64" ]; then CLI_ARCH=arm64; fi
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
sha256sum --check cilium-linux-${CLI_ARCH}.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/bin
rm cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}


# cilium cli 로 cilium cni 설치
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

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

2. Cluster Mesh 구성

Native Routing + 같은 네트워크 내에서 ClusterMesh 설정 시 자동으로 라우팅이 주입이 됩니다.

상대방의 k8s cluster와 통신을 하기 위해서는 Node별 PodCIDR에 대한 정보를 알고 있어야 하지만, 같은 네트워크 내에서 BGP를 사용하지 않고 Cluster Mesh를 사용하는 경우 자동으로 주입이 됩니다.

Cluster Mesh 연결


# East CA를 West CA와 동기화 작업 진행
keast get secret -n kube-system cilium-ca
keast delete secret -n kube-system cilium-ca

kubectl --context kind-west get secret -n kube-system cilium-ca -o yaml | \
kubectl --context kind-east create -f -


# 모니터링 : 신규 터미널 2개
cilium clustermesh status --context kind-west --wait  
cilium clustermesh status --context kind-east --wait


# Enable 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


kwest get svc,ep -n kube-system clustermesh-apiserver --context kind-west
# NAME                            TYPE       CLUSTER-IP   EXTERNAL-IP   PORT(S)          AGE
# service/clustermesh-apiserver   NodePort   10.2.29.72   <none>        2379:32379/TCP   2m3s

# NAME                              ENDPOINTS         AGE
# endpoints/clustermesh-apiserver   10.0.1.216:2379   2m3s


keast get svc,ep -n kube-system clustermesh-apiserver --context kind-east
# NAME                            TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
# service/clustermesh-apiserver   NodePort   10.3.11.145   <none>        2379:32379/TCP   3m36s

# NAME                              ENDPOINTS         AGE
# endpoints/clustermesh-apiserver   10.1.1.122:2379   3m36s

# 클러스터 간 연결
cilium clustermesh connect --context kind-west --destination-context kind-east

# ✨ Extracting access information of cluster west...
# 🔑 Extracting secrets from cluster west...
# ⚠️  Service type NodePort detected! Service may fail when nodes are removed from the cluster!
# ℹ️  Found ClusterMesh service IPs: [172.18.0.3]
# ✨ Extracting access information of cluster east...
# 🔑 Extracting secrets from cluster east...
# ⚠️  Service type NodePort detected! Service may fail when nodes are removed from the cluster!
# ℹ️  Found ClusterMesh service IPs: [172.18.0.5]
# ℹ️ Configuring Cilium in cluster kind-west to connect to cluster kind-east
# ℹ️ Configuring Cilium in cluster kind-east to connect to cluster kind-west
# ✅ Connected cluster kind-west <=> kind-east!

# 라우팅 정보 확인 : 클러스터간 PodCIDR 라우팅 주입 확인!
docker exec -it west-control-plane ip -c route
docker exec -it west-worker ip -c route
docker exec -it east-control-plane ip -c route
docker exec -it east-worker ip -c route

# 10.0.1.0/24 via 172.18.0.2 dev eth0 proto kernel
# 10.1.0.0/24 via 172.18.0.5 dev eth0 proto kernel
# 10.1.1.0/24 via 172.18.0.4 dev eth0 proto kernel

hubble 설치

helm upgrade cilium cilium/cilium --version 1.17.6 --namespace kube-system --reuse-values \
--set hubble.enabled=true --set hubble.relay.enabled=true --set hubble.ui.enabled=true \
--set hubble.ui.service.type=NodePort --set hubble.ui.service.nodePort=30001 --kube-context kind-west

kwest -n kube-system rollout restart ds/cilium


helm upgrade cilium cilium/cilium --version 1.17.6 --namespace kube-system --reuse-values \
--set hubble.enabled=true --set hubble.relay.enabled=true --set hubble.ui.enabled=true \
--set hubble.ui.service.type=NodePort --set hubble.ui.service.nodePort=31001 --kube-context kind-east

keast -n kube-system rollout restart ds/cilium

# hubble-ui 접속
wslview http://localhost:30001
wslview http://localhost:31001

West <-> East 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

kwest get pod -owide && keast get pod -owide
# NAME       READY   STATUS    RESTARTS   AGE    IP           NODE          NOMINATED NODE   READINESS GATES
# curl-pod   1/1     Running   0          116s   10.0.1.252   west-worker   <none>           <none>
# NAME       READY   STATUS    RESTARTS   AGE    IP          NODE          NOMINATED NODE   READINESS GATES
# curl-pod   1/1     Running   0          115s   10.1.1.11   east-worker   <none>           <none>

# 통신
kubectl exec -it curl-pod --context kind-west -- ping 10.1.1.11

Figure 2.1 Hubble 확인

Load-balancing & Service Discovery

West, East Cluster에 샘플 Application 을 배포하여 확인해보겠습니다.


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


#
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 to East service list 확인
kwest exec -it -n kube-system ds/cilium -c cilium-agent -- cilium service list --clustermesh-affinity
# 13   10.2.157.165:80/TCP    ClusterIP      1 => 10.0.1.31:80/TCP (active)
#                                            2 => 10.0.1.69:80/TCP (active)
#                                            3 => 10.1.1.241:80/TCP (active)
#                                            4 => 10.1.1.178:80/TCP (active)

# East to West service list 확인
keast exec -it -n kube-system ds/cilium -c cilium-agent -- cilium service list --clustermesh-affinity
# 13   10.3.83.188:80/TCP     ClusterIP      1 => 10.0.1.69:80/TCP (active)
#                                            2 => 10.0.1.31:80/TCP (active)
#                                            3 => 10.1.1.241:80/TCP (active)
#                                            4 => 10.1.1.178:80/TCP (active)

Service Affinity

트래픽 인입 시 service.cilium.io/affinity=loca Annotation을 사용해서 인입된 트래픽을 Cluster(Local)로 우선 인입 시킬 수 있습니다.

인입된 Cluster에 Replica 가 0인 경우에는 Preferred 옵션이기 때문에, Replica가 존재하는 Cluster로 트래픽이 인입됩니다.

반대로 service.cilium.io/affinity=remote Annotaion을 이용해서 인입된 트래픽을 Non Local로 우선 인입 시킬 수 있습니다.

service.cilium.io/shared Annotation을 false로 지정을 하게 되면 통신이 차단이 되며, 클러스터 간 통신이 되지 않습니다.

# Session Affinity Local 설정
kwest annotate service webpod service.cilium.io/affinity=local --overwrite
keast annotate service webpod service.cilium.io/affinity=local --overwrite

kwest exec -it -n kube-system ds/cilium -c cilium-agent -- cilium service list --clustermesh-affinity

# 13   10.2.157.165:80/TCP    ClusterIP      1 => 10.0.1.31:80/TCP (active) (preferred)
#                                            2 => 10.0.1.69:80/TCP (active) (preferred)

keast exec -it -n kube-system ds/cilium -c cilium-agent -- cilium service list --clustermesh-affinity

                                          # 3 => 10.1.1.241:80/TCP (active) (preferred)
                                          #  4 => 10.1.1.178:80/TCP (active) (preferred)