[es] Add content/es/docs/concepts/workloads/pods/init-containers.md
This commit is contained in:
parent
df256aaee5
commit
bf38b5f17a
|
@ -0,0 +1,341 @@
|
|||
---
|
||||
title: Contenedores de Inicialización
|
||||
content_type: concept
|
||||
weight: 40
|
||||
---
|
||||
|
||||
<!-- overview -->
|
||||
Esta página proporciona una descripción general de los contenedores de inicialización: contenedores especializados que se ejecutan
|
||||
antes de los contenedores de aplicación en un {{< glossary_tooltip text="Pod" term_id="pod" >}}.
|
||||
Los contenedores de inicialización pueden contener utilidades o scripts de instalación no presentes en una imagen de aplicación.
|
||||
|
||||
Tú puedes especificar contenedores de inicialización en la especificación del Pod junto con el array `containers`
|
||||
(el cual describe los contenedores de aplicación).
|
||||
|
||||
<!-- body -->
|
||||
## Entendiendo los contenedores de inicialización
|
||||
|
||||
Un {{< glossary_tooltip text="Pod" term_id="pod" >}} puede tener múltiples contenedores
|
||||
ejecutando applicaciones dentro de él, pero también puede tener uno o más contenedores de inicialización
|
||||
que se ejecutan antes de que se inicien los contenedores de aplicación.
|
||||
|
||||
Los contenedores de inicialización son exactamente iguales a los contenedores regulares excepto por:
|
||||
|
||||
* Los contenedores de inicialización siempre se ejecutan hasta su finalización.
|
||||
* Cada contenedor de inicialiación debe completarse correctamente antes de que comience el siguiente.
|
||||
|
||||
Si el contenedor de inicialización de un Pod falla, kubelet reinicia repetidamente ese contenedor de inicialización hasta que tenga éxito.
|
||||
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 en general al Pod como fallido.
|
||||
|
||||
Para especificar un contenedor de inicialización para un Pod, agrega el campo `initContainers` en
|
||||
la [especificación del Pod](/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodSpec),
|
||||
como un array de elementos `container` (similar al campo `containers` de aplicación y su contenido).
|
||||
Consulta [Container](/docs/reference/kubernetes-api/workload-resources/pod-v1/#Container) en la
|
||||
referencia de API para más detalles.
|
||||
|
||||
El estado de los contenedores de inicialización se devuelve en el campo `.status.initContainerStatuses`
|
||||
como un array de los estados del contenedor (similar al campo `.status.containerStatuses`).
|
||||
|
||||
### Diferencias con los contenedores regulares
|
||||
|
||||
Los contenedores de inicialización admiten todos los campos y características de los contenedores de aplicaciones,
|
||||
incluidos los límites de recursos, los volúmenes y la configuración de seguridad. Sin embargo, las
|
||||
solicitudes de recursos y los límites para un contenedor de inicialización se manejan de manera diferente,
|
||||
como se documenta en [Recursos](#resources).
|
||||
|
||||
Además, los contenedores de inicialización no admiten `lifecycle`, `livenessProbe`, `readinessProbe` o
|
||||
`startupProbe` porque deben de ejecutarse hasta su finalización antes de que el Pod pueda estar listo.
|
||||
|
||||
Si especificas varios contenedores de inicialización para un Pod, kubelet ejecuta cada contenedor
|
||||
de inicialización secuencialmente. Cada contenedor de inicialización debe tener éxito antes de que se pueda ejecutar el siguiente.
|
||||
Cuando todos los contenedores de inicialización se hayan ejecutado hasta su finalización, kubelet inicializa
|
||||
los contenedores de aplicación para el Pod y los ejecuta como de costumbre.
|
||||
|
||||
### Usando contenedores de inicialización
|
||||
|
||||
Dado que los contenedores de inicialización tienen imágenes separadas de los contenedores de aplicaciones, estos
|
||||
tienen algunas ventajas sobre el código relacionado de inicio:
|
||||
|
||||
* Los contenedores de inicialización pueden contener utilidades o código personalizado para la configuración que no están presentes en una
|
||||
imagen de aplicación. Por ejemplo, no hay necesidad de hacer una imagen `FROM` de otra imagen solo para usar una herramienta como
|
||||
`sed`, `awk`, `python` o `dig` durante la instalación.
|
||||
* Los roles de constructor e implementador de imágenes de aplicación pueden funcionar de forma independiente sin
|
||||
la necesidad de construir conjuntamente una sola imagen de aplicación.
|
||||
* Los contenedores de inicialización pueden ejecutarse con una vista diferente al sistema de archivos que los contenedores de aplicaciones en
|
||||
el mismo Pod. En consecuencia, se les puede dar acceso a
|
||||
{{<glossary_tooltip text = "Secrets" term_id = "secret">}} a los que los contenedores de aplicaciones no pueden acceder.
|
||||
* 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
|
||||
un mecanismo para bloquear o retrasar el inicio del contenedor de aplicación hasta que se cumplan una serie de condiciones previas. Una vez
|
||||
que las condiciones previas se cumplen, todos los contenedores de aplicaciones de un Pod pueden iniciarse en paralelo.
|
||||
* 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
|
||||
de contenedor menos segura. Si mantiene separadas herramientas innecesarias, puede limitar la superficie de ataque
|
||||
a la imagen del contenedor de aplicación.
|
||||
|
||||
### Ejemplos
|
||||
|
||||
A continuación, se muestran algunas ideas sobre cómo utilizar los contenedores de inicialización:
|
||||
|
||||
* Esperar a que se cree un {{< glossary_tooltip text="Service" term_id="service">}}
|
||||
usando un comando de una línea de shell:
|
||||
|
||||
```shell
|
||||
for i in {1..100}; do sleep 1; if dig myservice; then exit 0; fi; done; exit 1
|
||||
```
|
||||
|
||||
* Registrar este Pod con un servidor remoto desde la downward API con un comando como:
|
||||
|
||||
```shell
|
||||
curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'
|
||||
```
|
||||
|
||||
* Esperar algo de tiempo antes de iniciar el contenedor de aplicación con un comando como:
|
||||
|
||||
```shell
|
||||
sleep 60
|
||||
```
|
||||
|
||||
* Clonar un repositorio de Git en un {{< glossary_tooltip text="Volume" term_id="volume" >}}
|
||||
|
||||
* Colocar valores en un archivo de configuración y ejecutar una herramienta de plantilla para generar
|
||||
dinámicamente un archivo de configuración para el contenedor de aplicación principal. Por ejemplo,
|
||||
colocar el valor `POD_IP` en una configuración y generar el archivo de configuración
|
||||
de la aplicación principal usando Jinja.
|
||||
|
||||
#### Contenedores de inicialización en uso
|
||||
|
||||
Este ejemplo define un simple Pod que tiene dos contenedores de inicialización.
|
||||
El primero espera por `myservice` y el segundo espera por `mydb`. Una vez que ambos
|
||||
contenedores de inicialización se completen, el Pod ejecuta el contenedor de aplicación desde su sección `spec`.
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: myapp-pod
|
||||
labels:
|
||||
app: myapp
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp-container
|
||||
image: busybox:1.28
|
||||
command: ['sh', '-c', 'echo ¡La aplicación se está ejecutando! && sleep 3600']
|
||||
initContainers:
|
||||
- name: init-myservice
|
||||
image: busybox:1.28
|
||||
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"]
|
||||
- name: init-mydb
|
||||
image: busybox:1.28
|
||||
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"]
|
||||
```
|
||||
|
||||
Puedes iniciar este Pod ejecutando:
|
||||
|
||||
```shell
|
||||
kubectl apply -f myapp.yaml
|
||||
```
|
||||
|
||||
El resultado es similar a esto:
|
||||
|
||||
```shell
|
||||
pod/myapp-pod created
|
||||
```
|
||||
|
||||
Y verificar su estado con:
|
||||
|
||||
```shell
|
||||
kubectl get -f myapp.yaml
|
||||
```
|
||||
|
||||
El resultado es similar a esto:
|
||||
|
||||
```shell
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
myapp-pod 0/1 Init:0/2 0 6m
|
||||
```
|
||||
|
||||
o para más detalles:
|
||||
|
||||
```shell
|
||||
kubectl describe -f myapp.yaml
|
||||
```
|
||||
|
||||
El resultado es similar a esto:
|
||||
|
||||
```shell
|
||||
Name: myapp-pod
|
||||
Namespace: default
|
||||
[...]
|
||||
Labels: app=myapp
|
||||
Status: Pending
|
||||
[...]
|
||||
Init Containers:
|
||||
init-myservice:
|
||||
[...]
|
||||
State: Running
|
||||
[...]
|
||||
init-mydb:
|
||||
[...]
|
||||
State: Waiting
|
||||
Reason: PodInitializing
|
||||
Ready: False
|
||||
[...]
|
||||
Containers:
|
||||
myapp-container:
|
||||
[...]
|
||||
State: Waiting
|
||||
Reason: PodInitializing
|
||||
Ready: False
|
||||
[...]
|
||||
Events:
|
||||
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
|
||||
--------- -------- ----- ---- ------------- -------- ------ -------
|
||||
16s 16s 1 {default-scheduler } Normal Scheduled Successfully assigned myapp-pod to 172.17.4.201
|
||||
16s 16s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulling pulling image "busybox"
|
||||
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulled Successfully pulled image "busybox"
|
||||
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Created Created container with docker id 5ced34a04634; Security:[seccomp=unconfined]
|
||||
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Started Started container with docker id 5ced34a04634
|
||||
```
|
||||
|
||||
Para ver los logs de los contenedores de inicialización en este Pod ejecuta:
|
||||
|
||||
```shell
|
||||
kubectl logs myapp-pod -c init-myservice # Inspecciona el primer contenedor de inicialización
|
||||
kubectl logs myapp-pod -c init-mydb # Inspecciona el segundo contenedor de inicialización
|
||||
```
|
||||
|
||||
En este punto, estos contenedores de inicialización estarán esperando para descubrir los Servicios denominados
|
||||
`mydb` y `myservice`.
|
||||
|
||||
Aquí hay una configuración que puedes usar para que aparezcan esos Servicios:
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: myservice
|
||||
spec:
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 9376
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: mydb
|
||||
spec:
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 9377
|
||||
```
|
||||
|
||||
Para crear los servicios de `mydb` y `myservice`:
|
||||
|
||||
```shell
|
||||
kubectl apply -f services.yaml
|
||||
```
|
||||
|
||||
El resultado es similar a esto:
|
||||
|
||||
```shell
|
||||
service/myservice created
|
||||
service/mydb created
|
||||
```
|
||||
|
||||
Luego verás que esos contenedores de inicialización se completan y que el Pod `myapp-pod`
|
||||
pasa al estado `Running`:
|
||||
|
||||
```shell
|
||||
kubectl get -f myapp.yaml
|
||||
```
|
||||
|
||||
El resultado es similar a esto:
|
||||
|
||||
```shell
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
myapp-pod 1/1 Running 0 9m
|
||||
```
|
||||
|
||||
Este sencillo ejemplo debería servirte de inspiración para crear tus propios
|
||||
contenedores de inicialización. [What's next](#what-s-next) contiene un enlace a un ejemplo más detallado.
|
||||
|
||||
## Comportamiento detallado
|
||||
|
||||
Durante el inicio del Pod, kubelet retrasa la ejecución de contenedores de inicialización hasta que la red
|
||||
y el almacenamiento estén listos. Después, kubelet ejecuta los contenedores de inicialización del Pod en el orden que
|
||||
aparecen en la especificación del Pod.
|
||||
|
||||
Cada contenedor de inicialización debe salir correctamente antes de que
|
||||
comience el siguiente contenedor. Si un contenedor falla en iniciar debido al tiempo de ejecución o
|
||||
sale con una falla, se vuelve a intentar de acuerdo con el `restartPolicy` del Pod. Sin embargo,
|
||||
si el `restartPolicy` del Pod se establece en `Always`, los contenedores de inicialización usan
|
||||
el `restartPolicy` como `OnFailure`.
|
||||
|
||||
Un Pod no puede estar `Ready` sino hasta que todos los contenedores de inicialización hayan tenido éxito. Los puertos en un
|
||||
contenedor de inicialización no se agregan a un Servicio. Un Pod que se está inicializando,
|
||||
está en el estado de `Pending`, pero debe tener una condición `Initialized` configurada como falsa.
|
||||
|
||||
Si el Pod [se reinicia](#pod-restart-reasons) o es reiniciado, todos los contenedores de inicialización
|
||||
deben ejecutarse de nuevo.
|
||||
|
||||
Los cambios en la especificación del contenedor de inicialización se limitan al campo de la imagen del contenedor.
|
||||
Alterar un campo de la imagen del contenedor de inicialización equivale a reiniciar el Pod.
|
||||
|
||||
Debido a que los contenedores de inicialización se pueden reiniciar, reintentar o volverse a ejecutar, el código del contenedor de inicialización
|
||||
debe ser idempotente. En particular, el código que escribe en archivos en `EmptyDirs`
|
||||
debe estar preparado para la posibilidad de que ya exista un archivo de salida.
|
||||
|
||||
Los contenedores de inicialización tienen todos los campos de un contenedor de aplicaciones. Sin embargo, Kubernetes
|
||||
prohíbe el uso de `readinessProbe` porque los contenedores de inicialización no pueden
|
||||
definir el `readiness` distinto de la finalización. Esto se aplica durante la validación.
|
||||
|
||||
Usa `activeDeadlineSeconds` en el Pod para prevenir que los contenedores de inicialización fallen por siempre.
|
||||
La fecha límite incluye contenedores de inicialización.
|
||||
Sin embargo, se recomienda utilizar `activeDeadlineSeconds` si el usuario implementa su aplicación
|
||||
como un `Job` porque `activeDeadlineSeconds` tiene un efecto incluso después de que `initContainer` finaliza.
|
||||
El Pod que ya se está ejecutando correctamente sería eliminado por `activeDeadlineSeconds` si lo estableces.
|
||||
|
||||
El nombre de cada aplicación y contenedor de inicialización en un Pod debe ser único; un
|
||||
error de validación es arrojado para cualquier contenedor que comparta un nombre con otro.
|
||||
|
||||
### Recursos
|
||||
|
||||
Dado el orden y la ejecución de los contenedores de inicialización, las siguientes reglas
|
||||
para el uso de recursos se aplican:
|
||||
|
||||
* La más alta de cualquier solicitud particular de recurso o límite definido en todos los contenedores
|
||||
de inicialización es la *solicitud/límite de inicialización efectiva*. Si algún recurso no tiene un
|
||||
límite de recursos especificado éste se considera como el límite más alto.
|
||||
* La *solicitud/límite efectiva* para un recurso es la más alta entre:
|
||||
* la suma de todas las solicitudes/límites de los contenedores de aplicación, y
|
||||
* la solicitud/límite de inicialización efectiva para un recurso
|
||||
* La planificación es hecha con base en las solicitudes/límites efectivos, lo que significa
|
||||
que los contenedores de inicialización pueden reservar recursos para la inicialización que no se utilizan
|
||||
durante la vida del Pod.
|
||||
* El nivel de `QoS` (calidad de servicio) del *nivel de `QoS` efectivo* del Pod es el
|
||||
nivel de `QoS` tanto para los contenedores de inicialización como para los contenedores de aplicación.
|
||||
|
||||
La cuota y los límites son aplicados con base en la solicitud y límite efectivos de Pod.
|
||||
|
||||
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 scheduler.
|
||||
|
||||
### Razones de reinicio del Pod
|
||||
|
||||
Un Pod puede reiniciarse, provocando la re-ejecución de los contenedores de inicialización por las siguientes razones:
|
||||
|
||||
* 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.
|
||||
* Todos los contenedores en un Pod son terminados mientras `restartPolicy` esté configurado en `Always`,
|
||||
forzando un reinicio y el registro de finalización del contenedor de inicialización se ha perdido debido a
|
||||
la recolección de basura.
|
||||
|
||||
El Pod no se reiniciará cuando se cambie la imagen del contenedor de inicialización o cuando
|
||||
se pierda el registro de finalización del contenedor de inicialización debido a la recolección de basura. Esto
|
||||
se aplica a Kubernetes v1.20 y posteriores. Si estás utilizando una versión anterior de
|
||||
Kubernetes, consulta la documentación de la versión que estás utilizando.
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
* Lee acerca sobre [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)
|
||||
* Aprende cómo [depurar contenedores de inicialización](/docs/tasks/debug-application-cluster/debug-init-containers/)
|
Loading…
Reference in New Issue