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_TOKENexportado) - Terraform y el proveedor
ionos-cloud/ionoscloud kubectlyionosctlinstalados- Un Private Container Registry con la imagen
taskboard-apisubida (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
Activey los nodos estánReady - [ ] Los API Pods están
Running, noImagePullBackOff - [ ] 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:
-
Esperar que
type: LoadBalancerle 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
LoadBalancerreserva 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, configureexternalTrafficPolicy: Localpara 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 - Problema: Usted expone cada Servicio como
-
ImagePullBackOffdebido a un secreto de extracción que falta o tiene un alcance incorrecto- Problema: Pods nunca se inician;
kubectl describe podmuestraFailed to pull image ... no basic auth credentials. - Por qué sucede: Private Container Registry requiere autenticación en cada extracción, y el secreto
dockerconfigjsonestá limitado a un espacio de nombres. Un Secreto endefaultno hace nada para Pods entaskboard. - 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> - Problema: Pods nunca se inician;
-
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_configdel recursoionoscloud_k8s_cluster, marcado como sensible - Un servicio
type: LoadBalancerfija 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-registrycon espacio de nombres referenciado comoimagePullSecrets - Los eventos del plano de control de Kubernetes no llegan al Logging Service de IONOS; depure con
kubectly 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
dockerconfigjsonque 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: