Proteger servicios de Kubernetes con Istio

Este tutorial está dirigido a usuarios y administradores de Kubernetes que quieran usar la malla de servicios de Istio para desplegar servicios de Kubernetes de forma segura y habilitar la comunicación TLS mutua (mTLS).

Istio y Cloud Service Mesh

Istio no es un producto de Google admitido. Te recomendamos que uses Cloud Service Mesh gestionado. Para obtener más información, consulta Aprovisionar Cloud Service Mesh en un clúster Autopilot de GKE.

Cloud Service Mesh ofrece las siguientes ventajas:

  • Puedes aprovisionar Cloud Service Mesh gestionado con la API Fleet sin herramientas del lado del cliente como istioctl.
  • Cloud Service Mesh inserta automáticamente proxies sidecar en las cargas de trabajo sin conceder privilegios elevados a tus contenedores.
  • Puedes ver paneles de control detallados de tu malla y tus servicios sin necesidad de configurar nada adicional y, a continuación, usar estas métricas para configurar objetivos de nivel de servicio (SLOs) y alertas para monitorizar el estado de tus aplicaciones.
  • El plano de control gestionado de Cloud Service Mesh se actualiza automáticamente para que obtengas los parches de seguridad y las funciones más recientes.
  • El plano de datos gestionado de Cloud Service Mesh actualiza automáticamente los proxies sidecar de tus cargas de trabajo, por lo que no tienes que reiniciar los servicios tú mismo cuando haya disponibles actualizaciones de proxy y parches de seguridad.
  • Cloud Service Mesh es un producto compatible que se puede configurar mediante las APIs de código abierto estándar de Istio. Para obtener más información, consulta las funciones admitidas.

Preparar el entorno

Para configurar tu entorno, sigue estos pasos:

  1. Define las variables de entorno:

    export PROJECT_ID=PROJECT_ID
    gcloud config set project $PROJECT_ID
    gcloud config set compute/region us-central1
    

    Sustituye PROJECT_ID por el Google Cloud ID de tu proyecto.

  2. Clona el repositorio de GitHub:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git
    
  3. Cambia al directorio de trabajo:

    cd kubernetes-engine-samples/service-mesh/istio-tutorial
    

Crear un clúster de GKE

Habilita las funciones de Linux que requiere Istio: NET_RAW y NET_ADMIN. GKE Autopilot no permite NET_ADMIN de forma predeterminada, pero puedes habilitar NET_ADMIN con el comando --workload-policies=allow-net-admin en las versiones 1.27 y posteriores de GKE:

gcloud container clusters create-auto istio-cluster \
    --location="us-central1" \
    --workload-policies="allow-net-admin"

Para obtener más información sobre la seguridad de Autopilot de GKE, consulta las configuraciones de seguridad integradas.

Instalar Istio

Puedes instalar Istio en un clúster de GKE mediante Istioctl.

En este tutorial, instalarás Istio con el perfil de configuración predeterminado, que se recomienda para las implementaciones de producción.

  1. Instala Istio:

    • Para instalar la versión más reciente de Istio, sigue estos pasos:

      curl -L https://istio.io/downloadIstio | sh -
      
    • Para instalar una versión específica de Istio, sigue estos pasos:

      export ISTIO_VERSION=VERSION_NUMBER
      curl -L https://istio.io/downloadIstio | TARGET_ARCH=$(uname -m) sh -
      

      Sustituye VERSION_NUMBER por la versión de Istio que quieras instalar. Para obtener información sobre las versiones de Istio, consulta los anuncios de las versiones.

  2. Añade la herramienta de línea de comandos istioctl a PATH:

    cd istio-*
    export PATH=$PWD/bin:$PATH
    
  3. Instala Istio en el clúster:

    istioctl install --set profile="default" -y
    

    Este paso puede tardar varios minutos.

  4. Espera a que los pods de Istio estén listos:

    watch kubectl get pods -n istio-system
    

    El resultado debería ser similar al siguiente:

    NAME                                    READY   STATUS        RESTARTS   AGE
    istio-ingressgateway-5c47bff876-wjm96   1/1     Running       0          2m54s
    istiod-5fc7cb65cd-k8cp4                 1/1     Running       0          2m57s
    

    Cuando los pods de Istio estén Running, vuelve a la línea de comandos pulsando Ctrl+C.

Desplegar la aplicación de ejemplo

En esta sección, usarás la aplicación de ejemplo Bank of Anthos para crear una malla de servicios con autenticación mTLS.

  1. Añade una etiqueta de espacio de nombres que indique a Istio que habilite la inyección automática de proxies sidecar de Envoy:

    kubectl label namespace default istio-injection=enabled
    
  2. Despliega la aplicación de ejemplo:

    cd ..
    git clone https://github.com/GoogleCloudPlatform/bank-of-anthos.git
    kubectl apply -f bank-of-anthos/extras/jwt/jwt-secret.yaml
    kubectl apply -f bank-of-anthos/kubernetes-manifests/
    
  3. Espera a que la aplicación esté lista:

    watch kubectl get pods
    

    El resultado debería ser similar al siguiente:

    NAME                                 READY   STATUS    RESTARTS   AGE
    accounts-db-0                        2/2     Running   0          2m16s
    balancereader-5c695f78f5-x4wlz       2/2     Running   0          3m8s
    contacts-557fc79c5-5d7fg             2/2     Running   0          3m7s
    frontend-7dd589c5d7-b4cgq            2/2     Running   0          3m7s
    ledger-db-0                          2/2     Running   0          3m6s
    ledgerwriter-6497f5cf9b-25c6x        2/2     Running   0          3m5s
    loadgenerator-57f6896fd6-lx5df       2/2     Running   0          3m5s
    transactionhistory-6c498965f-tl2sk   2/2     Running   0          3m4s
    userservice-95f44b65b-mlk2p          2/2     Running   0          3m4s
    

    Cuando los pods estén Running, vuelve a la línea de comandos pulsando Ctrl+C.

  4. Revisa el siguiente archivo de manifiesto:

    # Copyright 2020 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: frontend-gateway
    spec:
      selector:
        istio: ingressgateway # use Istio default gateway implementation
      servers:
      - port:
          number: 80
          name: http
          protocol: HTTP
        hosts:
        - "*"
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: frontend-ingress
    spec:
      hosts:
      - "*"
      gateways:
      - frontend-gateway
      http:
      - route:
        - destination:
            host: frontend
            port:
              number: 80

    Este manifiesto describe los recursos Gateway y VirtualService de Istio, que exponen la aplicación y usan Istio como controlador de entrada.

  5. Aplica el manifiesto a tu clúster:

    kubectl apply -f bank-of-anthos/extras/istio/frontend-ingress.yaml
    

Configurar mTLS

La autenticación TLS mutua (mTLS) está habilitada de forma predeterminada en Istio. Esto significa que Istio monitoriza las cargas de trabajo del servidor que se han migrado a proxies de Istio y configura automáticamente los proxies de cliente para establecer conexiones mTLS con estas cargas de trabajo. Istio también configura los proxies de cliente para que no usen mTLS al conectarse a cargas de trabajo sin proxies sidecar.

Istio puede configurar mTLS para que funcione de tres formas:

  • PERMISSIVE: las cargas de trabajo aceptan tanto el tráfico mTLS como el de texto sin formato.
  • STRICT: las cargas de trabajo solo aceptan tráfico mTLS.
  • DISABLE: mTLS está inhabilitado. Usa este modo si quieres usar tu propia solución de seguridad.

Puedes aplicar la configuración de mTLS de forma global, por espacio de nombres o por carga de trabajo. En este tutorial, aplicará la configuración por espacio de nombres mediante el modo STRICT mTLS.

  1. Revisa el siguiente archivo de manifiesto:

    apiVersion: security.istio.io/v1beta1
    kind: PeerAuthentication
    metadata:
      name: default
    spec:
      mtls:
          mode: STRICT

    Este manifiesto describe un recurso personalizado de Istio de autenticación entre pares.

  2. Aplica el manifiesto a tu clúster:

    kubectl apply -f peer-authentication.yaml
    

Para obtener más información sobre mTLS en Istio, consulta Autenticación TLS mutua.

Verificar que mTLS esté habilitado

Kiali es un panel de control de observabilidad basado en la Web para la malla de servicios de Istio que proporciona una vista gráfica de tu entorno de microservicios, lo que te permite monitorizar tus aplicaciones y solucionar problemas. Puedes usar Kiali para verificar que la autenticación mTLS esté habilitada y funcione correctamente en la malla de servicios de Istio. Kiali requiere Prometheus como fuente de datos de telemetría. En este tutorial se usa Google Cloud Managed Service para Prometheus.

Instalar una interfaz de consulta

  1. Crea una cuenta de servicio de gestión de identidades y accesos con el rol roles/monitoring.viewer para permitir que la interfaz de consulta acceda a las métricas:

    gcloud iam service-accounts create monitoring \
        --display-name="Service account for query interface"
    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member "serviceAccount:monitoring@PROJECT_ID.iam.gserviceaccount.com" \
        --role roles/monitoring.viewer
    gcloud iam service-accounts add-iam-policy-binding \
      monitoring@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/iam.workloadIdentityUser \
        --member "serviceAccount:PROJECT_ID.svc.id.goog[monitoring/default]"
    
  2. Crea un espacio de nombres de Kubernetes:

    kubectl create namespace monitoring
    
  3. Anota la cuenta de servicio de Kubernetes predeterminada en el espacio de nombres para configurar Workload Identity Federation para GKE:

    kubectl annotate serviceaccount -n monitoring default \
        iam.gke.io/gcp-service-account=monitoring@PROJECT_ID.iam.gserviceaccount.com --overwrite
    
  4. Despliega la carga de trabajo de la interfaz de consulta:

    kubectl -n monitoring apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/prometheus-engine/v0.7.1/examples/frontend.yaml
    
  5. Revisa el siguiente archivo de manifiesto:

    apiVersion: monitoring.googleapis.com/v1
    kind: PodMonitoring
    metadata:
      name: istiod
      namespace: istio-system
    spec:
      selector:
        matchLabels:
          app: istiod
      endpoints:
      - port: 15014
        path: /metrics
        timeout: 30s
        interval: 60s

    Este manifiesto describe un recurso PodMonitoring que recoge métricas de Istio y Envoy Proxy.

  6. Aplica el manifiesto a tu clúster:

    kubectl apply -f pod-monitorings.yaml
    
  7. Obtén un enlace a la aplicación de ejemplo:

    INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    echo "http://$INGRESS_HOST"
    
  8. Abre el enlace para ver la aplicación de ejemplo. Inicia sesión con el nombre de usuario y la contraseña predeterminados para generar tráfico entre los microservicios.

Instalar Kiali

Te recomendamos que instales Kiali con el operador de Kiali.

  1. Instala el operador de Kiali:

    helm repo add kiali https://kiali.org/helm-charts
    helm repo update
    helm install \
        --namespace kiali-operator \
        --create-namespace \
        kiali-operator \
        kiali/kiali-operator
    
  2. Revisa el siguiente archivo de manifiesto:

    apiVersion: kiali.io/v1alpha1
    kind: Kiali
    metadata:
      name: kiali
      namespace: istio-system
    spec:
      deployment:
        namespace: istio-system
      auth:
        strategy: anonymous
      external_services:
        custom_dashboards:
          prometheus:
            url: "http://frontend.monitoring:9090/"
            auth:
              type: none
        prometheus:
          url: "http://frontend.monitoring:9090/"
          auth:
            type: none
        tracing:
          enabled: false
        grafana:
          enabled: false

    Este manifiesto describe un recurso personalizado de Operator que define el servidor de Kiali.

  3. Aplica el manifiesto a tu clúster:

    kubectl apply -f kiali.yaml
    
  4. Espera a que el servidor de Kiali esté listo:

    watch kubectl get pods -n istio-system
    

    El resultado debería ser similar al siguiente:

    NAME                                    READY   STATUS    RESTARTS   AGE
    istio-ingressgateway-6845466857-92zp8   1/1     Running   0          9m11s
    istiod-6b47d84cf-4cqlt                  1/1     Running   0          12m
    

    Cuando los pods estén Running, vuelve a la línea de comandos pulsando Ctrl+C.

  5. Configura el reenvío de puertos en el servicio del servidor de Kiali para acceder al panel de control:

    kubectl -n istio-system port-forward svc/kiali 8080:20001
    
  6. Abre Vista previa web. En Kiali, ve a la sección Gráfico y selecciona la opción Seguridad en el desplegable Mostrar. En esta vista se muestra el estado de seguridad de cada nodo del gráfico. Los nodos con la insignia mTLS habilitado indican que mTLS está habilitado para ese servicio, y los nodos sin la insignia indican que mTLS no está habilitado.