My Profile Photo

Mauricio Villagran - Blog


#Cloud #DevOps #Azure #Powershell #Microsoft


Kubernetes

En este articulo pretendo hablar de manera ordenada sobre los conceptos basicos que hacen de kubernetes el orquestador de contenedores mas usado para orquestar aplicaciones que corren sobre contenedores.

Conceptos a tener en cuenta

  • Cluster: Conjunto de máquinas físicas o virtuales que son utilizados por Kubernetes
  • Pod: es la unidad mínima de Kubernetes, realmente es un contenedor en jerga de Docker.
  • Labels y selectors: son pares de claves y valores, las cuales se pueden aplicar a pods, services, replication controllers, etc. y con ellos podremos identificarlos para poderlos gestionar.
  • Node: es el servidor ya sea virtual o físico que aloja el sistema de Kubernetes y donde vamos a desplegar nuestros pods (contenedores).
  • Replication Controller: es el responsable de gestionar la vida de los pods y el encargado de mantener iniciados los pods que se le hayan indicado en la configuración. Permite escalar de forma muy sencilla los sistemas y maneja la recreación de un pod cuando ocurre algún tipo de fallo.
  • Replica Sets: Es la nueva generación del Replication Controller, con nuevas funcionalidades. Una de las funcionalidades destacadas es que nos permite desplegar pods en función de los labels y selectors
  • Deployments: Es donde e especifican la cantidad de réplicas de pods que tendremos en el sistema. Es una funcionalidad más avanzada que los Replication Controller y muy parecida a los Replciation Sets, pero con otras características.
  • Namespaces: son agrupaciones, en ellos podremos diferenciar espacios de trabajo para diferentes situaciones. Por ejemplo podríamos realizar un Namespace para producción y otro para desarrollo y cada Namespace tendría sus propios pods, replication controllers, etc….
  • Volumes: Es el acceso a un sistema de almacenamiento
  • Secrets: Es donde se guarda la información confidencial como usuarios y passwords, para poder acceder a los recursos.
  • Service: Es la política de acceso a los pods. Lo podríamos definir como la abstracción que define un conjunto de pods y la lógica para poder acceder a ellos.

Que es kubernetes?

Basicamente vamos a comenzar por una corta definicion y vamos a quedarnos con el concepto de “orquestador de contenedores”

Definicion Kubernetes (referido en inglés comúnmente como “K8s”) es un sistema de código libre para la automatización del despliegue, ajuste de escala y manejo de aplicaciones en contenedores​ que fue originalmente diseñado por Google y donado a la Cloud Native Computing Foundation (parte de la Linux Foundation).

Un cluster de kubernetes esta formado por dos tipos de recursos:

  • Master es el encargado de manejar el cluster. Coordina todas las actividades en su clúster, como programar aplicaciones, mantener el estado deseado de las aplicaciones, escalar aplicaciones y desplegar nuevas actualizaciones.
  • Nodes es el servidor ya sea virtual o físico que aloja el sistema de Kubernetes y donde vamos a desplegar nuestros pods (contenedores). Cada nodo tiene un Kubelet, que es un agente para administrar el nodo y comunicarse con el maestro Kubernetes. El nodo también debe tener herramientas para manejar las operaciones de contenedores, como Docker o rkt. Un clúster de Kubernetes que maneje el tráfico de producción debe tener un mínimo de tres nodos.

Cuando implementan aplicaciones en Kubernetes, se le envia una orden al master que inicie los contenedores de aplicaciones. El master programa los contenedores para que se ejecuten en los nodos del clúster. Los nodos se comunican con el maestro utilizando la API de Kubernetes, que el master expone.

Diagrama k8s_Diagram

Ahora vamos a ver algunas herramientas que forman parte de kubernetes:

  • minikube para realizar pruebas se creó Minikube, el cual es una versión reducida de Kubernetes, corriendo en una única máquina virtual, la cual actúa de maestro y esclavos a la vez.

  • kubectl es necesario para poder comunicarse con el servidor Kubernetes.

Algunos comandos utiles con kubectl:

Si queremos ver la informacion del cluster: kubectl cluster-info

kubectl cluster-info
Kubernetes master is running at https://172.17.0.59:8443

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

Si queremos ver todos los nodos que forman parte del cluster: kubectl get nodes

$ kubectl get nodes
NAME       STATUS    ROLES     AGE       VERSION
minikube   Ready     <none>    14m       v1.10.0

Desplegando una aplicacion

Una vez que tenemos el cluster corriendo, podremos desplegar contenedores dentro del cluster, para ello debemos crear una configuracion de despliegue (Deployment Configuration). Cuando se ejecuta un deployment de configuracion, se le indica a kubernetes que debe crear y actualizar las instancias de nuestra aplicacion. Una vez que esta creado el despliegue, el master de kubernetes programa las instancias que deben correr en cada nodo miembro del cluster.

Una vez que la aplicacion ya esta creada y corriendo, Kubernetes Deployment Controller, monitorea continuamente estas instancias, si un nodo se cae o es borrado, el Deployment Controller enseguida lo remplaza.

k8s_App_Diagram

Podremos crear y administrar un despiegue (deployment) usando kubectl. Kubectl utiliza la API para interactuar con el cluster.

A continuacion vamos a desplegar una aplicacion de ejemplo sobre el cluster:

1- Desplegamos la aplicacion con el siguiente comando:

$ kubectl run kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1 --port=8080
deployment.apps/kubernetes-bootcamp created

La aplicacion se despliega ejecutando kubectl run, dicho comando crea una nueva implementacion. A dicho comando se le proporciona un nombre y la ubicacion de la imagen de la aplicacion (en este caso se le especifica la URL del repositorio de docker). Luego le pasamos el parametro --port: para especificarle el puerto al que queremos exponer nuestra aplicacion.

2- Con el siguiente comando, verificamos el correcto despliegue:

kubectl get deployments
NAME                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1         1         1            1           4m

3- Visualizando la appliaccion.

Los Pods (pensemos que el POD es un contenedor) corren dentro de Kubernetes y no estan expuestos al mundo. Estan aislados en una red privada. Por defecto son visibles desde otros Pods o servicios dentro del mismo cluster, pero no son accesibles desde fuera de la red. La manera de interactuar con estos Pods, es a traves de la herramienta kubectl, la cual interactua con la API de kubernetes.

Podemos establecer una conexion entre el host y el cluster de kubernetes a traves de un proxy. Para ello ejecutamos kubectl proxy. El proxy permite el acceso directo a la API desde estos terminales.

kubectl proxy
$
$ kubectl proxy
Starting to serve on 127.0.0.1:8001

Luego podremos ver todas las APIs alojadas a traves del proxy, ejecutando curl http://localhost:8001/version

curl http://localhost:8001/version
{
  "major": "1",
  "minor": "10",
  "gitVersion": "v1.10.0",
  "gitCommit": "fc32d2f3698e36b93322a3465f63a14e9f0eaead",
  "gitTreeState": "clean",
  "buildDate": "2018-04-10T12:46:31Z",
  "goVersion": "go1.9.4",
  "compiler": "gc",
  "platform": "linux/amd64"
}$

