멀티 클러스터 환경에서 다양하게 구성하는 경우가 많아서 이번에는 Cilium의 ClusterMesh를 이용하여 Mesh환경을 구성해보도록 하겠습니다.
클러스터 구성 전 주의사항
- 설치 전 주의사항은 두개의 클러스터가 모두 같은 네트워크 모드를 사용해야합니다. 한쪽이 vxlan 캡슐화를 하는데 한쪽은 native routing을 사용하면 안됩니다.
- 각 클러스터의 pod, service cidr은 겹치면 안됩니다.
- 모든 클러스터의 노드는 서로 IP 연결이 가능해야 하며, 이는 각 노드의 InternalIP를 사용하여 구성됩니다. 이 요구 사항은 일반적으로 클러스터 간 네트워크 피어링 또는 VPN 터널을 설정하여 충족됩니다.
- 클러스터 간의 네트워크는 상호 통신을 허용해야 하며, 구체적인 포트는 방화벽 규칙(Firewall Rules) 섹션에서 확인할 수 있습니다.
- 만약 네이티브 라우팅방식으로 구성한다면 ipv4-native-routing-cidr는 클러스터 간의 Pod 통신을 가능하게 하기 위해 모든 연결된 클러스터의 PodCIDR 범위를 포함하는 CIDR을 설정해야 합니다.
- Mesh로 추가할수 있는 기본은 255이며 변경 가능한데 수정할 수 있는 최대의 클러스터 수는 511입니다.
Cluster 2개 준비하기
구분하기 쉽게 파드와 서비스 대역을 나누어서 클러스터를 2개 생성하겠습니다.
Blue 클러스터 만들기
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
- role: worker
networking:
disableDefaultCNI: true
kubeProxyMode: "none"
podSubnet: "100.10.0.0/16"
serviceSubnet: "100.11.0.0/16"
위의 파일을 이용하여 클러스터를 생성합니다.
kind create cluster --name blue --config blue/kind.yaml
생성 완료
Green 클러스터 만들기
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
- role: worker
networking:
disableDefaultCNI: true
kubeProxyMode: "none"
podSubnet: "200.10.0.0/16"
serviceSubnet: "200.11.0.0/16"
위의 파일을 이용하여 클러스터를 생성합니다.
kind create cluster --name green --config green/kind.yaml
생성 완료
Cilium 설치하기
아래의 명령어를 사용해서 설치할 예정입니다.
cluster id는 0번은 cluster mesh를 안사용하는 클러스터에 적용할 때 두면 좋을 것 같고 cluster-mesh로 묶을 클러스터에는 1번부터 순서대로 적용하면 될 것 같습니다.
cilium install --version 1.16.2 --context kind-${CLUSTER_NAME} \
--set kubeProxyReplacement=true \
--set gatewayAPI.enabled=true \
--set hubble.enabled=true \
--set hubble.relay.enabled=true \
--set hubble.ui.enabled=true \
--set l2announcements.enabled=true \
--set k8sServiceHost=${KUBE_API_SERVER_IP} \
--set k8sServicePort=${KUBE_API_SERVER_PORT} \
--set externalIPs.enabled=true \
--set cluster.name=${CLUSTER_NAME} \
--set cluster.id=${CLUSTER_ID}
이 스크립트로 설치하면 빠르게 설치할 수 있습니다.
#!/bin/bash
clusters=("blue" "green")
index=0
for cluster in "${clusters[@]}"
do
# index 값을 1씩 증가
index=$((index + 1))
# 환경 변수 설정
export CONTEXT="kind-$cluster"
export CLUSTER_NAME=$cluster
export CONTROLPLANE_NAME="$cluster-control-plane"
# kubectl을 사용하여 KUBE_API_SERVER_IP 가져오기
export KUBE_API_SERVER_IP=$(kubectl get nodes $CONTROLPLANE_NAME -o json --context $CONTEXT | jq '.status.addresses[0].address' -r)
# API 서버 포트 설정
export KUBE_API_SERVER_PORT=6443
export CLUSTER_ID=$index
# 값 출력
echo "Context: $CONTEXT"
echo "Cluster Name: $CLUSTER_NAME"
echo "Kube API Server IP: $KUBE_API_SERVER_IP"
echo "Cluster ID: $CLUSTER_ID"
echo "----------------------------"
cilium install --version 1.16.2 --context ${CONTEXT} \
--set kubeProxyReplacement=true \
--set gatewayAPI.enabled=true \
--set hubble.enabled=true \
--set hubble.relay.enabled=true \
--set hubble.ui.enabled=true \
--set l2announcements.enabled=true \
--set k8sServiceHost=${KUBE_API_SERVER_IP} \
--set k8sServicePort=${KUBE_API_SERVER_PORT} \
--set externalIPs.enabled=true \
--set cluster.name=${CLUSTER_NAME} \
--set cluster.id=${CLUSTER_ID}
done
l2 설정의 경우 두 클러스터에 동일하게 설정하면 됩니다.
apiVersion: "cilium.io/v2alpha1"
kind: CiliumL2AnnouncementPolicy
metadata:
name: default
spec:
externalIPs: true
loadBalancerIPs: true
ipam 설정하기
blue 클러스터에 다음과 같은 ipam을 등록하겠습니다.
apiVersion: cilium.io/v2alpha1
kind: CiliumLoadBalancerIPPool
metadata:
name: ipam-blue
spec:
blocks:
- start: 172.17.0.51
stop: 172.17.0.100
green클러스터에는 헷갈리지 않도록 다른 ipam을 등록하겠습니다.
apiVersion: cilium.io/v2alpha1
kind: CiliumLoadBalancerIPPool
metadata:
name: ipam-green
spec:
blocks:
- start: 172.17.1.101
stop: 172.17.1.150
Cluster Mesh 활성화하기
설정 활성화하기
cilium clustermesh enable --context $CONTEXT --service-type NodePort
설정이 되면 cluster-mesh 전용 apiserver가 생성 된다.
클러스터 끼리 연결하기
istio에서는 mesh로 연결하려고 할때 양쪽에 설정을 해줘야했는데 여기는 이상하게도 한곳에 설정했는데 양쪽다 설정이 들어간것 같다.
cilium clustermesh connect --context $CLUSTER1 --destination-context $CLUSTER2
아래의 명령어로 정상적으로 설정되었는지 확인해볼 수 있다.
cilium clustermesh status
테스트 해보기
테스트 서비스 생성하기
양쪽에 동일하게 생성하게 합니다.
apiVersion: v1
kind: ServiceAccount
metadata:
name: httpbin
---
apiVersion: v1
kind: Service
metadata:
name: httpbin
annotations:
service.cilium.io/global: "true"
labels:
app: httpbin
service: httpbin
spec:
ports:
- name: http
port: 8000
targetPort: 8080
selector:
app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
version: v1
template:
metadata:
labels:
app: httpbin
version: v1
spec:
serviceAccountName: httpbin
containers:
- image: docker.io/kong/httpbin:0.1.0
imagePullPolicy: IfNotPresent
name: httpbin
# Same as found in Dockerfile's CMD but using an unprivileged port
command:
- pipenv
- run
- gunicorn
- -b
- 0.0.0.0:8080
- httpbin:app
- -k
- gevent
env:
# Tells pipenv to use a writable directory instead of $HOME
- name: WORKON_HOME
value: /tmp
ports:
- containerPort: 8080
Global 설정
이렇게 설정하고 나면 양쪽의 서비스의 엔드포인트에 다른 쪽의 파드들까지 들어오게 됩니다.
blue 클러스터의 cilium에서 서비스 리스트를 확인해보면 my-service에 green 클러스터의 파드들이 보이는것을 확인할 수 있습니다.
좀더 확인하기 쉽게 응답을 다르게 주게끔 했는데 이렇게 아이피로 호출했을 때에도 잘 응답이 오는것을 확인할 수 있다.
hubble에도 신기하게 두개의 클러스터가보인다.
'K8S > cilium' 카테고리의 다른 글
Bonding 인터페이스에서 Cilium XDP 활성화 하기 (2) | 2024.10.21 |
---|---|
Maglev 알고리즘 사용해보기 (0) | 2024.10.18 |
Kind에서 Cilium으로 외부 접근 LoadBalancer 설정하기 (2) | 2024.10.13 |
Maglev: Google의 로드밸런싱 알고리즘 (0) | 2024.10.03 |
cilium의 메트릭 정보 켜보기 (0) | 2024.10.03 |