|
| 1 | +--- |
| 2 | +title: ReplicaSet |
| 3 | +content_template: templates/concept |
| 4 | +weight: 10 |
| 5 | +--- |
| 6 | + |
| 7 | +{{% capture overview %}} |
| 8 | + |
| 9 | +El objeto de un ReplicaSet es el de mantener un conjunto estable de réplicas de Pods ejecutándose |
| 10 | +en todo momento. Así, se usa en numerosas ocasiones para garantizar la disponibilidad de un |
| 11 | +número específico de Pods idénticos. |
| 12 | + |
| 13 | + |
| 14 | +{{% /capture %}} |
| 15 | + |
| 16 | +{{% capture body %}} |
| 17 | + |
| 18 | +## Cómo funciona un ReplicaSet |
| 19 | + |
| 20 | +Un ReplicaSet se define con campos, incluyendo un selector que indica cómo identificar a los Pods que puede adquirir, |
| 21 | +un número de réplicas indicando cuántos Pods debería gestionar, y una plantilla pod especificando los datos de los nuevos Pods |
| 22 | +que debería crear para conseguir el número de réplicas esperado. Un ReplicaSet alcanza entonces su propósito |
| 23 | + mediante la creación y eliminación de los Pods que sea necesario para alcanzar el número esperado. |
| 24 | + Cuando un ReplicaSet necesita crear nuevos Pods, utiliza su plantilla Pod. |
| 25 | + |
| 26 | +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), |
| 27 | +el cual indica qué recurso es el propietario del objeto actual. Todos los Pods adquiridos por un ReplicaSet tienen su propia |
| 28 | +información de identificación del ReplicaSet en su campo ownerReferences. Y es a través de este enlace |
| 29 | +cómo el ReplicaSet conoce el estado de los Pods que está gestionando y actúa en consecuencia. |
| 30 | + |
| 31 | +Un ReplicaSet identifica los nuevos Pods a adquirir usando su selector. Si hay un Pod que no tiene OwnerReference |
| 32 | +o donde OwnerReference no es un controlador, pero coincide con el selector del ReplicaSet, |
| 33 | +este será inmediatamente adquirido por dicho ReplicaSet. |
| 34 | + |
| 35 | +## Cuándo usar un ReplicaSet |
| 36 | + |
| 37 | +Un ReplicaSet garantiza que un número específico de réplicas de un pod se está ejeuctando en todo momento. |
| 38 | +Sin embargo, un Deployment es un concepto de más alto nivel que gestiona ReplicaSets y |
| 39 | +proporciona actualizaciones de forma declarativa de los Pods junto con muchas otras características útiles. |
| 40 | +Por lo tanto, se recomienda el uso de Deployments en vez del uso directo de ReplicaSets, a no ser |
| 41 | +que se necesite una orquestración personalizada de actualización o no se necesite las actualizaciones en absoluto. |
| 42 | + |
| 43 | +En realidad, esto quiere decir que puede que nunca necesites manipular los objetos ReplicaSet: |
| 44 | +en vez de ello, usa un Deployment, y define tu aplicación en la sección spec. |
| 45 | + |
| 46 | +## Ejemplo |
| 47 | + |
| 48 | +{{< codenew file="controllers/frontend.yaml" >}} |
| 49 | + |
| 50 | +Si guardas este manifiesto en un archivo llamado `frontend.yaml` y lo lanzas en un clúster de Kubernetes, |
| 51 | + se creará el ReplicaSet definido y los Pods que maneja. |
| 52 | + |
| 53 | +```shell |
| 54 | +kubectl apply -f http://k8s.io/examples/controllers/frontend.yaml |
| 55 | +``` |
| 56 | + |
| 57 | +Puedes ver los ReplicaSets actuales desplegados: |
| 58 | +```shell |
| 59 | +kubectl get rs |
| 60 | +``` |
| 61 | + |
| 62 | +Y ver el frontend que has creado: |
| 63 | +```shell |
| 64 | +NAME DESIRED CURRENT READY AGE |
| 65 | +frontend 3 3 3 6s |
| 66 | +``` |
| 67 | + |
| 68 | +También puedes comprobar el estado del replicaset: |
| 69 | +```shell |
| 70 | +kubectl describe rs/frontend |
| 71 | +``` |
| 72 | + |
| 73 | +Y verás una salida parecida a la siguiente: |
| 74 | +```shell |
| 75 | +Name: frontend |
| 76 | +Namespace: default |
| 77 | +Selector: tier=frontend,tier in (frontend) |
| 78 | +Labels: app=guestbook |
| 79 | + tier=frontend |
| 80 | +Annotations: <none> |
| 81 | +Replicas: 3 current / 3 desired |
| 82 | +Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed |
| 83 | +Pod Template: |
| 84 | + Labels: app=guestbook |
| 85 | + tier=frontend |
| 86 | + Containers: |
| 87 | + php-redis: |
| 88 | + Image: gcr.io/google_samples/gb-frontend:v3 |
| 89 | + Port: 80/TCP |
| 90 | + Requests: |
| 91 | + cpu: 100m |
| 92 | + memory: 100Mi |
| 93 | + Environment: |
| 94 | + GET_HOSTS_FROM: dns |
| 95 | + Mounts: <none> |
| 96 | + Volumes: <none> |
| 97 | +Events: |
| 98 | + FirstSeen LastSeen Count From SubobjectPath Type Reason Message |
| 99 | + --------- -------- ----- ---- ------------- -------- ------ ------- |
| 100 | + 1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: frontend-qhloh |
| 101 | + 1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: frontend-dnjpy |
| 102 | + 1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: frontend-9si5l |
| 103 | +``` |
| 104 | + |
| 105 | +Y por último, puedes comprobar los Pods que ha arrancado: |
| 106 | +```shell |
| 107 | +kubectl get Pods |
| 108 | +``` |
| 109 | + |
| 110 | +Deberías ver la información de cada Pod similar a: |
| 111 | +```shell |
| 112 | +NAME READY STATUS RESTARTS AGE |
| 113 | +frontend-9si5l 1/1 Running 0 1m |
| 114 | +frontend-dnjpy 1/1 Running 0 1m |
| 115 | +frontend-qhloh 1/1 Running 0 1m |
| 116 | +``` |
| 117 | + |
| 118 | +También puedes verificar que la referencia de propietario de dichos pods está puesta al ReplicaSet frontend. |
| 119 | +Para ello, obtén el yaml de uno de los Pods ejecutándose: |
| 120 | +```shell |
| 121 | +kubectl get pods frontend-9si5l -o yaml |
| 122 | +``` |
| 123 | + |
| 124 | +La salida será parecida a esta, donde la información sobre el ReplicaSet aparece en el campo ownerReferences de los metadatos: |
| 125 | +```shell |
| 126 | +apiVersion: v1 |
| 127 | +kind: Pod |
| 128 | +metadata: |
| 129 | + creationTimestamp: 2019-01-31T17:20:41Z |
| 130 | + generateName: frontend- |
| 131 | + labels: |
| 132 | + tier: frontend |
| 133 | + name: frontend-9si5l |
| 134 | + namespace: default |
| 135 | + ownerReferences: |
| 136 | + - apiVersion: extensions/v1beta1 |
| 137 | + blockOwnerDeletion: true |
| 138 | + controller: true |
| 139 | + kind: ReplicaSet |
| 140 | + name: frontend |
| 141 | + uid: 892a2330-257c-11e9-aecd-025000000001 |
| 142 | +... |
| 143 | +``` |
| 144 | + |
| 145 | +## Adquisiciones de Pods fuera de la plantilla |
| 146 | + |
| 147 | +Aunque puedes crear Pods simples sin problemas, se recomienda encarecidamente asegurarse de que dichos Pods no tienen |
| 148 | +etiquetas que puedan coincidir con el selector de alguno de tus ReplicaSets. |
| 149 | +La razón de esta recomendación es que un ReplicaSet no se limita a poseer los Pods |
| 150 | +especificados en su plantilla -- sino que puede adquirir otros Pods como se explicó en secciones anteriores. |
| 151 | + |
| 152 | +Toma el ejemplo anterior del ReplicaSet frontend, y los Pods especificados en el siguiente manifiesto: |
| 153 | + |
| 154 | +{{< codenew file="pods/pod-rs.yaml" >}} |
| 155 | + |
| 156 | +Como estos Pods no tienen un Controlador (o cualquier otro objeto) como referencia de propietario |
| 157 | +y como además su selector coincide con el del ReplicaSet frontend, este último los terminará adquiriendo de forma inmediata. |
| 158 | + |
| 159 | +Supón que creas los Pods después de que el ReplicaSet frontend haya desplegado los suyos |
| 160 | +para satisfacer su requisito de cuenta de réplicas: |
| 161 | + |
| 162 | +```shell |
| 163 | +kubectl apply -f http://k8s.io/examples/pods/pod-rs.yaml |
| 164 | +``` |
| 165 | + |
| 166 | +Los nuevos Pods serán adquiridos por el ReplicaSet, e inmediatamente terminados ya que |
| 167 | + el ReplicaSet estaría por encima del número deseado. |
| 168 | + |
| 169 | +Obtener los Pods: |
| 170 | +```shell |
| 171 | +kubectl get Pods |
| 172 | +``` |
| 173 | + |
| 174 | +La salida muestra que los nuevos Pods se han terminado, o están en el proceso de terminarse: |
| 175 | +```shell |
| 176 | +NAME READY STATUS RESTARTS AGE |
| 177 | +frontend-9si5l 1/1 Running 0 1m |
| 178 | +frontend-dnjpy 1/1 Running 0 1m |
| 179 | +frontend-qhloh 1/1 Running 0 1m |
| 180 | +pod2 0/1 Terminating 0 4s |
| 181 | +``` |
| 182 | + |
| 183 | +Si creas primero los Pods: |
| 184 | +```shell |
| 185 | +kubectl apply -f http://k8s.io/examples/pods/pod-rs.yaml |
| 186 | +``` |
| 187 | + |
| 188 | +Y entonces creas el ReplicaSet: |
| 189 | +```shell |
| 190 | +kubectl apply -f http://k8s.io/examples/controllers/frontend.yaml |
| 191 | +``` |
| 192 | + |
| 193 | +Verás que el ReplicaSet ha adquirido dichos Pods y simplemente ha creado tantos nuevos |
| 194 | +como necesarios para cumplir con su especificación hasta que el número de |
| 195 | +sus nuevos Pods y los originales coincidan con la cuenta deseado. Al obtener los Pods: |
| 196 | +```shell |
| 197 | +kubectl get Pods |
| 198 | +``` |
| 199 | + |
| 200 | +Veremos su salida: |
| 201 | +```shell |
| 202 | +NAME READY STATUS RESTARTS AGE |
| 203 | +frontend-pxj4r 1/1 Running 0 5s |
| 204 | +pod1 1/1 Running 0 13s |
| 205 | +pod2 1/1 Running 0 13s |
| 206 | +``` |
| 207 | + |
| 208 | +De esta forma, un ReplicaSet puede poseer un conjunto no homogéneo de Pods |
| 209 | + |
| 210 | +## Escribir un manifiesto de ReplicaSet |
| 211 | + |
| 212 | +Al igual que con el esto de los objeto de la API de Kubernetes, un ReplicaSet necesita los campos |
| 213 | +`apiVersion`, `kind`, y `metadata`. Para los ReplicaSets, el tipo es siempre ReplicaSet. |
| 214 | +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. |
| 215 | +La versión `apps/v1beta2` de la API se ha desaprobado. |
| 216 | +Consulta las primeras líneas del ejemplo `frontend.yaml` como guía. |
| 217 | + |
| 218 | +Un ReplicaSet también necesita una [sección `.spec`](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status). |
| 219 | + |
| 220 | +### Plantilla Pod |
| 221 | + |
| 222 | +El campo `.spec.template` es una [plantilla pod](/docs/concepts/workloads/Pods/pod-overview/#pod-templates) que es |
| 223 | + también necesita obligatoriamente tener etiquetas definidas. En nuestro ejemplo `frontend.yaml` teníamos una etiqueta: `tier: frontend`. |
| 224 | +Lleva cuidado de que no se entremezcle con los selectores de otros controladores, no sea que traten de adquirir este Pod. |
| 225 | + |
| 226 | +Para el campo de [regla de reinicio](/docs/concepts/workloads/Pods/pod-lifecycle/#restart-policy) de la plantilla, |
| 227 | +`.spec.template.spec.restartPolicy`, el único valor permitido es `Always`, que es el valor predeterminado. |
| 228 | + |
| 229 | +### Selector de Pod |
| 230 | + |
| 231 | +El campo `.spec.selector` es un [selector de etiqueta](/docs/concepts/overview/working-with-objects/labels/). |
| 232 | +Como se explicó [anteriormente](#how-a-replicaset-works), estas son las etiquetas que se usan para |
| 233 | + identificar los Pods potenciales a adquirir. En nuestro ejemplo `frontend.yaml`, el selector era: |
| 234 | +```shell |
| 235 | +matchLabels: |
| 236 | + tier: frontend |
| 237 | +``` |
| 238 | + |
| 239 | +El el ReplicaSet, `.spec.template.metadata.labels` debe coincidir con `spec.selector`, o será |
| 240 | + rechazado por la API. |
| 241 | + |
| 242 | +{{< note >}} |
| 243 | +Cuando 2 ReplicaSets especifican el mismo campo `.spec.selector`, pero los campos |
| 244 | +`.spec.template.metadata.labels` y `.spec.template.spec` diferentes, cada ReplicaSet |
| 245 | +ignora los Pods creados por el otro ReplicaSet. |
| 246 | +{{< /note >}} |
| 247 | + |
| 248 | +### Réplicas |
| 249 | + |
| 250 | +Puedes configurar cuántos Pods deberían ejecutarse de forma concurrente indicando el campo `.spec.replicas`. |
| 251 | +El ReplicaSet creará/eliminará sus Pods para alcanzar este número. |
| 252 | + |
| 253 | +Si no indicas el valor del campo `.spec.replicas`, entonces por defecto se inicializa a 1. |
| 254 | + |
| 255 | +## Trabajar con ReplicaSets |
| 256 | + |
| 257 | +### Eliminar un ReplicaSet y sus Pods |
| 258 | + |
| 259 | +Para eliminar un ReplicaSet y todos sus Pods, utiliza el comando [`kubectl delete`](/docs/reference/generated/kubectl/kubectl-commands#delete). |
| 260 | +El [Recolector de basura](/docs/concepts/workloads/controllers/garbage-collection/) eliminará automáticamente |
| 261 | + todos los Pods subordinados por defecto. |
| 262 | + |
| 263 | +Cuando se usa la API REST o la librería `client-go`, se debe poner el valor de `propagationPolicy` a `Background` o |
| 264 | +`Foreground` en la opción -d. |
| 265 | +Por ejemplo: |
| 266 | +```shell |
| 267 | +kubectl proxy --port=8080 |
| 268 | +curl -X DELETE 'localhost:8080/apis/extensions/v1beta1/namespaces/default/replicasets/frontend' \ |
| 269 | +> -d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Foreground"}' \ |
| 270 | +> -H "Content-Type: application/json" |
| 271 | +``` |
| 272 | + |
| 273 | +### Eliminar sólo un ReplicaSet |
| 274 | + |
| 275 | +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`. |
| 276 | +Cuando se usa la API REST o la librería `client-go`, se debe poner `propagationPolicy` a `Orphan`. |
| 277 | +Por ejemplo: |
| 278 | +```shell |
| 279 | +kubectl proxy --port=8080 |
| 280 | +curl -X DELETE 'localhost:8080/apis/extensions/v1beta1/namespaces/default/replicasets/frontend' \ |
| 281 | +> -d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Orphan"}' \ |
| 282 | +> -H "Content-Type: application/json" |
| 283 | +``` |
| 284 | + |
| 285 | +Una vez que se ha eliminado el original, se puede crear un nuevo ReplicaSet para sustituirlo. |
| 286 | +Mientras el viejo y el nuevo `.spec.selector` sean el mismo, el nuevo adoptará a los viejos Pods. |
| 287 | +Sin embargo, no se esforzará en conseguir que los Pods existentes coincidan con una plantilla pod nueva, diferente. |
| 288 | +Para actualizar dichos Pods a la nueva especificación de forma controlada, |
| 289 | +usa una [actualización en línea](#rolling-updates). |
| 290 | + |
| 291 | +### Aislar Pods de un ReplicaSet |
| 292 | + |
| 293 | +Es posible aislar Pods de un ReplicaSet cambiando sus etiquetas. Esta técnica puede usarse |
| 294 | +para eliminar Pods de un servicio para poder depurar, recuperar datos, etc. Los Pods |
| 295 | +que se eliminar de esta forma serán sustituidos de forma automática (siempre que el |
| 296 | +número de réplicas no haya cambiado). |
| 297 | + |
| 298 | +### Escalar un ReplicaSet |
| 299 | + |
| 300 | +Se puede aumentar o reducir fácilmente un ReplicaSet simplemente actualizando el campo `.spec.replicas`. |
| 301 | +El controlador del ReplicaSet se asegura de que el número deseado de Pods con un selector |
| 302 | +de etiquetas coincidente está disponible y operacional. |
| 303 | + |
| 304 | +### ReplicaSet como blanco de un Horizontal Pod Autoscaler |
| 305 | + |
| 306 | +Un ReplicaSet puede también ser el blanco de un |
| 307 | +[Horizontal Pod Autoscalers (HPA)](/docs/tasks/run-application/horizontal-pod-autoscale/). Esto es, |
| 308 | +un ReplicaSet puede auto-escalarse mediante un HPA. Aquí se muestra un ejemplo de HPA dirigido |
| 309 | +al ReplicaSet que creamos en el ejemplo anterior. |
| 310 | + |
| 311 | +{{< codenew file="controllers/hpa-rs.yaml" >}} |
| 312 | + |
| 313 | +Si guardas este manifiesto en un archivo `hpa-rs.yaml` y lo lanzas contra el clúster de Kubernetes, |
| 314 | +debería crear el HPA definido que auto-escala el ReplicaSet destino dependiendo del uso |
| 315 | +de CPU de los Pods replicados. |
| 316 | + |
| 317 | +```shell |
| 318 | +kubectl apply -f https://k8s.io/examples/controllers/hpa-rs.yaml |
| 319 | +``` |
| 320 | + |
| 321 | +Alternativamente, puedes usar el comando `kubectl autoscale` para conseguir el mismo objetivo |
| 322 | +(¡y mucho más fácil!) |
| 323 | + |
| 324 | +```shell |
| 325 | +kubectl autoscale rs frontend --max=10 |
| 326 | +``` |
| 327 | + |
| 328 | +## Alternativas al ReplicaSet |
| 329 | + |
| 330 | +### Deployment (recomendado) |
| 331 | + |
| 332 | +Un[`Deployment`](/docs/concepts/workloads/controllers/deployment/) es un objeto que puede poseer ReplicaSets |
| 333 | +y actualizar a estos y a sus Pods mediante actualizaciones en línea declarativas en el servidor. |
| 334 | +Aunque que los ReplicaSets puede usarse independientemente, hoy en día se usan principalmente a través de los Deployments |
| 335 | +como el mecanismo para orquestrar la creación, eliminación y actualización de los Pods. |
| 336 | +Cuando usas Deployments no tienes que preocuparte de gestionar los ReplicaSets que crean. |
| 337 | +Los Deployments poseen y gestionan sus ReplicaSets. |
| 338 | +Por tanto, se recomienda que se use Deployments cuando se quiera ReplicaSets. |
| 339 | + |
| 340 | +### Pods simples |
| 341 | + |
| 342 | +A diferencia del caso en que un usuario creaba Pods de forma directa, un ReplicaSet sustituye los Pods que se eliminan |
| 343 | +o se terminan por la razón que sea, como en el caso de un fallo de un nodo o |
| 344 | +una intervención disruptiva de mantenimiento, como una actualización de kernel. |
| 345 | +Por esta razón, se recomienda que se use un ReplicaSet incluso cuando la aplicación |
| 346 | +sólo necesita un único Pod. Entiéndelo de forma similar a un proceso supervisor, |
| 347 | +donde se supervisa múltiples Pods entre múltiples nodos en vez de procesos individuales |
| 348 | +en un único nodo. Un ReplicaSet delega los reinicios del contenedor local a algún agente |
| 349 | +del nodo (por ejemplo, Kubelet o Docker). |
| 350 | + |
| 351 | +### Job |
| 352 | + |
| 353 | +Usa un [`Job`](/docs/concepts/jobs/run-to-completion-finite-workloads/) en vez de un ReplicaSet para |
| 354 | + aquellos Pods que se esperan que terminen por ellos mismos (esto es, trabajos por lotes). |
| 355 | + |
| 356 | +### DaemonSet |
| 357 | + |
| 358 | +Usa un [`DaemonSet`](/docs/concepts/workloads/controllers/daemonset/) en vez de un ReplicaSet para aquellos |
| 359 | + Pods que proporcionan funcionalidad a nivel de servidor, como monitorización de servidor o |
| 360 | + logging de servidor. Estos Pods tienen un ciclo de vida asociado al del servidor mismo: |
| 361 | + el Pod necesita ejecutarse en el servidor antes de que los otros Pods comiencen, y es seguro |
| 362 | + que terminen cuando el servidor esté listo para ser reiniciado/apagado. |
| 363 | + |
| 364 | +### ReplicationController |
| 365 | +Los ReplicaSets son los sucesores de los [_ReplicationControllers_](/docs/concepts/workloads/controllers/replicationcontroller/). |
| 366 | +Los dos sirven al mismo propósito, y se comportan de forma similar, excepto porque un ReplicationController |
| 367 | +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). |
| 368 | +Por ello, se prefiere los ReplicaSets a los ReplicationControllers. |
| 369 | + |
| 370 | +{{% /capture %}} |
0 commit comments