La API creará automáticamente una conexion para cada pod, según el nombre del pod, al que también se puede acceder a través del proxy.

Primero necesitamos saber el nombre del POD, dicho nombre esta alojado en la variable de entorno llamada POD_NAME:

$ export POD_NAME=$(kubectl get pods -o go-template --template '\n')
$ echo Name of the Pod: $POD_NAME
Name of the Pod: kubernetes-bootcamp-5c69669756-52r9w

Ahora vamos a probar la aplicacion que se esta ejecutando en este POD, realizando una solicitud HTTP:

curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5c69669756-52r9w | v=1

Pods y Nodos

Kubernetes Pods

Un POD es la instancia mínima que usará Kubernetes consistirá de al menos una imagen Docker, aunque pueden ser más. Suele usarse una sola por facilidad de control, por lo tanto, un pod puede ser desde una aplicación SpringBoot (sirviendo una REST API).

Los pods por definición son stateless, Kubernetes los desplegará y destruirá constantemente en función de las necesidades actuales. Si los pods deben persistir datos, deben apoyarse en volumes compartidos como por ejemplo NFS.

Cuando creamos una Deplyment en Kubernetes, esa deplyment crea Pods con contenedores dentro de ellos (en lugar de crear contenedores directamente). Cada Pod está vinculado al Nodo donde está programado y permanece allí hasta la terminación (según la política de reinicio) o la eliminación. En caso de una falla de Nodo, los Pods idénticos están programados en otros Nodos disponibles en el clúster.

k8s_Pods_Diagram

Nodos

Un Pod corre en un nodo. Un nodo es una maquina llamada worker que podria ser una maquina virtual o fisica. Cada nodo es administrado por el Master. Un nodo puede tener multiples pods, y el master maneja automaticamente la programacion de los nodos a traves del cluster. La programacion es automatica y tiene en cuenta los recursos disponibles en cada nodo.

Cada nodo de kubernetes ejecuta al menos:

  • kublet es el proceso responsable de la comunicacion entre el master y el nodo. Tambien gestiona los pods y los contenedores que se ejecutan en cada maquina.

  • container runtime (Doker, rkt), es el responsable del pull de las imagenes desde los repositorios (docker registry), tambien de desempaquetar el contenedor y correr la aplicacion.

k8s_node_Diagram

Comandos utiles para troubleshooting

  • kubectl get lista los recursos
  • kubectl describe da informacion detallada acerca de los recursos
  • kubectl logs imprime los logs de un contenedor en un pod
  • kubectl exec ejecuta un comando de un contenedor en un pod

A continuacion ejecutaremos los comandos mencionados anteriormente para ver como funcionan:

kubectl describe

$ kubectl describe pods
Name:           kubernetes-bootcamp-5c69669756-nz2gp
Namespace:      default
Node:           minikube/172.17.0.16
Start Time:     Thu, 03 Jan 2019 01:48:45 +0000
Labels:         pod-template-hash=1725225312
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.2
Controlled By:  ReplicaSet/kubernetes-bootcamp-5c69669756
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://f085623a9866cf52e740bb1414bdae6280d6912e7920715653be5607334ab72e
    Image:          gcr.io/google-samples/kubernetes-bootcamp:v1
    Image ID:       docker-pullable://gcr.io/google-samples/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 Jan 2019 01:48:46 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-gdhfp (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-gdhfp:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-gdhfp
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason                 Age                From               Message
  ----     ------                 ----               ----               -------
  Warning  FailedScheduling       52s (x4 over 55s)  default-scheduler  0/1 nodes are available: 1 node(s) were not ready.
  Normal   Scheduled              48s                default-scheduler  Successfully assigned kubernetes-bootcamp-5c69669756-nz2gp to minikube
  Normal   SuccessfulMountVolume  48s                kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-gdhfp"
  Normal   Pulled                 47s                kubelet, minikube  Container image"gcr.io/google-samples/kubernetes-bootcamp:v1" already present on machine
  Normal   Created                47s                kubelet, minikube  Created container
  Normal   Started                47s                kubelet, minikube  Started container

kubectl logs

$ export POD_NAME=$(kubectl get pods -o go-template --template '\n')
$ echo Name of the Pod: $POD_NAME
Name of the Pod: kubernetes-bootcamp-5c69669756-c5m9d
$ curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5c69669756-c5m9d | v=1
$
$
$ kubectl logs $POD_NAME
Kubernetes Bootcamp App Started At: 2019-01-03T01:51:35.933Z | Running On:  kubernetes-bootcamp-5c69669756-c5m9d

Running On: kubernetes-bootcamp-5c69669756-c5m9d | Total Requests: 1 | App Uptime: 37.56 seconds | Log Time: 2019-01-03T01:52:13.493Z

kubectl exec

 kubectl exec $POD_NAME env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=kubernetes-bootcamp-5c69669756-c5m9d
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
NPM_CONFIG_LOGLEVEL=info
NODE_VERSION=6.3.1
HOME=/root

 kubectl exec -ti $POD_NAME bash
root@kubernetes-bootcamp-5c69669756-c5m9d:/#

root@kubernetes-bootcamp-5c69669756-c5m9d:/# cat server.js
var http = require('http');
var requests=0;
var podname= process.env.HOSTNAME;
var startTime;
var host;
var handleRequest = function(request, response) {
  response.setHeader('Content-Type', 'text/plain');
  response.writeHead(200);
  response.write("Hello Kubernetes bootcamp! | Running on: ");
  response.write(host);
  response.end(" | v=1\n");
  console.log("Running On:" ,host, "| Total Requests:", ++requests,"| App Uptime:", (new Date() - startTime)/1000 , "seconds", "| Log Time:",new Date());
}
var www = http.createServer(handleRequest);
www.listen(8080,function () {
    startTime = new Date();;
    host = process.env.HOSTNAME;
    console.log ("Kubernetes Bootcamp App Started At:",startTime, "| Running On: " ,host, "\n" );
});

root@kubernetes-bootcamp-5c69669756-c5m9d:/# curl localhost:8080
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5c69669756-c5m9d | v=1

exit

Exponiendo la aplicacion

Los Pods de kubernetes son “mortales”, esto quiere decir que tienen un ciclo de vida. Cuando un nodo muere, todos los pods que corren en ese nodo se pierden. A continuacion el Replicaset (Nueva generacion de Replication Controller) crea dinamicamente nuevos pods para que la aplicacion siga corriendo.

Ejemplo: condiderando que tenemos una aplicacion con 3 repicas. Esas replicas son intercambiables, para el usuario final es transparente si cambian dichas replicas o incluso si muere un pod y el mismo es recreado.

Dicho esto, cada Pod en un clúster Kubernetes tiene una dirección IP única, incluso los Pods en el mismo Nodo, por lo que debe haber una forma de reconciliar automáticamente los cambios entre Pods para que las aplicaciones continúen funcionando.

Como habiamos dicho anteriormente. Un servicio en Kubernetes es una abstracción que define un conjunto lógico de Pods y una política mediante la cual acceder a ellos. Los servicios permiten un acoplamiento suelto entre Pods dependientes. Un servicio se define utilizando YAML (preferido) o JSON, como todos los objetos Kubernetes. El conjunto de Pods a los que apunta un Servicio suele estar determinado por un LabelSelector.

Aunque cada Pod tiene una dirección IP única, esas IP no están expuestas fuera del clúster sin un Servicio. Los servicios permiten que las aplicaciones reciban tráfico. Los servicios se pueden exponer de diferentes maneras especificando un tipo en la configuracion del ServiceSpec:

  • **CusterIP(default): Expone el servicio con una IP interna dentro del cluster. Esto hace que el servicio quede accesible desde dentro del cluster.

  • NodePort: Expone el servicio en el mismo puerto de cada Nodo seleccionado en el cluster usando NAT. Esto hace que un servicio sea accedible desde fuera del cluster usando <NodeIP>:<NodePort>

  • LoadBalancer: Crea un balanceador externo del cluster actual y asigna una ip externa fija al servicio.

  • ExternalName: Expone el servicio usando un nombre aleatorio (especificado en el atributo externalName) devolviendo un registro CNAME con el nombre. Esto requiere la version 1.7 de kube-dns o superior.

k8s_service_Diagram

El servicio rutea el trafico a traves del conjunto de Pods. Los servicios son una abstraccion que permite si un Pod muere se generen otras replicas en Kubernetes sin impactar en la aplicacion que esta corriendo.

El descubrimiento y enrutamiento entre los Pods dependientes (como los componentes de frontend y backend en una aplicación) son manejados por los Servicios de Kubernetes.

Un servicio coincide con una grupo de Pods que usan labels and selectors, es una agrupacion logia que permite a Kubernetes operar con estos objetos. Los labels son un par key/value que esta en cada objeto y se puede usar de varias maneras:

  • Designar objetos para ambientes (development, test y production).

  • Tags de version.

  • Clasificar los objetos.

k8s_tags_Diagram

A continuacion vamos a ver un ejemplo practico de lo que estuvimos hablando anteriormente:

1- Veremos los pods que estan corriendo con el siguiente comando:

kubectl get pods
NAME                                   READY     STATUS    RESTARTS   AGE
kubernetes-bootcamp-5c69669756-9qrl2   1/1       Running   0          1m

2- Listaremos los servicios que estan corriendo en el cluster:

$ kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   2m

Aqui tenemos un servicio llamado kubernetes que se crea cuando cuando minikube inicia el cluster. A conotinuacion vamos a crear otro servicio y exponerlo externamente, para exponerlo, en el comando le pasamos el parametro NodePort

3- Vamos a crear un nuevo servicio y exponerlo:

kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
service/kubernetes-bootcamp exposed

4- Verificamos que el servicio se haya creado:

kubectl get services
NAME                  TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes            ClusterIP   10.96.0.1        <none>        443/TCP          6m
kubernetes-bootcamp   NodePort    10.107.112.197   <none>        8080:30225/TCP   38s

Aqui tenemos el servicio llamado kubernetes-bootcamp. Vemos que el Servicio recibió una IP de clúster única, un puerto interno y una IP externa (la IP del Nodo).

5- Para ver qué puerto se abrió externamente (mediante la opción NodePort), ejecutaremos el comando describe service:

 kubectl describe services/kubernetes-bootcamp
Name:                     kubernetes-bootcamp
Namespace:                default
Labels:                   run=kubernetes-bootcamp
Annotations:              <none>
Selector:                 run=kubernetes-bootcamp
Type:                     NodePort
IP:                       10.107.112.197
Port:                     <unset>  8080/TCP
TargetPort:               8080/TCP
NodePort:                 <unset>  30225/TCP
Endpoints:                172.18.0.4:8080
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
$

6- Vamos a crear una variable de entorno llamada NODE_PORT que tenga el valor del puerto de nodo asignado:

$ export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='')
$ echo NODE_PORT=$NODE_PORT
NODE_PORT=30225

7- Ahora podemos probar que la aplicación está expuesta fuera del clúster utilizando curl, la IP del nodo y el puerto expuesto externamente:

$ curl $(minikube ip):$NODE_PORT
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5c69669756-9qrl2 | v=1

8- El deployment creó automáticamente una etiqueta para nuestro Pod. Con el comando describe deployment puede ver el nombre de la etiqueta:

 kubectl describe deployment
Name:                   kubernetes-bootcamp
Namespace:              default
CreationTimestamp:      Thu, 03 Jan 2019 13:26:31 +0000
Labels:                 run=kubernetes-bootcamp
Annotations:            deployment.kubernetes.io/revision=1
Selector:               run=kubernetes-bootcamp
Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  run=kubernetes-bootcamp
  Containers:
   kubernetes-bootcamp:
    Image:        gcr.io/google-samples/kubernetes-bootcamp:v1
    Port:         8080/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   kubernetes-bootcamp-5c69669756 (1/1 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  14m   deployment-controller  Scaled up replica set kubernetes-bootcamp-5c69669756 to 1

9- Usaremos el tag para consultar la lista de pods:

kubectl get pods -l run=kubernetes-bootcamp
NAME                                   READY     STATUS    RESTARTS   AGE
kubernetes-bootcamp-5c69669756-9qrl2   1/1       Running   0          18m

10- Podemos hacer lo mismo para listar los servicios existentes:

$ kubectl get services -l run=kubernetes-bootcamp
NAME                  TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes-bootcamp   NodePort   10.107.112.197   <none>        8080:30225/TCP   14m

11- Vamos a obtener el nombre del Pod y guardarlo en una variable llamada POD_Name:

 export POD_NAME=$(kubectl get pods -o go-template --template '\n')
$ echo Name of the Pod: $POD_NAME
Name of the Pod: kubernetes-bootcamp-5c69669756-9qrl2

12- Vamos a aplicar una nueva etiqueta, usamos el comando label seguido del tipo de objeto, el nombre del objeto y la nueva etiqueta:

$ kubectl label pod $POD_NAME app=v1
pod/kubernetes-bootcamp-5c69669756-9qrl2 labeled

13- Ejecutando el comando describe pods podremos ver con mas detalle la etiqueta que quedo en nuestro Pod:

$ kubectl describe pods $POD_NAME
Name:           kubernetes-bootcamp-5c69669756-9qrl2
Namespace:      default
Node:           minikube/172.17.0.115
Start Time:     Thu, 03 Jan 2019 13:26:38 +0000
Labels:         app=v1
                pod-template-hash=1725225312
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.4
Controlled By:  ReplicaSet/kubernetes-bootcamp-5c69669756
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://029f41eef268db44a5942fd4abe2f6736c760fd2356d903257de9a69cfcaf66b
    Image:          gcr.io/google-samples/kubernetes-bootcamp:v1
    Image ID:       docker-pullable://gcr.io/google-samples/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 Jan 2019 13:26:41 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-rhgf4 (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-rhgf4:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-rhgf4
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason                 Age                From               Message
  ----     ------                 ----               ----               -------
  Warning  FailedScheduling       25m (x4 over 25m)  default-scheduler  0/1 nodes are available: 1 node(s) were not ready.
  Normal   Scheduled              25m                default-scheduler  Successfully assigned kubernetes-bootcamp-5c69669756-9qrl2 to minikube
  Normal   SuccessfulMountVolume  25m                kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-rhgf4"
  Normal   Pulled                 25m                kubelet, minikube  Container image"gcr.io/google-samples/kubernetes-bootcamp:v1" already present on machine
  Normal   Created                25m                kubelet, minikube  Created container
  Normal   Started                25m                kubelet, minikube  Started container

14- Podremos consultar la lista de Pods, consultando a traves de la nueva etiqueta:

$ kubectl get pods -l app=v1
NAME                                   READY     STATUS    RESTARTS   AGE
kubernetes-bootcamp-5c69669756-9qrl2   1/1       Running   0          27m

15- Podremos borrar el servicio creado usando el comando delete service:

 kubectl delete service -l run=kubernetes-bootcamp
service "kubernetes-bootcamp" deleted

16- Vamos a confirmar que el servicio fue borrado:

$ kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   35m

17- Ahora vamos a comprobar que no quedo nada expuesto:

 curl $(minikube ip):$NODE_PORT
curl: (7) Failed to connect to 172.17.0.115 port 30225: Connection refused

18- Tambien vamos a comprobar que la app ya no esta expuesta y solo se ejecuta dentro del Pod:

$ kubectl exec -ti $POD_NAME curl localhost:8080
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5c69669756-9qrl2 | v=1

Corriendo multiples instancias

Escalando la aplicacion

Anteriormente hemos creado un Deployment, y fue expuesto a traves de un Service. En el Deployment solamente se ha creado un Pod en donde corria la aplicacion. Cuando el trafico se incrementa, necesitamos escalar la aplicacion para no afectar a los usuarios que consumen la misma.

k8s_scaling1_Diagram

k8s_scaling2_Diagram

El escalameinto del Deployment nos asegura que se crean nuevos Pods y se programan nuevos nodos para tener siempre recursos disponibles. El escalamiento aumentara el numero de pods al nuevo estado deseado. Kubernetes permite el autoescalado automatico de Pods. Tambien se puede el escalamiento “hacia abajo”, el cual termina los pods del Deployment.

Correr multiples instancias de una aplicacion va a requerir que todo el trafico sea distribuido. Los Services tienen integrado un load-balancer que se encarga de distribuir el trafico de red entre todos los pods que estan expuestos en el Deployment. El servicio realiza un monitoreo continuo de los enpoints de los Pods, para asegurarse que el trafico solo sea ditribuido a los pods que estan disponibles en el cluster.

Cuando se tienen multiples instancias corriendo, se pueden ejecutar Rolling Updates sin downtime.

A continuacion veremos de manera practica lo que hemos estado hablando:

1- Listaremos los deployments que se estan usando:

$ kubectl get deployments
NAME                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1         1         1            1           1m

Vamos a explicar la informacion que nos trae el comando:

  • Desired nos muestra el numero de replicas.
  • Current nos muestra cuantas replicas tenemos corriendo ahora.
  • Up-To-Date nos muestra el numero de replicas que estan actualizadas con respecto al estado deseado.
  • Available nos muestra el numero d replicas disponibles para los usuarios.

2- Vamos a escalar la cantidad de replicas a 4:

$ kubectl scale deployments/kubernetes-bootcamp --replicas=4
deployment.extensions/kubernetes-bootcamp scaled

3- Nuevamente listaremos los deployments para ver que se han la cantidad escalado las replicas:

 kubectl get deployments
NAME                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   4         4         4            4           7m

5- Vamos a chequear si el numero de Pods ha cambiado:

$ kubectl get pods -o wide
NAME                                   READY     STATUS    RESTARTS   AGE       IP     NODE
kubernetes-bootcamp-5c69669756-bkw2z   1/1       Running   0          1m        172.18.0.5   minikube
kubernetes-bootcamp-5c69669756-hkbj5   1/1       Running   0          1m        172.18.0.7   minikube
kubernetes-bootcamp-5c69669756-jmwwx   1/1       Running   0          8m        172.18.0.2   minikube
kubernetes-bootcamp-5c69669756-vswhc   1/1       Running   0          1m        172.18.0.6   minikube

Tenemos 4 Pods con diferentes IPs, el cambio fue resgistrado en el log del Deployment y podemos verlo ejecutando el comando describe .

$ kubectl describe deployments/kubernetes-bootcamp
Name:                   kubernetes-bootcamp
Namespace:              default
CreationTimestamp:      Thu, 03 Jan 2019 15:01:36 +0000
Labels:                 run=kubernetes-bootcamp
Annotations:            deployment.kubernetes.io/revision=1
Selector:               run=kubernetes-bootcamp
Replicas:               4 desired | 4 updated | 4 total | 4 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  run=kubernetes-bootcamp
  Containers:
   kubernetes-bootcamp:
    Image:        gcr.io/google-samples/kubernetes-bootcamp:v1
    Port:         8080/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Progressing    True    NewReplicaSetAvailable
  Available      True    MinimumReplicasAvailable
OldReplicaSets:  <none>
NewReplicaSet:   kubernetes-bootcamp-5c69669756 (4/4 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  10m   deployment-controller  Scaled up replica set kubernetes-bootcamp-5c69669756 to 1
  Normal  ScalingReplicaSet  3m    deployment-controller  Scaled up replica set kubernetes-bootcamp-5c69669756 to 4

6- Vamos a verificar el trafico, puertos expuestos del load-balancer:

$ kubectl describe services/kubernetes-bootcamp
Name:                     kubernetes-bootcamp
Namespace:                default
Labels:                   run=kubernetes-bootcamp
Annotations:              <none>
Selector:                 run=kubernetes-bootcamp
Type:                     NodePort
IP:                       10.109.163.196
Port:                     <unset>  8080/TCP
TargetPort:               8080/TCP
NodePort:                 <unset>  32215/TCP
Endpoints:                172.18.0.2:8080,172.18.0.5:8080,172.18.0.6:8080 + 1 more...
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

7- Vamos a crear una variable llamada NODE_PORT la cual va a quedar guardado el valor del puerto del nodo:

 export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='')
$ echo NODE_PORT=$NODE_PORT
NODE_PORT=32215

8- Ejecutaremos curl contra la ip y el puerto expuesto del balanceador (lo ejecutaremos varias veces para comprobar el que el balanceador esta funcionando correctamente):

$ curl $(minikube ip):$NODE_PORT
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5c69669756-bkw2z | v=1
$ curl $(minikube ip):$NODE_PORT
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5c69669756-jmwwx | v=1
$ curl $(minikube ip):$NODE_PORT
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5c69669756-bkw2z | v=1
$ curl $(minikube ip):$NODE_PORT
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5c69669756-vswhc | v=1

9- Ahora vamos a ejecutar el comando scale para bajar el numero de replicas a 2:

$ kubectl scale deployments/kubernetes-bootcamp --replicas=2
deployment.extensions/kubernetes-bootcamp scaled

10- Vamos a comprobar la cantidad de replicas que tenemos corriendo:

$ kubectl get deployments
NAME                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   2         2         2            2           20m

11- Ahora vamos a comprobar la cantidad de Pods que tenemos corriendo:

$ kubectl get pods -o wide
NAME                                   READY     STATUS    RESTARTS   AGE       IP     NODE
kubernetes-bootcamp-5c69669756-bkw2z   1/1       Running   0          14m       172.18.0.5   minikube
kubernetes-bootcamp-5c69669756-jmwwx   1/1       Running   0          21m       172.18.0.2   minikube

Como podemos ver hay dos Pods que fueron destruidos o terminados.

Rolling Updates

Ejecutando updates de la aplicacion

Como sabemos la aplicacion tiene que estar siempre disponible para los usuarios y los desarrolladores esperan que las aplicaciones estan siempre actualizadas.

Cuando se tienen multiples instancias corriendo, se pueden ejecutar Rolling Updates sin downtime. Rolling Updates permite desplegar la aplicacion actualizada sin downtime incrementando la cantidad de pods ya actualizados. Los nuevos pods son programados en Nodos con recursos disponibles.

k8s_update1_Diagram

k8s_update2_Diagram

k8s_update3_Diagram

k8s_update4_Diagram

Similar al esclado de una aplicacion, el deployment se expone publicamente, a traves del load-balance el trafico solo va hacia los pods que estan disponibles durante la actualizacion.

Durante un Rolling Update estan permitidas las siguientes acciones:

  • Promover una aplicación de un entorno a otro (a través de actualizaciones de imagen de contenedor)
  • Ejecutar un Rollback a versiones previas.
  • Ejecutar CI/CD sin perdida.

A continuacion vamos a ejecutar un update de la aplicacion que tenemos corriendo en nuestro cluster:

1- Primero vamos a listar los Deployments que tenemos:

kubectl get deployments
NAME                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   4         4         4            4           1m

2- Luego vamos a listar los Pods que tenemos corriendo:

$ kubectl get pods
NAME                                   READY     STATUS    RESTARTS   AGE
kubernetes-bootcamp-5c69669756-4lpxw   1/1       Running   0          2m
kubernetes-bootcamp-5c69669756-b666d   1/1       Running   0          2m
kubernetes-bootcamp-5c69669756-ffkhz   1/1       Running   0          2m
kubernetes-bootcamp-5c69669756-tgq47   1/1       Running   0          2m

3- Para ver la version de la imagen que esta corriendo en la app ejecutamos:

$ kubectl describe pods
Name:           kubernetes-bootcamp-5c69669756-4lpxw
Namespace:      default
Node:           minikube/172.17.0.59
Start Time:     Thu, 03 Jan 2019 16:10:01 +0000
Labels:         pod-template-hash=1725225312
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.4
Controlled By:  ReplicaSet/kubernetes-bootcamp-5c69669756
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://c0ed5956f375ad6bd7209041c6c3446d0723d803bd06ea39cb9c915a2a2be938
    Image:          gcr.io/google-samples/kubernetes-bootcamp:v1
    Image ID:       docker-pullable://gcr.io/google-samples/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 Jan 2019 16:10:03 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-dfmnt (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-dfmnt:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-dfmnt
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason                 Age              From               Message
  ----     ------                 ----             ----               -------
  Warning  FailedScheduling       4m (x3 over 4m)  default-scheduler  0/1 nodes are available: 1 node(s) were not ready.
  Normal   Scheduled              4m               default-scheduler  Successfully assigned kubernetes-bootcamp-5c69669756-4lpxw to minikube
  Normal   SuccessfulMountVolume  4m               kubelet, minikube  MountVolume.SetUpsucceeded for volume "default-token-dfmnt"
  Normal   Pulled                 4m               kubelet, minikube  Container image "gcr.io/google-samples/kubernetes-bootcamp:v1" already present on machine
  Normal   Created                4m               kubelet, minikube  Created container
  Normal   Started                4m               kubelet, minikube  Started container


Name:           kubernetes-bootcamp-5c69669756-b666d
Namespace:      default
Node:           minikube/172.17.0.59
Start Time:     Thu, 03 Jan 2019 16:10:00 +0000
Labels:         pod-template-hash=1725225312
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.3
Controlled By:  ReplicaSet/kubernetes-bootcamp-5c69669756
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://71c78b89fb470877da5643e6562026629835075b622a030e1d2f4de9bc547350
    Image:          gcr.io/google-samples/kubernetes-bootcamp:v1
    Image ID:       docker-pullable://gcr.io/google-samples/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 Jan 2019 16:10:03 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-dfmnt (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-dfmnt:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-dfmnt
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason                 Age              From               Message
  ----     ------                 ----             ----               -------
  Warning  FailedScheduling       4m (x3 over 4m)  default-scheduler  0/1 nodes are available: 1 node(s) were not ready.
  Normal   Scheduled              4m               default-scheduler  Successfully assigned kubernetes-bootcamp-5c69669756-b666d to minikube
  Normal   SuccessfulMountVolume  4m               kubelet, minikube  MountVolume.SetUpsucceeded for volume "default-token-dfmnt"
  Normal   Pulled                 4m               kubelet, minikube  Container image "gcr.io/google-samples/kubernetes-bootcamp:v1" already present on machine
  Normal   Created                4m               kubelet, minikube  Created container
  Normal   Started                4m               kubelet, minikube  Started container


Name:           kubernetes-bootcamp-5c69669756-ffkhz
Namespace:      default
Node:           minikube/172.17.0.59
Start Time:     Thu, 03 Jan 2019 16:09:59 +0000
Labels:         pod-template-hash=1725225312
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.2
Controlled By:  ReplicaSet/kubernetes-bootcamp-5c69669756
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://824b421f8ea23972e8b8478212608e54435e6a9d02b9482577a128594c4d2d1e
    Image:          gcr.io/google-samples/kubernetes-bootcamp:v1
    Image ID:       docker-pullable://gcr.io/google-samples/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 Jan 2019 16:10:00 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-dfmnt (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-dfmnt:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-dfmnt
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason                 Age              From               Message
  ----     ------                 ----             ----               -------
  Warning  FailedScheduling       4m (x2 over 4m)  default-scheduler  0/1 nodes are available: 1 node(s) were not ready.
  Normal   Scheduled              4m               default-scheduler  Successfully assigned kubernetes-bootcamp-5c69669756-ffkhz to minikube
  Normal   SuccessfulMountVolume  4m               kubelet, minikube  MountVolume.SetUpsucceeded for volume "default-token-dfmnt"
  Normal   Pulled                 4m               kubelet, minikube  Container image "gcr.io/google-samples/kubernetes-bootcamp:v1" already present on machine
  Normal   Created                4m               kubelet, minikube  Created container
  Normal   Started                4m               kubelet, minikube  Started container


Name:           kubernetes-bootcamp-5c69669756-tgq47
Namespace:      default
Node:           minikube/172.17.0.59
Start Time:     Thu, 03 Jan 2019 16:10:01 +0000
Labels:         pod-template-hash=1725225312
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.5
Controlled By:  ReplicaSet/kubernetes-bootcamp-5c69669756
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://0e17cb594de67650614e05151604f34ec12d8b78bb582512754557212f255a37
    Image:          gcr.io/google-samples/kubernetes-bootcamp:v1
    Image ID:       docker-pullable://gcr.io/google-samples/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 Jan 2019 16:10:03 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-dfmnt (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-dfmnt:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-dfmnt
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason                 Age              From               Message
  ----     ------                 ----             ----               -------
  Warning  FailedScheduling       4m (x3 over 4m)  default-scheduler  0/1 nodes are available: 1 node(s) were not ready.
  Normal   Scheduled              4m               default-scheduler  Successfully assigned kubernetes-bootcamp-5c69669756-tgq47 to minikube
  Normal   SuccessfulMountVolume  4m               kubelet, minikube  MountVolume.SetUpsucceeded for volume "default-token-dfmnt"
  Normal   Pulled                 4m               kubelet, minikube  Container image "gcr.io/google-samples/kubernetes-bootcamp:v1" already present on machine
  Normal   Created                4m               kubelet, minikube  Created container
  Normal   Started                4m               kubelet, minikube  Started container

4- Vamos a cambiar la version de la aplicacion a version 2, usando el comando set image:

$ kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2
deployment.extensions/kubernetes-bootcamp image updated

El comando que ejecutamos notifica al Deployment que use una imagen diferente para la app e inicie el rolling update.

5- Vamos a chequear el estatus de los nuevos pods y verificar que los pods con version anterior son terminados:

$ kubectl get pods
NAME                                   READY     STATUS    RESTARTS   AGE
kubernetes-bootcamp-7799cbcb86-bkdfg   1/1       Running   0          3m
kubernetes-bootcamp-7799cbcb86-jg2sm   1/1       Running   0          3m
kubernetes-bootcamp-7799cbcb86-mqmcm   1/1       Running   0          3m
kubernetes-bootcamp-7799cbcb86-zxcnb   1/1       Running   0          3m

6- Ahora vamos a verificar que la app esta corriendo y veremos en que ip/puerto esta expuesta:

 kubectl describe services/kubernetes-bootcamp
Name:                     kubernetes-bootcamp
Namespace:                default
Labels:                   run=kubernetes-bootcamp
Annotations:              <none>
Selector:                 run=kubernetes-bootcamp
Type:                     NodePort
IP:                       10.102.62.254
Port:                     <unset>  8080/TCP
TargetPort:               8080/TCP
NodePort:                 <unset>  32375/TCP
Endpoints:                172.18.0.10:8080,172.18.0.11:8080,172.18.0.8:8080 + 1 more...
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

7- Vamos a crear una variable de entorno llamada NODE_PORT que tenga el valor del puerto de nodo asignado:

$ export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='')
$ echo NODE_PORT=$NODE_PORT
NODE_PORT=32375

8- Vamos a conectarnos a la ip y puerto expuestas:

$ curl $(minikube ip):$NODE_PORT
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-7799cbcb86-jg2sm | v=2

Veremos que estamos ejecutando una solicitud a un nuevo pod ya con la version nueva de la app.

9- La actualización se puede confirmar también ejecutando el comando:

$ kubectl rollout status deployments/kubernetes-bootcamp
deployment "kubernetes-bootcamp" successfully rolled out

10- Ahora vamos a verificar que version estan ejecutando los pods:

$ kubectl describe pods
Name:           kubernetes-bootcamp-7799cbcb86-bkdfg
Namespace:      default
Node:           minikube/172.17.0.11
Start Time:     Thu, 03 Jan 2019 17:33:09 +0000
Labels:         pod-template-hash=3355767642
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.9
Controlled By:  ReplicaSet/kubernetes-bootcamp-7799cbcb86
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://b28af66de45c3738f8d480422cdcee6bdbb04952bb69c2218365f05cb74e3c25
    Image:          jocatalin/kubernetes-bootcamp:v2
    Image ID:       docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 Jan 2019 17:33:10 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-s62f4 (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-s62f4:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-s62f4
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  Scheduled              12m   default-scheduler  Successfully assigned kubernetes-bootcamp-7799cbcb86-bkdfg to minikube
  Normal  SuccessfulMountVolume  12m   kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-s62f4"
  Normal  Pulled                 12m   kubelet, minikube  Container image "jocatalin/kubernetes-bootcamp:v2" already present on machine
  Normal  Created                12m   kubelet, minikube  Created container
  Normal  Started                12m   kubelet, minikube  Started container


Name:           kubernetes-bootcamp-7799cbcb86-jg2sm
Namespace:      default
Node:           minikube/172.17.0.11
Start Time:     Thu, 03 Jan 2019 17:33:09 +0000
Labels:         pod-template-hash=3355767642
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.8
Controlled By:  ReplicaSet/kubernetes-bootcamp-7799cbcb86
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://67b1b3be63f43c37a16738aab9f0057546fcc7c4ded0f82e0313cf1d1688e905
    Image:          jocatalin/kubernetes-bootcamp:v2
    Image ID:       docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 Jan 2019 17:33:10 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-s62f4 (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-s62f4:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-s62f4
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  Scheduled              12m   default-scheduler  Successfully assigned kubernetes-bootcamp-7799cbcb86-jg2sm to minikube
  Normal  SuccessfulMountVolume  12m   kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-s62f4"
  Normal  Pulled                 12m   kubelet, minikube  Container image "jocatalin/kubernetes-bootcamp:v2" already present on machine
  Normal  Created                12m   kubelet, minikube  Created container
  Normal  Started                12m   kubelet, minikube  Started container


Name:           kubernetes-bootcamp-7799cbcb86-mqmcm
Namespace:      default
Node:           minikube/172.17.0.11
Start Time:     Thu, 03 Jan 2019 17:33:10 +0000
Labels:         pod-template-hash=3355767642
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.11
Controlled By:  ReplicaSet/kubernetes-bootcamp-7799cbcb86
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://ff45057c81beed58553fe76f106c5ce932e3856dfb1320da621e7fba0c624ef0
    Image:          jocatalin/kubernetes-bootcamp:v2
    Image ID:       docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 Jan 2019 17:33:12 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-s62f4 (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-s62f4:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-s62f4
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  Scheduled              12m   default-scheduler  Successfully assigned kubernetes-bootcamp-7799cbcb86-mqmcm to minikube
  Normal  SuccessfulMountVolume  12m   kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-s62f4"
  Normal  Pulled                 12m   kubelet, minikube  Container image "jocatalin/kubernetes-bootcamp:v2" already present on machine
  Normal  Created                12m   kubelet, minikube  Created container
  Normal  Started                12m   kubelet, minikube  Started container


Name:           kubernetes-bootcamp-7799cbcb86-zxcnb
Namespace:      default
Node:           minikube/172.17.0.11
Start Time:     Thu, 03 Jan 2019 17:33:10 +0000
Labels:         pod-template-hash=3355767642
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.10
Controlled By:  ReplicaSet/kubernetes-bootcamp-7799cbcb86
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://dd2ab77fe99aae43fc48958af209d91728035ed8e5938d69cb15a8b5bb37fa05
    Image:          jocatalin/kubernetes-bootcamp:v2
    Image ID:       docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 Jan 2019 17:33:11 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-s62f4 (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-s62f4:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-s62f4
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  Scheduled              12m   default-scheduler  Successfully assigned kubernetes-bootcamp-7799cbcb86-zxcnb to minikube
  Normal  SuccessfulMountVolume  12m   kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-s62f4"
  Normal  Pulled                 12m   kubelet, minikube  Container image "jocatalin/kubernetes-bootcamp:v2" already present on machine
  Normal  Created                12m   kubelet, minikube  Created container
  Normal  Started                12m   kubelet, minikube  Started container

Ahora vamos a hacer otra actuaizacion de la imagen y le vamos a poner el tag v10

11- Vamos a ejecutar el siguiente comando para desplegar la nueva imagen:

$ kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=gcr.io/google-samples/kubernetes-bootcamp:v10
deployment.extensions/kubernetes-bootcamp image updated

12- Vamos a ver el status del deployment:

$ kubectl get deployments
NAME                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   4         5         2            3           20m

Veremos que hay un detalle, no tenemos el numero deseado de Pods disponibles.

13- Vamos a verificar los pods que estan corriendo:

$ kubectl get pods
NAME                                   READY     STATUS             RESTARTS   AGE
kubernetes-bootcamp-5f76cd7b94-j9klm   0/1       ImagePullBackOff   0          2m
kubernetes-bootcamp-5f76cd7b94-rb2tn   0/1       ImagePullBackOff   0          2m
kubernetes-bootcamp-7799cbcb86-bkdfg   1/1       Running            0          17m
kubernetes-bootcamp-7799cbcb86-jg2sm   1/1       Running            0          17m
kubernetes-bootcamp-7799cbcb86-zxcnb   1/1       Running            0          17m

14- Si ejecutamos el comando describe vamos a obtener mas detalle:

$ kubectl describe pods
Name:           kubernetes-bootcamp-5f76cd7b94-j9klm
Namespace:      default
Node:           minikube/172.17.0.11
Start Time:     Thu, 03 Jan 2019 17:47:53 +0000
Labels:         pod-template-hash=1932783650
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Pending
IP:             172.18.0.3
Controlled By:  ReplicaSet/kubernetes-bootcamp-5f76cd7b94
Containers:
  kubernetes-bootcamp:
    Container ID:
    Image:          gcr.io/google-samples/kubernetes-bootcamp:v10
    Image ID:
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Waiting
      Reason:       ImagePullBackOff
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-s62f4 (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          False
  PodScheduled   True
Volumes:
  default-token-s62f4:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-s62f4
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason                 Age              From               Message
  ----     ------                 ----             ----               -------
  Normal   Scheduled              4m               default-scheduler  Successfully assigned kubernetes-bootcamp-5f76cd7b94-j9klm to minikube
  Normal   SuccessfulMountVolume  4m               kubelet, minikube  MountVolume.SetUpsucceeded for volume "default-token-s62f4"
  Normal   Pulling                2m (x4 over 4m)  kubelet, minikube  pulling image "gcr.io/google-samples/kubernetes-bootcamp:v10"
  Warning  Failed                 2m (x4 over 4m)  kubelet, minikube  Failed to pull image "gcr.io/google-samples/kubernetes-bootcamp:v10": rpc error: code = Unknown desc = unauthorized: authentication required
  Warning  Failed                 2m (x4 over 4m)  kubelet, minikube  Error: ErrImagePull
  Normal   BackOff                2m (x6 over 4m)  kubelet, minikube  Back-off pulling image "gcr.io/google-samples/kubernetes-bootcamp:v10"
  Warning  Failed                 2m (x6 over 4m)  kubelet, minikube  Error: ImagePullBackOff


Name:           kubernetes-bootcamp-5f76cd7b94-rb2tn
Namespace:      default
Node:           minikube/172.17.0.11
Start Time:     Thu, 03 Jan 2019 17:47:53 +0000
Labels:         pod-template-hash=1932783650
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Pending
IP:             172.18.0.2
Controlled By:  ReplicaSet/kubernetes-bootcamp-5f76cd7b94
Containers:
  kubernetes-bootcamp:
    Container ID:
    Image:          gcr.io/google-samples/kubernetes-bootcamp:v10
    Image ID:
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Waiting
      Reason:       ImagePullBackOff
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-s62f4 (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          False
  PodScheduled   True
Volumes:
  default-token-s62f4:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-s62f4
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason                 Age              From               Message
  ----     ------                 ----             ----               -------
  Normal   Scheduled              4m               default-scheduler  Successfully assigned kubernetes-bootcamp-5f76cd7b94-rb2tn to minikube
  Normal   SuccessfulMountVolume  4m               kubelet, minikube  MountVolume.SetUpsucceeded for volume "default-token-s62f4"
  Normal   Pulling                2m (x4 over 4m)  kubelet, minikube  pulling image "gcr.io/google-samples/kubernetes-bootcamp:v10"
  Warning  Failed                 2m (x4 over 4m)  kubelet, minikube  Failed to pull image "gcr.io/google-samples/kubernetes-bootcamp:v10": rpc error: code = Unknown desc = unauthorized: authentication required
  Warning  Failed                 2m (x4 over 4m)  kubelet, minikube  Error: ErrImagePull
  Normal   BackOff                2m (x6 over 4m)  kubelet, minikube  Back-off pulling image "gcr.io/google-samples/kubernetes-bootcamp:v10"
  Warning  Failed                 2m (x6 over 4m)  kubelet, minikube  Error: ImagePullBackOff


Name:           kubernetes-bootcamp-7799cbcb86-bkdfg
Namespace:      default
Node:           minikube/172.17.0.11
Start Time:     Thu, 03 Jan 2019 17:33:09 +0000
Labels:         pod-template-hash=3355767642
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.9
Controlled By:  ReplicaSet/kubernetes-bootcamp-7799cbcb86
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://b28af66de45c3738f8d480422cdcee6bdbb04952bb69c2218365f05cb74e3c25
    Image:          jocatalin/kubernetes-bootcamp:v2
    Image ID:       docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 Jan 2019 17:33:10 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-s62f4 (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-s62f4:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-s62f4
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  Scheduled              18m   default-scheduler  Successfully assigned kubernetes-bootcamp-7799cbcb86-bkdfg to minikube
  Normal  SuccessfulMountVolume  18m   kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-s62f4"
  Normal  Pulled                 18m   kubelet, minikube  Container image "jocatalin/kubernetes-bootcamp:v2" already present on machine
  Normal  Created                18m   kubelet, minikube  Created container
  Normal  Started                18m   kubelet, minikube  Started container


Name:           kubernetes-bootcamp-7799cbcb86-jg2sm
Namespace:      default
Node:           minikube/172.17.0.11
Start Time:     Thu, 03 Jan 2019 17:33:09 +0000
Labels:         pod-template-hash=3355767642
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.8
Controlled By:  ReplicaSet/kubernetes-bootcamp-7799cbcb86
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://67b1b3be63f43c37a16738aab9f0057546fcc7c4ded0f82e0313cf1d1688e905
    Image:          jocatalin/kubernetes-bootcamp:v2
    Image ID:       docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 Jan 2019 17:33:10 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-s62f4 (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-s62f4:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-s62f4
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  Scheduled              18m   default-scheduler  Successfully assigned kubernetes-bootcamp-7799cbcb86-jg2sm to minikube
  Normal  SuccessfulMountVolume  18m   kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-s62f4"
  Normal  Pulled                 18m   kubelet, minikube  Container image "jocatalin/kubernetes-bootcamp:v2" already present on machine
  Normal  Created                18m   kubelet, minikube  Created container
  Normal  Started                18m   kubelet, minikube  Started container


Name:           kubernetes-bootcamp-7799cbcb86-zxcnb
Namespace:      default
Node:           minikube/172.17.0.11
Start Time:     Thu, 03 Jan 2019 17:33:10 +0000
Labels:         pod-template-hash=3355767642
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.10
Controlled By:  ReplicaSet/kubernetes-bootcamp-7799cbcb86
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://dd2ab77fe99aae43fc48958af209d91728035ed8e5938d69cb15a8b5bb37fa05
    Image:          jocatalin/kubernetes-bootcamp:v2
    Image ID:       docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 Jan 2019 17:33:11 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-s62f4 (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-s62f4:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-s62f4
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  Scheduled              18m   default-scheduler  Successfully assigned kubernetes-bootcamp-7799cbcb86-zxcnb to minikube
  Normal  SuccessfulMountVolume  18m   kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-s62f4"
  Normal  Pulled                 18m   kubelet, minikube  Container image "jocatalin/kubernetes-bootcamp:v2" already present on machine
  Normal  Created                18m   kubelet, minikube  Created container
  Normal  Started                18m   kubelet, minikube  Started container

Veremos que no hay una imagen llamada v10 en el repositorio. Entonces vamos a hacer un rool back a una la version anetrior estable.

15- Vamos a ejecutar rollout para volver a una version estable:

$ kubectl rollout undo deployments/kubernetes-bootcamp
deployment.extensions/kubernetes-bootcamp

El comando revierte el deployment hacia una version anterior (v2 de la imagen). Todas las actualizaciones son versionadas y siempre podremos revertir a una version anetrior estable.

16- Vamos a comprobar el estado de los Pods:

$ kubectl get pods
NAME                                   READY     STATUS    RESTARTS   AGE
kubernetes-bootcamp-7799cbcb86-bkdfg   1/1       Running   0          26m
kubernetes-bootcamp-7799cbcb86-jg2sm   1/1       Running   0          26m
kubernetes-bootcamp-7799cbcb86-n6mpt   1/1       Running   0          2m
kubernetes-bootcamp-7799cbcb86-zxcnb   1/1       Running   0          26m

Ahora tenemos los 4 Pods corriendo y a continuacion vamos a verificar que imagen esta desplegada.

17- Vamos a verificar que imagen estan usando los Pods:

$ kubectl describe pods
Name:           kubernetes-bootcamp-7799cbcb86-bkdfg
Namespace:      default
Node:           minikube/172.17.0.11
Start Time:     Thu, 03 Jan 2019 17:33:09 +0000
Labels:         pod-template-hash=3355767642
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.9
Controlled By:  ReplicaSet/kubernetes-bootcamp-7799cbcb86
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://b28af66de45c3738f8d480422cdcee6bdbb04952bb69c2218365f05cb74e3c25
    Image:          jocatalin/kubernetes-bootcamp:v2
    Image ID:       docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 Jan 2019 17:33:10 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-s62f4 (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-s62f4:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-s62f4
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  Scheduled              27m   default-scheduler  Successfully assigned kubernetes-bootcamp-7799cbcb86-bkdfg to minikube
  Normal  SuccessfulMountVolume  27m   kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-s62f4"
  Normal  Pulled                 27m   kubelet, minikube  Container image "jocatalin/kubernetes-bootcamp:v2" already present on machine
  Normal  Created                27m   kubelet, minikube  Created container
  Normal  Started                27m   kubelet, minikube  Started container


Name:           kubernetes-bootcamp-7799cbcb86-jg2sm
Namespace:      default
Node:           minikube/172.17.0.11
Start Time:     Thu, 03 Jan 2019 17:33:09 +0000
Labels:         pod-template-hash=3355767642
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.8
Controlled By:  ReplicaSet/kubernetes-bootcamp-7799cbcb86
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://67b1b3be63f43c37a16738aab9f0057546fcc7c4ded0f82e0313cf1d1688e905
    Image:          jocatalin/kubernetes-bootcamp:v2
    Image ID:       docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 Jan 2019 17:33:10 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-s62f4 (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-s62f4:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-s62f4
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  Scheduled              27m   default-scheduler  Successfully assigned kubernetes-bootcamp-7799cbcb86-jg2sm to minikube
  Normal  SuccessfulMountVolume  27m   kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-s62f4"
  Normal  Pulled                 27m   kubelet, minikube  Container image "jocatalin/kubernetes-bootcamp:v2" already present on machine
  Normal  Created                27m   kubelet, minikube  Created container
  Normal  Started                27m   kubelet, minikube  Started container


Name:           kubernetes-bootcamp-7799cbcb86-n6mpt
Namespace:      default
Node:           minikube/172.17.0.11
Start Time:     Thu, 03 Jan 2019 17:57:35 +0000
Labels:         pod-template-hash=3355767642
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.4
Controlled By:  ReplicaSet/kubernetes-bootcamp-7799cbcb86
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://1d1767c6e109f26a154522c27727fd560f495aa7454ffe4af0d92f2fe8400303
    Image:          jocatalin/kubernetes-bootcamp:v2
    Image ID:       docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 Jan 2019 17:57:35 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-s62f4 (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-s62f4:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-s62f4
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  Scheduled              3m    default-scheduler  Successfully assigned kubernetes-bootcamp-7799cbcb86-n6mpt to minikube
  Normal  SuccessfulMountVolume  3m    kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-s62f4"
  Normal  Pulled                 3m    kubelet, minikube  Container image "jocatalin/kubernetes-bootcamp:v2" already present on machine
  Normal  Created                3m    kubelet, minikube  Created container
  Normal  Started                3m    kubelet, minikube  Started container


Name:           kubernetes-bootcamp-7799cbcb86-zxcnb
Namespace:      default
Node:           minikube/172.17.0.11
Start Time:     Thu, 03 Jan 2019 17:33:10 +0000
Labels:         pod-template-hash=3355767642
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.10
Controlled By:  ReplicaSet/kubernetes-bootcamp-7799cbcb86
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://dd2ab77fe99aae43fc48958af209d91728035ed8e5938d69cb15a8b5bb37fa05
    Image:          jocatalin/kubernetes-bootcamp:v2
    Image ID:       docker-pullable://jocatalin/kubernetes-bootcamp@sha256:fb1a3ced00cecfc1f83f18ab5cd14199e30adc1b49aa4244f5d65ad3f5feb2a5
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 Jan 2019 17:33:11 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-s62f4 (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-s62f4:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-s62f4
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  Scheduled              27m   default-scheduler  Successfully assigned kubernetes-bootcamp-7799cbcb86-zxcnb to minikube
  Normal  SuccessfulMountVolume  27m   kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-s62f4"
  Normal  Pulled                 27m   kubelet, minikube  Container image "jocatalin/kubernetes-bootcamp:v2" already present on machine
  Normal  Created                27m   kubelet, minikube  Created container
  Normal  Started                27m   kubelet, minikube  Started container

Final

Este articulo pretende ser un resumen del curso oficial de Kubernetes, espero que les sea de utilidad.

Kubernetes Documentacion Oficial