Tareas

Esta sección de la documentación de Kubernetes contiene páginas que muestran cómo acometer tareas individuales. Cada página de tarea muestra cómo realizar una única cosa, típicamente proporcionando una pequeña secuencia de comandos.

Interfaz Web de Usuario (Tablero de Control)

Despliega y accede al interfaz web de usuario del Tablero de Control para ayudarte en la gestión y monitorización de las aplicaciones en contenedores de tu clúster de Kubenertes.

Usar la línea de comandos con kubectl

Instala y configura la herramienta de línea de comandos kubectl para gestionar de forma directa tus clústers de Kubernetes.

Configurar Pods y Contenedores

Realiza tareas comunes de configuración para tus Pods y Contenedores.

Ejecutar Aplicaciones

Realiza tareas comunes de gestión de aplicaciones, como actualizaciones de lanzamiento, inyectar información en los pods, y auto-escalado horizontal de pods.

Ejecutar Jobs

Ejecuta Jobs usando procesado paralelo.

Acceder a las Aplicaciones de un Clúster

Configura el balanceo de carga, re-envío de puertos, o configura el cortafuegos o las configuraciones de DNS para acceder a las aplicaciones en un clúster.

Monitorización, Trazas, y Depuración

Configura la monitorización y las trazas para identificar problemas en un clúster o depurar una aplicación en un contenedor.

Acceder a la API de Kubernetes

Aprende varios métodos para acceder directamente a la API de Kubernetes.

Usar TLS

Configura tu aplicación para que confíe y use el Certificado de Autoridad (CA) raíz de tu clúster.

Administrar un Clúster

Aprende tareas comunes de administración de un clúster.

Administrar la Federación

Configura componentes en una federación de clústers.

Gestionar Aplicaciones con Estado

Realiza tareas comunes de gestión de aplicaciones con estado, incluyendo escalado, borrado y depuración de StatefulSets.

Daemons del Clúster

Realiza tareas comunes de gestión de un DaemonSet, como llevar a cabo una actualización de lanzamiento.

Gestionar GPUs

Configura y planifica GPUs de NVIDIA para hacerlas disponibles como recursos a los nodos de un clúster.

Gestionar HugePages

Configura y planifica HugePages como un recurso planificado en un clúster.

Siguientes pasos

Si quisieras escribir una página de Tareas, echa un vistazo a Crear una Petición de Subida de Documentación.

1 - Instalar herramientas

Configurar las herramientas de Kubernetes en su computadora.

kubectl

Usa la herramienta de línea de comandos de Kubernetes, kubectl, para desplegar y gestionar aplicaciones en Kubernetes. Usando kubectl, puedes inspeccionar recursos del clúster; crear, eliminar, y actualizar componentes; explorar tu nuevo clúster y arrancar aplicaciones.

Ver Instalar y Configurar kubectl para más información sobre cómo descargar y instalar kubectl y configurarlo para acceder su clúster.

Ver la guía de instalación y configuración de kubectl

También se puede leer la documentación de referencia de kubectl.

kind

kind le permite usar Kubernetes en su máquina local. Esta herramienta require que Docker instalado y configurado.

En la página de inicio rápido encontrarás toda la información necesaria para empezar con kind.

Ver la guía de inicio rápido

minikube

De forma similar a kind, minikube es una herramienta que le permite usar Kubernetes en su máquina local. minikube le permite ejecutar un único nodo en su computadora personal (PC de Windows, macOS y Linux) para que se pueda probar Kubernetes, o para su trabajo de desarrollo.

Se puede seguir la guía oficial de minikube si su enfoque esta instalando la herramienta.

Ver la guía de minikube

Una vez minikube ha terminado de instalarse, está lista para desplegar un aplicación de ejemplo (/docs/tutorials/hello-minikube/).

kubeadm

Se puede usar la utilidad kubeadm para crear y gestionar clústeres de Kubernetes.

En instalando kubeadm se muestra como instalar kubeadm. Una vez instalado, se puede utilizar para crear un clúster.

Ver la guía de instalación

1.1 - Instalar y Configurar kubectl

Usa la herramienta de línea de comandos de Kubernetes, kubectl, para desplegar y gestionar aplicaciones en Kubernetes. Usando kubectl, puedes inspeccionar recursos del clúster; crear, eliminar, y actualizar componentes; explorar tu nuevo clúster; y arrancar aplicaciones de ejemplo. Para ver la lista completa de operaciones de kubectl, se puede ver el resumen de kubectl.

Antes de empezar

Debes usar una versión de kubectl que esté a menos de una versión menor de diferencia con tu clúster. Por ejemplo, un cliente v1.2 debería funcionar con un máster v1.1, v1.2, y v1.3. Usar la última versión de kubectl ayuda a evitar problemas inesperados.

Instalar kubectl en Linux

Instalar el binario de kubectl con curl en Linux

  1. Descargar la última entrega:

    curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl"
    

Para descargar una versión específica, remplaza el comando $(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt) con la versión específica.

Por ejemplo, para descarga la versión v1.23.0 en Linux, teclea:

```
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.23.0/bin/linux/amd64/kubectl
```
  1. Habilita los permisos de ejecución del binario kubectl.

    chmod +x ./kubectl
    
  2. Mueve el binario dentro de tu PATH.

    sudo mv ./kubectl /usr/local/bin/kubectl
    
  3. Comprueba que la versión que se ha instalado es la más reciente.

    kubectl version --client
    

Instalar mediante el gestor de paquetes del sistema


sudo apt-get update && sudo apt-get install -y apt-transport-https gnupg2 curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubectl

cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
sudo yum install -y kubectl

Instalar usando otro gestor de paquetes

Si usas Ubuntu o alguna de las otras distribuciones de Linux que soportan el gestor de paquetes snap, kubectl está disponible como una aplicación snap.

snap install kubectl --classic

kubectl version --client

