Cluster Mesh 설정하기

Cluster Mesh 설정하기 (Setting up Cluster Mesh)

이 가이드는 Kubernetes 클러스터의 메시를 구축하는 단계별 가이드예요. 클러스터를 서로 연결하고, 모든 클러스터에 걸친 Pod-to-pod 연결을 활성화하며, 크로스 클러스터 서비스 디스커버리와 로드 밸런싱을 설정하고, 마지막으로 접근을 제한하는 보안 정책을 적용하는 방법을 안내합니다.

출처: Setting up Cluster Mesh

본문

이 가이드는 Kubernetes 클러스터의 메시를 구축하는 단계별 가이드입니다. 이 가이드는 클러스터를 서로 연결하고, 모든 클러스터에 걸친 Pod-to-pod 연결을 활성화하고, 크로스 클러스터 서비스 디스커버리와 로드 밸런싱을 설정하고, 마지막으로 접근을 제한하는 보안 정책을 적용하는 방법을 보여 줘요.

Video

이 단계별 가이드 외에도 Cilium의 Clustermesh 기능이 어떻게 동작하는지 보고 싶다면 eCHO Episode 41: Cilium Clustermesh를 확인해 보세요.

사전 준비

클러스터 주소 지정 요구사항

모든 클러스터는 동일한 데이터패스 모드로 구성되어야 합니다. Cilium 설치는 특정 클라우드 환경에 따라 기본적으로 Encapsulation 또는 Native-Routing 모드로 설정될 수 있어요.

모든 클러스터의 Cilium 버전은 마이너 릴리스 하나 이하로 차이가 나야 합니다. 예를 들어 Cilium 1.18.x 는 1.17.x 또는 1.19.x 를 실행하는 클러스터와 연결할 수 있지만, 1.16.x 는 안 됩니다.

모든 클러스터와 모든 노드의 PodCIDR 범위는 서로 충돌하지 않고 고유한 IP 주소여야 합니다.

모든 클러스터의 노드는 각 노드에 대해 구성된 InternalIP를 사용해 서로 IP 연결이 가능해야 합니다. 이 요구사항은 보통 각 클러스터 노드의 네트워크 간에 피어링이나 VPN 터널을 구축해 충족합니다.

클러스터 간 네트워크는 클러스터 간 통신을 허용해야 합니다. 정확한 포트는 방화벽 규칙 섹션에 문서화되어 있어요.

Note

클라우드별 배포의 경우 다음 가이드가 위 요구사항을 충족하는 방법을 보여 줍니다:

Native-routed 데이터패스 모드의 추가 요구사항

각 클러스터의 Cilium은 연결된 모든 클러스터의 모든 PodCIDR 범위를 포괄하는 네이티브 라우팅 CIDR로 구성되어야 합니다. 클러스터 CIDR은 보통 10.0.0.0/8 사설 주소 공간에서 할당됩니다. 이런 경우 10.0.0.0/8 같은 네이티브 라우팅 CIDR이 모든 클러스터를 포괄해야 해요:

  • ConfigMap 옵션 ipv4-native-routing-cidr=10.0.0.0/8
  • Helm 옵션 --set ipv4NativeRoutingCIDR=10.0.0.0/8
  • cilium install 옵션 --set ipv4NativeRoutingCIDR=10.0.0.0/8

노드 외에도 모든 클러스터의 Pod는 서로 IP 연결이 가능해야 합니다. 이 요구사항은 보통 각 클러스터 노드의 네트워크 간에 피어링이나 VPN 터널을 구축해 충족합니다.

클러스터 간 네트워크는 Pod가 사용할 수 있는 모든 포트에 걸쳐 Pod-to-pod 클러스터 간 통신을 허용해야 합니다. 이는 보통 다른 클러스터의 Pod가 모든 포트에서 서로 도달할 수 있게 하는 방화벽 규칙으로 해결해요.

확장 한계

기본적으로 Cluster Mesh로 연결할 수 있는 최대 클러스터 수는 255입니다. maxConnectedClusters 옵션을 사용하면 이 한계를 511로 설정할 수 있으며, 대신 최대 클러스터-로컬 아이덴티티 수가 낮아집니다. 유효한 구성과 해당 클러스터-로컬 아이덴티티 한계는 다음 표를 참고하세요:

