Versión imprimible multipagina. Haga click aquí para imprimir.
Introducción
- 1: ¿Qué es Kubernetes?
- 2: Componentes de Kubernetes
- 3: API de Kubernetes
- 4: Objetos de Kubernetes
- 4.1: Entender los Objetos de Kubernetes
- 4.2: Nombres
- 4.3: Espacios de nombres
- 4.4: Etiquetas y Selectores
- 4.5: Anotaciones
- 4.6: Selectores de Campo
- 4.7: Finalizadores
- 4.8: Etiquetas recomendadas
- 5: Gestión de objetos usando kubectl
1 - ¿Qué es Kubernetes?
Esta página ofrece una visión general sobre Kubernetes.
Kubernetes es una plataforma portable y extensible de código abierto para administrar cargas de trabajo y servicios. Kubernetes facilita la automatización y la configuración declarativa. Tiene un ecosistema grande y en rápido crecimiento. El soporte, las herramientas y los servicios para Kubernetes están ampliamente disponibles.
Google liberó el proyecto Kubernetes en el año 2014. Kubernetes se basa en la experiencia de Google corriendo aplicaciones en producción a gran escala por década y media, junto a las mejores ideas y prácticas de la comunidad.
¿Por qué necesito Kubernetes y qué puede hacer por mi?
Kubernetes tiene varias características. Puedes pensar en Kubernetes como:
- una plataforma de contenedores
- una plataforma de microservicios
- una plataforma portable de nube
y mucho más.
Kubernetes ofrece un entorno de administración centrado en contenedores. Kubernetes orquesta la infraestructura de cómputo, redes y almacenamiento para que las cargas de trabajo de los usuarios no tengan que hacerlo. Esto ofrece la simplicidad de las Plataformas como Servicio (PaaS) con la flexibilidad de la Infraestructura como Servicio (IaaS) y permite la portabilidad entre proveedores de infraestructura.
¿Qué hace de Kubernetes una plataforma?
A pesar de que Kubernetes ya ofrece muchas funcionalidades, siempre hay nuevos escenarios que se benefician de nuevas características. Los flujos de trabajo de las aplicaciones pueden optimizarse para acelerar el tiempo de desarrollo. Una solución de orquestación propia puede ser suficiente al principio, pero suele requerir una automatización robusta cuando necesita escalar. Es por ello que Kubernetes fue diseñada como una plataforma: para poder construir un ecosistema de componentes y herramientas que hacen más fácil el desplegar, escalar y administrar aplicaciones.
Las etiquetas, o Labels, le permiten a los usuarios organizar sus recursos como deseen. Las anotaciones, o Annotations, les permiten asignar información arbitraria a un recurso para facilitar sus flujos de trabajo y hacer más fácil a las herramientas administrativas inspeccionar el estado.
Además, el Plano de Control de Kubernetes usa las mismas APIs que usan los desarrolladores y usuarios finales. Los usuarios pueden escribir sus propios controladores, como por ejemplo un planificador o scheduler, usando sus propias APIs desde una herramienta de línea de comandos.
Este diseño ha permitido que otros sistemas sean construidos sobre Kubernetes.
Lo que Kubernetes no es
Kubernetes no es una Plataforma como Servicio (PaaS) convencional. Ya que Kubernetes opera a nivel del contenedor y no a nivel del hardware, ofrece algunas características que las PaaS también ofrecen, como deployments, escalado, balanceo de carga, registros y monitoreo. Dicho esto, Kubernetes no es monolítico y las soluciones que se ofrecen de forma predeterminada son opcionales e intercambiables.
Kubernetes ofrece los elementos esenciales para construir una plataforma para desarrolladores, preservando la elección del usuario y la flexibilidad en las partes más importantes.
Entonces, podemos decir que Kubernetes:
- No limita el tipo de aplicaciones que soporta. Kubernetes busca dar soporte a un número diverso de cargas de trabajo, que incluyen aplicaciones con y sin estado así como aplicaciones que procesan datos. Si la aplicación puede correr en un contenedor, debería correr bien en Kubernetes.
- No hace deployment de código fuente ni compila tu aplicación. Los flujos de integración, entrega y deployment continuo (CI/CD) vienen determinados por la cultura y preferencia organizacional y sus requerimientos técnicos.
- No provee servicios en capa de aplicación como middleware (por ejemplo, buses de mensaje), frameworks de procesamiento de datos (como Spark), bases de datos (como MySQL), caches o sistemas de almacenamiento (como Ceph). Es posible correr estas aplicaciones en Kubernetes, o acceder a ellos desde una aplicación usando un mecanismo portable como el Open Service Broker.
- No dictamina las soluciones de registros, monitoreo o alerta que se deben usar. Hay algunas integraciones que se ofrecen como prueba de concepto, y existen mecanismos para recolectar y exportar métricas.
- No provee ni obliga a usar un sistema o lenguaje de configuración (como jsonnet) sino que ofrece una API declarativa que puede ser usada con cualquier forma de especificación declarativa
- No provee ni adopta un sistema exhaustivo de mantenimiento, administración o corrección automática de errores
Además, Kubernetes no es un mero sistema de orquestación. De hecho, Kubernetes elimina la necesidad de orquestar. Orquestación se define como la ejecución de un flujo de trabajo definido: haz A, luego B y entonces C. Kubernetes está compuesto de un conjunto de procesos de control independientes y combinables entre si que llevan el estado actual hacia el estado deseado. No debería importar demasiado como llegar de A a C. No se requiere control centralizado y, como resultado, el sistema es más fácil de usar, más poderoso, robusto, resiliente y extensible.
¿Por qué usar contenedores?
¿Te preguntas las razones para usar contenedores?
La Manera Antigua de desplegar aplicaciones era instalarlas en un servidor usando el administrador de paquetes del sistema operativo. La desventaja era que los ejecutables, la configuración, las librerías y el ciclo de vida de todos estos componentes se entretejían unos a otros. Podíamos construir imágenes de máquina virtual inmutables para tener rollouts y rollbacks predecibles, pero las máquinas virtuales son pesadas y poco portables.
La Manera Nueva es desplegar contenedores basados en virtualización a nivel del sistema operativo, en vez del hardware. Estos contenedores están aislados entre ellos y con el servidor anfitrión: tienen sus propios sistemas de archivos, no ven los procesos de los demás y el uso de recursos puede ser limitado. Son más fáciles de construir que una máquina virtual, y porque no están acoplados a la infraestructura y sistema de archivos del anfitrión, pueden llevarse entre nubes y distribuciones de sistema operativo.
Ya que los contenedores son pequeños y rápidos, una aplicación puede ser empaquetada en una imagen de contenedor. Esta relación uno a uno entre aplicación e imagen nos abre un abanico de beneficios para usar contenedores. Con contenedores, podemos crear imágenes inmutables al momento de la compilación en vez del despliegue ya que las aplicaciones no necesitan componerse junto al resto del stack ni atarse al entorno de infraestructura de producción. Generar una imagen de contenedor al momento de la compilación permite tener un entorno consistente que va desde desarrollo hasta producción. De igual forma, los contenedores son más transparentes que las máquinas virtuales y eso hace que el monitoreo y la administración sean más fáciles. Esto se aprecia más cuando los ciclos de vida de los contenedores son administrados por la infraestructura en vez de un proceso supervisor escondido en el contenedor. Por último, ya que solo hay una aplicación por contenedor, administrar el despliegue de la aplicación se reduce a administrar el contenedor.
En resumen, los beneficios de usar contenedores incluyen:
- Ágil creación y despliegue de aplicaciones: Mayor facilidad y eficiencia al crear imágenes de contenedor en vez de máquinas virtuales
- Desarrollo, integración y despliegue continuo: Permite que la imagen de contenedor se construya y despliegue de forma frecuente y confiable, facilitando los rollbacks pues la imagen es inmutable
- Separación de tareas entre Dev y Ops: Puedes crear imágenes de contenedor al momento de compilar y no al desplegar, desacoplando la aplicación de la infraestructura
- Observabilidad No solamente se presenta la información y métricas del sistema operativo, sino la salud de la aplicación y otras señales
- Consistencia entre los entornos de desarrollo, pruebas y producción: La aplicación funciona igual en un laptop y en la nube
- Portabilidad entre nubes y distribuciones: Funciona en Ubuntu, RHEL, CoreOS, tu datacenter físico, Google Kubernetes Engine y todo lo demás
- Administración centrada en la aplicación: Eleva el nivel de abstracción del sistema operativo y el hardware virtualizado a la aplicación que funciona en un sistema con recursos lógicos
- Microservicios distribuidos, elásticos, liberados y débilmente acoplados: Las aplicaciones se separan en piezas pequeñas e independientes que pueden ser desplegadas y administradas de forma dinámica, y no como una aplicación monolítica que opera en una sola máquina de gran capacidad
- Aislamiento de recursos: Hace el rendimiento de la aplicación más predecible
- Utilización de recursos: Permite mayor eficiencia y densidad
¿Qué significa Kubernetes? ¿Qué significa K8S?
El nombre Kubernetes proviene del griego y significa timonel o piloto. Es la raíz de gobernador y de cibernética. K8s es una abrevación que se obtiene al reemplazar las ocho letras "ubernete" con el número 8.
Siguientes pasos
- ¿Estás listo para empezar?
- Para saber más, visita el resto de la documentación de Kubernetes.
2 - Componentes de Kubernetes
Este documento describe los distintos componentes que son necesarios para operar un clúster de Kubernetes.
Componentes del plano de control
Los componentes que forman el plano de control toman decisiones globales sobre
el clúster (por ejemplo, la planificación) y detectan y responden a eventos del clúster, como la creación
de un nuevo pod cuando la propiedad replicas
de un controlador de replicación no se cumple.
Estos componentes pueden ejecutarse en cualquier nodo del clúster. Sin embargo para simplificar, los scripts de instalación típicamente se inician en el mismo nodo de forma exclusiva, sin que se ejecuten contenedores de los usuarios en esos nodos. El plano de control se ejecuta en varios nodos para garantizar la alta disponibilidad.
kube-apiserver
El servidor de la API es el componente del plano de control de Kubernetes que expone la API de Kubernetes. Se trata del frontend de Kubernetes, recibe las peticiones y actualiza acordemente el estado en etcd.
La principal implementación de un servidor de la API de Kubernetes es kube-apiserver. Es una implementación preparada para ejecutarse en alta disponiblidad y que puede escalar horizontalmente para balancear la carga entre varias instancias.
etcd
Almacén de datos persistente, consistente y distribuido de clave-valor utilizado para almacenar toda a la información del clúster de Kubernetes.
Si tu clúster utiliza etcd como sistema de almacenamiento, échale un vistazo a la documentación sobre estrategias de backup.
Puedes encontrar información detallada sobre etcd en su documentación oficial.
kube-scheduler
Componente del plano de control que está pendiente de los Pods que no tienen ningún nodo asignado y seleciona uno donde ejecutarlo.
Para decidir en qué nodo se ejecutará el pod, se tienen en cuenta diversos factores: requisitos de recursos, restricciones de hardware/software/políticas, afinidad y anti-afinidad, localización de datos dependientes, entre otros.
kube-controller-manager
Componente del plano de control que ejecuta los controladores de Kubernetes.
Lógicamente cada controlador es un proceso independiente, pero para reducir la complejidad, todos se compilan en un único binario y se ejecuta en un mismo proceso.
Estos controladores incluyen:
- Controlador de nodos: es el responsable de detectar y responder cuándo un nodo deja de funcionar
- Controlador de replicación: es el responsable de mantener el número correcto de pods para cada controlador de replicación del sistema
- Controlador de endpoints: construye el objeto
Endpoints
, es decir, hace una unión entre losServices
y losPods
- Controladores de tokens y cuentas de servicio: crean cuentas y tokens de acceso a la API por defecto para los nuevos Namespaces.
cloud-controller-manager
cloud-controller-manager ejecuta controladores que
interactúan con proveedores de la nube. El binario cloud-controller-manager
es una característica alpha que se introdujo en la versión 1.6 de Kubernetes.
cloud-controller-manager
sólo ejecuta ciclos de control específicos para cada proveedor de la nube. Es posible
desactivar estos ciclos en kube-controller-manager
pasando la opción --cloud-provider= external
cuando se arranque el kube-controller-manager
.
cloud-controller-manager
permite que el código de Kubernetes y el del proveedor de la nube evolucionen de manera independiente. Anteriormente, el código de Kubernetes dependía de la funcionalidad específica de cada proveedor de la nube. En el futuro, el código que sea específico a una plataforma debería ser mantenido por el proveedor de la nube y enlazado a cloud-controller-manager
al correr Kubernetes.
Los siguientes controladores dependen de alguna forma de un proveedor de la nube:
- Controlador de nodos: es el responsable de detectar y actuar cuándo un nodo deja de responder
- Controlador de rutas: para configurar rutas en la infraestructura de nube subyacente
- Controlador de servicios: para crear, actualizar y eliminar balanceadores de carga en la nube
- Controlador de volúmenes: para crear, conectar y montar volúmenes e interactuar con el proveedor de la nube para orquestarlos
Componentes de nodo
Los componentes de nodo corren en cada nodo, manteniendo a los pods en funcionamiento y proporcionando el entorno de ejecución de Kubernetes.
kubelet
Agente que se ejecuta en cada nodo de un clúster. Se asegura de que los contenedores estén corriendo en un pod.
El agente kubelet toma un conjunto de especificaciones de Pod, llamados PodSpecs, que han sido creados por Kubernetes y garantiza que los contenedores descritos en ellos estén funcionando y en buen estado.
kube-proxy
kube-proxy permite abstraer un servicio en Kubernetes manteniendo las reglas de red en el anfitrión y haciendo reenvío de conexiones.
Runtime de contenedores
El runtime de los contenedores es el software responsable de ejecutar los contenedores. Kubernetes soporta varios de ellos: Docker, containerd, cri-o, rktlet y cualquier implementación de la interfaz de runtime de contenedores de Kubernetes, o Kubernetes CRI.
Addons
Los addons son pods y servicios que implementan funcionalidades del clúster. Estos pueden ser administrados
por Deployments
, ReplicationControllers
y otros. Los addons asignados a un espacio de nombres se crean en el espacio kube-system
.
Más abajo se describen algunos addons. Para una lista más completa de los addons disponibles, por favor visite Addons.
DNS
Si bien los otros addons no son estrictamente necesarios, todos los clústers de Kubernetes deberían tener un DNS interno del clúster ya que la mayoría de los ejemplos lo requieren.
El DNS interno del clúster es un servidor DNS, adicional a los que ya podrías tener en tu red, que sirve registros DNS a los servicios de Kubernetes.
Los contenedores que son iniciados por Kubernetes incluyen automáticamente este servidor en sus búsquedas DNS.
Interfaz Web (Dashboard)
El Dashboard es una interfaz Web de propósito general para clústeres de Kubernetes. Le permite a los usuarios administrar y resolver problemas que puedan presentar tanto las aplicaciones como el clúster.
Monitor de recursos de contenedores
El Monitor de recursos de contenedores almacena de forma centralizada series de tiempo con métricas sobre los contenedores, y provee una interfaz para navegar estos datos.
Registros del clúster
El mecanismo de registros del clúster está a cargo de almacenar los registros de los contenedores de forma centralizada, proporcionando una interfaz de búsqueda y navegación.
3 - API de Kubernetes
Las convenciones globales de la API se describen en el documento de convenciones de la API.
Los endpoints, tipos de recursos y ejemplos se describen en la Referencia de la API.
El acceso remoto a la API se discute en el documento Controlando el acceso a la API.
La API de Kubernetes sirve como base para el esquema de configuración declarativa del sistema. La herramienta de línea de comandos kubectl puede ser usada para crear, actualizar, eliminar y consultar objetos a través de la API.
Kubernetes también almacena el estado de los recursos de la API en forma serializada. Actualmente esto se hace en etcd.
Kubernetes está compuesto, en si mismo, por varios componentes que interactúan a través de su API.
Cambios a la API
En nuestra experiencia, cualquier sistema exitoso necesita crecer y evolucionar al cambiar o emerger nuevos casos de uso. Por lo tanto, esperamos que la API de Kubernetes cambie y crezca continuamente. Dicho esto, nuestro objetivo es no romper la compatibilidad con los clientes ya existentes, por un período de tiempo razonable. En general, podemos esperar que se agreguen nuevos recursos y propiedades con cierta frecuencia. Para eliminar un recurso o propiedad, se requiere seguir la política de obsolescencia de la API.
En el documento de cambios a la API describimos como cambiar la API y definimos lo que es considerado como un cambio compatible.
Definiciones OpenAPI y Swagger
Los detalles completos de la API se documentan usando OpenAPI.
A partir de Kubernetes 1.10, el servidor de API de Kubernetes provee una especificación OpenAPI en el endpoint /openapi/v2
.
Se puede solicitar un formato en particular utilizando las siguientes cabeceras HTTP:
Cabecera | Valores admitidos |
---|---|
Accept | application/json , application/com.github.proto-openapi.spec.v2@v1.0+protobuf (el content-type predeterminado es application/json si esta cabecera contiene */* o se omite) |
Accept-Encoding | gzip (esta cabecera es opcional) |
Antes de 1.14, los endpoints separados por formato (/swagger.json
, /swagger-2.0.0.json
, /swagger-2.0.0.pb-v1
, /swagger-2.0.0.pb-v1.gz
)
servían la especificación OpenAPI en distintos formatos. Estos endpoints se consideran obsoletos y serán removidos en Kubernetes 1.14.
Ejemplos:
Antes de 1.10 | A partir de 1.10 |
---|---|
GET /swagger.json | GET /openapi/v2 Accept: application/json |
GET /swagger-2.0.0.pb-v1 | GET /openapi/v2 Accept: application/com.github.proto-openapi.spec.v2@v1.0+protobuf |
GET /swagger-2.0.0.pb-v1.gz | GET /openapi/v2 Accept: application/com.github.proto-openapi.spec.v2@v1.0+protobuf Accept-Encoding: gzip |
Kubernetes implementa un formato alternativo de serialización basado en Protocol Buffer (Protobuf) diseñado principalmente para las comunicaciones dentro del clúster. Este formato está documentado en su propuesta de diseño y los archivos IDL de cada esquema se encuentran en los paquetes de Go que definen los objetos de la API.
Antes de 1.14, el apiserver
de Kubernetes ofrecía una API para obtener la especificación Swagger v1.2 de la API de Kubernetes en /swaggerapi
. Este endpoint se considera obsoleto y será removido en Kubernetes 1.14.
Versionado de la API
Para facilitar la eliminación de propiedades o reestructurar la representación de un recurso, Kubernetes soporta múltiples versiones de la API en distintas rutas como /api/v1
or /apis/extensions/v1beta1
.
Se versiona a nivel de la API en vez de a nivel de los recursos o propiedades para asegurarnos de que la API presenta una visión clara y consistente de los recursos y el comportamiento del sistema, y para controlar el acceso a las APIs experimentales o que estén terminando su ciclo de vida. Los esquemas de serialización JSON y Protobuf siguen los mismos lineamientos para los cambios, es decir, estas descripciones cubren ambos formatos.
Se ha de tener en cuenta que hay una relación indirecta entre el versionado de la API y el versionado del resto del software. La propuesta de versionado de la API y releases describe esta relación.
Las distintas versiones de la API implican distintos niveles de estabilidad y soporte. El criterio para cada nivel se describe en detalle en la documentación de Cambios a la API. A continuación se ofrece un resumen:
- Nivel "alpha":
- El nombre de la versión contiene
alpha
(p. ej.,v1alpha1
). - Puede tener muchos errores. Activar esta característica podría exponer errores. Desactivada por defecto.
- El soporte para esta característica podría ser eliminado sin previo aviso.
- La API podría volverse incompatible en el futuro y sin previo aviso.
- Se recomienda su uso solo en clústers efímeros y de prueba ya que hay mayor riesgo de errores y carece de soporte a largo plazo
- El nombre de la versión contiene
- Nivel "beta":
- El nombre de la versión contiene
beta
(p. ej.,v2beta3
). - El código ha sido probado. Activar esta característica es seguro. Activada por defecto.
- Los detalles de esta característica podrían cambiar, pero se mantendrá el soporte.
- El esquema y/o la semántica de un objeto podría volverse incompatible en el futuro. Si esto pasa, se ofrecerán instrucciones para migrar a una nueva versión. Esto podría requerir eliminar, editar o volver a crear objetos. El proceso de edición podría requerir planificación, incluyendo tiempo de inactividad para aplicaciones que usaban esta característica.
- No se recomienda para aplicaciones críticas de negocio ya que podría volverse incompatible en futuras versiones. Si tiene múltiples clústeres que pueden actualizarse de forma independiente se podría decidir correr este riesgo.
- Por favor, ¡pruebe las características en fase beta y comparta sus comentarios! Una vez que salgan de la fase beta, sería más difícil hacer cambios.
- El nombre de la versión contiene
- Nivel estable:
- El nombre de la versión es
vX
dondeX
es un entero. - Las versiones estables de las características aparecerán en los siguientes releases.
- El nombre de la versión es
Grupos de API
Para que sea más fácil extender la API de Kubernetes, se han creado los grupos de API.
Estos grupos se especifican en una ruta REST y en la propiedad apiVersion
de un objeto serializado.
Actualmente hay varios grupos de API en uso:
El grupo core (o group) en la ruta REST
/api/v1
y usaapiVersion: v1
.Los grupos con entidad propia están en la ruta REST
/apis/$NOMBRE_GRUPO/$VERSION
y usanapiVersion: $NOMBRE_GRUPO/$VERSION
. (p. ej.,apiVersion: batch/v1
). La lista completa de los grupos soportados está disponible en la Referencia de la API.
Hay dos rutas soportadas para extender la API con recursos personalizados:
- CustomResourceDefinition es para los usuarios que tengan necesidades CRUD muy básicas.
- Los usuarios que necesiten la semántica completa de la API pueden implementar su propio
apiserver
usando el agregador para hacerlo transparente para los clientes.
Activar los grupos de API
Ciertos recursos y grupos de API están activados por defecto. Pueden activarse o desactivarse con la opción --runtime-config
en apiserver
. --runtime-config
acepta valores separados por coma. Por ejemplo, para desactivar batch/v1
, use la opción
--runtime-config=batch/v1=false
. Para activar batch/v2alpha1
, pase la opción --runtime-config=batch/v2alpha1
.
Esta opción acepta pares de clave=valor
separados por coma que describen la configuración operativa del apiserver
.
IMPORTANTE: Activar o desactivar grupos o recursos requiere reiniciar el apiserver
y el controller-manager para que estos reconozcan los cambios a --runtime-config
.
Activar recursos en los grupos
Los DaemonSets
, Deployments
, HorizontalPodAutoscalers
, Ingresses
, Jobs
y ReplicaSets
están activados por defecto.
Se pueden activar otros recursos con la opción --runtime-config
del apiserver
. Por ejemplo, como --runtime-config
acepta valores separados por coma, puede desactivar los Deployments y los Ingress con la opción
--runtime-config=extensions/v1beta1/deployments=false,extensions/v1beta1/ingresses=false
4 - Objetos de Kubernetes
4.1 - Entender los Objetos de Kubernetes
Esta página explica cómo se representan los objetos de Kubernetes en la API de Kubernetes, y cómo puedes definirlos en formato .yaml
.
Entender los Objetos de Kubernetes
Los Objetos de Kubernetes son entidades persistentes dentro del sistema de Kubernetes. Kubernetes utiliza estas entidades para representar el estado de tu clúster. Específicamente, pueden describir:
- Qué aplicaciones corren en contenedores (y en qué nodos)
- Los recursos disponibles para dichas aplicaciones
- Las políticas acerca de cómo dichas aplicaciones se comportan, como las políticas de reinicio, actualización, y tolerancia a fallos
Un objeto de Kubernetes es un "registro de intención" -- una vez que has creado el objeto, el sistema de Kubernetes se pondrá en marcha para asegurar que el objeto existe. Al crear un objeto, en realidad le estás diciendo al sistema de Kubernetes cómo quieres que sea la carga de trabajo de tu clúster; esto es, el estado deseado de tu clúster.
Para trabajar con los objetos de Kubernetes -- sea para crearlos, modificarlos, o borrarlos -- necesitarás usar la API de Kubernetes. Cuando utilizas el interfaz de línea de comandos kubectl
, por ejemplo, este realiza las llamadas necesarias a la API de Kubernetes en tu lugar. También puedes usar la API de Kubernetes directamente desde tus programas utilizando alguna de las Librerías de Cliente.
Alcance y Estado de un Objeto
Cada objeto de Kubernetes incluye dos campos como objetos anidados que determinan la configuración del objeto: el campo de objeto spec y el campo de objeto status. El campo spec, que es obligatorio, describe el estado deseado del objeto -- las características que quieres que tenga el objeto. El campo status describe el estado actual del objeto, y se suministra y actualiza directamente por el sistema de Kubernetes. En cualquier momento, el Plano de Control de Kubernetes gestiona de forma activa el estado actual del objeto para que coincida con el estado deseado requerido.
Por ejemplo, un Deployment de Kubernetes es un objeto que puede representar una aplicación de tu clúster. Cuando creas el Deployment, puedes especificar en el spec del Deployment que quieres correr tres réplicas de la aplicación. El sistema de Kubernetes lee el spec del Deployment y comienza a instanciar réplicas de tu aplicación -- actualizando el estado para conciliarlo con tu spec. Si cualquiera de las instancias falla (un cambio de estado), el sistema de Kubernetes soluciona la diferencia entre la spec y el estado llevando a cabo una correción -- en este caso, iniciando otra instancia de reemplazo.
Para obtener más información acerca de la spec, el status, y los metadatos de los objetos, echa un vistazo a las Normas de la API de Kubernetes.
Describir un Objeto de Kubernetes
Cuando creas un objeto en Kubernetes, debes especificar la spec del objeto que describe su estado deseado, así como información básica del mismo (como el nombre). Cuando usas la API de Kubernetes para crear el objeto (bien de forma directa o usando kubectl
), dicha petición a la API debe incluir toda la información en formato JSON en el cuerpo de la petición. A menudo, le proporcionas la información a kubectl
como un archivo .yaml. kubectl
convierte esa información a JSON cuando realiza la llamada a la API.
Aquí hay un ejemplo de un archivo .yaml
que muestra los campos requeridos y la spec del objeto Deployment de Kubernetes:
apiVersion: apps/v1 # Usa apps/v1beta2 para versiones anteriores a 1.9.0
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2 # indica al controlador que ejecute 2 pods
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
Una forma de crear un Deployment utilizando un archivo .yaml
como el indicado arriba sería ejecutar el comando
kubectl apply
en el interfaz de línea de comandos, pasándole el archivo .yaml
como argumento. Aquí tienes un ejemplo de cómo hacerlo:
kubectl apply -f https://k8s.io/examples/application/deployment.yaml --record
La salida del comando sería algo parecido a esto:
deployment.apps/nginx-deployment created
Campos requeridos
En el archivo .yaml
del objeto de Kubernetes que quieras crear, obligatoriamente tendrás que indicar los valores de los siguientes campos (como mínimo):
apiVersion
- Qué versión de la API de Kubernetes estás usando para crear este objetokind
- Qué clase de objeto quieres crearmetadata
- Datos que permiten identificar unívocamente al objeto, incluyendo una cadena de texto para elname
, UID, y opcionalmente elnamespace
También deberás indicar el campo spec
del objeto. El formato del campo spec
es diferente según el tipo de objeto de Kubernetes, y contiene campos anidados específicos de cada objeto. La Referencia de la API de Kubernetes puede servirte de ayuda para encontrar el formato de la spec para cada uno de los objetos que puedes crear usando Kubernetes.
Por ejemplo, el formato de la spec
para un objeto de tipo Pod
lo puedes encontrar
aquí,
y el formato de la spec
para un objeto de tipo Deployment
lo puedes encontrar
aquí.
Siguientes pasos
- Aprender más acerca de los objetos básicos más importantes de Kubernetes, como el Pod.
4.2 - Nombres
Todos los objetos de la API REST de Kubernetes se identifica de forma inequívoca mediante un Nombre y un UID.
Para aquellos atributos provistos por el usuario que no son únicos, Kubernetes provee de etiquetas y anotaciones.
Echa un vistazo al documento de diseño de identificadores para información precisa acerca de las reglas sintácticas de los Nombres y UIDs.
Nombres
Una cadena de caracteres proporcionada por el cliente que identifica un objeto en la URL de un recurso, como por ejemplo, /api/v1/pods/nombre-del-objeto
.
Los nombres de los objetos son únicos para cada tipo de objeto. Sin embargo, si se elimina el objeto, se puede crear un nuevo objeto con el mismo nombre.
Por regla general, los nombres de los recursos de Kubernetes no deben exceder la longitud máxima de 253 caracteres y deben incluir caracteres alfanuméricos en minúscula, -
, y .
; aunque algunos recursos tienen restricciones más específicas.
UIDs
Una cadena de caracteres generada por Kubernetes para identificar objetos de forma única.
Cada objeto creado a lo largo de toda la vida de un clúster Kubernetes tiene un UID distinto. Está pensado para distinguir entre ocurrencias históricas de entidades similares.
4.3 - Espacios de nombres
Kubernetes soporta múltiples clústeres virtuales respaldados por el mismo clúster físico. Estos clústeres virtuales se denominan espacios de nombres (namespaces).
Cuándo Usar Múltiple Espacios de Nombre
Los espacios de nombres están pensados para utilizarse en entornos con muchos usuarios distribuidos entre múltiples equipos, o proyectos. Para aquellos clústeres con unas pocas decenas de usuarios, no deberías necesitar crear o pensar en espacios de nombres en absoluto. Empieza a usarlos solamente si necesitas las características que proporcionan.
Los espacios de nombres proporcionan un campo de acción para los nombres. Los nombres de los recursos tienen que ser únicos dentro de cada espacio de nombres, pero no entre dichos espacios de nombres.
Los espacios de nombres son una forma de dividir los recursos del clúster entre múltiples usuarios (via cuotas de recursos).
En futuras versiones de Kubernetes, los objetos de un mismo espacio de nombres tendrán las mismas políticas de control de acceso por defecto.
No es necesario usar múltiples espacios de nombres sólo para separar recursos ligeramente diferentes, como versiones diferentes de la misma aplicación: para ello utiliza etiquetas para distinguir tus recursos dentro del mismo espacio de nombres.
Trabajar con Espacios de Nombres
La creación y borrado de espacios de nombres se describe en la documentación de la Guía de Administración para espacios de nombres.
Ver espacios de nombre
Puedes listar los espacios de nombres actuales dentro de un clúster mediante:
kubectl get namespaces
NAME STATUS AGE
default Active 1d
kube-system Active 1d
kube-public Active 1d
Kubernetes arranca con tres espacios de nombres inicialmente:
default
El espacio de nombres por defecto para aquellos objetos que no especifican ningún espacio de nombreskube-system
El espacio de nombres para aquellos objetos creados por el sistema de Kuberneteskube-public
Este espacio de nombres se crea de forma automática y es legible por todos los usuarios (incluyendo aquellos no autenticados). Este espacio de nombres se reserva principalmente para uso interno del clúster, en caso de que algunos recursos necesiten ser visibles y legibles de forma pública para todo el clúster. La naturaleza pública de este espacio de nombres es simplemente por convención, no es un requisito.
Establecer el espacio de nombres para una petición
Para indicar de forma temporal el espacio de nombres para una petición, usa la opción --namespace
.
Por ejemplo:
kubectl --namespace=<insert-namespace-name-here> run nginx --image=nginx
kubectl --namespace=<insert-namespace-name-here> get pods
Establecer la preferencia de espacio de nombres
Puedes indicar de forma permanente el espacio de nombres para todas las llamadas futuras a comandos kubectl en dicho contexto.
kubectl config set-context --current --namespace=<insert-namespace-name-here>
# Validate it
kubectl config view | grep namespace:
Espacios de nombres y DNS
Cuando creas un Servicio, se crea una entrada DNS correspondiente.
Esta entrada tiene la forma <service-name>.<namespace-name>.svc.cluster.local
, que significa
que si un contenedor simplemente usa <service-name>
, se resolverá al servicio
que sea local al espacio de nombres. Esto es de utilidad para poder emplear la misma
configuración entre múltiples espacios de nombres como Development, Staging y Production.
Si quieres referenciar recursos entre distintos espacios de nombres, entonces
debes utilizar el nombre cualificado completo de dominio (FQDN).
No Todos los Objetos están en un Espacio de nombres
La mayoría de los recursos de Kubernetes (ej. pods, services, replication controllers, y otros) están en algunos espacios de nombres. Sin embargo, los recursos que representan a los propios espacios de nombres no están a su vez en espacios de nombres. De forma similar, los recursos de bajo nivel, como los nodos y los volúmenes persistentes, no están en ningún espacio de nombres.
Para comprobar qué recursos de Kubernetes están y no están en un espacio de nombres:
# In a namespace
kubectl api-resources --namespaced=true
# Not in a namespace
kubectl api-resources --namespaced=false
4.4 - Etiquetas y Selectores
Las etiquetas son pares de clave/valor que se asocian a los objetos, como los pods. El propósito de las etiquetas es permitir identificar atributos de los objetos que son relevantes y significativos para los usuarios, pero que no tienen significado para el sistema principal. Se puede usar las etiquetas para organizar y seleccionar subconjuntos de objetos. Las etiquetas se pueden asociar a los objetos a la hora de crearlos y posteriormente modificarlas o añadir nuevas. Cada objeto puede tener un conjunto de etiquetas clave/valor definidas, donde cada clave debe ser única para un mismo objeto.
"metadata": {
"labels": {
"key1" : "value1",
"key2" : "value2"
}
}
Las etiquetas permiten consultar y monitorizar los objetos de forma más eficiente y son ideales para su uso en UIs y CLIs. El resto de información no identificada debe ser registrada usando anotaciones.
Motivación
Las etiquetas permiten que los usuarios mapeen sus estructuras organizacionales en los propios objetos sin acoplamiento, sin forzar a los clientes a almacenar estos mapeos.
Los despliegues de servicios y los procesos en lotes suelen requerir a menudo la gestión de entidades multi-dimensionales (ej., múltiples particiones o despliegues, múltiples entregas, múltiples capas, múltiples microservicios por capa). Tal gestión a menudo requiere de operaciones horizontales que rompen la encapsulación de representaciones estrictamente jerárquicas, especialmente jerarquías rígidas determinadas por la infraestructura en vez de por los usuarios.
Ejemplos de etiquetas:
"release" : "stable"
,"release" : "canary"
"environment" : "dev"
,"environment" : "qa"
,"environment" : "production"
"tier" : "frontend"
,"tier" : "backend"
,"tier" : "cache"
"partition" : "customerA"
,"partition" : "customerB"
"track" : "daily"
,"track" : "weekly"
Estos son sólo algunos ejemplos de etiquetas de uso común; eres libre de establecer tus propias normas. Ten en cuenta que la clave de cada etiqueta debe ser única dentro de cada objeto.
Sintaxis y conjunto de caracteres
Las etiquetas son pares de clave/valor. Las claves válidas de etiqueta tienen dos partes: un prefijo opcional y un nombre, separados por una barra (/
). La parte del nombre es obligatoria y debe ser menor o igual a 63 caracteres, empezando y terminando con un carácter alfanumérico ([a-z0-9A-Z]
), con guiones (-
), guiones bajos (_
), puntos (.
), y cualquier carácter alfanumérico en medio. El prefijo es opcional. Si se indica, este debe ser un subdominio DNS: una serie de etiquetas DNS separadas por puntos (.
), no mayores de 253 caracteres en total, seguidas de una barra (/
).
Si se omite el prefijo, la clave de la etiqueta se entiende que es privada para el usuario. Los componentes automatizados del sistema (ej. kube-scheduler
, kube-controller-manager
, kube-apiserver
, kubectl
, u otros de terceras partes) que añaden etiquetas a los objetos de usuario deben especificar obligatoriamente un prefijo.
Los prefijos kubernetes.io/
y k8s.io/
están reservados para el sistema de Kubernetes.
Los valores de etiqueta válidos deben tener como máximo 63 caracteres y empezar y terminar con un carácter alfanumérico ([a-z0-9A-Z]
), con guiones (-
), guiones bajos (_
), puntos (.
), y cualquier carácter alfanumérico en medio.
Selectores de etiquetas
Al contrario que los nombres y UIDs, las etiquetas no garantizan la unicidad. En general, se espera que muchos objetos compartan la(s) misma(s) etiqueta(s).
A través del selector de etiqueta, el cliente/usuario puede identificar un conjunto de objetos. El selector de etiqueta es la primitiva principal de agrupación en Kubernetes.
La API actualmente soporta dos tipos de selectores: basados en igualdad y basados en conjunto.
Un selector de etiqueta puede componerse de múltiples requisitos separados por coma. En el caso de múltiples requisitos, todos ellos deben ser satisfechos de forma que las comas actúan como operadores AND (&&
) lógicos.
La semántica de selectores vacíos o no espefificados es dependiente del contexto, y los tipos de la API que utilizan los selectores deberían documentar su propia validación y significado.
Nota:
Para algunos tipos de la API, como los ReplicaSets, los selectores de etiqueta de dos instancias no deben superponerse dentro del mismo espacio de nombres, ya que el controlador puede interpretarlos como un conflicto y no ser capaz de determinar cuántas réplicas debería haber finalmente.Requisito basado en Igualdad
Los requisitos basados en Igualdad o Desigualdad permiten filtrar por claves y valores de etiqueta. Los objetos coincidentes deben satisfacer todas y cada una de las etiquetas indicadas, aunque puedan tener otras etiquetas adicionalmente.
Se permiten tres clases de operadores =
,==
,!=
. Los dos primeros representan la igualdad (y son simplemente sinónimos), mientras que el último representa la desigualdad. Por ejemplo:
environment = production
tier != frontend
El primero selecciona todos los recursos cuya clave es igual a environment
y su valor es igual a production
.
El último selecciona todos los recursos cuya clave es igual a tier
y su valor distinto de frontend
, y todos los recursos que no tengan etiquetas con la clave tier
.
Se podría filtrar los recursos de production
que excluyan frontend
usando comas: environment=production,tier!=frontend
Un escenario de uso de requisitos basados en igualdad es aquel donde los Pods pueden especificar
los criterios de selección de nodo. Por ejemplo, el Pod de abajo selecciona aquellos nodos con
la etiqueta "accelerator=nvidia-tesla-p100
".
apiVersion: v1
kind: Pod
metadata:
name: cuda-test
spec:
containers:
- name: cuda-test
image: "registry.k8s.io/cuda-vector-add:v0.1"
resources:
limits:
nvidia.com/gpu: 1
nodeSelector:
accelerator: nvidia-tesla-p100
Requisito basado en Conjunto
Los requisitos de etiqueta basados en Conjuntos permiten el filtro de claves en base a un conjunto de valores. Se puede utilizar tres tipos de operadores: in
,notin
y exists
(sólo el identificador clave). Por ejemplo:
environment in (production, qa)
tier notin (frontend, backend)
partition
!partition
El primer ejemplo selecciona todos los recursos cuya clave es igual a environment
y su valor es igual a production
o qa
.
El segundo ejemplo selecciona todos los recursos cuya clave es igual a tier
y sus valores son distintos de frontend
y backend
, y todos los recursos que no tengan etiquetas con la clavetier
.
El tercer ejemplo selecciona todos los recursos que incluyan una etiqueta con la clave partition
; sin comprobar los valores.
El cuarto ejemplo selecciona todos los recursos que no incluyan una etiqueta con la clave partition
; sin comprobar los valores.
De forma similar, el separador de coma actúa como un operador AND . Así, el filtro de recursos con una clave igual a partition
(sin importar el valor) y con un environment
distinto de qa
puede expresarse como partition,environment notin (qa)
.
El selector basado en conjunto es una forma genérica de igualdad puesto que environment=production
es equivalente a environment in (production)
; y lo mismo aplica para !=
y notin
.
Los requisitos basados en conjunto pueden alternarse con aquellos basados en igualdad. Por ejemplo: partition in (customerA, customerB),environment!=qa
.
API
Filtro con LIST y WATCH
Las operaciones LIST y WATCH pueden especificar selectores de etiqueta para filtrar el conjunto de objetos devueltos usando un parámetro de consulta. Ambos requisitos están permitidos (se presentan aquí como aparecerían en la cadena URL de consulta):
- requisitios basados en igualdad:
?labelSelector=environment%3Dproduction,tier%3Dfrontend
- requisitios basados en conjunto:
?labelSelector=environment+in+%28production%2Cqa%29%2Ctier+in+%28frontend%29
Es posible utilizar ambos estilos de selección de etiquetas para mostrar u observar recursos con un cliente REST. Por ejemplo, para enfocarse en apiserver
con kubectl
usando el estilo basado en igualdad se puede ejecutar:
kubectl get pods -l environment=production,tier=frontend
o usando requisitos basados en conjunto:
kubectl get pods -l 'environment in (production),tier in (frontend)'
Como ya se ha comentado, los requisitos basados en conjunto son más expresivos. Por ejemplo, se puede implementar el operador OR sobre valores:
kubectl get pods -l 'environment in (production, qa)'
o restringir la coincidencia negativa mediante el operador notin:
kubectl get pods -l 'environment,environment notin (frontend)'
Establecer referencias en los objetos de la API
Algunos objetos de Kubernetes, como los services
y los replicationcontrollers
, también hacen uso de los selectores de etiqueta para referirse a otros conjuntos de objetos, como los pods.
Service y ReplicationController
El conjunto de pods que un service
expone se define con un selector de etiqueta. De forma similar, el conjunto de pods que un replicationcontroller
debería gestionar se define con un selector de etiqueta.
Los selectores de etiqueta para ambos objetos se definen en los archivos json
o yaml
usando mapas, y únicamente se permite los selectores basados en igualad:
"selector": {
"component" : "redis",
}
ó
selector:
component: redis
este selector (respectivamente en formato json
o yaml
) es equivalente a component=redis
o component in (redis)
.
Recursos que soportan requisitos basados en conjunto
Algunos recursos más recientes, como el Job
, el Deployment
, el Replica Set
, y el Daemon Set
, sí permiten requisitos basados en conjunto.
selector:
matchLabels:
component: redis
matchExpressions:
- {key: tier, operator: In, values: [cache]}
- {key: environment, operator: NotIn, values: [dev]}
matchLabels
es un mapa de pares {key,value}
. Una única combinación de {key,value}
en el mapa matchLabels
es equivalente a un elemento en matchExpressions
donde el campo key
es "key", el operator
es "In", y la matriz values
contiene únicamente "value". matchExpressions
es una lista de requisitos de selección de pod. Los operadores permitidos son In, NotIn, Exists, y DoesNotExist. El conjunto de valores no puede ser vacío en el caso particular de In y NotIn. Todos los requisitos, tanto de matchLabels
como de matchExpressions
se combinan entre sí con el operador AND -- todos ellos deben ser satisfechos.
Seleccionar conjuntos de objetos
Un caso de uso de selección basada en etiquetas es la posibilidad de limitar los nodos en los que un pod puede desplegarse. Ver la documentación sobre selección de nodo para más información.
4.5 - Anotaciones
Puedes usar las anotaciones de Kubernetes para adjuntar metadatos arbitrarios a los objetos, de tal forma que clientes como herramientas y librerías puedan obtener fácilmente dichos metadatos.
Adjuntar metadatos a los objetos
Puedes usar las etiquetas o anotaciones para adjuntar metadatos a los objetos de Kubernetes. Las etiquetas pueden utilizarse para seleccionar objetos y para encontrar colecciones de objetos que satisfacen ciertas condiciones. Por el contrario, las anotaciones no se utilizan para identificar y seleccionar objetos. Los metadatos de una anotación pueden ser pequeños o grandes, estructurados o no estructurados, y pueden incluir caracteres no permitidos en las etiquetas.
Las anotaciones, al igual que las etiquetas, son mapas de clave/valor:
"metadata": {
"annotations": {
"key1" : "value1",
"key2" : "value2"
}
}
Aquí se presentan algunos ejemplos de información que podría ser indicada como anotaciones:
Campos gestionados por una capa de configuración declarativa. Adjuntando dichos campos como anotaciones permitiría diferenciarlos de los valores por defecto establecidos por clientes o servidores, además de los campos auto-generados y los campos modificados por sistemas de auto-escalado.
Información acerca de la construcción, entrega, o imagen como marcas de fecha, IDs de entrega, rama de Git, número de PR, funciones hash de imágenes, y direcciones de registro.
Referencias a los repositorios de trazas, monitorización, analíticas, o auditoría.
Información de librería de cliente o herramienta que puede usarse con fines de depuración de código: por ejemplo, nombre, versión, e información de construcción.
Información de usuario o procedencia de herramienta/sistema, como las URLs de los objetos provenientes de otros componentes del ecosistema.
Metadatos para una herramienta ligera de lanzamiento de aplicaciones: por ejemplo, configuración o puntos de control.
Número de teléfono o contacto de las personas a cargo, o entradas de directorio que especifican dónde puede encontrarse dicha información, como la página web de un equipo de trabajo.
Directivas del usuario final a las implementaciones para modificar el comportamiento o solicitar funcionalidades no estándar.
En vez de usar anotaciones, podrías almacenar este tipo de información en una base de datos externa o un directorio, pero eso complicaría enormemente la posibilidad de crear librerías compartidas de cliente, así como herramientas para el despliegue, gestión, introspección, y similares.
Sintaxis y conjunto de caracteres
Las Anotaciones son entradas clave/valor. Una clave válida para una anotación tiene dos partes: un prefijo opcional y un nombre, separados por una barra (/
). La parte del nombre es obligatoria y debe tener 63 caracteres o menos, empezando y terminando con un carácter alfanumérico ([a-z0-9A-Z]
) con guiones (-
), guiones bajos (_
), puntos (.
) en medio. El prefijo es opcional. Si se indica,
el prefijo debe ser un subdominio DNS: una serie de etiquetas DNS separadas por puntos (.
), no superior a 253 caracteres en total, seguida de una barra (/
).
Si se omite el prefijo, la clave de la anotación se entiende que es privada para el usuario. Los componentes automatizados del sistema (e.g. kube-scheduler
, kube-controller-manager
, kube-apiserver
, kubectl
, u otros de terceros) que añaden anotaciones a los objetos de usuario deben, pues, especificar un prefijo.
Los prefijos kubernetes.io/
y k8s.io/
se reservan para el uso exclusivo de los componentes principales de Kubernetes.
Siguientes pasos
Aprende más acerca de las Etiquetas y Selectores.
4.6 - Selectores de Campo
Los selectores de campo te permiten seleccionar recursos de Kubernetes basados en el valor de uno o más campos del recurso. Aquí se presentan varios ejemplos de consultas de selectores de campo:
metadata.name=my-service
metadata.namespace!=default
status.phase=Pending
Este comando kubectl
selecciona todos los Pods para los cuales el valor del campo status.phase
es igual a Running
:
kubectl get pods --field-selector status.phase=Running
Nota:
Los selectores de campo son esencialmente filtros de recursos. Por defecto, no se aplica ningún selector/filtro, lo que significa que todos los tipos de recursos son seleccionados. Esto hace que las siguientes consultas con kubectl
sean equivalentes:
kubectl get pods
kubectl get pods --field-selector ""
Campos soportados
Los selectores de campos soportados varían según el tipo de recursos de Kubernetes. Todos los tipos de recursos permiten los campos metadata.name
y metadata.namespace
. El uso de un selector de campo no soportado provoca un error. Por ejemplo:
kubectl get ingress --field-selector foo.bar=baz
Error from server (BadRequest): Unable to find "ingresses" that match label selector "", field selector "foo.bar=baz": "foo.bar" is not a known field selector: only "metadata.name", "metadata.namespace"
Operadores soportados
Puedes usar los operadores =
, ==
, y !=
en los selectores de campo (=
y ==
significan lo mismo). Este comando de kubectl
, por ejemplo, selecciona todos los servicios de Kubernetes que no están en el espacio de nombres default
:
kubectl get services --field-selector metadata.namespace!=default
Selectores anidados
De la misma manera que con una etiqueta y otros selectores, los selectores de campo pueden anidarse como una lista de elementos separados por coma. Este comando de kubectl
selecciona todos los Pods para los que el campo status.phase
no es igual a Running
y el campo spec.restartPolicy
es igual a Always
:
kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Always
Múltiples tipos de recursos
Puedes usar los selectores de campo entre múltiples tipos de recursos. Este comando de kubectl
selecciona todos los Statefulsets y Services que no están en el espacio de nombres default
:
kubectl get statefulsets,services --all-namespaces --field-selector metadata.namespace!=default
4.7 - Finalizadores
Los finalizadores son atributos de un namespace que instruyen a Kubernetes a esperar a que ciertas condiciones sean satisfechas antes que pueda borrar definitivamente un objeto que ha sido marcado para eliminarse. Los finalizadores alertan a los controladores para borrar recursos que poseian esos objetos eliminados.
Cuando instruyes a Kubernetes a borrar un objeto que tiene finalizadores
especificados, la API de Kubernetes marca ese objeto para eliminacion
configurando el campo metadata.deletionTimestamp
, y retorna un codigo de
estado 202
(HTTP "Aceptado").
El objeto a borrar permanece en un estado
de terminacion mientras el plano de contol, u otros componentes, ejecutan
las acciones definidas en los finalizadores.
Luego de que esas acciones son completadas, el controlador borra los
finalizadores relevantes del objeto. Cuando el campo metadata.finalizers
esta vacio, Kubernetes considera el proceso de eliminacion completo y borra
el objeto.
Puedes utilizar finalizadores para controlar garbage collection de recursos. Por ejemplo, puedes definir un finalizador para borrar recursos relacionados o infraestructura antes que el controlador elimine el objeto.
Puedes usar finalizadores para controlar garbage collection de los recursos alertando a los controladores para que ejecuten tareas de limpieza especificas antes de eliminar el recurso.
Los finalizadores usualmente no especifican codigo a ejecutar, sino que son generalmente listas de parametros referidos a un recurso especifico, similares a las anotaciones. Kubernetes especifica algunos finalizadores automaticamente, pero podrías especificar tus propios.
Cómo funcionan los finalizadores
Cuando creas un recurso utilizando un archivo de manifiesto, puedes especificar
finalizadores mediante el campo metadata.finalizers
. Cuando intentas eliminar el
recurso, el servidor API que maneja el pedido de eliminación ve los valores en el
campo finalizadores
y hace lo siguiente:
- Modifica el objecto para agregar un campo
metadata.deletionTimestamp
con el momento en que comenzaste la eliminación. - Previene que el objeto sea eliminado hasta que su campo
metadata.finalizers
este vacío. - Retorna un codigo de estado
202
(HTTP "Aceptado")
El controlador que meneja ese finalizador recibe la actualización del objecto
configurando el campo metadata.deletionTimestamp
, indicando que la eliminación
del objeto ha sido solicitada.
El controlador luego intenta satisfacer los requerimientos de los finalizadores
especificados para ese recurso. Cada vez que una condición del finalizador es
satisfecha, el controlador remueve ese parametro del campo finalizadores
. Cuando
el campo finalizadores
esta vacío, un objeto con un campo deletionTimestamp
configurado es automaticamente borrado. Puedes tambien utilizar finalizadores para
prevenir el borrado de recursos no manejados.
Un ejemplo usual de un finalizador es kubernetes.io/pv-protection
, el cual
previene el borrado accidental de objetos PersistentVolume
. Cuando un objeto
PersistentVolume
está en uso por un Pod, Kubernetes agrega el finalizador
pv-protection
. Si intentas elimiar el PersistentVolume
, este pasa a un estado
Terminating
, pero el controlador no puede eliminarlo ya que existe el finalizador.
Cuando el Pod deja de utilizar el PersistentVolume
, Kubernetes borra el finalizador
pv-protection
y el controlador borra el volumen.
Referencias de dueño, etiquetas y finalizadores (#owners-labels-finalizers)
Al igual que las etiquetas, las referencias de dueño describen las relaciones entre objetos en Kubernetes, pero son utilizadas para un propósito diferente. Cuando un controlador maneja objetos como Pods, utiliza etiquetas para identificar cambios a grupos de objetos relacionados. Por ejemplo, cuando un Job crea uno o más Pods, el controlador del Job agrega etiquetas a esos pods para identificar cambios a cualquier Pod en el cluster con la misma etiqueta.
El controlador del Job tambien agrega referencias de dueño a esos Pods, referidas al Job que creo a los Pods. Si borras el Job mientras estos Pods estan corriendo, Kubernetes utiliza las referencias de dueño (no las etiquetas) para determinar cuáles Pods en el cluster deberían ser borrados.
Kubernetes también procesa finalizadores cuando identifica referencias de dueño en un recurso que ha sido marcado para eliminación.
En algunas situaciones, los finalizadores pueden bloquear el borrado de objetos dependientes, causando que el objeto inicial a borrar permanezca más de lo esperado sin ser completamente eliminado. En esas situaciones, deberías chequear finalizadores y referencias de dueños en los objetos y sus dependencias para intentar solucionarlo.
Nota:
En casos donde los objetos queden bloqueados en un estado de eliminación, evita borrarlos manualmente para que el proceso continue. Los finalizadores usualmente son agregados a los recursos por una razón, por lo cual eliminarlos forzosamente puede causar problemas en tu cluster. Borrados manuales sólo deberían ejecutados cuando el propósito del finalizador es entendido y satisfecho de alguna otra manera (por ejemplo, borrando manualmente un objeto dependiente).Siguientes pasos
- Lea Using Finalizers to Control Deletion en el blog de Kubernetes.
4.8 - Etiquetas recomendadas
Puedes visualizar y gestionar los objetos de Kubernetes con herramientas adicionales a kubectl y el propio tablero de control. Un conjunto común de etiquetas permite a dichas herramientas trabajar de forma interoperable, describiendo los objetos de una forma común que todas las herramientas puedan entender.
Además del soporte a herramientas, las etiquetas recomendadas describen las aplicaciones de forma que puedan ser consultadas.
Los metadatos se organizan en torno al concepto de una aplicación. Kubernetes no es una plataforma como servicio (PaaS) y ni tiene o restringe la definición formal de una aplicación. Al contrario, las aplicaciones son informales y se describen mediante el uso de los metadatos. La definición de lo que contiene una aplicación es imprecisa.
Nota:
Estas son las etiquetas recomendadas. Estas facilitan la gestión de aplicaciones, pero no son obligatorias para las herramientas en general.Las etiquetas compartidas y las anotaciones comparten un prefijo común: app.kubernetes.io
.
Las etiquetas sin un prefijo son privadas para los usuarios. El prefijo compartido
garantiza que las etiquetas compartidas no entran en conflicto con las etiquetas
personalizadas de usuario.
Etiquetas
Para beneficiarse al máximo del uso de estas etiquetas, estas deberían aplicarse a cada objeto de recurso.
Clave | Descripción | Ejemplo | Tipo |
---|---|---|---|
app.kubernetes.io/name | El nombre de la aplicación | mysql | string |
app.kubernetes.io/instance | Un nombre único que identifique la instancia de la aplicación | wordpress-abcxzy | string |
app.kubernetes.io/version | La versión actual de la aplicación (ej., la versión semántica, cadena hash de revisión, etc.) | 5.7.21 | string |
app.kubernetes.io/component | El componente dentro de la arquitectura | database | string |
app.kubernetes.io/part-of | El nombre de una aplicación de nivel superior de la cual es parte esta aplicación | wordpress | string |
app.kubernetes.io/managed-by | La herramienta usada para gestionar la operativa de una aplicación | helm | string |
Para ilustrar estas etiquetas en acción, consideremos el siguiente objeto StatefulSet:
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/instance: wordpress-abcxzy
app.kubernetes.io/version: "5.7.21"
app.kubernetes.io/component: database
app.kubernetes.io/part-of: wordpress
app.kubernetes.io/managed-by: helm
Aplicaciones e Instancias de Aplicaciones
Una misma aplicación puede desplegarse una o más veces en un clúster de Kubernetes e, incluso, el mismo espacio de nombres. Por ejemplo, wordpress puede instalarse más de una vez de forma que sitios web diferentes sean instalaciones diferentes de wordpress.
El nombre de una aplicación y el nombre de la instancia se almacenan de forma separada.
Por ejemplo, WordPress tiene un app.kubernetes.io/name
igual a wordpress
mientras que
tiene un nombre de instancia, representado como app.kubernetes.io/instance
con un valor de
wordpress-abcxzy
. Esto permite identificar tanto a la aplicación como a sus instancias.
Cada instancia de una aplicación tiene su propio nombre único.
Ejemplos
Para ilustrar las diferentes formas en que se puede utilizar las etiquetas, los siguientes ejemplos presentan distintas complejidades.
Un Servicio Simple sin Estado
Considera el caso de un servicio simple sin estado desplegado mediante el uso de un objeto Deployment
y Service
. Los dos siguientes extractos de código representan cómo usar las etiquetas de la forma más sencilla.
El objeto Deployment
se utiliza para supervisar los pods que ejecutan la propia aplicación.
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: myservice
app.kubernetes.io/instance: myservice-abcxzy
...
El objeto Service
se utiliza para exponer la aplicación.
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: myservice
app.kubernetes.io/instance: myservice-abcxzy
...
Aplicación Web con una Base de Datos
Considera una aplicación un poco más complicada: una aplicación web (WordPress) que utiliza una base de datos (MySQL), instalada utilizando Helm. Los siguientes extractos de código ilustran la parte inicial de los objetos utilizados para desplegar esta aplicación.
El comienzo del objeto Deployment
siguiente se utiliza para WordPress:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: wordpress
app.kubernetes.io/instance: wordpress-abcxzy
app.kubernetes.io/version: "4.9.4"
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: server
app.kubernetes.io/part-of: wordpress
...
El objeto Service
se emplea para exponer WordPress:
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: wordpress
app.kubernetes.io/instance: wordpress-abcxzy
app.kubernetes.io/version: "4.9.4"
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: server
app.kubernetes.io/part-of: wordpress
...
MySQL se expone como un objeto StatefulSet
con metadatos tanto para sí mismo como para la aplicación global que lo contiene:
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/instance: wordpress-abcxzy
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: database
app.kubernetes.io/part-of: wordpress
app.kubernetes.io/version: "5.7.21"
...
El objeto Service
se usa para exponer MySQL como parte de WordPress:
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/instance: wordpress-abcxzy
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: database
app.kubernetes.io/part-of: wordpress
app.kubernetes.io/version: "5.7.21"
...
Con los objetos StatefulSet
y Service
de MySQL te darás cuenta que se incluye la información acerca de MySQL y Wordpress, la aplicación global.