인그레스 게이트웨이에서 TLS 종료 설정

개요

이 페이지에서는 Cloud Service Mesh의 인그레스 게이트웨이에서 TLS 종료를 설정하여 서비스에 대한 외부 HTTPS 트래픽을 관리하는 방법을 보여줍니다. 게이트웨이를 설정하는 방법에 관한 기본적인 소개는 게이트웨이 가이드를 참조하세요. TLS를 사용해 보안 통신을 위한 게이트웨이를 구성하여 애플리케이션에 대한 암호화된 액세스를 사용 설정하는 방법을 알아봅니다. 이 프로세스는 Cloud Service Mesh 기능을 활용하여 서비스를 안전하게 노출합니다.

시작하기 전에

이 문서의 단계를 완료하려면 다음 리소스가 필요합니다.

  • Cloud Service Mesh가 설치된 Kubernetes 클러스터 Cloud Service Mesh를 설치하는 방법에 관한 자세한 내용은 설치 가이드를 참조하세요.

환경 설정

사용하려는 클러스터에 액세스할 수 있는 워크스테이션에서 다음 명령어를 실행합니다. kubectl 도구가 클러스터에 대한 클러스터 컨텍스트를 사용하도록 구성되었는지 확인합니다.

  1. 환경 변수를 설정하고,

    export CSM_INGRESSGATEWAY_NAMESPACE=CSM_INGRESSGATEWAY_NAMESPACE
    export CSM_INGRESSGATEWAY_DEPLOYMENT_NAME=CSM_INGRESSGATEWAY_DEPLOYMENT_NAME
    export CSM_INGRESSGATEWAY_SERVICE_NAME=CSM_INGRESSGATEWAY_SERVICE_NAME
    
  2. 클러스터에 foo 애플리케이션을 배포합니다. 다음 yaml을 사용하여 설치합니다.

    apiVersion: v1
    kind: Service
    metadata:
      name: foo
      namespace: foo
    spec:
      selector:
        app: test-backend
      ports:
      - port: 8080
        targetPort: 8080
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: foo
      namespace: foo
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: test-backend
      template:
        metadata:
          labels:
            app: test-backend
        spec:
          containers:
          - name: whereami
            image: gcr.io/google-samples/whereami:v1.2.23
            ports:
            - containerPort: 8080
    EOF
    
  3. 인증서와 키를 생성합니다.

    인그레스 게이트웨이를 보호하려면 TLS 인증서와 키가 필요합니다. 인증서 생성 도구를 사용하거나 다음 단계에 따라 openssl을 사용해 필요한 사용자 인증 정보를 만들 수 있습니다.

    • 루트 CA 인증서 및 키 만들기
    mkdir example_certs
    openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=Example Corp/CN=example.com' \
      -keyout example.com.key -out example.com.crt
    
    • 인그레스용 인증서 및 키 생성
    openssl req -out foo.example.com.csr -newkey rsa:2048 -nodes \
      -keyout foo.example.com.key -subj "/CN=foo.example.com/O=Foo Org"
    
    openssl x509 -req -sha256 -days 365 -CA example.com.crt \
      -CAkey example.com.key -set_serial 0 \
      -in foo.example.com.csr -out foo.example.com.crt
    

TLS 인그레스 게이트웨이 설정

다음 단계에서는 TLS 인그레스 게이트웨이를 설정하는 방법을 설명합니다.

TLS 인증서 저장

  1. 네임스페이스를 만듭니다. 이 네임스페이스는 인그레스 게이트웨이를 배포하는 데 사용됩니다.

    kubectl create namespace ${CSM_INGRESSGATEWAY_NAMESPACE}
    
  2. 기본 삽입 라벨을 네임스페이스에 적용합니다.

    kubectl label namespace ${CSM_INGRESSGATEWAY_NAMESPACE} \
        istio.io/rev- istio-injection=enabled --overwrite
    
  3. Kubernetes 보안 비밀에 TLS 사용자 인증 정보를 저장합니다.

    kubectl create -n ${CSM_INGRESSGATEWAY_NAMESPACE} secret tls foo-credential \
      --key=example_certs/foo.example.com.key \
      --cert=example_certs/foo.example.com.crt
    

게이트웨이에 TLS 인증서 적용

게이트웨이에서 새로 만든 TLS 인증서를 사용하도록 하는 방법에는 두 가지가 있습니다.

