클러스터 피어링 연결 설정

클러스터 피어링 연결 설정 (K8s)

이 페이지는 Consul on Kubernetes 배포에서 서비스 간 클러스터 피어링 연결을 설정하는 과정을 자세히 설명해요. 피어링 토큰 생성, 두 번째 클러스터와의 피어링 설정, 서비스 내보내기, 피어 권한을 위한 의도 생성까지 네 단계를 거친답니다.

출처: 문서

본문

이 페이지는 Consul on Kubernetes 배포에서 서비스 간 클러스터 피어링 연결을 설정하는 과정을 자세히 설명합니다.

클러스터 피어링 연결을 설정하는 전체 과정은 다음 단계로 구성됩니다.

  1. 한 클러스터에서 피어링 토큰을 생성합니다.
  2. 피어링 토큰을 사용해 두 번째 클러스터와 피어링을 설정합니다.
  3. 클러스터 간 서비스를 내보냅니다.
  4. 피어를 위한 권한을 승인하는 의도를 만듭니다.

네 단계가 모두 완료되어야 서비스 간 클러스터 피어링이 설정될 수 있습니다. 클러스터 피어링 연결을 설정하면서 동시에 sameness group을 만들고 싶다면 create sameness groups의 지침을 참조하세요.

클러스터 피어링 연결 설정에 대한 일반적인 지침은 Establish cluster peering connections을 참조하세요.

사전 요구 사항 (Prerequisites)

Kubernetes에서 Consul의 클러스터 피어링 기능을 사용하려면 다음 요구 사항을 충족해야 합니다.

  • Consul v1.14.1 이상
  • Consul on Kubernetes v1.0.0 이상
  • 최소 두 개의 Kubernetes 클러스터

Consul on Kubernetes에서 피어는 PeeringAcceptor와 PeeringDialer CRD를 만들 때 설정하는 metadata.name 값으로 서로를 식별합니다. Kubernetes 배포에서 클러스터 피어링에 대한 추가 요구 사항은 Cluster peering on Kubernetes technical specifications을 참조하세요.

클러스터 ID를 환경 변수에 할당

Kubernetes 클러스터를 프로비저닝하고 여러 Kubernetes 클러스터에 대한 액세스를 관리하도록 kubeconfig 파일을 설정한 후에는 향후 사용을 위해 클러스터를 환경 변수에 할당할 수 있습니다.

  1. 다음 방법 중 하나로 Kubernetes 클러스터의 컨텍스트 이름을 가져오세요.
    • kubectl config current-context 명령을 실행해 현재 있는 클러스터의 컨텍스트를 가져옵니다.
    • kubectl config get-contexts 명령을 실행해 kubeconfig 파일의 모든 구성된 컨텍스트를 가져옵니다.
  2. kubectl 명령으로 Kubernetes 컨텍스트 이름을 내보내고 변수로 설정하세요. kubeconfig와 컨텍스트 사용 방법에 대한 자세한 내용은 Kubernetes docs on configuring access to multiple clusters를 참조하세요.
    $ export CLUSTER1_CONTEXT=<CONTEXT for first Kubernetes cluster>
    $ export CLUSTER2_CONTEXT=<CONTEXT for second Kubernetes cluster>
    

Helm으로 Consul 설치 및 메시 게이트웨이를 통한 피어링 구성

