Cómo implementar Istio usando Kubernetes en producción. Parte 1

Qué es Istio? Это так называемый Service mesh, технология, которая добавляет уровень абстракции над сетью. Мы перехватываем весь или часть трафика в кластере и производим определенный набор операций с ним. Какой именно? Например, делаем умный роутинг, или реализуем подход circuit breaker, можем организовывать «canary deployment», частично переключая трафик на новую версию сервиса, а можем ограничивать внешние взаимодействия и контролировать все походы из кластера во внешнюю сеть. Есть возможность задавать policy правила для контроля походов между разными микросервисами. Наконец, мы можем получить всю карту взаимодействия по сети и сделать унифицированный сбор метрик полностью прозрачно для приложений.

Se puede leer sobre el mecanismo de funcionamiento en documentación oficial. Istio es realmente una herramienta poderosa que permite resolver numerosas tareas y problemas. En este artículo, me gustaría responder a las preguntas más comunes que suelen surgir al comenzar a trabajar con Istio. Esto le ayudará a comprenderlo más rápidamente.

Cómo implementar Istio usando Kubernetes en producción. Parte 1

Principio de funcionamiento.

Istio consta de dos áreas principales: el plano de control y el plano de datos. El plano de control contiene los componentes clave que aseguran el correcto funcionamiento de los demás. En la versión actual (1.0), el plano de control tiene tres componentes principales: Pilot, Mixer y Citadel. No analizaremos Citadel, ya que se utiliza para generar certificados que garantizan el funcionamiento de mutual TLS entre servicios. Veamos en detalle la estructura y el propósito de Pilot y Mixer.

Cómo implementar Istio usando Kubernetes en producción. Parte 1

Pilot es el componente principal de gestión que distribuye toda la información sobre lo que tenemos en el clúster: servicios, sus puntos finales y reglas de enrutamiento (por ejemplo, reglas para despliegues Canary o reglas de circuit breaker).

Mixer es un componente opcional del plano de control que permite la recolección de métricas, registros y cualquier información sobre la interacción en red. También supervisa el cumplimiento de las reglas de políticas y los límites de tasa.

El plano de datos se implementa mediante contenedores sidecar proxy. Por defecto, se utiliza un potente servidor proxy envoy. Puede ser reemplazado por otra implementación, como nginx (nginmesh).

Para que Istio funcione de manera completamente transparente para las aplicaciones, existe un sistema de inyección automática. La última implementación es adecuada para versiones de Kubernetes 1.9+ (mutational admission webhook). Para las versiones de Kubernetes 1.7 y 1.8, existe la opción de utilizar Initializer.

Los contenedores sidecar se conectan a Pilot a través del protocolo GRPC, que permite optimizar el modelo de envío de cambios que ocurren en el clúster. GRPC comenzó a utilizarse en Envoy a partir de la versión 1.6, en Istio se utiliza desde la versión 0.8 y consiste en un pilot-agent, que es una envoltura en golang sobre envoy que configura los parámetros de lanzamiento.

Pilot y Mixer son componentes completamente stateless, manteniendo todo el estado en memoria. La configuración para ellos se establece en forma de Recursos Personalizados de Kubernetes, que se almacenan en etcd.
El Istio-agent obtiene la dirección de Pilot y abre un flujo GRPC hacia él.

Como ya mencioné, Istio implementa toda la funcionalidad de forma completamente transparente para las aplicaciones. Vamos a analizar cómo. El algoritmo es el siguiente:

  1. Desplegamos una nueva versión del servicio.
  2. Dependiendo del enfoque de inyección, se añaden los contenedores istio-init e istio-agent (envoy) en la etapa de aplicación de la configuración, o pueden haber sido insertados manualmente en la descripción de la entidad Pod de Kubernetes.
  3. El contenedor istio-init es un script que aplica reglas de iptables para el pod. Hay dos opciones para configurar la redirección del tráfico en el contenedor istio-agent: usar reglas de redirección de iptables, o TPROXY. En el momento de redactar este artículo, por defecto se utiliza el enfoque con reglas de redirección. En istio-init hay la posibilidad de configurar qué tráfico debe ser interceptado y dirigido al istio-agent. Por ejemplo, para interceptar todo el tráfico entrante y saliente, es necesario establecer los parámetros , el intervalo entre el envío de paquetes. y -b en *. Se pueden especificar puertos concretos que deben ser interceptados. Para no interceptar una subred específica, se puede indicar mediante la opción -x.
  4. Después de que se ejecutan los contenedores init, se inician los principales, incluido el pilot-agent (envoy). Se conecta al Pilot ya desplegado por GRPC y obtiene información sobre todos los servicios existentes y políticas de enrutamiento en el clúster. Según los datos recibidos, configura los clústeres y asigna directamente los endpoints de nuestras aplicaciones en el clúster de Kubernetes. También es importante señalar un punto clave: envoy configura dinámicamente los listeners (pares de IP, puerto) que comienza a escuchar. Por lo tanto, cuando las solicitudes entran en el pod, son redirigidas mediante reglas de iptables al sidecar, y envoy puede procesar estas conexiones con éxito y entender a dónde debe dirigir el tráfico. En esta etapa también se envían datos al Mixer, que veremos más adelante, y se envían spans de trazado.

