Merge branch 'master' of https://github.com/kubernetes/website into es/docs/concepts_workloads_controllers/jobs-run_and_replicaset

This commit is contained in:
Enrique Medina Montenegro
2020-06-07 10:14:37 +02:00
4380 changed files with 418943 additions and 434664 deletions
@@ -0,0 +1,61 @@
---
title: CronJob
content_template: templates/concept
weight: 80
---
{{% capture overview %}}
Un _Cron Job_ ejecuta tareas, [Jobs](/docs/concepts/workloads/controllers/jobs-run-to-completion/), a intervalos regulares.
Un objeto CronJob es como una línea de un archivo _crontab_ (tabla cron). Ejecuta un trabajo de forma periódica
según un horario programado escrito en formato [Cron](https://en.wikipedia.org/wiki/Cron).
{{< note >}}
Todos los `horarios` **CronJob** se basan en la zona horaria del máster donde se inicia el trabajo.
{{< /note >}}
Para instrucciones sobre cómo crear y trabajar con trabajos programados,
incluyendo definiciones de ejemplo,
puedes consultar [Ejecutar tareas automatizadas con trabajos programados](/docs/tasks/job/automated-tasks-with-cron-jobs).
{{% /capture %}}
{{% capture body %}}
## Limitaciones de las tareas programados
Un trabajo programado crea un objeto job _como mínimo_ una vez por cada ejecución de su programación. Decimos "como mínimo" porque
hay determinadas circunstancias bajo las cuales dos trabajos pueden crearse, o ninguno de ellos se crea. Se intenta que estos casos sean residuales,
pero no pueden evitarse completamente. Por lo tanto, los trabajos deberían ser _idempotentes_, es decir, que se pueden ejecutar más de una vez con el mismo resultado.
Si el valor de `startingDeadlineSeconds` se establece a un valor grande o se deja sin especificar (por defecto)
y si el valor de `concurrencyPolicy` se establece a `Allow`, los trabajos siempre se ejecutarán por lo menos una vez.
Para cada CronJob, el controlador de CronJob verifica cuántas programaciones se han perdido desde la última programación hasta el momento actual.
Si hay más de 100 programaciones perdidas, entonces ya no vuelve a ejecutar el trabajo y registra el error:
````
Cannot determine if job needs to be started. Too many missed start time (> 100). Set or decrease .spec.startingDeadlineSeconds or check clock skew.
````
Es importante destacar que si el campo `startingDeadlineSeconds` está configurado, es decir, no es nulo (`nil`), el controlador cuenta cuántos trabajos perdidos se produjeron desde el valor de `startingDeadlineSeconds`
hasta el momento actual, en vez de la última programación. Por ejemplo, si `startingDeadlineSeconds` es `200`, el controlador cuenta cuántos trabajos perdidos se produjeron en los últimos 200 segundos.
Se cuenta un CronJob como perdido si no se ha podido crear a la hora programada. Por ejemplo, si establecemos el valor de `concurrencyPolicy` a `Forbid` y se intentó programar
un CronJob cuando otro previamente programado estaba todavía ejecutándose, entonces contará como perdido.
Por ejemplo, imagina que un CronJob se configura para programar un nuevo Job cada minuto a partir de las `08:30:00`, y su campo
`startingDeadlineSeconds` no se configura. Si el controlador del CronJob no estuviera disponible de `08:29:00` a `10:21:00`,
el trabajo no comenzaría porque el número de trabajos perdidos que se habría perdido en su programación sería superior a 100.
Para ilustrar este concepto mejor, vamos a suponer que programamos un CronJob para que ejecute un nuevo Job cada minuto comenzando a las `08:30:00`, y establecemos el valor del campo
`startingDeadlineSeconds` a 200 segundos. Si el controlador del CronJob no se encuentra disponible
durante el mismo período que en el ejemplo anterior (`08:29:00` a `10:21:00`,) aún así el Job comenzará a las 10:22:00.
Esto ocurre porque el controlador en este caso comprueba cuántas programaciones perdidas ha habido en los últimos 200 segundos (esto es, 3 programaciones que no se han ejecutado), en vez de comprobarlo a partir de la última programación hasta el momento actual.
El CronJob es únicamente responsable de crear los Jobs que coinciden con su programación, y
el Job por otro lado es el responsable de gestionar los Pods que representa.
{{% /capture %}}
@@ -0,0 +1,238 @@
---
title: DaemonSet
content_template: templates/concept
weight: 50
---
{{% capture overview %}}
Un _DaemonSet_ garantiza que todos (o algunos) de los nodos ejecuten una copia de un Pod. Conforme se añade más nodos
al clúster, nuevos Pods son añadidos a los mismos. Conforme se elimina nodos del clúster, dichos Pods se destruyen.
Al eliminar un DaemonSet se limpian todos los Pods que han sido creados.
Algunos casos de uso típicos de un DaemonSet son:
- ejecutar un proceso de almacenamiento en el clúster, como `glusterd`, `ceph`, en cada nodo.
- ejecutar un proceso de recolección de logs en cada nodo, como `fluentd` o `logstash`.
- ejecutar un proceso de monitorización de nodos en cada nodo, como [Prometheus Node Exporter](
https://github.com/prometheus/node_exporter), [Sysdig Agent] (https://sysdigdocs.atlassian.net/wiki/spaces/Platform), `collectd`,
[Dynatrace OneAgent](https://www.dynatrace.com/technologies/kubernetes-monitoring/),
[AppDynamics Agent](https://docs.appdynamics.com/display/CLOUD/Container+Visibility+with+Kubernetes),
[Datadog agent](https://docs.datadoghq.com/agent/kubernetes/daemonset_setup/),
[New Relic agent](https://docs.newrelic.com/docs/integrations/kubernetes-integration/installation/kubernetes-installation-configuration),
Ganglia `gmond` o un agente de Instana.
De forma básica, se debería usar un DaemonSet, cubriendo todos los nodos, por cada tipo de proceso.
En configuraciones más complejas se podría usar múltiples DaemonSets para un único tipo de proceso,
pero con diferentes parámetros y/o diferentes peticiones de CPU y memoria según el tipo de hardware.
{{% /capture %}}
{{% capture body %}}
## Escribir una especificación de DaemonSet
### Crear un DaemonSet
Un DaemonSet se describe por medio de un archivo YAML. Por ejemplo, el archivo `daemonset.yaml` de abajo describe un DaemonSet que ejecuta la imagen Docker de fluentd-elasticsearch:
{{< codenew file="controllers/daemonset.yaml" >}}
* Crear un DaemonSet basado en el archivo YAML:
```
kubectl apply -f https://k8s.io/examples/controllers/daemonset.yaml
```
### Campos requeridos
Como con cualquier otra configuración de Kubernetes, un DaemonSet requiere los campos `apiVersion`, `kind`, y `metadata`.
Para información general acerca de cómo trabajar con ficheros de configuración, ver los documentos [desplegar aplicaciones](/docs/user-guide/deploying-applications/),
[configurar contenedores](/docs/tasks/), y [gestión de objetos usando kubectl](/docs/concepts/overview/object-management-kubectl/overview/).
Un DaemonSet también necesita un sección [`.spec`](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status).
### Plantilla Pod
El campo `.spec.template` es uno de los campos obligatorios de la sección `.spec`.
El campo `.spec.template` es una [plantilla Pod](/docs/concepts/workloads/pods/pod-overview/#pod-templates). Tiene exactamente el mismo esquema que un [Pod](/docs/concepts/workloads/pods/pod/),
excepto por el hecho de que está anidado y no tiene los campos `apiVersion` o `kind`.
Además de los campos obligatorios de un Pod, la plantilla Pod para un DaemonSet debe especificar
las etiquetas apropiadas (ver [selector de pod](#pod-selector)).
Una plantilla Pod para un DaemonSet debe tener una [`RestartPolicy`](/docs/user-guide/pod-states)
igual a `Always`, o no indicarse, lo cual asume por defecto el valor `Always`.
### Selector de Pod
El campo `.spec.selector` es un selector de pod. Funciona igual que el campo `.spec.selector`
de un [Job](/docs/concepts/jobs/run-to-completion-finite-workloads/).
A partir de Kubernetes 1.8, se debe configurar un selector de pod que coincida con las
etiquetas definidas en el `.spec.template`. Así, el selector de pod ya no asume valores por defecto cuando no se indica.
Dichos valores por defecto no eran compatibles con `kubectl apply`. Además, una vez que se ha creado el DaemonSet,
su campo `.spec.selector` no puede alterarse porque, si fuera el caso, ello podría resultar
en Pods huérfanos, lo cual confundiría a los usuarios.
El campo `.spec.selector` es un objeto que, a su vez, consiste en dos campos:
* `matchLabels` - funciona igual que el campo `.spec.selector` de un [ReplicationController](/docs/concepts/workloads/controllers/replicationcontroller/).
* `matchExpressions` - permite construir selectores más sofisticados indicando la clave,
la lista de valores y un operador para relacionar la clave y los valores.
Cuando se configura ambos campos, el resultado es conjuntivo (AND).
Si se especifica el campo `.spec.selector`, entonces debe coincidir con el campo `.spec.template.metadata.labels`. Aquellas configuraciones que no coinciden, son rechazadas por la API.
Además, normalmente no se debería crear ningún Pod con etiquetas que coincidan con el selector, bien sea de forma directa, via otro
DaemonSet, o via otro controlador como un ReplicaSet. De ser así, el controlador del DaemonSet
pensará que dichos Pods fueron en realidad creados por él mismo. Kubernetes, en cualquier caso, no te impide realizar esta
operación. Un caso donde puede que necesites hacer esto es cuando quieres crear manualmente un Pod con un valor diferente en un nodo para pruebas.
### Ejecutar Pods sólo en algunos Nodos
Si se configura un `.spec.template.spec.nodeSelector`, entonces el controlador del DaemonSet
creará los Pods en aquellos nodos que coincidan con el [selector de nodo](/docs/concepts/configuration/assign-pod-node/) indicado.
De forma similar, si se configura una `.spec.template.spec.affinity`,
entonces el controlador del DaemonSet creará los Pods en aquellos nodos que coincidan con la [afinidad de nodo](/docs/concepts/configuration/assign-pod-node/) indicada.
Si no se configura ninguno de los dos, entonces el controlador del DaemonSet creará los Pods en todos los nodos.
## Cómo se planifican los Pods procesos
### Planificados por el controlador del DaemonSet (deshabilitado por defecto a partir de 1.12)
Normalmente, el planificador de Kubernetes determina la máquina donde se ejecuta un Pod. Sin embargo, los Pods
creados por el controlador del DaemonSet ya tienen la máquina seleccionada (puesto que cuando se crea el Pod,
se indica el campo `.spec.nodeName`, y por ello el planificador los ignora). Por lo tanto:
- El controlador del DaemonSet no tiene en cuenta el campo [`unschedulable`](/docs/admin/node/#manual-node-administration) de un nodo.
- El controlador del DaemonSet puede crear Pods incluso cuando el planificador no ha arrancado, lo cual puede ayudar en el arranque del propio clúster.
### Planificados por el planificador por defecto de Kubernetes (habilitado por defecto desde 1.12)
{{< feature-state state="beta" for-kubernetes-version="1.12" >}}
Un DaemonSet garantiza que todos los nodos elegibles ejecuten una copia de un Pod.
Normalmente, es el planificador de Kubernetes quien determina el nodo donde se ejecuta un Pod. Sin embargo,
los pods del DaemonSet son creados y planificados por el mismo controlador del DaemonSet.
Esto introduce los siguientes inconvenientes:
* Comportamiento inconsistente de los Pods: Los Pods normales que están esperando
a ser creados, se encuentran en estado `Pending`, pero los pods del DaemonSet no pasan por el estado `Pending`.
Esto confunde a los usuarios.
* La [prioridad y el comportamiento de apropiación de Pods](/docs/concepts/configuration/pod-priority-preemption/)
se maneja por el planificador por defecto. Cuando se habilita la contaminación, el controlador del DaemonSet
tomará la decisiones de planificación sin considerar ni la prioridad ni la contaminación del pod.
`ScheduleDaemonSetPods` permite planificar DaemonSets usando el planificador por defecto
en vez del controlador del DaemonSet, añadiendo la condición `NodeAffinity`
a los pods del DaemonSet, en vez de la condición `.spec.nodeName`. El planificador por defecto
se usa entonces para asociar el pod a su servidor destino. Si la afinidad de nodo del
pod del DaemonSet ya existe, se sustituye. El controlador del DaemonSet sólo realiza
estas operaciones cuando crea o modifica los pods del DaemonSet, y no se realizan cambios
al `spec.template` del DaemonSet.
```yaml
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchFields:
- key: metadata.name
operator: In
values:
- target-host-name
```
Adicionalmente, se añade de forma automática la tolerancia `node.kubernetes.io/unschedulable:NoSchedule`
a los Pods del DaemonSet. Así, el planificador por defecto ignora los nodos
`unschedulable` cuando planifica los Pods del DaemonSet.
### Contaminaciones (taints) y Tolerancias (tolerations)
A pesar de que los Pods de proceso respetan las
[contaminaciones y tolerancias](/docs/concepts/configuration/taint-and-toleration),
la siguientes tolerancias son añadidas a los Pods del DaemonSet de forma automática
según las siguientes características:
| Clave de tolerancia | Efecto | Versión | Descripción |
| ---------------------------------------- | ---------- | ------- | ------------------------------------------------------------ |
| `node.kubernetes.io/not-ready` | NoExecute | 1.13+ | Los pods del DaemonSet no son expulsados cuando hay problemas de nodo como una partición de red. |
| `node.kubernetes.io/unreachable` | NoExecute | 1.13+ | Los pods del DaemonSet no son expulsados cuando hay problemas de nodo como una partición de red. |
| `node.kubernetes.io/disk-pressure` | NoSchedule | 1.8+ | Los pods del DaemonSet no son expulsados cuando hay problemas de nodo como la falta de espacio en disco. |
| `node.kubernetes.io/memory-pressure` | NoSchedule | 1.8+ | Los pods del DaemonSet no son expulsados cuando hay problemas de nodo como la falta de memoria. |
| `node.kubernetes.io/unschedulable` | NoSchedule | 1.12+ | Los pods del DaemonSet toleran los atributos unschedulable del planificador por defecto. |
| `node.kubernetes.io/network-unavailable` | NoSchedule | 1.12+ | Los pods del DaemonSet, que usan la red del servidor anfitrión, toleran los atributos network-unavailable del planificador por defecto. |
## Comunicarse con los Pods de los DaemonSets
Algunos patrones posibles para la comunicación con los Pods de un DaemonSet son:
- **Push**: Los Pods del DaemonSet se configuran para enviar actualizaciones a otro servicio,
como una base de datos de estadísticas. No tienen clientes.
- **NodeIP y Known Port**: Los Pods del DaemonSet pueden usar un `hostPort`, de forma que se les puede alcanzar via las IPs del nodo. Los clientes conocen la lista de IPs del nodo de algún modo,
y conocen el puerto acordado.
- **DNS**: Se crea un [servicio headless](/docs/concepts/services-networking/service/#headless-services) con el mismo selector de pod,
y entonces se descubre a los DaemonSets usando los recursos `endpoints` o mediante múltiples registros de tipo A en el DNS.
- **Service**: Se crea un servicio con el mismo selector de Pod, y se usa el servicio para llegar al proceso de uno de los nodos. (No hay forma de determinar el nodo exacto.)
## Actualizar un DaemonSet
Si se cambian las etiquetas de nodo, el DaemonSet comenzará de forma inmediata a añadir Pods a los nuevos nodos que coincidan y a eliminar
los Pods de aquellos nuevos nodos donde no coincidan.
Puedes modificar los Pods que crea un DaemonSet. Sin embargo, no se permite actualizar todos los campos de los Pods.
Además, el controlador del DaemonSet utilizará la plantilla original la próxima vez que se cree un nodo (incluso con el mismo nombre).
Puedes eliminar un DaemonSet. Si indicas el parámetro `--cascade=false` al usar `kubectl`,
entonces los Pods continuarán ejecutándose en los nodos. Así, puedes crear entonces un nuevo DaemonSet con una plantilla diferente.
El nuevo DaemonSet con la plantilla diferente reconocerá a todos los Pods existentes que tengan etiquetas coincidentes y
no modificará o eliminará ningún Pod aunque la plantilla no coincida con los Pods desplegados.
Entonces, deberás forzar la creación del nuevo Pod eliminando el Pod mismo o el nodo.
A partir de las versión 1.6 de Kubernetes, puedes [llevar a cabo una actualización continua](/docs/tasks/manage-daemon/update-daemon-set/) en un DaemonSet.
## Alternativas al DaemonSet
### Secuencias de comandos de inicialización
Aunque es perfectamente posible ejecutar procesos arrancándolos directamente en un nodo (ej. usando
`init`, `upstartd`, o `systemd`), existen numerosas ventajas si se realiza via un DaemonSet:
- Capacidad de monitorizar y gestionar los logs de los procesos del mismo modo que para las aplicaciones.
- Mismo lenguaje y herramientas de configuración (ej. plantillas de Pod, `kubectl`) tanto para los procesos como para las aplicaciones.
- Los procesos que se ejecutan en contenedores con límitaciones de recursos aumentan el aislamiento entre dichos procesos y el resto de contenedores de aplicaciones.
Sin embargo, esto también se podría conseguir ejecutando los procesos en un contenedor en vez de un Pod
(ej. arrancarlos directamente via Docker).
### Pods individuales
Es posible crear Pods directamente sin indicar el nodo donde ejecutarse. Sin embargo,
la ventaja del DaemonSet es que sustituye los Pods que se eliminan o terminan por cualquier razón, como en el caso
de un fallo del nodo o una intervención disruptiva de mantenimiento del nodo, como la actualización del kernel.
Por esta razón, deberías siempre utilizar un DaemonSet en vez de crear Pods individuales.
### Pods estáticos
Es posible crear Pods a partir de archivos en el directorio donde está escuchando el proceso Kubelet.
Este tipo de Pods se denomina [pods estáticos](/docs/concepts/cluster-administration/static-pod/).
A diferencia del DaemonSet, los Pods estáticos no se pueden gestionar con kubectl
o cualquier otro cliente de la API de Kubernetes. Los Pods estáticos no dependen del apiserver, lo cual los hace
convenientes para el arranque inicial del clúster. Además, puede que los Pods estáticos se deprecien en el futuro.
### Deployments
Los DaemonSets son similares a los [Deployments](/docs/concepts/workloads/controllers/deployment/) en el sentido que
ambos crean Pods, y que dichos Pods tienen procesos que no se espera que terminen (ej. servidores web,
servidores de almacenamiento).
Utiliza un Deployment para definir servicios sin estado, como las interfaces de usuario, donde el escalado vertical y horizontal
del número de réplicas y las actualizaciones continuas son mucho más importantes que el control exacto del servidor donde se ejecuta el Pod.
Utiliza un DaemonSet cuando es importante que una copia de un Pod siempre se ejecute en cada uno de los nodos,
y cuando se necesite que arranque antes que el resto de Pods.
{{% /capture %}}
@@ -0,0 +1,332 @@
---
title: ReplicationController
feature:
title: Auto-reparación
anchor: Cómo funciona un ReplicationController
description: >
Reinicia contenedores que fallan, sustituye y reprograma contenedores cuando los nodos mueren,
mata los contenedores que no responden a tus pruebas de salud definidas,
y no los expone a los clientes hasta que no están listo para servirse.
content_template: templates/concept
weight: 20
---
{{% capture overview %}}
{{< note >}}
hoy en día la forma recomendada de configurar la replicación es con un [`Deployment`](/docs/concepts/workloads/controllers/deployment/) que configura un [`ReplicaSet`](/docs/concepts/workloads/controllers/replicaset/).
{{< /note >}}
Un _ReplicationController_ garantiza que un número determinado de réplicas se estén ejecutando
en todo momento. En otras palabras, un ReplicationController se asegura que un pod o un conjunto homogéneo de pods
siempre esté arriba y disponible.
{{% /capture %}}
{{% capture body %}}
## Cómo Funciona un ReplicationController
Si hay muchos pods, el ReplicationController termina los pods extra. Si hay muy pocos, el
ReplicationController arranca más pods. A difrencia de los pods creados manualmente, los pods mantenidos por un
ReplicationController se sustituyen de forma automática si fallan, se borran, o se terminan.
Por ejemplo, tus pods se re-crean en un nodo durante una intervención disruptiva de mantenimiento como una actualización del kernel.
Por esta razón, deberías usar un ReplicationController incluso cuando tu aplicación sólo necesita
un único pod. Un ReplicationController es parecido a un supervisor de procesos,
pero en vez de supervisar procesos individuales en un único nodo,
el ReplicationController supervisa múltiples pods entre múltiples nodos.
A menudo nos referimos a un ReplicationController de forma abreviada como "rc" o "rcs", así como
atajo en los comandos de kubectl.
Un caso simple es crear un objeto ReplicationController para ejecutar de manera fiable una instancia
de un Pod indefinidamente. Un caso de uso más complejo es ejecutar varias réplicas idénticas
de un servicio replicado, como los servidores web.
## Ejecutar un ejemplo de ReplicationController
Esta configuración de un ReplicationController de ejemplo ejecuta tres copias del servidor web nginx.
{{< codenew file="controllers/replication.yaml" >}}
Ejecuta el ejemplo descargando el archivo de ejemplo y ejecutando este comando:
```shell
kubectl apply -f https://k8s.io/examples/controllers/replication.yaml
```
```
replicationcontroller/nginx created
```
Comprueba el estado del ReplicationController con este comando:
```shell
kubectl describe replicationcontrollers/nginx
```
```
Name: nginx
Namespace: default
Selector: app=nginx
Labels: app=nginx
Annotations: <none>
Replicas: 3 current / 3 desired
Pods Status: 0 Running / 3 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx
Port: 80/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- ---- ------ -------
20s 20s 1 {replication-controller } Normal SuccessfulCreate Created pod: nginx-qrm3m
20s 20s 1 {replication-controller } Normal SuccessfulCreate Created pod: nginx-3ntk0
20s 20s 1 {replication-controller } Normal SuccessfulCreate Created pod: nginx-4ok8v
```
Como se puede observar, se han creado tres pods, pero ninguno se está ejecutándose todavía,
puede que porque la imagen todavía se está descargando.
Unos momentos después, el mismo comando puede que muestre:
```shell
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
```
Para listar todos los pods que pertenecen al ReplicationController de forma legible,
puedes usar un comando como el siguiente:
```shell
pods=$(kubectl get pods --selector=app=nginx --output=jsonpath={.items..metadata.name})
echo $pods
```
```
nginx-3ntk0 nginx-4ok8v nginx-qrm3m
```
Como se puede ver, el selector es el mismo que el selector del ReplicationController (mostrado en la salida de
`kubectl describe`), y con una forma diferente a lo definido en el archivo `replication.yaml`.
La opción `--output=jsonpath` especifica una expresión que simplemente muestra el nombre
de cada pod en la lista devuelta.
## Escribir una especificación de ReplicationController
Al igual que con el resto de configuraciones de Kubernetes, un ReplicationController necesita los campos `apiVersion`, `kind`, y `metadata`.
Para información general acerca del trabajo con archivos de configuración, ver la [gestión de objetos](/docs/concepts/overview/object-management-kubectl/overview/).
Un ReplicationController también necesita un [sección `.spec`](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status).
### Plantilla Pod
El campo `.spec.template` es el único campo requerido de `.spec`.
El campo `.spec.template` es una [plantilla pod](/docs/concepts/workloads/pods/pod-overview/#pod-templates).
Tiene exactamente el mismo esquema que un [pod](/docs/concepts/workloads/pods/pod/), excepto por el hecho de que está anidado y no tiene los campos `apiVersion` ni `kind`.
Además de los campos obligatorios de un Pod, una plantilla pod de un ReplicationController debe especificar las etiquetas apropiadas
y la regla de reinicio apropiada. En el caso de las etiquetas, asegúrate que no se entremezclan con otros controladores. Ver el [selector de pod](#pod-selector).
Sólo se permite el valor `Always` para el campo [`.spec.template.spec.restartPolicy`](/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy),
que es el valor predeterminado si no se indica.
Para los reinicios locales de los contenedores, los ReplicationControllers delegan en los agentes del nodo,
por ejmplo el [Kubelet](/docs/admin/kubelet/) o Docker.
### Etiquetas en los ReplicationController
los ReplicationController puede tener sus propias (`.metadata.labels`). Normalmente, se indicaría dichas etiquetas
con los mismos valores que el campo `.spec.template.metadata.labels`; si el campo `.metadata.labels` no se indica,
entonces se predetermina al valor de `.spec.template.metadata.labels`. Sin embargo, se permite que sean diferentes,
y el valor de `.metadata.labels` no afecta al comportamiento del ReplicationController.
### Selector de Pod
El campo `.spec.selector` es un [selector de etiqueta](/docs/concepts/overview/working-with-objects/labels/#label-selectors). Un ReplicationController
gestiona todos los pods con etiquetas que coinciden con el selector. No distingue entre
pods que creó o eliminó, y pods que otra persona o proceso creó o eliminó. Esto permite sustituir al ReplicationController sin impactar a ninguno de sus pods que se esté ejecutando.
Si se indica, el valor de `.spec.template.metadata.labels` debe ser igual al de `.spec.selector`, o será rechazado por la API.
Si no se indica el valor de `.spec.selector`, se tomará como predeterminado el de `.spec.template.metadata.labels`.
Tampoco deberías crear ningún pod cuyas etiquetas coincidan con las de este selector, ni directamente con
otro ReplicationController, ni con otro controlador como un Job. Si lo haces, el
ReplicationController piensa que el creó también los otros pods. Kubernetes no te impide hacerlo.
Si al final terminas con múltiples controladores que tienen selectores que se entremezclan,
tendrás que gestionar la eliminación tú mismo (ver [abajo](#working-with-replicationcontrollers)).
### Múltiples Réplicas
Puedes configurar cuántos pods deberían ejecutarse de forma concurrente poniendo el valor de `.spec.replicas` al número
de pods que te gustaría tener ejecutándose a la vez. El número de ejecuciones en cualquier momento puede que sea superior
o inferior, dependiendo de si las réplicas se han incrementado o decrementado, o si un pod se ha apagado de forma controlada,
y su sustituto arranca más pronto.
Si no se indica el valor de `.spec.replicas`, entonces se predetermina a 1.
## Trabajar con ReplicationControllers
### Eliminar un ReplicationController y sus Pods
Para eliminar un ReplicationController y todos sus pods, usa el comando [`kubectl
delete`](/docs/reference/generated/kubectl/kubectl-commands#delete). Kubectl reducirá el ReplicationController a cero y esperará
que elimine cada pod antes de eliminar al ReplicationController mismo. Si este comando kubectl
se interrumpe, puede ser reiniciado.
Cuando uses la API REST o la librería Go, necesitas realizar los pasos de forma explícita (reducir las réplicas a cero,
esperar a que se eliminen los pods, y entonces eliminar el ReplicationController).
### Eliminar sólo el ReplicationController
Puedes eliminar un ReplicationController sin impactar a ninguno de sus Pods.
Usando kubectl, indica la opción `--cascade=false` en el comando [`kubectl delete`](/docs/reference/generated/kubectl/kubectl-commands#delete).
Cuando uses la API REST o la librería Go, simplemente elimina objeto ReplicationController.
Una vez que el objeto original se ha eliminado, puedes crear un nuevo ReplicationController para sustituirlo.
Mientras el viejo y el nuevo valor del `.spec.selector` sea el mismo, el nuevo adoptará a los viejos pods.
Sin embargo, no se molestará en hacer que los pods actuales coincidan con una plantilla pod nueva, diferente.
Para actualizar los pods con una nueva especificación de forma controlada, utiliza la [actualización en línea](#rolling-updates).
### Aislar pods de un ReplicationController
Se puede aislar Pods del conjunto destino de un ReplicationController cambiando sus etiquetas.
Esta técnica puede usarse para eliminar pods de un servicio para poder depurarlos, recuperar datos, etc.
Los Pods que se eliminan de esta forma serán sustituidos de forma automática (asumiendo que el número de réplicas no ha cambiado tampoco).
## Patrones comunes de uso
### Reprogramación
Como se comentó arriba, cuando tienes 1 pod que quieres mantener ejecutándose, o 1000, un ReplicationController se asegura de que el número indicado de pods exista,
incluso si falla un nodo o se termina algún pod (por ejemplo, debido a alguna acción de otro agente de control).
### Escalado
El ReplicationController facilita el escalado del número de réplicas tanto para su aumento como para su disminución,
bien manualmente o mediante un agente de auto-escalado, simplemente actualizando el campo `replicas`.
### Actualizaciones en línea
El ReplicationController se ha diseñado para facilitar las actualizaciones en línea de un servicio mediante la sustitución de sus pods uno por uno.
Cómo se explicó en [#1353](http://issue.k8s.io/1353), la estrategia recomendada es crear un nuevo ReplicationController con 1 réplica,
escalar el nuevo (+1) y el viejo (-1) controlador uno por uno, y entonces eliminar el viejo controlador una vez que alcanza las 0 réplicas.
Esto actualiza de forma predecible el conjunto de pods independientemente de que se produzcan fallos inesperados.
De forma ideal, el controlador de actualización en línea tendrá en cuenta si la aplicación está lista, y
se asegurará de que un número suficiente de pods está en servicio en todo momento.
Los dos ReplicationControllers necesitarán crear pods con al menos una etiqueta diferenciadora, como la etiqueta de imagen del contenedor primario del pod,
ya que las actualizaciones de imagen son las que normalmente desencadenan las actualizaciones en línea.
La actualización en línea se implementa a través de la herramienta cliente mediante
[`kubectl rolling-update`](/docs/reference/generated/kubectl/kubectl-commands#rolling-update).
Echa un vistazo a la [tarea `kubectl rolling-update`](/docs/tasks/run-application/rolling-update-replication-controller/) para más ejemplos concretos.
### Múltiples operaciones de despliegue
Además de llevar a cabo múltiples despliegues de una aplicación cuando una actualización en línea está en progreso,
es común ejecutar varios despliegues durante un período extendido de tiempo, o incluso de forma contínua, usando múltiples operaciones de despliegue. Dichas operaciones se diferenciarían por etiquetas.
Por ejemplo, un servicio puede que exponga todos los pods con etiquetas `tier in (frontend), environment in (prod)`. Ahora digamos que tenemos 10 pods replicados que forman este grupo.
Pero queremos poder desplegar una nueva versión 'canary' de este component. Se podría configurar un ReplicationController con el valor de `replicas` puesto a 9 para la mayor parte de las réplicas,
con etiquetas `tier=frontend, environment=prod, track=stable`, y otro ReplicationController con el valor de `replicas` puesto a 1 para el 'canary',
con las etiquetas `tier=frontend, environment=prod, track=canary`. Así el servicio cubriría tanto los pods canary como el resto.
Pero también es posible trastear con los ReplicationControllers de forma separada para probar cosas, monitorizar los resultados, etc.
### Usar ReplicationControllers con servicios
Un único servicio puede exponer múltiples ReplicationControllers, de forma que, por ejemplo, algo de tráfico
vaya a la versión vieja, y otro tanto vaya a la versión nueva.
Un ReplicationController nunca se terminará por sí mismo, pero tampoco se espera que se ejecute permanentemente como los servicios.
Los servicios puede que estén compuestos de pods controlados por múltiples ReplicationControllers,
y se espera que muchos ReplicationControllers se creen y se destruyan durante el ciclo de vida de un servicio (por ejemplo,
para realizar una actualización de los pods que ejecutan el servicio). Ambos servicios mismos y sus clientes deberían permanecer
ajenos a los ReplicationControllers que mantienen los pods que proporcionan los servicios.
## Escribir aplicaciones que se repliquen
Los Pods creados por un ReplicationController están pensados para que sean intercambiables y semánticamente idénticos,
aunque sus configuraciones puede que sean heterogéneas a lo largo del tiempo. Este es un ajuste obvio para los servidores sin estado replicados,
pero los ReplicationControllers también pueden utilizarse para mantener la disponibilidad de aplicaciones que se elijen por un maestro, las particionadas, y las de grupos de trabajadores.
Dichas aplicaciones deberían usar los mecanismos de asignación dinámica de trabajo, como las [colas de trabajo RabbitMQ](https://www.rabbitmq.com/tutorials/tutorial-two-python.html),
en vez de la personalización estática/de una sola vez en la configuración de cada pod,
ya que se considera un anti-patrón. Cualquier personalización de pod que se haga, como el calibrado vertical automático de recursos (por ejemplo, cpu o memoria),
debería realizarse a través de otro proceso de controlador en línea, no con el mismo ReplicationController.
## Responsabilidades de un ReplicationController
El ReplicationController simplemente garantiza que el número deseado de pods coincide con su selector de etiqueta y que son operacionales.
Actualmente, sólo los pods que han terminado se excluyen de la cuenta. En el futuro, la [disponibilidad](http://issue.k8s.io/620) y otra información disponible en el sistema
se tendrá en cuenta, se añadirá más controles sobre la regla de sussitución, y se está planificando
emitir eventos que podrían ser aprovechados por clientes externos para implementar reglas complejas de sustitución y escalado de forma arbitraria.
El ReplicationController está siempre condicionado a esta reducida responsabilidad.
Él mismo no llevará a cabo ni pruebas de estar listo ni vivo. En vez de aplicar el auto-escalado,
se pretende que este sea realizado por un auto-escalador externo (como se vio en [#492](http://issue.k8s.io/492)), que sería el encargado de cambiar su campo `replicas`.
No se añadirá reglas de programación (por ejemplo, [propagación](http://issue.k8s.io/367#issuecomment-48428019)) al ReplicationController.
Ni se debería validar que los pods controlados coincidan con la plantilla actual especificada, ya que eso obstruiría el auto-calibrado y otros procesos automáticos.
De forma similar, los vencimientos de término, las dependencias de orden, la extensión de la configuración, y otras características se aplican en otro lado.
Incluso se plantea excluir el mecanismo de creación de pods a granel ([#170](http://issue.k8s.io/170)).
El ReplicationController está pensado para ser una primitiva de bloques is intended to be a composable building-block primitive. We expect higher-level APIs and/or tools to be built on top of it and other complementary primitives for user convenience in the future. The "macro" operations currently supported by kubectl (run, scale, rolling-update) are proof-of-concept examples of this. For instance, we could imagine something like [Asgard](http://techblog.netflix.com/2012/06/asgard-web-based-cloud-management-and.html) managing ReplicationControllers, auto-scalers, services, scheduling policies, canaries, etc.
## Obejto API
El ReplicationController es un recurso de alto nivel en la API REST de Kubernetes. Más detalles acerca del
objeto API se pueden encontrar aquí:
[Objeto API ReplicationController](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#replicationcontroller-v1-core).
## Alternativas al ReplicationController
### ReplicaSet
El [`ReplicaSet`](/docs/concepts/workloads/controllers/replicaset/) es el ReplicationController de nueva generación que soporta el nuevo [selector de etiqueta basado en conjunto](/docs/concepts/overview/working-with-objects/labels/#set-based-requirement).
Se usa principalmente por el [`Deployment`](/docs/concepts/workloads/controllers/deployment/) como un mecanismo para orquestrar la creación de pods, la eliminación y las actualizaciones.
Nótese que se recomienda usar Deployments en vez de directamente usar los ReplicaSets, a menos que necesites una orquestración personalizada de actualizaciones o no quieras actualizaciones en absoluto.
### Deployment (Recomendado)
El [`Deployment`](/docs/concepts/workloads/controllers/deployment/) es un objeto de alto nivel de la API que actualiza sus ReplicaSets subyacenetes y sus Pods
de forma similar a cómo lo hace el comando `kubectl rolling-update`. Se recomienda el uso de Deployments si se quiere esta functionalidad de actualización en línea,
porque a diferencia del comando `kubectl rolling-update`, son declarativos, se ejecutan del lado del servidor, y tienen características adicionales.
### Pods simples
A diferencia del caso en que un usuario ha creado directamente pods, un ReplicationController sustituye los pods que han sido eliminador o terminados por cualquier motivo,
como en el caso de un fallo de un nodo o una intervención disruptiva de mantenimiento, como la actualización del kernel.
Por esta razón, se recomienda que se usa un ReplicationController incluso si tu aplicación sólo necesita un único pod.
Piensa que es similar a un supervisor de proceso, sólo que supervisa múltiples pods entre múltiples nodos en vez de
procesos individuales en un único nodo. Un ReplicationController delega los reinicios locales de
los contenedores a algún agente del nodo (por ejemplo, Kubelet o Docker).
### Job
Usa un [`Job`](/docs/concepts/jobs/run-to-completion-finite-workloads/) en vez de un ReplicationController para aquellos pods que se espera que terminen por sí mismos
(esto es, trabajos por lotes).
### DaemonSet
Usa un [`DaemonSet`](/docs/concepts/workloads/controllers/daemonset/) en vez de un ReplicationController para aquellos pods que proporcionan
una función a nivel de servidor, como la monitorización o el loggin de servidor. Estos pods tienen un ciclo de vida que está asociado
al del servidor: el pod necesita ejecutarse en el servidor antes que los otros pods arranquen, y es seguro
terminarlo cuando el servidor está listo para reiniciarse/apagarse.
## Para más información
Lee [Ejecutar Aplicaciones sin Estado con un ReplicationController](/docs/tutorials/stateless-application/run-stateless-ap-replication-controller/).
{{% /capture %}}
@@ -0,0 +1,267 @@
---
title: StatefulSets
content_template: templates/concept
weight: 40
---
{{% capture overview %}}
Un StatefulSet es el objeto de la API workload que se usa para gestionar aplicaciones con estado.
{{< note >}}
Los StatefulSets son estables (GA) en la versión 1.9.
{{< /note >}}
{{< glossary_definition term_id="statefulset" length="all" >}}
{{% /capture %}}
{{% capture body %}}
## Usar StatefulSets
Los StatefulSets son valiosos para aquellas aplicaciones que necesitan uno o más de los siguientes:
* Identificadores de red estables, únicos.
* Almacenamiento estable, persistente.
* Despliegue y escalado ordenado, controlado.
* Actualizaciones en línea ordenadas, automatizadas.
De los de arriba, estable es sinónimo de persistencia entre (re)programaciones de Pods.
Si una aplicación no necesita ningún identificador estable o despliegue,
eliminación, o escalado ordenado, deberías desplegar tu aplicación con un controlador que
proporcione un conjunto de réplicas sin estado, como un
[Deployment](/docs/concepts/workloads/controllers/deployment/) o un
[ReplicaSet](/docs/concepts/workloads/controllers/replicaset/), ya que están mejor preparados
para tus necesidades sin estado.
## Limitaciones
* El almacenamiento de un determinado Pod debe provisionarse por un [Provisionador de PersistentVolume](https://github.com/kubernetes/examples/tree/{{< param "githubbranch" >}}/staging/persistent-volume-provisioning/README.md) basado en la `storage class` requerida, o pre-provisionarse por un administrador.
* Eliminar y/o reducir un StatefulSet *no* eliminará los volúmenes asociados con el StatefulSet. Este comportamiento es intencional y sirve para garantizar la seguridad de los datos, que da más valor que la purga automática de los recursos relacionados del StatefulSet.
* Los StatefulSets actualmente necesitan un [Servicio Headless](/docs/concepts/services-networking/service/#headless-services) como responsable de la identidad de red de los Pods. Es tu responsabilidad crear este Service.
* Los StatefulSets no proporcionan ninguna garantía de la terminación de los pods cuando se elimina un StatefulSet. Para conseguir un término de los pods ordenado y controlado en el StatefulSet, es posible reducir el StatefulSet a 0 réplicas justo antes de eliminarlo.
* Cuando se usan las [Actualizaciones en línea](#rolling-updates) con la
[Regla de Gestión de Pod](#pod-management-policies) (`OrderedReady`) por defecto,
es posible entrar en un estado inconsistente que requiere de una
[intervención manual para su reparación](#retroceso-forzado).
## Componentes
El ejemplo de abajo demuestra los componentes de un StatefulSet:
* Un servicio Headless, llamado nginx, se usa para controlar el dominio de red.
* Un StatefulSet, llamado web, que tiene una especificación que indica que se lanzarán 3 réplicas del contenedor nginx en Pods únicos.
* Un volumeClaimTemplate que proporciona almacenamiento estable por medio de [PersistentVolumes](/docs/concepts/storage/persistent-volumes/) provisionados por un provisionador de tipo PersistentVolume.
```yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx # tiene que coincidir con .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # por defecto es 1
template:
metadata:
labels:
app: nginx # tiene que coincidir con .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "my-storage-class"
resources:
requests:
storage: 1Gi
```
## Selector de Pod
Debes poner el valor del campo `.spec.selector` de un StatefulSet para que coincida con las etiquetas de su campo `.spec.template.metadata.labels`. Antes de Kubernetes 1.8,
el campo `.spec.selector` se predeterminaba cuando se omitía. A partir de la versión 1.8, si no se especifica un selector de coincidencia de Pods, se produce un error de validación
durante la creación del StatefulSet.
## Identidad de Pod
Los Pods de un StatefulSet tienen una identidad única que está formada por un ordinal,
una identidad estable de red, y almacenamiento estable. La identidad se asocia al Pod,
independientemente del nodo en que haya sido (re)programado.
### Índice Ordinal
Para un StatefulSet con N réplicas, a cada Pod del StatefulSet se le asignará
un número entero ordinal, desde 0 hasta N-1, y que es único para el conjunto.
### ID estable de Red
El nombre de anfitrión (hostname) de cada Pod de un StatefulSet se deriva del nombre del StatefulSet
y del número ordinal del Pod. El patrón para construir dicho hostname
es `$(statefulset name)-$(ordinal)`. Así, el ejemplo de arriba creará tres Pods
denominados `web-0,web-1,web-2`.
Un StatefulSet puede usar un [Servicio Headless](/docs/concepts/services-networking/service/#headless-services)
para controlar el nombre de dominio de sus Pods. El nombre de dominio gestionado por este Service tiene la forma:
`$(service name).$(namespace).svc.cluster.local`, donde "cluster.local" es el nombre de dominio del clúster.
Conforme se crea cada Pod, se le asigna un nombre DNS correspondiente de subdominio, que tiene la forma:
`$(podname).$(governing service domain)`, donde el servicio en funciones se define por el campo
`serviceName` del StatefulSet.
Como se indicó en la sección [limitaciones](#limitaciones), la creación del
[Servicio Headless](/docs/concepts/services-networking/service/#headless-services)
encargado de la identidad de red de los pods es enteramente tu responsabilidad.
Aquí se muestran algunos ejemplos de elecciones de nombres de Cluster Domain, nombres de Service,
nombres de StatefulSet, y cómo impactan en los nombres DNS de los Pods del StatefulSet:
Cluster Domain | Service (ns/nombre) | StatefulSet (ns/nombre) | StatefulSet Domain | Pod DNS | Pod Hostname |
-------------- | ----------------- | ----------------- | -------------- | ------- | ------------ |
cluster.local | default/nginx | default/web | nginx.default.svc.cluster.local | web-{0..N-1}.nginx.default.svc.cluster.local | web-{0..N-1} |
cluster.local | foo/nginx | foo/web | nginx.foo.svc.cluster.local | web-{0..N-1}.nginx.foo.svc.cluster.local | web-{0..N-1} |
kube.local | foo/nginx | foo/web | nginx.foo.svc.kube.local | web-{0..N-1}.nginx.foo.svc.kube.local | web-{0..N-1} |
{{< note >}}
El valor de Cluster Domain se pondrá a `cluster.local` a menos que
[se configure de otra forma](/docs/concepts/services-networking/dns-pod-service/).
{{< /note >}}
### Almacenamiento estable
Kubernetes crea un [PersistentVolume](/docs/concepts/storage/persistent-volumes/) para cada
VolumeClaimTemplate. En el ejemplo de nginx de arriba, cada Pod recibirá un único PersistentVolume
con una StorageClass igual a `my-storage-class` y 1 Gib de almacenamiento provisionado. Si no se indica ninguna StorageClass,
entonces se usa la StorageClass por defecto. Cuando un Pod se (re)programa
en un nodo, sus `volumeMounts` montan los PersistentVolumes asociados con sus
PersistentVolume Claims. Nótese que los PersistentVolumes asociados con los
PersistentVolume Claims de los Pods no se eliminan cuando los Pods, o los StatefulSet se eliminan.
Esto debe realizarse manualmente.
### Etiqueta de Nombre de Pod
Cuando el controlador del StatefulSet crea un Pod, añade una etiqueta, `statefulset.kubernetes.io/pod-name`,
que toma el valor del nombre del Pod. Esta etiqueta te permite enlazar un Service a un Pod específico
en el StatefulSet.
## Garantías de Despliegue y Escalado
* Para un StatefulSet con N réplicas, cuando los Pods se despliegan, se crean secuencialmente, en orden de {0..N-1}.
* Cuando se eliminan los Pods, se terminan en orden opuesto, de {N-1..0}.
* Antes de que una operación de escalado se aplique a un Pod, todos sus predecesores deben estar Running y Ready.
* Antes de que se termine un Pod, todos sus sucesores deben haberse apagado completamente.
El StatefulSet no debería tener que indicar un valor 0 para el campo `pod.Spec.TerminationGracePeriodSeconds`.
Esta práctica no es segura y se aconseja no hacerlo. Para una explicación más detallada, por favor echa un vistazo a cómo [forzar la eliminación de Pods de un StatefulSet](/docs/tasks/run-application/force-delete-stateful-set-pod/).
Cuando el ejemplo nginx de arriba se crea, se despliegan tres Pods en el orden
web-0, web-1, web-2. web-1 no se desplegará hasta que web-0 no esté
[Running y Ready](/docs/user-guide/pod-states/), y web-2 no se desplegará hasta que
web-1 esté Running y Ready. En caso de que web-0 fallase, después de que web-1 estuviera Running y Ready, pero antes
de que se desplegara web-2, web-2 no se desplegaría hasta que web-0 se redesplegase con éxito y estuviera
Running y Ready.
Si un usuario fuera a escalar el ejemplo desplegado parcheando el StatefulSet de forma que
`replicas=1`, web-2 se terminaría primero. web-1 no se terminaría hasta que web-2
no se hubiera apagado y eliminado por completo. Si web-0 fallase después de que web-2 se hubiera terminado y
apagado completamente, pero antes del término de web-1, entonces web-1 no se terminaría hasta
que web-0 estuviera Running y Ready.
### Reglas de Gestión de Pods
En Kubernetes 1.7 y versiones posteriores, el StatefulSet permite flexibilizar sus garantías de ordenación
al mismo tiempo que preservar su garantía de singularidad e identidad a través del campo `.spec.podManagementPolicy`.
#### Gestión de tipo OrderedReady de Pods
La gestión de tipo `OrderedReady` de pods es la predeterminada para los StatefulSets. Implementa el comportamiento
descrito [arriba](#deployment-and-scaling-guarantees).
#### Gestión de tipo Parallel de Pods
La gestión de tipo `Parallel` de pods le dice al controlador del StatefulSet que lance y termine
todos los Pods en paralelo, y que no espere a que los Pods estén Running
y Ready o completamente terminados antes de lanzar o terminar otro Pod.
## Estrategias de Actualización
En Kubernetes 1.7 y a posteriori, el campo `.spec.updateStrategy` del StatefulSet permite configurar
y deshabilitar las actualizaciones automátizadas en línea para los contenedores, etiquetas, peticiones/límites de recursos,
y anotaciones de los Pods del StatefulSet.
### On Delete
La estrategia de actualización `OnDelete` implementa el funcionamiento tradicional (1.6 y previo). Cuando el campo
`.spec.updateStrategy.type` de un StatefulSet se pone al valor `OnDelete`, el controlador del StatefulSet no actualizará automáticamente
los Pods del StatefulSet. Los usuarios deben eliminar manualmente los Pods para forzar al controlador a crear
nuevos Pods que reflejen las modificaciones hechas al campo `.spec.template` del StatefulSet.
### Rolling Updates
La estrategia de actualización `RollingUpdate` implementa una actualización automatizada en línea de los Pods del
StatefulSet. Es la estrategia por defecto cuando el campo `.spec.updateStrategy` se deja sin valor. Cuando el campo `.spec.updateStrategy.type` de un StatefulSet
se pone al valor `RollingUpdate`, el controlador del StatefulSet lo eliminará y recreará cada Pod en el StatefulSet. Procederá
en el mismo orden en que ha terminado los Pod (del número ordinal más grande al más pequeño), actualizando
cada Pod uno por uno. Esperará a que el Pod actualizado esté Running y Ready antes de
actualizar su predecesor.
#### Particiones
La estrategia de actualización `RollingUpdate` puede particionarse, indicando el valor del campo
`.spec.updateStrategy.rollingUpdate.partition`. Si se indica una partición, todos los Pods con un
número ordinal mayor o igual que el de la partición serán actualizados cuando el campo `.spec.template`
del StatefulSet se actualice. Todos los Pods con un número ordinal que sea menor que el de la partición
no serán actualizados, e incluso si son eliminados, serán recreados con la versión anterior. Si el campo
`.spec.updateStrategy.rollingUpdate.partition` de un StatefulSet es mayor que el valor del campo `.spec.replicas`,
las modificaciones al campo `.spec.template` no se propagarán a sus Pods.
En la mayoría de ocasiones, no necesitarás usar una partición, pero pueden resultar útiles si quieres preparar una actualización,
realizar un despliegue tipo canary, o llevar a cabo un despliegue en fases.
#### Retroceso Forzado
Cuando se usa [Actualizaciones en línea](#rolling-updates) con el valor de la
[Regla de Gestión de Pod](#pod-management-policies) (`OrderedReady`) por defecto,
es posible acabar en un estado inconsistente que requiera de una intervención manual para arreglarlo.
Si actualizas la plantilla Pod a una configuración que nunca llega a Running y
Ready (por ejemplo, debido a un binario incorrecto o un error de configuración a nivel de aplicación),
el StatefulSet detendrá el despliegue y esperará.
En este estado, no es suficiente con revertir la plantilla Pod a la configuración buena.
Debido a un [problema conocido](https://github.com/kubernetes/kubernetes/issues/67250),
el StatefulSet seguirá esperando a que los Pod estropeados se pongan en Ready
(lo que nunca ocurre) antes de intentar revertirla a la configuración que funcionaba.
Antes de revertir la plantilla, debes también eliminar cualquier Pod que el StatefulSet haya
intentando ejecutar con la configuración incorrecta.
El StatefulSet comenzará entonces a recrear los Pods usando la plantilla revertida.
{{% /capture %}}
{{% capture whatsnext %}}
* Sigue el ejemplo de cómo [desplegar un aplicación con estado](/docs/tutorials/stateful-application/basic-stateful-set/).
* Sigue el ejemplo de cómo [desplegar Cassandra con StatefulSets](/docs/tutorials/stateful-application/cassandra/).
{{% /capture %}}
@@ -0,0 +1,85 @@
---
title: Controlador TTL para Recursos Finalizados
content_template: templates/concept
weight: 65
---
{{% capture overview %}}
{{< feature-state for_k8s_version="v1.12" state="alpha" >}}
El controlador TTL proporciona un mecanismo TTL para limitar el tiempo de vida de los objetos
de recurso que ya han terminado su ejecución. El controlador TTL sólo se ocupa de los
[Jobs](/docs/concepts/workloads/controllers/jobs-run-to-completion/) por el momento,
y puede que se extienda para gestionar otros recursos que terminen su ejecución,
como los Pods y los recursos personalizados.
Descargo de responsabilidad Alpha: esta característica está actualmente en versión alpha, y puede habilitarse mediante el
[feature gate](/docs/reference/command-line-tools-reference/feature-gates/)
`TTLAfterFinished`.
{{% /capture %}}
{{% capture body %}}
## Controlador TTL
El controlador TTL sólo soporta los Jobs por ahora. Un operador del clúster puede usar esta funcionalidad para limpiar
los Jobs terminados (bien `Complete` o `Failed`) automáticamente especificando el valor del campo
`.spec.ttlSecondsAfterFinished` del Job, como en este
[ejemplo](/docs/concepts/workloads/controllers/jobs-run-to-completion/#clean-up-finished-jobs-automatically).
El controlador TTL asumirá que un recurso es candidato a ser limpiado
TTL segundos después de que el recurso haya terminado; dicho de otra forma, cuando el TTL haya expirado.
Cuando el controlador TTL limpia un recursos, lo elimina en cascada, esto es, borra
sus objetos subordinados juntos. Nótese que cuando se elimina un recurso,
se respetan las garantías de su ciclo de vida, como con los finalizadores.
Los segundos TTL pueden ser configurados en cualquier momento. Aquí se muestran algunos ejemplos para poner valores al campo
`.spec.ttlSecondsAfterFinished` de un Job:
* Indicando este campo en el manifiesto de los recursos, de forma que se pueda limpiar un Job
automáticamente un tiempo después de que haya finalizado.
* Haciendo que el campo de los recursos existentes, ya finalizados, adopte esta nueva característica.
* Usando un [mutating admission webhook](/docs/reference/access-authn-authz/extensible-admission-controllers/#admission-webhooks)
para poner el valor de este campo dinámicamente en el momento de la creación del recursos. Los administradores del clúster pueden
usar este enfoque para forzar una regla TTL para los recursos terminados.
* Usando un
[mutating admission webhook](/docs/reference/access-authn-authz/extensible-admission-controllers/#admission-webhooks)
para poner el valor de este campo dinámicamente después de que el recurso haya terminado,
y eligiendo diferentes valores TTL basados en los estados de los recursos, etiquetas, etc.
## Advertencia
### Actualizar los segundos TTL
Cabe señalar que el período TTL , ej. campo `.spec.ttlSecondsAfterFinished` de los Jobs,
puede modificarse después de que el recurso haya sido creado o terminado. Sin embargo, una vez
que el Job se convierte en candidato para ser eliminado (cuando el TTL ha expirado), el sistema
no garantiza que se mantendrán los Jobs, incluso si una modificación para extender el TTL
devuelve una respuesta API satisfactoria.
### Diferencia horaria
Como el controlador TTL usa marcas de fecha/hora almacenadas en los recursos de Kubernetes
para determinar si el TTL ha expirado o no, esta funcionalidad es sensible a las
diferencias horarias del clúster, lo que puede provocar que el controlador TTL limpie recursos
en momentos equivocados.
En Kubernetes, se necesita ejecutar NTP en todos los nodos
(ver [#6159](https://github.com/kubernetes/kubernetes/issues/6159#issuecomment-93844058))
para evitar este problema. Los relojes no siempre son correctos, pero la diferencia debería ser muy pequeña.
Ten presente este riesgo cuando pongas un valor distinto de cero para el TTL.
{{% /capture %}}
{{% capture whatsnext %}}
[Limpiar Jobs automáticamente](/docs/concepts/workloads/controllers/jobs-run-to-completion/#clean-up-finished-jobs-automatically)
[Documento de diseño](https://github.com/kubernetes/community/blob/master/keps/sig-apps/0026-ttl-after-finish.md)
{{% /capture %}}