Configurar la cancelación de TLS en la pasarela de entrada

Información general

En esta página se muestra cómo configurar una terminación de TLS en la puerta de enlace de entrada de Cloud Service Mesh para gestionar el tráfico HTTPS externo a tus servicios. Para obtener una introducción más básica sobre cómo configurar pasarelas, consulta la guía de pasarelas. Aprenderás a configurar la pasarela para que la comunicación sea segura mediante TLS, lo que permite acceder a tus aplicaciones de forma cifrada. Este proceso aprovecha las funciones de Cloud Service Mesh para exponer los servicios de forma segura.

Antes de empezar

Para completar los pasos de este documento, necesitas los siguientes recursos:

  • Un clúster de Kubernetes con Cloud Service Mesh instalado. Consulta la guía de instalación para obtener más información sobre cómo instalar Cloud Service Mesh.

Configurar un entorno

Ejecuta los siguientes comandos desde una estación de trabajo que pueda acceder al clúster que quieras usar. Asegúrate de que la herramienta kubectl esté configurada para usar el contexto de clúster específico de tu clúster.

  1. Define las variables de entorno.

    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. Despliega la aplicación foo en tu clúster. Instálalo con el siguiente archivo 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. Genera certificados y claves.

    Para proteger tu gateway de entrada, necesitarás certificados y claves TLS. Puedes usar cualquier herramienta de generación de certificados o seguir estos pasos con openssl para crear las credenciales necesarias.

    • Crear un certificado y una clave de AC raíz
    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
    
    • Generar un certificado y una clave para el ingreso
    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
    

Almacenar el certificado TLS

Almacena el certificado TLS como Secret.

  1. Crea el espacio de nombres. Este espacio de nombres se usa para desplegar la puerta de enlace de entrada.

    kubectl create namespace ${CSM_INGRESSGATEWAY_NAMESPACE}
    
  2. Aplica la etiqueta de inyección predeterminada al espacio de nombres:

    kubectl label namespace ${CSM_INGRESSGATEWAY_NAMESPACE} \
        istio.io/rev- istio-injection=enabled --overwrite
    
  3. Almacena las credenciales TLS en un secreto de Kubernetes:

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

Aplicar el certificado TLS a una pasarela

Hay dos formas de conseguir que la pasarela use el certificado TLS recién creado.

Despliegue con credenciales montadas (opción preferida)

  1. Copia el manifiesto de la pasarela de entrada predeterminada en un archivo local.

    curl https://raw.githubusercontent.com/GoogleCloudPlatform/anthos-service-mesh-samples/main/docs/ingress-gateway-external-lb/ingress-gateway.yaml > ingress-gateway.yaml
    
  2. Modifica el archivo de especificación de la implementación en ingress-gateway.yaml para montar la credencial secreta de 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
    

    A continuación, crea los recursos relacionados con la puerta de enlace de entrada.

    kubectl --namespace ${CSM_INGRESSGATEWAY_NAMESPACE} apply --filename ingress-gateway.yaml 
    
  3. Define la pasarela de entrada.

    Crea un recurso Gateway para gestionar el tráfico HTTPS en el puerto 443 que haga referencia a los secretos montados:

    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
    

Despliegue sin credenciales montadas

  1. Aplica el archivo de manifiesto de la pasarela de entrada.

    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
    

    Resultado esperado:

    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. Define la pasarela de entrada.

    Crea un recurso Gateway para gestionar el tráfico HTTPS en el puerto 443:

    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
    

Optimizar la implementación

Si usas la implementación sin credenciales montadas, los pods de la pasarela de entrada comprueban periódicamente si las credenciales se han actualizado. De forma predeterminada, tarda hasta 60 minutos. Para cambiar la frecuencia de sondeo, define las variables de entorno CSM_MIN_K8S_SECRET_REFRESH_INTERVAL y CSM_MAX_K8S_SECRET_REFRESH_INTERVAL para la implementación de los pods de la puerta de enlace de entrada.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: asm-ingressgateway
  ...
spec:
  ...
  template:
    ...
    spec:
      containers:
      - name: istio-proxy
        image: auto
        env:
        - name: CSM_MIN_K8S_SECRET_REFRESH_INTERVAL
          value: "15m" # Half of the default minimum interval
        - name: CSM_MAX_K8S_SECRET_REFRESH_INTERVAL
          value: "30m" # Half of the default maximum interval
      ...

Tráfico de prueba

  1. Dirige el tráfico al servicio foo.

    Define un VirtualService para dirigir el tráfico a la implementación de foo:

    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. Configura el balanceador de carga externo para que se conecte con la pasarela de entrada del clúster.

  3. Prueba la conexión segura.

    Usa el siguiente comando curl para verificar la configuración:

    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"
    

    Sustituye EXTERNAL_LB_IP_ADDRESS por la IP del balanceador de carga externo.

    El resultado debería ser similar al siguiente:

      {
        "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"
      }
    

Siguientes pasos