17 min de lectura

Objetivos de aprendizaje

Al final de este módulo, podrás:

  • Proporcionar un Managed Kubernetes Cluster y Node Pools con Terraform y recuperar el kubeconfig directamente desde el estado
  • Desplegar despliegues, servicios, ConfigMaps y secretos en MKS, extrayendo imágenes de Private Container Registry con `imagePullSecrets`
  • Exponer el tráfico de aplicaciones correctamente, considerando que el tipo de servicio `LoadBalancer` en MKS no es un verdadero Load Balancer externo, y frente al Cluster con un Application Load Balancer provisionado por separado
  • Administrar Node Pools de forma programática: escalar los recuentos de Node, ejecutar actualizaciones de versión y aislar cargas de trabajo en varios grupos
  • Depurar cargas de trabajo en ejecución con `kubectl logs`, `exec` y eventos, sabiendo qué señalesles la plataforma IONOS si y no superficie

Unidad 3.2: Despliegue y operaciones de Kubernetes

Introducción

Usted containerizó la parte frontal, el trabajador y TaskBoard's API en la Unidad 3.1 y los empujó a Private Container Registry con etiquetas de git-SHA. Ahora necesita algún lugar para ejecutarlos. En esta unidad, usted aprovisiona un Managed Kubernetes (MKS) Cluster como código, conecta las credenciales del registro en el Cluster para que pueda extraer sus imágenes, y despliega los tres servicios como recursos estándar de Kubernetes.

El plano de control de MKS es gestionado por usted, pero dos realidades específicas de IONOS dan forma a cada despliegue que escribe. Primero, un Service de tipo LoadBalancer en MKS no provisiona un Load Balancer externo real, por lo que el ingreso de producción está front-end por una Application Load Balancer (ALB) provisionada por separado. Segundo, los eventos del plano de control que podría esperar en una secuencia de registro centralizada no están allí, lo que cambia la forma en que usted depura. Usted escribirá código para ambas realidades, en lugar de trabajar alrededor de ellas después de que lo muerdan en producción.

1. Provisionar el Cluster con Terraform

Un Managed Kubernetes Cluster en IONOS es dos recursos distintos: el Cluster (el plano de control gestionado) y uno o más Node Pools (el cómputo de trabajador que paga). El plano de control en sí es gratuito; solo paga por el cómputo del Node Pool subyacente y los volúmenes Block Storage que su Pods proporciona. Cree el Cluster primero, luego adjunte Node Pools que lo referencia.

1.1 Recursos de Cluster y Node Pool

El recurso ionoscloud_k8s_cluster define el plano de control y su versión Kubernetes. El recurso ionoscloud_k8s_node_pool define Worker Nodes dentro de un centro de datos específico.

resource "ionoscloud_k8s_cluster" "taskboard" {
  name        = "taskboard-prod"
  k8s_version = "1.34"

  maintenance_window {
    day_of_the_week = "Sunday"
    time            = "03:00:00Z"
  }
}

resource "ionoscloud_k8s_node_pool" "app" {
  name              = "taskboard-app-pool"
  k8s_cluster_id    = ionoscloud_k8s_cluster.taskboard.id
  datacenter_id     = ionoscloud_datacenter.taskboard.id
  k8s_version       = ionoscloud_k8s_cluster.taskboard.k8s_version
  cpu_family        = "INTEL_SKYLAKE"
  server_type       = "DedicatedCore"
  node_count        = 3
  cores_count       = 4
  ram_size          = 8192
  availability_zone = "AUTO"
  storage_type      = "SSD"
  storage_size      = 100
}

Las versiones Kubernetes compatibles son 1.34, 1.33, 1.32 y 1.31. Fije una versión explícita k8s_version en lugar de seguir la última, porque cada actualización del Node Pool se ejecuta durante la ventana de mantenimiento y puede causar desconexiones. Los Node Pools aceptan tanto los tipos de servidor DedicatedCore como vCPU, así que dimensione el Node Pool de aplicaciones de TaskBoard en Dedicated Core para un rendimiento predecible.

