|
| 1 | +--- |
| 2 | +title: Contenedores de Inicialización |
| 3 | +content_type: concept |
| 4 | +weight: 40 |
| 5 | +--- |
| 6 | + |
| 7 | +<!-- overview --> |
| 8 | +Esta página proporciona una descripción general de los contenedores de inicialización (init containers): contenedores especializados que se ejecutan |
| 9 | +antes de los contenedores de aplicación en un {{< glossary_tooltip text="Pod" term_id="pod" >}}. |
| 10 | +Los contenedores de inicialización pueden contener utilidades o scripts de instalación no presentes en una imagen de aplicación. |
| 11 | + |
| 12 | +Tú puedes especificar contenedores de inicialización en la especificación del Pod junto con el arreglo de `containers` |
| 13 | +(el cual describe los contenedores de aplicación). |
| 14 | + |
| 15 | +<!-- body --> |
| 16 | +## Entendiendo los contenedores de inicialización |
| 17 | + |
| 18 | +Un {{< glossary_tooltip text="Pod" term_id="pod" >}} puede tener múltiples contenedores |
| 19 | +ejecutando aplicaciones dentro de él, pero también puede tener uno o más contenedores de inicialización |
| 20 | +que se ejecutan antes de que se inicien los contenedores de aplicación. |
| 21 | + |
| 22 | +Los contenedores de inicialización son exactamente iguales a los contenedores regulares excepto por: |
| 23 | + |
| 24 | +* Los contenedores de inicialización siempre se ejecutan hasta su finalización. |
| 25 | +* Cada contenedor de inicialiación debe completarse correctamente antes de que comience el siguiente. |
| 26 | + |
| 27 | +Si el contenedor de inicialización de un Pod falla, kubelet reinicia repetidamente ese contenedor de inicialización hasta que tenga éxito. |
| 28 | +Sin embargo, si el Pod tiene una `restartPolicy` de `Never` y un contenedor de inicialización falla durante el inicio de ese Pod, Kubernetes trata al Pod en general como fallido. |
| 29 | + |
| 30 | +Para especificar un contenedor de inicialización para un Pod, agrega el campo `initContainers` en |
| 31 | +la [especificación del Pod](/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodSpec), |
| 32 | +como un arreglo de elementos `container` (similar al campo `containers` de aplicación y su contenido). |
| 33 | +Consulta [Container](/docs/reference/kubernetes-api/workload-resources/pod-v1/#Container) en la |
| 34 | +referencia de API para más detalles. |
| 35 | + |
| 36 | +El estado de los contenedores de inicialización se devuelve en el campo `.status.initContainerStatuses` |
| 37 | +como un arreglo de los estados del contenedor (similar al campo `.status.containerStatuses`). |
| 38 | + |
| 39 | +### Diferencias con los contenedores regulares |
| 40 | + |
| 41 | +Los contenedores de inicialización admiten todos los campos y características de los contenedores de aplicaciones, |
| 42 | +incluidos los límites de recursos, los volúmenes y la configuración de seguridad. Sin embargo, las |
| 43 | +solicitudes de recursos y los límites para un contenedor de inicialización se manejan de manera diferente, |
| 44 | +como se documenta en [Recursos](#resources). |
| 45 | + |
| 46 | +Además, los contenedores de inicialización no admiten `lifecycle`, `livenessProbe`, `readinessProbe` o |
| 47 | +`startupProbe` porque deben de ejecutarse hasta su finalización antes de que el Pod pueda estar listo. |
| 48 | + |
| 49 | +Si especificas varios contenedores de inicialización para un Pod, kubelet ejecuta cada contenedor |
| 50 | +de inicialización secuencialmente. Cada contenedor de inicialización debe tener éxito antes de que se pueda ejecutar el siguiente. |
| 51 | +Cuando todos los contenedores de inicialización se hayan ejecutado hasta su finalización, kubelet inicializa |
| 52 | +los contenedores de aplicación para el Pod y los ejecuta como de costumbre. |
| 53 | + |
| 54 | +### Usando contenedores de inicialización |
| 55 | + |
| 56 | +Dado que los contenedores de inicialización tienen imágenes separadas de los contenedores de aplicaciones, estos |
| 57 | +tienen algunas ventajas sobre el código relacionado de inicio: |
| 58 | + |
| 59 | +* Los contenedores de inicialización pueden contener utilidades o código personalizado para la configuración que no están presentes en una |
| 60 | + imagen de aplicación. Por ejemplo, no hay necesidad de hacer una imagen `FROM` de otra imagen solo para usar una herramienta como |
| 61 | + `sed`, `awk`, `python` o `dig` durante la instalación. |
| 62 | +* Los roles de constructor e implementador de imágenes de aplicación pueden funcionar de forma independiente sin |
| 63 | + la necesidad de construir conjuntamente una sola imagen de aplicación. |
| 64 | +* Los contenedores de inicialización pueden ejecutarse con una vista diferente al sistema de archivos que los contenedores de aplicaciones en |
| 65 | + el mismo Pod. En consecuencia, se les puede dar acceso a |
| 66 | + {{<glossary_tooltip text = "Secrets" term_id = "secret">}} a los que los contenedores de aplicaciones no pueden acceder. |
| 67 | +* Debido a que los contenedores de inicialización se ejecutan hasta su finalización antes de que se inicien los contenedores de aplicaciones, los contenedores de inicialización ofrecen |
| 68 | + un mecanismo para bloquear o retrasar el inicio del contenedor de aplicación hasta que se cumplan una serie de condiciones previas. Una vez |
| 69 | + que las condiciones previas se cumplen, todos los contenedores de aplicaciones de un Pod pueden iniciarse en paralelo. |
| 70 | +* Los contenedores de inicialización pueden ejecutar de forma segura utilidades o código personalizado que de otro modo harían a una imagen de aplicación |
| 71 | + de contenedor menos segura. Si mantiene separadas herramientas innecesarias, puede limitar la superficie de ataque |
| 72 | + a la imagen del contenedor de aplicación. |
| 73 | + |
| 74 | +### Ejemplos |
| 75 | + |
| 76 | +A continuación, se muestran algunas ideas sobre cómo utilizar los contenedores de inicialización: |
| 77 | + |
| 78 | +* Esperar a que se cree un {{< glossary_tooltip text="Service" term_id="service">}} |
| 79 | + usando una sola linea de comando de shell: |
| 80 | + |
| 81 | + ```shell |
| 82 | + for i in {1..100}; do sleep 1; if dig myservice; then exit 0; fi; done; exit 1 |
| 83 | + ``` |
| 84 | + |
| 85 | +* Registrar este Pod con un servidor remoto desde la downward API con un comando como: |
| 86 | + |
| 87 | + ```shell |
| 88 | + curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)' |
| 89 | + ``` |
| 90 | + |
| 91 | +* Esperar algo de tiempo antes de iniciar el contenedor de aplicación con un comando como: |
| 92 | + |
| 93 | + ```shell |
| 94 | + sleep 60 |
| 95 | + ``` |
| 96 | + |
| 97 | +* Clonar un repositorio de Git en un {{< glossary_tooltip text="Volume" term_id="volume" >}} |
| 98 | + |
| 99 | +* Colocar valores en un archivo de configuración y ejecutar una herramienta de plantilla para generar |
| 100 | + dinámicamente un archivo de configuración para el contenedor de aplicación principal. Por ejemplo, |
| 101 | + colocar el valor `POD_IP` en una configuración y generar el archivo de configuración |
| 102 | + de la aplicación principal usando Jinja. |
| 103 | + |
| 104 | +#### Contenedores de inicialización en uso |
| 105 | + |
| 106 | +Este ejemplo define un simple Pod que tiene dos contenedores de inicialización. |
| 107 | +El primero espera por `myservice` y el segundo espera por `mydb`. Una vez que ambos |
| 108 | +contenedores de inicialización se completen, el Pod ejecuta el contenedor de aplicación desde su sección `spec`. |
| 109 | + |
| 110 | +```yaml |
| 111 | +apiVersion: v1 |
| 112 | +kind: Pod |
| 113 | +metadata: |
| 114 | + name: myapp-pod |
| 115 | + labels: |
| 116 | + app: myapp |
| 117 | +spec: |
| 118 | + containers: |
| 119 | + - name: myapp-container |
| 120 | + image: busybox:1.28 |
| 121 | + command: ['sh', '-c', 'echo ¡La aplicación se está ejecutando! && sleep 3600'] |
| 122 | + initContainers: |
| 123 | + - name: init-myservice |
| 124 | + image: busybox:1.28 |
| 125 | + command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo esperando a myservice; sleep 2; done"] |
| 126 | + - name: init-mydb |
| 127 | + image: busybox:1.28 |
| 128 | + command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo esperando a mydb; sleep 2; done"] |
| 129 | +``` |
| 130 | +
|
| 131 | +Puedes iniciar este Pod ejecutando: |
| 132 | +
|
| 133 | +```shell |
| 134 | +kubectl apply -f myapp.yaml |
| 135 | +``` |
| 136 | + |
| 137 | +El resultado es similar a esto: |
| 138 | + |
| 139 | +```shell |
| 140 | +pod/myapp-pod created |
| 141 | +``` |
| 142 | + |
| 143 | +Y verificar su estado con: |
| 144 | + |
| 145 | +```shell |
| 146 | +kubectl get -f myapp.yaml |
| 147 | +``` |
| 148 | + |
| 149 | +El resultado es similar a esto: |
| 150 | + |
| 151 | +```shell |
| 152 | +NAME READY STATUS RESTARTS AGE |
| 153 | +myapp-pod 0/1 Init:0/2 0 6m |
| 154 | +``` |
| 155 | + |
| 156 | +o para más detalles: |
| 157 | + |
| 158 | +```shell |
| 159 | +kubectl describe -f myapp.yaml |
| 160 | +``` |
| 161 | + |
| 162 | +El resultado es similar a esto: |
| 163 | + |
| 164 | +```shell |
| 165 | +Name: myapp-pod |
| 166 | +Namespace: default |
| 167 | +[...] |
| 168 | +Labels: app=myapp |
| 169 | +Status: Pending |
| 170 | +[...] |
| 171 | +Init Containers: |
| 172 | + init-myservice: |
| 173 | +[...] |
| 174 | + State: Running |
| 175 | +[...] |
| 176 | + init-mydb: |
| 177 | +[...] |
| 178 | + State: Waiting |
| 179 | + Reason: PodInitializing |
| 180 | + Ready: False |
| 181 | +[...] |
| 182 | +Containers: |
| 183 | + myapp-container: |
| 184 | +[...] |
| 185 | + State: Waiting |
| 186 | + Reason: PodInitializing |
| 187 | + Ready: False |
| 188 | +[...] |
| 189 | +Events: |
| 190 | + FirstSeen LastSeen Count From SubObjectPath Type Reason Message |
| 191 | + --------- -------- ----- ---- ------------- -------- ------ ------- |
| 192 | + 16s 16s 1 {default-scheduler } Normal Scheduled Successfully assigned myapp-pod to 172.17.4.201 |
| 193 | + 16s 16s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulling pulling image "busybox" |
| 194 | + 13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulled Successfully pulled image "busybox" |
| 195 | + 13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Created Created container with docker id 5ced34a04634; Security:[seccomp=unconfined] |
| 196 | + 13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Started Started container with docker id 5ced34a04634 |
| 197 | +``` |
| 198 | + |
| 199 | +Para ver los logs de los contenedores de inicialización en este Pod ejecuta: |
| 200 | + |
| 201 | +```shell |
| 202 | +kubectl logs myapp-pod -c init-myservice # Inspecciona el primer contenedor de inicialización |
| 203 | +kubectl logs myapp-pod -c init-mydb # Inspecciona el segundo contenedor de inicialización |
| 204 | +``` |
| 205 | + |
| 206 | +En este punto, estos contenedores de inicialización estarán esperando para descubrir los Servicios denominados |
| 207 | +`mydb` y `myservice`. |
| 208 | + |
| 209 | +Aquí hay una configuración que puedes usar para que aparezcan esos Servicios: |
| 210 | + |
| 211 | +```yaml |
| 212 | +--- |
| 213 | +apiVersion: v1 |
| 214 | +kind: Service |
| 215 | +metadata: |
| 216 | + name: myservice |
| 217 | +spec: |
| 218 | + ports: |
| 219 | + - protocol: TCP |
| 220 | + port: 80 |
| 221 | + targetPort: 9376 |
| 222 | +--- |
| 223 | +apiVersion: v1 |
| 224 | +kind: Service |
| 225 | +metadata: |
| 226 | + name: mydb |
| 227 | +spec: |
| 228 | + ports: |
| 229 | + - protocol: TCP |
| 230 | + port: 80 |
| 231 | + targetPort: 9377 |
| 232 | +``` |
| 233 | +
|
| 234 | +Para crear los servicios de `mydb` y `myservice`: |
| 235 | + |
| 236 | +```shell |
| 237 | +kubectl apply -f services.yaml |
| 238 | +``` |
| 239 | + |
| 240 | +El resultado es similar a esto: |
| 241 | + |
| 242 | +```shell |
| 243 | +service/myservice created |
| 244 | +service/mydb created |
| 245 | +``` |
| 246 | + |
| 247 | +Luego verás que esos contenedores de inicialización se completan y que el Pod `myapp-pod` |
| 248 | +pasa al estado `Running`: |
| 249 | + |
| 250 | +```shell |
| 251 | +kubectl get -f myapp.yaml |
| 252 | +``` |
| 253 | + |
| 254 | +El resultado es similar a esto: |
| 255 | + |
| 256 | +```shell |
| 257 | +NAME READY STATUS RESTARTS AGE |
| 258 | +myapp-pod 1/1 Running 0 9m |
| 259 | +``` |
| 260 | + |
| 261 | +Este sencillo ejemplo debería servirte de inspiración para crear tus propios |
| 262 | +contenedores de inicialización. [¿Qué es lo que sigue?](#what-s-next) contiene un enlace a un ejemplo más detallado. |
| 263 | + |
| 264 | +## Comportamiento detallado |
| 265 | + |
| 266 | +Durante el inicio del Pod, kubelet retrasa la ejecución de contenedores de inicialización hasta que la red |
| 267 | +y el almacenamiento estén listos. Después, kubelet ejecuta los contenedores de inicialización del Pod en el orden que |
| 268 | +aparecen en la especificación del Pod. |
| 269 | + |
| 270 | +Cada contenedor de inicialización debe salir correctamente antes de que |
| 271 | +comience el siguiente contenedor. Si un contenedor falla en iniciar debido al tiempo de ejecución o |
| 272 | +sale con una falla, se vuelve a intentar de acuerdo con el `restartPolicy` del Pod. Sin embargo, |
| 273 | +si el `restartPolicy` del Pod se establece en `Always`, los contenedores de inicialización usan |
| 274 | +el `restartPolicy` como `OnFailure`. |
| 275 | + |
| 276 | +Un Pod no puede estar `Ready` sino hasta que todos los contenedores de inicialización hayan tenido éxito. Los puertos en un |
| 277 | +contenedor de inicialización no se agregan a un Servicio. Un Pod que se está inicializando, |
| 278 | +está en el estado de `Pending`, pero debe tener una condición `Initialized` configurada como falsa. |
| 279 | + |
| 280 | +Si el Pod [se reinicia](#pod-restart-reasons) o es reiniciado, todos los contenedores de inicialización |
| 281 | +deben ejecutarse de nuevo. |
| 282 | + |
| 283 | +Los cambios en la especificación del contenedor de inicialización se limitan al campo de la imagen del contenedor. |
| 284 | +Alterar un campo de la imagen del contenedor de inicialización equivale a reiniciar el Pod. |
| 285 | + |
| 286 | +Debido a que los contenedores de inicialización se pueden reiniciar, reintentar o volverse a ejecutar, el código del contenedor de inicialización |
| 287 | +debe ser idempotente. En particular, el código que escribe en archivos en `EmptyDirs` |
| 288 | +debe estar preparado para la posibilidad de que ya exista un archivo de salida. |
| 289 | + |
| 290 | +Los contenedores de inicialización tienen todos los campos de un contenedor de aplicaciones. Sin embargo, Kubernetes |
| 291 | +prohíbe el uso de `readinessProbe` porque los contenedores de inicialización no pueden |
| 292 | +definir el `readiness` distinto de la finalización. Esto se aplica durante la validación. |
| 293 | + |
| 294 | +Usa `activeDeadlineSeconds` en el Pod para prevenir que los contenedores de inicialización fallen por siempre. |
| 295 | +La fecha límite incluye contenedores de inicialización. |
| 296 | +Sin embargo, se recomienda utilizar `activeDeadlineSeconds` si el usuario implementa su aplicación |
| 297 | +como un `Job` porque `activeDeadlineSeconds` tiene un efecto incluso después de que `initContainer` finaliza. |
| 298 | +El Pod que ya se está ejecutando correctamente sería eliminado por `activeDeadlineSeconds` si lo estableces. |
| 299 | + |
| 300 | +El nombre de cada aplicación y contenedor de inicialización en un Pod debe ser único; un |
| 301 | +error de validación es arrojado para cualquier contenedor que comparta un nombre con otro. |
| 302 | + |
| 303 | +### Recursos |
| 304 | + |
| 305 | +Dado el orden y la ejecución de los contenedores de inicialización, las siguientes reglas |
| 306 | +para el uso de recursos se aplican: |
| 307 | + |
| 308 | +* La solicitud más alta de cualquier recurso o límite particular definido en todos los contenedores |
| 309 | + de inicialización es la *solicitud/límite de inicialización efectiva*. Si algún recurso no tiene un |
| 310 | + límite de recursos especificado éste se considera como el límite más alto. |
| 311 | +* La *solicitud/límite efectiva* para un recurso es la más alta entre: |
| 312 | + * la suma de todas las solicitudes/límites de los contenedores de aplicación, y |
| 313 | + * la solicitud/límite de inicialización efectiva para un recurso |
| 314 | +* La planificación es hecha con base en las solicitudes/límites efectivos, lo que significa |
| 315 | + que los contenedores de inicialización pueden reservar recursos para la inicialización que no se utilizan |
| 316 | + durante la vida del Pod. |
| 317 | +* El nivel de `QoS` (calidad de servicio) del *nivel de `QoS` efectivo* del Pod es el |
| 318 | + nivel de `QoS` tanto para los contenedores de inicialización como para los contenedores de aplicación. |
| 319 | + |
| 320 | +La cuota y los límites son aplicados con base en la solicitud y límite efectivos de Pod. |
| 321 | + |
| 322 | +Los grupos de control de nivel de Pod (cgroups) se basan en la solicitud y el límite de Pod efectivos, al igual que el planificador de Kubernetes ({{< glossary_tooltip term_id="kube-scheduler" text="kube-scheduler" >}}). |
| 323 | + |
| 324 | +### Razones de reinicio del Pod |
| 325 | + |
| 326 | +Un Pod puede reiniciarse, provocando la re-ejecución de los contenedores de inicialización por las siguientes razones: |
| 327 | + |
| 328 | +* Se reinicia el contenedor de infraestructura del Pod. Esto es poco común y debería hacerlo alguien con acceso de root a los nodos. |
| 329 | +* Todos los contenedores en un Pod son terminados mientras `restartPolicy` esté configurado en `Always`, |
| 330 | + forzando un reinicio y el registro de finalización del contenedor de inicialización se ha perdido debido a |
| 331 | + la recolección de basura. |
| 332 | + |
| 333 | +El Pod no se reiniciará cuando se cambie la imagen del contenedor de inicialización o cuando |
| 334 | +se pierda el registro de finalización del contenedor de inicialización debido a la recolección de basura. Esto |
| 335 | +se aplica a Kubernetes v1.20 y posteriores. Si estás utilizando una versión anterior de |
| 336 | +Kubernetes, consulta la documentación de la versión que estás utilizando. |
| 337 | + |
| 338 | +## {{% heading "whatsnext" %}} |
| 339 | + |
| 340 | +* Lee acerca de [creando un Pod que tiene un contenedor de inicialización](/docs/tasks/configure-pod-container/configure-pod-initialization/#create-a-pod-that-has-an-init-container) |
| 341 | +* Aprende cómo [depurar contenedores de inicialización](/docs/tasks/debug-application-cluster/debug-init-containers/) |
0 commit comments