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

¿Qué Istio? Se trata del llamado Service mesh, una tecnología que añade una capa de abstracción sobre la red. Interceptamos todo o parte del tráfico en el clúster y realizamos un determinado conjunto de operaciones con él. ¿Cuál? Por ejemplo, hacemos enrutamiento inteligente, o implementamos el enfoque de disyuntores, podemos organizar una "implementación canary", cambiando parcialmente el tráfico a una nueva versión del servicio, o podemos limitar las interacciones externas y controlar todos los viajes desde el clúster al red externa. Es posible establecer reglas de política para controlar viajes entre diferentes microservicios. Finalmente, podemos obtener todo el mapa de interacción de la red y hacer que la colección unificada de métricas sea completamente transparente para las aplicaciones.

Puedes leer sobre el mecanismo de trabajo en documentación oficial. Istio es una herramienta realmente poderosa que le permite resolver muchas tareas y problemas. En este artículo me gustaría responder a las principales preguntas que suelen surgir al empezar a utilizar Istio. Esto te ayudará a lidiar con eso más rápido.

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

¿Cómo funciona?

Istio consta de dos áreas principales: el plano de control y el plano de datos. El plano de control contiene los componentes principales que aseguran el correcto funcionamiento del resto. En la versión actual (1.0) el plano de control tiene tres componentes principales: Piloto, Mezclador, Ciudadela. No consideraremos Citadel, es necesario generar certificados para garantizar TLS mutuo entre servicios. Echemos un vistazo más de cerca al dispositivo y propósito de Pilot y Mixer.

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

Pilot es el principal componente de control 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 la implementación de Canary o reglas de disyuntores).

Mixer es un componente de plano de control opcional que brinda la capacidad de recopilar métricas, registros y cualquier información sobre la interacción de la red. También supervisa el cumplimiento de las normas de la Póliza y el cumplimiento de los límites de tarifas.

El plano de datos se implementa mediante contenedores proxy sidecar. Potente se utiliza de forma predeterminada. representante del enviado. Se puede reemplazar por otra implementación, como nginx (nginmesh).

Para que Istio funcione de forma totalmente transparente a las aplicaciones, existe un sistema de inyección automática. La última implementación es adecuada para las versiones Kubernetes 1.9+ (webhook de admisión mutacional). Para las versiones 1.7 y 1.8 de Kubernetes, es posible utilizar el Inicializador.

Los contenedores con sidecar se conectan a Pilot mediante el protocolo GRPC, que le permite optimizar el modelo de inserción para los cambios que se producen en el clúster. GRPC se ha utilizado en Envoy desde la versión 1.6, en Istio se ha utilizado desde la versión 0.8 y es un agente piloto, un contenedor de Golang sobre Envoy que configura las opciones de lanzamiento.

Pilot y Mixer son componentes completamente sin estado, todo el estado se mantiene en la memoria. La configuración para ellos se establece en forma de recursos personalizados de Kubernetes, que se almacenan en etcd.
Istio-agent obtiene la dirección del piloto y abre una transmisión GRPC.

Como dije, Istio implementa toda la funcionalidad de forma completamente transparente para las aplicaciones. Veamos cómo. El algoritmo es este:

  1. Implementación de una nueva versión del servicio.
  2. Según el enfoque de inyección del contenedor sidecar, el contenedor istio-init y el contenedor istio-agent (enviado) se agregan en la etapa de aplicación de la configuración, o ya se pueden insertar manualmente en la descripción de la entidad Kubernetes Pod.
  3. El contenedor istio-init es un script que aplica las reglas de iptables al pod. Hay dos opciones para configurar el tráfico para que se envuelva en un contenedor istio-agent: usar las reglas de redirección de iptables o Tproxy. En el momento de escribir este artículo, el enfoque predeterminado es con reglas de redirección. En istio-init, es posible configurar qué tráfico debe ser interceptado y enviado a istio-agent. Por ejemplo, para interceptar todo el tráfico entrante y saliente, debe configurar los parámetros -i и -b en significado *. Puede especificar puertos específicos para interceptar. Para no interceptar una subred específica, puede especificarla usando la bandera -x.
  4. Después de ejecutar los contenedores init, se lanzan los principales, incluido el piloto-agente (enviado). Se conecta al piloto ya implementado a través de GRPC y recibe información sobre todos los servicios y políticas de enrutamiento existentes en el clúster. Según los datos recibidos, configura los clústeres y los asigna directamente a los puntos finales de nuestras aplicaciones en el clúster de Kubernetes. También es necesario tener en cuenta un punto importante: envoy configura dinámicamente los oyentes (IP, pares de puertos) que comienza a escuchar. Por lo tanto, cuando las solicitudes ingresan al pod, se redirigen mediante las reglas de redirección de iptables en el sidecar, el envoy ya puede procesar con éxito estas conexiones y comprender dónde enviar el tráfico mediante proxy. También en esta etapa, la información se envía al Mezclador, que veremos más adelante, y se envían tramos de seguimiento.

Como resultado, obtenemos una red completa de servidores proxy Envoy que podemos configurar desde un punto (Piloto). Todas las solicitudes entrantes y salientes pasan por Envoy. Además, solo se intercepta el tráfico TCP. Esto significa que la IP del servicio de Kubernetes se resuelve mediante kube-dns sobre UDP sin cambios. Luego, después de la resolución, la solicitud saliente es interceptada y procesada por envoy, que ya decide a qué punto final debe enviarse la solicitud (o no enviarse, en el caso de las políticas de acceso o el disyuntor del algoritmo).

