Versión imprimible multipagina. Haga click aquí para imprimir.
Arquitectura de Kubernetes
- 1: Nodos
- 2: Comunicación entre Nodos y el Plano de Control
- 3: Conceptos subyacentes del Cloud Controller Manager
- 4: Leases
- 5: Container Runtime Interface (CRI)
1 - Nodos
Un nodo es una máquina de trabajo en Kubernetes, previamente conocida como minion
. Un nodo puede ser una máquina virtual o física, dependiendo del tipo de clúster. Cada nodo está gestionado por el componente máster y contiene los servicios necesarios para ejecutar pods. Los servicios en un nodo incluyen el container runtime, kubelet y el kube-proxy. Accede a la sección The Kubernetes Node en el documento de diseño de arquitectura para más detalle.
Estado del Nodo
El estado de un nodo comprende la siguiente información:
Direcciones
El uso de estos campos varía dependiendo del proveedor de servicios en la nube y/o de la configuración en máquinas locales.
HostName
: El nombre de la máquina huésped como aparece en el kernel del nodo. Puede ser reconfigurado a través del kubelet usando el parámetro--hostname-override
.ExternalIP
: La dirección IP del nodo que es accesible externamente (que está disponible desde fuera del clúster).InternalIP
: La dirección IP del nodo que es accesible únicamente desde dentro del clúster.
Estados
El campo conditions
describe el estado de todos los nodos en modo Running
.
Estado | Descripción |
---|---|
OutOfDisk |
True si no hay espacio suficiente en el nodo para añadir nuevos pods; sino False |
Ready |
True si el nodo está en buen estado y preparado para aceptar nuevos pods, Falso si no puede aceptar nuevos pods, y Unknown si el controlador aún no tiene constancia del nodo después del último node-monitor-grace-period (por defecto cada 40 segundos) |
MemoryPressure |
True si hay presión en la memoria del nodo -- es decir, si el consumo de memoria en el nodo es elevado; sino False |
PIDPressure |
True si el número de PIDs consumidos en el nodo es alto -- es decir, si hay demasiados procesos en el nodo; sino False |
DiskPressure |
True si hay presión en el tamaño del disco -- esto es, si la capacidad del disco es baja; sino False |
NetworkUnavailable |
True si la configuración de red del nodo no es correcta; sino False |
El estado del nodo se representa como un objeto JSON. Por ejemplo, la siguiente respuesta describe un nodo en buen estado:
"conditions": [
{
"type": "Ready",
"status": "True"
}
]
Si el status
de la condición Ready
se mantiene como Unknown
o False
por más tiempo de lo que dura un pod-eviction-timeout
, se pasa un argumento al kube-controller-manager y todos los pods en el nodo se marcan para borrado por el controlador de nodos. El tiempo de desalojo por defecto es de cinco minutos. En algunos casos, cuando el nodo se encuentra inaccesible, el API Server no puede comunicar con el kubelet del nodo. La decisión de borrar pods no se le puede hacer llegar al kubelet hasta que la comunicación con el API Server se ha restablecido. Mientras tanto, los pods marcados para borrado pueden continuar ejecutándose en el nodo aislado.
En versiones de Kubernetes anteriores a 1.5, el controlador de nodos forzaba el borrado de dichos pods inaccesibles desde el API Server. Sin embargo, desde la versión 1.5, el nodo controlador no fuerza el borrado de pods hasta que se confirma que dichos pods han dejado de ejecutarse en el clúster. Pods que podrían estar ejecutándose en un nodo inalcanzable se muestran como Terminating
o Unknown
. En aquellos casos en los que Kubernetes no puede deducir si un nodo ha abandonado el clúster de forma permanente, puede que sea el administrador el que tenga que borrar el nodo de forma manual. Borrar un objeto Node
en un clúster de Kubernetes provoca que los objetos Pod que se ejecutaban en el nodo sean eliminados en el API Server y libera sus nombres.
En la versión 1.12, la funcionalidad TaintNodesByCondition
se eleva a beta, de forma que el controlador del ciclo de vida de nodos crea taints de forma automática, que representan estados de nodos.
De forma similar, el planificador de tareas ignora estados cuando evalúa un nodo; en su lugar mira los taints del nodo y las tolerancias de los pods.
En la actualidad, los usuarios pueden elegir entre la versión de planificación antigua y el nuevo, más flexible, modelo de planificación. Un pod que no tiene definida ninguna tolerancia es planificado utilizando el modelo antiguo, pero si un nodo tiene definidas ciertas tolerancias, sólo puede ser asignado a un nodo que lo permita.
Precaución:
Habilitar esta funcionalidad crea una pequeña demora entre que una condición es evaluada y un taint creado. Esta demora suele ser inferior a un segundo, pero puede incrementar el número de pods que se planifican con éxito pero que luego son rechazados por el kubelet.Capacidad
Describe los recursos disponibles en el nodo: CPU, memoria, y el número máximo de pods que pueden ser planificados dentro del nodo.
Información
Información general sobre el nodo: versión del kernel, versión de Kubernetes (versiones del kubelet y del kube-proxy), versión de Docker (si se utiliza), nombre del sistema operativo. Toda esta información es recogida por el kubelet en el nodo.
Gestión
A diferencia de pods y services, los nodos no son creados por Kubernetes de forma inherente; o son creados de manera externa por los proveedores de servicios en la nube como Google Compute Engine, o existen en la colección de máquinas virtuales o físicas. De manera que cuando Kubernetes crea un nodo, crea un objeto que representa el nodo. Después de ser creado, Kubernetes comprueba si el nodo es válido o no. Por ejemplo, si intentas crear un nodo con el siguiente detalle:
{
"kind": "Node",
"apiVersion": "v1",
"metadata": {
"name": "10.240.79.157",
"labels": {
"name": "my-first-k8s-node"
}
}
}
Kubernetes crea un objeto Node
internamente (la representación), y valida el nodo comprobando su salud en el campo metadata.name
. Si el nodo es válido -- es decir, si todos los servicios necesarios están ejecutándose -- el nodo es elegible para correr un pod. Sino, es ignorado para cualquier actividad del clúster hasta que se convierte en un nodo válido.
Nota:
Kubernetes conserva el objeto de un nodo inválido y continúa probando por si el nodo, en algún momento, entrase en servicio. Para romper este ciclo deberás borrar el objetoNode
explícitamente.Actualmente, hay tres componentes que interactúan con la interfaz de nodos de Kubernetes: controlador de nodos, kubelet y kubectl.
Controlador de Nodos
El controlador de nodos es un componente maestro en Kubernetes que gestiona diferentes aspectos de los nodos.
El controlador juega múltiples papeles en la vida de un nodo. El primero es asignar un bloque CIDR (Class Inter-Domain Routing) al nodo cuando este se registra (si la asignación CIDR está activada) que contendrá las IPs disponibles para asignar a los objetos que se ejecutarán en ese nodo.
El segundo es mantener actualizada la lista interna del controlador con la lista de máquinas disponibles a través del proveedor de servicios en la nube. Cuando Kubernetes se ejecuta en la nube, si un nodo deja de responder, el controlador del nodo preguntará al proveedor si la máquina virtual de dicho nodo continúa estando disponible. Si no lo está, el controlador borrará dicho nodo de su lista interna.
El tercero es el de monitorizar la salud de los nodos. El controlador de nodos es el responsable de actualizar la condición NodeReady
del campo NodeStatus
a ConditionUnknown
cuando un nodo deja de estar accesible (por ejemplo, si deja de recibir señales de vida del nodo indicando que está disponible, conocidas como latidos o hearbeats
en inglés) y, también es responsable de posteriormente desalojar todos los pods del nodo si este continúa estando inalcanzable. Por defecto, cuando un nodo deja de responder, el controlador sigue reintentando contactar con el nodo durante 40 segundos antes de marcar el nodo con ConditionUnknown
y, si el nodo no se recupera de ese estado pasados 5 minutos, empezará a drenar los pods del nodo para desplegarlos en otro nodo que esté disponible. El controlador comprueba el estado de cada nodo cada --node-monitor-period
segundos.
En versiones de Kubernetes previas a 1.13, NodeStatus
es el heartbeat
del nodo. Empezando con 1.13 la funcionalidad de node lease
se introduce como alfa (NodeLease
,
KEP-0009). Cuando la funcionalidad está habilitada, cada nodo tiene un objeto Lease
asociado en el namespace kube-node-lease
que se renueva periódicamente y ambos, el NodeStatus
y el Lease
son considerados como hearbeats
del nodo. Node leases
se renuevan con frecuencia, mientras que NodeStatus
se transmite desde el nodo al máster únicamente si hay cambios o si ha pasado cierto tiempo (por defecto, 1 minuto, que es más que la cuenta atrás por defecto de 40 segundos que marca un nodo como inalcanzable). Al ser los node lease
más ligeros que NodeStatus
, los hearbeats
resultan más económicos desde las perspectivas de escalabilidad y de rendimiento.
En Kubernetes 1.4, se actualizó la lógica del controlador de nodos para gestionar mejor los casos en los que un gran número de nodos tiene problemas alcanzando el nodo máster (Por ejemplo, cuando el nodo máster es el que tiene un problema de red). Desde 1.4, el controlador de nodos observa el estado de todos los nodos en el clúster cuando toma decisiones sobre desalojo de pods.
En la mayoría de los casos, el controlador de nodos limita el ritmo de desalojo --node-eviction-rate
(0.1 por defecto) por segundo, lo que significa que no desalojará pods de más de un nodo cada diez segundos.
El comportamiento de desalojo de nodos cambia cuando un nodo en una zona de disponibilidad tiene problemas. El controlador de nodos comprobará qué porcentaje de nodos en la zona no se encuentran en buen estado (es decir, que su condición NodeReady
tiene un valor ConditionUnknown
o ConditionFalse
) al mismo tiempo. Si la fracción de nodos con problemas es de al menos --unhealthy-zone-threshold
(0.55 por defecto) entonces se reduce el ratio de desalojos: si el clúster es pequeño (por ejemplo, tiene menos o los mismos nodos que --large-cluster-size-threshold
- 50 por defecto) entonces los desalojos se paran. Sino, el ratio se reduce a --secondary-node-eviction-rate
(0.01 por defecto) por segundo. La razón por la que estas políticas se implementan por zonas de disponibilidad es debido a que una zona puede quedarse aislada del nodo máster mientras que las demás continúan conectadas. Si un clúster no comprende más de una zona, todo el clúster se considera una única zona.
La razón principal por la que se distribuyen nodos entre varias zonas de disponibilidad es para que el volumen de trabajo se transfiera a aquellas zonas que se encuentren en buen estado cuando una de las zonas se caiga.
Por consiguiente, si todos los nodos de una zona se encuentran en mal estado, el nodo controlador desaloja al ritmo normal --node-eviction-rate
. En el caso extremo de que todas las zonas se encuentran en mal estado (es decir, no responda ningún nodo del clúster), el controlador de nodos asume que hay algún tipo de problema con la conectividad del nodo máster y paraliza todos los desalojos hasta que se restablezca la conectividad.
Desde la versión 1.6 de Kubernetes el controlador de nodos también es el responsable de desalojar pods que están ejecutándose en nodos con NoExecute
taints, cuando los pods no permiten dichos taints. De forma adicional, como una funcionalidad alfa que permanece deshabilitada por defecto, el NodeController
es responsable de añadir taints que se corresponden con problemas en los nodos del tipo nodo inalcanzable o nodo no preparado. En esta sección de la documentación hay más detalles acerca de los taints NoExecute
y de la funcionalidad alfa.
Desde la versión 1.8, el controlador de nodos puede ser responsable de la creación de taints que representan condiciones de nodos. Esta es una funcionalidad alfa en 1.8.
Auto-Registro de Nodos
Cuando el atributo del kubelet --register-node
está habilitado (el valor por defecto), el kubelet intentará auto-registrarse con el API Server. Este es el patrón de diseño preferido, y utilizado por la mayoría de distribuciones.
Para auto-registro, el kubelet se inicia con las siguientes opciones:
--kubeconfig
- La ruta a las credenciales para autentificarse con el API Server.--cloud-provider
- Cómo comunicarse con un proveedor de servicios para leer meta-datos sobre si mismo.--register-node
- Registro automático con el API Server.--register-with-taints
- Registro del nodo con la lista de taints proporcionada (separada por comas<key>=<value>:<effect>
). Esta opción se ignora si el atributo--register-node
no está habilitado.--node-ip
- La dirección IP del nodo.--node-labels
- Etiquetas para añadir al nodo durante el registro en el clúster (ver las restricciones que impone el NodeRestriction admission plugin en 1.13+).--node-status-update-frequency
- Especifica la frecuencia con la que el nodo envía información de estado al máster.
Cuando el Node authorization mode y el NodeRestriction admission plugin están habilitados, los kubelets sólo tienen permisos para crear/modificar su propio objeto Node
.
Administración Manual de Nodos
Los administradores del clúster pueden crear y modificar objetos Node
.
Si un administrador desea crear objetos Node
de forma manual, debe levantar kubelet con el atributo --register-node=false
.
Los administradores del clúster pueden modificar recursos Node
(independientemente del valor de --register-node
). Dichas modificaciones incluyen crear etiquetas en el nodo y/o marcarlo como no-planificable (de forma que pods no pueden ser planificados para instalación en el nodo).
Etiquetas y selectores de nodos pueden utilizarse de forma conjunta para controlar las tareas de planificación, por ejemplo, para determinar un subconjunto de nodos elegibles para ejecutar un pod.
Marcar un nodo como no-planificable impide que nuevos pods sean planificados en dicho nodo, pero no afecta a ninguno de los pods que existían previamente en el nodo. Esto resulta de utilidad como paso preparatorio antes de reiniciar un nodo, etc. Por ejemplo, para marcar un nodo como no-planificable, se ejecuta el siguiente comando:
kubectl cordon $NODENAME
Nota:
Los pods creados por un controlador DaemonSet ignoran el planificador de Kubernetes y no respetan el atributo no-planificable de un nodo. Se asume que los daemons pertenecen a la máquina huésped y que se ejecutan incluso cuando esta está siendo drenada de aplicaciones en preparación de un reinicio.Capacidad del Nodo
La capacidad del nodo (número de CPUs y cantidad de memoria) es parte del objeto Node
.
Normalmente, nodos se registran a sí mismos y declaran sus capacidades cuando el objeto Node
es creado. Si se está haciendo administración manual, las capacidades deben configurarse en el momento de añadir el nodo.
El planificador de Kubernetes asegura la existencia de recursos suficientes para todos los pods que se ejecutan en un nodo. Comprueba que la suma recursos solicitados por los pods no exceda la capacidad del nodo. Incluye todos los pods iniciados por el kubelet, pero no tiene control sobre contenedores iniciados directamente por el runtime de contenedores ni sobre otros procesos que corren fuera de contenedores.
Para reservar explícitamente recursos en la máquina huésped para procesos no relacionados con pods, sigue este tutorial reserva de recursos para daemons de sistema.
Objeto API
Un nodo es un recurso principal dentro de la REST API de Kubernetes. Más detalles sobre el objeto en la API se puede encontrar en: Object Node API.
2 - Comunicación entre Nodos y el Plano de Control
Este documento cataloga las diferentes vías de comunicación entre el kube-apiserver y el clúster de Kubernetes. La intención es permitir a los usuarios personalizar sus instalaciones para proteger sus configuraciones de red de forma que el clúster pueda ejecutarse en una red insegura (o en un proveedor de servicios en la nube con direcciones IP públicas)
Nodo al Plano de Control
La API de Kubernetes usa el patrón de "hub-and-spoke". Todo uso de la API desde los nodos (o los pods que ejecutan) termina en el servidor API. Ninguno de los otros componentes del plano de control está diseñado para exponer servicios remotos. El servidor API está configurado para escuchar conexiones remotas en un puerto seguro HTTPS (normalmente 443) con una o más formas de autenticación de cliente habilitada. Una o más formas de autorización deben ser habilitadas, especialmente si las peticiones anónimas o los tokens de cuenta de servicio están permitidos.
Los nodos deben ser aprovisionados con el certificado raíz público del clúster, de modo que puedan conectarse de forma segura al servidor API en conjunto con credenciales de cliente válidas. Un buen enfoque es que las credenciales de cliente proporcionadas al kubelet estén en forma de certificado de cliente. Véase el TLS bootstrapping de kubelet para ver cómo aprovisionar certificados de cliente kubelet de forma automática.
Los Pods que deseen conectar con el apiserver pueden hacerlo de forma segura a través de una cuenta de servicio, de esta forma Kubernetes inserta de forma automática el certificado raíz público y un bearer token válido en el pod cuando es instanciado. El servicio kubernetes
(en todos los namespaces) se configura con una dirección IP virtual que es redireccionada (via kube-proxy
) al punto de acceso HTTPS en el apiserver.
Los componentes del plano de control también se comunican con el apiserver del clúster a través de un puerto seguro.
Como resultado, el modo de operación para las conexiones desde los nodos y pods que se ejecutan en los nodos al plano de control es seguro por defecto y puede ejecutarse en redes públicas y/o inseguras.
Plano de control al nodo
Hay dos vías de comunicación primaria desde el plano de control (apiserver) y los nodos. La primera es desde el apiserver al proceso kubelet que se ejecuta en cada nodo del clúster. La segunda es desde el apiserver a cualquier nodo, pod o servicio a través de la funcionalidad proxy del apiserver.
Apiserver al kubelet
Las conexiones del apiserver al kubelet se utilizan para:
- Recoger entradas de registro de pods.
- Conectar (a través de
kubectl
) con pods en ejecución. - Facilitar la funcionalidad
port-forwarding
del kubelet.
Estas conexiones terminan en el endpoint HTTPS del kubelet. Por defecto, el apiserver no verifica el certificado del kubelet, por lo que la conexión es vulnerable a ataques del tipo "ataque de intermediario" ("man-in-the-middle"), e insegura para conectar a través de redes públicas y/o no fiables.
Para verificar esta conexión, se utiliza el atributo --kubelet-certificate-authority
que provee el apiserver con un certificado raíz con el que verificar el certificado del kubelet.
Si esto no es posible, se utiliza un túnel SSH entre el apiserver y el kubelet para conectar a través de redes públicas o de no confianza.
Finalmente, la autenticación y/o autorización al kubelet debe ser habilitada para proteger la API de kubelet.
Apiserver para nodos, pods y servicios
Las conexiones desde el apiserver a un nodo, pod o servicio se realizan por defecto con conexiones HTTP simples y, por consiguiente, no son autenticadas o encriptadas. Pueden ser ejecutadas en una conexión segura HTTPS con el prefijo https:
al nodo, pod o nombre de servicio en la URL de la API, pero no validarán el certificado proporcionado por el punto final HTTPS ni proporcionarán las credenciales del cliente. Por tanto, aunque la conexión estará cifrada, no proporcionará ninguna garantía de integridad. Estas conexiones no son actualmente seguras para ejecutarse en redes públicas o no fiables.
Túneles SSH
Kubernetes ofrece soporte para túneles SSH que protegen la comunicación entre el plano de control y los nodos. En este modo de configuración, el apiserver inicia un túnel SSH a cada nodo en el clúster (conectando al servidor SSH en el puerto 22) y transfiere todo el tráfico destinado a un kubelet, nodo, pod o servicio a través del túnel. El túnel garantiza que dicho tráfico no es expuesto fuera de la red en la que se ejecutan los nodos.
Nota:
Los túneles SSH están actualmente obsoletos, por lo que no deberías optar por utilizarlos a menos que sepas lo que estás haciendo. El Konnectivity service es un sustituto de este canal de comunicación.Servicio Konnectivity
Kubernetes v1.18 [beta]
En sustitución de los túneles SSH, el servicio Konnectivity proporciona un proxy de nivel TCP para la comunicación entre el plano de control y el clúster. El servicio Konnectivity consta de dos partes: el servidor Konnectivity en la red del plano de control y los agentes Konnectivity en la red de nodos.
Los agentes Konnectivity inician conexiones con el servidor Konnectivity y mantienen las conexiones de red. Tras habilitar el servicio Konnectivity, todo el tráfico del plano de control a los nodos pasa por estas conexiones.
Sigue la Tarea del servicio Konnectivity para configurar el servicio Konnectivity en tu clúster.
Siguientes pasos
- Componentes del plano de control de Kubernetes
- Más información sobre el modelo Hubs y Spoke
- Cómo proteger un clúster
- Más información sobre la API de Kubernetes
- Configurar el Servicio Konnectivity
- Utilizar el Port Forwarding para acceder a aplicaciones en un clúster
- Aprenda Fetch logs para Pods, use kubectl port-forward
3 - Conceptos subyacentes del Cloud Controller Manager
El concepto del Cloud Controller Manager (CCM) (no confundir con el ejecutable) fue creado originalmente para permitir que Kubernetes y el código específico de proveedores de servicios en la nube evolucionen de forma independiente. El Cloud Controller Manager se ejecuta a la par con otros componentes maestros como el Kubernetes Controller Manager, el API Server y el planificador. También puede ejecutarse como un extra, en cuyo caso se ejecuta por encima de Kubernetes.
El diseño del Cloud Controller Manager está basado en un sistema de plugins, lo que permite a nuevos proveedores de servicios integrarse de forma fácil con Kubernetes. Se está trabajando en implementar nuevos proveedores de servicios y para migrar los existentes del antiguo modelo al nuevo CCM.
Este documento describe los conceptos tras el Cloud Controller Manager y detalla sus funciones asociadas.
En la siguiente imagen, se puede visualizar la arquitectura de un cluster de Kubernetes que no utiliza el Cloud Controller Manager:
Diseño
En el diagrama anterior, Kubernetes y el proveedor de servicios en la nube están integrados a través de diferentes componentes:
- Kubelet
- Kubernetes controller manager
- Kubernetes API server
El CCM consolida toda la lógica dependiente de la nube de estos tres componentes para crear un punto de integración único. La nueva arquitectura con CCM se muestra a continuación:
Componentes del CCM
El CCM secciona parte de la funcionalidad del Kubernetes Controller Manager (KCM) y la ejecuta como procesos independientes. Específicamente, aquellos controladores en el KCM que son dependientes de la nube:
- Controlador de Nodos
- Controlador de Volúmenes
- Controlador de Rutas
- Controlador de Servicios
En la versión 1.9, el CCM se encarga de la ejecución de los siguientes controladores:
- Controlador de Nodos
- Controlador de Rutas
- Controlador de Servicios
Nota:
El controlador de volúmenes se dejó fuera del CCM de forma explícita. Debido a la complejidad que ello requería y a los esfuerzos existentes para abstraer lógica de volúmenes específica a proveedores de servicios, se decidió que el controlador de volúmenes no fuese movido al CCM.El plan original para habilitar volúmenes en CCM era utilizar volúmenes Flex con soporte para volúmenes intercambiables. Sin embargo, otro programa conocido como CSI (Container Storage Interface) se está planeando para reemplazar Flex.
Considerando todo lo anterior, se ha decidido esperar hasta que CSI esté listo.
Funciones del CCM
El CCM hereda sus funciones de componentes que son dependientes de un proveedor de servicios en la nube. Esta sección se ha estructurado basado en dichos componentes:
1. Kubernetes Controller Manager
La mayoría de las funciones del CCM derivan del KCM. Como se ha mencionado en la sección anterior, el CCM es responsable de los siguientes circuitos de control:
- Controlador de Nodos
- Controlador de Rutas
- Controlador de Servicios
Controlador de Nodos
El controlador de nodos es responsable de inicializar un nodo obteniendo información del proveedor de servicios sobre los nodos ejecutándose en el clúster. El controlador de nodos lleva a cabo las siguientes funciones:
- Inicializa un nodo con etiquetas de región y zona específicas del proveedor.
- Inicializa un nodo con detalles de la instancia específicos del proveedor, como por ejemplo, el tipo o el tamaño.
- Obtiene las direcciones de red del nodo y su hostname.
- En caso de que el nodo deje de responder, comprueba la nube para ver si el nodo ha sido borrado. Si lo ha sido, borra el objeto nodo en Kubernetes.
Controlador de Rutas
El controlador de Rutas es responsable de configurar rutas en la nube para que contenedores en diferentes nodos dentro de un clúster kubernetes se puedan comunicar entre sí.
Controlador de Servicios
El controlador de servicios es responsable de monitorizar eventos de creación, actualización y borrado de servicios. Basándose en el estado actual de los servicios en el clúster Kubernetes, configura balanceadores de carga del proveedor (como Amazon ELB, Google LB, or Oracle Cloud Infrastructure Lb) de forma que estos reflejen los servicios definidos en Kubernetes. Adicionalmente, se asegura de que los sistemas de apoyo de servicios para balanceadores de carga en la nube se encuentren actualizados.
2. Kubelet
El controlador de nodos incluye la funcionalidad del kubelet que es dependiente de la nube. Previa a la introducción de CCM, el kubelet era responsable de inicializar un nodo con detalles específicos al proveedor como direcciones IP, etiquetas de región/zona y tipo de instancia. La introduccion de CCM transfiere esta inicialización del kubelet al CCM.
En este nuevo modelo, el kubelet inicializa un nodo sin información especifica del proveedor de servicios. Sin embargo, añade un taint
al nodo recién creado de forma que este no esté disponible para el planificador hasta que el CCM completa el nodo con la información específica del proveedor. Sólo entonces elimina el taint
y el nodo se vuelve accesible.
Mecanismo de Plugins (extensiones)
El Cloud Controller Manager utiliza interfaces Go(lang), lo que permite que implementaciones de cualquier proveedor de servicios sean conectadas. Específicamente, utiliza el CloudProvider Interface definido aquí.
La implementación de los cuatro controladores referenciados en este documento, algunas estructuras de inicialización junto con el interface CloudProvider, permanecerán como parte del núcleo de Kubernetes.
Para más información sobre el desarrollo de extensiones/plugins, consultar Desarrollo del CCM.
Autorización
Esta sección divide el nivel de acceso requerido por varios objetos API para que el CCM pueda llevar acabo sus operaciones.
Controlador de Nodos
El controlador de nodos sólo opera con objetos Nodo. Necesita de acceso total para obtener, listar, crear, actualizar, arreglar, monitorizar y borrar objetos Nodo.
v1/Node:
- Get
- List
- Create
- Update
- Patch
- Watch
- Delete
Controlador de Rutas
El controlador de rutas permanece a la escucha de eventos de creación de nodos y configura sus rutas. Necesita acceso a los objetos Nodo.
v1/Node:
- Get
Controlador de Servicios
El controlador de servicios permanece a la escucha de eventos de creación, actualización y borrado de objetos Servicio, y se encarga de configurar los endpoints para dichos servicios.
Para acceder a los objetos Servicio, necesita permisos para listar y monitorizar. Para el mantenimiento de servicios necesita permisos para parchear y actualizar.
Para configurar endpoints para los servicios necesita permisos para crear, listar, obtener, monitorizar y actualizar.
v1/Service:
- List
- Get
- Watch
- Patch
- Update
Otros
La implementación del núcleo de CCM requiere acceso para crear eventos, y para asegurar la seguridad de operaciones; necesita acceso para crear ServiceAccounts.
v1/Event:
- Create
- Patch
- Update
v1/ServiceAccount:
- Create
El RBAC ClusterRole para CCM se muestra a continuación:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cloud-controller-manager
rules:
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- update
- apiGroups:
- ""
resources:
- nodes
verbs:
- '*'
- apiGroups:
- ""
resources:
- nodes/status
verbs:
- patch
- apiGroups:
- ""
resources:
- services
verbs:
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:
- serviceaccounts
verbs:
- create
- apiGroups:
- ""
resources:
- persistentvolumes
verbs:
- get
- list
- update
- watch
- apiGroups:
- ""
resources:
- endpoints
verbs:
- create
- get
- list
- watch
- update
Implementaciones de Proveedores
Los siguientes proveedores de servicios en la nube han implementado CCMs:
Administración del Clúster
Instrucciones para configurar y ejecutar el CCM pueden encontrarse aquí.
4 - Leases
Los sistemas distribuidos suelen necesitar leases, que proporcionan un mecanismo para bloquear recursos compartidos
y coordinar la actividad entre los miembros de un conjunto.
En Kubernetes, el concepto de lease (arrendamiento) está representado por objetos Lease
en el grupo API de coordination.k8s.io
,
que se utilizan para capacidades críticas del sistema, como los heartbeats del nodo y la elección del líder a nivel de componente.
Heartbeats del nodo
Kubernetes utiliza la API Lease para comunicar los heartbeats de los nodos kubelet al servidor API de Kubernetes.
Para cada Nodo
, existe un objeto Lease
con un nombre que coincide en el espacio de nombres kube-node-lease
.
Analizando a detalle, cada hearbeat es una solicitud update a este objeto Lease
, actualizando
el campo spec.renewTime
del objeto Lease. El plano de control de Kubernetes utiliza la marca de tiempo de este campo
para determinar la disponibilidad de este «Nodo».
Ve Objetos Lease de nodos para más detalles.
Elección del líder
Kubernetes también utiliza Leases para asegurar que sólo una instancia de un componente se está ejecutando en un momento dado.
Esto lo utilizan componentes del plano de control como kube-controller-manager
y kube-scheduler
en configuraciones de
HA, donde sólo una instancia del componente debe estar ejecutándose activamente mientras las otras
instancias están en espera.
Identidad del servidor API
Kubernetes v1.26 [beta]
(enabled by default: true)
A partir de Kubernetes v1.26, cada kube-apiserver
utiliza la API Lease para publicar su identidad al resto del sistema.
Aunque no es particularmente útil por sí mismo, esto proporciona un mecanismo para que los clientes
puedan descubrir cuántas instancias de kube-apiserver
están operando el plano de control de Kubernetes.
La existencia de los objetos leases de kube-apiserver permite futuras capacidades que pueden requerir la coordinación entre
cada kube-apiserver.
Puedes inspeccionar los leases de cada kube-apiserver buscando objetos leases en el namespace kube-system
con el nombre kube-apiserver-<sha256-hash>
. También puedes utilizar el selector de etiquetas apiserver.kubernetes.io/identity=kube-apiserver
:
kubectl -n kube-system get lease -l apiserver.kubernetes.io/identity=kube-apiserver
NAME HOLDER AGE
apiserver-07a5ea9b9b072c4a5f3d1c3702 apiserver-07a5ea9b9b072c4a5f3d1c3702_0c8914f7-0f35-440e-8676-7844977d3a05 5m33s
apiserver-7be9e061c59d368b3ddaf1376e apiserver-7be9e061c59d368b3ddaf1376e_84f2a85d-37c1-4b14-b6b9-603e62e4896f 4m23s
apiserver-1dfef752bcb36637d2763d1868 apiserver-1dfef752bcb36637d2763d1868_c5ffa286-8a9a-45d4-91e7-61118ed58d2e 4m43s
El hash SHA256 utilizado en el nombre del lease se basa en el nombre de host del sistema operativo visto por ese servidor API. Cada kube-apiserver debe ser
configurado para utilizar un nombre de host que es único dentro del clúster. Las nuevas instancias de kube-apiserver que utilizan el mismo nombre de host
asumirán los leases existentes utilizando una nueva identidad de titular, en lugar de instanciar nuevos objetos leases. Puedes comprobar el
nombre de host utilizado por kube-apiserver comprobando el valor de la etiqueta kubernetes.io/hostname
:
kubectl -n kube-system get lease apiserver-07a5ea9b9b072c4a5f3d1c3702 -o yaml
apiVersion: coordination.k8s.io/v1
kind: Lease
metadata:
creationTimestamp: "2023-07-02T13:16:48Z"
labels:
apiserver.kubernetes.io/identity: kube-apiserver
kubernetes.io/hostname: master-1
name: apiserver-07a5ea9b9b072c4a5f3d1c3702
namespace: kube-system
resourceVersion: "334899"
uid: 90870ab5-1ba9-4523-b215-e4d4e662acb1
spec:
holderIdentity: apiserver-07a5ea9b9b072c4a5f3d1c3702_0c8914f7-0f35-440e-8676-7844977d3a05
leaseDurationSeconds: 3600
renewTime: "2023-07-04T21:58:48.065888Z"
Los leases caducados de los kube-apiservers que ya no existen son recogidos por los nuevos kube-apiservers después de 1 hora.
Puedes desactivar el lease de identidades del servidor API desactivando la opción APIServerIdentity
de los interruptores de funcionalidades.
Cargas de trabajo
Tu propia carga de trabajo puede definir su propio uso de los leases. Por ejemplo, puede ejecutar un
controlador en la que un miembro principal o líder
realiza operaciones que sus compañeros no realizan. Tú defines un Lease para que las réplicas del controlador puedan seleccionar
o elegir un líder, utilizando la API de Kubernetes para la coordinación.
Si utilizas un lease, es una buena práctica definir un nombre para el lease que esté obviamente vinculado a
el producto o componente. Por ejemplo, si tienes un componente denominado Ejemplo Foo, utilice un lease denominado
ejemplo-foo
.
Si un operador de clúster u otro usuario final puede desplegar varias instancias de un componente, selecciona un nombre prefijo y elije un mecanismo (como el hash del nombre del despliegue) para evitar colisiones de nombres para los leases.
Puedes utilizar otro enfoque siempre que consigas el mismo resultado: los distintos productos de software no entren en conflicto entre sí.
5 - Container Runtime Interface (CRI)
CRI es una interfaz de plugin que permite que kubelet use una amplia variedad de container runtimes, sin necesidad de volver a compilar los componentes del clúster.
Necesitas un container runtime ejecutándose en cada Nodo en tu clúster, de manera que kubelet pueda iniciar los Pods y sus contenedores.
Container Runtime Interface (CRI) es el protocolo principal para la comunicación entre el kubelet y el Container Runtime.
La Kubernetes Container Runtime Interface (CRI) define el principal protocolo de gRPC para la comunicación entre los componentes de clúster kubelet y container runtime.
API
Kubernetes v1.23 [stable]
Kubelet actúa como un cliente cuando se conecta al runtime del contenedor a través de gRPC.
El runtime y los endpoints del servicio de imágenes deben estar disponibles en el runtime del contenedor,
que se puede configurar por separado dentro de kubelet usando
--image-service-endpoint
banderas de línea de comando.
Para Kubernetes v1.31, kubelet prefiere usar CRI v1
.
Si el runtime del contenedor no es compatible con v1
del CRI, kubelet intenta
negociar cualquier versión compatible anterior.
Kubelet v1.31 también puede negociar CRI v1alpha2
, pero
esta versión se considera obsoleta.
Si kubelet no puede negociar una versión CRI soportada, kubelet se da por vencido
y no se registra como nodo.
Actualizando
Al actualizar Kubernetes, kubelet intenta seleccionar automáticamente la última versión de CRI al reiniciar el componente. Si eso falla, entonces la alternativa se llevará a cabo como se mencionó anteriormente. Si se requirió una rellamada de gRPC porque el runtime del contenedor se ha actualizado, entonces el runtime del contenedor también debe soportar la versión seleccionada inicialmente o se espera que la rellamada falle. Esto requiere un reinicio de kubelet.
Siguientes pasos
- Más información sobre CRI definición de protocolo