En consecuencia, obtenemos toda una red de servidores proxy envoy que podemos configurar desde un solo punto (Pilot). Todas las solicitudes entrantes y salientes pasan a través de envoy. Además, solo se intercepta el tráfico TCP. Esto significa que la IP del servicio de Kubernetes se resuelve mediante kube-dns a través de UDP sin cambios. Luego, después de la resolución, se intercepta la solicitud saliente y se procesa por envoy, que ya decide a qué endpoint debe enviar la solicitud (o no enviarla, en caso de políticas de acceso o activación del algoritmo de cortocircuito).

Ahora que hemos entendido el Pilot, necesitamos comprender cómo funciona el Mixer y por qué es necesario. Se puede leer la documentación oficial sobre esto. aquí.

Mixer en su forma actual consiste en dos componentes: istio-telemetry e istio-policy (hasta la versión 0.8, esto era un solo componente, istio-mixer). Ambos representan un mixer, cada uno de los cuales tiene su propia función. Istio telemetry recibe a través de GRPC desde los contenedores sidecar Report la información sobre a dónde va cada uno y con qué parámetros. Istio-policy recibe solicitudes de Check para verificar si se cumplen las reglas de Policy. Las verificaciones de Policy se realizan, por supuesto, no para cada solicitud, sino que se almacenan en caché en el cliente (en el sidecar) durante un tiempo determinado. Los check de Report se envían en solicitudes por lotes. Cómo configurarlo y qué parámetros deben enviarse lo veremos un poco más adelante.

Mixer está diseñado como un componente de alta disponibilidad que asegura un funcionamiento ininterrumpido en la recopilación y procesamiento de datos de telemetría. El sistema resulta ser, en última instancia, un búfer de múltiples niveles. Inicialmente, los datos se almacenan en búfer en el lado de los contenedores sidecar, luego en el lado del mixer y después se envían a los llamados mixer backends. En consecuencia, si algún componente del sistema falla, el búfer crece y, tras la recuperación del sistema, se vacía. Los mixer backends representan puntos finales para el envío de datos de telemetría: statsd, newrelic, etc. Se puede escribir un backend propio, es bastante sencillo, y veremos cómo hacerlo.

Cómo implementar Istio usando Kubernetes en producción. Parte 1

En resumen, el esquema de trabajo con istio-telemetry es el siguiente.

  1. El servicio 1 envía una solicitud al servicio 2.
  2. Al salir del servicio 1, la solicitud se envuelve en su propio sidecar.
  3. El sidecar envoy supervisa cómo transcurre la solicitud hacia el servicio 2 y prepara la información necesaria.
  4. Luego la envía a istio-telemetry a través de una solicitud de Report.
  5. Istio-telemetry determina si es necesario enviar este Report a los backends, a cuáles específicamente y qué datos deben enviarse.
  6. Istio-telemetry envía los datos de Report a los backends si es necesario.

Ahora veamos cómo desplegar en el sistema Istio que consta solo de los componentes principales (Pilot y sidecar envoy).

Primero, veamos la configuración principal (mesh) que lee Pilot:

apiVersion: v1
kind: ConfigMap
metadata:
  name: istio
  namespace: istio-system
  labels:
    app: istio
    service: istio
data:
  mesh: |-

    # por el momento no habilitamos el envío de información de tracing (pilot configurará los envoy de tal manera que no se enviará)
    enableTracing: false

    # por el momento no especificamos los endpoints de mixer para que los contenedores sidecar no envíen información allí
    #mixerCheckServer: istio-policy.istio-system:15004
    #mixerReportServer: istio-telemetry.istio-system:15004

    # establecemos el intervalo de tiempo con el que envoy volverá a preguntar a Pilot (esto es para la versión antigua del proxy envoy)
    rdsRefreshDelay: 5s

    # configuración por defecto para el sidecar de envoy
    defaultConfig:
      # similar a rdsRefreshDelay
      discoveryRefreshDelay: 5s

      # dejamos por defecto (ruta a la configuración y al binario de envoy)
      configPath: "/etc/istio/proxy"
      binaryPath: "/usr/local/bin/envoy"

      # nombre por defecto del contenedor sidecar en ejecución (se utiliza, por ejemplo, en los nombres de servicio al enviar spans de tracing)
      serviceCluster: istio-proxy

      # tiempo que esperará envoy antes de forzar el cierre de todas las conexiones establecidas
      drainDuration: 45s
      parentShutdownDuration: 1m0s

      # por defecto se utilizan las reglas REDIRECT de iptables. Se puede cambiar a TPROXY.
      #interceptionMode: REDIRECT

      # Puerto en el que se ejecutará el panel de administración de cada contenedor sidecar (envoy)
      proxyAdminPort: 15000

      # dirección a la que se enviarán los traces mediante el protocolo zipkin (al principio deshabilitamos el envío, por lo que este campo no se utilizará actualmente)
      zipkinAddress: tracing-collector.tracing:9411

      # dirección statsd para enviar métricas de los contenedores de envoy (deshabilitado)
      # statsdUdpAddress: aggregator:8126

      # deshabilitamos el soporte para la opción Mutual TLS
      controlPlaneAuthPolicy: NONE

      # dirección en la que escuchará istio-pilot para informar sobre el descubrimiento de servicios a todos los contenedores sidecar
      discoveryAddress: istio-pilot.istio-system:15007

