Spanish Translation
This commit is contained in:
@@ -0,0 +1,457 @@
|
|||||||
|
---
|
||||||
|
title: Jobs - Ejecución hasta el final
|
||||||
|
content_template: templates/concept
|
||||||
|
feature:
|
||||||
|
title: Ejecución en lotes
|
||||||
|
description: >
|
||||||
|
Además de los servicios, Kubernetes puede gestionar tus trabajos por lotes y CI, sustituyendo los contenedores que fallen, si así se desea.
|
||||||
|
weight: 70
|
||||||
|
---
|
||||||
|
|
||||||
|
{{% capture overview %}}
|
||||||
|
|
||||||
|
Un Job crea uno o más Pods y se asegura de que un número específico de ellos termina de forma satisfactoria.
|
||||||
|
Conforme los pods terminan satisfactoriamente, el Job realiza el seguimiento de las ejecuciones satisfactorias.
|
||||||
|
Cuando se alcanza un número específico de ejecuciones satisfactorias, la tarea (esto es, el Job) se completa.
|
||||||
|
Al eliminar un Job se eliminan los Pods que haya creado.
|
||||||
|
|
||||||
|
Un caso simple de uso es crear un objeto Job para que se ejecute un Pod de manera fiable hasta el final.
|
||||||
|
El objeto Job arrancará un nuevo Pod si el primer Pod falla o se elimina (por ejemplo
|
||||||
|
como consecuencia de un fallo de hardware o un reinicio en un nodo).
|
||||||
|
|
||||||
|
También se puede usar un Job para ejecutar múltiples Pods en paralelo.
|
||||||
|
|
||||||
|
{{% /capture %}}
|
||||||
|
|
||||||
|
|
||||||
|
{{% capture body %}}
|
||||||
|
|
||||||
|
## Ejecutar un Job de ejemplo
|
||||||
|
|
||||||
|
Aquí se muestra un ejemplo de configuración de Job. Este ejemplo calcula los primeros 2000 decimales de π y los imprime por pantalla.
|
||||||
|
Tarda unos 10s en completarse.
|
||||||
|
|
||||||
|
{{< codenew file="controllers/job.yaml" >}}
|
||||||
|
|
||||||
|
Puedes ejecutar el ejemplo con este comando:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl apply -f https://k8s.io/examples/controllers/job.yaml
|
||||||
|
```
|
||||||
|
```
|
||||||
|
job "pi" created
|
||||||
|
```
|
||||||
|
|
||||||
|
Comprueba el estado del Job con `kubectl`:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl describe jobs/pi
|
||||||
|
```
|
||||||
|
```
|
||||||
|
Name: pi
|
||||||
|
Namespace: default
|
||||||
|
Selector: controller-uid=b1db589a-2c8d-11e6-b324-0209dc45a495
|
||||||
|
Labels: controller-uid=b1db589a-2c8d-11e6-b324-0209dc45a495
|
||||||
|
job-name=pi
|
||||||
|
Annotations: <none>
|
||||||
|
Parallelism: 1
|
||||||
|
Completions: 1
|
||||||
|
Start Time: Tue, 07 Jun 2016 10:56:16 +0200
|
||||||
|
Pods Statuses: 0 Running / 1 Succeeded / 0 Failed
|
||||||
|
Pod Template:
|
||||||
|
Labels: controller-uid=b1db589a-2c8d-11e6-b324-0209dc45a495
|
||||||
|
job-name=pi
|
||||||
|
Containers:
|
||||||
|
pi:
|
||||||
|
Image: perl
|
||||||
|
Port:
|
||||||
|
Command:
|
||||||
|
perl
|
||||||
|
-Mbignum=bpi
|
||||||
|
-wle
|
||||||
|
print bpi(2000)
|
||||||
|
Environment: <none>
|
||||||
|
Mounts: <none>
|
||||||
|
Volumes: <none>
|
||||||
|
Events:
|
||||||
|
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
|
||||||
|
--------- -------- ----- ---- ------------- -------- ------ -------
|
||||||
|
1m 1m 1 {job-controller } Normal SuccessfulCreate Created pod: pi-dtn4q
|
||||||
|
```
|
||||||
|
|
||||||
|
Para ver los Pods de un Job que se han completado, usa `kubectl get pods`.
|
||||||
|
|
||||||
|
Para listar todos los Pods que pertenecen a un Job de forma que sea legible, puedes usar un comando como:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
pods=$(kubectl get pods --selector=job-name=pi --output=jsonpath='{.items[*].metadata.name}')
|
||||||
|
echo $pods
|
||||||
|
```
|
||||||
|
```
|
||||||
|
pi-aiw0a
|
||||||
|
```
|
||||||
|
|
||||||
|
En este caso, el selector es el mismo que el selector del Job. La opción `--output=jsonpath` indica un expresión
|
||||||
|
que simplemente obtiene el nombre de cada Pod en la lista devuelta.
|
||||||
|
|
||||||
|
Mira la salida estándar de uno de los Pods:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ kubectl logs $pods
|
||||||
|
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275901
|
||||||
|
```
|
||||||
|
|
||||||
|
## Escribir una especificación de Job
|
||||||
|
|
||||||
|
Como con el resto de configuraciones de Kubernetes, un Job necesita los campos `apiVersion`, `kind`, y `metadata`.
|
||||||
|
|
||||||
|
Un Job también necesita la [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 obligatorio 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/user-guide/pods),
|
||||||
|
excepto por el hecho de que está anidado y no tiene el campo `apiVersion` o `kind`.
|
||||||
|
|
||||||
|
Además de los campos olbigatorios de un Pod, una plantilla Pod de un Job debe indicar las etiquetas apropiadas
|
||||||
|
(ver [selector de pod](#pod-selector)) y una regla de reinicio apropiada.
|
||||||
|
|
||||||
|
Sólo se permite los valores `Never` o `OnFailure` para [`RestartPolicy`](/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy).
|
||||||
|
|
||||||
|
### Selector de Pod
|
||||||
|
|
||||||
|
El campo `.spec.selector` es opcional. En la práctica mayoría de los casos no deberías configurarlo.
|
||||||
|
Mira la sección sobre [configurar tu propio selector de pod](#specifying-your-own-pod-selector).
|
||||||
|
|
||||||
|
|
||||||
|
### Jobs en paralelo
|
||||||
|
|
||||||
|
Hay tres tipos principales de tarea aptos para ejecutarse como un Job:
|
||||||
|
|
||||||
|
1. Jobs no paralelos
|
||||||
|
- normalmente, sólo se arranca un Pod, a menos que el Pod falle.
|
||||||
|
- el Job se completa tan pronto como su Pod termine de forma satisfactoria.
|
||||||
|
1. Jobs en paralelo con un *cupo fijo de terminación*:
|
||||||
|
- se configura un valor positivo distinto de cero para el campo `.spec.completions`.
|
||||||
|
- el Job representa la tarea en general, y se completa cuando hay una ejecución satisfactoria de un Pod por cada valor dentro del rango de 1 a `.spec.completions`.
|
||||||
|
- **no implementado todavía:** A cada Pod se le pasa un índice diferenente dentro del rango de 1 a `.spec.completions`.
|
||||||
|
1. Jobs en paralelo con una *cola de trabajo*:
|
||||||
|
- no se especifica el campo `.spec.completions`, por defecto `.spec.parallelism`.
|
||||||
|
- los Pods deben coordinarse entre ellos mismos o a través de un servicio externo que determine quién debe trabajar en qué.
|
||||||
|
Por ejemplo, un Pod podría ir a buscar un lote de hasta N ítems de una cola de trabajo.
|
||||||
|
- cada Pod es capaz de forma independiente de determinar si sus compañeros han terminado o no, y como consecuencia el Job entero ha terminado.
|
||||||
|
- cuando _cualquier_ Pod del Job termina con éxito, no se crean nuevos Pods.
|
||||||
|
- una vez que al menos uno de los Pods ha terminado con éxito y todos los Pods han terminado, entonces el Job termina con éxito.
|
||||||
|
- una vez que cualquier Pod ha terminado con éxito, ningún otro Pod debería continuar trabajando en la misma tarea o escribiendo ningún resultado. Todos ellos deberían estar en proceso de terminarse.
|
||||||
|
|
||||||
|
En un Job _no paralelo_, no debes indicar el valor de `.spec.completions` ni `.spec.parallelism`. Cuando ambos se dejan
|
||||||
|
sin valor, ambos se predeterminan a 1.
|
||||||
|
|
||||||
|
En un Job con _cupo fijo de terminación_, deberías poner el valor de `.spec.completions` al número de terminaciones que se necesiten.
|
||||||
|
Puedes dar un valor a `.spec.parallelism`, o dejarlo sin valor, en cuyo caso se predetermina a 1.
|
||||||
|
|
||||||
|
En un Job con _cola de trabajo_, no debes indicar el valor de `.spec.completions`, y poner el valor de `.spec.parallelism` a
|
||||||
|
un entero no negativo.
|
||||||
|
|
||||||
|
Para más información acerca de cómo usar los distintos tipos de Job, ver la sección de [patrones de job](#job-patterns).
|
||||||
|
|
||||||
|
|
||||||
|
#### Controlar el paralelismo
|
||||||
|
|
||||||
|
El paralelismo solicitado (`.spec.parallelism`) puede usar cualquier valor no negativo.
|
||||||
|
Si no se indica, se predeterminad a 1.
|
||||||
|
Si se indica como 0, entonces el Job se pausa de forma efectiva hasta que se incremente.
|
||||||
|
|
||||||
|
El paralelismo actual (número de pods ejecutándose en cada momento) puede que sea mayor o menor que el solicitado,
|
||||||
|
por los siguientes motivos:
|
||||||
|
|
||||||
|
- Para los Jobs con _cupo fijo de terminaciones_, el número actual de pods ejecutándose en paralelo no excede el número de terminaciones pendientes.
|
||||||
|
Los valores superiores de `.spec.parallelism` se ignoran.
|
||||||
|
- Para los Jobs con _cola de trabajo_, no se arranca nuevos Pods después de que cualquier Pod se haya completado -- sin embargo, se permite que se completen los Pods pendientes.
|
||||||
|
- Cuando el controlador no ha tenido tiempo para reaccionar.
|
||||||
|
- Cuando el controlador no pudo crear los Pods por el motivo que fuera (falta de `ResourceQuota`, falta de permisos, etc.),
|
||||||
|
entonces puede que haya menos pods que los solicitados.
|
||||||
|
- El controlador puede que regule la creación de nuevos Pods debido al excesivo número de fallos anteriores en el mismo Job.
|
||||||
|
- Cuando un Pod se para de forma controlada, lleva tiempo pararlo.
|
||||||
|
|
||||||
|
## Gestionar Fallos de Pod y Contenedor
|
||||||
|
|
||||||
|
Un contenedor de un Pod puede fallar por cualquier motivo, como porque el proceso que se estaba ejecutando termina con un código de salida distinto de cero,
|
||||||
|
o porque se mató el contenedor por exceder un límite de memoria, etc. Si esto ocurre, y se tiene
|
||||||
|
`.spec.template.spec.restartPolicy = "OnFailure"`, entonces el Pod permance en el nodo,
|
||||||
|
pero el contenedor se vuelve a ejecutar. Por lo tanto, tu aplicación debe poder gestionar el caso en que se reinicia de forma local,
|
||||||
|
o bien especificar `.spec.template.spec.restartPolicy = "Never"`.
|
||||||
|
Ver el [ciclo de vida de un pod](/docs/concepts/workloads/pods/pod-lifecycle/#example-states) para más información sobre `restartPolicy`.
|
||||||
|
|
||||||
|
Un Pod entero puede también fallar por cualquier motivo, como cuando se expulsa al Pod del nodo
|
||||||
|
(porque el nodo se actualiza, reinicia, elimina, etc.), o si un contenedor del Pod falla
|
||||||
|
cuando `.spec.template.spec.restartPolicy = "Never"`. Cuando un Pod falla, entonces el controlador del Job
|
||||||
|
arranca un nuevo Pod. Esto quiere decir que tu aplicación debe ser capaz de gestionar el caso en que se reinicia en un nuevo pod.
|
||||||
|
En particular, debe ser capaz de gestionar los ficheros temporales, los bloqueos, los resultados incompletos, y cualquier otra dependencia
|
||||||
|
de ejecuciones previas.
|
||||||
|
|
||||||
|
Nótese que incluso si se configura `.spec.parallelism = 1` y `.spec.completions = 1` y
|
||||||
|
`.spec.template.spec.restartPolicy = "Never"`, el mismo programa puede arrancarse dos veces.
|
||||||
|
|
||||||
|
Si se especifica `.spec.parallelism` y `.spec.completions` con valores mayores que 1,
|
||||||
|
entonces puede que haya múltiples pods ejecutándose a la vez. Por ello, tus pods deben tolerar la concurrencia.
|
||||||
|
|
||||||
|
### Regla de retroceso de Pod por fallo
|
||||||
|
|
||||||
|
Hay situaciones en que quieres que el Job falle después de intentar ejecutarlo unas cuantas veces debido
|
||||||
|
a un error lógico en la configuración, etc.
|
||||||
|
Para hacerlo, pon el valor de `.spec.backoffLimit` al número de reintentos que quieres
|
||||||
|
antes de considerar el Job como fallido. El límite de retroceso se predetermina a 6.
|
||||||
|
Los Pods fallidos asociados al Job son recreados por el controlador del Job con un
|
||||||
|
retroceso exponencial (10s, 20s, 40s ...) limitado a seis minutos. El contador
|
||||||
|
de retroceso se resetea si no aparecen Pods fallidos antes del siguiente chequeo de estado del Job.
|
||||||
|
|
||||||
|
{{< note >}}
|
||||||
|
El problema [#54870](https://github.com/kubernetes/kubernetes/issues/54870) todavía existe en las versiones de Kubernetes anteriores a la versión 1.12
|
||||||
|
{{< /note >}}
|
||||||
|
|
||||||
|
## Terminación y Limpieza de un Job
|
||||||
|
|
||||||
|
Cuando un Job se completa, ya no se crea ningún Pod, pero tampoco se elimina los Pods. Guardarlos permite
|
||||||
|
ver todavía los logs de los pods acabados para comprobar errores, avisos, o cualquier otro resultado de diagnóstico.
|
||||||
|
El objeto job también se conserva una vez que se ha completado para que se pueda ver su estado. Es decisión del usuario si elimina
|
||||||
|
los viejos jobs después de comprobar su estado. Eliminar el job con el comando `kubectl` (ej. `kubectl delete jobs/pi` o `kubectl delete -f ./job.yaml`).
|
||||||
|
Cuando eliminas un job usando el comando `kubectl`, todos los pods que creó se eliminan también.
|
||||||
|
|
||||||
|
Por defecto, un Job se ejecutará de forma ininterrumpida a menos que uno de los Pods falle, en cuyo caso el Job se fija en el valor de
|
||||||
|
`.spec.backoffLimit` descrito arriba. Otra forma de acabar un Job es poniéndole un vencimiento activo.
|
||||||
|
Haz esto poniendo el valor del campo `.spec.activeDeadlineSeconds` del Job a un número de segundos.
|
||||||
|
|
||||||
|
El campo `activeDeadlineSeconds` se aplica a la duración del job, independientemente de cuántos Pods se hayan creado.
|
||||||
|
Una vez que el Job alcanza `activeDeadlineSeconds`, se terminan todos sus Pods y el estado del Job se pone como `type: Failed` con `reason: DeadlineExceeded`.
|
||||||
|
|
||||||
|
Fíjate que el campo `.spec.activeDeadlineSeconds` de un Job tiene precedencia sobre el campo `.spec.backoffLimit`.
|
||||||
|
Por lo tanto, un Job que está reintentando uno o más Pods fallidos no desplegará nuevos Pods una vez que alcance el límite de tiempo especificado por `activeDeadlineSeconds`,
|
||||||
|
incluso si todavía no se ha alcanzado el `backoffLimit`.
|
||||||
|
|
||||||
|
Ejemplo:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: batch/v1
|
||||||
|
kind: Job
|
||||||
|
metadata:
|
||||||
|
name: pi-with-timeout
|
||||||
|
spec:
|
||||||
|
backoffLimit: 5
|
||||||
|
activeDeadlineSeconds: 100
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: pi
|
||||||
|
image: perl
|
||||||
|
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
|
||||||
|
restartPolicy: Never
|
||||||
|
```
|
||||||
|
|
||||||
|
Fíjate que tanto la especificación del Job como la [especificación de la plantilla Pod](/docs/concepts/workloads/pods/init-containers/#detailed-behavior)
|
||||||
|
dentro del Job tienen un campo `activeDeadlineSeconds`. Asegúrate que pones el valor de este campo de forma adecuada.
|
||||||
|
|
||||||
|
## Limpiar los Jobs terminados automáticamente
|
||||||
|
|
||||||
|
Normalmente, los Jobs que han terminado ya no se necesitan en el sistema. Conservarlos sólo añade
|
||||||
|
más presión al servidor API. Si dichos Jobs no se gestionan de forma directa por un controlador de más alto nivel,
|
||||||
|
como los [CronJobs](/docs/concepts/workloads/controllers/cron-jobs/), los Jobs pueden
|
||||||
|
limpiarse por medio de CronJobs en base a la regla de limpieza basada en capacidad que se haya especificado.
|
||||||
|
|
||||||
|
### Mecanismo TTL para Jobs terminados
|
||||||
|
|
||||||
|
{{< feature-state for_k8s_version="v1.12" state="alpha" >}}
|
||||||
|
|
||||||
|
Otra forma de limpiar los Jobs terminados (bien `Complete` o `Failed`)
|
||||||
|
de forma automática es usando un mecanismo TTL proporcionado por un
|
||||||
|
[controlador TTL](/docs/concepts/workloads/controllers/ttlafterfinished/) de recursos finalizados,
|
||||||
|
indicando el valor `.spec.ttlSecondsAfterFinished` del Job.
|
||||||
|
|
||||||
|
Cuando el controlador TTL limpia el Job, lo eliminará en cascada,
|
||||||
|
esto es, eliminará sus objetos subordinados, como Pods, junto con el Job. Nótese
|
||||||
|
que cuando se elimina el Job, sus garantías de ciclo de vida, como los finalizadores,
|
||||||
|
se tendrán en cuenta.
|
||||||
|
|
||||||
|
Por ejemplo:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: batch/v1
|
||||||
|
kind: Job
|
||||||
|
metadata:
|
||||||
|
name: pi-with-ttl
|
||||||
|
spec:
|
||||||
|
ttlSecondsAfterFinished: 100
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: pi
|
||||||
|
image: perl
|
||||||
|
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
|
||||||
|
restartPolicy: Never
|
||||||
|
```
|
||||||
|
|
||||||
|
Aquí el Job `pi-with-ttl` será candidato a ser automáticamente eliminado, `100`
|
||||||
|
segundos después de que termine.
|
||||||
|
|
||||||
|
Si el campo se pone a `0`, el Job será candidato a ser automáticamente eliminado
|
||||||
|
inmediatamente después de haber terminado. Si no se pone valor al campo, este Job no será eliminado
|
||||||
|
por el controlador TTL una vez concluya.
|
||||||
|
|
||||||
|
Nótese que este mecanismo TTL está todavía en alpha, a través de la característica denominada `TTLAfterFinished`.
|
||||||
|
Para más información, ver la documentación del [controlador TTL](/docs/concepts/workloads/controllers/ttlafterfinished/) para
|
||||||
|
recursos terminados.
|
||||||
|
|
||||||
|
## Patrones de Job
|
||||||
|
|
||||||
|
El objeto Job puede usarse para dar soporte a la ejecución fiable de Pods en paralelo. El objeto Job
|
||||||
|
no se diseñó para dar soporte a procesos paralelos estrechamente comunicados, como los que comúnmente
|
||||||
|
se encuentran en la computación científica. Eso sí, permite el proceso paralelo de un conjunto de *ítems de trabajo* independientes, pero relacionados entre sí.
|
||||||
|
Estos pueden ser correos a enviar, marcos a renderizar, archivos a codificar, rangos de claves en una base de datos NoSQL a escanear, y demás.
|
||||||
|
|
||||||
|
En un sistema complejo, puede haber múltiples diferentes conjuntos de ítems de trabajo. Aquí sólo se está
|
||||||
|
considerando un conjunto de ítems de trabajo que el usuario quiere gestionar de forma conjunta — un *proceso por lotes*.
|
||||||
|
|
||||||
|
Hay varios patrones diferentes para computación en paralelo, cada uno con sus fortalezas y sus debilidades.
|
||||||
|
Los sacrificios a tener en cuenta son:
|
||||||
|
|
||||||
|
- Un objeto Job para cada ítem de trabajo vs. un objeto Job simple para todos los ítems de trabajo. El último es mejor
|
||||||
|
para grandes números de ítems de trabajo. El primero añade sobrecarga para el usuario y para el sistema
|
||||||
|
al tener que gestionar grandes números de objetos Job.
|
||||||
|
- El número de pods creados es igual al número de ítems de trabajo vs. cada Pod puede procesar múltiplese ítems de trabajo.
|
||||||
|
El primero típicamente requiere menos modificaciones al código existente y a los contenedores.
|
||||||
|
El último es mejor cuanto mayor sea el número de ítems de trabajo, por las mismas razones que antes..
|
||||||
|
- Varios enfoques usan una cola de trabajo. Ello requiere ejecutar un servicio de colas,
|
||||||
|
y modificaciones a las aplicaciones o contenedores existentes para que hagan uso de la cola de trabajo.
|
||||||
|
Otras estrategias son más fáciles de adaptar a una aplicación ya usando contenedores.
|
||||||
|
|
||||||
|
|
||||||
|
Los sacrificios a tener en cuenta se indican a continuación, donde las columnas 2 a 4 representan los sacrificios de arriba.
|
||||||
|
Los nombres de los patrones son también enlaces a ejemplos e información más detallada.
|
||||||
|
|
||||||
|
| Patrón | Objeto Job simple | ¿Menos pods que ítems de trabajo? | ¿No modificar la aplicación? | ¿Funciona en Kube 1.1? |
|
||||||
|
| -------------------------------------------------------------------- |:-----------------:|:---------------------------:|:-------------------:|:-------------------:|
|
||||||
|
| [Extensión de la Plantilla Job](/docs/tasks/job/parallel-processing-expansion/) | | | ✓ | ✓ |
|
||||||
|
| [Cola con Pod por Ítem de Trabajo](/docs/tasks/job/coarse-parallel-processing-work-queue/) | ✓ | | a veces | ✓ |
|
||||||
|
| [Cola con Cuenta Variable de Pods](/docs/tasks/job/fine-parallel-processing-work-queue/) | ✓ | ✓ | | ✓ |
|
||||||
|
| Job simple con Asignación Estática de Trabajo | ✓ | | ✓ | |
|
||||||
|
|
||||||
|
Cuando se especifican terminaciones con `.spec.completions`, cada Pod creado por el controlado del Job
|
||||||
|
tiene un [`spec`](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status)idéntico.
|
||||||
|
Esto significa que todos los pods de una tarea tendrán la misma línea de comandos y la
|
||||||
|
misma imagne, los mismo volúmenes, y (casi) las mismas variables de entorno.
|
||||||
|
Estos patrones otorgan diferentes formas de organizar los pods para que trabajen en cosas distintas.
|
||||||
|
|
||||||
|
Esta tabla muestra la configuración necesaria para `.spec.parallelism` y `.spec.completions` para cada uno de los patrones.
|
||||||
|
Aquí, `T` es el número de ítems de trabajo.
|
||||||
|
|
||||||
|
| Patrón | `.spec.completions` | `.spec.parallelism` |
|
||||||
|
| -------------------------------------------------------------------- |:-------------------:|:--------------------:|
|
||||||
|
| [Extensión de la Plantilla Job](/docs/tasks/job/parallel-processing-expansion/) | 1 | debería ser 1 |
|
||||||
|
| [Cola con Pod por Ítem de Trabajo](/docs/tasks/job/coarse-parallel-processing-work-queue/) | T | cualquiera |
|
||||||
|
| [Cola con Cuenta Variable de Pods](/docs/tasks/job/fine-parallel-processing-work-queue/) | 1 | cualquiera |
|
||||||
|
| Job simple con Asignación Estática de Trabajo | T | cualquiera |
|
||||||
|
|
||||||
|
|
||||||
|
## Uso Avanzado
|
||||||
|
|
||||||
|
### Especificar tu propio selector de pod
|
||||||
|
|
||||||
|
Normalmente, cuando creas un objeto Job, no especificas el campo `.spec.selector`.
|
||||||
|
La lógica por defecto del sistema añade este campo cuando se crea el Job.
|
||||||
|
Se elige un valor de selector que no se entremezcle con otras tareas.
|
||||||
|
|
||||||
|
Sin embargo, en algunos casos, puede que necesites sobreescribir este selector que se configura de forma automática.
|
||||||
|
Para ello, puedes indicar el valor de `.spec.selector` en el Job.
|
||||||
|
|
||||||
|
Pero ten mucho cuidado cuando lo hagas. Si configuras un selector de etiquta que no
|
||||||
|
es único para los pods de ese Job, y que selecciona Pods que no tienen que ver,
|
||||||
|
entonces estos últimos pueden ser eliminados, o este Job puede contar los otros
|
||||||
|
Pods para terminarse, o uno o ambos Jobs pueden negarse a crear Pods o ejecutarse hasta el final.
|
||||||
|
Si se elige un selector que no es único, entonces otros controladores (ej. ReplicationController)
|
||||||
|
y sus Pods puede comportarse de forma impredecibles también. Kubernetes no te impide cometer un error
|
||||||
|
especificando el `.spec.selector`.
|
||||||
|
|
||||||
|
Aquí se muestra un ejemplo de un caso en que puede que necesites usar esta característica.
|
||||||
|
|
||||||
|
Digamos que el Job `viejo` todavía está ejeuctándose. Quieres que los Pods existentes
|
||||||
|
sigan corriendo, pero quieres que el resto de los Pods que se creen
|
||||||
|
usen una plantilla pod diferente y que el Job tenga un nombre nuevo.
|
||||||
|
Como no puedes modificar el Job porque esos campos no son modificables, eliminas el Job `old`,
|
||||||
|
pero _dejas sus pods ejecutándose_ mediante el comando `kubectl delete jobs/old --cascade=false`.
|
||||||
|
Antes de eliminarlo, apúntate el selector actual que está usando:
|
||||||
|
|
||||||
|
```
|
||||||
|
kind: Job
|
||||||
|
metadata:
|
||||||
|
name: viejo
|
||||||
|
...
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
job-uid: a8f3d00d-c6d2-11e5-9f87-42010af00002
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Entonces, creas un nuevo Job con el nombre `nuevo` y le configuras explícitamente el mismo selector.
|
||||||
|
Puesto que los Pods existentes tienen la etiqueta `job-uid=a8f3d00d-c6d2-11e5-9f87-42010af00002`,
|
||||||
|
son controlados por el Job `nuevo` igualmente.
|
||||||
|
|
||||||
|
Necesitas configurar `manualSelector: true` en el nuevo Job, ya qye no estás usando
|
||||||
|
el selector que normalmente se genera de forma automática por el sistema.
|
||||||
|
|
||||||
|
```
|
||||||
|
kind: Job
|
||||||
|
metadata:
|
||||||
|
name: nuevo
|
||||||
|
...
|
||||||
|
spec:
|
||||||
|
manualSelector: true
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
job-uid: a8f3d00d-c6d2-11e5-9f87-42010af00002
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
El mismo Job nuevo tendrá un uid distinto a `a8f3d00d-c6d2-11e5-9f87-42010af00002`.
|
||||||
|
Poniendo `manualSelector: true` le dice al sistema que sabes lo que estás haciendo
|
||||||
|
y que te permita hacer este desajuste.
|
||||||
|
|
||||||
|
## Alternativas
|
||||||
|
|
||||||
|
### Pods simples
|
||||||
|
|
||||||
|
Cuando el nodo donde un Pod simple se estaba ejecutando se reinicia o falla, dicho pod se termina
|
||||||
|
y no será reinicado. Sin embargo, un Job creará nuevos Pods para sustituir a los que se han terminando.
|
||||||
|
Por esta razón, se recomienda que se use un Job en vez de un Pod simple, incluso si tu aplicación
|
||||||
|
sólo necesita un único Pod.
|
||||||
|
|
||||||
|
### Replication Controller
|
||||||
|
|
||||||
|
Los Jobs son complementarios a los [Replication Controllers](/docs/user-guide/replication-controller).
|
||||||
|
Un Replication Controller gestiona aquellos Pods que se espera que no terminen (ej. servidores web), y un Job
|
||||||
|
gestiona aquellos Pods que se espera que terminen (ej. tareas por lotes).
|
||||||
|
|
||||||
|
Como se discutió en el [Ciclo de vida de un Pod](/docs/concepts/workloads/pods/pod-lifecycle/), un `Job` *sólo* es apropiado
|
||||||
|
para aquellos pods con `RestartPolicy` igual a `OnFailure` o `Never`.
|
||||||
|
(Nota: Si `RestartPolicy` no se pone, el valor predeterminado es `Always`.)
|
||||||
|
|
||||||
|
### Job simple arranca que arranca un controlador de Pod
|
||||||
|
|
||||||
|
Otro patrón es aquel donde un Job simple crea un Pod que, a su vez, crea otros Pods, actuando como una especie
|
||||||
|
de controlador personalizado para esos Pods. Esto da la máxima flexibilidad, pero puede que
|
||||||
|
cueste un poco más de entender y ofrece menos integración con Kubernetes.
|
||||||
|
|
||||||
|
Un ejemplo de este patrón sería un Job que arranca un Pod que ejecuta una secuencia de comandos que, a su vez,
|
||||||
|
arranca un controlador maestro de Spark (ver el [ejemplo de spark](https://github.com/kubernetes/examples/tree/{{< param "githubbranch" >}}/staging/spark/README.md)),
|
||||||
|
ejecuta un manejador de spark, y a continuación lo limpia todo.
|
||||||
|
|
||||||
|
Una ventaja de este enfoque es que el proceso general obtiene la garantía del objeto Job,
|
||||||
|
además del control completo de los Pods que se crean y cómo se les asigna trabajo.
|
||||||
|
|
||||||
|
## Cron Jobs {#cron-jobs}
|
||||||
|
|
||||||
|
Puedes utilizar un [`CronJob`](/docs/concepts/workloads/controllers/cron-jobs/) para crear un Job que se ejecute en una hora/fecha determinadas, de forma similar
|
||||||
|
a la herramienta `cron` de Unix.
|
||||||
|
|
||||||
|
{{% /capture %}}
|
||||||
@@ -0,0 +1,370 @@
|
|||||||
|
---
|
||||||
|
title: ReplicaSet
|
||||||
|
content_template: templates/concept
|
||||||
|
weight: 10
|
||||||
|
---
|
||||||
|
|
||||||
|
{{% capture overview %}}
|
||||||
|
|
||||||
|
El objeto de un ReplicaSet es el de mantener un conjunto estable de réplicas de Pods ejecutándose
|
||||||
|
en todo momento. Así, se usa en numerosas ocasiones para garantizar la disponibilidad de un
|
||||||
|
número específico de Pods idénticos.
|
||||||
|
|
||||||
|
|
||||||
|
{{% /capture %}}
|
||||||
|
|
||||||
|
{{% capture body %}}
|
||||||
|
|
||||||
|
## Cómo funciona un ReplicaSet
|
||||||
|
|
||||||
|
Un ReplicaSet se define con campos, incluyendo un selector que indica cómo identificar a los Pods que puede adquirir,
|
||||||
|
un número de réplicas indicando cuántos Pods debería gestionar, y una plantilla pod especificando los datos de los nuevos Pods
|
||||||
|
que debería crear para conseguir el número de réplicas esperado. Un ReplicaSet alcanza entonces su propósito
|
||||||
|
mediante la creación y eliminación de los Pods que sea necesario para alcanzar el número esperado.
|
||||||
|
Cuando un ReplicaSet necesita crear nuevos Pods, utiliza su plantilla Pod.
|
||||||
|
|
||||||
|
El enlace que un ReplicaSet tiene hacia sus Pods es a través del campo del Pod denominado [metadata.ownerReferences](/docs/concepts/workloads/controllers/garbage-collection/#owners-and-dependents),
|
||||||
|
el cual indica qué recurso es el propietario del objeto actual. Todos los Pods adquiridos por un ReplicaSet tienen su propia
|
||||||
|
información de identificación del ReplicaSet en su campo ownerReferences. Y es a través de este enlace
|
||||||
|
cómo el ReplicaSet conoce el estado de los Pods que está gestionando y actúa en consecuencia.
|
||||||
|
|
||||||
|
Un ReplicaSet identifica los nuevos Pods a adquirir usando su selector. Si hay un Pod que no tiene OwnerReference
|
||||||
|
o donde OwnerReference no es un controlador, pero coincide con el selector del ReplicaSet,
|
||||||
|
este será inmediatamente adquirido por dicho ReplicaSet.
|
||||||
|
|
||||||
|
## Cuándo usar un ReplicaSet
|
||||||
|
|
||||||
|
Un ReplicaSet garantiza que un número específico de réplicas de un pod se está ejeuctando en todo momento.
|
||||||
|
Sin embargo, un Deployment es un concepto de más alto nivel que gestiona ReplicaSets y
|
||||||
|
proporciona actualizaciones de forma declarativa de los Pods junto con muchas otras características útiles.
|
||||||
|
Por lo tanto, se recomienda el uso de Deployments en vez del uso directo de ReplicaSets, a no ser
|
||||||
|
que se necesite una orquestración personalizada de actualización o no se necesite las actualizaciones en absoluto.
|
||||||
|
|
||||||
|
En realidad, esto quiere decir que puede que nunca necesites manipular los objetos ReplicaSet:
|
||||||
|
en vez de ello, usa un Deployment, y define tu aplicación en la sección spec.
|
||||||
|
|
||||||
|
## Ejemplo
|
||||||
|
|
||||||
|
{{< codenew file="controllers/frontend.yaml" >}}
|
||||||
|
|
||||||
|
Si guardas este manifiesto en un archivo llamado `frontend.yaml` y lo lanzas en un clúster de Kubernetes,
|
||||||
|
se creará el ReplicaSet definido y los Pods que maneja.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl apply -f http://k8s.io/examples/controllers/frontend.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Puedes ver los ReplicaSets actuales desplegados:
|
||||||
|
```shell
|
||||||
|
kubectl get rs
|
||||||
|
```
|
||||||
|
|
||||||
|
Y ver el frontend que has creado:
|
||||||
|
```shell
|
||||||
|
NAME DESIRED CURRENT READY AGE
|
||||||
|
frontend 3 3 3 6s
|
||||||
|
```
|
||||||
|
|
||||||
|
También puedes comprobar el estado del replicaset:
|
||||||
|
```shell
|
||||||
|
kubectl describe rs/frontend
|
||||||
|
```
|
||||||
|
|
||||||
|
Y verás una salida parecida a la siguiente:
|
||||||
|
```shell
|
||||||
|
Name: frontend
|
||||||
|
Namespace: default
|
||||||
|
Selector: tier=frontend,tier in (frontend)
|
||||||
|
Labels: app=guestbook
|
||||||
|
tier=frontend
|
||||||
|
Annotations: <none>
|
||||||
|
Replicas: 3 current / 3 desired
|
||||||
|
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
|
||||||
|
Pod Template:
|
||||||
|
Labels: app=guestbook
|
||||||
|
tier=frontend
|
||||||
|
Containers:
|
||||||
|
php-redis:
|
||||||
|
Image: gcr.io/google_samples/gb-frontend:v3
|
||||||
|
Port: 80/TCP
|
||||||
|
Requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 100Mi
|
||||||
|
Environment:
|
||||||
|
GET_HOSTS_FROM: dns
|
||||||
|
Mounts: <none>
|
||||||
|
Volumes: <none>
|
||||||
|
Events:
|
||||||
|
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
|
||||||
|
--------- -------- ----- ---- ------------- -------- ------ -------
|
||||||
|
1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: frontend-qhloh
|
||||||
|
1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: frontend-dnjpy
|
||||||
|
1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: frontend-9si5l
|
||||||
|
```
|
||||||
|
|
||||||
|
Y por último, puedes comprobar los Pods que ha arrancado:
|
||||||
|
```shell
|
||||||
|
kubectl get Pods
|
||||||
|
```
|
||||||
|
|
||||||
|
Deberías ver la información de cada Pod similar a:
|
||||||
|
```shell
|
||||||
|
NAME READY STATUS RESTARTS AGE
|
||||||
|
frontend-9si5l 1/1 Running 0 1m
|
||||||
|
frontend-dnjpy 1/1 Running 0 1m
|
||||||
|
frontend-qhloh 1/1 Running 0 1m
|
||||||
|
```
|
||||||
|
|
||||||
|
También puedes verificar que la referencia de propietario de dichos pods está puesta al ReplicaSet frontend.
|
||||||
|
Para ello, obtén el yaml de uno de los Pods ejecutándose:
|
||||||
|
```shell
|
||||||
|
kubectl get pods frontend-9si5l -o yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
La salida será parecida a esta, donde la información sobre el ReplicaSet aparece en el campo ownerReferences de los metadatos:
|
||||||
|
```shell
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: 2019-01-31T17:20:41Z
|
||||||
|
generateName: frontend-
|
||||||
|
labels:
|
||||||
|
tier: frontend
|
||||||
|
name: frontend-9si5l
|
||||||
|
namespace: default
|
||||||
|
ownerReferences:
|
||||||
|
- apiVersion: extensions/v1beta1
|
||||||
|
blockOwnerDeletion: true
|
||||||
|
controller: true
|
||||||
|
kind: ReplicaSet
|
||||||
|
name: frontend
|
||||||
|
uid: 892a2330-257c-11e9-aecd-025000000001
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Adquisiciones de Pods fuera de la plantilla
|
||||||
|
|
||||||
|
Aunque puedes crear Pods simples sin problemas, se recomienda encarecidamente asegurarse de que dichos Pods no tienen
|
||||||
|
etiquetas que puedan coincidir con el selector de alguno de tus ReplicaSets.
|
||||||
|
La razón de esta recomendación es que un ReplicaSet no se limita a poseer los Pods
|
||||||
|
especificados en su plantilla -- sino que puede adquirir otros Pods como se explicó en secciones anteriores.
|
||||||
|
|
||||||
|
Toma el ejemplo anterior del ReplicaSet frontend, y los Pods especificados en el siguiente manifiesto:
|
||||||
|
|
||||||
|
{{< codenew file="pods/pod-rs.yaml" >}}
|
||||||
|
|
||||||
|
Como estos Pods no tienen un Controlador (o cualquier otro objeto) como referencia de propietario
|
||||||
|
y como además su selector coincide con el del ReplicaSet frontend, este último los terminará adquiriendo de forma inmediata.
|
||||||
|
|
||||||
|
Supón que creas los Pods después de que el ReplicaSet frontend haya desplegado los suyos
|
||||||
|
para satisfacer su requisito de cuenta de réplicas:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl apply -f http://k8s.io/examples/pods/pod-rs.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Los nuevos Pods serán adquiridos por el ReplicaSet, e inmediatamente terminados ya que
|
||||||
|
el ReplicaSet estaría por encima del número deseado.
|
||||||
|
|
||||||
|
Obtener los Pods:
|
||||||
|
```shell
|
||||||
|
kubectl get Pods
|
||||||
|
```
|
||||||
|
|
||||||
|
La salida muestra que los nuevos Pods se han terminado, o están en el proceso de terminarse:
|
||||||
|
```shell
|
||||||
|
NAME READY STATUS RESTARTS AGE
|
||||||
|
frontend-9si5l 1/1 Running 0 1m
|
||||||
|
frontend-dnjpy 1/1 Running 0 1m
|
||||||
|
frontend-qhloh 1/1 Running 0 1m
|
||||||
|
pod2 0/1 Terminating 0 4s
|
||||||
|
```
|
||||||
|
|
||||||
|
Si creas primero los Pods:
|
||||||
|
```shell
|
||||||
|
kubectl apply -f http://k8s.io/examples/pods/pod-rs.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Y entonces creas el ReplicaSet:
|
||||||
|
```shell
|
||||||
|
kubectl apply -f http://k8s.io/examples/controllers/frontend.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Verás que el ReplicaSet ha adquirido dichos Pods y simplemente ha creado tantos nuevos
|
||||||
|
como necesarios para cumplir con su especificación hasta que el número de
|
||||||
|
sus nuevos Pods y los originales coincidan con la cuenta deseado. Al obtener los Pods:
|
||||||
|
```shell
|
||||||
|
kubectl get Pods
|
||||||
|
```
|
||||||
|
|
||||||
|
Veremos su salida:
|
||||||
|
```shell
|
||||||
|
NAME READY STATUS RESTARTS AGE
|
||||||
|
frontend-pxj4r 1/1 Running 0 5s
|
||||||
|
pod1 1/1 Running 0 13s
|
||||||
|
pod2 1/1 Running 0 13s
|
||||||
|
```
|
||||||
|
|
||||||
|
De esta forma, un ReplicaSet puede poseer un conjunto no homogéneo de Pods
|
||||||
|
|
||||||
|
## Escribir un manifiesto de ReplicaSet
|
||||||
|
|
||||||
|
Al igual que con el esto de los objeto de la API de Kubernetes, un ReplicaSet necesita los campos
|
||||||
|
`apiVersion`, `kind`, y `metadata`. Para los ReplicaSets, el tipo es siempre ReplicaSet.
|
||||||
|
En la versión 1.9 de Kubernetes, la versión `apps/v1` de la API en un tipo ReplicaSet es la versión actual y está habilitada por defecto.
|
||||||
|
La versión `apps/v1beta2` de la API se ha desaprobado.
|
||||||
|
Consulta las primeras líneas del ejemplo `frontend.yaml` como guía.
|
||||||
|
|
||||||
|
Un ReplicaSet también necesita una [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 una [plantilla pod](/docs/concepts/workloads/Pods/pod-overview/#pod-templates) que es
|
||||||
|
también necesita obligatoriamente tener etiquetas definidas. En nuestro ejemplo `frontend.yaml` teníamos una etiqueta: `tier: frontend`.
|
||||||
|
Lleva cuidado de que no se entremezcle con los selectores de otros controladores, no sea que traten de adquirir este Pod.
|
||||||
|
|
||||||
|
Para el campo de [regla de reinicio](/docs/concepts/workloads/Pods/pod-lifecycle/#restart-policy) de la plantilla,
|
||||||
|
`.spec.template.spec.restartPolicy`, el único valor permitido es `Always`, que es el valor predeterminado.
|
||||||
|
|
||||||
|
### Selector de Pod
|
||||||
|
|
||||||
|
El campo `.spec.selector` es un [selector de etiqueta](/docs/concepts/overview/working-with-objects/labels/).
|
||||||
|
Como se explicó [anteriormente](#how-a-replicaset-works), estas son las etiquetas que se usan para
|
||||||
|
identificar los Pods potenciales a adquirir. En nuestro ejemplo `frontend.yaml`, el selector era:
|
||||||
|
```shell
|
||||||
|
matchLabels:
|
||||||
|
tier: frontend
|
||||||
|
```
|
||||||
|
|
||||||
|
El el ReplicaSet, `.spec.template.metadata.labels` debe coincidir con `spec.selector`, o será
|
||||||
|
rechazado por la API.
|
||||||
|
|
||||||
|
{{< note >}}
|
||||||
|
Cuando 2 ReplicaSets especifican el mismo campo `.spec.selector`, pero los campos
|
||||||
|
`.spec.template.metadata.labels` y `.spec.template.spec` diferentes, cada ReplicaSet
|
||||||
|
ignora los Pods creados por el otro ReplicaSet.
|
||||||
|
{{< /note >}}
|
||||||
|
|
||||||
|
### Réplicas
|
||||||
|
|
||||||
|
Puedes configurar cuántos Pods deberían ejecutarse de forma concurrente indicando el campo `.spec.replicas`.
|
||||||
|
El ReplicaSet creará/eliminará sus Pods para alcanzar este número.
|
||||||
|
|
||||||
|
Si no indicas el valor del campo `.spec.replicas`, entonces por defecto se inicializa a 1.
|
||||||
|
|
||||||
|
## Trabajar con ReplicaSets
|
||||||
|
|
||||||
|
### Eliminar un ReplicaSet y sus Pods
|
||||||
|
|
||||||
|
Para eliminar un ReplicaSet y todos sus Pods, utiliza el comando [`kubectl delete`](/docs/reference/generated/kubectl/kubectl-commands#delete).
|
||||||
|
El [Recolector de basura](/docs/concepts/workloads/controllers/garbage-collection/) eliminará automáticamente
|
||||||
|
todos los Pods subordinados por defecto.
|
||||||
|
|
||||||
|
Cuando se usa la API REST o la librería `client-go`, se debe poner el valor de `propagationPolicy` a `Background` o
|
||||||
|
`Foreground` en la opción -d.
|
||||||
|
Por ejemplo:
|
||||||
|
```shell
|
||||||
|
kubectl proxy --port=8080
|
||||||
|
curl -X DELETE 'localhost:8080/apis/extensions/v1beta1/namespaces/default/replicasets/frontend' \
|
||||||
|
> -d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Foreground"}' \
|
||||||
|
> -H "Content-Type: application/json"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Eliminar sólo un ReplicaSet
|
||||||
|
|
||||||
|
Se puede eliminar un ReplicaSet sin afectar a ninguno de sus Pods usando el comando [`kubectl delete`](/docs/reference/generated/kubectl/kubectl-commands#delete) con la opción `--cascade=false`.
|
||||||
|
Cuando se usa la API REST o la librería `client-go`, se debe poner `propagationPolicy` a `Orphan`.
|
||||||
|
Por ejemplo:
|
||||||
|
```shell
|
||||||
|
kubectl proxy --port=8080
|
||||||
|
curl -X DELETE 'localhost:8080/apis/extensions/v1beta1/namespaces/default/replicasets/frontend' \
|
||||||
|
> -d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Orphan"}' \
|
||||||
|
> -H "Content-Type: application/json"
|
||||||
|
```
|
||||||
|
|
||||||
|
Una vez que se ha eliminado el original, se puede crear un nuevo ReplicaSet para sustituirlo.
|
||||||
|
Mientras el viejo y el nuevo `.spec.selector` sean el mismo, el nuevo adoptará a los viejos Pods.
|
||||||
|
Sin embargo, no se esforzará en conseguir que los Pods existentes coincidan con una plantilla pod nueva, diferente.
|
||||||
|
Para actualizar dichos Pods a la nueva especificación de forma controlada,
|
||||||
|
usa una [actualización en línea](#rolling-updates).
|
||||||
|
|
||||||
|
### Aislar Pods de un ReplicaSet
|
||||||
|
|
||||||
|
Es posible aislar Pods de un ReplicaSet cambiando sus etiquetas. Esta técnica puede usarse
|
||||||
|
para eliminar Pods de un servicio para poder depurar, recuperar datos, etc. Los Pods
|
||||||
|
que se eliminar de esta forma serán sustituidos de forma automática (siempre que el
|
||||||
|
número de réplicas no haya cambiado).
|
||||||
|
|
||||||
|
### Escalar un ReplicaSet
|
||||||
|
|
||||||
|
Se puede aumentar o reducir fácilmente un ReplicaSet simplemente actualizando el campo `.spec.replicas`.
|
||||||
|
El controlador del ReplicaSet se asegura de que el número deseado de Pods con un selector
|
||||||
|
de etiquetas coincidente está disponible y operacional.
|
||||||
|
|
||||||
|
### ReplicaSet como blanco de un Horizontal Pod Autoscaler
|
||||||
|
|
||||||
|
Un ReplicaSet puede también ser el blanco de un
|
||||||
|
[Horizontal Pod Autoscalers (HPA)](/docs/tasks/run-application/horizontal-pod-autoscale/). Esto es,
|
||||||
|
un ReplicaSet puede auto-escalarse mediante un HPA. Aquí se muestra un ejemplo de HPA dirigido
|
||||||
|
al ReplicaSet que creamos en el ejemplo anterior.
|
||||||
|
|
||||||
|
{{< codenew file="controllers/hpa-rs.yaml" >}}
|
||||||
|
|
||||||
|
Si guardas este manifiesto en un archivo `hpa-rs.yaml` y lo lanzas contra el clúster de Kubernetes,
|
||||||
|
debería crear el HPA definido que auto-escala el ReplicaSet destino dependiendo del uso
|
||||||
|
de CPU de los Pods replicados.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl apply -f https://k8s.io/examples/controllers/hpa-rs.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternativamente, puedes usar el comando `kubectl autoscale` para conseguir el mismo objetivo
|
||||||
|
(¡y mucho más fácil!)
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl autoscale rs frontend --max=10
|
||||||
|
```
|
||||||
|
|
||||||
|
## Alternativas al ReplicaSet
|
||||||
|
|
||||||
|
### Deployment (recomendado)
|
||||||
|
|
||||||
|
Un[`Deployment`](/docs/concepts/workloads/controllers/deployment/) es un objeto que puede poseer ReplicaSets
|
||||||
|
y actualizar a estos y a sus Pods mediante actualizaciones en línea declarativas en el servidor.
|
||||||
|
Aunque que los ReplicaSets puede usarse independientemente, hoy en día se usan principalmente a través de los Deployments
|
||||||
|
como el mecanismo para orquestrar la creación, eliminación y actualización de los Pods.
|
||||||
|
Cuando usas Deployments no tienes que preocuparte de gestionar los ReplicaSets que crean.
|
||||||
|
Los Deployments poseen y gestionan sus ReplicaSets.
|
||||||
|
Por tanto, se recomienda que se use Deployments cuando se quiera ReplicaSets.
|
||||||
|
|
||||||
|
### Pods simples
|
||||||
|
|
||||||
|
A diferencia del caso en que un usuario creaba Pods de forma directa, un ReplicaSet sustituye los Pods que se eliminan
|
||||||
|
o se terminan por la razón que sea, como en el caso de un fallo de un nodo o
|
||||||
|
una intervención disruptiva de mantenimiento, como una actualización de kernel.
|
||||||
|
Por esta razón, se recomienda que se use un ReplicaSet incluso cuando la aplicación
|
||||||
|
sólo necesita un único Pod. Entiéndelo de forma similar a un proceso supervisor,
|
||||||
|
donde se supervisa múltiples Pods entre múltiples nodos en vez de procesos individuales
|
||||||
|
en un único nodo. Un ReplicaSet delega los reinicios del contenedor local 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 ReplicaSet para
|
||||||
|
aquellos Pods que se esperan que terminen por ellos mismos (esto es, trabajos por lotes).
|
||||||
|
|
||||||
|
### DaemonSet
|
||||||
|
|
||||||
|
Usa un [`DaemonSet`](/docs/concepts/workloads/controllers/daemonset/) en vez de un ReplicaSet para aquellos
|
||||||
|
Pods que proporcionan funcionalidad a nivel de servidor, como monitorización de servidor o
|
||||||
|
logging de servidor. Estos Pods tienen un ciclo de vida asociado al del servidor mismo:
|
||||||
|
el Pod necesita ejecutarse en el servidor antes de que los otros Pods comiencen, y es seguro
|
||||||
|
que terminen cuando el servidor esté listo para ser reiniciado/apagado.
|
||||||
|
|
||||||
|
### ReplicationController
|
||||||
|
Los ReplicaSets son los sucesores de los [_ReplicationControllers_](/docs/concepts/workloads/controllers/replicationcontroller/).
|
||||||
|
Los dos sirven al mismo propósito, y se comportan de forma similar, excepto porque un ReplicationController
|
||||||
|
no soporta los requisitos del selector basado en conjunto, como se describe en la [guía de usuario de etiquetas](/docs/concepts/overview/working-with-objects/labels/#label-selectors).
|
||||||
|
Por ello, se prefiere los ReplicaSets a los ReplicationControllers.
|
||||||
|
|
||||||
|
{{% /capture %}}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: ReplicaSet
|
||||||
|
metadata:
|
||||||
|
name: frontend
|
||||||
|
labels:
|
||||||
|
app: guestbook
|
||||||
|
tier: frontend
|
||||||
|
spec:
|
||||||
|
# modifica las réplicas según tu caso de uso
|
||||||
|
replicas: 3
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
tier: frontend
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
tier: frontend
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: php-redis
|
||||||
|
image: gcr.io/google_samples/gb-frontend:v3
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: autoscaling/v1
|
||||||
|
kind: HorizontalPodAutoscaler
|
||||||
|
metadata:
|
||||||
|
name: frontend-scaler
|
||||||
|
spec:
|
||||||
|
scaleTargetRef:
|
||||||
|
kind: ReplicaSet
|
||||||
|
name: frontend
|
||||||
|
minReplicas: 3
|
||||||
|
maxReplicas: 10
|
||||||
|
targetCPUUtilizationPercentage: 50
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
apiVersion: batch/v1
|
||||||
|
kind: Job
|
||||||
|
metadata:
|
||||||
|
name: pi
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: pi
|
||||||
|
image: perl
|
||||||
|
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
|
||||||
|
restartPolicy: Never
|
||||||
|
backoffLimit: 4
|
||||||
|
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: pod1
|
||||||
|
labels:
|
||||||
|
tier: frontend
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: hello1
|
||||||
|
image: gcr.io/google-samples/hello-app:2.0
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: pod2
|
||||||
|
labels:
|
||||||
|
tier: frontend
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: hello2
|
||||||
|
image: gcr.io/google-samples/hello-app:1.0
|
||||||
Reference in New Issue
Block a user