Global Services
Global Services
이 튜토리얼은 Cilium Global Services를 사용해 여러 Kubernetes 클러스터에 걸쳐 로드 밸런싱과 서비스 디스커버리를 수행하는 방법을 안내해요. 같은 이름과 네임스페이스의 Service에 service.cilium.io/global: "true" 애노테이션을 붙이면 양쪽 클러스터의 Pod로 자동 로드 밸런싱됩니다.
출처: Global Services
본문
이 튜토리얼은 Cilium Global Services를 사용해 여러 Kubernetes 클러스터에 걸쳐 로드 밸런싱과 서비스 디스커버리를 수행하는 방법을 안내합니다.
사전 준비
정상 작동하는 Cluster Mesh 설정이 필요해요. 설정하려면 Cluster Mesh 설정하기 가이드를 따라주세요.
Global Services로 로드 밸런싱
클러스터 간 로드 밸런싱을 구축하는 방법은 각 클러스터에 동일한 이름과 네임스페이스의 Kubernetes 서비스를 정의하고, service.cilium.io/global: "true" 애노테이션을 추가해 global로 선언하는 것입니다. Cilium은 두 클러스터의 Pod에 자동으로 로드 밸런싱을 수행해요.
apiVersion: v1
kind: Service
metadata:
name: rebel-base
annotations:
service.cilium.io/global: "true"
spec:
type: ClusterIP
ports:
- port: 80
selector:
name: rebel-base
Global Service 공유 비활성화
기본적으로 Global Service는 여러 클러스터의 백엔드에 걸쳐 로드 밸런싱합니다. 이는 service.cilium.io/shared: "true" 를 암시적으로 구성합니다. Service 백엔드가 다른 클러스터와 공유되는 것을 막으려면 이 옵션을 비활성화해야 해요.
아래 예시는 로컬 엔드포인트를 공유하지 않고 원격 엔드포인트를 노출합니다.
apiVersion: v1
kind: Service
metadata:
name: rebel-base
annotations:
service.cilium.io/global: "true"
service.cilium.io/shared: "false"
spec:
type: ClusterIP
ports:
- port: 80
selector:
name: rebel-base
Kubernetes EndpointSlice 동기화 (베타)
Note
이것은 베타 기능입니다. 문제가 발생하면 피드백을 제공하고 GitHub 이슈를 올려주세요.
기본적으로 Kubernetes EndpointSlice 동기화는 비-Headless Global service에서는 비활성화되어 있어요. Global Service의 원격 클러스터 엔드포인트를 DNS나 타사 컨트롤러에서 발견하도록 하려면 service.cilium.io/global-sync-endpoint-slices: "true" 애노테이션을 추가해 동기화를 활성화하세요. 이렇게 하면 Cilium이 해당 애노테이션이 있는 서비스에 대해 원격 클러스터에 속하는 Kubernetes EndpointSlice를 만들 수 있어요. Global Headless 서비스에 관해서는 명시적으로 service.cilium.io/global-sync-endpoint-slices: "false" 애노테이션을 추가해 거부하지 않는 한 이 옵션이 기본적으로 활성화됩니다.
이 기능은 다른 Cilium 기능을 보완하지 않으며 필요로 하지도 않는다는 점을 기억하세요. 타사 컨트롤러에서 원격 클러스터의 EndpointSlice를 발견해야 할 때만 필요해요. 예를 들어 Cilium ingress 컨트롤러는 이 기능 없이도 Cluster Mesh에서 동작하지만, 다른 ingress 컨트롤러를 사용한다면 활성화해야 할 수 있습니다.
이 기능은 현재 기능 플래그를 통해 기본적으로 비활성화되어 있어요. EndpointSlice Cluster Mesh 동기화로 Cilium을 설치하려면 다음을 실행하세요:
Helm RepositoryOCI Registry
helm install cilium cilium/cilium --version 1.20.2 \
--namespace kube-system \
--set clustermesh.enableEndpointSliceSynchronization=true
helm install cilium oci://quay.io/cilium/charts/cilium 1.20.2 \
--namespace kube-system \
--set clustermesh.enableEndpointSliceSynchronization=true
기존 Cilium 설치에서 EndpointSlice Cluster Mesh 동기화를 활성화하려면 다음을 실행하세요:
Helm RepositoryOCI Registry
helm upgrade cilium cilium/cilium --version 1.20.2 \
--namespace kube-system \
--reuse-values \
--set clustermesh.enableEndpointSliceSynchronization=true
kubectl -n kube-system rollout restart deployment/cilium-operator
helm upgrade cilium oci://quay.io/cilium/charts/cilium 1.20.2 \
--namespace kube-system \
--reuse-values \
--set clustermesh.enableEndpointSliceSynchronization=true
kubectl -n kube-system rollout restart deployment/cilium-operator
알려진 한계
이것은 베타 기능이므로 버그나 부족한 점을 겪을 수 있어요.
호스트 이름은 어떤 형태의 충돌 해결 메커니즘 없이 그대로 동기화됩니다. 즉 여러 클러스터에 걸쳐 EndpointSlice를 동기화하는 단일 governing Service를 가진 여러 StatefulSet은 서로 다른 이름을 가져야 합니다. 예를 들어 StatefulSet 이름에 클러스터 이름을 추가할 수 있어요 ( my-statefulset 대신 cluster1-my-statefulset ).
간단한 예시 서비스 배포
클러스터 1에서 배포합니다:
kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/1.20.2/examples/kubernetes/clustermesh/cluster1.yaml
kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/1.20.2/examples/kubernetes/clustermesh/global-service-example.yaml
클러스터 2에서 배포합니다:
kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/1.20.2/examples/kubernetes/clustermesh/cluster2.yaml
kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/1.20.2/examples/kubernetes/clustermesh/global-service-example.yaml
어느 클러스터에서든 global service에 접근합니다:
kubectl exec -ti deployment/x-wing -- curl rebel-base
두 클러스터의 Pod에서 응답을 볼 수 있을 거예요.
클러스터 1에서 기존 global service에 service.cilium.io/shared="false" 를 추가하세요
kubectl annotate service rebel-base service.cilium.io/shared="false" --overwrite
클러스터 1에서 global service에 다시 접근합니다:
kubectl exec -ti deployment/x-wing -- curl rebel-base
여전히 두 클러스터의 Pod에서 응답을 볼 수 있을 거예요.
클러스터 2에서 global service에 다시 접근합니다:
kubectl exec -ti deployment/x-wing -- curl rebel-base
클러스터 1의 global service가 더 이상 공유되지 않으므로 클러스터 2의 Pod에서만 응답을 볼 수 있을 거예요.
클러스터 1에서 기존 global service의 service.cilium.io/shared 애노테이션을 제거하세요
kubectl annotate service rebel-base service.cilium.io/shared-
어느 클러스터에서든 global service에 접근합니다:
kubectl exec -ti deployment/x-wing -- curl rebel-base
다시 두 클러스터의 Pod에서 응답을 볼 수 있을 거예요.
Global 및 Shared Services 참조
아래 플로우 차트는 두 클러스터(즉 Cluster1과 Cluster2)에 존재하는 서비스와 service.cilium.io/global 및 service.cilium.io/shared 애노테이션 값의 다양한 조합을 고려한 전체 동작을 요약합니다. 종료 노드는 각 조합에서 두 클러스터가 검토 중인 서비스에 사용하는 엔드포인트를 나타냅니다.
도달 불가능한 클러스터 처리
기본적으로 원격 클러스터가 도달 불가능해지면 Cilium은 마지막으로 알려진 서비스 정보를 캐시에 유지합니다. 이로 인해 "stale"하거나 도달 불가능한 백엔드로 트래픽이 전송될 수 있어요.
이를 완화하려면 캐시 TTL(time-to-live)을 구성할 수 있습니다. 원격 클러스터의 연결이 끊기고 이 기간 내에 다시 설정되지 않으면 Cilium은 해당 클러스터의 캐시된 데이터를 자동으로 철회해요. Global services의 경우, 이는 Cilium이 도달 불가능한 클러스터의 서비스 백엔드로의 로드 밸런싱을 중단한다는 뜻입니다. 연결이 다시 설정되면 원격 클러스터의 서비스가 다시 채워지고 백엔드로의 로드 밸런싱이 재개됩니다.
기본값은 "0s" 로, 이 기능이 비활성화되어 캐시가 절대 철회되지 않음을 의미해요. 활성화하려면 clustermesh.cacheTTL 을 0보다 큰 기간(예: "15m" )으로 설정하세요.
Helm RepositoryOCI Registry
helm upgrade cilium cilium/cilium --version 1.20.2 \
--namespace kube-system \
--reuse-values \
--set clustermesh.cacheTTL="15m"
helm upgrade cilium oci://quay.io/cilium/charts/cilium 1.20.2 \
--namespace kube-system \
--reuse-values \
--set clustermesh.cacheTTL="15m"
한계
Global NodePort 서비스는 Cilium이 kube-proxy를 대체하도록 구성된 경우( kubeProxyReplacement=true )에만 로컬과 원격 백엔드 모두에 걸쳐 로드 밸런싱합니다. 그렇지 않으면 NodePort로 접근할 때 로컬 백엔드만 로드 밸런싱 대상이 됩니다.
Node 또는 host 네트워크에서 실행되는 Pod가 접근하는 Global services는 Cilium이 kube-proxy를 대체하도록 구성된 경우( kubeProxyReplacement=true )에만 로컬과 원격 백엔드 모두에 걸쳐 로드 밸런싱합니다. 이 한계는 host 네임스페이스에서 SocketLB를 활성화해 극복할 수 있어요: socketLB.enabled=true , socketLB.hostNamespaceOnly=true . 그렇지 않으면 로컬 백엔드만 로드 밸런싱 대상이 됩니다.