Ampliación de la infraestructura con Kubernetes y RKE2: un análisis profundo de la producción
Una guía para ingenieros de producción sobre la arquitectura del clúster RKE2, el escalado automático horizontal y vertical, la alta disponibilidad, la gobernanza de recursos y la observabilidad de Prometheus/Grafana.
Ejecutar un clúster Kubernetes en producción es una cosa. Ejecutar uno que pueda absorber picos de tráfico impredecibles, sobrevivir a fallas del plano de control, imponer el aislamiento de los inquilinos y brindarle a su equipo de operaciones una visibilidad clara de cada capa del sistema: ese es un desafío completamente diferente. RKE2, la distribución Kubernetes de próxima generación de Rancher, está diseñada específicamente para entornos donde esos requisitos no son negociables.
Este artículo analiza el ciclo de vida completo de una implementación de RKE2 de nivel de producción: arquitectura de clúster inicial, escalado automático a nivel de pod y nodo, planos de control de alta disponibilidad, gobernanza de recursos y observabilidad con Prometheus y Grafana.
¿Por qué RKE2?
RKE2 se distingue del Kubernetes ascendente y de su predecesor RKE1 en tres áreas clave. En primer lugar, se envía con una configuración reforzada con el estándar CIS Kubernetes lista para usar: los controladores de admisión, el registro de auditoría, la seguridad del módulo y las configuraciones TLS están preconfigurados para pasar un escaneo CIS Nivel 1 sin intervención manual. En segundo lugar, cumple con FIPS 140-2, lo que lo hace adecuado para implementaciones gubernamentales y de industrias reguladas. En tercer lugar, incorpora contenedores directamente y se envía con su propio CNI (Canal o Cilium según su elección de configuración), lo que reduce la superficie de dependencias externas que necesita administrar.
RKE2 también es compatible con espacios de aire. El paquete de instalación incluye todas las imágenes de contenedor necesarias, lo cual es de gran importancia en implementaciones locales y perimetrales donde el acceso a Internet desde los nodos del clúster está restringido o es imposible.
Arquitectura del clústerUn clúster RKE2 de producción se divide en nodos de servidor (que ejecutan el plano de control y etcd) y nodos de agente (que ejecutan cargas de trabajo). La topología recomendada para alta disponibilidad es tres o cinco nodos de servidor y una cantidad variable de nodos de agentes organizados en grupos de nodos por clase de carga de trabajo.
# /etc/rancher/rke2/config.yaml (server node)
token: <shared-cluster-token>
tls-san:
- 10.0.0.10 # VIP or load balancer address
- k8s.internal.example.com
cni: cilium
cluster-cidr: 10.42.0.0/16
service-cidr: 10.43.0.0/16
etcd-expose-metrics: true
kube-apiserver-arg:
- "audit-log-path=/var/log/kubernetes/audit.log"
- "audit-log-maxage=30"
- "audit-log-maxsize=100"# /etc/rancher/rke2/config.yaml (agent node)
server: https://10.0.0.10:9345
token: <shared-cluster-token>
node-label:
- "workload-class=general"
- "topology.kubernetes.io/zone=eu-west-1a"Instale el servidor en su primer nodo del plano de control, luego una los nodos del servidor restantes y todos los nodos del agente usando el mismo token y la dirección VIP. RKE2 elige automáticamente a los líderes de etcd y gestiona el quórum.
# Install and start RKE2 server
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE=server sh -
systemctl enable --now rke2-server.service
# Retrieve the node token for joining additional nodes
cat /var/lib/rancher/rke2/server/node-token
# Install and start RKE2 agent (on worker nodes)
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE=agent sh -
systemctl enable --now rke2-agent.serviceGrupos de nodos y ubicación de cargas de trabajo
No todas las cargas de trabajo tienen el mismo perfil de recursos. Los servicios web sin estado tienen requisitos diferentes a los de los trabajos de inferencia GPU, las cargas de trabajo de análisis con uso intensivo de memoria o las bases de datos sensibles a la latencia. La organización de los nodos del agente en grupos con etiquetas y etiquetas distintas permite a Kubernetes programar cada clase de carga de trabajo en hardware del tamaño adecuado.
# Label a node pool for memory-intensive workloads
kubectl label nodes worker-mem-{1..4} workload-class=memory-optimised
kubectl taint nodes worker-mem-{1..4} workload-class=memory-optimised:NoSchedule
# Label a separate pool for general compute
kubectl label nodes worker-gen-{1..8} workload-class=general# Deployment targeting the memory-optimised pool
apiVersion: apps/v1
kind: Deployment
metadata:
name: analytics-engine
spec:
template:
spec:
nodeSelector:
workload-class: memory-optimised
tolerations:
- key: workload-class
operator: Equal
value: memory-optimised
effect: NoSchedule
containers:
- name: analytics
image: registry.internal/analytics:v2.3.1
resources:
requests:
memory: "8Gi"
cpu: "2"
limits:
memory: "16Gi"
cpu: "4"Escalador automático de módulo horizontalEl escalador automático de pod horizontal (HPA) ajusta el recuento de réplicas de una implementación o un StatefulSet en función de las métricas observadas. La utilización de CPU es el desencadenante clásico, pero las configuraciones HPA modernas también pueden escalar en función de métricas personalizadas expuestas por su aplicación o de métricas externas de fuentes como la profundidad de la cola de mensajes.
Primero, asegúrese de que Metrics Server se esté ejecutando; RKE2 no lo incluye de forma predeterminada.
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yamlapiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-server-hpa
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-server
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 65
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 70
behavior:
scaleDown:
stabilizationWindowSeconds: 300 # wait 5 minutes before scaling down
policies:
- type: Percent
value: 25
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 30El bloquebehaviores fundamental para la estabilidad. Sin una ventana de estabilización reducida, una breve caída del tráfico eliminará los pods prematuramente, dejándolo con un suministro insuficiente cuando regrese la carga. La política asimétrica (aumento agresivo, reducción conservadora) es la opción predeterminada adecuada para la mayoría de las cargas de trabajo de producción.
El escalador automático de pods vertical (VPA) ajusta el tamaño correcto del CPU y las solicitudes de memoria en pods individuales según el uso observado. Resuelve un problema común: los desarrolladores establecen solicitudes de recursos iniciales basándose en conjeturas, y esos valores nunca se actualizan, lo que genera un desperdicio de aprovisionamiento excesivo o pods OOMKilled bajo carga.
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: worker-vpa
namespace: production
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: background-worker
updatePolicy:
updateMode: "Auto" # or "Off" to only view recommendations
resourcePolicy:
containerPolicies:
- containerName: worker
minAllowed:
cpu: 100m
memory: 256Mi
maxAllowed:
cpu: 4
memory: 8Gi
controlledResources: ["cpu", "memory"]Tenga en cuenta que VPA en modoAutodesalojará y reiniciará los pods para aplicar nuevos valores de recursos. Para servicios donde las solicitudes en curso no se pueden interrumpir, ejecute VPA en modoOffpara generar recomendaciones que puede aplicar manualmente o mediante un flujo de trabajo GitOps durante las ventanas de mantenimiento.
Importante:HPA y VPA no deben administrar el mismo recurso (CPU o memoria) en la misma implementación simultáneamente. Utilice HPA para el escalado horizontal controlado por CPU y VPA en modoOffpara ajustar el tamaño de la memoria, o utiliceKEDApara el escalado controlado por eventos donde se necesita un control detallado.
funcionan dentro de la capacidad del nodo existente. Cuando esa capacidad se agota (los pods están bloqueados enPendingporque ningún nodo tiene recursos suficientes), necesita el escalador automático de clúster para aprovisionar nuevos nodos. Por el contrario, cuando los nodos están significativamente infrautilizados, Cluster Autoscaler puede drenarlos y desmantelarlos para reducir el costo de infraestructura.
En implementaciones bare-metal o locales, Cluster Autoscaler se integra con su capa de aprovisionamiento de infraestructura. Para implementaciones en la nube, proveedores como AWS, GCP y Azure ofrecen integraciones de grupos de nodos nativos. El siguiente ejemplo muestra la configuración principal para un grupo de Auto Scaling AWS.
apiVersion: apps/v1
kind: Deployment
metadata:
name: cluster-autoscaler
namespace: kube-system
spec:
template:
spec:
containers:
- name: cluster-autoscaler
image: registry.k8s.io/autoscaling/cluster-autoscaler:v1.29.0
command:
- ./cluster-autoscaler
- --cloud-provider=aws
- --nodes=2:10:k8s-general-worker-asg
- --nodes=1:4:k8s-memory-worker-asg
- --scale-down-delay-after-add=10m
- --scale-down-unneeded-time=10m
- --scale-down-utilization-threshold=0.5
- --skip-nodes-with-local-storage=false
- --expander=least-waste
env:
- name: AWS_REGION
value: eu-west-1La opción--expander=least-wastele dice al escalador automático que prefiera el grupo de nodos que tendría la menor cantidad de recursos no utilizados después de acomodar el pod pendiente, lo que minimiza el costo. Los expansores alternativos incluyenrandom,most-podsypriority.
Plano de control de alta disponibilidad
Un plano de control de tres nodos con etcd integrado es la topología HA mínima viable. etcd requiere quórum: la mayoría de los miembros deben estar en buen estado para que el clúster acepte escrituras. Con tres miembros puedes tolerar un fracaso; con cinco miembros puedes tolerar dos.
Los nodos del plano de control deben ubicarse detrás de un equilibrador de carga. Para implementaciones en la nube, un balanceador de carga TCP dirigido al puerto 6443 (kube-apiserver) y 9345 (registro RKE2) funciona bien. Las implementaciones locales suelen utilizar keepalived con una dirección IP virtual.
# keepalived.conf on control-plane nodes
vrrp_instance VI_1 {
state MASTER # BACKUP on the other two nodes
interface eth0
virtual_router_id 51
priority 100 # 90 and 80 on the other two nodes
advert_int 1
authentication {
auth_type PASS
auth_pass securepassword
}
virtual_ipaddress {
10.0.0.10/24 # VIP used in tls-san and agent server address
}
}Valide que etcd esté en buen estado después de cualquier operación del plano de control. RKE2 incluyeetcdctly/var/lib/rancher/rke2/bin/etcdctl.
ETCDCTL_API=3 /var/lib/rancher/rke2/bin/etcdctl \
--endpoints=https://127.0.0.1:2379 \
--cacert=/var/lib/rancher/rke2/server/tls/etcd/server-ca.crt \
--cert=/var/lib/rancher/rke2/server/tls/etcd/client.crt \
--key=/var/lib/rancher/rke2/server/tls/etcd/client.key \
endpoint health --clusterCuotas de recursos y rangos de límites
En clústeres de múltiples inquilinos, donde diferentes equipos o aplicaciones comparten la misma infraestructura física, ResourceQuotas y LimitRanges son barreras de seguridad esenciales. ResourceQuotas establece límites estrictos en el consumo total de recursos dentro de un espacio de nombres. LimitRanges establece valores predeterminados y máximos para contenedores individuales, evitando que una implementación mal configurada solicite recursos ilimitados.
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-alpha-quota
namespace: team-alpha
spec:
hard:
requests.cpu: "20"
requests.memory: 40Gi
limits.cpu: "40"
limits.memory: 80Gi
count/deployments.apps: "20"
count/services: "15"
persistentvolumeclaims: "10"
requests.storage: 500GiapiVersion: v1
kind: LimitRange
metadata:
name: team-alpha-limits
namespace: team-alpha
spec:
limits:
- type: Container
default:
cpu: 500m
memory: 512Mi
defaultRequest:
cpu: 100m
memory: 128Mi
max:
cpu: "8"
memory: 16Gi
- type: PersistentVolumeClaim
max:
storage: 100GiLa aplicación de LimitRanges garantiza que los desarrolladores que olviden especificar las solicitudes de recursos sigan obteniendo valores predeterminados sensatos en lugar de solicitar cero CPU, lo que haría que el programador colocara el pod en cualquier lugar y potencialmente privaría a otras cargas de trabajo en el mismo nodo.
Monitoreocon Prometheus y Grafana
La observabilidad en un clúster Kubernetes tiene tres pilares: métricas, registros y seguimientos. Prometheus maneja la recopilación de métricas; Grafana se encarga de la visualización. El gráficokube-prometheus-stackHelm implementa toda la pila (operador Prometheus, administrador de alertas, Grafana, exportadores de nodos y un conjunto completo de paneles prediseñados) en un solo comando.
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--create-namespace \
--set prometheus.prometheusSpec.retention=30d \
--set prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.storageClassName=longhorn \
--set prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storage=100Gi \
--set grafana.adminPassword=<secure-password> \
--set alertmanager.alertmanagerSpec.storage.volumeClaimTemplate.spec.resources.requests.storage=10GiRKE2 expone métricas de etcd cuandoetcd-expose-metrics: trueestá configurado en la configuración del servidor. Agregue un ServiceMonitor para que Prometheus los elimine.
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: rke2-etcd
namespace: monitoring
labels:
release: kube-prometheus-stack
spec:
namespaceSelector:
matchNames: [kube-system]
selector:
matchLabels:
app.kubernetes.io/name: rke2-etcd
endpoints:
- port: metrics
scheme: https
tlsConfig:
caFile: /etc/prometheus/secrets/etcd-client-cert/ca.crt
certFile: /etc/prometheus/secrets/etcd-client-cert/client.crt
keyFile: /etc/prometheus/secrets/etcd-client-cert/client.keyReglas de alerta esenciales
Los paneles prediseñados son un punto de partida, pero las reglas de alerta personalizadas adaptadas a su entorno son las que permiten a los ingenieros de guardia actuar antes de que los usuarios noten un problema.
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: workload-alerts
namespace: monitoring
labels:
release: kube-prometheus-stack
spec:
groups:
- name: pod-health
rules:
- alert: PodCrashLooping
expr: rate(kube_pod_container_status_restarts_total[10m]) > 0.5
for: 5m
labels:
severity: critical
annotations:
summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} is crash-looping"
- alert: NodeMemoryPressure
expr: |
(node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) < 0.1
for: 2m
labels:
severity: warning
annotations:
summary: "Node {{ $labels.node }} memory below 10%"
- alert: HPAMaxedOut
expr: |
kube_horizontalpodautoscaler_status_current_replicas
== kube_horizontalpodautoscaler_spec_max_replicas
for: 15m
labels:
severity: warning
annotations:
summary: "HPA {{ $labels.namespace }}/{{ $labels.horizontalpodautoscaler }} at maximum replicas"La alertaHPAMaxedOutes particularmente valiosa en la práctica. Cuando un HPA se fija en su máximo durante un período prolongado, significa que el tráfico ha superado su límite actual. Necesita aumentar el máximo o agregar capacidad al grupo de nodos, y desea saberlo antes del próximo pico, no durante el mismo.
Mejores prácticas de producción
Presupuestos de interrupción del pod
Un PodDisruptionBudget (PDB) limita cuántos pods en una implementación pueden no estar disponibles simultáneamente durante interrupciones voluntarias, como drenajes de nodos. Sin PDB, vaciar un nodo para mantenimiento puede desconectar toda una implementación.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api-server-pdb
namespace: production
spec:
minAvailable: 2 # or use maxUnavailable: 1
selector:
matchLabels:
app: api-serverRestricciones de extensión de topologíaDe forma predeterminada, el planificador distribuye réplicas entre nodos utilizando un algoritmo de mejor esfuerzo. Las restricciones de distribución de topología le brindan garantías estrictas de que las réplicas se distribuyen entre zonas de disponibilidad o bastidores.
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: api-serverEstrategia de actualizaciónRKE2 admite actualizaciones continuas a través del controlador de actualización del sistema. Usted define un plan que apunta a nodos de servidor o agente y especifica la versión de destino; el controlador drena, actualiza y descordona los nodos secuencialmente.
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
name: rke2-server-upgrade
namespace: system-upgrade
spec:
concurrency: 1
cordon: true
nodeSelector:
matchExpressions:
- { key: node-role.kubernetes.io/control-plane, operator: In, values: ["true"] }
serviceAccountName: system-upgrade
upgrade:
image: rancher/rke2-upgrade
version: v1.29.4+rke2r1etcd Copia de seguridad y restauración
RKE2 puede tomar instantáneas etcd programadas automáticamente. Asegúrese de que estén escritos en un almacenamiento duradero fuera del clúster (un depósito S3 o un montaje NFS remoto) en lugar de en un disco local en los nodos del plano de control.
# /etc/rancher/rke2/config.yaml additions for automated snapshots
etcd-snapshot-schedule-cron: "0 */6 * * *" # every 6 hours
etcd-snapshot-retention: 10
etcd-snapshot-dir: /mnt/nfs/etcd-snapshots
# Manual snapshot
rke2 etcd-snapshot save --name pre-upgrade-$(date +%Y%m%d)
# Restore from snapshot (run on a single server node with cluster stopped)
rke2 server --cluster-reset --cluster-reset-restore-path=/path/to/snapshot.dbConclusión
Ampliar la infraestructura con RKE2 no es un único cambio de configuración: es un sistema de capacidades entrelazadas que deben diseñarse y operarse en conjunto. El ajuste de escala automático del pod horizontal maneja ráfagas de tráfico de corta duración a nivel de carga de trabajo. El ajuste de escala automático del pod vertical mantiene las solicitudes de recursos honestas a lo largo del tiempo. El escalador automático de clúster garantiza que la capacidad del nodo subyacente realice un seguimiento de la demanda agregada de sus escaladores automáticos de pod. Los grupos de nodos y las restricciones de topología garantizan que las cargas de trabajo lleguen al hardware adecuado. Las cuotas de recursos y los rangos de límites protegen a los inquilinos entre sí. PodDisruptionLos presupuestos y las restricciones de distribución de topología refuerzan la disponibilidad. Y Prometheus con Grafana le brinda a su equipo la visibilidad para detectar la degradación antes de que se convierta en una interrupción.
RKE2 gana su lugar en la producción precisamente porque envía una parte sustancial de esta pila preendurecida y preintegrada. Su responsabilidad es comprender los controles, ajustarlos a las características de su carga de trabajo y crear la disciplina operativa (runbooks, enrutamiento de alertas, cadencia de actualización, validación de respaldo) que convierte un clúster bien configurado en una plataforma genuinamente confiable.