마운트된 사용자 인증 정보가 있는 배포(권장)

  1. 기본 인그레스 게이트웨이 매니페스트를 로컬 파일에 복사합니다.

    curl https://raw.githubusercontent.com/GoogleCloudPlatform/anthos-service-mesh-samples/main/docs/ingress-gateway-external-lb/ingress-gateway.yaml > ingress-gateway.yaml
    
  2. ingress-gateway.yaml의 배포 사양을 수정하여 TLS 보안 비밀 사용자 인증 정보를 마운트합니다.

    apiVersion: apps/v1
    kind: Deployment
    ...
    spec:
      ...
        spec:
            ...
            volumeMounts:
            - name: foo-credential # Add new volume mount specifying mount path.
              mountPath: /etc/secrets/foo-credential 
              readOnly: true
          volumes:
          - name: foo-credential # Point volume mount to the Kubernetes secret holding the TLS certificate and keys.
            secret:
              secretName: foo-credential
    

    그런 다음 인그레스 게이트웨이와 관련된 리소스를 만듭니다.

    kubectl --namespace ${CSM_INGRESSGATEWAY_NAMESPACE} apply --filename ingress-gateway.yaml 
    
  3. 인그레스 게이트웨이를 정의합니다.

    마운트된 보안 비밀을 참조하는 포트 443의 HTTPS 트래픽을 처리할 게이트웨이 리소스를 만듭니다.

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.istio.io/v1
    kind: Gateway
    metadata:
      name: secure-gateway
      namespace: ${CSM_INGRESSGATEWAY_NAMESPACE}
    spec:
      selector:
        app: asm-ingressgateway
        istio: ingressgateway
      servers:
      - port:
          number: 443
          name: https
          protocol: HTTPS
        tls:
          mode: SIMPLE
          serverCertificate: /etc/secrets/foo-credential/foo.example.com.crt
          privateKey: /etc/secrets/foo-credential/foo.example.com.key
        hosts:
        - "foo.example.com"
    EOF
    

마운트된 사용자 인증 정보가 없는 배포

  1. 인그레스 게이트웨이 매니페스트 파일을 적용합니다.

    kubectl --namespace ${CSM_INGRESSGATEWAY_NAMESPACE} apply --filename https://raw.githubusercontent.com/GoogleCloudPlatform/anthos-service-mesh-samples/main/docs/ingress-gateway-external-lb/ingress-gateway.yaml
    

    예상 출력:

    serviceaccount/asm-ingressgateway created
    role.rbac.authorization.k8s.io/asm-ingressgateway created
    rolebinding.rbac.authorization.k8s.io/asm-ingressgateway created
    deployment.apps/asm-ingressgateway created
    service/asm-ingressgateway created
    poddisruptionbudget.policy/asm-ingressgateway created
    horizontalpodautoscaler.autoscaling/asm-ingressgateway created
    
  2. 인그레스 게이트웨이를 정의합니다.

    포트 443에서 HTTPS 트래픽을 처리할 게이트웨이 리소스를 만듭니다.

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.istio.io/v1
    kind: Gateway
    metadata:
      name: secure-gateway
      namespace: ${CSM_INGRESSGATEWAY_NAMESPACE}
    spec:
      selector:
        app: asm-ingressgateway
        istio: ingressgateway
      servers:
      - port:
          number: 443
          name: https
          protocol: HTTPS
        tls:
          mode: SIMPLE
          credentialName: foo-credential
        hosts:
        - "foo.example.com"
    EOF
    

트래픽 테스트

  1. 트래픽을 foo 서비스로 라우팅합니다.

    트래픽을 foo 배포로 전달하는 VirtualService를 정의합니다.

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.istio.io/v1
    kind: VirtualService
    metadata:
      name: foo-routing
      namespace: ${CSM_INGRESSGATEWAY_NAMESPACE}
    spec:
      hosts:
      - "foo.example.com"
      gateways:
      - secure-gateway
      http:
      - match:
        - uri:
            prefix: /status
        - uri:
            prefix: /delay
        route:
        - destination:
            host: foo
            port:
              number: 8080
    EOF
    
  2. 클러스터에서 인그레스 게이트웨이와 연결되도록 외부 부하 분산기를 설정합니다.

  3. 보안 연결을 테스트합니다.

    다음 curl 명령어를 사용하여 설정을 확인합니다.

    export EXTERNAL_LB_IP_ADDRESS=EXTERNAL_LB_IP_ADDRESS
    curl -v -H "Host: foo.example.com" --resolve "foo.example.com:443:$EXTERNAL_LB_IP_ADDRESS" \
      --cacert example_certs/example.com.crt "https://foo.example.com:443/ping"
    

    EXTERNAL_LB_IP_ADDRESS를 외부 부하 분산기의 IP로 바꿉니다.

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

      {
        "cluster_name": "gke-us",
        "host_header": "34.120.175.141",
        "pod_name": "whereami-deployment-954cbf78-mtlpf",
        "pod_name_emoji": "😎",
        "project_id": "my-project",
        "timestamp": "2021-11-29T17:01:59",
        "zone": "us-central1-b"
      }
    

다음 단계