Preparando una aplicación para Istio

Preparando una aplicación para Istio

Istio es una herramienta conveniente para conectar, proteger y monitorear aplicaciones distribuidas. Istio utiliza una variedad de tecnologías para ejecutar y administrar software a escala, incluidos contenedores para empaquetar el código de la aplicación y las dependencias para la implementación, y Kubernetes para administrar esos contenedores. Por tanto, para trabajar con Istio debes saber cómo funciona una aplicación con múltiples servicios basada en estas tecnologías. sin Istio. Si estas herramientas y conceptos ya le resultan familiares, no dude en omitir este tutorial e ir directamente a la sección Instalación de Istio en Google Kubernetes Engine (GKE) o instalar una extensión Istio en GKE.

Esta es una guía paso a paso en la que recorreremos todo el proceso, desde el código fuente hasta el contenedor de GKE, para brindarle una comprensión básica de estas tecnologías a través de un ejemplo. También verá cómo Istio aprovecha el poder de estas tecnologías. Esto supone que no sabes nada sobre contenedores, Kubernetes, mallas de servicios o Istio.

Tareas

En este tutorial, completará las siguientes tareas:

  1. Aprender una aplicación sencilla de Hola Mundo con múltiples servicios.
  2. Ejecute la aplicación desde el código fuente.
  3. Envasar la aplicación en contenedores.
  4. Creando un clúster de Kubernetes.
  5. Implementar contenedores en un clúster.

Antes de que empieces

Siga las instrucciones para habilitar la API de Kubernetes Engine:

  1. Ir a Página del motor de Kubernetes en la consola de Google Cloud Platform.
  2. Crea o selecciona un proyecto.
  3. Espere hasta que la API y los servicios relacionados estén habilitados. Esto puede tomar unos pocos minutos.
  4. Asegúrate de que la facturación esté configurada para tu proyecto de Google Cloud Platform. Aprenda cómo habilitar la facturación.

En este tutorial, puede utilizar Cloud Shell, que prepara la máquina virtual. g1-pequeño en Google Compute Engine con Linux basado en Debian, o una computadora Linux o macOS.

Opción A: usar Cloud Shell

Beneficios de usar Cloud Shell:

  • Entornos de desarrollo Python 2 y Python 3 (incluidos virtualenv) están completamente configurados.
  • Herramientas de línea de comando nube de gcloud, estibador, git и kubectl, que usaremos ya están instalados.
  • Tienes varios para elegir editores de texto:
    1. Editor de código, que se abre con el ícono 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 comando en Cloud Shell.

Usar Cáscara de la nube:

  1. Vaya a la consola de GCP.
  2. Нажмите кнопку Activar Cloud Shell (Activar Cloud Shell) en la parte superior de la ventana de la consola de GCP.

Preparando una aplicación para Istio

En la parte baja consola GCP Se abrirá una sesión de Cloud Shell con una línea de comando en una nueva ventana.

Preparando una aplicación para Istio

Opción B: usar herramientas de línea de comandos localmente

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

  1. Personalizar Entorno de desarrollo Python 3 y Python 2.

  2. Instalar el SDK de la nube con herramienta de línea de comando nube de gcloud.

  3. Establecer kubectl - herramienta de línea de comando para trabajar con Kubernetes.

    gcloud components install kubectl

  4. Establecer Edición comunitaria Docker (CE). Utilizarás la herramienta de línea de comando. estibadorpara crear imágenes de contenedor para la aplicación de muestra.

  5. Instalar la herramienta control de versiones de gitpara obtener la aplicación de muestra de GitHub.

Descargar código de muestra

  1. Descarga el código fuente holaservidor:

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

  2. Vaya al directorio de código de ejemplo:

    cd istio-samples/sample-apps/helloserver

Explorando una aplicación con múltiples servicios

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

  • servidor: servidor simple con un punto final CONSEGUIR, /, que imprime "hola mundo" en la consola.
  • generador de carga: script que envía tráfico a servidor, con un número configurable de solicitudes por segundo.

