클러스터 간 인그레스 배포

이 페이지에서는 여러 GKE 클러스터에 애플리케이션을 제공하는 인그레스를 배포하는 방법을 보여줍니다. 멀티 클러스터 인그레스에 대해 알아보려면 멀티 클러스터 인그레스를 참조하세요.

배포 가이드

아래 작업에서는 두 클러스터에 zoneprinter라는 가상 앱 및 멀티 클러스터 인그레스를 배포합니다. 인그레스는 앱 배포를 위해 공유 VIP(가상 IP) 주소를 제공합니다.

이 페이지에서는 2개의 클러스터를 만들고 등록한 멀티 클러스터 인그레스 설정에서 수행한 작업을 바탕으로 합니다. Fleet에도 등록된 2개의 클러스터가 있는지 확인합니다.

gcloud container clusters list

출력은 다음과 비슷합니다.

NAME    LOCATION        MASTER_VERSION  MASTER_IP       MACHINE_TYPE   NODE_VERSION     NUM_NODES  STATUS
gke-eu  europe-west1-c  1.16.8-gke.9    ***             e2-medium      1.16.8-gke.9     2          RUNNING
gke-us  us-central1-a   1.16.8-gke.9    ***             e2-medium      1.16.6-gke.13 *  2          RUNNING

네임스페이스 만들기

Fleet에는 네임스페이스 동일성 속성이 있으므로, 동일한 그룹에서 동일한 네임스페이스를 소유하고 관리할 수 있도록 클러스터 전체에서 네임스페이스 생성 및 관리를 조정하는 것이 좋습니다. 팀, 환경, 애플리케이션 또는 애플리케이션 구성요소별로 네임스페이스를 만들 수 있습니다. 네임스페이스는 한 클러스터의 네임스페이스 ns1이 다른 클러스터의 ns1과 동일한 의미와 사용량을 갖는 한 필요에 따라 세분화할 수 있습니다.

이 예시에서는 각 클러스터의 애플리케이션별로 zoneprinter 네임스페이스를 만듭니다.

  1. 다음 내용이 포함된 namespace.yaml이라는 파일을 만듭니다.

    apiVersion: v1
    kind: Namespace
    metadata:
      name: zoneprinter
    
  2. gke-us 컨텍스트로 전환합니다.

    kubectl config use-context gke-us
    
  3. 네임스페이스를 만듭니다.

    kubectl apply -f namespace.yaml
    
  4. gke-eu 컨텍스트로 전환합니다.

    kubectl config use-context gke-eu
    
  5. 네임스페이스를 만듭니다.

    kubectl apply -f namespace.yaml
    

    출력은 다음과 비슷합니다.

    namespace/zoneprinter created
    

앱 배포

  1. 다음 내용이 포함된 deploy.yaml이라는 파일을 만듭니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: zone-ingress
      namespace: zoneprinter
      labels:
        app: zoneprinter
    spec:
      selector:
        matchLabels:
          app: zoneprinter
      template:
        metadata:
          labels:
            app: zoneprinter
        spec:
          containers:
          - name: frontend
            image: gcr.io/google-samples/zone-printer:0.2
            ports:
            - containerPort: 8080
    
  2. gke-us 컨텍스트로 전환합니다.

    kubectl config use-context gke-us
    
  3. zoneprinter 앱을 배포합니다.

    kubectl apply -f deploy.yaml
    
  4. gke-eu 컨텍스트로 전환합니다.

    kubectl config use-context gke-eu
    
  5. zoneprinter 앱을 배포합니다.

    kubectl apply -f deploy.yaml
    
  6. zoneprinter 앱이 각 클러스터에 성공적으로 배포되었는지 확인합니다.

    kubectl get deployment --namespace zoneprinter
    

    출력은 두 클러스터 모두에서 다음과 비슷하게 표시됩니다.

    NAME           READY   UP-TO-DATE   AVAILABLE   AGE
    zone-ingress   1/1     1            1           12m
    

구성 클러스터를 통한 배포

이제 애플리케이션이 gke-usgke-eu 전체에 배포되었으므로 구성 클러스터의 MultiClusterIngress(MCI) 및 MultiClusterService(MCS) 리소스를 배포하여 부하 분산기를 배포합니다. MCI 및 MCS는 인그레스 및 서비스 리소스의 멀티 클러스터에 해당하는 커스텀 리소스(CRD)입니다.

설정 가이드에서 gke-us 클러스터를 구성 클러스터로 구성했습니다. 구성 클러스터는 모든 클러스터에 인그레스를 배포하고 구성하는 데 사용됩니다.

  1. 컨텍스트를 구성 클러스터로 설정합니다.

    kubectl config use-context gke-us
    

MultiClusterService

  1. 다음 내용이 포함된 mcs.yaml이라는 파일을 만듭니다.

    apiVersion: networking.gke.io/v1
    kind: MultiClusterService
    metadata:
      name: zone-mcs
      namespace: zoneprinter
    spec:
      template:
        spec:
          selector:
            app: zoneprinter
          ports:
          - name: web
            protocol: TCP
            port: 8080
            targetPort: 8080
    
  2. zoneprinter 앱과 일치하는 MultiClusterService 리소스를 배포합니다.

    kubectl apply -f mcs.yaml
    
  3. zone-mcs 리소스가 구성 클러스터에 성공적으로 배포되었는지 확인합니다.

    kubectl get mcs -n zoneprinter
    

    출력은 다음과 비슷합니다.

    NAME       AGE
    zone-mcs   9m26s
    

    이 MCS는 파생된 헤드리스 서비스를 포드가 app: zoneprinter와 일치하는 모든 클러스터에서 만듭니다. 서비스 하나가 gke-us 클러스터 kubectl get service -n zoneprinter에 존재하는 것을 확인할 수 있습니다.

    출력은 다음과 비슷합니다.

    NAME                                TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
    mci-zone-mcs-svc-lgq966x5mxwwvvum   ClusterIP   None          <none>        8080/TCP         4m59s
    