Si usas alguna de las otras distribuciones de Linux que soportan el gestor de paquetes Homebrew, kubectl está disponible como una aplicación de [Homebrew]((https://docs.brew.sh/Homebrew-on-Linux#install).

brew install kubectl

kubectl version --client

Instalar kubectl en macOS

Instalar el binario de kubectl usando curl en macOS

  1. Descarga la última entrega:

    curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl"
    

    Para descargar una versión específica, remplaza el comando $(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt) con la versión específica.

    Por ejemplo, para descargar la versión v1.23.0 en macOS, teclea:

 curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.23.0/bin/darwin/amd64/kubectl
  1. Habilita los permisos de ejecución del binario kubectl.

    chmod +x ./kubectl
    
  2. Mueve el binario dentro de tu PATH.

    sudo mv ./kubectl /usr/local/bin/kubectl
    
  3. Para asegurar que la versión utilizada sea la más actual puedes probar:

    kubectl version --client
    

Instalar con Homebrew en macOS

Si estás usando macOS y el gestor de paquetes es Homebrew, puedes instalar kubectl con brew.

  1. Ejecuta el comando de instalación:

    brew install kubectl
    

    o

    brew install kubernetes-cli
    
  2. Para asegurar que la versión utilizada sea la más actual, puedes ejecutar:

    kubectl version --client
    

Instalar con Macports en macOS

Si estás en macOS y utilizas el gestor de paquetes Macports, puedes instalar kubectl con port.

  1. Ejecuta los comandos de instalación:

    sudo port selfupdate
    sudo port install kubectl
    
  2. Para asegurar que la versión utilizada sea la más actual puedes ejecutar:

    kubectl version --client
    

Instalar kubectl en Windows

Instalar el binario de kubectl con curl en Windows

  1. Descargar la última entrega v1.23.0 de este link.

    o si tiene curl instalada, utiliza este comando:

    curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.23.0/bin/windows/amd64/kubectl.exe
    

    Para averiguar la última versión estable (por ejemplo, para secuencias de comandos), echa un vistazo a https://storage.googleapis.com/kubernetes-release/release/stable.txt.

  2. Añade el binario a tu PATH.

  3. Para asegurar que la versión utilizada sea la más actual, puedes ejecutar:

    kubectl version --client
    

Instalar con Powershell desde PSGallery

Si estás en Windows y utilizas el gestor de paquetes Powershell Gallery, puedes instalar y actualizar kubectl con Powershell.

  1. Ejecuta los comandos de instalación (asegurándote de especificar una DownloadLocation):

    Install-Script -Name 'install-kubectl' -Scope CurrentUser -Force
    install-kubectl.ps1 [-DownloadLocation <path>]
    

    El instalador crea $HOME/.kube y crea un archivo de configuración

  2. Para asegurar que la versión utilizada sea la más actual puedes probar:

    kubectl version --client
    

Instalar en Windows usando Chocolatey o scoop

  1. Para instalar kubectl en Windows puedes usar el gestor de paquetes Chocolatey o el instalador de línea de comandos scoop.

    Using Chocolatey.

    ```powershell
    choco install kubernetes-cli
    ```
    

    Using scoop.

    ```powershell
    scoop install kubectl
    ```
    
  2. Para asegurar que la versión utilizada sea la más actual puedes probar:

    kubectl version --client
    
  3. Navega a tu directorio de inicio:

    # Si estas usando cmd.exe, ejecuta: cd %USERPROFILE%
    cd ~
    
  4. Crea el directorio .kube:

    mkdir .kube
    
  5. Cambia al directorio .kube que acabas de crear:

    cd .kube
    
  6. Configura kubectl para usar un clúster remoto de Kubernetes:

    New-Item config -type file
    

Descarga como parte del Google Cloud SDK

Puedes instalar kubectl como parte del Google Cloud SDK.

  1. Instala el Google Cloud SDK.

  2. Ejecuta el comando de instalación de kubectl:

    gcloud components install kubectl
    
  3. Para asegurar que la versión utilizada sea la más actual puedes probar:

    kubectl version --client
    

Comprobar la configuración kubectl

Para que kubectl pueda encontrar y acceder a un clúster de Kubernetes, necesita un fichero kubeconfig, que se crea de forma automática cuando creas un clúster usando kube-up.sh o despliegas de forma satisfactoria un clúster de Minikube. Revisa las guías para comenzar para más información acerca de crear clústers. Si necesitas acceso a un clúster que no has creado, ver el documento de Compartir Acceso a un Clúster. Por defecto, la configuración de kubectl se encuentra en ~/.kube/config.

Comprueba que kubectl está correctamente configurado obteniendo el estado del clúster:

kubectl cluster-info

Si ves una respuesta en forma de URL, kubectl está correctamente configurado para acceder a tu clúster.

Si ves un mensaje similar al siguiente, kubectl no está correctamente configurado o no es capaz de conectar con un clúster de Kubernetes.

The connection to the server <server-name:port> was refused - did you specify the right host or port?

Por ejemplo, si intentas ejecutar un clúster de Kubernetes en tu portátil (localmente), necesitarás una herramienta como minikube que esté instalada primero y entonces volver a ejecutar los comandos indicados arriba.

Si kubectl cluster-info devuelve la respuesta en forma de url, pero no puedes acceder a tu clúster, para comprobar si está configurado adecuadamente, usa:

kubectl cluster-info dump

kubectl configuraciones opcionales

Habilitar el auto-completado en el intérprete de comandos

kubectl provee de soporte para auto-completado para Bash y Zsh, ¡que te puede ahorrar mucho uso del teclado!

Abajo están los procedimientos para configurar el auto-completado para Bash (incluyendo la diferencia entre Linux y macOS) y Zsh.

Introducción

La secuencia de comandos de completado de kubectl para Bash puede ser generado con el comando kubectl completion bash. Corriendo la secuencia de comandos de completado en tu intérprete de comandos habilita el auto-completado de kubectl.

Sin embargo, la secuencia de comandos de completado depende de bash-completion*, lo que significa que tienes que instalar primero este programa (puedes probar si ya tienes bash-completion instalado ejecutando type _init_completion).

Instalar bash-completion

bash-completion es ofrecido por muchos gestores de paquetes (ver aquí). Puedes instalarlo con apt-get install bash-completion o yum install bash-completion, etc.

Los comandos de arriba crean /usr/share/bash-completion/bash_completion, que es la secuencia de comandos principal de bash-completion. Dependiendo de tu gestor de paquetes, tienes que correr manualmente este archivo en tu ~/.bashrc.

Para averiguarlo, recarga tu intérprete de comandos y ejecuta type _init_completion. Si el comando tiene éxito, ya has terminado; si no, añade lo siguiente a tu ~/.bashrc:

source /usr/share/bash-completion/bash_completion

recarga tu intérprete de comandos y verifica que bash-completion está correctamente instalado tecleando type _init_completion.

Habilitar el auto-completado de kubectl

Debes asegurarte que la secuencia de comandos de completado de kubectl corre en todas tus sesiones de tu intérprete de comandos. Hay dos formas en que puedes hacer esto:

  • Corre la secuencia de comandos de completado en tu ~/.bashrc:

    echo 'source <(kubectl completion bash)' >>~/.bashrc
    
  • Añade la secuencia de comandos de completado al directorio /etc/bash_completion.d:

    kubectl completion bash >/etc/bash_completion.d/kubectl
    

Si tienes un alias para kubectl, puedes extender los comandos de shell para funcionar con ese alias:

echo 'alias k=kubectl' >>~/.bashrc
echo 'complete -F __start_kubectl k' >>~/.bashrc

Ambas estrategias son equivalentes. Tras recargar tu intérprete de comandos, el auto-completado de kubectl debería estar funcionando.

Introducción

La secuencia de comandos de completado de kubectl para Bash puede generarse con el comando kubectl completion bash. Corriendo la secuencia de comandos de completado en tu intérprete de comandos habilita el auto-completado de kubectl.

Sin embargo, la secuencia de comandos de completado depende de bash-completion*, lo que significa que tienes que instalar primero este programa (puedes probar si ya tienes bash-completion instalado ejecutando type _init_completion).

Actualizar bash

Las instrucciones asumen que usa Bash 4.1+. Puedes comprobar tu versión de bash con:

echo $BASH_VERSION

Si no es 4.1+, puede actualizar bash con Homebrew:

brew install bash

Recarga tu intérprete de comandos y verifica que estás usando la versión deseada:

echo $BASH_VERSION $SHELL

Usualmente, Homebrew lo instala en /usr/local/bin/bash.

Instalar bash-completion

Puedes instalar bash-completion con Homebrew:

brew install bash-completion@2

Como se indicaba en la salida de brew install (sección "Caveats"), añade las siguientes líneas a tu ~/.bashrc o ~/.bash_profile:

export BASH_COMPLETION_COMPAT_DIR="/usr/local/etc/bash_completion.d"
[[ -r "/usr/local/etc/profile.d/bash_completion.sh" ]] && . "/usr/local/etc/profile.d/bash_completion.sh"

Recarga tu intérprete de comandos y verifica que bash-completion está correctamente instalado tecleando type _init_completion.

Habilitar el auto-completado de kubectl

Debes asegurarte que la secuencia de comandos de completado de kubectl corre en todas tus sesiones de tu intérprete de comenados. Hay múltiples formas en que puedes hacer esto:

  • Corre la secuencia de comandos de completado en tu ~/.bashrc:

    echo 'source <(kubectl completion bash)' >>~/.bashrc
    
    
  • Añade la secuencia de comandos de completado al directorio /usr/local/etc/bash_completion.d:

    kubectl completion bash >/usr/local/etc/bash_completion.d/kubectl
    
  • Si has instalado kubectl con Homebrew (como se explica aquí), entonces la secuencia de comandos de completado se instaló automáticamente en /usr/local/etc/bash_completion.d/kubectl. En este caso, no tienes que hacer nada.

Todas las estrategias son equivalentes. Tras recargar tu intérprete de comandos, el auto-completado de kubectl debería funcionar.

La secuencia de comandos de completado de kubectl para Zsh puede ser generada con el comando kubectl completion zsh. Corriendo la secuencia de comandos de completado en tu intérprete de comandos habilita el auto-completado de kubectl.

Para hacerlo en todas tus sesiones de tu intérprete de comandos, añade lo siguiente a tu ~/.zshrc:

source <(kubectl completion zsh)

Si tienes alias para kubectl, puedes extender el completado de intérprete de comandos para funcionar con ese alias.

echo 'alias k=kubectl' >>~/.zshrc
echo 'compdef __start_kubectl k' >>~/.zshrc

Tras recargar tu intérprete de comandos, el auto-completado de kubectl debería funcionar.

Si obtienes un error como complete:13: command not found: compdef, entonces añade lo siguiente al principio de tu ~/.zshrc:

autoload -Uz compinit
compinit

Siguientes pasos

2 - Administrar un clúster

2.1 - Administrar un clúster con kubeadm

2.2 - Administrar recursos de memoria, CPU y API

2.3 - Instalar un proveedor de políticas de red

3 - Configurar pods y contenedores

3.1 - Configura un Pod para Usar un Volume como Almacenamiento

En esta página se muestra cómo configurar un Pod para usar un Volume (volumen) como almacenamiento.

El sistema de ficheros de un Contenedor existe mientras el Contenedor exista. Por tanto, cuando un Contenedor es destruido o reiniciado, los cambios realizados en el sistema de ficheros se pierden. Para un almacenamiento más consistente que sea independiente del ciclo de vida del Contenedor, puedes usar un Volume. Esta característica es especialmente importante para aplicaciones que deben mantener un estado, como motores de almacenamiento clave-valor (por ejemplo Redis) y bases de datos.

Antes de empezar

Debes tener un cluster Kubernetes a tu dispocición, y la herramienta de línea de comandos kubectl debe estar configurada. Si no tienes un cluster, puedes crear uno utilizando Minikube, o puedes utilizar una de las siguientes herramientas en línea:

Para comprobar la versión, introduzca kubectl version.

Configura un Volume para un Pod

En este ejercicio crearás un Pod que ejecuta un único Contenedor. Este Pod tiene un Volume de tipo emptyDir (directorio vacío) que existe durante todo el ciclo de vida del Pod, incluso cuando el Contenedor es destruido y reiniciado. Aquí está el fichero de configuración del Pod:

apiVersion: v1
kind: Pod
metadata:
  name: redis
spec:
  containers:
  - name: redis
    image: redis
    volumeMounts:
    - name: redis-storage
      mountPath: /data/redis
  volumes:
  - name: redis-storage
    emptyDir: {}
  1. Crea el Pod:

    kubectl apply -f https://k8s.io/examples/pods/storage/redis.yaml
    
  2. Verifica que el Contenedor del Pod se está ejecutando y después observa los cambios en el Pod

    kubectl get pod redis --watch
    

    La salida debería ser similar a:

    NAME      READY     STATUS    RESTARTS   AGE
    redis     1/1       Running   0          13s
    
  3. En otro terminal, abre una sesión interactiva dentro del Contenedor que se está ejecutando:

    kubectl exec -it redis -- /bin/bash
    
  4. En el terminal, ve a /data/redis y crea un fichero:

    root@redis:/data# cd /data/redis/
    root@redis:/data/redis# echo Hello > test-file
    
  5. En el terminal, lista los procesos en ejecución:

    root@redis:/data/redis# apt-get update
    root@redis:/data/redis# apt-get install procps
    root@redis:/data/redis# ps aux
    

    La salida debería ser similar a:

    USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
    redis        1  0.1  0.1  33308  3828 ?        Ssl  00:46   0:00 redis-server *:6379
    root        12  0.0  0.0  20228  3020 ?        Ss   00:47   0:00 /bin/bash
    root        15  0.0  0.0  17500  2072 ?        R+   00:48   0:00 ps aux
    
  6. En el terminal, mata el proceso de Redis:

    root@redis:/data/redis# kill <pid>
    

    donde <pid> es el ID de proceso (PID) de Redis.

  7. En el terminal original, observa los cambios en el Pod de Redis. Eventualmente verás algo como lo siguiente:

    NAME      READY     STATUS     RESTARTS   AGE
    redis     1/1       Running    0          13s
    redis     0/1       Completed  0         6m
    redis     1/1       Running    1         6m
    

En este punto, el Contenedor ha sido destruido y reiniciado. Esto es debido a que el Pod de Redis tiene una restartPolicy (política de reinicio) de Always (siempre).

  1. Abre un terminal en el Contenedor reiniciado:

    kubectl exec -it redis -- /bin/bash
    
  2. En el terminal, ve a /data/redis y verifica que test-file todavía existe:

    root@redis:/data/redis# cd /data/redis/
    root@redis:/data/redis# ls
    test-file
    
  3. Elimina el Pod que has creado para este ejercicio:

    kubectl delete pod redis
    

Siguientes pasos

  • Revisa Volume.

  • Revisa Pod.

  • Además del almacenamiento local proporcionado por emptyDir, Kubernetes soporta diferentes tipos de soluciones de almacenamiento por red, incluyendo los discos gestionados de los diferentes proveedores cloud, como por ejemplo los Persistent Disks en Google Cloud Platform o el Elastic Block Storage de Amazon Web Services. Este tipo de soluciones para volúmenes son las preferidas para el almacenamiento de datos críticos. Kubernetes se encarga de todos los detalles, tal como montar y desmontar los dispositivos en los nodos del clúster. Revisa Volumes para obtener más información.

4 - Administrar Objetos en Kubernetes

Interactuando con el API de Kubernetes aplicando paradigmas declarativo e imperativo.

4.1 - Administración declarativa de Objetos en Kubernetes usando archivos de Configuración

Objetos en Kubernetes pueden ser creados, actualizados y eliminados utilizando archivos de configuración almacenados en un directorio. Usando el comando kubectl apply podrá crearlos o actualizarlos de manera recursiva según sea necesario. Este método retiene cualquier escritura realizada contra objetos activos en el sistema sin unirlos de regreso a los archivos de configuración. kubectl diff le permite visualizar de manera previa los cambios que apply realizará.

Antes de empezar

Instale kubectl.

Debes tener un cluster Kubernetes a tu dispocición, y la herramienta de línea de comandos kubectl debe estar configurada. Si no tienes un cluster, puedes crear uno utilizando Minikube, o puedes utilizar una de las siguientes herramientas en línea:

Para comprobar la versión, introduzca kubectl version.

Modos de administración

La herramienta kubectl soporta tres modos distintos para la administración de objetos:

  • Comandos imperativos
  • Configuración de objetos imperativa
  • Configuración de objetos declarativa

Acceda Administración de objetos de Kubernetes para una discusión de las ventajas y desventajas de cada modo distinto de administración.

Visión general

La configuración de objetos declarativa requiere una comprensión firme de la definición y configuración de objetos de Kubernetes. Si aún no lo ha hecho, lea y complete los siguientes documentos:

A continuación la definición de términos usados en este documento:

  • archivo de configuración de objeto / archivo de configuración: Un archivo en el que se define la configuración de un objeto de Kubernetes. Este tema muestra como utilizar archivos de configuración con kubectl apply. Los archivos de configuración por lo general se almacenan en un sistema de control de versiones, como Git.
  • configuración activa de objeto / configuración activa: Los valores de configuración activos de un objeto, según estén siendo observados por el Clúster. Esta configuración se almacena en el sistema de almacenamiento de Kubernetes, usualmente etcd.
  • escritor de configuración declarativo / escritor declarativo: Una persona o componente de software que actualiza a un objeto activo. Los escritores activos a los que se refiere este tema aplican cambios a los archivos de configuración de objetos y ejecutan kubectl apply para aplicarlos.

Como crear objetos

Utilice kubectl apply para crear todos los objetos definidos en los archivos de configuración existentes en un directorio específico, con excepción de aquellos que ya existen:

kubectl apply -f <directorio>/

Esto definirá la anotación kubectl.kubernetes.io/last-applied-configuration: '{...}' en cada objeto. Esta anotación contiene el contenido del archivo de configuración utilizado para la creación del objeto.

El siguiente es un ejemplo de archivo de configuración para un objeto:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  minReadySeconds: 5
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

Ejecute kubectl diff para visualizar el objeto que será creado:

kubectl diff -f https://k8s.io/examples/application/simple_deployment.yaml

Cree el objeto usando kubectl apply:

kubectl apply -f https://k8s.io/examples/application/simple_deployment.yaml

Despliegue la configuración activa usando kubectl get:

kubectl get -f https://k8s.io/examples/application/simple_deployment.yaml -o yaml

La salida le mostrará que la anotación kubectl.kubernetes.io/last-applied-configuration fue escrita a la configuración activa, y es consistente con los contenidos del archivo de configuración:

kind: Deployment
metadata:
  annotations:
    # ...
    # Esta es la representación JSON de simple_deployment.yaml
    # Fue escrita por kubectl apply cuando el objeto fue creado
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"apps/v1","kind":"Deployment",
      "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
      "spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
      "spec":{"containers":[{"image":"nginx:1.14.2","name":"nginx",
      "ports":[{"containerPort":80}]}]}}}}      
  # ...