Preparando una aplicación para Istio

Ejecutar una aplicación desde el código fuente

Para explorar la aplicación de muestra, ejecútela en Cloud Shell o en su computadora.
1) En el catálogo istio-samples/aplicaciones-de-muestra/helloserver correr servidor:

python3 server/server.py

Cuando se ejecuta servidor se muestra lo siguiente:

INFO:root:Starting server...

2) Abra otra ventana de terminal para enviar solicitudes a servidor. Si está utilizando Cloud Shell, haga clic en el ícono Agregar para abrir otra sesión.
3) Enviar una solicitud a 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 generador de carga:

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) Corre virtualenv:

virtualenv --python python3 env

7) Activar el entorno virtual:

source env/bin/activate

8) Establecer requisitos para generador de carga:

pip3 install -r requirements.txt

9) Corre generador de carga:

python3 loadgen.py

Cuando se ejecuta generador de carga muestra algo como 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 servidor envía 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 un único host (computadora local o máquina virtual de Cloud Shell). Por lo tanto puedes usar localhostpara enviar solicitudes a servidor.
10) Parar generador de carga и servidor, ingresar Ctrl-c en cada ventana de terminal.
11) En la ventana de terminal generador de carga desactivar el entorno virtual:

deactivate

Empaquetar una aplicación en contenedores

Para ejecutar la aplicación en GKE, debe empaquetar la aplicación de muestra: servidor и generador de carga - en contenedores. Un contenedor es una forma de empaquetar una aplicación para aislarla de su entorno.

Para empaquetar una aplicación en un contenedor, necesita Dockerfile. Dockerfile es un archivo de texto que define comandos para construir el código fuente de la aplicación y sus dependencias en Imagen acoplable. Una vez creada, carga la imagen en un registro de contenedor como Docker Hub o Registro de contenedores.

El ejemplo ya tiene Dockerfile para servidor и generador de carga con todos los comandos necesarios para recopilar imágenes. Abajo - 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" ]

  • Equipo DESDE Python:3-slim como base le dice a Docker que use la última versión Imagen de Python 3 como base.
  • Equipo COPIAR. . copia los archivos fuente al directorio de trabajo actual (en nuestro caso solo servidor.py) al sistema de archivos del contenedor.
  • PUNTO DE ENTRADA define el comando que se utiliza para iniciar el contenedor. En nuestro caso, este comando es casi el mismo que usaste para ejecutar servidor.py del código fuente.
  • Equipo EXPOSICION indica que servidor espera datos a través del puerto 8080. este equipo no es proporciona puertos. Este es algún tipo de documentación que se necesita para abrir el puerto. 8080 al arrancar el contenedor.

Preparándose para contenerizar su aplicación

1) Establezca las siguientes variables de entorno. Reemplazar PROJECTO ID a su ID de proyecto de GCP.

export PROJECT_ID="PROJECT_ID"

export GCR_REPO="preparing-istio"

Usando valores PROJECTO ID и GCR_REPO usted etiqueta la imagen de Docker cuando la crea y la envía a un Registro de contenedores privado.

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

gcloud config set project $PROJECT_ID

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

gcloud config set compute/zone us-central1-b

4) Asegúrese de que el servicio Container Registry esté habilitado en el proyecto GCP.

gcloud services enable containerregistry.googleapis.com

Servidor de contenedores

  1. Vaya al directorio donde se encuentra el ejemplo. servidor:

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

  2. Montar la imagen usando Dockerfile y las variables de entorno que definiste anteriormente:

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

Parámetro -t representa la etiqueta Docker. Este es el nombre de la imagen que utiliza al implementar el contenedor.

  1. Sube la imagen al Registro de Contenedores:
    docker push gcr.io/$PROJECT_ID/$GCR_REPO/helloserver:v0.0.1

Contenedorización de loadgen

1) Vaya al directorio donde se encuentra el ejemplo. generador de carga:

cd ../loadgen

2) Recoge la imagen:

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

3) Sube la imagen al Registro de Contenedores:

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

Ver una lista de imágenes

Revise la lista de imágenes en el repositorio y verifique que las imágenes hayan sido cargadas:

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

El comando muestra los nombres de las imágenes recién cargadas:

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

Creando un clúster de GKE.

Estos contenedores podrían ejecutarse en una máquina virtual de Cloud Shell o en una computadora con el comando Docker Run. Pero en un entorno de producción, se necesita una forma de organizar los contenedores de forma centralizada. Por ejemplo, necesita un sistema que garantice que los contenedores estén siempre ejecutándose y necesita una forma de escalar y activar instancias de contenedores adicionales si aumenta el tráfico.

Para ejecutar aplicaciones en contenedores, puede utilizar GKE. GKE es una plataforma de orquestación de contenedores que agrega máquinas virtuales en un clúster. Cada máquina virtual se llama nodo. Los clústeres de GKE se basan en el sistema de gestión de clústeres Kubernetes de código abierto. Kubernetes proporciona mecanismos para interactuar con el clúster.

Creando un clúster de GKE:

1) Crear un clúster:

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

Equipo nube de gcloud Crea un clúster istioready en el proyecto de GCP y la zona predeterminada que especificaste. Para ejecutar Istio recomendamos tener al menos 4 nodos y una máquina virtual n1-estándar-2.

El equipo crea el clúster en unos minutos. Cuando el clúster está listo, el comando genera algo como esto сообщение.

2) Proporcione credenciales en la herramienta de línea de comando kubectlpara usarlo para administrar el clúster:

gcloud container clusters get-credentials istioready

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

kubectl get nodes

El comando produce 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 una aplicación en GKE:

Preparando una aplicación para Istio

Antes de implementar contenedores en GKE, aprende los conceptos clave de Kubernetes. Hay enlaces al final si desea obtener más información.

  • Nodos y clusters. En GKE, un nodo es una máquina virtual. En otras plataformas de Kubernetes, un nodo puede ser una computadora o una máquina virtual. Un clúster es una colección de nodos que pueden considerarse una única unidad donde se implementa una aplicación en contenedores.
  • vainas. En Kubernetes, los contenedores se ejecutan en pods. Un Pod en Kubernetes es una unidad indivisible. Un Pod contiene uno o más contenedores. Implementas contenedores de servidores y generador de carga en vainas separadas. Cuando hay varios contenedores en un pod (por ejemplo, un servidor de aplicaciones y servidor proxy), los contenedores se administran como una sola entidad y comparten recursos del pod.
  • Implementaciones. En Kubernetes, una implementación es un objeto que es una colección de pods idénticos. La implementación lanza múltiples réplicas de pods distribuidos en los nodos del clúster. La implementación reemplaza automáticamente los pods que fallaron o no responden.
  • Servicio Kubernetes. Al ejecutar el código de la aplicación en GKE, la conexión entre generador de carga и servidor. Cuando inició servicios en una máquina virtual o un escritorio de Cloud Shell, envió solicitudes a servidor por dirección localhost: 8080. Una vez implementados en GKE, los pods se ejecutan en los nodos disponibles. De forma predeterminada, no tienes control sobre en qué nodo se ejecuta el pod, por lo que vainas sin direcciones IP permanentes.
    Para obtener una dirección IP para servidor, debe definir una abstracción de red encima de los pods. Eso es lo que es Servicio Kubernetes. El servicio Kubernetes proporciona un punto final persistente para un conjunto de pods. Hay algunos tipos de servicios. servidor usos equilibrador de carga, que proporciona una dirección IP externa para contactar servidor desde fuera del cúmulo.
    Kubernetes también tiene un sistema DNS integrado que asigna nombres DNS (por ejemplo, holaservidor.default.cluster.local) servicios. Gracias a esto, los pods dentro del clúster se comunican con otros pods del clúster en una dirección constante. El nombre DNS no se puede utilizar fuera del clúster, como en Cloud Shell o en una computadora.

Kubernetes se manifiesta

Cuando ejecutó la aplicación desde la fuente, utilizó el comando imperativo python3

servidor.py

El imperativo implica un verbo: "hacer esto".

Usos de Kubernetes modelo declarativo. Esto significa que no le estamos diciendo a Kubernetes exactamente qué hacer, sino más bien describiendo el estado deseado. Por ejemplo, Kubernetes inicia y detiene pods según sea necesario para mantener el estado real del sistema coherente con el estado deseado.

Indicas el estado deseado en manifiestos o archivos. Ñame. Un archivo YAML contiene especificaciones para uno o más objetos de Kubernetes.

El ejemplo contiene un archivo YAML para servidor и generador de carga. Cada archivo YAML especifica el estado deseado del objeto de implementación y el servicio de Kubernetes.

servidor.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

  • tipo indica el tipo de objeto.
  • nombre.metadatos especifica el nombre de la implementación.
  • primer campo especulación contiene una descripción del estado deseado.
  • especificaciones.réplicas indica el número deseado de vainas.
  • Sección plantilla.especificación define una plantilla de pod. Hay un campo en la especificación del pod. imagen, que especifica el nombre de la imagen que debe extraerse del Container Registry.

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

  • equilibrador de carga: los clientes envían solicitudes a la dirección IP del equilibrador de carga, que tiene una dirección IP persistente y es accesible desde fuera del clúster.
  • destinoPuerto: como recordarás, el equipo EXPONER 8080 в Dockerfile no proporcionó puertos. Tu proporcionas el puerto 8080para que puedas contactar con el contenedor servidor fuera del cúmulo. En nuestro caso holavc.default.cluster.local:80 (nombre corto: holavc) corresponde al puerto 8080 Direcciones IP del módulo holaservidor.
  • Puerto: este es el número de puerto donde otros servicios del clúster enviarán solicitudes.

cargagen.yaml

Objeto de implementación para cargagen.yaml parecerse a servidor.yaml. La diferencia es que el objeto de implementación contiene una sección env. Define las variables de entorno que se necesitan. generador de carga y que instaló al ejecutar la aplicación desde la 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

Tiempo generador de carga no acepta solicitudes entrantes, para el campo tipo indicado IP de clúster. Este tipo proporciona una dirección IP persistente que los servicios del clúster pueden usar, pero esta dirección IP no está expuesta a clientes externos.

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

Implementación de contenedores en GKE

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

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

2) Abierto servidor.yaml en un editor de texto.
3) Reemplace el nombre en el campo. imagen al nombre de su imagen de Docker.

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

Reemplazar PROJECTO ID a su ID de proyecto de GCP.
4) Guardar y cerrar servidor.yaml.
5) Implemente el archivo YAML en Kubernetes:

kubectl apply -f server.yaml

Al completarse exitosamente, el comando produce el siguiente código:

deployment.apps/helloserver created
service/hellosvc created

6) Vaya al directorio donde generador de carga:

cd ../loadgen

7) Abierto cargagen.yaml en un editor de texto.
8) Reemplace el nombre en el campo. imagen al nombre de su imagen de Docker.

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

Reemplazar PROJECTO ID a su ID de proyecto de GCP.
9) Guardar y cerrar cargagen.yaml, cierre el editor de texto.
10) Implemente el archivo YAML en Kubernetes:

kubectl apply -f loadgen.yaml

Al completarse exitosamente, el comando produce el siguiente código:

deployment.apps/loadgenerator created
service/loadgensvc created

11) Verificar el estado de las vainas:

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) Extraer registros de aplicaciones del pod generador de carga. Reemplazar POD_ID al identificador de la respuesta anterior.

kubectl logs loadgenerator-POD_ID

13) Obtener direcciones IP externas holavc:

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 holavc: reemplazar IP_EXTERNA a una dirección IP externa holavc.

curl http://EXTERNAL_IP

Enfrentémonos a Istio

Ya tienes una aplicación implementada en GKE. generador de carga puede utilizar Kubernetes DNS (holavc:80) para enviar solicitudes a servidory puedes enviar solicitudes a servidor por dirección IP externa. Aunque Kubernetes tiene muchas características, falta información sobre los servicios:

  • ¿Cómo interactúan los servicios? ¿Cuáles son las relaciones entre servicios? ¿Cómo fluye el tráfico entre servicios? ¿Eres consciente de que generador de carga envía solicitudes a servidor, pero imagina que no sabes nada sobre la aplicación. Para responder estas preguntas, veamos la lista de pods en ejecución en GKE.
  • Métrica. Cuánto tiempo servidor responde a una solicitud entrante? ¿Cuántas solicitudes por segundo recibe el servidor? ¿Da mensajes de error?
  • Informacion de seguridad. Tráfico entre generador de carga и servidor solo pasa por HTTP o por mTLS?

Istio responde a todas estas preguntas. Para hacer esto, Istio coloca un proxy sidecar Enviado en cada vaina. El proxy Envoy intercepta todo el tráfico entrante y saliente a los contenedores de aplicaciones. Esto significa que servidor и generador de carga recibir a través del proxy sidecar Envoy y todo el tráfico desde generador de carga к servidor pasa por el proxy Envoy.

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

Preparando una aplicación para Istio

Dado que los proxies Envoy se ejecutan en sus propios contenedores, Istio se puede instalar encima de un clúster de GKE casi sin cambios en el código de la aplicación. Pero has trabajado un poco para que tu aplicación esté lista para ser administrada por Istio:

  • Servicios para todos los contenedores. A implementaciones servidor и generador de carga vinculado al servicio de Kubernetes. Incluso generador de carga, que no recibe solicitudes entrantes, hay un servicio.
  • Los puertos en los servicios deben tener nombres. Aunque los puertos de servicio se pueden dejar sin nombre en GKE, Istio requiere que especifiques nombre del puerto de acuerdo con su protocolo. En el archivo YAML el puerto para servidor llamado httpporque el servidor usa el protocolo HTTP. Si de coches utilizado gRPC, nombrarías el puerto grpc.
  • Las implementaciones están marcadas. Por lo tanto, puede utilizar las funciones de gestión del tráfico de Istio, como dividir el tráfico entre versiones del mismo servicio.

Instalación

Hay dos formas de instalar Istio. Poder habilitar Istio en la extensión GKE o instalar la versión de código abierto de Istio en el cúmulo. Con Istio en GKE, puedes administrar fácilmente las instalaciones y actualizaciones de Istio durante todo el ciclo de vida del clúster de GKE. Si desea la última versión de Istio o tener más control sobre la configuración de su panel de control de Istio, instale la versión de código abierto en lugar de la extensión Istio en GKE. Para decidir el enfoque, lea el artículo. ¿Necesito Istio en GKE?.

Seleccione una opción, lea la guía adecuada y siga las instrucciones para instalar Istio en su clúster. Si desea utilizar Istio con su aplicación recién implementada, habilitar la implementación del sidecar para espacio de nombres tu préstamo estudiantil.

limpieza

Para evitar que se le cobre en su cuenta de Google Cloud Platform por los recursos que utilizó en este tutorial, elimine el clúster de contenedores una vez que haya instalado Istio y haya jugado con la aplicación de muestra. Esto eliminará todos los recursos del clúster, como instancias informáticas, discos y recursos de red.

¿Qué será lo próximo?

Fuente: habr.com

Añadir un comentario