유사한 헤드리스 서비스가 gke-eu에도 존재합니다. 이러한 로컬 서비스는 pod 엔드포인트를 동적으로 선택하여 백엔드로 전역 인그레스 부하 분산기를 프로그래밍하는 데 사용됩니다.

MultiClusterIngress

  1. 다음 내용이 포함된 mci.yaml이라는 파일을 만듭니다.

    apiVersion: networking.gke.io/v1
    kind: MultiClusterIngress
    metadata:
      name: zone-ingress
      namespace: zoneprinter
    spec:
      template:
        spec:
          backend:
            serviceName: zone-mcs
            servicePort: 8080
    

    이 구성은 모든 트래픽을 zoneprinter 네임스페이스의 zone-mcs라는 MultiClusterService로 라우팅합니다.

  2. zone-mcs를 백엔드로 참조하는 MultiClusterIngress 리소스를 배포합니다.

    kubectl apply -f mci.yaml
    

    출력은 다음과 비슷합니다.

    multiclusteringress.networking.gke.io/zone-ingress created
    

    MultiClusterIngress는 Kubernetes 인그레스와 동일한 스키마를 사용합니다. 또한 인그레스 리소스 시맨틱스는 backend.serviceName 필드를 제외하고는 동일한 스키마를 사용합니다.

MultiClusterIngressbackend.serviceName 필드는 Kubernetes 클러스터의 서비스가 아닌 Fleet API의 MultiClusterService를 참조합니다. 즉, TLS 종료와 같은 인그레스의 모든 설정을 동일한 방식으로 구성할 수 있습니다.

성공적인 배포 상태 검증

새 부하 분산기를 배포하는 경우 Google Cloud 부하 분산기를 배포하는 데 몇 분 정도 걸릴 수 있습니다. 기존 부하 분산기를 업데이트하면 새 리소스를 배포할 필요가 없으므로 더 빠르게 완료할 수 있습니다. MCI 리소스는 MCI를 대신하여 생성된 기본 Compute Engine 리소스를 자세히 설명합니다.

  1. 배포가 성공적으로 완료되었는지 확인합니다.

    kubectl describe mci zone-ingress -n zoneprinter
    

    출력은 다음과 비슷합니다.

    Name:         zone-ingress
    Namespace:    zoneprinter
    Labels:       <none>
    Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                    {"apiVersion":"networking.gke.io/v1","kind":"MultiClusterIngress","metadata":{"annotations":{},"name":"zone-ingress","namespace":"zon...
    API Version:  networking.gke.io/v1
    Kind:         MultiClusterIngress
    Metadata:
      Creation Timestamp:  2020-04-10T23:35:10Z
      Finalizers:
        mci.finalizer.networking.gke.io
      Generation:        2
      Resource Version:  26458887
      Self Link:         /apis/networking.gke.io/v1/namespaces/zoneprinter/multiclusteringresses/zone-ingress
      UID:               62bec0a4-8a08-4cd8-86b2-d60bc2bda63d
    Spec:
      Template:
        Spec:
          Backend:
            Service Name:  zone-mcs
            Service Port:  8080
    Status:
      Cloud Resources:
        Backend Services:
          mci-8se3df-8080-zoneprinter-zone-mcs
        Firewalls:
          mci-8se3df-default-l7
        Forwarding Rules:
          mci-8se3df-fw-zoneprinter-zone-ingress
        Health Checks:
          mci-8se3df-8080-zoneprinter-zone-mcs
        Network Endpoint Groups:
          zones/europe-west1-c/networkEndpointGroups/k8s1-e4adffe6-zoneprint-mci-zone-mcs-svc-lgq966x5m-808-88670678
          zones/us-central1-a/networkEndpointGroups/k8s1-a6b112b6-zoneprint-mci-zone-mcs-svc-lgq966x5m-808-609ab6c6
        Target Proxies:
          mci-8se3df-zoneprinter-zone-ingress
        URL Map:  mci-8se3df-zoneprinter-zone-ingress
      VIP:        34.98.102.37
    Events:
      Type    Reason  Age                    From                              Message
      ----    ------  ----                   ----                              -------
      Normal  ADD     3m35s                  multi-cluster-ingress-controller  zoneprinter/zone-ingress
      Normal  UPDATE  3m10s (x2 over 3m34s)  multi-cluster-ingress-controller  zoneprinter/zone-ingress
    

    인그레스 배포의 상태를 나타내는 몇 가지 필드는 다음과 같습니다.

    • Events를 가장 먼저 확인합니다. 오류가 발생한 경우 여기에 표시됩니다.

    • Cloud Resource는 멀티 클러스터 인그레스 컨트롤러에서 만든 전달 규칙, 백엔드 서비스, 방화벽 규칙 등의 Compute Engine 리소스를 나열합니다. 이러한 규칙이 나열되지 않는다면 아직 생성되지 않았다는 의미입니다. Console 또는 gcloud 명령어로 개별 Compute Engine 리소스를 검사하여 상태를 확인할 수 있습니다.

    • VIP는 할당된 IP 주소를 나열합니다. VIP가 있어도 부하 분산기가 아직 트래픽을 처리하지 않을 수도 있습니다. 몇 분 후에도 VIP가 표시되지 않거나 부하 분산기가 10분 이내에 200 응답을 반환하지 않는 경우 문제해결 및 작업을 참조하세요.

    출력 이벤트가 Normal이면 MCI 배포가 성공할 가능성이 높지만, 전체 트래픽 경로가 작동하는지 확인하려면 테스트를 해 보는 수밖에 없습니다.

  2. 애플리케이션이 /ping 엔드포인트로 VIP에서 제공되는지 확인합니다.

    curl INGRESS_VIP/ping
    

    INGRESS_VIP를 가상 IP(VIP) 주소로 바꿉니다.

    출력은 다음과 비슷합니다.

    {"Hostname":"34.98.102.37","Version":"1.0","GCPZone":"us-central1-a","Backend":"zone-ingress-5554bb95b4-svv5d"}
    

    출력에는 애플리케이션의 리전과 백엔드가 표시됩니다.

  3. 또한 브라우저에서 http://INGRESS_VIP URL로 이동하여 서비스가 제공되는 리전을 보여주는 애플리케이션의 그래픽 버전을 확인할 수 있습니다.

    트래픽이 전달되는 클러스터는 위치에 따라 다릅니다. GCLB는 클라이언트 트래픽을 용량이 있는 가장 가까운 백엔드로 전달하도록 설계되었습니다.

리소스 사양

MultiClusterService 사양

MultiClusterService 정의는 다음 두 요소로 구성됩니다.

  1. Kubernetes 클러스터에서 만들 서비스를 정의하는 template. template 섹션에는 일반적인 서비스에서 지원되는 필드가 포함되어 있지만, MultiClusterService에서는 selectorports 필드만 지원됩니다. 다른 필드는 무시됩니다.

  2. 트래픽을 수신하는 클러스터와 각 클러스터의 부하 분산 속성을 정의하는 선택적 clusters 섹션. clusters 섹션을 지정하지 않거나 나열된 클러스터가 없으면 기본적으로 모든 클러스터가 사용됩니다.

다음 매니페스트에서는 표준 MCS를 설명합니다.

apiVersion: networking.gke.io/v1
kind: MultiClusterService
metadata:
  name: NAME
  namespace: NAMESPACE
spec:
  template:
    spec:
      selector:
        app: POD_LABEL
      ports:
      - name: web
        protocol: TCP
        port: PORT
        targetPort: TARGET_PORT

다음을 바꿉니다.

  • NAME: MCS의 이름입니다. 이 이름은 MCI 리소스의 serviceName 필드에서 참조됩니다.
  • NAMESPACE: MCS가 배포되는 Kubernetes 네임스페이스입니다. Fleet의 모든 클러스터 간에 MCI 및 포드와 동일한 네임스페이스에 있어야 합니다.
  • POD_LABEL: Fleet의 모든 클러스터에서 이 MCS의 백엔드로 선택되는 포드를 결정하는 라벨입니다.
  • PORT는 이 MCS를 참조하는 MCI에서 참조되는 포트와 일치해야 합니다.
  • TARGET_PORT: GCLB에서 포드로 트래픽을 전송하는 데 사용되는 포트입니다. NEG는 이 포트를 제공 포트로 포함하는 각 클러스터에 생성됩니다.

MultiClusterIngress 사양

다음 mci.yaml은 부하 분산기 프런트엔드를 설명합니다.

apiVersion: networking.gke.io/v1
kind: MultiClusterIngress
metadata:
  name: NAME
  namespace: NAMESPACE
spec:
  template:
    spec:
      backend:
       serviceName: DEFAULT_SERVICE
       servicePort: PORT
      rules:
        - host: HOST_HEADER
          http:
            paths:
            - path: PATH
              backend:
                serviceName: SERVICE
                servicePort: PORT

다음을 바꿉니다.

  • NAME: MCI 리소스의 이름입니다.
  • NAMESPACE: MCI가 배포되는 Kubernetes 네임스페이스입니다. Fleet의 모든 클러스터 간에 MCS 및 포드와 동일한 네임스페이스에 있어야 합니다.
  • DEFAULT_SERVICE: 호스트 또는 경로 규칙과 일치하지 않는 모든 트래픽의 기본 백엔드 역할을 합니다. 필수 입력란이며, 다른 호스트 또는 구성된 경로 일치가 있더라도 MCI에 기본 백엔드를 지정해야 합니다.
  • PORT: 유효한 포트 번호입니다. MCS 리소스의 port 필드와 일치해야 합니다.
  • HOST_HEADER: HTTP 호스트 헤더 필드를 기준으로 트래픽을 일치시킵니다. host 필드는 선택사항입니다.
  • PATH: HTTP URL의 경로를 통해 트래픽을 일치시킵니다. path 필드는 선택사항입니다.
  • SERVICE: 이 MCI와 동일한 네임스페이스 및 구성 클러스터에 배포되는 MCS의 이름입니다.

멀티 클러스터 인그레스 기능

이 섹션에서는 추가적으로 멀티 클러스터 인그레스 기능을 구성하는 방법을 보여줍니다.

클러스터 선택

기본적으로 멀티 클러스터 인그레스에서 파생된 서비스는 모든 구성원 클러스터에서 예약됩니다. 하지만 특정 클러스터에 인그레스 규칙을 적용할 수 있습니다. 사용 사례의 예시는 다음과 같습니다.

  • 멀티 클러스터 인그레스를 모든 클러스터에 적용합니다. 단, 구성 클러스터의 격리를 위해 구성 클러스터는 제외합니다.
  • 블루-그린 방식으로 클러스터 간에 워크로드를 마이그레이션합니다.
  • 클러스터의 하위 집합에만 있는 애플리케이션 백엔드로 라우팅합니다.
  • 다른 클러스터에 있는 백엔드로의 호스트/경로 라우팅에 L7 VIP 1개를 사용합니다.

클러스터 선택에서는 MultiClusterService 객체의 리전/이름을 기준으로 클러스터를 선택할 수 있습니다. 그러면 멀티 클러스터 인그레스가 가리키는 클러스터와 파생된 서비스의 예약 조건을 제어할 수 있습니다. 동일한 Fleet 및 리전 내의 클러스터 이름이 같아서는 안 됩니다. 그래야 클러스터를 고유하게 참조할 수 있습니다.

  1. mcs.yaml 열기

    apiVersion: networking.gke.io/v1
    kind: MultiClusterService
    metadata:
      name: zone-mcs
      namespace: zoneprinter
    spec:
      template:
        spec:
          selector:
            app: zoneprinter
          ports:
          - name: web
            protocol: TCP
            port: 8080
            targetPort: 8080
    

    현재 이 사양은 모든 클러스터에 파생된 서비스를 만듭니다(기본 동작).

  2. 클러스터 섹션에 다음 줄을 추가합니다.

    apiVersion: networking.gke.io/v1
    kind: MultiClusterService
    metadata:
      name: zone-mcs
      namespace: zoneprinter
    spec:
      template:
        spec:
          selector:
            app: zoneprinter
          ports:
          - name: web
            protocol: TCP
            port: 8080
            targetPort: 8080
      clusters:
      - link: "us-central1-a/gke-us"
      - link: "europe-west1-c/gke-eu"
    

    이 예시에서는 gke-us 및 gke-eu 클러스터에만 파생된 서비스 리소스를 만듭니다. 인그레스 규칙을 선택적으로 적용하려면 클러스터를 선택해야 합니다. MultiClusterService의 '클러스터' 섹션을 지정하지 않거나 나열된 클러스터가 없으면 기본값인 '전체' 클러스터로 해석됩니다.

HTTPS 지원

Kubernetes 보안 비밀은 HTTPS를 지원합니다. HTTPS 지원을 사용 설정하려면 먼저 고정 IP 주소를 만들어야 합니다. 이 고정 IP를 사용하면 HTTP와 HTTPS가 동일한 IP 주소를 공유할 수 있습니다. 자세한 내용은 고정 IP 만들기를 참조하세요.

고정 IP 주소를 만든 후에는 보안 비밀을 만들 수 있습니다.

  1. 보안 비밀을 만듭니다.

    kubectl -n prod create secret tls SECRET_NAME --key PATH_TO_KEYFILE --cert PATH_TO_CERTFILE
    

    다음을 바꿉니다.

    • SECRET_NAME을 보안 비밀 이름으로 바꿉니다.
    • PATH_TO_KEYFILE을 TLS 키 파일의 경로로 바꿉니다.
    • PATH_TO_CERTFILE을 TLS 인증서 파일의 경로로 바꿉니다.
  2. mci.yaml 파일을 보안 비밀 이름으로 업데이트합니다.

    apiVersion: networking.gke.io/v1
    kind: MultiClusterIngress
    metadata:
      name: zone-ingress
      namespace: zoneprinter
      annotations:
        networking.gke.io/static-ip: STATIC_IP_ADDRESS
    spec:
      template:
        spec:
          backend:
            serviceName: zone-mcs
            servicePort: 8080
          tls:
          - secretName: SECRET_NAME
    

    SECRET_NAME을 보안 비밀 이름으로 바꿉니다. STATIC_IP_ADDRESS는 IP 주소 또는 고정 IP 만들기 섹션에서 할당한 주소의 전체 URL입니다.

  3. MultiClusterIngress 리소스를 다시 배포합니다.

    kubectl apply -f mci.yaml
    

    출력은 다음과 비슷합니다.

    multiclusteringress.networking.gke.io/zone-ingress configured
    

BackendConfig 지원

BackendConfig CRD를 사용하면 Compute Engine BackendService 리소스의 설정을 맞춤설정할 수 있습니다. 지원되는 사양은 다음과 같습니다.

apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
  name: zone-health-check-cfg
  namespace: zoneprinter
spec:
  healthCheck:
    checkIntervalSec: [int]
    timeoutSec: [int]
    healthyThreshold: [int]
    unhealthyThreshold: [int]
    type: [HTTP | HTTPS | HTTP2 | TCP]
    port: [int]
    requestPath: [string]
  timeoutSec: [int]
  connectionDraining:
    drainingTimeoutSec: [int]
  sessionAffinity:
    affinityType: [CLIENT_IP | CLIENT_IP_PORT_PROTO | CLIENT_IP_PROTO | GENERATED_COOKIE | HEADER_FIELD | HTTP_COOKIE | NONE]
    affinityCookieTtlSec: [int]
  cdn:
    enabled: [bool]
    cachePolicy:
      includeHost: [bool]
      includeQueryString: [bool]
      includeProtocol: [bool]
      queryStringBlacklist: [string list]
      queryStringWhitelist: [string list]
  securityPolicy:
    name: ca-how-to-security-policy
  logging:
    enable: [bool]
    sampleRate: [float]
  iap:
    enabled: [bool]
    oauthclientCredentials:
      secretName: [string]

BackendConfig를 사용하려면 주석을 사용하여 MultiClusterService 리소스에서 연결합니다.

apiVersion: networking.gke.io/v1
kind: MultiClusterService
metadata:
  name: zone-mcs
  namespace: zoneprinter
  annotations:
    beta.cloud.google.com/backend-config: '{"ports": {"8080":"zone-health-check-cfg"}}'
spec:
 template:
   spec:
     selector:
       app: zoneprinter
     ports:
     - name: web
       protocol: TCP
       port: 8080
       targetPort: 8080

BackendConfig 시맨틱스에 대한 상세 설명은 서비스 포트를 BackendConfig와 연결을 참조하세요.

gRPC 지원

멀티 클러스터 인그레스에서 gRPC 애플리케이션을 구성하려면 매우 구체적인 설정이 필요합니다. 부하 분산기를 올바르게 설정하기 위한 몇 가지 팁은 다음과 같습니다.

  1. 부하 분산기에서 애플리케이션으로의 트래픽이 HTTP/2인지 확인합니다. 이를 구성하려면 애플리케이션 프로토콜을 사용합니다.
  2. HTTP/2의 요구사항에 따라 애플리케이션이 SSL용으로 올바르게 구성되었는지 확인합니다. 자체 서명된 인증서를 사용할 수 있습니다.
  3. L7 외부 부하 분산기에는 mTLS가 지원되지 않기 때문에 애플리케이션에서 mTLS를 해제해야 합니다.

리소스 수명 주기

구성 변경사항

MultiClusterIngressMultiClusterService 리소스는 표준 Kubernetes 객체처럼 동작하므로 객체 변경사항은 시스템에 비동기식으로 반영됩니다. 변경사항으로 인해 구성이 무효화되면 연결된 Google Cloud 객체는 변경되지 않고 그대로 유지되지만 객체 이벤트 스트림에서 오류가 발생합니다. 구성과 연결된 오류가 이벤트로 보고됩니다.

Kubernetes 리소스 관리

인그레스 객체를 삭제하면 HTTP(S) 부하 분산기가 해제되므로 트래픽이 더 이상 정의된 MultiClusterService에 전달되지 않습니다.

MultiClusterService를 삭제하면 각 클러스터에서 연결된 파생 서비스가 삭제됩니다.

클러스터 관리

부하 분산기에서 타겟팅하는 클러스터 집합은 멤버십을 추가하거나 삭제하여 변경할 수 있습니다.

예를 들어 인그레스의 백엔드로서 gke-eu 클러스터를 삭제하려면 다음을 실행합니다.

gcloud container hub memberships unregister CLUSTER_NAME \
  --gke-uri=URI

다음을 바꿉니다.

  • CLUSTER_NAME: 클러스터 이름입니다.
  • URI: GKE 클러스터의 URI입니다.

유럽에 클러스터를 추가하려면 다음을 실행합니다.

gcloud container hub memberships register europe-cluster \
  --context=europe-cluster --service-account-key-file=PATH_TO_SERVICE_ACCOUNT_KEY_FILE

PATH_TO_SERVICE_ACCOUNT_KEY_FILE을 서비스 계정의 키 파일 경로로 바꿉니다.

클러스터를 등록하거나 등록 취소하면 모든 인그레스의 백엔드 상태가 변경됩니다. 위의 예시에서 gke-eu 클러스터를 등록 취소하면 이 클러스터는 생성된 모든 인그레스에서 사용 가능한 백엔드로도 삭제됩니다. 반대의 경우 즉, 새 클러스터를 등록하는 경우도 마찬가지입니다.

멀티 클러스터 인그레스 사용 중지

멀티 클러스터 인그레스를 중지하기 전에 먼저 MultiClusterIngressMultiClusterService 리소스를 삭제하고 연결된 모든 네트워킹 리소스가 삭제되었는지 확인해야 합니다.

그런 후 멀티 클러스터 인그레스를 중지하기 위해 다음 명령어를 사용합니다.

gcloud alpha container hub ingress disable

멀티 클러스터 인그레스를 중지하기 전에 MultiClusterIngressMultiClusterService 리소스를 삭제하지 않으면 다음과 비슷한 오류가 발생할 수 있습니다.

Feature has associated resources that should be cleaned up before deletion.

멀티 클러스터 인그레스를 강제로 중지하려면 다음 명령어를 사용합니다.

gcloud alpha container hub ingress disable --force

주석

다음 주석은 MultiClusterIngressMultiClusterService 리소스에서 지원됩니다.

MultiClusterIngress 주석

주석 설명
networking.gke.io/frontend-config MultiClusterIngress 리소스와 동일한 네임스페이스의 FrontendConfig 리소스를 참조합니다.
networking.gke.io/static-ip 전역 고정 IP의 리터럴 IP 주소를 나타냅니다.
networking.gke.io/pre-shared-certs 전역 SSLCertificate 리소스를 나타냅니다.

MultiClusterService 주석

주석 설명
networking.gke.io/app-protocols 이 주석을 사용하여 부하 분산기와 애플리케이션 간의 통신 프로토콜을 설정합니다. 가능한 프로토콜은 HTTP, HTTPS, HTTP/2입니다. 부하 분산기와 애플리케이션 간 HTTPS인그레스를 사용한 부하 분산용 HTTP/2를 참조하세요.
beta.cloud.google.com/backend-config 이 주석을 사용하여 servicePort와 연결된 백엔드 서비스를 구성합니다. 자세한 내용은 인그레스 기능을 참조하세요.

SSL 정책 및 HTTPS 리디렉션

FrontendConfig 리소스를 사용하여 SSL 정책과 HTTPS 리디렉션을 구성할 수 있습니다. SSL 정책을 사용하면 부하 분산기에서 허용되는 암호화 스위트와 TLS 버전을 지정할 수 있습니다. HTTPS 리디렉션을 사용하면 HTTP/포트 80에서 HTTPS/포트 443으로 리디렉션을 시행할 수 있습니다. 다음 단계에서는 SSL 정책 및 HTTPS 리디렉션을 함께 구성합니다. 이것들은 독립적으로 구성할 수도 있습니다.

  1. TLS v1.2보다 낮은 버전을 사용하여 요청을 거부하는 SSL 정책을 만듭니다.

    gcloud compute ssl-policies create tls-12-policy \
     --profile MODERN \
     --min-tls-version 1.2 \
     --project=PROJECT_ID
    

    PROJECT_ID를 GKE 클러스터가 실행되는 프로젝트 ID로 바꿉니다.

  2. 정책이 생성되었는지 확인합니다.

    gcloud compute ssl-policies list --project=PROJECT_ID
    

    출력은 다음과 비슷합니다.

    NAME           PROFILE  MIN_TLS_VERSION
    tls-12-policy  MODERN   TLS_1_2
    
  3. 이 예시와 같이 foo.example.com의 인증서를 만듭니다. key.pemcert.pem이 준비되었으면 이러한 사용자 인증 정보를 MultiClusterIngress 리소스에서 참조되는 보안 비밀로 저장합니다.

    kubectl -n multi-cluster-demo create secret tls SECRET_NAME --key key.pem --cert cert.pem
    
  4. 다음 FrontendConfig 리소스를 frontendconfig.yaml로 저장합니다. FrontendConfig 내에서 지원되는 필드에 대한 자세한 내용은 FrontendConfig 리소스 구성을 참조하세요.

    apiVersion: networking.gke.io/v1beta1
    kind: FrontendConfig
    metadata:
      name: frontend-redirect-tls-policy
      namespace: multi-cluster-demo
    spec:
      sslPolicy: tls-12-policy
      redirectToHttps:
        enabled: true
    

    이 FrontendConfig는 HTTPS 리디렉션과 최소 TLS 버전 1.2를 시행하는 SSL 정책을 사용 설정합니다.

  5. frontendconfig.yaml을 구성 클러스터에 배포합니다.

    kubectl apply -f frontendconfig.yaml --context MCI_CONFIG_CLUSTER
    

    MCI_CONFIG_CLUSTER구성 클러스터의 이름으로 바꿉니다.

  6. 다음 MultiClusterIngress를 mci-frontendconfig.yaml로 저장합니다.

    apiVersion: networking.gke.io/v1
    kind: MultiClusterIngress
    metadata:
      name: foo-ingress
      namespace: multi-cluster-demo
      annotations:
        networking.gke.io/frontend-config: frontend-redirect-tls-policy
        networking.gke.io/static-ip: STATIC_IP_ADDRESS
    spec:
      template:
        spec:
          backend:
            serviceName: default-backend
            servicePort: 8080
          rules:
          - host: foo.example.com
            http:
              paths:
                - backend:
                    serviceName: foo
                    servicePort: 8080
          tls:
          - secretName: SECRET_NAME
    
    • STATIC_IP_ADDRESS를 이미 프로비저닝한 고정 전역 IP 주소로 바꿉니다.
    • SECRET_NAMEfoo.example.com 인증서가 저장된 보안 비밀로 바꿉니다.

    HTTPS 리디렉션을 사용 설정할 때는 두 가지 요구사항이 있습니다.

    • TLS는 spec.tls 필드 또는 사전 공유된 인증서 주석 networking.gke.io/pre-shared-certs을 통해 사용 설정해야 합니다. HTTPS 리디렉션을 사용 설정했더라도 HTTPS를 사용 설정하지 않으면 MultiClusterIngress가 배포되지 않습니다.
    • 고정 IP는 networking.gke.io/static-ip 주석을 통해 참조되어야 합니다. MultiClusterIngress에서 HTTPS를 사용 설정할 때는 고정 IP가 필요합니다.
  7. 구성 클러스터에 MultiClusterIngress를 배포합니다.

    kubectl apply -f mci-frontendconfig.yaml --context MCI_CONFIG_CLUSTER
    
  8. 1~2분 정도 기다린 후 foo-ingress를 검사합니다.

    kubectl describe mci foo-ingress --context MCI_CONFIG_CLUSTER
    

    성공한 출력은 다음과 비슷합니다.

    • Cloud Resources 상태에 리소스 이름이 채워집니다.
    • VIP 필드는 부하 분산기 IP 주소로 채워집니다.
    Name:         foobar-ingress
    Namespace:    multi-cluster-demo
    
    ...
    
    Status:
      Cloud Resources:
        Backend Services:
          mci-otn9zt-8080-multi-cluster-demo-bar
          mci-otn9zt-8080-multi-cluster-demo-default-backend
          mci-otn9zt-8080-multi-cluster-demo-foo
        Firewalls:
          mci-otn9zt-default-l7
        Forwarding Rules:
          mci-otn9zt-fw-multi-cluster-demo-foobar-ingress
          mci-otn9zt-fws-multi-cluster-demo-foobar-ingress
        Health Checks:
          mci-otn9zt-8080-multi-cluster-demo-bar
          mci-otn9zt-8080-multi-cluster-demo-default-backend
          mci-otn9zt-8080-multi-cluster-demo-foo
        Network Endpoint Groups:
          zones/europe-west1-b/networkEndpointGroups/k8s1-1869d397-multi-cluste-mci-default-backend-svc--80-9e362e3d
          zones/europe-west1-b/networkEndpointGroups/k8s1-1869d397-multi-cluster--mci-bar-svc-067a3lzs8-808-89846515
          zones/europe-west1-b/networkEndpointGroups/k8s1-1869d397-multi-cluster--mci-foo-svc-820zw3izx-808-8bbcb1de
          zones/us-central1-b/networkEndpointGroups/k8s1-a63e24a6-multi-cluste-mci-default-backend-svc--80-a528cc75
          zones/us-central1-b/networkEndpointGroups/k8s1-a63e24a6-multi-cluster--mci-bar-svc-067a3lzs8-808-36281739
          zones/us-central1-b/networkEndpointGroups/k8s1-a63e24a6-multi-cluster--mci-foo-svc-820zw3izx-808-ac733579
        Target Proxies:
          mci-otn9zt-multi-cluster-demo-foobar-ingress
          mci-otn9zt-multi-cluster-demo-foobar-ingress
        URL Map:  mci-otn9zt-rm-multi-cluster-demo-foobar-ingress
      VIP:        34.149.29.76
    Events:
      Type     Reason  Age                From                              Message
      ----     ------  ----               ----                              -------
      Normal   UPDATE  38m (x5 over 62m)  multi-cluster-ingress-controller  multi-cluster-demo/foobar-ingress
    
  9. curl을 통해 HTTP 요청을 전송하여 HTTPS 리디렉션이 올바르게 작동하는지 확인합니다.

    curl VIP
    

    VIP를 MultiClusterIngress IP 주소로 바꿉니다.

    요청이 HTTPS 포트로 리디렉션되었음이 출력에 표시되며, 이는 리디렉션이 올바르게 작동하고 있음을 나타냅니다.

  10. TLS 버전 1.1을 사용해서 HTTPS 요청을 전송하여 TLS 정책이 올바르게 작동하는지 확인합니다. 이 도메인에 대해 DNS가 구성되지 않았으므로 --resolve 옵션을 사용하여 curl에 IP 주소를 직접 확인하도록 지정합니다.

    curl https://foo.example.com --resolve foo.example.com:443:VIP --cacert CERT_FILE -v
    

    이 단계에서는 MultiClusterIngress 보호에 사용되는 인증서 PEM 파일이 필요합니다. 성공한 출력은 다음과 비슷합니다.

    ...
    * SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
    * ALPN, server accepted to use h2
    * Server certificate:
    *  subject: O=example; CN=foo.example.com
    *  start date: Sep  1 10:32:03 2021 GMT
    *  expire date: Aug 27 10:32:03 2022 GMT
    *  common name: foo.example.com (matched)
    *  issuer: O=example; CN=foo.example.com
    *  SSL certificate verify ok.
    * Using HTTP2, server supports multi-use
    * Connection state changed (HTTP/2 confirmed)
    * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
    * Using Stream ID: 1 (easy handle 0x7fa10f00e400)
    > GET / HTTP/2
    > Host: foo.example.com
    > User-Agent: curl/7.64.1
    > Accept: */*
    >
    * Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
    < HTTP/2 200
    < content-type: application/json
    < content-length: 308
    < access-control-allow-origin: *
    < server: Werkzeug/1.0.1 Python/3.8.6
    < date: Wed, 01 Sep 2021 11:39:06 GMT
    < via: 1.1 google
    < alt-svc: clear
    <
    {"cluster_name":"gke-us","host_header":"foo.example.com","metadata":"foo","node_name":"gke-gke-us-default-pool-22cb07b1-r5r0.c.mark-church-project.internal","pod_name":"foo-75ccd9c96d-dkg8t","pod_name_emoji":"👞","project_id":"mark-church-project","timestamp":"2021-09-01T11:39:06","zone":"us-central1-b"}
    * Connection #0 to host foo.example.com left intact
    * Closing connection 0
    

    응답 코드는 200이고 모든 것이 올바르게 작동하고 있음을 나타내는 TLSv1.2가 사용됩니다.

    그런 다음 TLS 1.1로 연결을 시도하여 SSL 정책이 올바른 TLS 버전을 시행하는지 확인할 수 있습니다. 이 단계가 작동하려면 SSL 정책이 최소 버전 1.2로 구성되어야 합니다.

  11. 이전 단계의 동일한 요청을 전송하되 TLS 버전 1.1을 시행합니다.

    curl https://foo.example.com --resolve foo.example.com:443:VIP -v \
      --cacert CERT_FILE \
      --tls-max 1.1
    

    성공한 출력은 다음과 비슷합니다.

    * Added foo.example.com:443:34.149.29.76 to DNS cache
    * Hostname foo.example.com was found in DNS cache
    *   Trying 34.149.29.76...
    * TCP_NODELAY set
    * Connected to foo.example.com (34.149.29.76) port 443 (#0)
    * ALPN, offering h2
    * ALPN, offering http/1.1
    * successfully set certificate verify locations:
    *   CAfile: cert.pem
      CApath: none
    * TLSv1.1 (OUT), TLS handshake, Client hello (1):
    * TLSv1.1 (IN), TLS alert, protocol version (582):
    * error:1400442E:SSL routines:CONNECT_CR_SRVR_HELLO:tlsv1 alert protocol version
    * Closing connection 0
    curl: (35) error:1400442E:SSL routines:CONNECT_CR_SRVR_HELLO:tlsv1 alert protocol version
    

    TLS 핸드셰이크를 완료하지 못하면 SSL 정책이 TLS 1.1을 성공적으로 차단했음을 나타냅니다.

고정 IP 만들기

  1. 고정 IP를 할당합니다.

    gcloud compute addresses create ADDRESS_NAME --global
    

    ADDRESS_NAME을 할당할 고정 IP의 이름으로 바꿉니다.

    출력에는 다음과 비슷하게 생성된 주소의 전체 URL이 포함됩니다.

    Created [https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/addresses/ADDRESS_NAME].
    
  2. 방금 만든 IP 주소를 확인합니다.

    gcloud compute addresses list
    

    출력은 다음과 비슷합니다.

    NAME          ADDRESS/RANGE  TYPE      STATUS
    ADDRESS_NAME  STATIC_IP_ADDRESS  EXTERNAL  RESERVED
    

    이 출력에는 다음이 포함됩니다.

    • 정의한 ADDRESS_NAME
    • 할당된 STATIC_IP_ADDRESS
  3. 고정 IP로 mci.yaml 파일을 업데이트합니다.

    apiVersion: networking.gke.io/v1
    kind: MultiClusterIngress
    metadata:
      name: zone-ingress
      namespace: zoneprinter
    annotations:
      networking.gke.io/static-ip: STATIC_IP_ADDRESS
    spec:
      template:
        spec:
          backend:
            serviceName: zone-mcs
            servicePort: 8080
    

    STATIC_IP_ADDRESS를 다음 중 하나로 바꿉니다.

    • 34.102.201.47과 비슷한 할당된 IP 주소
    • "https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/addresses/ADDRESS_NAME"과 비슷한 생성된 주소의 전체 URL

    STATIC_IP_ADDRESS는 리소스 이름이 아닙니다(ADDRESS_NAME).

  4. MultiClusterIngress 리소스를 다시 배포합니다.

    kubectl apply -f mci.yaml
    

    출력은 다음과 비슷합니다.

    multiclusteringress.networking.gke.io/zone-ingress configured
    
  5. 성공한 배포 상태 검증의 단계에 따라 배포가 STATIC_IP_ADDRESS로 작동하는지 확인합니다.

사전 공유 인증서

사전 공유 인증서는 Kubernetes 보안 비밀에 저장된 인증서 대신 부하 분산기에서 TLS 종료에 사용할 수 있는 인증서로, Google Cloud에 업로드됩니다. 이러한 인증서는 대역 외 GKE에서 Google Cloud로 업로드되며 멀티 클러스터 인그레스 객체에서 참조합니다. 사전 공유 인증서 또는 Kubernetes 보안 비밀을 통해 여러 인증서도 지원됩니다.

멀티 클러스터 인그레스에서 인증서를 사용하려면 networking.gke.io/pre-shared-certs 주석과 인증서의 이름이 필요합니다. 특정 멀티 클러스터 인그레스 객체에 여러 인증서가 지정되면 각 인증서는 미리 지정된 순서에 따라 클라이언트에 표시됩니다.

다음을 실행하여 사용 가능한 SSL 인증서를 나열할 수 있습니다.

gcloud compute ssl-certificates list

아래 예시에서는 도메인 이름과 일치하는 각 인증서가 표시되도록 사전 공유 인증서의 일반 이름과 일치하는 지정된 호스트 중 하나의 호스트로 전달되는 클라이언트 트래픽을 설명합니다.

kind: MultiClusterIngress
metadata:
  name: shopping-service
  namespace: prod
  annotations:
    networking.gke.io/pre-shared-certs: "domain1-cert, domain2-cert"
spec:
  template:
    spec:
      rules:
      - host: my-domain1.gcp.com
        http:
          paths:
          - backend:
              serviceName: domain1-svc
              servicePort: 443
      - host: my-domain2.gcp.com
        http:
          paths:
          - backend:
              serviceName: domain2-svc
              servicePort: 443

Google 관리형 인증서

Google 관리형 인증서는 멀티 클러스터 인그레스에서 networking.gke.io/pre-shared-certs 주석을 통해 지원됩니다. 멀티 클러스터 인증서는 MultiClusterIngress 리소스에 대한 Google 관리형 인증서 첨부를 지원합니다. 하지만 단일 클러스터 인그레스와 달리 Kubernetes ManagedCertificate 리소스의 선언적 생성은 멀티 클러스터 인증서에서 지원되지 않습니다. Google 관리형 인증서 원본 만들기는 MultiClusterIngress에 연결하기 전 compute ssl-certificates create API를 통해 직접 수행되어야 합니다. 이 작업은 다음 단계에 따라 수행될 수 있습니다.

  1. 여기 1단계에서 Google 관리형 인증서를 만듭니다. 멀티 클러스터 인그레스가 인증서를 연결하므로 2단계로 이동하지 마세요.

    gcloud compute ssl-certificates create my-google-managed-cert \
        --domains=my-domain.gcp.com \
        --global
    
  2. networking.gke.io/pre-shared-certs 주석을 사용하여 MultiClusterIngress에서 인증서 이름을 참조합니다.

    kind: MultiClusterIngress
    metadata:
    name: shopping-service
    namespace: prod
    annotations:
      networking.gke.io/pre-shared-certs: "my-google-managed-cert"
    spec:
    template:
      spec:
        rules:
        - host: my-domain.gcp.com
          http:
            paths:
            - backend:
                serviceName: my-domain-svc
                servicePort: 8080
    

앞의 매니페스트는 백엔드 GKE 클러스터에 대해 트래픽을 종료할 수 있도록 인증서를 MultiClusterIngress에 연결합니다. Google Cloud는 인증서 만료 전 인증서를 자동으로 갱신합니다. 갱신은 투명하게 수행되며 멀티 클러스터 인그레스에 대해 어떠한 업데이트도 요구하지 않습니다.

애플리케이션 프로토콜

부하 분산기 프록시와 애플리케이션 간의 연결에는 기본적으로 HTTP가 사용됩니다. networking.gke.io/app-protocols 주석을 사용하면 요청을 애플리케이션으로 전달할 때 HTTPS 또는 HTTP/2를 사용하도록 부하 분산기를 구성할 수 있습니다. 다음 예시의 annotation 필드에서 http2MultiClusterService 포트 이름을 나타내고 HTTP2는 부하 분산기가 사용하는 프로토콜을 나타냅니다.

kind: MultiClusterService
metadata:
  name: shopping-service
  namespace: prod
  annotations:
    networking.gke.io/app-protocols: '{"http2":"HTTP2"}'
spec:
  template:
    spec:
      ports:
      - port: 443
        name: http2

BackendConfig

주석을 구성하는 방법은 상단 섹션을 참조하세요.

다음 단계