Consul on Kubernetes 배포와 클러스터 피어링을 사용하려면 필요한 값으로 Helm chart를 업데이트하세요. Helm chart를 업데이트한 후 consul-k8s CLI를 사용해 values.yaml을 각 클러스터에 적용할 수 있습니다.

  1. cluster-01에서 다음 명령을 실행하세요.
    $ export HELM_RELEASE_NAME1=cluster-01
    
    $ helm install ${HELM_RELEASE_NAME1} hashicorp/consul --create-namespace --namespace consul --version "1.2.0" --values values.yaml --set global.datacenter=dc1 --kube-context $CLUSTER1_CONTEXT
    
  2. cluster-02에서 다음 명령을 실행하세요.
    $ export HELM_RELEASE_NAME2=cluster-02
    
    $ helm install ${HELM_RELEASE_NAME2} hashicorp/consul --create-namespace --namespace consul --version "1.2.0" --values values.yaml --set global.datacenter=dc2 --kube-context $CLUSTER2_CONTEXT
    
  3. 두 클러스터 모두에 Mesh Gateway Specifications에서 제공하는 Mesh 구성 항목 값을 적용하여 메시 게이트웨이를 통한 피어링 연결 설정을 허용합니다.

서비스 간 트래픽을 위한 메시 게이트웨이 모드 구성

Kubernetes 배포에서 메시 게이트웨이를 local 모드로 구성하여 원격 피어의 서비스를 호출하는 서비스가 원격 메시 게이트웨이 대신 로컬 메시 게이트웨이를 호출하도록 할 수 있습니다. 이 트래픽이 항상 로컬 메시 게이트웨이를 통해 나가도록 메시 게이트웨이 모드를 구성하려면 ProxyDefaults CRD를 사용할 수 있습니다.

  1. cluster-01에서 다음 ProxyDefaults CRD를 적용해 메시 게이트웨이 모드를 구성하세요. proxy-defaults.yaml
    apiVersion: consul.hashicorp.com/v1alpha1
    kind: ProxyDefaults
    metadata:
      name: global
    spec:
      meshGateway:
        mode: local
    
    $ kubectl --context $CLUSTER1_CONTEXT apply -f proxy-defaults.yaml 
    
  2. cluster-02에서 다음 ProxyDefaults CRD를 적용해 메시 게이트웨이 모드를 구성하세요. proxy-defaults.yaml
    apiVersion: consul.hashicorp.com/v1alpha1
    kind: ProxyDefaults
    metadata:
      name: global
    spec:
      meshGateway:
        mode: local
    
    $ kubectl --context $CLUSTER2_CONTEXT apply -f proxy-defaults.yaml 
    

피어링 토큰 생성

클러스터 피어링 과정을 시작하려면 클러스터 중 하나에서 피어링 토큰을 생성하세요. 다른 클러스터는 이 토큰을 사용해 피어링 연결을 설정합니다.

피어링 토큰을 생성할 때마다 연결을 설정하기 위한 일회용 시크릿이 토큰에 포함됩니다. 피어링 토큰을 다시 생성하면 이전에 생성된 시크릿이 무효화되므로, 피어링 연결을 설정하려면 가장 최근에 생성된 토큰을 사용해야 합니다.

  1. cluster-01에서 PeeringAcceptor 사용자 리소스를 만드세요. 클러스터 피어링 연결을 안전하게 하려면 metadata.name 필드가 중복될 수 없습니다. 피어를 특정 이름으로 참조하세요. acceptor.yaml
    apiVersion: consul.hashicorp.com/v1alpha1
    kind: PeeringAcceptor
    metadata:
      name: cluster-02 ## The name of the peer you want to connect to
    spec:
      peer:
        secret:
          name: "peering-token"
          key: "data"
          backend: "kubernetes"
    
  2. PeeringAcceptor 리소스를 첫 번째 클러스터에 적용하세요.
    $ kubectl --context $CLUSTER1_CONTEXT apply --filename acceptor.yaml
    
  3. 피어링 토큰을 다른 클러스터로 내보낼 수 있도록 저장하세요.
    $ kubectl --context $CLUSTER1_CONTEXT get secret peering-token --output yaml > peering-token.yaml
    

클러스터 간 연결 설정

다음으로 피어링 토큰을 사용해 클러스터 간의 보안 연결을 설정하세요.

  1. 피어링 토큰을 두 번째 클러스터에 적용하세요.
    $ kubectl --context $CLUSTER2_CONTEXT apply --filename peering-token.yaml
    
  2. cluster-02에서 PeeringDialer 사용자 리소스를 만드세요. 클러스터 피어링 연결을 안전하게 하려면 metadata.name 필드가 중복될 수 없습니다. 피어를 특정 이름으로 참조하세요. dialer.yaml
    apiVersion: consul.hashicorp.com/v1alpha1
    kind: PeeringDialer
    metadata:
      name: cluster-01 ## The name of the peer you want to connect to
    spec:
      peer:
        secret:
          name: "peering-token"
          key: "data"
          backend: "kubernetes"
    
  3. PeeringDialer 리소스를 두 번째 클러스터에 적용하세요.
    $ kubectl --context $CLUSTER2_CONTEXT apply --filename dialer.yaml
    

클러스터 간 서비스 내보내기

클러스터 간 연결을 설정한 후에는 다른 관리 파티션에서 사용할 수 있는 서비스를 정의하는 exported-services CRD를 만들어야 합니다.

CRD는 로컬 또는 원격 관리 파티션을 대상으로 할 수 있지만, 클러스터 피어링은 항상 원격 관리 파티션으로 서비스를 내보냅니다. 자세한 내용은 exported service consumers을 참조하세요.

  1. 내보내려는 cluster-02의 서비스에 대해 배포 전에 서비스 pod에 "consul.hashicorp.com/connect-inject": "true" 어노테이션을 추가하세요. 이 어노테이션은 워크로드가 메시에 조인할 수 있게 해줍니다. 다음 예시에서 강조되어 있습니다. backend.yaml
    # Service to expose backend
    apiVersion: v1
    kind: Service
    metadata:
      name: backend
    spec:
      selector:
        app: backend
      ports:
      - name: http
        protocol: TCP
        port: 80
        targetPort: 9090
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: backend
    ---
    # Deployment for backend
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: backend
      labels:
        app: backend
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: backend
      template:
        metadata:
          labels:
            app: backend
          annotations:
            "consul.hashicorp.com/connect-inject": "true"
        spec:
          serviceAccountName: backend
          containers:
          - name: backend
            image: nicholasjackson/fake-service:v0.22.4
            ports:
            - containerPort: 9090
            env:
            - name: "LISTEN_ADDR"
              value: "0.0.0.0:9090"
            - name: "NAME"
              value: "backend"
            - name: "MESSAGE"
              value: "Response from backend"
    
  2. backend 서비스를 두 번째 클러스터에 배포하세요.
    $ kubectl --context $CLUSTER2_CONTEXT apply --filename backend.yaml
    
  3. cluster-02에서 ExportedServices 사용자 리소스를 만드세요. 서비스를 소비하는 피어의 이름은 PeeringDialer CRD에 설정된 이름과 동일해야 합니다. exported-service.yaml
    apiVersion: consul.hashicorp.com/v1alpha1
    kind: ExportedServices
    metadata:
      name: default ## The name of the partition containing the service
    spec:
      services:
        - name: backend ## The name of the service you want to export
          consumers:
          - peer: cluster-01 ## The name of the peer that receives the service
    
  4. ExportedServices 리소스를 두 번째 클러스터에 적용하세요.
    $ kubectl --context $CLUSTER2_CONTEXT apply --filename exported-service.yaml
    

피어를 위한 서비스 승인

피어링된 클러스터에서 서비스를 호출하기 전에 해당 클러스터가 특정 서비스를 사용하도록 승인하는 서비스 의도를 설정해야 합니다. Consul은 승인되지 않은 클러스터로 서비스가 내보내지는 것을 방지합니다.

  1. 두 번째 클러스터에 대한 서비스 의도를 만드세요. 피어의 이름은 PeeringDialer CRD에 설정된 이름과 일치해야 합니다. intention.yaml
    apiVersion: consul.hashicorp.com/v1alpha1
    kind: ServiceIntentions
    metadata:
      name: backend-deny
    spec:
      destination:
        name: backend
      sources:
       - name: "*"
         action: deny
       - name: frontend
         action: allow
         peer: cluster-01 ## The peer of the source service
    
  2. 의도를 두 번째 클러스터에 적용하세요.
    $ kubectl --context $CLUSTER2_CONTEXT apply --filename intention.yaml
    
  3. cluster-01의 서비스가 cluster-02의 backend를 호출할 수 있도록 워크로드 배포 전에 서비스 pod에 "consul.hashicorp.com/connect-inject": "true" 어노테이션을 추가하세요. 애플리케이션에서 업스트림 서비스를 호출하려면 Service Virtual IP Lookups에 지정된 대로 요청이 올바른 DNS 이름으로 전송되도록 애플리케이션을 구성하세요. 다음 예시에서 워크로드가 메시에 조인할 수 있게 하는 어노테이션과 워크로드가 올바른 DNS 이름으로 업스트림 서비스를 호출할 수 있게 하는 워크로드에 제공된 구성이 강조되어 있습니다. Service Virtual IP Lookups for Consul Enterprise는 파티션과 네임스페이스를 포함한 DNS 이름을 유사하게 형식화하는 방법을 자세히 설명합니다. frontend.yaml
    # Service to expose frontend
    apiVersion: v1
    kind: Service
    metadata:
      name: frontend
    spec:
      selector:
        app: frontend
      ports:
      - name: http
        protocol: TCP
        port: 9090
        targetPort: 9090
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: frontend
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: frontend
      labels:
        app: frontend
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: frontend
      template:
        metadata:
          labels:
            app: frontend
          annotations:
            "consul.hashicorp.com/connect-inject": "true"
        spec:
          serviceAccountName: frontend
          containers:
          - name: frontend
            image: nicholasjackson/fake-service:v0.22.4
            securityContext:
              capabilities:
                add: ["NET_ADMIN"]
            ports:
            - containerPort: 9090
            env:
            - name: "LISTEN_ADDR"
              value: "0.0.0.0:9090"
            - name: "UPSTREAM_URIS"
              value: "http://backend.virtual.cluster-02.consul"
            - name: "NAME"
              value: "frontend"
            - name: "MESSAGE"
              value: "Hello World"
            - name: "HTTP_CLIENT_KEEP_ALIVES"
              value: "false"
    
  4. 서비스 파일을 첫 번째 클러스터에 적용하세요.
    $ kubectl --context $CLUSTER1_CONTEXT apply --filename frontend.yaml
    
  5. frontend에서 다음 명령을 실행하고 출력을 확인하여 클러스터가 성공적으로 피어링되었는지 확인하세요.
    $ kubectl --context $CLUSTER1_CONTEXT exec -it $(kubectl --context $CLUSTER1_CONTEXT get pod -l app=frontend -o name) -- curl localhost:9090
    
    {
      "name": "frontend",
      "uri": "/",
      "type": "HTTP",
      "ip_addresses": [
        "10.16.2.11"
      ],
      "start_time": "2022-08-26T23:40:01.167199",
      "end_time": "2022-08-26T23:40:01.226951",
      "duration": "59.752279ms",
      "body": "Hello World",
      "upstream_calls": {
        "http://backend.virtual.cluster-02.consul": {
          "name": "backend",
          "uri": "http://backend.virtual.cluster-02.consul",
          "type": "HTTP",
          "ip_addresses": [
            "10.32.2.10"
          ],
          "start_time": "2022-08-26T23:40:01.223503",
          "end_time": "2022-08-26T23:40:01.224653",
          "duration": "1.149666ms",
          "headers": {
            "Content-Length": "266",
            "Content-Type": "text/plain; charset=utf-8",
            "Date": "Fri, 26 Aug 2022 23:40:01 GMT"
          },
          "body": "Response from backend",
          "code": 200
        }
      },
      "code": 200
    }
    

더 알아보기 (Learn more)