1.2 Recuperar el kubeconfig desde el estado

No descarga el kubeconfig desde una interfaz de usuario. El recurso Cluster expone la configuración directamente, por lo que Terraform puede escribirla en el disco para que kubectl y CI la consuman.

output "kubeconfig" {
  value     = ionoscloud_k8s_cluster.taskboard.kube_config
  sensitive = true
}

resource "local_file" "kubeconfig" {
  content         = ionoscloud_k8s_cluster.taskboard.kube_config
  filename        = "${path.module}/kubeconfig.yaml"
  file_permission = "0600"
}
export KUBECONFIG=$(pwd)/kubeconfig.yaml
kubectl get nodes

El kubeconfig también es recuperable a través de API en GET /k8s/{k8sClusterId}/kubeconfig y mediante ionosctl k8s kubeconfig get --cluster-id <id>. Trátelo como un secreto: otorga acceso completo a Cluster. Marque la salida de Terraform como sensitive y nunca comprometa el archivo generado.

2. Implementación de cargas de trabajo en MKS

Una vez que kubectl alcanza el Cluster, MKS se comporta como un Kubernetes estándar upstream. No hay un dialecto de manifiesto específico de IONOS. Usted aplica implementaciones, servicios, ConfigMaps y Secretos exactamente como lo haría en cualquier Cluster conforme. El CNI es Calico y es fijo, por lo que la autoría de la política de red sigue la semántica de Calico sin opción para cambiar el plugin.

2.1 Implementación, ConfigMap y Secret

TaskBoard necesita configuración no secreta y credenciales secretas de API. Sepárelos: un ConfigMap para el host de la base de datos y las banderas de características, un Secret para la contraseña de conexión.

apiVersion: v1
kind: ConfigMap
metadata:
  name: taskboard-config
  namespace: taskboard
data:
  DB_HOST: "pg-cluster.taskboard.internal"
  CACHE_TTL: "300"
---
apiVersion: v1
kind: Secret
metadata:
  name: taskboard-db
  namespace: taskboard
type: Opaque
stringData:
  DB_PASSWORD: "REPLACED_FROM_TERRAFORM_OUTPUT"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: taskboard-api
  namespace: taskboard
spec:
  replicas: 3
  selector:
    matchLabels:
      app: taskboard-api
  template:
    metadata:
      labels:
        app: taskboard-api
    spec:
      imagePullSecrets:
        - name: registry-cred
      containers:
        - name: api
          image: <registry-name>.cr.de-fra.ionos.com/taskboard-api:<git-sha>
          ports:
            - containerPort: 8080
          envFrom:
            - configMapRef:
                name: taskboard-config
          env:
            - name: DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: taskboard-db
                  key: DB_PASSWORD
          readinessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 5
          livenessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 15

Los datos secretos están cifrados en REST en MKS, pero los Secretos de Kubernetes solo están codificados en base64 en el manifiesto, por lo que aún debe mantener los valores de origen fuera de Git y inyectarlos desde la salida de Terraform en el momento de la implementación. La sonda de preparación es importante porque las actualizaciones de rodillo esperan a que se complete antes de cambiar el tráfico.

2.2 Extracción de imágenes con imagePullSecrets

Private Container Registry requiere autenticación para cada extracción, y es un inicio de sesión basado en token Docker solo, sin RBAC y sin repositorios por equipo. Kubernetes necesita un Secret dockerconfigjson creado a partir de un token de registro, referenciado como imagePullSecrets en la especificación del pod anterior.

kubectl create namespace taskboard

kubectl create secret docker-registry registry-cred \
  --namespace taskboard \
  --docker-server=<registry-name>.cr.de-fra.ionos.com \
  --docker-username=<token-name> \
  --docker-password=<registry-token>

Si omite la referencia imagePullSecrets, o limita el Secret al namespace incorrecto, Pods se bloqueará en ImagePullBackOff. El Secret es de namespace, por lo que créelo en cada namespace que ejecuta imágenes de registro. En CI, genera el token de registro una vez y lo almacena como un secreto de pipeline, luego crea el Secret de Kubernetes como un paso de implementación.

3. Exponiendo tráfico: la realidad de LoadBalancer

Este es el hecho más importante específico de IONOS en la unidad. Un Service de tipo LoadBalancer en MKS no provisiona un verdadero Load Balancer externo. IONOS Cloud reserva una dirección pública estática IP y la asigna como una dirección secundaria IP a un worker Node, que se convierte en el ingreso Node, y kube-proxy luego NATs el tráfico al pod objetivo.

3.1 Qué significa esto para sus manifestos

Dos consecuencias siguen directamente. La fuente del cliente IP se pierde a menos que establezca externalTrafficPolicy: Local, y el rendimiento está limitado a ese solo ingreso Node con un techo público de 2 Gbit/s porque todo el tráfico se canaliza a través de un Node. No hay alta disponibilidad automática en los nodos para esa IP.

apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  selector:
    app: ingress-nginx
  ports:
    - port: 443
      targetPort: 8443

Para escalar el tráfico más allá de un solo Node, se reservan varias direcciones LB IP y se distribuyen en varios nodos de ingreso utilizando DNS de equilibrio de carga. Como solo las direcciones Node Pools públicas admiten el tipo de servicio LoadBalancer (las direcciones Node Pools privadas no), mantenga su controlador de ingreso que enfrenta a Internet en un grupo público. Exponga solo el controlador de ingreso como LoadBalancer, nunca un Servicio por aplicación.

3.2 Fronting el Cluster con un ALB provisionado por separado

Para la tabla de tareas de producción, proporcione una aplicación Load Balancer por separado a través de Terraform. El ALB no se crea automáticamente a partir de ningún manifiesto Kubernetes, por lo que no hay anotación del controlador de ingreso que lo invoque. Usted lo proporciona como infraestructura y apunta sus reglas de reenvío al Node IPs que sirven el controlador de ingreso.

resource "ionoscloud_application_loadbalancer" "taskboard" {
  name          = "taskboard-alb"
  datacenter_id = ionoscloud_datacenter.taskboard.id
  listener_lan  = ionoscloud_lan.public.id
  ips           = [ionoscloud_ipblock.alb.ips[0]]
  target_lan    = ionoscloud_lan.app.id
}

resource "ionoscloud_application_loadbalancer_forwardingrule" "https" {
  datacenter_id               = ionoscloud_datacenter.taskboard.id
  application_loadbalancer_id = ionoscloud_application_loadbalancer.taskboard.id
  name                        = "https-rule"
  protocol                    = "HTTP"
  listener_ip                 = ionoscloud_ipblock.alb.ips[0]
  listener_port               = 443
}

Tenga en cuenta que las reglas de NSG no se aplican al ALB. Las reglas Network Security Groups se unen al nivel de NIC del servidor, no al ALB administrado o a MKS, por lo que controla el tráfico de ingreso a través de las reglas de reenvío del ALB y las reglas de seguridad en las NIC del worker Node, no adjuntando un NSG al Load Balancer.

4. Node Operaciones de grupo

Node Pools son la superficie operativa que usted gestiona durante la vida útil de Cluster: escalabilidad para carga, actualización de versiones de Kubernetes y aislamiento de cargas de trabajo. Los nodos en sí mismos son inmutables, por lo que los cambios de configuración que afectan un Node lo reemplazan en lugar de mutarlo en su lugar.

4.1 Escalabilidad y aislamiento de Workload

Escalabilidad de un grupo es un cambio node_count aplicado a través de Terraform o API. Un grupo de Node puede contener hasta 100 nodos (se recomiendan 20), un Cluster puede contener hasta 500 Node Pools (se recomiendan 50) y hasta 5000 nodos en total, y cada Node puede ejecutar hasta 110 Pods con hasta 20 volúmenes adjuntos. Utilice grupos separados para aislar cargas de trabajo, por ejemplo, un grupo de Dedicated Core para el API sensible a la latencia y un grupo de vCPU para el trabajador en segundo plano.