MaxConnectedClusters Maximum cluster-local identities
255 (default) 65535
511 32767

Cluster Mesh 전체의 모든 클러스터는 동일한 maxConnectedClusters 값으로 구성되어야 합니다.

  • ConfigMap 옵션 max-connected-clusters=511
  • Helm 옵션 --set clustermesh.maxConnectedClusters=511
  • cilium install 옵션 --set clustermesh.maxConnectedClusters=511

Note

이 옵션은 숫자 아이덴티티의 비트 할당을 제어하며 할당될 수 있는 최대 클러스터-로컬 아이덴티티 수에 영향을 줍니다. 기본적으로 클러스터-로컬 보안 아이덴티티는 Cluster Mesh 사용 여부와 무관하게 65535로 제한됩니다.

Warning

MaxConnectedClusters 는 Cilium 설치 중 한 번만 설정할 수 있으며 기존 클러스터에 대해서는 변경하면 안 됩니다. 실행 중인 클러스터에서 이 옵션을 변경하면 연결 중단과 네트워크 정책의 잘못된 적용 가능성이 생길 수 있어요.

클러스터 준비

이 튜토리얼의 나머지 부분에서는 두 클러스터를 연결하려고 하며, kubectl 구성 컨텍스트가 환경 변수 $CLUSTER1 과 $CLUSTER2 에 저장되어 있다고 가정할게요. 이 컨텍스트 이름은 보통 kubectl --context 에 전달하는 것과 동일합니다.

클러스터 이름과 ID 지정

각 클러스터에 Cilium이 설치되어 있어야 합니다.

각 클러스터에는 고유한 사람이 읽을 수 있는 이름과 숫자 클러스터 ID(1-255)가 할당되어야 합니다. 클러스터 이름은 다음 제약을 따라야 해요:

  • 최대 32자까지 포함해야 합니다;
  • 소문자 영숫자 문자로 시작하고 끝나야 합니다;
  • 그 사이에 소문자 영숫자 문자와 대시를 포함할 수 있습니다.

클러스터 이름과 클러스터 ID는 설치 시점에 둘 다 할당하는 것이 가장 좋아요. 각 클러스터에 다음 Helm 값을 설정하세요:

cluster:
  name: cluster1
  id: 1

각 클러스터에서 다른 이름과 ID를 사용하세요. 자세한 내용과 사용 사례는 Cilium Quick Installation을 검토하세요.

Important

작업 부하가 실행 중인 클러스터에서 클러스터 ID 및/또는 클러스터 이름을 변경하면 모든 작업 부하를 재시작해야 합니다. 클러스터 ID는 보안 아이덴티티를 생성하는 데 사용되며, 클러스터 간 접근을 수립하려면 다시 생성해야 하기 때문이에요.

TLS 인증서 구성

Cluster Mesh는 클러스터 내부와 클러스터 간의 컨트롤 플레인 연결을 보호하기 위해 mTLS를 사용합니다. TLS 인증서는 자동으로 생성하거나 수동으로 제공할 수 있어요.

TLS 인증서를 자동으로 구성하는 데 사용할 수 있는 옵션은 다음과 같습니다:

모든 클러스터는 다른 클러스터가 제시하는 인증서를 신뢰해야 합니다. 공통 루트 CA를 사용하거나 신뢰하는 모든 CA 인증서로 tls.caBundle 을 구성하세요.

CronJob (certgen)cert-managerHelmUser Provided Certificates

certgen을 사용하면 TLS 인증서가 설치 시점에 생성되고 Kubernetes CronJob 이 (만료 날짜와 무관하게) 이를 갱신하도록 예약됩니다. certgen 방식은 cert-manager보다 구현하기 쉬우지만 덜 유연합니다.

certgen을 구성하는 Helm 값은 다음과 같습니다:

clustermesh:
  apiserver:
    tls:
      auto:
        # enable automatic TLS certificate generation
        enabled: true
        # auto generate certificates using cronJob method
        method: cronJob
        # certificates validity duration in days (default 1 year)
        certValidityDuration: 365
        # schedule for certificate re-generation (crontab syntax)
        schedule: "0 0 1 */4 *"

이 방식은 TLS 인증서를 생성하기 위해 cert-manager에 의존합니다. cert-manager는 Kubernetes에서 TLS 인증서를 관리하는 사실상의 표준이며, 문서화된 다른 방식에 비해 다음과 같은 장점이 있어요:

  • 여러 발급자(예: 사용자 지정 CA, Vault, Let's Encrypt, Google's Certificate Authority Service 등)를 지원해 조직의 요구사항에 맞는 발급자를 선택할 수 있습니다.
  • PEM 파일보다 Kubernetes 도구로 검사하기 쉬운 CRD를 통해 인증서를 관리합니다.

설치 단계:

먼저 cert-manager를 설치하고 issuer를 설정하세요. 발급자가 구성된 Cluster Mesh API 서버 이름에 대한 인증서를 만들 수 있는지 확인하세요.

다음 Helm 값으로 Cilium을 설치하거나 업그레이드하세요:

clustermesh:
  apiserver:
    tls:
      auto:
        # enable automatic TLS certificate generation
        enabled: true
        # auto generate certificates using cert-manager
        method: certmanager
        # certificates validity duration in days (default 1 year)
        certValidityDuration: 365
        certManagerIssuerRef:
          # Reference to cert-manager's issuer
          group: cert-manager.io
          kind: ClusterIssuer
          name: ca-issuer

첫 Cilium 설치 동안, Cilium이 Certificate 리소스를 만들 때 cert-manager의 webhook가 아직 사용 가능하지 않을 수 있어요. 그런 경우 TLS Certificate Troubleshooting을 참고하세요.

Helm을 사용하면 Helm으로 Cilium을 설치하거나 업그레이드할 때마다 TLS 인증서가 (재)생성됩니다.

Helm 인증서 생성을 구성하는 Helm 값은 다음과 같습니다:

clustermesh:
  apiserver:
    tls:
      auto:
        # enable automatic TLS certificate generation
        enabled: true
        # auto generate certificates using helm method
        method: helm
        # certificates validity duration in days (default 1 year)
        certValidityDuration: 365

Helm 방식의 단점은 인증서가 자동으로 생성되지만 자동으로 갱신되지는 않는다는 것입니다. 따라서 인증서가 만료되기 전에(즉 구성된 clustermesh.apiserver.tls.auto.certValidityDuration 전에) helm upgrade 를 실행해야 해요.

자체 TLS 인증서를 제공하려면 clustermesh.apiserver.tls.auto.enabled 를 false 로 설정하고, Cilium이 설치된 네임스페이스(보통 kube-system )에 다음 고정 이름의 Secrets를 만들어야 합니다.

인증서의 Common Name (CN)과 Subject Alternative Name (SAN)은 다음과 같이 설정해야 합니다:

  • Server: CN clustermesh-apiserver..svc . SAN에는 clustermesh-apiserver..svc , *.mesh.cilium.io , 127.0.0.1 , ::1 , 그리고 원격 클러스터가 Cluster Mesh API Service에 도달하는 모든 DNS 이름이 포함되어야 합니다.
  • Admin: CN admin-
  • Remote: CN remote 와 기본 migration 인증 모드
  • Local: CN local-

인증서가 발급되면 대상 네임스페이스에 다음 Secrets를 만드세요:

  • clustermesh-apiserver-server-cert
  • clustermesh-apiserver-admin-cert
  • clustermesh-apiserver-remote-cert
  • clustermesh-apiserver-local-cert

각 Secret은 다음 키를 포함해야 합니다:

  • tls.crt : 인증서 파일
  • tls.key : 개인 키 파일
  • ca.crt : CA 인증서 파일

Secrets를 만든 후, 다음 Helm 값으로 자동 인증서 생성을 비활성화한 상태로 Cilium을 설치하거나 업그레이드하세요:

clustermesh:
  apiserver:
    tls:
      auto:
        enabled: false

TLS 트러블슈팅은 TLS Certificate Troubleshooting을 참고하세요.

Helm으로 Cluster Mesh 구성

다음 예시 값 파일들은 cluster1 과 cluster2 를 Cluster Mesh로 구성합니다. 환경에 맞게 조정하세요. 이들은 Cluster Mesh API 서버가 clusterX.example.com DNS 이름으로 노출된 LoadBalancer를 통해 도달 가능하고, 단순함을 위해 공유 CA와 certgen을 사용한다고 가정해요. 적절하다면 #clustermesh-setup-tls Configure TLS certificates에서 설명한 대로 다른 인증서 방식을 선택하세요.

다음 값 파일들을 만드세요:

cluster1.yamlcluster2.yamlclusters.yaml

cluster:
  name: cluster1
  id: 1

clustermesh:
  useAPIServer: true

  config:
    enabled: true

  apiserver:
    service:
      type: LoadBalancer
      annotations: {}
      # The following annotations are examples. Adapt them to your
      # environment and context.
      #
      # Optional: Have ExternalDNS create the DNS records to
      # reach this API server. Otherwise, create the same record
      # through your usual DNS management workflow.
      # annotations:
      #   external-dns.alpha.kubernetes.io/hostname: cluster1.example.com
      #
      # AKS:
      # annotations:
      #   service.beta.kubernetes.io/azure-load-balancer-internal: "true"
      #
      # EKS:
      # annotations:
      #   service.beta.kubernetes.io/aws-load-balancer-scheme: internal
      #
      # GKE:
      # annotations:
      #   networking.gke.io/load-balancer-type: Internal
      #   networking.gke.io/internal-load-balancer-allow-global-access: "true"
    tls:
      auto:
        enabled: true
        method: cronJob
        server:
          extraDnsNames:
            - cluster1.example.com

  # Optional Cluster Mesh features that you may find useful:
  # enableEndpointSliceSynchronization: true
  # mcsapi:
  #   enabled: true
  #   corednsAutoConfigure:
  #     enabled: true
cluster:
  name: cluster2
  id: 2

clustermesh:
  useAPIServer: true

  config:
    enabled: true

  apiserver:
    service:
      type: LoadBalancer
      annotations: {}
      # The following annotations are examples. Adapt them to your
      # environment and context.
      #
      # Optional: Have ExternalDNS create the DNS records to
      # reach this API server. Otherwise, create the same record
      # through your usual DNS management workflow.
      # annotations:
      #   external-dns.alpha.kubernetes.io/hostname: cluster2.example.com
      #
      # AKS:
      # annotations:
      #   service.beta.kubernetes.io/azure-load-balancer-internal: "true"
      #
      # EKS:
      # annotations:
      #   service.beta.kubernetes.io/aws-load-balancer-scheme: internal
      #
      # GKE:
      # annotations:
      #   networking.gke.io/load-balancer-type: Internal
      #   networking.gke.io/internal-load-balancer-allow-global-access: "true"
    tls:
      auto:
        enabled: true
        method: cronJob
        server:
          extraDnsNames:
            - cluster2.example.com

  # Optional Cluster Mesh features that you may find useful:
  # enableEndpointSliceSynchronization: true
  # mcsapi:
  #   enabled: true
  #   corednsAutoConfigure:
  #     enabled: true
clustermesh:
  config:
    clusters:
      cluster1:
        address: cluster1.example.com
        port: 2379
      cluster2:
        address: cluster2.example.com
        port: 2379

clusters.yaml 파일은 모든 원격 클러스터를 포함하므로, 모든 클러스터의 값 파일에 같은 정보를 반복할 필요가 없어요. Cilium이 원격 클러스터 목록에서 로컬 클러스터를 무시하므로 이것이 가능하다는 점을 기억하세요.

Important

clustermesh.apiserver.service.type 의 가능한 모든 값은 다음과 같습니다:

  • LoadBalancer: 컨트롤 플레인을 노출하기 위해 LoadBalancer 유형의 Kubernetes 서비스가 사용됩니다. 이는 안정적인 LoadBalancer IP를 사용하며 보통 최상의 옵션입니다.
  • NodePort: 컨트롤 플레인을 노출하기 위해 NodePort 유형의 Kubernetes 서비스가 사용됩니다. 안정적인 노드 IP가 필요합니다. 노드가 사라지면 Cluster Mesh는 다른 노드에 다시 연결해야 할 수 있어요. 모든 노드가 사용 불가능해지면 새 노드 IP를 추출하기 위해 클러스터를 다시 연결해야 할 수 있습니다.
  • ClusterIP: 컨트롤 플레인을 노출하기 위해 ClusterIP 유형의 Kubernetes 서비스가 사용됩니다. ClusterIP가 클러스터 간에 라우팅 가능해야 해요. 이는 보통 helm 차트 설치 방식을 통해서만 사용 가능합니다.

Helm RepositoryOCI Registry

helm upgrade cilium cilium/cilium --version 1.20.2 \
   --namespace kube-system \
   --kube-context $CLUSTER1 --reuse-values -f clusters.yaml -f cluster1.yaml
helm upgrade cilium oci://quay.io/cilium/charts/cilium 1.20.2 \
   --namespace kube-system \
   --kube-context $CLUSTER1 --reuse-values -f clusters.yaml -f cluster1.yaml

cluster2 에서 Cluster Mesh를 활성화하기 전에 Cilium CA를 cluster2 로 복사하여 두 클러스터가 같은 CA가 서명한 인증서를 생성하도록 하세요:

$ kubectl --context $CLUSTER1 get secret -n kube-system cilium-ca -o yaml | \
    kubectl --context $CLUSTER2 create -f -

Helm RepositoryOCI Registry

helm upgrade cilium cilium/cilium --version 1.20.2 \
   --namespace kube-system \
   --kube-context $CLUSTER2 --reuse-values -f clusters.yaml -f cluster2.yaml
helm upgrade cilium oci://quay.io/cilium/charts/cilium 1.20.2 \
   --namespace kube-system \
   --kube-context $CLUSTER2 --reuse-values -f clusters.yaml -f cluster2.yaml

필요에 따라 이 파일들을 자신의 구성 관리 모델에 맞게 조정하세요. 예를 들어 모든 공유 설정에 공통 값 파일을 사용하거나, 클러스터 맵을 그룹 파일로 나눠 각 클러스터가 가입할 그룹만 적용하고 모든 클러스터를 서로 연결하는 대신 "부분 메시(partial mesh)"를 구축할 수 있어요.

Cluster Mesh는 KVStore 모드로 독립형 etcd 사용하기, 자체 인증서 및/또는 etcd 클라이언트 구성 생성하기, 모든 클러스터가 서로 연결되지 않는 부분 메시 구성하기 등 다양한 다른 구성 시나리오를 지원합니다. 사용 가능한 모든 옵션을 발견하려면 Helm 값을 탐색해 보세요.

Cilium CLI 설치

남은 검증 단계에서는 Cilium CLI를 사용합니다. 대안인 Cilium CLI 설정을 사용하는 경우에도 필요해요.

최신 버전의 Cilium CLI를 설치하세요. Cilium CLI는 Cilium 설치, Cilium 설치 상태 확인, 그리고 다양한 기능(예: clustermesh, Hubble)의 활성화/비활성화에 사용할 수 있어요.

LinuxmacOSOther

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_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
if [ "$(uname -m)" = "arm64" ]; then CLI_ARCH=arm64; fi
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-darwin-${CLI_ARCH}.tar.gz{,.sha256sum}
shasum -a 256 -c cilium-darwin-${CLI_ARCH}.tar.gz.sha256sum
sudo tar xzvfC cilium-darwin-${CLI_ARCH}.tar.gz /usr/local/bin
rm cilium-darwin-${CLI_ARCH}.tar.gz{,.sha256sum}

전체 릴리스 페이지를 참고하세요.

대안: Cilium CLI로 구성

Cilium CLI는 클러스터 간에 Cluster Mesh를 활성화하고 구성할 수도 있어요. Helm의 래퍼이며 가능할 때 Helm과 함께 사용할 수 있습니다. 이미 Cilium CLI로 Cilium을 구성하고 있거나 랩 환경이나 데모 같은 빠른 설정에 편리할 수 있어요.

이 대안도 여전히 모든 클러스터에서 고유한 cluster.name 과 cluster.id 를 구성해야 합니다.

Cilium CLI를 사용한 예시 설치:

$ cilium install --set cluster.name=$CLUSTER1 --set cluster.id=1 --context $CLUSTER1
$ cilium install --set cluster.name=$CLUSTER2 --set cluster.id=2 --context $CLUSTER2

자세한 내용과 사용 사례는 Cilium Quick Installation을 검토하세요.

두 클러스터의 컨텍스트에서 cilium clustermesh enable 을 실행해 필요한 모든 구성 요소를 활성화하세요. 이렇게 하면 clustermesh-apiserver 가 클러스터에 배포되고 필요한 모든 인증서가 생성되어 Kubernetes secrets로 가져와집니다. 또한 다른 클러스터에 Cluster Mesh 컨트롤 플레인을 노출할 LoadBalancer에 가장 적합한 서비스 유형을 자동 감지하려고 시도합니다.

$ cilium clustermesh enable --context $CLUSTER1
$ cilium clustermesh enable --context $CLUSTER2

마지막으로 클러스터를 연결합니다. 이 단계는 한 방향에서만 수행하면 됩니다. 연결은 양방향으로 자동 수립됩니다:

$ cilium clustermesh connect --context $CLUSTER1 --destination-context $CLUSTER2

Cluster Mesh 검증

cilium clustermesh status --wait 를 호출해 Cluster Mesh 구성 요소가 올라올 때까지 기다리세요. LoadBalancer 유형의 서비스를 사용한다면 LoadBalancer에 IP가 할당될 때까지도 기다립니다.

$ cilium clustermesh status --context $CLUSTER1 --wait
$ cilium clustermesh status --context $CLUSTER2 --wait

출력은 다음과 같을 거예요:

✅ Cluster access information is available:
  - 10.168.0.89:2379
✅ Service "clustermesh-apiserver" of type "LoadBalancer" found
⌛ Waiting (12s) for clusters to be connected: 2 nodes are not ready
⌛ Waiting (25s) for clusters to be connected: 2 nodes are not ready
⌛ Waiting (38s) for clusters to be connected: 2 nodes are not ready
⌛ Waiting (51s) for clusters to be connected: 2 nodes are not ready
⌛ Waiting (1m4s) for clusters to be connected: 2 nodes are not ready
⌛ Waiting (1m17s) for clusters to be connected: 1 nodes are not ready
✅ All 2 nodes are connected to all clusters [min:1 / avg:1.0 / max:1]
🔌 Cluster Connections:
- cilium-cli-ci-multicluster-2-168: 2/2 configured, 2/2 connected

이 단계가 성공적으로 완료되지 않으면 #clustermesh-setup-troubleshooting Troubleshooting 섹션으로 진행하세요.

클러스터 간 Pod 연결 테스트

축하합니다. 클러스터를 성공적으로 연결했어요. 멀티 클러스터 모드로 연결 테스트를 실행해 연결성을 검증할 수 있습니다:

$ cilium connectivity test --context $CLUSTER1 --multi-cluster $CLUSTER2

다음 단계

여기서부터 탐색할 논리적 다음 단계는 다음과 같습니다:

트러블슈팅

다음 단계 목록으로 ClusterMesh 문제를 해결해 보세요:

Cilium Pod가 정상이고 ready인지 검증하세요:

$ cilium status --context $CLUSTER1
$ cilium status --context $CLUSTER2

Cluster Mesh가 활성화되고 작동 중인지 검증하세요:

$ cilium clustermesh status --context $CLUSTER1
$ cilium clustermesh status --context $CLUSTER2

위 명령으로 문제를 해결할 수 없다면, 더 자세한 트러블슈팅 가이드인 Cluster Mesh Troubleshooting을 참고하세요.

더 알아보기 (Learn more)