spec:
  # ...
  minReadySeconds: 5
  selector:
    matchLabels:
      # ...
      app: nginx
  template:
    metadata:
      # ...
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.14.2
        # ...
        name: nginx
        ports:
        - containerPort: 80
        # ...
      # ...
    # ...
  # ...

Como actualizar objetos

También puede usar kubectl apply para actualizar los objetos definidos en un directorio, aún cuando esos objetos ya existan en la configuración activa. Con este enfoque logrará lo siguiente:

  1. Definir los campos que aparecerán en la configuración activa.
  2. Eliminar aquellos campos eliminados en el archivo de configuración, de la configuración activa.
kubectl diff -f <directorio>/
kubectl apply -f <directorio>/

Este es un ejemplo de archivo de configuración:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  minReadySeconds: 5
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

Cree el objeto usando kubectl apply:

kubectl apply -f https://k8s.io/examples/application/simple_deployment.yaml

Despliegue la configuración activa usando kubectl get:

kubectl get -f https://k8s.io/examples/application/simple_deployment.yaml -o yaml

La salida le mostrará que la anotación kubectl.kubernetes.io/last-applied-configuration fue escrita a la configuración activa, y es consistente con los contenidos del archivo de configuración:

kind: Deployment
metadata:
  annotations:
    # ...
    # Esta es la representación JSON de simple_deployment.yaml
    # Fue escrita por kubectl apply cuando el objeto fue creado
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"apps/v1","kind":"Deployment",
      "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
      "spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
      "spec":{"containers":[{"image":"nginx:1.14.2","name":"nginx",
      "ports":[{"containerPort":80}]}]}}}}      
  # ...
spec:
  # ...
  minReadySeconds: 5
  selector:
    matchLabels:
      # ...
      app: nginx
  template:
    metadata:
      # ...
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.14.2
        # ...
        name: nginx
        ports:
        - containerPort: 80
        # ...
      # ...
    # ...
  # ...

De manera directa, actualice el campo replicas en la configuración activa usando kubectl scale. En este caso no se usa kubectl apply:

kubectl scale deployment/nginx-deployment --replicas=2

Despliegue la configuración activa usando kubectl get:

kubectl get deployment nginx-deployment -o yaml

La salida le muestra que el campo replicas ha sido definido en 2, y que la anotación last-applied-configuration no contiene el campo replicas:

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    # ...
    # note que la anotación no contiene replicas
    # debido a que el objeto no fue actualizado usando apply
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"apps/v1","kind":"Deployment",
      "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
      "spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
      "spec":{"containers":[{"image":"nginx:1.14.2","name":"nginx",
      "ports":[{"containerPort":80}]}]}}}}      
  # ...
spec:
  replicas: 2 # definido por scale
  # ...
  minReadySeconds: 5
  selector:
    matchLabels:
      # ...
      app: nginx
  template:
    metadata:
      # ...
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.14.2
        # ...
        name: nginx
        ports:
        - containerPort: 80
      # ...

Actualice el archivo de configuración simple_deployment.yaml para cambiar el campo image de nginx:1.14.2 a nginx:1.16.1, y elimine el campo minReadySeconds:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.16.1 # actualice el valor de image
        ports:
        - containerPort: 80

Aplique los cambios realizados al archivo de configuración:

kubectl diff -f https://k8s.io/examples/application/update_deployment.yaml
kubectl apply -f https://k8s.io/examples/application/update_deployment.yaml

Despliegue la configuración activa usando kubectl get:

kubectl get -f https://k8s.io/examples/application/update_deployment.yaml -o yaml

La salida le mostrará los siguientes cambios hechos a la configuración activa:

  • El campo replicas retiene el valor de 2 definido por kubectl scale. Esto es posible ya que el campo fue omitido en el archivo de configuración.
  • El campo image ha sido actualizado de nginx:1.16.1 a nginx:1.14.2.
  • La anotación last-applied-configuration ha sido actualizada con la nueva imagen.
  • El campo minReadySeconds ha sido despejado.
  • La anotación last-applied-configuration ya no contiene el campo minReadySeconds
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    # ...
    # La anotación contiene la imagen acutalizada a nginx 1.11.9,
    # pero no contiene la actualización de las replicas a 2
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"apps/v1","kind":"Deployment",
      "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
      "spec":{"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
      "spec":{"containers":[{"image":"nginx:1.16.1","name":"nginx",
      "ports":[{"containerPort":80}]}]}}}}      
    # ...
spec:
  replicas: 2 # Definido por `kubectl scale`.  Ignorado por `kubectl apply`.
  # minReadySeconds fue despejado por `kubectl apply`
  # ...
  selector:
    matchLabels:
      # ...
      app: nginx
  template:
    metadata:
      # ...
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.16.1 # Definido `kubectl apply`
        # ...
        name: nginx
        ports:
        - containerPort: 80
        # ...
      # ...
    # ...
  # ...

Como eliminar objetos

Hay dos opciones diferentes para eliminar objetos gestionados por kubectl apply.

Manera recomendada: kubectl delete -f <archivo>

La manera recomendada de eliminar objetos de manera manual es utilizando el comando imperativo, ya que es más explícito en relación a lo que será eliminado, y es menos probable que resulte en algo siendo eliminado sin la intención del usuario.

kubectl delete -f <archivo>

Manera alternativa: kubectl apply -f <directorio/> --prune -l etiqueta=deseada

Únicamente utilice esta opción si está seguro de saber lo que está haciendo.

Como una alternativa a kubectl delete, puede usar kubectl apply para identificar objetos a ser eliminados, luego de que sus archivos de configuración han sido eliminados del directorio. El commando apply con --prune consulta a la API del servidor por todos los objetos que coincidan con un grupo de etiquetas, e intenta relacionar la configuración obtenida de los objetos activos contra los objetos según sus archivos de configuración. Si un objeto coincide con la consulta, y no tiene un archivo de configuración en el directorio, pero si tiene una anotación last-applied-configuration, entonces será eliminado.

kubectl apply -f <directorio/> --prune -l <etiquetas>

Como visualizar un objeto

Puede usar kubectl get con -o yaml para ver la configuración de objetos activos:

kubectl get -f <archivo|url> -o yaml

Como son las diferencias calculadas y unidas por apply

Cuando kubectl apply actualiza la configuración activa para un objeto, lo hace enviando una solicitud de patch al servidor de API. El patch define actualizaciones para campos específicos en la configuración del objeto activo. El comando kubectl apply calcula esta solicitud de patch usando el archivo de configuración, la configuración activa, y la anotación last-applied-configuration almacenada en la configuración activa.

Calculando la unión de un patch

El comando kubectl apply escribe los contenidos de la configuración a la anotación kubectl.kubernetes.io/last-applied-configuration. Esto es usado para identificar aquellos campos que han sido eliminados de la configuración y deben ser limpiados. Los siguientes pasos son usados para calcular que campos deben ser eliminados o definidos:

  1. Calculo de campos por eliminar. Estos son los campos presentes en last-applied-configuration pero ausentes en el archivo de configuración.
  2. Calculo de campos por agregar o definir. Estos son los campos presentes en el archivo de configuración, con valores inconsistentes con la configuración activa.

A continuación un ejemplo. Suponga que este es el archivo de configuración para un objeto de tipo Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.16.1 # actualice el valor de image
        ports:
        - containerPort: 80

También, suponga que esta es la configuración activa para ese mismo objeto de tipo Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    # ...
    # tome nota de que la anotación no contiene un valor para replicas
    # dado que no fue actualizado usando el comando apply
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"apps/v1","kind":"Deployment",
      "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
      "spec":{"minReadySeconds":5,"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
      "spec":{"containers":[{"image":"nginx:1.14.2","name":"nginx",
      "ports":[{"containerPort":80}]}]}}}}      
  # ...
spec:
  replicas: 2 # definidas por scale
  # ...
  minReadySeconds: 5
  selector:
    matchLabels:
      # ...
      app: nginx
  template:
    metadata:
      # ...
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.14.2
        # ...
        name: nginx
        ports:
        - containerPort: 80
      # ...

Estos son los cálculos de unión que serían realizados por kubectl apply:

  1. Calcular los campos por eliminar, leyendo los valores de last-applied-configuration y comparándolos con los valores en el archivo de configuración. Limpiar los campos definidos en null de manera explícita en el archivo de configuración sin tomar en cuenta si se encuentran presentes en la anotación last-applied-configuration. En este ejemplo, minReadySeconds aparece en la anotación last-applied-configuration pero no aparece en el archivo de configuración. Acción: Limpiar minReadySeconds de la configuración activa.
  2. Calcular los campos por ser definidos, al leer los valores del fichero de configuración y compararlos con los valores en la configuración activa. En este ejemplo, el valor image en el archivo de configuración, no coincide con el valor en la configuración activa. Acción: Definir el campo image en la configuración activa.
  3. Definir el valor de la anotación last-applied-configuration para que sea consistente con el archivo de configuración.
  4. Unir los resultados de 1, 2 y 3, en una única solicitud de patch para enviar al servidor de API.