Colocaremos todos los componentes principales de control (control plane) en el namespace istio-system en Kubernetes.

Mínimamente necesitamos desplegar solo Pilot. Para ello utilizaremos esta configuración.

Y configuraremos manualmente el inyectado del contenedor sidecar.

Contenedor Init:

initContainers:
 - name: istio-init
   args:
   - -p
   - "15001"
   - -u
   - "1337"
   - -m
   - REDIRECT
   - -i
   - '*'
   - -b
   - '*'
   - -d
   - ""
   image: istio/proxy_init:1.0.0
   imagePullPolicy: IfNotPresent
   resources:
     limits:
       memory: 128Mi
   securityContext:
     capabilities:
       add:
       - NET_ADMIN

Y sidecar:

       nombre: istio-proxy
       args:
         - "bash"
         - "-c"
         - |
           exec /usr/local/bin/pilot-agent proxy sidecar 
           --configPath 
           /etc/istio/proxy 
           --binaryPath 
           /usr/local/bin/envoy 
           --serviceCluster 
           service-name 
           --drainDuration 
           45s 
           --parentShutdownDuration 
           1m0s 
           --discoveryAddress 
           istio-pilot.istio-system:15007 
           --discoveryRefreshDelay 
           1s 
           --connectTimeout 
           10s 
           --proxyAdminPort 
           "15000" 
           --controlPlaneAuthPolicy 
           NONE
         env:
         - name: POD_NAME
           valueFrom:
             fieldRef:
               fieldPath: metadata.name
         - name: POD_NAMESPACE
           valueFrom:
             fieldRef:
               fieldPath: metadata.namespace
         - name: INSTANCE_IP
           valueFrom:
             fieldRef:
               fieldPath: status.podIP
         - name: ISTIO_META_POD_NAME
           valueFrom:
             fieldRef:
               fieldPath: metadata.name
         - name: ISTIO_META_INTERCEPTION_MODE
           value: REDIRECT
         image: istio/proxyv2:1.0.0
         imagePullPolicy: IfNotPresent
         resources:
           requests:
             cpu: 100m
             memory: 128Mi
           limits:
             memory: 2048Mi
         securityContext:
           privileged: false
           readOnlyRootFilesystem: true
           runAsUser: 1337
         volumeMounts:
         - mountPath: /etc/istio/proxy
           name: istio-envoy

Para que todo funcione correctamente, es necesario crear un ServiceAccount, ClusterRole, ClusterRoleBinding, y CRD para Pilot, cuya descripción se puede encontrar aquí.

Como resultado, el servicio en el que inyectamos el sidecar con envoy debe iniciarse correctamente, obtener todo el descubrimiento del piloto y manejar las solicitudes.

Es importante entender que todos los componentes del plano de control son aplicaciones sin estado y se pueden escalar horizontalmente sin problemas. Todos los datos se almacenan en etcd en forma de definiciones de recursos personalizados de Kubernetes.

Además, Istio (por ahora experimentalmente) tiene la posibilidad de ejecutarse fuera del clúster y la capacidad de ver y compartir el descubrimiento de servicios entre varios clústeres de Kubernetes. Puede leer más sobre esto aquí.

Al realizar una instalación multiclúster, se deben tener en cuenta las siguientes limitaciones:

  1. El Pod CIDR y el Service CIDR deben ser únicos en todos los clústeres y no deben superponerse.
  2. Todos los Pod CIDR deben ser accesibles desde cualquier Pod CIDR entre clústeres.
  3. Todos los servidores API de Kubernetes deben ser accesibles entre sí.

Esta es información inicial que le ayudará a comenzar a trabajar con Istio. Sin embargo, hay muchos otros aspectos a tener en cuenta. Por ejemplo, características del enrutamiento del tráfico externo (fuera del clúster), enfoques para depurar sidecars, perfiles, configuración del mixer y la escritura de un backend de mixer personalizado, la configuración del mecanismo de tracing y su funcionamiento con envoy.
Todo esto lo veremos en próximas publicaciones. Hagan sus preguntas, intentaré abordarlas.

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster