Preparando la aplicación para Istio


Istio es una herramienta conveniente para conectar, proteger y monitorear aplicaciones distribuidas. Istio utiliza una variedad de tecnologías para lanzar y administrar software a gran escala, incluidos contenedores para empaquetar código de aplicación y dependencias para la implementación, y Kubernetes para administrar estos contenedores. Por lo tanto, para trabajar con Istio, debe saber cómo funciona una aplicación con varios servicios basados ​​en estas tecnologías sin Istio. Si ya conoce estas herramientas y conceptos, no dude en omitir esta guía e ir directamente a Instalar Istio en Google Kubernetes Engine (GKE) o instalar Istio en la extensión GKE .


Esta es una guía paso a paso donde veremos todo el proceso desde el código fuente hasta un contenedor en GKE para que pueda obtener una idea básica de estas tecnologías usando un ejemplo. También verá cómo Istio aprovecha estas tecnologías. Se supone que no sabe nada sobre contenedores, Kubernetes, servicio de malla o Istio.


Las tareas


En esta guía, completará las siguientes tareas:


  1. Explorando una aplicación sencilla de hello world con varios servicios.
  2. Ejecutando la aplicación desde el código fuente.
  3. Embalaje de la aplicación en contenedores.
  4. Crear un clúster de Kubernetes
  5. Implemente contenedores en un clúster.

Antes de empezar


Siga las instrucciones para habilitar la API de Kubernetes Engine:


  1. Vaya a la página de Kubernetes Engine en la consola de Google Cloud Platform.
  2. Crea o selecciona un proyecto.
  3. Espere a que se activen la API y los servicios relacionados. Esto puede tomar varios minutos.
  4. Asegúrese de que la facturación esté configurada para el proyecto Google Cloud Platform. Obtenga información sobre cómo habilitar la facturación .

En esta guía, puede usar Cloud Shell, que prepara la máquina virtual pequeña g1 en Google Compute Engine con Linux basado en Debian, o una computadora Linux o macOS.


Opción A: uso de Cloud Shell


Beneficios de usar Cloud Shell:


  • Los entornos de desarrollo Python 2 y Python 3 (incluido virtualenv ) están totalmente personalizados.
  • Las herramientas de línea de comandos gcloud , docker , git y kubectl que usaremos ya están instaladas.
  • Tiene varios editores de texto para elegir:
    1. El editor de código que se abre con el icono de edición en la parte superior de la ventana de Cloud Shell.
    2. Emacs, Vim o Nano que se abren desde la línea de comandos en Cloud Shell.

Para usar Cloud Shell :


  1. Vaya a la consola de GCP.
  2. Haga clic en el botón Activar Cloud Shell en la parte superior de la ventana de la consola GCP.


En la parte inferior de la consola GCP, en una nueva ventana, se abre una sesión de Cloud Shell con una línea de comando.



Opción B: uso local de herramientas de línea de comando


Si va a trabajar en una computadora con Linux o macOS, debe configurar e instalar los siguientes componentes:


  1. Configure su entorno de desarrollo Python 3 y Python 2 .


  2. Instale Cloud SDK con la herramienta de línea de comandos gcloud .


  3. Instale kubectl , una herramienta de línea de comandos para trabajar con Kubernetes .


    gcloud components install kubectl 

  4. Instale Docker Community Edition (CE) . Utilizará la herramienta de línea de comandos de Docker para crear imágenes de contenedor para una aplicación de muestra.


  5. Instale la herramienta de control de versiones de Git para obtener una aplicación de muestra con GitHub.



Descargar código de muestra


  1. Descargue el código fuente de helloserver :


     git clone https://github.com/GoogleCloudPlatform/istio-samples 

  2. Vaya al directorio del código de muestra:


     cd istio-samples/sample-apps/helloserver 


Explorando una aplicación multiservicio


La aplicación de muestra está escrita en Python y consta de dos componentes que interactúan con REST :


  • servidor : un servidor simple con un punto final GET, / , que muestra "hello world" en la consola.
  • loadgen : un script que envía tráfico al servidor , con un número configurable de solicitudes por segundo.


Ejecutar una aplicación desde el origen


Para aprender una aplicación de muestra, ejecútela en Cloud Shell o en una computadora.
1) En el directorio istio-samples / sample-apps / helloserver , ejecute el servidor :


 python3 server/server.py 

Cuando se inicia el servidor , se muestra lo siguiente:


 INFO:root:Starting server... 

2) Abra otra ventana de terminal para enviar solicitudes al servidor . Si está utilizando Cloud Shell, haga clic en el icono Agregar para abrir otra sesión.
3) Enviar una solicitud al servidor :


 curl http://localhost:8080 

respuestas del servidor:


 Hello World! 

4) Desde el directorio donde descargó el código de muestra, vaya al directorio que contiene loadgen :


 cd YOUR_WORKING_DIRECTORY/istio-samples/sample-apps/helloserver/loadgen 

5) Cree las siguientes variables de entorno:


 export SERVER_ADDR=http://localhost:8080 export REQUESTS_PER_SECOND=5 

6) Ejecute virtualenv :


 virtualenv --python python3 env 

7) Activar el entorno virtual:


 source env/bin/activate 

8) Establecer requisitos para loadgen :


 pip3 install -r requirements.txt 

9) Ejecute loadgen :


 python3 loadgen.py 

Cuando se inicia, loadgen muestra el siguiente mensaje:


 Starting loadgen: 2019-05-20 10:44:12.448415 5 request(s) complete to http://localhost:8080 

En otra ventana de terminal, el servidor muestra los siguientes mensajes a la consola:


 127.0.0.1 - - [21/Jun/2019 14:22:01] "GET / HTTP/1.1" 200 - INFO:root:GET request, Path: / Headers: Host: localhost:8080 User-Agent: python-requests/2.22.0 Accept-Encoding: gzip, deflate Accept: */* 

Desde una perspectiva de red, toda la aplicación se ejecuta en el mismo host (computadora local o máquina virtual Cloud Shell). Por lo tanto, puede usar localhost para enviar solicitudes al servidor .
10) Para detener loadgen y el servidor , ingrese Ctrl-c en cada ventana de terminal.
11) En la ventana del terminal loadgen, desactive el entorno virtual:


 deactivate 

Empaquetar la aplicación en contenedores


Para ejecutar la aplicación en GKE, debe empaquetar la aplicación de muestra ( servidor y loadgen ) en contenedores . Un contenedor es una forma de empaquetar una aplicación para aislarla del entorno.


Para empacar la aplicación en un contenedor, necesita un Dockerfile . Un Dockerfile es un archivo de texto que define comandos para construir el código fuente de una aplicación y sus dependencias en una imagen Docker. Después de la compilación, carga la imagen en el registro de contenedores, por ejemplo, Docker Hub o el Registro de contenedores .


El ejemplo ya tiene un Dockerfile para server y loadgen con todos los comandos necesarios para ensamblar las imágenes. A continuación se muestra el Dockerfile para servidor :


 FROM python:3-slim as base FROM base as builder RUN apt-get -qq update \ && apt-get install -y --no-install-recommends \ g++ \ && rm -rf /var/lib/apt/lists/* # Enable unbuffered logging FROM base as final ENV PYTHONUNBUFFERED=1 RUN apt-get -qq update \ && apt-get install -y --no-install-recommends \ wget WORKDIR /helloserver # Grab packages from builder COPY --from=builder /usr/local/lib/python3.7/ /usr/local/lib/python3.7/ # Add the application COPY . . EXPOSE 8080 ENTRYPOINT [ "python", "server.py" ] 

  • El comando FROM python: 3-slim as base le dice a Docker que use la última imagen de Python 3 como base.
  • COPIA del equipo . . copia los archivos de origen en el directorio de trabajo actual (en nuestro caso, solo server.py ) en el sistema de archivos del contenedor.
  • ENTRYPOINT define el comando que se utiliza para iniciar el contenedor. En nuestro caso, este comando es casi el mismo que usó para ejecutar server.py desde el código fuente.
  • El comando EXPOSE indica que el servidor está escuchando en el puerto 8080 . Este comando no proporciona puertos . Este es algún tipo de documentación que se necesita para abrir el puerto 8080 cuando se inicia el contenedor.

Preparación para la aplicación de contenedores


1) Establezca las siguientes variables de entorno. Reemplace PROJECT_ID con su identificador de proyecto GCP.


 export PROJECT_ID="PROJECT_ID" 

 export GCR_REPO="preparing-istio" 

Usando los valores PROJECT_ID y GCR_REPO, etiqueta la imagen de Docker cuando la recopila y la envía al Registro de Contenedores privado.


2) Establezca el proyecto GCP predeterminado para la herramienta de línea de comando gcloud .


 gcloud config set project $PROJECT_ID 

3) Establezca la zona predeterminada para la herramienta de línea de comando gcloud .


 gcloud config set compute/zone us-central1-b 

4) Asegúrese de que el servicio de registro de contenedores esté incluido en el proyecto GCP.


 gcloud services enable containerregistry.googleapis.com 

Servidor de contenedores


  1. Cambie al directorio donde se encuentra el ejemplo del servidor :


     cd YOUR_WORKING_DIRECTORY/istio-samples/sample-apps/helloserver/server/ 

  2. Cree la imagen utilizando el Dockerfile y las variables de entorno que definió anteriormente:


     docker build -t gcr.io/$PROJECT_ID/$GCR_REPO/helloserver:v0.0.1 . 


La opción -t representa la etiqueta Docker. Este es el nombre de la imagen que utiliza al implementar el contenedor.


  1. Envíe la imagen al Registro de contenedores:
     docker push gcr.io/$PROJECT_ID/$GCR_REPO/helloserver:v0.0.1 

Containerization loadgen


1) Vaya al directorio donde se encuentra el ejemplo de loadgen :


 cd ../loadgen 

2) Montar la imagen:


 docker build -t gcr.io/$PROJECT_ID/$GCR_REPO/loadgen:v0.0.1 . 

3) Enviar la imagen al Registro de contenedores:


 docker push gcr.io/$PROJECT_ID/$GCR_REPO/loadgen:v0.0.1 

Ver una lista de imágenes


Explore la lista de imágenes en el repositorio y asegúrese de enviar las imágenes:


 gcloud container images list --repository gcr.io/$PROJECT_ID/preparing-istio 

El comando muestra los nombres de las imágenes que acabamos de enviar:


 NAME gcr.io/PROJECT_ID/preparing-istio/helloserver gcr.io/PROJECT_ID/preparing-istio/loadgen 

Crear un clúster GKE


Estos contenedores se pueden ejecutar en la máquina virtual Cloud Shell o en la computadora con el comando docker run . Pero en un entorno de producción, necesita una forma de orquestar los contenedores de forma centralizada. Por ejemplo, necesitamos un sistema que garantice que los contenedores siempre funcionen, y necesitamos una forma de acercar y lanzar instancias adicionales de contenedores si aumenta el tráfico.


Puede usar GKE para ejecutar aplicaciones de contenedor. GKE es una plataforma de orquestación de contenedores que agrupa máquinas virtuales. Cada máquina virtual se llama host. Los clústeres GKE se basan en el sistema de gestión de clústeres de código abierto Kubernetes. Kubernetes proporciona mecanismos para interactuar con el clúster.


Crear un clúster GKE:


1) Crear un clúster:


 gcloud container clusters create istioready \ --cluster-version latest \ --machine-type=n1-standard-2 \ --num-nodes 4 

El comando gcloud crea un clúster istioready en el proyecto GCP y la zona predeterminada que especificó. Para iniciar Istio, le recomendamos que tenga al menos 4 nodos y una máquina virtual n1-standard-2 .


El equipo crea un clúster durante varios minutos. Cuando el clúster está listo, el comando emite un mensaje similar.


2) Especifique las credenciales en la herramienta de línea de comandos kubectl para usarla para administrar el clúster:


 gcloud container clusters get-credentials istioready 

3) Ahora puedes comunicarte con Kubernetes a través de kubectl . Por ejemplo, con el siguiente comando puede averiguar el estado de los nodos:


 kubectl get nodes 

El comando muestra una lista de nodos:


 NAME STATUS ROLES AGE VERSION gke-istoready-default-pool-dbeb23dc-1vg0 Ready <none> 99s v1.13.6-gke.13 gke-istoready-default-pool-dbeb23dc-36z5 Ready <none> 100s v1.13.6-gke.13 gke-istoready-default-pool-dbeb23dc-fj7s Ready <none> 99s v1.13.6-gke.13 gke-istoready-default-pool-dbeb23dc-wbjw Ready <none> 99s v1.13.6-gke.13 

Conceptos clave de Kubernetes


El diagrama muestra la aplicación en GKE:



Antes de implementar contenedores en GKE, observe los conceptos clave de Kubernetes. Hay enlaces al final si quieres saber más.


  • Nodos y agrupaciones . En GKE, un nodo es una máquina virtual. En otras plataformas de Kubernetes, el host puede ser una computadora o una máquina virtual. Un clúster es una colección de nodos que se pueden considerar como un todo y donde se implementa una aplicación en contenedores.
  • Vainas En Kubernetes, los contenedores corren en vainas. Una vaina en Kubernetes es una unidad indivisible. Una vaina contiene uno o más contenedores. Implemente el servidor y los contenedores loadgen en pods separados. Cuando hay varios contenedores en un pod (por ejemplo, un servidor de aplicaciones y un servidor proxy ), los contenedores se administran como un solo objeto y comparten los recursos del pod.
  • Despliegue En Kubernetes, la implementación es un objeto que es una colección de pods idénticos. La implementación ejecuta varias réplicas de pods distribuidos en los nodos del clúster. La implementación reemplaza automáticamente los pods que fallan o no responden.
  • Servicio de kubernetes . Cuando ejecuta el código de la aplicación en GKE, la conexión entre loadgen y el servidor cambia. Cuando inició los servicios en la máquina virtual Cloud Shell o en la computadora, envió solicitudes al servidor en localhost: 8080 . Después de la implementación en GKE, los pods se ejecutan en los nodos disponibles. De forma predeterminada, no puede controlar en qué host se está ejecutando, por lo que los pod no tienen direcciones IP permanentes.
    Para obtener la dirección IP del servidor , debe definir la abstracción de red en la parte superior de los pods. Este es el servicio de Kubernetes . El servicio Kubernetes proporciona un punto final permanente para un conjunto de pods. Existen varios tipos de servicios . El servidor utiliza un LoadBalancer , que proporciona una dirección IP externa para contactar con el servidor desde fuera del clúster.
    Kubernetes también tiene un sistema DNS integrado que asigna nombres DNS (por ejemplo, helloserver.default.cluster.local ) a los servicios. Gracias a esto, los pods dentro del clúster se comunican con otros pods en el clúster en una dirección fija. El nombre DNS no se puede usar fuera del clúster, como en Cloud Shell o en una computadora.

Manifiestos de Kubernetes


Cuando inició la aplicación desde el código fuente, utilizó el imperativo comando python3


server.py


Imperativo implica el verbo: "hazlo".


Kubernetes usa un modelo declarativo . Esto significa que no le decimos a Kubernetes qué debe hacerse exactamente, sino que describimos el estado deseado. Por ejemplo, Kubernetes inicia y detiene los pods según sea necesario, para que el estado real del sistema sea el deseado.


Usted especifica el estado deseado en manifiestos o archivos YAML . El archivo YAML contiene especificaciones para uno o más objetos de Kubernetes.


El ejemplo contiene el archivo YAML para servidor y loadgen . Cada archivo YAML indica el estado deseado del objeto de implementación y el servicio Kubernetes.


server.yaml


 apiVersion: apps/v1 kind: Deployment metadata: name: helloserver spec: selector: matchLabels: app: helloserver replicas: 1 template: metadata: labels: app: helloserver spec: terminationGracePeriodSeconds: 5 restartPolicy: Always containers: - name: main image: gcr.io/google-samples/istio/helloserver:v0.0.1 imagePullPolicy: Always 

  • kind indica el tipo de objeto.
  • metadata.name indica el nombre de la implementación.
  • La primera especificación de campo contiene una descripción del estado deseado.
  • spec.replicas indica el número deseado de pods.
  • La sección spec.template define la plantilla de pod . En la especificación de pods hay un campo de imagen donde se indica el nombre de la imagen que se extraerá del Registro de contenedores.

El servicio se define de la siguiente manera:


 apiVersion: v1 kind: Service metadata: name: hellosvc spec: type: LoadBalancer selector: app: helloserver ports: - name: http port: 80 targetPort: 8080 

  • LoadBalancer : los clientes envían solicitudes a la dirección IP del equilibrador de carga, que tiene una dirección IP fija y a la que se puede acceder desde fuera del clúster.
  • targetPort : como recordará, el comando EXPOSE 8080 en el Dockerfile no proporcionó puertos. Proporciona el puerto 8080 para que pueda llegar al contenedor del servidor desde fuera del clúster. En nuestro caso, hellosvc.default.cluster.local: 80 (nombre corto: hellosvc ) corresponde al puerto 8080 de la dirección IP del pod helloserver .
  • puerto : este es el número de puerto donde otros servicios en el clúster enviarán solicitudes.

loadgen.yaml


El objeto de implementación en loadgen.yaml es similar a server.yaml . La diferencia es que el objeto de implementación contiene una sección env . Define las variables de entorno que necesita loadgen y que establece cuando inicia la aplicación desde el código fuente.


 apiVersion: apps/v1 kind: Deployment metadata: name: loadgenerator spec: selector: matchLabels: app: loadgenerator replicas: 1 template: metadata: labels: app: loadgenerator spec: terminationGracePeriodSeconds: 5 restartPolicy: Always containers: - name: main image: gcr.io/google-samples/istio/loadgen:v0.0.1 imagePullPolicy: Always env: - name: SERVER_ADDR value: "http://hellosvc:80/" - name: REQUESTS_PER_SECOND value: "10" resources: requests: cpu: 300m memory: 256Mi limits: cpu: 500m memory: 512Mi 

Como loadgen no acepta solicitudes entrantes, ClusterIP se especifica para el campo de tipo . Este tipo proporciona una dirección IP fija que los servicios en el clúster pueden usar, pero esta dirección IP no se proporciona a clientes externos.


 apiVersion: v1 kind: Service metadata: name: loadgensvc spec: type: ClusterIP selector: app: loadgenerator ports: - name: http port: 80 targetPort: 8080 

Implementar contenedores en GKE


1) Vaya al directorio donde se encuentra el ejemplo del servidor :


 cd YOUR_WORKING_DIRECTORY/istio-samples/sample-apps/helloserver/server/ 

2) Abra server.yaml en un editor de texto.
3) Reemplace el nombre en el campo de imagen con el nombre de su imagen Docker.


 image: gcr.io/PROJECT_ID/preparing-istio/helloserver:v0.0.1 

Reemplace PROJECT_ID con el identificador de su proyecto GCP.
4) Guarde y cierre server.yaml .
5) Expande el archivo YAML en Kubernetes:


 kubectl apply -f server.yaml 

Después de completar con éxito, el comando emite el siguiente código:


 deployment.apps/helloserver created service/hellosvc created 

6) Vaya al directorio donde se encuentra loadgen :


 cd ../loadgen 

7) Abra loadgen.yaml en un editor de texto.
8) Reemplace el nombre en el campo de imagen con el nombre de su imagen Docker.


 image: gcr.io/PROJECT_ID/preparing-istio/loadgenv0.0.1 

Reemplace PROJECT_ID con el identificador de su proyecto GCP.
9) Guarde y cierre loadgen.yaml , cierre el editor de texto.
10) Expanda el archivo YAML en Kubernetes:


 kubectl apply -f loadgen.yaml 

Después de completar con éxito, el comando emite el siguiente código:


 deployment.apps/loadgenerator created service/loadgensvc created 

11) Verifique el estado de los hogares:


 kubectl get pods 

El comando muestra el estado:


 NAME READY STATUS RESTARTS AGE helloserver-69b9576d96-mwtcj 1/1 Running 0 58s loadgenerator-774dbc46fb-gpbrz 1/1 Running 0 57s 

12) Extraiga los registros de la aplicación de la cápsula loadgen . Reemplace POD_ID con el identificador de la respuesta anterior.


 kubectl logs loadgenerator-POD_ID 

13) Obtenga las IP externas de hellosvc :


 kubectl get service 

La respuesta del comando se parece a esto:


 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hellosvc LoadBalancer 10.81.15.158 192.0.2.1 80:31127/TCP 33m kubernetes ClusterIP 10.81.0.1 <none> 443/TCP 93m loadgensvc ClusterIP 10.81.15.155 <none> 80/TCP 4m52s 

14) Enviar una solicitud a hellosvc : reemplace EXTERNAL_IP con la dirección IP externa de hellosvc .


 curl http://EXTERNAL_IP 

Tackle Istio


Ya tiene una aplicación implementada en GKE. loadgen puede usar Kubernetes DNS ( hellosvc: 80 ) para enviar solicitudes al servidor , y usted puede enviar solicitudes al servidor en una dirección IP externa. Aunque Kubernetes tiene muchas características, falta información sobre los servicios:


  • ¿Cómo interactúan los servicios? ¿Cuál es la relación entre los servicios? ¿Cómo es el tráfico entre servicios? Sabe que loadgen envía solicitudes al servidor , pero imagine que no sabe nada sobre la aplicación. Para responder a estas preguntas, miramos la lista de hogares en funcionamiento en GKE.
  • Métricas ¿Cuánto tiempo responde el servidor a una solicitud entrante? ¿Cuántas solicitudes por segundo van al servidor? ¿Da mensajes de error?
  • Información de seguridad . ¿Es el tráfico entre loadgen y el servidor simplemente a través de HTTP o mTLS ?

Todas estas preguntas son respondidas por Istio. Para hacer esto, Istio coloca un proxy de sidecar Envoy en cada pod. El proxy de envío intercepta todo el tráfico entrante y saliente a los contenedores de aplicaciones. Esto significa que el servidor y loadgen reciben proxies de sidecar de Envoy, y todo el tráfico desde loadgen al servidor pasa por proxies de Envoy.


Las conexiones entre los representantes de Envoy forman una malla de servicio. La arquitectura de malla de servicio proporciona una capa de control sobre Kubernetes.



Una vez que los servidores proxy de Envoy se ejecutan en sus contenedores, Istio se puede instalar en la parte superior del clúster GKE, casi sin cambiar el código de la aplicación. Pero trabajó un poco para preparar la aplicación para la administración con Istio:


  • Servicios para todos los contenedores. Las implementaciones de servidor y loadgen están vinculadas por el servicio Kubernetes. Incluso loadgen , que no recibe solicitudes entrantes, tiene un servicio.
  • Los puertos en los servicios deben tener nombres. Aunque los puertos de servicio pueden dejarse sin nombre en GKE, Istio requiere un nombre de puerto de acuerdo con su protocolo. En el archivo YAML, el puerto para el servidor se llama http porque el servidor usa el protocolo HTTP . Si el servicio usara gRPC , usted nombraría el puerto grpc .
  • Las implementaciones están marcadas. Por lo tanto, puede usar las funciones de administración de tráfico de Istio, por ejemplo, compartir tráfico entre versiones del mismo servicio.

Instalar Istio


Hay dos formas de instalar Istio. Puede habilitar la extensión Istio en GKE o instalar la versión de código abierto de Istio en un clúster. Con Istio en GKE, puede administrar fácilmente la instalación y actualización de Istio como parte del ciclo de vida del clúster GKE. Si necesita la última versión de Istio o más control sobre la configuración del panel de control de Istio, instale la versión de código abierto en lugar de la extensión Istio en GKE. Para decidir sobre el enfoque, lea el artículo ¿Necesito Istio en GKE? .


Seleccione una opción, estudie el manual apropiado y siga las instrucciones para instalar Istio en el clúster. Si desea usar Istio con su aplicación recién implementada, habilite la incrustación de sidecar para el espacio de nombres predeterminado .


Limpieza


Para asegurarse de que los recursos para los recursos que utilizó en esta guía no se debiten de su cuenta de Google Cloud Platform, elimine el clúster de contenedores cuando instale Istio y juegue con la aplicación de muestra. Esto eliminará todos los recursos del clúster, como instancias de cómputo, discos y recursos de red.


Que sigue


Source: https://habr.com/ru/post/469515/


All Articles