Descubrimos Pilot, ahora necesitamos entender cómo funciona Mixer y por qué es necesario. Puedes leer la documentación oficial para ello. aquí.

Mixer en su forma actual consta de dos componentes: istio-telemetry, istio-policy (antes de la versión 0.8 era un componente istio-mixer). Ambos son mezcladores, cada uno de los cuales es responsable de su propia tarea. La telemetría de Istio recibe información sobre quién va a dónde y con qué parámetros desde contenedores de informes sidecar a través de GRPC. Istio-policy acepta solicitudes de verificación para verificar que se cumplen las reglas de la política. Por supuesto, las comprobaciones de política no se realizan para cada solicitud, sino que se almacenan en caché en el cliente (en el sidecar) durante un tiempo determinado. Los cheques de informe se envían como solicitudes por lotes. Veamos cómo configurar y qué parámetros se deben enviar un poco más tarde.

Se supone que Mixer es un componente de alta disponibilidad que garantiza un trabajo ininterrumpido en el ensamblaje y procesamiento de datos de telemetría. El sistema se obtiene como resultado como un búfer de varios niveles. Inicialmente, los datos se almacenan en el lado del sidecar de los contenedores, luego en el lado del mezclador y luego se envían a los llamados backends del mezclador. Como resultado, si alguno de los componentes del sistema falla, el búfer crece y se vacía después de restaurar el sistema. Los backends de mezcladores son puntos finales para enviar datos de telemetría: statsd, newrelic, etc. Puede escribir su propio backend, es bastante simple y veremos cómo hacerlo.

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

En resumen, el esquema para trabajar con istio-telemetría 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. Sidecar envoy supervisa cómo va la solicitud al servicio 2 y prepara la información necesaria.
  4. Luego lo envía a istio-telemetry mediante una solicitud de informe.
  5. Istio-telemetry determina si este informe debe enviarse a los backends, a cuáles y qué datos deben enviarse.
  6. Istio-telemetry envía datos de informes al backend si es necesario.

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

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

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

    # пока что не включаем отправку tracing информации (pilot настроит envoy’и таким образом, что отправка не будет происходить)
    enableTracing: false

    # пока что не указываем mixer endpoint’ы, чтобы sidecar контейнеры не отправляли информацию туда
    #mixerCheckServer: istio-policy.istio-system:15004
    #mixerReportServer: istio-telemetry.istio-system:15004

    # ставим временной промежуток, с которым будет envoy переспрашивать Pilot (это для старой версии envoy proxy)
    rdsRefreshDelay: 5s

    # default конфигурация для envoy sidecar
    defaultConfig:
      # аналогично как rdsRefreshDelay
      discoveryRefreshDelay: 5s

      # оставляем по умолчанию (путь к конфигурации и бинарю envoy)
      configPath: "/etc/istio/proxy"
      binaryPath: "/usr/local/bin/envoy"

      # дефолтное имя запущенного sidecar контейнера (используется, например, в именах сервиса при отправке tracing span’ов)
      serviceCluster: istio-proxy

      # время, которое будет ждать envoy до того, как он принудительно завершит все установленные соединения
      drainDuration: 45s
      parentShutdownDuration: 1m0s

      # по умолчанию используются REDIRECT правила iptables. Можно изменить на TPROXY.
      #interceptionMode: REDIRECT

      # Порт, на котором будет запущена admin панель каждого sidecar контейнера (envoy)
      proxyAdminPort: 15000

      # адрес, по которому будут отправляться trace’ы по zipkin протоколу (в начале мы отключили саму отправку, поэтому это поле сейчас не будет использоваться)
      zipkinAddress: tracing-collector.tracing:9411

      # statsd адрес для отправки метрик envoy контейнеров (отключаем)
      # statsdUdpAddress: aggregator:8126

      # выключаем поддержку опции Mutual TLS
      controlPlaneAuthPolicy: NONE

      # адрес, на котором будет слушать istio-pilot для того, чтобы сообщать информацию о service discovery всем sidecar контейнерам
      discoveryAddress: istio-pilot.istio-system:15007

Todos los componentes de control principales (plano de control) estarán ubicados en el espacio de nombres istio-system en Kubernetes.

Como mínimo, solo necesitamos implementar Pilot. Para esto usaremos tal configuración.

Y configuraremos manualmente el sidecar de inyección del contenedor.

Contenedor de inicio:

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:

       name: 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 comience con éxito, debe crear una cuenta de servicio, ClusterRole, ClusterRoleBinding, CRD para Pilot, cuyas descripciones se pueden encontrar aquí.

Como resultado, el servicio en el que inyectamos sidecar con enviado debería iniciarse correctamente, recibir todo el descubrimiento del piloto y procesar las solicitudes.

Es importante comprender 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 descripciones personalizadas de los recursos de Kubernetes.

Además, Istio (todavía experimental) tiene la capacidad de ejecutarse fuera del clúster y la capacidad de observar y buscar a tientas el descubrimiento de servicios entre varios clústeres de Kubernetes. Puedes leer más sobre esto aquí.

Para una instalación de varios clústeres, tenga en cuenta las siguientes limitaciones:

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

Esta es la información inicial para ayudarlo a comenzar con Istio. Sin embargo, todavía hay muchas trampas. Por ejemplo, características de enrutamiento de tráfico externo (fuera del clúster), enfoques para depurar sidecars, creación de perfiles, configuración de un mezclador y escritura de un back-end de mezclador personalizado, configuración de un mecanismo de rastreo y su funcionamiento mediante envoy.
Todo esto lo consideraremos en las siguientes publicaciones. Haga sus preguntas, trataré de cubrirlas.

Fuente: habr.com

Añadir un comentario