Esta es la configuración activa como resultado de esta unión:

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    # ...
    # La anotación contiene la imágen actualizada a nginx 1.11.9,
    # pero no contiene la actualización a 2 replicas
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"apps/v1","kind":"Deployment",
      "metadata":{"annotations":{},"name":"nginx-deployment","namespace":"default"},
      "spec":{"selector":{"matchLabels":{"app":nginx}},"template":{"metadata":{"labels":{"app":"nginx"}},
      "spec":{"containers":[{"image":"nginx:1.16.1","name":"nginx",
      "ports":[{"containerPort":80}]}]}}}}      
    # ...
spec:
  selector:
    matchLabels:
      # ...
      app: nginx
  replicas: 2 # Definido por `kubectl scale`.  Ignorado por `kubectl apply`.
  # minReadySeconds eliminado por `kubectl apply`
  # ...
  template:
    metadata:
      # ...
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.16.1 # Definido por `kubectl apply`
        # ...
        name: nginx
        ports:
        - containerPort: 80
        # ...
      # ...
    # ...
  # ...

Como se unen los diferentes tipos de campos

La manera en la que los campos en un archivo de configuración son unidos con la configuración activa depende del tipo de campo. Existen varios tipos de campos:

  • primitivo: Campos de cadena de texto (string), enteros (integer), o lógicos (boolean). Por ejemplo, image y replicas son campos de tipo primitivo. Acción: Reemplazarlos.

  • mapa, también llamados objeto: Campo de tipo mapa o un tipo complejo que contiene sub-campos. Por ejemplo, labels, annotations,spec y metadata son todos mapas. Acción: Unir los elementos o sub-campos.

  • lista: Campos que contienen una lista de elementos que pueden ser de tipo primitivo o mapa. Como ejemplos, containers, ports, y args son listas. Acción: Varía.

Cuando kubectl apply actualiza un campo de tipo mapa o lista, típicamente no reemplaza el campo completo, sino actualiza los sub-elementos individuales. Por ejemplo, cuando se hace una unión del campo spec en un Deployment, el spec completo no es reemplazado, por el contrario, únicamente los sub-campos de spec como replica son comparados y unidos.

Uniendo cambios en campos primitivos

Campos primitivos son limpiados o reemplazados.

Campo en el archivo de configuración Campo en la configuración activa Campo en last-applied-configuration Acción
Si Si - Define el valor en el archivo de configuración como activo.
Si No - Define el valor a la configuración local.
No - Si Elimina de la configuración activa.
No - No No hacer nada. Mantiene el valor activo.

Uniendo cambios en campos de un mapa

Los campos que conjuntamente representan un mapa, son unidos al comparar cada uno de los subcampos o elementos del mapa:

Propiedad en archivo de configuración Propiedad en configuración activa Campo en last-applied-configuration Acción
Si Si - Comparar valores de sub-propiedades.
Si No - Usar configuración local.
No - Si Eliminar de la configuración activa.
No - No No hacer nada. Mantener el valor activo.

Uniendo cambios en campos de tipo lista

El unir cambios en una lista utiliza una de tres posibles estrategias:

  • Reemplazar la lista si todos sus elementos son primitivos.
  • Unir elementos individuales en líneas de elementos complejos.
  • Unir una lista de elementos primitivos.

Se define la estrategia elegida con base en cada campo.

Reemplazar una lista si todos sus elementos son primitivos

Trata la lista como si fuese un campo primitivo. Reemplaza o elimina la lista completa. Esto preserva el orden de los elementos.

Ejemplo: Usando kubectl apply para actualizar el campo args de un Contenedor en un Pod. Esto define el valor de args en la configuración activa, al valor en el archivo de configuración. Cualquier elemento de args que haya sido previamente agregado a la configuración activa se perderá. El orden de los elementos definidos en args en el archivo de configuración, serán conservados en la configuración activa.

# valor en last-applied-configuration
    args: ["a", "b"]

# valores en archivo de configuración
    args: ["a", "c"]

# configuración activa
    args: ["a", "b", "d"]

# resultado posterior a la unión
    args: ["a", "c"]

Explicación: La unión utilizó los valores del archivo de configuración para definir los nuevos valores de la lista.

Unir elementos individuales en una lista de elementos complejos

Trata la lista como un mapa, y trata cada campo específico de cada elemento como una llave. Agrega, elimina o actualiza elementos individuales. Esta operación no conserva el orden.

Esta estrategia de unión utiliza una etiqueta especial en cada campo llamada patchMergeKey. La etiqueta patchMergeKey es definida para cada campo en el código fuente de Kubernetes: types.go Al unir una lista de mapas, el campo especificado en patchMergeKey para el elemento dado se utiliza como un mapa de llaves para ese elemento.

Ejemplo: Utilice kubectl apply para actualizar el campo containers de un PodSpec. Esto une la lista como si fuese un mapa donde cada elemento utiliza name por llave.

# valor en last-applied-configuration
    containers:
    - name: nginx
      image: nginx:1.16
    - name: nginx-helper-a # llave: nginx-helper-a; será eliminado en resultado
      image: helper:1.3
    - name: nginx-helper-b # llave: nginx-helper-b; será conservado
      image: helper:1.3

# valor en archivo de configuración
    containers:
    - name: nginx
      image: nginx:1.16
    - name: nginx-helper-b
      image: helper:1.3
    - name: nginx-helper-c # llavel: nginx-helper-c; será agregado en el resultado
      image: helper:1.3

# configuración activa
    containers:
    - name: nginx
      image: nginx:1.16
    - name: nginx-helper-a
      image: helper:1.3
    - name: nginx-helper-b
      image: helper:1.3
      args: ["run"] # Campo será conservado
    - name: nginx-helper-d # llave: nginx-helper-d; será conservado
      image: helper:1.3

# resultado posterior a la unión
    containers:
    - name: nginx
      image: nginx:1.16
      # Elemento nginx-helper-a fue eliminado
    - name: nginx-helper-b
      image: helper:1.3
      args: ["run"] # Campo fue conservado
    - name: nginx-helper-c # Elemento fue agregado
      image: helper:1.3
    - name: nginx-helper-d # Elemento fue ignorado
      image: helper:1.3

Explicación:

  • El contenedor llamado "nginx-helper-a" fué eliminado al no aparecer ningún contenedor llamado "nginx-helper-a" en el archivo de configuración.
  • El contenedor llamado "nginx-helper-b" mantiene los cambios existentes en args en la configuración activa. kubectl apply pudo identificar que el contenedor "nginx-helper-b" en la configuración activa es el mismo "nginx-helper-b" que aparece en el archivo de configuración, aún teniendo diferentes valores en los campos (no existe args en el archivo de configuración). Esto sucede debido a que el valor del campo patchMergeKey (name) es idéntico en ambos.
  • El contenedor llamado "nginx-helper-c" fue agregado ya que no existe ningún contenedor con ese nombre en la configuración activa, pero si existe uno con ese nombre en el archivo de configuración.
  • El contendor llamado "nginx-helper-d" fue conservado debido a que no aparece ningún elemento con ese nombre en last-applied-configuration.

Unir una lista de elementos primitivos

A partir de Kubernetes 1.5, el unir listas de elementos primitivos no es soportado.

Valores de campo por defecto

El Servidor de API define algunos campos a sus valores por defecto si no son especificados al momento de crear un objeto.

Aquí puede ver un archivo de configuración para un Deployment. Este archivo no especifica el campo strategy:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  minReadySeconds: 5
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

Cree un nuevo objeto kubectl apply:

kubectl apply -f https://k8s.io/examples/application/simple_deployment.yaml

Despliegue la configuración activa usando kubectl get:

kubectl get -f https://k8s.io/examples/application/simple_deployment.yaml -o yaml

La salida muestra que el servidor de API definió varios campos con los valores por defecto en la configuración activa. Estos campos no fueron especificados en el archivo de configuración.

apiVersion: apps/v1
kind: Deployment
# ...
spec:
  selector:
    matchLabels:
      app: nginx
  minReadySeconds: 5
  replicas: 1 # valor por defecto definido por apiserver
  strategy:
    rollingUpdate: # valor por defecto definido por apiserver - derivado de strategy.type
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate # valor por defecto definido por apiserver
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.14.2
        imagePullPolicy: IfNotPresent # valor por defecto definido por apiserver
        name: nginx
        ports:
        - containerPort: 80
          protocol: TCP # valor por defecto definido por apiserver
        resources: {} # valor por defecto definido por apiserver
        terminationMessagePath: /dev/termination-log # valor por defecto definido por apiserver
      dnsPolicy: ClústerFirst # valor por defecto definido por apiserver
      restartPolicy: Always # valor por defecto definido por apiserver
      securityContext: {} # valor por defecto definido por apiserver
      terminationGracePeriodSeconds: 30 # valor por defecto definido por apiserver
# ...

En una solicitud de patch, los campos definidos a valores por defecto no son redefinidos a excepción de cuando hayan sido limpiados de manera explícita como parte de la solicitud de patch. Esto puede causar comportamientos no esperados para campos cuyo valor por defecto es basado en los valores de otros campos. Cuando el otro campo ha cambiado, el valor por defecto de ellos no será actualizado de no ser que sean limpiados de manera explícita.

Por esta razón, se recomienda que algunos campos que reciben un valor por defecto del servidor sean definidos de manera explícita en los archivos de configuración, aun cuando el valor definido sea idéntico al valor por defecto. Esto facilita la identificación de valores conflictivos que podrían no ser revertidos a valores por defecto por parte del servidor.

Ejemplo:

# last-applied-configuration
spec:
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

# archivo de configuración
spec:
  strategy:
    type: Recreate # valor actualizado
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

# configuración activa
spec:
  strategy:
    type: RollingUpdate # valor por defecto
    rollingUpdate: # valor por defecto derivado del campo type
      maxSurge : 1
      maxUnavailable: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

# resultado posterior a la unión - ERROR!
spec:
  strategy:
    type: Recreate # valor actualizado: incompatible con RollingUpdate
    rollingUpdate: # valor por defecto: incompatible con "type: Recreate"
      maxSurge : 1
      maxUnavailable: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

Explicación:

  1. El usuario crea un Deployment sin definir strategy.type.
  2. El servidor define strategy.type a su valor por defecto de RollingUpdate y agrega los valores por defecto a strategy.rollingUpdate.
  3. El usuario cambia strategy.type a Recreate. Los valores de strategy.rollingUpdate se mantienen en su configuración por defecto, sin embargo el servidor espera que se limpien. Si los valores de strategy.rollingUpdate hubiesen sido definidos inicialmente en el archivo de configuración, hubiese sido más claro que requerían ser eliminados.
  4. Apply fallará debido a que strategy.rollingUpdate no fue eliminado. El campo strategy.rollingupdate no puede estar definido, si el valor de strategy.type es Recreate.

Recomendación: Estos campos deberían de ser definidos de manera explícita en el archivo de configuración:

  • Etiquetas de Selectors y PodTemplate en cargas de trabajo como Deployment, StatefulSet, Job, DaemonSet, ReplicaSet, y ReplicationController
  • Estrategia de rollout para un Deployment

Como limpiar campos definidos a valores por defecto por el servidor, o definidos por otros escritores

Campos que no aparecen en el archivo de configuración pueden ser limpiados si se define su valor a null y luego se aplica el archivo de configuración. Para los campos definidos a valores por defecto por el servidor, esto provoca que se reestablezca a sus valores por defecto.

Como cambiar al propietario de un campo entre un archivo de configuración y un escritor imperativo

Estos son los únicos métodos que debe usar para cambiar un campo individual de un objeto:

  • Usando kubectl apply.
  • Escribiendo de manera directa a la configuración activa sin modificar el archivo de configuración: por ejemplo, usando kubectl scale.

Cambiando al propietario de un campo de un escritor imperativo a un archivo de configuración

Añada el campo al archivo de configuración, y no realice nuevas actualizaciones a la configuración activa que no sucedan por medio de kubectl apply.

Cambiando al propietario de un archivo de configuración a un escritor imperativo

A partir de Kubernetes 1.5, el cambiar un campo que ha sido definido por medio de un archivo de configuración para que sea modificado por un escritor imperativo requiere pasos manuales:

  • Eliminar el campo del archivo de configuración.
  • Eliminar el campo de la anotación kubectl.kubernetes.io/last-applied-configuration en el objeto activo.

Cambiando los métodos de gestión

Los objetos en Kubernetes deberían de ser gestionados utilizando únicamente un método a la vez. El alternar de un método a otro es posible, pero es un proceso manual.

Migrando de gestión imperativa con comandos a configuración declarativa de objetos

El migrar de gestión imperativa utilizando comandos a la gestión declarativa de objetos requiere varios pasos manuales:

  1. Exporte el objeto activo a un archivo local de configuración:

    kubectl get <tipo>/<nombre> -o yaml > <tipo>_<nombre>.yaml
    
  2. Elimine de manera manual el campo status del archivo de configuración.

  3. Defina la anotación kubectl.kubernetes.io/last-applied-configuration en el objeto:

    kubectl replace --save-config -f <tipo>_<nombre>.yaml
    
  4. Modifique el proceso para usar kubectl apply para gestionar el objeto de manera exclusiva.

Migrando de gestión imperativa de la configuración de objetos a gestión declarativa

  1. Defina la anotación kubectl.kubernetes.io/last-applied-configuration en el objeto:

    kubectl replace --save-config -f <tipo>_<nombre>.yaml
    
  2. Modifique el proceso para usar kubectl apply para gestionar el objeto de manera exclusiva.

Definiendo los selectores para el controlador y las etiquetas de PodTemplate

La forma recomendada es definir una etiqueta única e inmutable para PodTemplate usada únicamente por el selector del controlador sin tener ningún otro significado semántico.

Ejemplo:

selector:
  matchLabels:
      controller-selector: "apps/v1/deployment/nginx"
template:
  metadata:
    labels:
      controller-selector: "apps/v1/deployment/nginx"

Siguientes pasos

5 - Inyectar datos en las aplicaciones

6 - Gestionar y ejecutar aplicaciones

6.1 - Corre una aplicación stateless usando un Deployment

Ésta página enseña como correr una aplicación stateless usando un deployment de Kubernetes.

Objetivos

  • Crear un deployment de nginx.
  • Usar kubectl para obtener información acerca del deployment.
  • Actualizar el deployment.

Antes de empezar

Debes tener un cluster Kubernetes a tu dispocición, y la herramienta de línea de comandos kubectl debe estar configurada. Si no tienes un cluster, puedes crear uno utilizando Minikube, o puedes utilizar una de las siguientes herramientas en línea:

Su versión de Kubernetes debe ser como mínimo v1.9. Para comprobar la versión, introduzca kubectl version.

Creando y explorando un nginx deployment

Puedes correr una aplicación creando un deployment de Kubernetes, y puedes describir el deployment en un fichero YAML. Por ejemplo, el siguiente fichero YAML describe un deployment que corre la imágen Docker nginx:1.7.9:

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
  1. Crea un deployment basado en el fichero YAML:

     kubectl apply -f https://k8s.io/examples/application/deployment.yaml
    
  2. Obtén información acerca del deployment:

     kubectl describe deployment nginx-deployment
    

    El resultado es similar a esto:

     Name:     nginx-deployment
     Namespace:    default
     CreationTimestamp:  Tue, 30 Aug 2016 18:11:37 -0700
     Labels:     app=nginx
     Annotations:    deployment.kubernetes.io/revision=1
     Selector:   app=nginx
     Replicas:   2 desired | 2 updated | 2 total | 2 available | 0 unavailable
     StrategyType:   RollingUpdate
     MinReadySeconds:  0
     RollingUpdateStrategy:  1 max unavailable, 1 max surge
     Pod Template:
       Labels:       app=nginx
       Containers:
        nginx:
         Image:              nginx:1.7.9
         Port:               80/TCP
         Environment:        <none>
         Mounts:             <none>
       Volumes:              <none>
     Conditions:
       Type          Status  Reason
       ----          ------  ------
       Available     True    MinimumReplicasAvailable
       Progressing   True    NewReplicaSetAvailable
     OldReplicaSets:   <none>
     NewReplicaSet:    nginx-deployment-1771418926 (2/2 replicas created)
     No events.
    
  3. Lista los pods creados por el deployment:

     kubectl get pods -l app=nginx
    

    El resultado es similar a esto:

     NAME                                READY     STATUS    RESTARTS   AGE
     nginx-deployment-1771418926-7o5ns   1/1       Running   0          16h
     nginx-deployment-1771418926-r18az   1/1       Running   0          16h
    
  4. Muestra información acerca del pod:

     kubectl describe pod <pod-name>
    

    donde <pod-name> es el nombre de uno de los pods.

Actualizando el deployment

Puedes actualizar el deployment aplicando un nuevo fichero YAML. El siguiente fichero YAML especifica que el deployment debería ser actualizado para usar nginx 1.8.

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
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.8 # Actualiza la versión de nginx de 1.7.9 a 1.8
        ports:
        - containerPort: 80
  1. Aplica el nuevo fichero YAML:

      kubectl apply -f https://k8s.io/examples/application/deployment-update.yaml
    
  2. Comprueba como el deployment crea nuevos pods con la nueva imagen mientras va eliminando los pods con la especificación antigua:

      kubectl get pods -l app=nginx
    

Escalando la aplicación aumentado el número de replicas

Puedes aumentar el número de pods en tu deployment aplicando un nuevo fichero YAML. El siguiente fichero YAML especifica un total de 4 replicas, lo que significa que el deployment debería tener cuatro pods:

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: 4 # Actualiza el número de réplicas de 2 a 4
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.8
        ports:
        - containerPort: 80
  1. Aplica el nuevo fichero YAML:

     kubectl apply -f https://k8s.io/examples/application/deployment-scale.yaml
    
  2. Verifica que el deployment tiene cuatro pods:

     kubectl get pods -l app=nginx
    

    El resultado es similar a esto:

     NAME                               READY     STATUS    RESTARTS   AGE
     nginx-deployment-148880595-4zdqq   1/1       Running   0          25s
     nginx-deployment-148880595-6zgi1   1/1       Running   0          25s
     nginx-deployment-148880595-fxcez   1/1       Running   0          2m
     nginx-deployment-148880595-rwovn   1/1       Running   0          2m
    

Eliminando un deployment

Elimina el deployment por el nombre:

kubectl delete deployment nginx-deployment

ReplicationControllers

La manera preferida de crear una aplicación con múltiples instancias es usando un Deployment, el cual usa un ReplicaSet. Antes de que Deployment y ReplicaSet fueran introducidos en Kubernetes, aplicaciones con múltiples instancias eran configuradas usando un ReplicationController.

Siguientes pasos

6.2 - Especificando un presupuesto de disrupción para tu aplicación

Ésta pagina enseña como limitar el numero de disrupciones concurrentes que afectan a tu aplicación definiendo presupuestos de disrupción de pods, Pod Disruption Budgets (PDB) en inglés. Estos presupuestos definen el mínimo número de pods que deben estar ejecutándose en todo momento para asegurar la disponibilidad de la aplicación durante operaciones de mantenimiento efectuadas sobre los nodos por los administradores del cluster.

Antes de empezar

Protegiendo una aplicación con un PodDisruptionBudget

  1. Identifica la aplicación que quieres proteger con un PodDisruptionBudget (PDB).
  2. Revisa como afectan las disrupciones a tú aplicación.
  3. Crea un PDB usando un archivo YAML.
  4. Crea el objecto PDB desde el archivo YAML.

Identifica la applicación que quieres proteger

El caso más común es proteger aplicaciones que usan uno de los controladores incorporados en Kubernetes:

  • Deployment
  • Replicationcontrolador
  • ReplicaSet
  • StatefulSet

En este caso, toma nota del .spec.selector que utiliza el controlador; el mismo se utilizará en el spec.selector del PDB.

También puedes utilizar PDBs para proteger pods que no estan gestionados por uno de los controladores listados arriba, o agrupaciones arbitrarias de pods, con algunas restricciones descritas en Controladores Arbitrarios y Selectors.

Revisa como afectan las disrupciones a tú aplicación

Decide cuántas instancias de tu aplicación pueden estar fuera de servicio al mismo tiempo debido a disrupciones voluntarias de corto plazo.

  • Frontend stateless:
    • Objetivo: evitar reducir capacidad para servir por mas de 10%.
      • Solución: usar un PDB que especifica minAvailable 90%.
  • Aplicación Stateful con una sola instancia:
    • Objetivo: no terminar esta aplicación sin primero confirmar conmigo.
      • Posible Solución 1: No usar un PDB y tolerar inactividad ocasional.
      • Posible Solución 2: Crea un PDB con maxUnavailable=0. Entiende que el operador del cluster debe consultar contigo antes de terminar tu aplicación. Cuando el operador te contacte, prepara tu aplicación para downtime y elimina el PDB para indicar que estas preparado para la disrupción. Crea el PDB de nuevo al terminar la disrupción.
  • Aplicación Stateful con múltiples instancias como Consul, ZooKeeper, etcd, Redis o MySQL:
    • Objetivo: no reducir el numero de instancias por debajo del quorum, de lo contrario, las escrituras fallarían.
      • Posible Solución 1: fijar maxUnavailable a 1 (funciona con diferentes escalas de aplicación).
      • Posible Solución 2: fijar minAvailable al tamaño del quorum (e.g. 3 cuando hay un total de 5 instancias). (Permite mas disrupciones a la vez.).
  • Trabajos por lote reiniciables:
    • Objetivo: El trabajo debe completarse en caso de una interrupción voluntaria.
      • Posible solución: No cree un PDB. El controlador de Jobs creará un pod de reemplazo.

Especificando un PodDisruptionBudget

Un PodDisruptionBudget tiene tres atributos:

  • Un label selector .spec.selector para especificar el grupo de pods donde aplicar el presupuesto. Este campo es requerido.
  • .spec.minAvailable que es una descripción del número de pods del grupo que deben estar disponibles después del desalojo, incluso en ausencia del pod desalojado. minAvailable puede ser un número absoluto o un porcentaje.
  • .spec.maxUnavailable (disponible en Kubernetes 1.7 y superior) que es una descripción del numero de pods del grupo que pueden estar indisponibles despues del desalojo. Puede ser un número absoluto o un porcentaje.

Puedes especificar únicamente un valor para maxUnavailable y minAvailable por PodDisruptionBudget. maxUnavailable solo se puede usar para controlar el desalojo de pods que tienen un controlador asociado manejándolos. En los ejemplos a continuación, "réplicas deseadas" hace referencia al valor 'scale' del controlador que gestiona el grupo de pods seleccionados por el PodDisruptionBudget.

Ejemplo 1: Con un minAvailable de 5, se permiten los desalojos siempre que dejen 5 o más pods disponibles entre las seleccionadas por el selector del PodDisruptionBudget.

Ejemplo 2: Con un minAvailable del 30%, se permiten los desalojos mientras que al menos 30% de la cantidad de réplicas se mantengan disponibles.

Ejemplo 3: Con un maxUnavailable de 5, se permiten desalojos siempre que haya como máximo 5 réplicas indisponibles entre el número total de réplicas deseadas.

Ejemplo 4: Con un maxUnavailable de 30%, se permiten los desalojos siempre y cuando no más del 30% de las réplicas esten indisponibles.

En el uso típico, se usaría un solo presupuesto para una colección de pods administrados por un controlador, por ejemplo, los pods en un solo ReplicaSet o StatefulSet.

Un maxUnavailable de 0% (o 0) o un minAvailable de 100% (o igual al número de réplicas) puede prevenir que los nodos sean purgados completamente. Esto está permitido según la semántica de PodDisruptionBudget.

Puedes encontrar ejemplos de presupuestos de disrupción de pods definidas a continuación. Los ejemplos aplican al grupo de pods que tienen la etiqueta app: zookeeper.

Ejemplo de PDB usando minAvailable:

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: zk-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: zookeeper

Ejemplo de PDB usando maxUnavailable (Kubernetes 1.7 o superior):

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: zk-pdb
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: zookeeper

Por ejemplo, si el objeto anterior zk-pdb selecciona los pods de un StatefulSet de tamaño 3, ambas especificaciones tienen el mismo significado exacto. Se recomienda el uso de maxUnavailable ya que responde automáticamente a los cambios en el número de réplicas del controlador correspondiente.

Crea el objeto PDB

Puedes crear el objeto PDB con el comando kubectl apply -f mypdb.yaml.

No puedes actualizar objetos PDB. Deben ser eliminados y recreados.

Comprueba el estado del PDB

Utiliza kubectl para comprobar que se ha creado tu PDB.

Suponiendo que en realidad no tengas pods que coincidan con app: zookeeper en su namespace, entonces verás algo como esto:

kubectl get poddisruptionbudgets
NAME      MIN-AVAILABLE   ALLOWED-DISRUPTIONS   AGE
zk-pdb    2               0                     7s

Si hay pods que coinciden (por ejemplo, 3), entonces debes ver algo similar a esto:

kubectl get poddisruptionbudgets
NAME      MIN-AVAILABLE   ALLOWED-DISRUPTIONS   AGE
zk-pdb    2               1                     7s

El valor distinto a cero de ALLOWED-DISRUPTIONS significa que el controlador de disrupción ha visto los pods, contó los pods coincidentes, y actualizó el estado del PDB.

Puedes obtener más información sobre el estado de un PDB con este comando:

kubectl get poddisruptionbudgets zk-pdb -o yaml
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  creationTimestamp: 2017-08-28T02:38:26Z
  generation: 1
  name: zk-pdb
...
status:
  currentHealthy: 3
  desiredHealthy: 3
  disruptedPods: null
  disruptionsAllowed: 1
  expectedPods: 3
  observedGeneration: 1

Por último, los PodDisruptionBudgets también se pueden consultar con kubectl utilizando el nombre corto pdb:

kubectl get pdb
NAME      MIN-AVAILABLE   ALLOWED-DISRUPTIONS   AGE
zk-pdb    2               0                     7s

Controladores y selectors arbitrarios

Puedes omitir esta sección si solo utilizas PDBs con los controladores integrados de aplicaciones (Deployment, Replicationcontrolador, ReplicaSet y StatefulSet), con el selector de PDB coincidiendo con el selector del controlador.

Puedes utilizar un PDB con pods controlados por otro tipo de controlador, por un "Operator", o pods individuales, pero con las siguientes restricciones:

  • solo puedes usar .spec.minAvailable, no .spec.maxUnavailable.
  • solo puedes usar un número entero en .spec.minAvailable, no un porcentaje.

Puedes usar un selector que selecciona un subconjunto o superconjunto de los pods que pertenecen a un controlador incorporado. Sin embargo, cuando hay varios PDB en un namespace, debes tener cuidado de no crear PDBs cuyos selectores se superponen.

7 - Gestionar y ejecutar daemons

8 - Gestionar y ejecutar trabajos

9 - Acceder al clúster y las aplicaciones

10 - Monitorización, Logs y Debugging

10.1 - Auditoría

La auditoría de Kubernetes proporciona un conjunto de registros cronológicos referentes a la seguridad que documentan la secuencia de actividades que tanto los usuarios individuales, como los administradores y otros componentes del sistema ha realizado en el sistema. Así, permite al administrador del clúster responder a las siguientes cuestiones:

  • ¿qué ha pasado?
  • ¿cuándo ha pasado?
  • ¿quién lo ha iniciado?
  • ¿sobre qué ha pasado?
  • ¿dónde se ha observado?
  • ¿desde dónde se ha iniciado?
  • ¿hacia dónde iba?

El componente Kube-apiserver lleva a cabo la auditoría. Cada petición en cada fase de su ejecución genera un evento, que se pre-procesa según un cierto reglamento y se escribe en un backend. Este reglamento determina lo que se audita y los backends persisten los registros. Las implementaciones actuales de backend incluyen los archivos de logs y los webhooks.

Cada petición puede grabarse junto con una "etapa" asociada. Las etapas conocidas son:

  • RequestReceived - La etapa para aquellos eventos generados tan pronto como el responsable de la auditoría recibe la petición, pero antes de que sea delegada al siguiente responsable en la cadena.
  • ResponseStarted - Una vez que las cabeceras de la respuesta se han enviado, pero antes de que el cuerpo de la respuesta se envíe. Esta etapa sólo se genera en peticiones de larga duración (ej. watch).
  • ResponseComplete - El cuerpo de la respuesta se ha completado y no se enviarán más bytes.
  • Panic - Eventos que se generan cuando ocurre una situación de pánico.

Reglamento de Auditoría

El reglamento de auditoría define las reglas acerca de los eventos que deberían registrarse y los datos que deberían incluir. La estructura del objeto de reglas de auditoría se define en el audit.k8s.io grupo de API. Cuando se procesa un evento, se compara con la lista de reglas en orden. La primera regla coincidente establece el "nivel de auditoría" del evento. Los niveles de auditoría conocidos son:

  • None - no se registra eventos que disparan esta regla.
  • Metadata - se registra los metadatos de la petición (usuario que la realiza, marca de fecha y hora, recurso, verbo, etc.), pero no la petición ni el cuerpo de la respuesta.
  • Request - se registra los metadatos del evento y el cuerpo de la petición, pero no el cuerpo de la respuesta. Esto no aplica para las peticiones que no son de recurso.
  • RequestResponse - se registra los metadatos del evento, y los cuerpos de la petición y la respuesta. Esto no aplica para las peticiones que no son de recurso.

Es posible indicar un archivo al definir el reglamento en el kube-apiserver usando el parámetro --audit-policy-file. Si dicho parámetros se omite, no se registra ningún evento. Nótese que el campo rules debe proporcionarse en el archivo del reglamento de auditoría. Un reglamento sin (0) reglas se considera ilegal.

Abajo se presenta un ejemplo de un archivo de reglamento de auditoría:

apiVersion: audit.k8s.io/v1 # Esto es obligatorio.
kind: Policy
# No generar eventos de auditoría para las peticiones en la etapa RequestReceived.
omitStages:
  - "RequestReceived"
rules:
  # Registrar los cambios del pod al nivel RequestResponse
  - level: RequestResponse
    resources:
    - group: ""
      # Los recursos "pods" no hacen coincidir las peticiones a cualquier sub-recurso de pods,
      # lo que es consistente con la regla RBAC.
      resources: ["pods"]
  # Registrar "pods/log", "pods/status" al nivel Metadata
  - level: Metadata
    resources:
    - group: ""
      resources: ["pods/log", "pods/status"]

  # No registrar peticiones al configmap denominado "controller-leader"
  - level: None
    resources:
    - group: ""
      resources: ["configmaps"]
      resourceNames: ["controller-leader"]

  # No registrar peticiones de observación hechas por "system:kube-proxy" sobre puntos de acceso o servicios
  - level: None
    users: ["system:kube-proxy"]
    verbs: ["watch"]
    resources:
    - group: "" # Grupo API base
      resources: ["endpoints", "services"]

  # No registrar peticiones autenticadas a ciertas rutas URL que no son recursos.
  - level: None
    userGroups: ["system:authenticated"]
    nonResourceURLs:
    - "/api*" # Coincidencia por comodín.
    - "/version"

  # Registrar el cuerpo de la petición de los cambios de configmap en kube-system.
  - level: Request
    resources:
    - group: "" # Grupo API base
      resources: ["configmaps"]
    # Esta regla sólo aplica a los recursos en el Namespace "kube-system".
    # La cadena vacía "" se puede usar para seleccionar los recursos sin Namespace.
    namespaces: ["kube-system"]

  # Registrar los cambios de configmap y secret en todos los otros Namespaces al nivel Metadata.
  - level: Metadata
    resources:
    - group: "" # Grupo API base
      resources: ["secrets", "configmaps"]

  # Registrar todos los recursos en core y extensions al nivel Request.
  - level: Request
    resources:
    - group: "" # Grupo API base
    - group: "extensions" # La versión del grupo NO debería incluirse.

  # Regla para "cazar" todos las demás peticiones al nivel Metadata.
  - level: Metadata
    # Las peticiones de larga duración, como los watches, que caen bajo esta regla no
    # generan un evento de auditoría en RequestReceived.
    omitStages:
      - "RequestReceived"

Puedes usar un archivo mínimo de reglamento de auditoría para registrar todas las peticiones al nivel Metadata de la siguiente forma:

# Log all requests at the Metadata level.
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata

El perfil de auditoría utilizado por GCE debería servir como referencia para que los administradores construyeran sus propios perfiles de auditoría.

Backends de auditoría

Los backends de auditoría persisten los eventos de auditoría en un almacenamiento externo. El Kube-apiserver por defecto proporciona tres backends:

  • Backend de logs, que escribe los eventos en disco
  • Backend de webhook, que envía los eventos a una API externa
  • Backend dinámico, que configura backends de webhook a través de objetos de la API AuditSink.

En todos los casos, la estructura de los eventos de auditoría se define por la API del grupo audit.k8s.io. La versión actual de la API es v1.

Backend de Logs

El backend de logs escribe los eventos de auditoría a un archivo en formato JSON. Puedes configurar el backend de logs de auditoría usando el siguiente parámetro de kube-apiserver flags:

  • --audit-log-path especifica la ruta al archivo de log que el backend utiliza para escribir los eventos de auditoría. Si no se especifica, se deshabilita el backend de logs. - significa salida estándar
  • --audit-log-maxage define el máximo número de días a retener los archivos de log
  • --audit-log-maxbackup define el máximo número de archivos de log a retener
  • --audit-log-maxsize define el tamaño máximo en megabytes del archivo de logs antes de ser rotado

Backend de Webhook

El backend de Webhook envía eventos de auditoría a una API remota, que se supone es la misma API que expone el kube-apiserver. Puedes configurar el backend de webhook de auditoría usando los siguientes parámetros de kube-apiserver:

  • --audit-webhook-config-file especifica la ruta a un archivo con configuración del webhook. La configuración del webhook es, de hecho, un archivo kubeconfig.
  • --audit-webhook-initial-backoff especifica la cantidad de tiempo a esperar tras una petición fallida antes de volver a intentarla. Los reintentos posteriores se ejecutan con retraso exponencial.

El archivo de configuración del webhook usa el formato kubeconfig para especificar la dirección remota del servicio y las credenciales para conectarse al mismo.

En la versión 1.13, los backends de webhook pueden configurarse dinámicamente.

Procesamiento por lotes

Tanto el backend de logs como el de webhook permiten procesamiento por lotes. Si usamos el webhook como ejemplo, aquí se muestra la lista de parámetros disponibles. Para aplicar el mismo parámetro al backend de logs, simplemente sustituye webhook por log en el nombre del parámetro. Por defecto, el procesimiento por lotes está habilitado en webhook y deshabilitado en log. De forma similar, por defecto la regulación (throttling) está habilitada en webhook y deshabilitada en log.

  • --audit-webhook-mode define la estrategia de memoria intermedia (búfer), que puede ser una de las siguientes:
    • batch - almacenar eventos y procesarlos de forma asíncrona en lotes. Esta es la estrategia por defecto.
    • blocking - bloquear todas las respuestas del servidor API al procesar cada evento de forma individual.
    • blocking-strict - igual que blocking, pero si ocurre un error durante el registro de la audtoría en la etapa RequestReceived, la petición completa al apiserver fallará.

Los siguientes parámetros se usan únicamente en el modo batch:

  • --audit-webhook-batch-buffer-size define el número de eventos a almacenar de forma intermedia antes de procesar por lotes. Si el ritmo de eventos entrantes desborda la memoria intermedia, dichos eventos se descartan.
  • --audit-webhook-batch-max-size define el número máximo de eventos en un único proceso por lotes.
  • --audit-webhook-batch-max-wait define la cantidad máxima de tiempo a esperar de forma incondicional antes de procesar los eventos de la cola.
  • --audit-webhook-batch-throttle-qps define el promedio máximo de procesos por lote generados por segundo.
  • --audit-webhook-batch-throttle-burst define el número máximo de procesos por lote generados al mismo tiempo si el QPS permitido no fue usado en su totalidad anteriormente.

Ajuste de parámetros

Los parámetros deberían ajustarse a la carga del apiserver.

Por ejemplo, si kube-apiserver recibe 100 peticiones por segundo, y para cada petición se audita las etapas ResponseStarted y ResponseComplete, deberías esperar unos ~200 eventos de auditoría generados por segundo. Asumiendo que hay hasta 100 eventos en un lote, deberías establecer el nivel de regulación (throttling) por lo menos a 2 QPS. Además, asumiendo que el backend puede tardar hasta 5 segundos en escribir eventos, deberías configurar el tamaño de la memoria intermedia para almacenar hasta 5 segundos de eventos, esto es, 10 lotes, o sea, 1000 eventos.

En la mayoría de los casos, sin embargo, los valores por defecto de los parámetros deberían ser suficientes y no deberías preocuparte de ajustarlos manualmente. Puedes echar un vistazo a la siguientes métricas de Prometheus que expone kube-apiserver y también los logs para monitorizar el estado del subsistema de auditoría:

  • apiserver_audit_event_total métrica que contiene el número total de eventos de auditoría exportados.
  • apiserver_audit_error_total métrica que contiene el número total de eventos descartados debido a un error durante su exportación.

Truncado

Tanto el backend de logs como el de webhook permiten truncado. Como ejemplo, aquí se indica la lista de parámetros disponible para el backend de logs:

  • audit-log-truncate-enabled indica si el truncado de eventos y por lotes está habilitado.
  • audit-log-truncate-max-batch-size indica el tamaño máximo en bytes del lote enviado al backend correspondiente.
  • audit-log-truncate-max-event-size indica el tamaño máximo en bytes del evento de auditoría enviado al backend correspondiente.

Por defecto, el truncado está deshabilitado tanto en webhook como en log; un administrador del clúster debe configurar bien el parámetro audit-log-truncate-enabled o audit-webhook-truncate-enabled para habilitar esta característica.

Backend dinámico

FEATURE STATE: Kubernetes v1.13 [alpha]

En la versión 1.13 de Kubernetes, puedes configurar de forma dinámica los backends de auditoría usando objetos de la API AuditSink.

Para habilitar la auditoría dinámica, debes configurar los siguientes parámetros de apiserver:

  • --audit-dynamic-configuration: el interruptor principal. Cuando esta característica sea GA, el único parámetro necesario.
  • --feature-gates=DynamicAuditing=true: en evaluación en alpha y beta.
  • --runtime-config=auditregistration.k8s.io/v1alpha1=true: habilitar la API.

Cuando se habilita, un objeto AuditSink se provisiona de la siguiente forma:

apiVersion: auditregistration.k8s.io/v1alpha1
kind: AuditSink
metadata:
  name: mysink
spec:
  policy:
    level: Metadata
    stages:
    - ResponseComplete
  webhook:
    throttle:
      qps: 10
      burst: 15
    clientConfig:
      url: "https://audit.app"

Para una definición completa de la API, ver AuditSink. Múltiples objetos existirán como soluciones independientes.

Aquellos backends estáticos que se configuran con parámetros en tiempo de ejecución no se ven impactados por esta característica. Sin embargo, estos backends dinámicos comparten las opciones de truncado del webhook estático, de forma que si dichas opciones se configura con parámetros en tiempo de ejecución, entonces se aplican a todos los backends dinámicos.

Reglamento

El reglamento de AuditSink es diferente del de la auditoría en tiempo de ejecución. Esto es debido a que el objeto de la API sirve para casos de uso diferentes. El reglamento continuará evolucionando para dar cabida a más casos de uso.

El campo level establece el nivel de auditoría indicado a todas las peticiones. El campo stages es actualmente una lista de las etapas que se permite registrar.

Seguridad

Los administradores deberían tener en cuenta que permitir el acceso en modo escritura de esta característica otorga el modo de acceso de lectura a toda la información del clúster. Así, el acceso debería gestionarse como un privilegio de nivel cluster-admin.

Rendimiento

Actualmente, esta característica tiene implicaciones en el apiserver en forma de incrementos en el uso de la CPU y la memoria. Aunque debería ser nominal cuando se trata de un número pequeño de destinos, se realizarán pruebas adicionales de rendimiento para entender su impacto real antes de que esta API pase a beta.

Configuración multi-clúster

Si estás extendiendo la API de Kubernetes mediante la capa de agregación, puedes también configurar el registro de auditoría para el apiserver agregado. Para ello, pasa las opciones de configuración en el mismo formato que se describe arriba al apiserver agregado y configura el mecanismo de ingestión de logs para que recolecte los logs de auditoría. Cada uno de los apiservers puede tener configuraciones de auditoría diferentes con diferentes reglamentos de auditoría.

Ejemplos de recolectores de Logs

Uso de fluentd para recolectar y distribuir eventos de auditoría a partir de un archivo de logs

Fluentd es un recolector de datos de libre distribución que proporciona una capa unificada de registros. En este ejemplo, usaremos fluentd para separar los eventos de auditoría por nombres de espacio:

  1. Instala fluentd, fluent-plugin-forest y fluent-plugin-rewrite-tag-filter en el nodo donde corre kube-apiserver

  2. Crea un archivo de configuración para fluentd:

    cat <<'EOF' > /etc/fluentd/config
    # fluentd conf runs in the same host with kube-apiserver
    <source>
        @type tail
        # audit log path of kube-apiserver
        path /var/log/kube-audit
        pos_file /var/log/audit.pos
        format json
        time_key time
        time_format %Y-%m-%dT%H:%M:%S.%N%z
        tag audit
    </source>
    
    <filter audit>
        #https://github.com/fluent/fluent-plugin-rewrite-tag-filter/issues/13
        @type record_transformer
        enable_ruby
        <record>
         namespace ${record["objectRef"].nil? ? "none":(record["objectRef"]["namespace"].nil? ? "none":record["objectRef"]["namespace"])}
        </record>
    </filter>
    
    <match audit>
        # route audit according to namespace element in context
        @type rewrite_tag_filter
        <rule>
            key namespace
            pattern /^(.+)/
            tag ${tag}.$1
        </rule>
    </match>
    
    <filter audit.**>
       @type record_transformer
       remove_keys namespace
    </filter>
    
    <match audit.**>
        @type forest
        subtype file
        remove_prefix audit
        <template>
            time_slice_format %Y%m%d%H
            compress gz
            path /var/log/audit-${tag}.*.log
            format json
            include_time_key true
        </template>
    </match>
    EOF
    
  3. Arranca fluentd:

    fluentd -c /etc/fluentd/config  -vv
    
  4. Arranca el componente kube-apiserver con las siguientes opciones:

    --audit-policy-file=/etc/kubernetes/audit-policy.yaml --audit-log-path=/var/log/kube-audit --audit-log-format=json
    
  5. Comprueba las auditorías de los distintos espacios de nombres en /var/log/audit-*.log

Uso de logstash para recolectar y distribuir eventos de auditoría desde un backend de webhook

Logstash es una herramienta de libre distribución de procesamiento de datos en servidor. En este ejemplo, vamos a usar logstash para recolectar eventos de auditoría a partir de un backend de webhook, y grabar los eventos de usuarios diferentes en archivos distintos.

  1. Instala logstash

  2. Crea un archivo de configuración para logstash:

    cat <<EOF > /etc/logstash/config
    input{
        http{
            #TODO, figure out a way to use kubeconfig file to authenticate to logstash
            #https://www.elastic.co/guide/en/logstash/current/plugins-inputs-http.html#plugins-inputs-http-ssl
            port=>8888
        }
    }
    filter{
        split{
            # Webhook audit backend sends several events together with EventList
            # split each event here.
            field=>[items]
            # We only need event subelement, remove others.
            remove_field=>[headers, metadata, apiVersion, "@timestamp", kind, "@version", host]
        }
        mutate{
            rename => {items=>event}
        }
    }
    output{
        file{
            # Audit events from different users will be saved into different files.
            path=>"/var/log/kube-audit-%{[event][user][username]}/audit"
        }
    }
    EOF
    
  3. Arranca logstash:

    bin/logstash -f /etc/logstash/config --path.settings /etc/logstash/
    
  4. Crea un archivo kubeconfig para el webhook del backend de auditoría de kube-apiserver:

     cat <<EOF > /etc/kubernetes/audit-webhook-kubeconfig
     apiVersion: v1
     clusters:
     - cluster:
         server: http://<ip_of_logstash>:8888
       name: logstash
     contexts:
     - context:
         cluster: logstash
         user: ""
       name: default-context
     current-context: default-context
     kind: Config
     preferences: {}
     users: []
     EOF
    
  5. Arranca kube-apiserver con las siguientes opciones:

    --audit-policy-file=/etc/kubernetes/audit-policy.yaml --audit-webhook-config-file=/etc/kubernetes/audit-webhook-kubeconfig
    
  6. Comprueba las auditorías en los directorios /var/log/kube-audit-*/audit de los nodos de logstash

Nótese que además del plugin para salida en archivos, logstash ofrece una variedad de salidas adicionales que permiten a los usuarios enviar la información donde necesiten. Por ejemplo, se puede enviar los eventos de auditoría al plugin de elasticsearch que soporta búsquedas avanzadas y analíticas.

10.2 - Depurar Contenedores de Inicialización

Esta página muestra cómo investigar problemas relacionados con la ejecución de los contenedores de inicialización (init containers). Las líneas de comando del ejemplo de abajo se refieren al Pod como <pod-name> y a los Init Containers como <init-container-1> e <init-container-2> respectivamente.

Antes de empezar

Debes tener un cluster Kubernetes a tu dispocición, y la herramienta de línea de comandos kubectl debe estar configurada. Si no tienes un cluster, puedes crear uno utilizando Minikube, o puedes utilizar una de las siguientes herramientas en línea:

Para comprobar la versión, introduzca kubectl version.

Comprobar el estado de los Init Containers

Muestra el estado de tu pod:

kubectl get pod <pod-name>

Por ejemplo, un estado de Init:1/2 indica que uno de los Init Containers se ha ejecutado satisfactoriamente:

NAME         READY     STATUS     RESTARTS   AGE
<pod-name>   0/1       Init:1/2   0          7s

Echa un vistazo a Comprender el estado de un Pod para más ejemplos de valores de estado y sus significados.

Obtener detalles acerca de los Init Containers

Para ver información detallada acerca de la ejecución de un Init Container:

kubectl describe pod <pod-name>

Por ejemplo, un Pod con dos Init Containers podría mostrar lo siguiente:

Init Containers:
  <init-container-1>:
    Container ID:    ...
    ...
    State:           Terminated
      Reason:        Completed
      Exit Code:     0
      Started:       ...
      Finished:      ...
    Ready:           True
    Restart Count:   0
    ...
  <init-container-2>:
    Container ID:    ...
    ...
    State:           Waiting
      Reason:        CrashLoopBackOff
    Last State:      Terminated
      Reason:        Error
      Exit Code:     1
      Started:       ...
      Finished:      ...
    Ready:           False
    Restart Count:   3
    ...

También puedes acceder al estado del Init Container de forma programática mediante la lectura del campo status.initContainerStatuses dentro del Pod Spec:

kubectl get pod nginx --template '{{.status.initContainerStatuses}}'

Este comando devolverá la misma información que arriba en formato JSON.

Acceder a los logs de los Init Containers

Indica el nombre del Init Container así como el nombre del Pod para acceder a sus logs.

kubectl logs <pod-name> -c <init-container-2>

Los Init Containers que ejecutan secuencias de línea de comandos muestran los comandos conforme se van ejecutando. Por ejemplo, puedes hacer lo siguiente en Bash indicando set -x al principio de la secuencia.

Comprender el estado de un Pod

Un estado de un Pod que comienza con Init: especifica el estado de la ejecución de un Init Container. La tabla a continuación muestra algunos valores de estado de ejemplo que puedes encontrar al depurar Init Containers.

Estado Significado
Init:N/M El Pod tiene M Init Containers, y por el momento se han completado N.
Init:Error Ha fallado la ejecución de un Init Container.
Init:CrashLoopBackOff Un Init Container ha fallado de forma repetida.
Pending El Pod todavía no ha comenzado a ejecutar sus Init Containers.
PodInitializing o Running El Pod ya ha terminado de ejecutar sus Init Containers.

10.3 - Escribiendo Logs con Elasticsearch y Kibana

En la plataforma Google Compute Engine (GCE), por defecto da soporte a la escritura de logs haciendo uso de Stackdriver Logging, el cual se describe en detalle en Logging con Stackdriver Logging.

Este artículo describe cómo configurar un clúster para la ingesta de logs en Elasticsearch y su posterior visualización con Kibana, a modo de alternativa a Stackdriver Logging cuando se utiliza la plataforma GCE.

Para utilizar Elasticsearch y Kibana para escritura de logs del clúster, deberías configurar la siguiente variable de entorno que se muestra a continuación como parte de la creación del clúster con kube-up.sh:

KUBE_LOGGING_DESTINATION=elasticsearch

También deberías asegurar que KUBE_ENABLE_NODE_LOGGING=true (que es el valor por defecto en la plataforma GCE).

Así, cuando crees un clúster, un mensaje te indicará que la recolección de logs de los daemons de Fluentd que corren en cada nodo enviará dichos logs a Elasticsearch:

cluster/kube-up.sh
...
Project: kubernetes-satnam
Zone: us-central1-b
... calling kube-up
Project: kubernetes-satnam
Zone: us-central1-b
+++ Staging server tars to Google Storage: gs://kubernetes-staging-e6d0e81793/devel
+++ kubernetes-server-linux-amd64.tar.gz uploaded (sha1 = 6987c098277871b6d69623141276924ab687f89d)
+++ kubernetes-salt.tar.gz uploaded (sha1 = bdfc83ed6b60fa9e3bff9004b542cfc643464cd0)
Looking for already existing resources
Starting master and configuring firewalls
Created [https://www.googleapis.com/compute/v1/projects/kubernetes-satnam/zones/us-central1-b/disks/kubernetes-master-pd].
NAME                 ZONE          SIZE_GB TYPE   STATUS
kubernetes-master-pd us-central1-b 20      pd-ssd READY
Created [https://www.googleapis.com/compute/v1/projects/kubernetes-satnam/regions/us-central1/addresses/kubernetes-master-ip].
+++ Logging using Fluentd to elasticsearch

Tanto los pods por nodo de Fluentd, como los pods de Elasticsearch, y los pods de Kibana deberían ejecutarse en el namespace de kube-system inmediatamente después de que el clúster esté disponible.

kubectl get pods --namespace=kube-system
NAME                                           READY     STATUS    RESTARTS   AGE
elasticsearch-logging-v1-78nog                 1/1       Running   0          2h
elasticsearch-logging-v1-nj2nb                 1/1       Running   0          2h
fluentd-elasticsearch-kubernetes-node-5oq0     1/1       Running   0          2h
fluentd-elasticsearch-kubernetes-node-6896     1/1       Running   0          2h
fluentd-elasticsearch-kubernetes-node-l1ds     1/1       Running   0          2h
fluentd-elasticsearch-kubernetes-node-lz9j     1/1       Running   0          2h
kibana-logging-v1-bhpo8                        1/1       Running   0          2h
kube-dns-v3-7r1l9                              3/3       Running   0          2h
monitoring-heapster-v4-yl332                   1/1       Running   1          2h
monitoring-influx-grafana-v1-o79xf             2/2       Running   0          2h

Los pods de fluentd-elasticsearch recogen los logs de cada nodo y los envían a los pods de elasticsearch-logging, que son parte de un servicio llamado elasticsearch-logging. Estos pods de Elasticsearch almacenan los logs y los exponen via una API REST. El pod de kibana-logging proporciona una UI via web donde leer los logs almacenados en Elasticsearch, y es parte de un servicio denominado kibana-logging.

Los servicios de Elasticsearch y Kibana ambos están en el namespace kube-system y no se exponen de forma directa mediante una IP accesible públicamente. Para poder acceder a dichos logs, sigue las instrucciones acerca de cómo Acceder a servicios corriendo en un clúster.

Si tratas de acceder al servicio de elasticsearch-logging desde tu navegador, verás una página de estado que se parece a la siguiente:

Estado de Elasticsearch

A partir de ese momento, puedes introducir consultas de Elasticsearch directamente en el navegador, si lo necesitas. Echa un vistazo a la documentación de Elasticsearch para más detalles acerca de cómo hacerlo.

De forma alternativa, puedes ver los logs de tu clúster en Kibana (de nuevo usando las instrucciones para acceder a un servicio corriendo en un clúster). La primera vez que visitas la URL de Kibana se te presentará una página que te pedirá que configures una vista de los logs. Selecciona la opción de valores de serie temporal y luego @timestamp. En la página siguiente selecciona la pestaña de Discover y entonces deberías ver todos los logs. Puedes establecer el intervalo de actualización en 5 segundos para refrescar los logs de forma regular.

Aquí se muestra una vista típica de logs desde el visor de Kibana:

Kibana logs

Siguientes pasos

¡Kibana te permite todo tipo de potentes opciones para explorar tus logs! Puedes encontrar algunas ideas para profundizar en el tema en la documentación de Kibana.

10.4 - Pipeline de métricas de recursos

Desde Kubernetes 1.8, las métricas de uso de recursos, tales como el uso de CPU y memoria del contenedor, están disponibles en Kubernetes a través de la API de métricas. Estas métricas son accedidas directamente por el usuario, por ejemplo usando el comando kubectl top, o usadas por un controlador en el cluster, por ejemplo el Horizontal Pod Autoscaler, para la toma de decisiones.

La API de Métricas

A través de la API de métricas, Metrics API en inglés, puedes obtener la cantidad de recursos usados actualmente por cada nodo o pod. Esta API no almacena los valores de las métricas, así que no es posible, por ejemplo, obtener la cantidad de recursos que fueron usados por un nodo hace 10 minutos.

La API de métricas está completamente integrada en la API de Kubernetes:

  • se expone a través del mismo endpoint que las otras APIs de Kubernetes bajo el path /apis/metrics.k8s.io/
  • ofrece las mismas garantías de seguridad, escalabilidad y confiabilidad

La API está definida en el repositorio k8s.io/metrics. Puedes encontrar más información sobre la API ahí.

Servidor de Métricas

El Servidor de Métricas es un agregador de datos de uso de recursos de todo el clúster. A partir de Kubernetes 1.8, el servidor de métricas se despliega por defecto como un objeto de tipo Deployment en clústeres creados con el script kube-up.sh. Si usas otro mecanismo de configuración de Kubernetes, puedes desplegarlo usando los yamls de despliegue proporcionados. Está soportado a partir de Kubernetes 1.7 (más detalles al final).

El servidor reune métricas de la Summary API, que es expuesta por el Kubelet en cada nodo.

El servidor de métricas se añadió a la API de Kubernetes utilizando el Kubernetes aggregator introducido en Kubernetes 1.7.

Puedes aprender más acerca del servidor de métricas en el documento de diseño.

11 - Extender la API de Kubernetes

11.1 - Usar recursos personalizados

12 - Gestionar certificados TLS

13 - Federación

13.1 - Administrar la federación de clústeres

14 - Catálogo de servicios