resource "ionoscloud_k8s_node_pool" "worker" {
  name           = "taskboard-worker-pool"
  k8s_cluster_id = ionoscloud_k8s_cluster.taskboard.id
  datacenter_id  = ionoscloud_datacenter.taskboard.id
  k8s_version    = ionoscloud_k8s_cluster.taskboard.k8s_version
  server_type    = "vCPU"
  node_count     = 2
  cores_count    = 2
  ram_size       = 4096
  storage_type   = "SSD"
  storage_size   = 50
}

Programar el despliegue del trabajador en este grupo con un nodeSelector que coincida con el grupo, manteniéndolo fuera de los nodos de API.

4.2 Actualizaciones de versión

Aumentar k8s_version en el grupo de Node para actualizar. La operación alinea los recursos en el centro de datos de destino y el grupo vuelve a Active cuando esté completo, pero se ejecuta durante el mantenimiento y puede causar desconexiones, así que hágalo deliberadamente. Mantenga la versión menor del controlador y las versiones del grupo de Node dentro de la desviación admitida, y actualice el controlador antes de Node Pools.

ionosctl k8s nodepool update \
  --cluster-id <cluster-id> \
  --nodepool-id <nodepool-id> \
  --k8s-version 1.34

Los volúmenes persistentes están provisionados por el controlador IONOS CSI (provisionador cloud.ionos.com) respaldado por Block Storage, por lo que los Pods con PVC se vuelven a programar en nodos de reemplazo durante una actualización sin perder datos.

5. Depuración de cargas de trabajo en MKS

Cuando una implementación se comporta mal, trabaje desde el pod hacia afuera. La cadena de triage estándar kubectl se aplica, pero una brecha en la plataforma cambia su estrategia: los eventos del plano de control de Kubernetes no fluyen a través de IONOS Logging Service, así que no espere encontrar registros del programador o del servidor API allí.

5.1 La cadena de triage

# pod status and restart counts
kubectl get pods -n taskboard -o wide

# why a pod is stuck (events at the bottom)
kubectl describe pod taskboard-api-7d9f -n taskboard

# application stdout/stderr, including the previous crashed container
kubectl logs taskboard-api-7d9f -n taskboard --previous

# cluster-scoped events, newest last
kubectl get events -n taskboard --sort-by=.lastTimestamp

# shell into a running container to test connectivity
kubectl exec -it taskboard-api-7d9f -n taskboard -- sh

kubectl describe es donde ImagePullBackOff, el programación fallida y las fallas de sondeo se manifiestan, así que léalo antes de buscar registros. Para la observabilidad a nivel de aplicación, envíe sus propios registros de contenedor a Logging Service explícitamente, porque la plataforma no capturará señales de plano de control para usted.

5.2 Conociendo el límite de la plataforma

Si asume que los eventos del plano de control se registran centralmente, perderá horas buscando en un flujo que nunca los contenía. Configure el envío de registros a nivel de Cluster (por ejemplo, un DaemonSet de Fluent Bit que envía registros de pod a Logging Service) para los registros de aplicación que controla, y confíe en kubectl get events para la visibilidad del plano de control. Combine esto con las sondas de preparación y vitalidad de la Sección 2 para que Cluster reinicie y reprogramme automáticamente los Pods no saludables mientras investiga.

API Tarjeta de referencia rápida

Puntos de conexión clave de API para Managed Kubernetes:

Método Punto de conexión Descripción
GET /k8s Lista todos los clústeres de Kubernetes
POST /k8s Crea un nuevo Cluster
GET /k8s/{k8sClusterId}/kubeconfig Recupera el kubeconfig de Cluster
POST /k8s/{k8sClusterId}/nodepools Crea un grupo de Node
PUT /k8s/{k8sClusterId}/nodepools/{nodepoolId} Escala o actualiza un grupo de Node

URL base: https://api.ionos.com/cloudapi/v6 Autenticación: Authorization: Bearer <token>

Laboratorio de código

Objetivo: Provisionar un MKS Cluster con Terraform, implementar TaskBoard's API desde Private Container Registry y acceder a él a través de un controlador de ingreso.

Requisitos previos:

  • Cuenta de IONOS Cloud con token API (IONOS_TOKEN exportado)
  • Terraform y el proveedor ionos-cloud/ionoscloud
  • kubectl y ionosctl instalados
  • Un Private Container Registry con la imagen taskboard-api subida (Unidad 3.1)

Paso 1: Provisionar el grupo Cluster y Node

terraform init
terraform apply -auto-approve

Salida esperada:

ionoscloud_k8s_cluster.taskboard: Creation complete
ionoscloud_k8s_node_pool.app: Creation complete
Apply complete! Resources: 2 added.

Paso 2: Escribir el kubeconfig y conectar

terraform output -raw kubeconfig > kubeconfig.yaml
chmod 600 kubeconfig.yaml
export KUBECONFIG=$(pwd)/kubeconfig.yaml
kubectl get nodes

Salida esperada:

NAME                  STATUS   ROLES    AGE   VERSION
taskboard-app-pool-1  Ready    <none>   2m    v1.34.x
taskboard-app-pool-2  Ready    <none>   2m    v1.34.x
taskboard-app-pool-3  Ready    <none>   2m    v1.34.x

Paso 3: Crear espacio de nombres y secreto de extracción de registro

kubectl create namespace taskboard
kubectl create secret docker-registry registry-cred \
  --namespace taskboard \
  --docker-server=<registry-name>.cr.de-fra.ionos.com \
  --docker-username=<token-name> \
  --docker-password=<registry-token>

Salida esperada:

namespace/taskboard created
secret/registry-cred created

Paso 4: Implementar el API, ConfigMap y Secret

kubectl apply -f taskboard-api.yaml
kubectl rollout status deployment/taskboard-api -n taskboard

Salida esperada:

deployment "taskboard-api" successfully rolled out

Paso 5: Verificar que los Pods estén extrayendo y ejecutándose

kubectl get pods -n taskboard

Salida esperada:

NAME                            READY   STATUS    RESTARTS   AGE
taskboard-api-7d9f8c-abcde      1/1     Running   0          40s
taskboard-api-7d9f8c-fghij      1/1     Running   0          40s
taskboard-api-7d9f8c-klmno      1/1     Running   0          40s

Paso 6: Exponer el controlador de ingreso y leer su IP

kubectl apply -f ingress.yaml
kubectl get svc ingress-nginx -n ingress

Salida esperada:

NAME            TYPE           EXTERNAL-IP      PORT(S)
ingress-nginx   LoadBalancer   <reserved-ip>    443:3xxxx/TCP

Paso 7: Confirmar que el punto de conexión responde

curl -sk https://<reserved-ip>/healthz

Salida esperada:

{"status":"ok"}

Lista de verificación:

  • [ ] El grupo Cluster y Node alcanza Active y los nodos están Ready
  • [ ] Los API Pods están Running, no ImagePullBackOff
  • [ ] El ingreso IP devuelve una respuesta saludable desde el API

Limpieza:

kubectl delete namespace taskboard
terraform destroy -auto-approve

Errores comunes

Errores de los desarrolladores que deben evitarse al implementar en MKS:

  1. Esperar que type: LoadBalancer le proporcione una dirección Load Balancer externa real

    • Problema: Usted expone cada Servicio como LoadBalancer, espera alta disponibilidad en los nodos y las direcciones IP de origen todas se muestran como una sola dirección Node.
    • Por qué sucede: En MKS, un Servicio LoadBalancer reserva una dirección IP estática y la asigna a un worker Node como una dirección IP secundaria; kube-proxy NAT a la cápsula y se pierde la dirección IP de origen.
    • Solución: Exponga solo el controlador de ingreso como LoadBalancer, configure externalTrafficPolicy: Local para conservar la dirección IP de origen y coloque el tráfico de producción frente a un ALB provisionado por separado:
    spec:
      type: LoadBalancer
      externalTrafficPolicy: Local
    
  2. ImagePullBackOff debido a un secreto de extracción que falta o tiene un alcance incorrecto

    • Problema: Pods nunca se inician; kubectl describe pod muestra Failed to pull image ... no basic auth credentials.
    • Por qué sucede: Private Container Registry requiere autenticación en cada extracción, y el secreto dockerconfigjson está limitado a un espacio de nombres. Un Secreto en default no hace nada para Pods en taskboard.
    • Solución: Cree el secreto del registro en el espacio de nombres de Workload y hágalo referencia bajo imagePullSecrets:
    kubectl create secret docker-registry registry-cred -n taskboard \
      --docker-server=<registry-name>.cr.de-fra.ionos.com \
      --docker-username=<token-name> --docker-password=<registry-token>
    
  3. Buscar eventos de control de plano en el Logging Service

    • Problema: Una cápsula no se programa y usted pasa una hora buscando errores de programador en registros centralizados que no están allí.
    • Por qué sucede: Los eventos de control de plano de Kubernetes no fluyen a través del Logging Service de IONOS.
    • Solución: Lea las señales de control de plano con kubectl, y solo envíe los registros de aplicación que usted controla:
    kubectl get events -n taskboard --sort-by=.lastTimestamp
    kubectl describe pod <pod> -n taskboard
    

Resumen

Ahora puede aprovisionar un Managed Kubernetes Cluster y Node Pools completamente como código, recuperar el kubeconfig desde el estado de Terraform y desplegar servicios contenerizados que extraen de Private Container Registry. También conoce las dos realidades de IONOS que separan una implementación de MKS funcional de una rota: el tipo de servicio LoadBalancer no es un verdadero Load Balancer externo, por lo que el tráfico de producción es gestionado por un ALB provisionado por separado, y los eventos del plano de control no se registran centralmente, por lo que la depuración se realiza a través de kubectl más su propio envío de registros.

Con TaskBoard's API, frontend y worker ejecutándose en MKS detrás de un ALB, tiene un objetivo desplegable. La siguiente unidad automatiza el camino desde un compromiso de Git hasta este Cluster en ejecución.

Puntos clave:

  • El plano de control de MKS es gratuito; solo paga por el cómputo del Node Pool y los volúmenes Block Storage
  • Recupere el kubeconfig desde el atributo kube_config del recurso ionoscloud_k8s_cluster, marcado como sensible
  • Un servicio type: LoadBalancer fija una IP estática a un worker Node y no es un verdadero Load Balancer externo; frente a la producción con un ALB provisionado por separado
  • Extraiga imágenes privadas con un secreto docker-registry con espacio de nombres referenciado como imagePullSecrets
  • Los eventos del plano de control de Kubernetes no llegan al Logging Service de IONOS; depure con kubectl y envíe los registros de la aplicación usted mismo

Terminología importante:

  • Node Pool: Un grupo de Worker Nodes de un tipo de servidor en un centro de datos, escalado y actualizado como una unidad (hasta 100 nodos, 20 recomendados)
  • kubeconfig: El archivo de credenciales y conexión para kubectl, expuesto por el recurso Cluster y tratado como un secreto
  • imagePullSecrets: Una referencia de especificación de pod a un secreto dockerconfigjson que autentica las extracciones de Private Container Registry
  • externalTrafficPolicy: Local: Una configuración de servicio que conserva la dirección IP del cliente manteniendo el tráfico en el Node receptor en lugar de reenviarlo
  • CSI provisioner (cloud.ionos.com): El controlador de almacenamiento de IONOS que respalda las reclamaciones de volumen persistente con Block Storage para que los datos sobrevivan al reemplazo de Node

Próximos pasos

Continúe aprendiendo: Unidad 3.3: CI/CD Pipelines para IONOS

Temas relacionados: