관리형 Kubernetes에 Windows 애플리케이션 배포

Last reviewed 2024-08-14 UTC

이 문서에서는 관리형 Kubernetes에서 실행되는 Windows 애플리케이션의 네트워킹을 관리하고 조정에서 참조 아키텍처를 배포하는 방법을 설명합니다.

이 안내는 Google Kubernetes Engine (GKE) 클러스터에서 실행되는 Windows 애플리케이션의 설계 및 관리를 담당하는 클라우드 설계자, 네트워크 관리자, IT 전문가를 대상으로 합니다.

아키텍처

다음 다이어그램은 관리형 GKE 클러스터에서 실행되는 Windows 애플리케이션을 배포할 때 사용하는 참조 아키텍처를 보여줍니다.

데이터는 내부 애플리케이션 부하 분산기와 Envoy 게이트웨이를 통해 흐릅니다.

위의 다이어그램에서 화살표는 Cloud Service Mesh 및 Envoy 게이트웨이를 사용하여 GKE에서 실행되는 Windows 애플리케이션의 네트워킹을 관리하는 워크플로를 나타냅니다. 지역 GKE 클러스터에는 Windows 노드 풀과 Linux 노드 풀이 모두 포함됩니다. Cloud Service Mesh는 Windows 포드로의 트래픽 경로를 생성하고 관리합니다.

목표

  • Windows 애플리케이션과 Envoy 프록시를 실행할 GKE 클러스터를 만들고 설정합니다.
  • Windows 애플리케이션을 배포하고 확인합니다.
  • Cloud Service Mesh를 Envoy 게이트웨이의 제어 영역으로 구성합니다.
  • Kubernetes Gateway API를 사용하여 내부 애플리케이션 부하 분산기를 프로비저닝하고 Envoy 게이트웨이를 노출합니다.
  • 만든 지속적 배포 작업을 이해합니다.

비용

이 아키텍처 배포에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.

이 배치를 마친 후에 계속 비용이 청구되지 않도록 하려면 만든 리소스를 삭제하면 됩니다. 자세한 내용은 삭제를 참조하세요.

시작하기 전에

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  2. Make sure that billing is enabled for your Google Cloud project.

  3. Enable the Cloud Shell, and Cloud Service Mesh APIs.

    Enable the APIs

  4. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

공유 VPC 환경에서 실행하는 경우 Cloud Load Balancing 응답성 확인을 위해 프록시 전용 서브넷 및 방화벽 규칙을 수동으로 만드는 안내도 따라야 합니다.

GKE 클러스터 만들기

다음 단계에 따라 GKE 클러스터를 만듭니다. GKE 클러스터를 사용하여 이 배포에서 Windows 애플리케이션과 Envoy 프록시를 포함하고 실행합니다.

  1. Cloud Shell에서 다음 Google Cloud CLI 명령어를 실행하여 세 개의 리전에 각각 노드 하나가 있는 리전별 GKE 클러스터를 만듭니다.

    gcloud container clusters create my-cluster
        --enable-ip-alias \
        --num-nodes=1 \
        --release-channel stable \
        --enable-dataplane-v2 \
        --region us-central1 \
        --scopes=cloud-platform \
        --gateway-api=standard
    
  2. GKE 클러스터에 Windows 노드 풀을 추가합니다.

    gcloud container node-pools create win-pool \
        --cluster=my-cluster \
        --image-type=windows_ltsc_containerd \
        --no-enable-autoupgrade \
        --region=us-central1 \
        --num-nodes=1 \
        --machine-type=n1-standard-2 \
        --windows-os-version=ltsc2019
    

    이 작업을 완료하는 데 약 20분이 걸릴 수 있습니다.

  3. Google Cloud 프로젝트 ID를 환경 변수에 저장합니다.

    export PROJECT_ID=$(gcloud config get project)
    
  4. GKE 클러스터에 연결합니다.

    gcloud container clusters get-credentials my-cluster --region us-central1
    
  5. GKE 클러스터의 모든 노드를 나열합니다.

    kubectl get nodes
    

    출력에 Linux 노드 3개와 Windows 노드 3개가 표시됩니다.

    GKE 클러스터가 준비되면 Windows 기반 테스트 애플리케이션 2개를 배포할 수 있습니다.

테스트 애플리케이션 2개 배포

이 섹션에서는 Windows 기반 테스트 애플리케이션 2개를 배포합니다. 두 테스트 애플리케이션 모두 애플리케이션이 실행되는 호스트 이름을 출력합니다. 또한 독립형 네트워크 엔드포인트 그룹 (NEG)을 통해 애플리케이션을 노출하는 Kubernetes 서비스를 만듭니다.

지역 클러스터에 Windows 기반 애플리케이션과 Kubernetes 서비스를 배포하면 애플리케이션이 실행되는 각 영역에 NEG가 생성됩니다. 이 배포 가이드에서는 나중에 이러한 NEG를 Cloud Service Mesh 서비스의 백엔드로 구성하는 방법을 설명합니다.

  1. Cloud Shell에서 kubectl를 사용하여 다음 YAML 파일을 적용하여 첫 번째 테스트 애플리케이션을 배포합니다. 이 명령어는 각 지역 영역에 하나씩 테스트 애플리케이션의 인스턴스 3개를 배포합니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: win-webserver-1
      name: win-webserver-1
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: win-webserver-1
      template:
        metadata:
          labels:
            app: win-webserver-1
          name: win-webserver-1
        spec:
         containers:
          - name: windowswebserver
            image: k8s.gcr.io/e2e-test-images/agnhost:2.36
            command: ["/agnhost"]
            args: ["netexec", "--http-port", "80"]
         topologySpreadConstraints:
          - maxSkew: 1
            topologyKey: kubernetes.io/hostname
            whenUnsatisfiable: DoNotSchedule
            labelSelector:
              matchLabels:
                app: win-webserver-1
         nodeSelector:
          kubernetes.io/os: windows
    
  2. 일치하는 Kubernetes 서비스를 적용하고 NEG로 노출합니다.

    apiVersion: v1
    kind: Service
    metadata:
      name: win-webserver-1
      annotations:
        cloud.google.com/neg: '{"exposed_ports": {"80":{"name": "win-webserver-1"}}}'
    spec:
      type: ClusterIP
      selector:
        app: win-webserver-1
      ports:
      - name: http
        protocol: TCP
        port: 80
        targetPort: 80
    
  3. 배포를 확인합니다.

    kubectl get pods
    

    출력에는 애플리케이션에 실행 중인 Windows 포드가 3개 있음을 보여줍니다.

    NAME                               READY   STATUS    RESTARTS   AGE
    win-webserver-1-7bb4c57f6d-hnpgd   1/1     Running   0          5m58s
    win-webserver-1-7bb4c57f6d-rgqsb   1/1     Running   0          5m58s
    win-webserver-1-7bb4c57f6d-xp7ww   1/1     Running   0          5m58s
    
  4. Kubernetes 서비스가 생성되었는지 확인합니다.

    $ kubectl get svc
    

    다음과 유사한 결과가 출력됩니다.

    NAME              TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
    kubernetes        ClusterIP   10.64.0.1            443/TCP   58m
    win-webserver-1   ClusterIP   10.64.6.20           80/TCP    3m35s
    
  5. kubectl에 대해 describe 명령어를 실행하여 애플리케이션이 실행되는 각 영역에서 Kubernetes 서비스에 대해 상응하는 NEG가 생성되었는지 확인합니다.

    $ kubectl describe service win-webserver-1
    

    다음과 유사한 결과가 출력됩니다.

    Name:              win-webserver-1
    Namespace:         default
    Labels:            
    Annotations:       cloud.google.com/neg: {"exposed_ports": {"80":{"name": "win-webserver-1"}}}
                       cloud.google.com/neg-status: {"network_endpoint_groups":{"80":"win-webserver-1"},"zones":["us-central1-a","us-central1-b","us-central1-c"]}
    Selector:          app=win-webserver-1
    Type:              ClusterIP
    IP Family Policy:  SingleStack
    IP Families:       IPv4
    IP:                10.64.6.20
    IPs:               10.64.6.20
    Port:              http  80/TCP
    TargetPort:        80/TCP
    Endpoints:         10.60.3.5:80,10.60.4.5:80,10.60.5.5:80
    Session Affinity:  None
    Events:
      Type    Reason  Age    From            Message
      ----    ------  ----   ----            -------
      Normal  Create  4m25s  neg-controller  Created NEG "win-webserver-1" for default/win-webserver-1-win-webserver-1-http/80-80-GCE_VM_IP_PORT-L7 in "us-central1-a".
      Normal  Create  4m18s  neg-controller  Created NEG "win-webserver-1" for default/win-webserver-1-win-webserver-1-http/80-80-GCE_VM_IP_PORT-L7 in "us-central1-b".
      Normal  Create  4m11s  neg-controller  Created NEG "win-webserver-1" for default/win-webserver-1-win-webserver-1-http/80-80-GCE_VM_IP_PORT-L7 in "us-central1-c".
      Normal  Attach  4m9s   neg-controller  Attach 1 network endpoint(s) (NEG "win-webserver-1" in zone "us-central1-a")
      Normal  Attach  4m8s   neg-controller  Attach 1 network endpoint(s) (NEG "win-webserver-1" in zone "us-central1-c")
      Normal  Attach  4m8s   neg-controller  Attach 1 network endpoint(s) (NEG "win-webserver-1" in zone "us-central1-b")
    

    위 명령어의 출력은 각 영역에 NEG가 생성되었음을 보여줍니다.

  6. 선택사항: gcloud CLI를 사용하여 NEG가 생성되었는지 확인합니다.

    gcloud compute network-endpoint-groups list
    

    출력은 다음과 같습니다.

    NAME                                                        LOCATION            ENDPOINT_TYPE     SIZE
    win-webserver-1                                us-central1-a  GCE_VM_IP_PORT  1
    win-webserver-1                                us-central1-b  GCE_VM_IP_PORT  1
    win-webserver-1                                us-central1-c  GCE_VM_IP_PORT  1
    
  7. 두 번째 테스트 애플리케이션을 배포하려면 다음 YAML 파일을 적용합니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: win-webserver-2
      name: win-webserver-2
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: win-webserver-2
      template:
        metadata:
          labels:
            app: win-webserver-2
          name: win-webserver-2
        spec:
         containers:
          - name: windowswebserver
            image: k8s.gcr.io/e2e-test-images/agnhost:2.36
            command: ["/agnhost"]
            args: ["netexec", "--http-port", "80"]
         topologySpreadConstraints:
          - maxSkew: 1
            topologyKey: kubernetes.io/hostname
            whenUnsatisfiable: DoNotSchedule
            labelSelector:
              matchLabels:
                app: win-webserver-2
         nodeSelector:
          kubernetes.io/os: windows
    
  8. 상응하는 Kubernetes 서비스를 만듭니다.

    apiVersion: v1
    kind: Service
    metadata:
      name: win-webserver-2
      annotations:
        cloud.google.com/neg: '{"exposed_ports": {"80":{"name": "win-webserver-2"}}}'
    spec:
      type: ClusterIP
      selector:
        app: win-webserver-2
      ports:
      - name: http
        protocol: TCP
        port: 80
        targetPort: 80
    
  9. 애플리케이션 배포를 확인합니다.

    kubectl get pods
    

    출력을 확인하고 실행 중인 포드가 3개 있는지 확인합니다.

  10. Kubernetes 서비스와 NEG 3개가 생성되었는지 확인합니다.

    kubectl describe service win-webserver-2
    

Cloud Service Mesh 구성

이 섹션에서는 Cloud Service Mesh가 Envoy 게이트웨이의 컨트롤 플레인으로 구성됩니다.

scope_name 매개변수를 지정하여 Envoy 게이트웨이를 관련 Cloud Service Mesh 라우팅 구성에 매핑합니다. scope_name 매개변수를 사용하면 여러 Envoy 게이트웨이에 서로 다른 라우팅 규칙을 구성할 수 있습니다.

  1. Cloud Shell에서 애플리케이션 응답성을 확인하는 Google 서비스의 수신 트래픽을 허용하는 방화벽 규칙을 만듭니다.

    gcloud compute firewall-rules create allow-health-checks \
      --network=default \
      --direction=INGRESS \
      --action=ALLOW \
      --rules=tcp \
      --source-ranges="35.191.0.0/16,130.211.0.0/22,209.85.152.0/22,209.85.204.0/22"
    
  2. 첫 번째 애플리케이션의 응답성을 확인합니다.

    gcloud compute health-checks create http win-app-1-health-check \
      --enable-logging \
      --request-path="/healthz" \
      --use-serving-port
    
  3. 두 번째 애플리케이션의 응답성을 확인합니다.

    gcloud compute health-checks create http win-app-2-health-check \
      --enable-logging \
      --request-path="/healthz" \
      --use-serving-port
    
  4. 첫 번째 애플리케이션의 Cloud Service Mesh 백엔드 서비스를 만듭니다.

    gcloud compute backend-services create win-app-1-service \
     --global \
     --load-balancing-scheme=INTERNAL_SELF_MANAGED \
     --port-name=http \
     --health-checks win-app-1-health-check
    
  5. 두 번째 애플리케이션의 Cloud Service Mesh 백엔드 서비스를 만듭니다.

    gcloud compute backend-services create win-app-2-service \
     --global \
     --load-balancing-scheme=INTERNAL_SELF_MANAGED \
     --port-name=http \
     --health-checks win-app-2-health-check
    
  6. 이전에 만든 NEG를 추가합니다. 이러한 NEG는 Cloud Service Mesh 백엔드 서비스의 백엔드로 만든 첫 번째 애플리케이션과 연결됩니다. 이 코드 샘플은 만든 리전 클러스터의 각 영역에 NEG를 하나씩 추가합니다.

    BACKEND_SERVICE=win-app-1-service
    APP1_NEG_NAME=win-webserver-1
    MAX_RATE_PER_ENDPOINT=10
    
    gcloud compute backend-services add-backend $BACKEND_SERVICE \
      --global \
      --network-endpoint-group $APP1_NEG_NAME \
      --network-endpoint-group-zone us-central1-b \
      --balancing-mode RATE \
      --max-rate-per-endpoint $MAX_RATE_PER_ENDPOINT
    
    gcloud compute backend-services add-backend $BACKEND_SERVICE \
      --global \
      --network-endpoint-group $APP1_NEG_NAME \
      --network-endpoint-group-zone us-central1-a \
      --balancing-mode RATE \
      --max-rate-per-endpoint $MAX_RATE_PER_ENDPOINT
    
    gcloud compute backend-services add-backend $BACKEND_SERVICE \
      --global \
      --network-endpoint-group $APP1_NEG_NAME \
      --network-endpoint-group-zone us-central1-c \
      --balancing-mode RATE \
      --max-rate-per-endpoint $MAX_RATE_PER_ENDPOINT
    
  7. NEG를 추가합니다. 이러한 NEG는 Cloud Service Mesh 백엔드 서비스의 백엔드로 만든 두 번째 애플리케이션과 연결됩니다. 이 코드 샘플은 만든 리전 클러스터의 각 영역에 NEG를 하나씩 추가합니다.

    BACKEND_SERVICE=win-app-2-service
    APP2_NEG_NAME=win-webserver-2
    
    gcloud compute backend-services add-backend $BACKEND_SERVICE \
      --global \
      --network-endpoint-group $APP2_NEG_NAME \
      --network-endpoint-group-zone us-central1-b \
      --balancing-mode RATE \
      --max-rate-per-endpoint $MAX_RATE_PER_ENDPOINT
    
    gcloud compute backend-services add-backend $BACKEND_SERVICE \
      --global \
      --network-endpoint-group $APP2_NEG_NAME \
      --network-endpoint-group-zone us-central1-a \
      --balancing-mode RATE \
      --max-rate-per-endpoint $MAX_RATE_PER_ENDPOINT
    
    gcloud compute backend-services add-backend $BACKEND_SERVICE \
      --global \
      --network-endpoint-group $APP2_NEG_NAME \
      --network-endpoint-group-zone us-central1-c \
      --balancing-mode RATE \
      --max-rate-per-endpoint $MAX_RATE_PER_ENDPOINT
    

추가 Cloud Service Mesh 리소스 구성

이제 Cloud Service Mesh 서비스를 구성했으므로 Cloud Service Mesh 설정을 완료하려면 두 가지 리소스를 추가로 구성해야 합니다.

먼저 다음 단계에서는 Gateway 리소스를 구성하는 방법을 보여줍니다. Gateway 리소스는 Cloud Service Mesh 라우팅 규칙을 생성하는 데 사용되는 가상 리소스입니다. Cloud Service Mesh 라우팅 규칙은 Envoy 프록시를 게이트웨이로 구성하는 데 사용됩니다.

다음 단계에서는 각 백엔드 서비스에 HTTPRoute 리소스를 구성하는 방법을 보여줍니다. HTTPRoute 리소스는 HTTP 요청을 관련 백엔드 서비스에 매핑합니다.

  1. Cloud Shell에서 Gateway 리소스를 정의하는 gateway.yaml이라는 YAML 파일을 만듭니다.

    cat <<EOF> gateway.yaml
    name: gateway80
    scope: gateway-proxy
    ports:
    - 8080
    type: OPEN_MESH
    EOF
    
  2. gateway.yaml 파일을 호출하여 Gateway 리소스를 만듭니다.

    gcloud network-services gateways import gateway80 \
      --source=gateway.yaml \
      --location=global
    

    Gateway 이름은 projects/$PROJECT_ID/locations/global/gateways/gateway80입니다.

    각 백엔드 서비스의 HTTPRoutes를 만들 때 이 Gateway 이름을 사용합니다.

각 백엔드 서비스의 HTTPRoutes를 만듭니다.

  1. Cloud Shell에서 Google Cloud 프로젝트 ID를 환경 변수에 저장합니다.

    export PROJECT_ID=$(gcloud config get project)
    
  2. 첫 번째 애플리케이션의 HTTPRoute YAML 파일을 만듭니다.

    cat <<EOF> win-app-1-route.yaml
    name: win-app-1-http-route
    hostnames:
    - win-app-1
    gateways:
    - projects/$PROJECT_ID/locations/global/gateways/gateway80
    rules:
    - action:
       destinations:
       - serviceName: "projects/$PROJECT_ID/locations/global/backendServices/win-app-1-service"
    EOF
    
  3. 첫 번째 애플리케이션의 HTTPRoute 리소스를 만듭니다.

    gcloud network-services http-routes import win-app-1-http-route \
      --source=win-app-1-route.yaml \
      --location=global
    
  4. 두 번째 애플리케이션의 HTTPRoute YAML 파일을 만듭니다.

    cat <<EOF> win-app-2-route.yaml
    name: win-app-2-http-route
    hostnames:
    - win-app-2
    gateways:
    - projects/$PROJECT_ID/locations/global/gateways/gateway80
    rules:
    - action:
       destinations:
     - serviceName: "projects/$PROJECT_ID/locations/global/backendServices/win-app-2-service"
    EOF
    
  5. 두 번째 애플리케이션의 HTTPRoute 리소스를 만듭니다.

    gcloud network-services http-routes import win-app-2-http-route \
      --source=win-app-2-route.yaml \
      --location=global
    

Envoy 게이트웨이 배포 및 노출

두 개의 Windows 기반 테스트 애플리케이션과 Cloud Service Mesh를 만든 후 배포 YAML 파일을 만들어 Envoy 게이트웨이를 배포합니다. 배포 YAML 파일은 다음 작업을 실행합니다.

  • Envoy 게이트웨이를 부트스트랩합니다.
  • Cloud Service Mesh를 제어 영역으로 사용하도록 Envoy 게이트웨이를 구성합니다.
  • Gateway80라는 게이트웨이에 HTTPRoutes를 사용하도록 Envoy 게이트웨이를 구성합니다.

복제 Envoy 게이트웨이 2개를 배포합니다. 이 접근 방식은 게이트웨이를 내결함성 있게 만들고 중복을 제공하는 데 도움이 됩니다. 부하에 따라 Envoy 게이트웨이를 자동으로 확장하려면 원하는 경우 수평형 포드 자동 확장 처리를 구성하면 됩니다. 수평형 포드 자동 확장 처리를 구성하려면 수평형 포드 자동 확장 구성의 안내를 따라야 합니다.

  1. Cloud Shell에서 YAML 파일을 만듭니다.

    apiVersion: apps/v1
    kind: Deployment
        metadata:
      creationTimestamp: null
      labels:
        app: td-envoy-gateway
      name: td-envoy-gateway
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: td-envoy-gateway
      template:
        metadata:
          creationTimestamp: null
          labels:
            app: td-envoy-gateway
        spec:
          containers:
          - name: envoy
            image: envoyproxy/envoy:v1.21.6
            imagePullPolicy: Always
            resources:
              limits:
                cpu: "2"
                memory: 1Gi
              requests:
                cpu: 100m
                memory: 128Mi
            env:
            - name: ENVOY_UID
              value: "1337"
            volumeMounts:
              - mountPath: /etc/envoy
                name: envoy-bootstrap
          initContainers:
          - name: td-bootstrap-writer
            image: gcr.io/trafficdirector-prod/xds-client-bootstrap-generator
            imagePullPolicy: Always
            args:
              - --project_number='my_project_number'
              - --scope_name='gateway-proxy'
              - --envoy_port=8080
              - --bootstrap_file_output_path=/var/lib/data/envoy.yaml
              - --traffic_director_url=trafficdirector.googleapis.com:443
              - --expose_stats_port=15005
            volumeMounts:
              - mountPath: /var/lib/data
                name: envoy-bootstrap
          volumes:
            - name: envoy-bootstrap
              emptyDir: {}
    
    • 여기에서 my_project_number를 프로젝트 번호로 바꿉니다.

      • 다음 명령어를 실행하여 프로젝트 번호를 찾을 수 있습니다.
      gcloud projects describe $(gcloud config get project)
       --format="value(projectNumber)"
      

    포트 15005/stats라는 이름의 Envoy Admin 엔드포인트를 노출하는 데 사용됩니다. 다음 용도로도 사용됩니다.

    • 내부 애플리케이션 부하 분산기의 응답성 엔드포인트로
    • Envoy에서 Google Cloud Managed Service for Prometheus 측정항목을 사용하는 방법으로

    두 Envoy 게이트웨이 포드가 실행되면 ClusterIP 유형의 서비스를 만들어 노출합니다. BackendConfig라는 YAML 파일도 만들어야 합니다. BackendConfig는 비표준 응답성 검사를 정의합니다. 이 검사는 Envoy 게이트웨이의 응답성을 확인하는 데 사용됩니다.

  2. 비표준 응답성 검사를 사용하여 백엔드 구성을 만들려면 envoy-backendconfig이라는 YAML 파일을 만듭니다.

    apiVersion: cloud.google.com/v1
    kind: BackendConfig
    metadata:
      name: envoy-backendconfig
    spec:
      healthCheck:
        checkIntervalSec: 5
        timeoutSec: 5
        healthyThreshold: 2
        unhealthyThreshold: 3
        type: HTTP
        requestPath: /stats
        port: 15005
    

    응답성 검사는 포트 15005/stats 엔드포인트를 사용하여 Envoy 게이트웨이의 응답성을 지속적으로 확인합니다.

  3. Envoy 게이트웨이 서비스를 만듭니다.

    apiVersion: v1
    kind: Service
    metadata:
      name: td-envoy-gateway
      annotations:
        cloud.google.com/backend-config: '{"default": "envoy-backendconfig"}'
    spec:
      type: ClusterIP
      selector:
        app: td-envoy-gateway
      ports:
      - name: http
        protocol: TCP
        port: 8080
        targetPort: 8080
      - name: stats
        protocol: TCP
        port: 15005
        targetPort: 15005
    
  4. 만든 Envoy 게이트웨이 서비스를 확인합니다.

    kubectl get svc td-envoy-gateway
    

Kubernetes 게이트웨이 리소스 만들기

Kubernetes 게이트웨이 리소스를 만들면 내부 애플리케이션 부하 분산기가 프로비저닝되어 Envoy 게이트웨이를 노출합니다.

이 리소스를 만들기 전에 샘플 자체 서명 인증서 2개를 만든 다음 Kubernetes 비밀로 GKE 클러스터로 가져와야 합니다. 인증서는 다음과 같은 게이트웨이 아키텍처를 사용 설정합니다.

  • 각 애플리케이션은 HTTPS를 통해 제공됩니다.
  • 각 애플리케이션은 전용 인증서를 사용합니다.

자체 관리형 인증서를 사용하는 경우 내부 애플리케이션 부하 분산기는 최대 인증서 한도까지 사용하여 서로 다른 정규화된 도메인 이름으로 애플리케이션을 노출할 수 있습니다.

인증서를 만들려면 openssl를 사용합니다.

  1. Cloud Shell에서 첫 번째 인증서의 구성 파일을 생성합니다.

    cat <<EOF >CONFIG_FILE
    [req]
    default_bits              = 2048
    req_extensions            = extension_requirements
    distinguished_name        = dn_requirements
    prompt                    = no
    [extension_requirements]
    basicConstraints          = CA:FALSE
    keyUsage                  = nonRepudiation, digitalSignature, keyEncipherment
    subjectAltName            = @sans_list
    [dn_requirements]
    0.organizationName        = example
    commonName                = win-webserver-1.example.com
    [sans_list]
    DNS.1                     = win-webserver-1.example.com
    EOF
    
  2. 첫 번째 인증서의 비공개 키를 생성합니다.

    openssl genrsa -out sample_private_key 2048
    
  3. 인증서 요청을 생성합니다.

    openssl req -new -key sample_private_key -out CSR_FILE -config CONFIG_FILE
    
  4. 첫 번째 인증서에 서명하고 생성합니다.

    openssl x509 -req -signkey sample_private_key -in CSR_FILE -out sample.crt     -extfile CONFIG_FILE -extensions extension_requirements -days 90
    
  5. 두 번째 인증서의 구성 파일을 생성합니다.

    cat <<EOF >CONFIG_FILE2
    [req]
    default_bits              = 2048
    req_extensions            = extension_requirements
    distinguished_name        = dn_requirements
    prompt                    = no
    [extension_requirements]
    basicConstraints          = CA:FALSE
    keyUsage                  = nonRepudiation, digitalSignature, keyEncipherment
    subjectAltName            = @sans_list
    [dn_requirements]
    0.organizationName        = example
    commonName                = win-webserver-2.example.com
    [sans_list]
    DNS.1                     = win-webserver-2.example.com
    EOF
    
  6. 두 번째 인증서의 비공개 키를 생성합니다.

    openssl genrsa -out sample_private_key2 2048
    
  7. 인증서 요청을 생성합니다.

    openssl req -new -key sample_private_key2 -out CSR_FILE2 -config CONFIG_FILE2
    
  8. 두 번째 인증서에 서명하고 생성합니다.

    openssl x509 -req -signkey sample_private_key2 -in CSR_FILE2 -out sample2.crt     -extfile CONFIG_FILE2 -extensions extension_requirements -days 90
    

Kubernetes 보안 비밀로 인증서 가져오기

이 섹션에서는 다음 태스크를 수행합니다.

  • 자체 서명된 인증서를 Kubernetes 보안 비밀로 GKE 클러스터에 가져옵니다.
  • 내부 VPC의 고정 IP 주소를 만듭니다.
  • Kubernetes Gateway API 리소스를 만듭니다.
  • 인증서가 작동하는지 확인합니다.
  1. Cloud Shell에서 첫 번째 인증서를 Kubernetes 보안 비밀로 가져옵니다.

    kubectl create secret tls sample-cert --cert sample.crt --key sample_private_key
    
  2. 두 번째 인증서를 Kubernetes 보안 비밀로 가져옵니다.

    kubectl create secret tls sample-cert-2 --cert sample2.crt --key sample_private_key2
    
  3. 내부 애플리케이션 부하 분산기를 사용 설정하려면 내부 VPC에서 고정 IP 주소를 만듭니다.

    gcloud compute addresses create sample-ingress-ip --region us-central1 --subnet default
    
  4. Kubernetes Gateway API 리소스 YAML 파일을 만듭니다.

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: internal-https
    spec:
      gatewayClassName: gke-l7-rilb
      addresses:
        - type: NamedAddress
          value: sample-ingress-ip
      listeners:
      - name: https
        protocol: HTTPS
        port: 443
        tls:
          mode: Terminate
          certificateRefs:
          - name: sample-cert
          - name: sample-cert-2
    

    기본적으로 Kubernetes 게이트웨이에는 기본 경로가 없습니다. 게이트웨이로 요청이 전송되면 게이트웨이는 페이지를 찾을 수 없음 (404) 오류를 반환합니다.

  5. 수신되는 모든 요청을 Envoy 게이트웨이로 전달하는 Kubernetes 게이트웨이의 기본 route YAML 파일을 구성합니다.

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: envoy-default-backend
      spec:
        parentRefs:
        - kind: Gateway
          name: internal-https
        rules:
        - backendRefs:
          - name: td-envoy-gateway
            port: 8080
    

    두 애플리케이션 모두에 HTTP 요청을 전송하여 전체 흐름을 확인합니다. Envoy 게이트웨이가 트래픽을 올바른 애플리케이션 포드로 라우팅하는지 확인하려면 HTTP 호스트 헤더를 검사합니다.

  6. Kubernetes 게이트웨이 IP 주소를 찾아 환경 변수에 저장합니다.

    export EXTERNAL_IP=$(kubectl get gateway internal-https -o json | jq .status.addresses[0].value -r)
    
  7. 첫 번째 애플리케이션에 요청을 보냅니다.

    curl --insecure -H "Host: win-app-1" https://$EXTERNAL_IP/hostName
    
  8. 두 번째 애플리케이션에 요청을 보냅니다.

    curl --insecure -H "Host: win-app-2" https://$EXTERNAL_IP/hostName
    
  9. 요청에서 반환된 호스트 이름이 win-app-1win-app-2를 실행하는 포드와 일치하는지 확인합니다.

    kubectl get pods
    

    출력에 win-app-1win-app-2가 표시됩니다.

Envoy 게이트웨이 모니터링

Google Cloud Managed Service for Prometheus로 Envoy 게이트웨이를 모니터링합니다.

앞서 만든 클러스터에서 Google Cloud Managed Service for Prometheus는 기본적으로 사용 설정되어 있어야 합니다.

  1. Cloud Shell에서 다음 YAML 파일을 적용하여 PodMonitoring 리소스를 만듭니다.

    apiVersion: monitoring.googleapis.com/v1
    kind: PodMonitoring
    metadata:
      name: prom-envoy
    spec:
      selector:
        matchLabels:
          app: td-envoy-gateway
      endpoints:
      - port: 15005
        interval: 30s
        path: /stats/prometheus
    

    YAML 파일을 적용하면 시스템이 대시보드에서 Google Cloud Managed Service for Prometheus 측정항목을 수집하기 시작합니다.

  2. Google Cloud Managed Service for Prometheus 측정항목 대시보드를 만들려면 다음 안내를 따르세요.

    1. Google Cloud Console에 로그인합니다.
    2. 메뉴를 엽니다.
    3. 작업 > 모니터링 > 대시보드를 클릭합니다.
  3. 대시보드를 가져오려면 다음 안내를 따르세요.

    1. 대시보드 화면에서 샘플 라이브러리를 클릭합니다.
    2. 필터 상자에 envoy를 입력합니다.
    3. Istio Envoy Prometheus 개요를 클릭합니다.
    4. 체크박스를 선택합니다.
    5. 가져오기를 클릭한 다음 확인을 클릭하여 대시보드를 가져옵니다.
  4. 대시보드를 보려면 다음 안내를 따르세요.

    1. 대시보드 목록을 클릭합니다.
    2. 통합을 선택합니다.
    3. Istio Envoy Prometheus 개요를 클릭하여 대시보드를 봅니다.

이제 Envoy 게이트웨이의 가장 중요한 측정항목을 확인할 수 있습니다. 기준에 따라 알림을 구성할 수도 있습니다. 정리하기 전에 애플리케이션에 테스트 요청을 몇 번 더 보내고 대시보드가 최신 측정항목으로 업데이트되는 방식을 확인합니다.

삭제

이 배포에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 리소스가 포함된 프로젝트를 삭제하거나 프로젝트는 유지하되 개별 리소스를 삭제하세요.

프로젝트 삭제

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

다음 단계

참여자

저자: Eitan Eibschutz | 직원 기술 솔루션 컨설턴트

기타 참여자: