Instalación del cliente kubectl en Ubuntu y conectarnos a un Cluster de Kubernetes

Para evitar errores en las validaciones de las API que utiliza kubernetes es necesario instalar la misma versión de kubectl que la versión de kubernetes que corre en nuestro Cluster.

Para este ejemplo vamos a utilizar un cluster basado en minikube. Como todos sabemos minikube es un cluster formado por una sola máquina y que podemos utilizar cuando queremos formarnos y comprender como kubernetes funciona.

Este artículo no pretende dar los pasos necesario para conectarnos a un cluster de producción si no identificar los recursos que intervienen entre un cliente kubectl y un Cluster de kubernetes. Como en casi todos estos sistemas todo esta basado en una autenticación basada en certificados.

Instalación en un sistema linux

$ curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.7.0/bin/linux/amd64/kubectl
$ chmod +x ./kubectl
$ sudo mv ./kubectl /usr/local/bin/kubectl

Configurar el acceso al Cluster

La configuración de acceso a un Cluster se encuentra normalmente en

~/.kube/config

En el caso que nos ocupa estamos utilizando minikube en un sistema Windows y lo que queremos es poder conectarnos desde una maquina virtual Ubuntu al cluster de minikube. Copiamos la configuración de nuestro sistema en nuestro Ubuntu.

Lo normal no es hacerlo así, si no que nos proporcionen un certificado cliente para nosotros y así autenticarnos con el cluster, o bien generar nosotros una petición de firma de certificado y que la CA nos la firme.

La configuración en nuestro sistema Windows es la siguiente:

$ cat ~/.kube/config
apiVersion: v1
clusters:
- cluster:
    certificate-authority: C:\Software\minikube\.minikube\ca.crt
    server: https://192.168.99.100:8443
  name: minikube
contexts:
- context:
    cluster: minikube
    user: minikube
  name: minikube
current-context: minikube
kind: Config
preferences: {}
users:
- name: minikube
  user:
    client-certificate: C:\Software\minikube\.minikube\apiserver.crt
    client-key: C:\Software\minikube\.minikube\apiserver.key

$ kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority: C:\Software\minikube\.minikube\ca.crt
    server: https://192.168.99.100:8443
  name: minikube
contexts:
- context:
    cluster: minikube
    user: minikube
  name: minikube
current-context: minikube
kind: Config
preferences: {}
users:
- name: minikube
  user:
    client-certificate: C:\Software\minikube\.minikube\apiserver.crt
    client-key: C:\Software\minikube\.minikube\apiserver.key

Copiamos dicha configuración en Ubuntu en
~/.kube/config
y modificamos la ruta de los certificados. Como vemos tenemos

  • el certificado de la CA

y

  • clave privada de cliente y el certificado de cliente

que nuestro administrador de kubernetes nos ha generado para nosotros.

Nuestra configuración en Ubuntu quedaría:

$ find /var/minikube/
/var/minikube/
/var/minikube/.minikube
/var/minikube/.minikube/ca.crt
/var/minikube/.minikube/apiserver.key
/var/minikube/.minikube/apiserver.crt

$ cat ~/.kube/config
apiVersion: v1
clusters:
- cluster:
    certificate-authority: /var/minikube/.minikube/ca.crt
    server: https://192.168.99.100:8443
  name: minikube
contexts:
- context:
    cluster: minikube
    user: minikube
  name: minikube
current-context: minikube
kind: Config
preferences: {}
users:
- name: minikube
  user:
    client-certificate: /var/minikube/.minikube/apiserver.crt
    client-key: /var/minikube/.minikube/apiserver.key

Validamos la configuración

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"7", GitVersion:"v1.7.0", GitCommit:"d3ada0119e776222f11ec7945e6d860061339aad", GitTreeState:"clean", BuildDate:"2017-06-29T23:15:59Z", GoVersion:"go1.8.3", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"7", GitVersion:"v1.7.0", GitCommit:"d3ada0119e776222f11ec7945e6d860061339aad", GitTreeState:"clean", BuildDate:"2017-07-26T00:12:31Z", GoVersion:"go1.8.3", Compiler:"gc", Platform:"linux/amd64"}

$ kubectl get all
NAME                                   READY     STATUS    RESTARTS   AGE
po/frontend-3872149310-0qz3m           1/1       Running   4          1d
po/hello-1243552595-bv62v              1/1       Running   2          1d
po/hello-1243552595-h9fdd              1/1       Running   2          1d
po/hello-1243552595-jmwp2              1/1       Running   2          1d
po/hello-1243552595-k3q4d              1/1       Running   2          1d
po/hello-1243552595-w4sw1              1/1       Running   2          1d
po/hello-1243552595-xb96t              1/1       Running   2          1d
po/hello-1243552595-xvw2q              1/1       Running   2          1d
po/hello-minikube-180744149-b7g45      1/1       Running   5          48d
po/nginx-deployment-2078889897-mcdz4   1/1       Running   3          2d
po/nginx-deployment-2078889897-qc4dk   1/1       Running   3          2d
po/nginx-deployment-2078889897-xnzzh   1/1       Running   3          2d

NAME                 CLUSTER-IP   EXTERNAL-IP   PORT(S)          AGE
svc/frontend         10.0.0.30         80:31303/TCP     1d
svc/hello            10.0.0.6             80/TCP           1d
svc/hello-minikube   10.0.0.201        8080:31033/TCP   48d
svc/kubernetes       10.0.0.1             443/TCP          49d

NAME                      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/frontend           1         1         1            1           1d
deploy/hello              7         7         7            7           1d
deploy/hello-minikube     1         1         1            1           48d
deploy/nginx-deployment   3         3         3            3           2d

NAME                             DESIRED   CURRENT   READY     AGE
rs/frontend-3872149310           1         1         1         1d
rs/hello-1243552595              7         7         7         1d
rs/hello-minikube-180744149      1         1         1         48d
rs/nginx-deployment-2078889897   3         3         3         2d
rs/nginx-deployment-2558903419   0         0         0         2d
rs/nginx-deployment-3896099094   0         0         0         2d

Configurar el acceso a más de un cluster

Desde nuestr cliente kubectl podemos conectarnos a más de un cluster. Solo tenemos que modificar el fichero de configuración añadiendo la nueva entrada. Si nos fijamos tenemos varias secciones para indicar la configuración de mas de un cluster y el mecanismo de autenticación para cada uno de ellos.

Estas secciones son <strong>clusters</strong>, <strong>context</strong> y <strong>users</strong>.

Para cambiarnos y apuntar a otro cluster diferente de donde nos encontremos es bastante sencillo. Solo tenemos que apuntar al contexto que queremos.

En este caso solo tenemos 1 contexto, es decir 1 configuración a cluster. El comando sería:

$ kubectl config use-context minikube
Switched to context "minikube"
Anuncios

Kubernetes – Vídeos resumen de la arquitectura detrás Kubernetes

Vídeos de diferentes canales donde resumen de forma muy esquemática y clara la arquitectura detrás de Kubernetes.

Son vídeos extraídos de los canales siguientes:

Kubernetes in 5 minutes
kubernete 101. Master
Kubernetes 101. Nodes
Kubernetes. Master and Scheduler
Kubernetes. Understanding Resources via YAML, Deployments, Replica Sets and Pods
Kubernetes: Cluster Integration: Services: Getting in and out of the cluster
Kubernetes: DNS and Name discovery
Networking with Kubernetes

Git Cookbook. Cambiar en nuestro repositorio local la rama del repositorio remoto que seguimos

Git

Para la elaboración de este artículo se ha utilizado la versión de git 2.7.4

Esta situación nos la encontramos cuando trabajamos con multiples repositorios remotos en nuestro repositorio local y en un momento determinado queremos dejar de seguir a la rama del repositorio remoto por defecto origin por otra rama de otro repositorio remoto diferente.

Para verlo con más claridad vamos a verlo con una secuencia de comandos.

Estado local de nuestro repositorio

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean

Listado de los repositorios remotos

$ git remote -v
gitlab  ssh://... (fetch)
gitlab  ssh://... (push)
origin  ssh://... (fetch)
origin  ssh://... (push)

Cambiar el repositorio remoto por defecto al que seguimos

La opción -u es la misma que –set-upstream-to.

$ git branch -u gitlab/master
Branch master set up to track remote branch master from gitlab.

$ git status
On branch master
Your branch is up-to-date with 'gitlab/master'.
nothing to commit, working directory clean

A partir de este momento cada vez que hagamos cualquier operación con git donde interviene el repositorio, si no le indicamos nada, el repositorio por defecto donde se hace las operaciones es gitlab

Por ejemplo, cambiamos un fichero y hacemos un git push. Por defecto se va al repositorio remoto gitlab. Si no cambiamos el repositorio remoto por defecto al que seguimos, para enviar los cambios a origin tendriamos que hacer un git push origin master.

Vamos a seguir con la secuencia de comandos.

$ echo "Readme.md" > README.md
$ git add .
$ git commit -m "fichero readme"

# diferencia entre repositorio local y el remoto origin
#
$ git diff origin/master --name-only
README.md

# diferencia entre repositorio local y el remoto gitlab
#
$ git diff gitlab/master --name-only
README.md

# realizamos un push sin indicar el repositorio remoto. Los cambios van por defecto al repositorio *gitlab*
#
$ git push
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 299 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To ssh://...
   2c0999b..61dbe03  master -> master

# diferencia entre repositorio local y el remoto gitlab. En este caso no hay ninguna diferencia
#  
$ git diff gitlab/master --name-only

# diferencia entre repositorio local y el remoto origin. En este caso sigue existiendo el fichero modificado
#
$ git diff origin/master --name-only
README.md

# Subir los cambios al *origin* sin modificar el repositorio remoto que seguimos
#
$ git push origin master
Password authentication
Password:
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 299 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1)
remote: Updating references: 100% (1/1)
To ssh://...
   2c0999b..61dbe03  master -> master

# Ya no existe diferencia entre repositorio local y el remoto origin.
#
$ git diff origin/master --name-only

Creación de un cluster con docker swarm

Docker Logo

El artículo se ha escrito utilizando docker 1.12 y 4 máquinas ubuntu 16.04.1 LTS virtualizadas con VirtualBox, de las cuales solo 1 de ellas tenia instalado docker-machine.

Este artículo es una guia rápida de creación de un cluster de nodos de docker, gestionados de forma nativa por docker swarm.

Algunos de los conceptos manejados por docker swarm son:

  • nodos. Diferentes equipos ejecutando docker
  • manager. Uno de los nodos del cluster actúan de manager y es el responsable de gestionar los nodos del cluster.
  • worker. El resto de nodos son los workers. Estos con los responsables de ejecutar las tareas que el manager le indica, creando y ejecutando los contenedores. El manager también puede actuar como worker.

Cuando desplegamos una aplicación en un cluster de docker swarm, creamos una definición de un servicio. Esta definición del servicio la enviamos al manager. El manager divide el servicio en tareas o tasks y las envia a los workers, que son los que finalmente ejecutan las tareas. Estas tareas o tasks se traducen en la creación de los contenedores que son los que finalmente ejecutan nuestra aplicación.

Sigue leyendo

Aprovisionar o instalar docker en una máquina remota utilizando docker-machine

Docker Logo

Para la elaboración del artículo hemos utilizado docker 1.12 y dos equipos ubuntu 16.04.1 LTS virtualizados con Virtualbox

Guía rápida de aprovisionamiento de una máquina remota utilizando docker-machine y el driver genérico. Se trata por tanto de instalar de docker forma remota desde un equipo local.

Para el artículo vamos a suponer que

  • la máquina remota se llama remotehost
  • la cuenta del usuario del equipo remoto es udocker
  • la maquina local donde ejecutamos docker-machine es sourcehost

Sigue leyendo

Realizar un login remoto o ssh utilizando autenticación por certificado RSA

ssh

… o lo que es lo mismo realizar un login remoto o ssh sin utilizar usuario y contraeña.

Es el caso en el que queremos realizar un login remoto o login por ssh desde un equipo A a un equipo B (o a ‘n’ equipos) y no queremos utilizar el usuario y contraseña cada vez que realizamos el login.

Los pasos son los siguientes:

  • Relizar el login en el equipo A
  • Generar la clave rsa para autenticación
  • Copiar la clave rsa generada en el equipo B
  • Realizar el login en el equipo B utilizando la clave recién generada

Como podemos imaginarnos necesitamos tener cuentas en ambos equipos para poder realizar estos pasos

Generar las claves para autenticación desde el equipo A

El comando ssh-keygen genera las claves de autenticación que podemos utilizar para el protocolo ssh de versiones 1 y 2. En este caso dejamos en blanco la passphrase.

La cuenta de usuario en este equipo se corresponde con user1.

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user1/.ssh/id_rsa):
/home/user1/.ssh/id_rsa already exists.
Overwrite (y/n)? y
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user1/.ssh/id_rsa.
Your public key has been saved in /home/user1/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:a3xg5xjLeq8t7qYVwcaa/m4wK/K+zn/ugE5GTxW8WHE user1@equipoa
The key's randomart image is:
+---[RSA 2048]----+
...
...
+----[SHA256]-----+

Copiar la clave recién generada en el equipo B desde la cuenta de usuario del equipo A

La cuenta de usuario en el equipo B se corresponde con user2.

$ ssh-copy-id user2@equipob
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/user1/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
user2@equipob's password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'user2@equipob'"
and check to make sure that only the key(s) you wanted were added.

Realizar el login ssh desde el equipo A en el equipo remoto B utilizando la clave recién copiada

$ ssh user2@equipob
Welcome to Ubuntu 16.04.1 LTS (GNU/Linux 4.4.0-31-generic x86_64)

A partir de ahora cada vez que realicemos el login en el equipo B no necesitaremos realizar el login ssh con la contraseña.

Spring Boot y el sistema de logging

Logo Spring

Resumen del funcionamiento del sistema de logging en Spring Boot 1.4.0.RELEASE

Principales características

  • Spring Boot utiliza internamente Commons Logging
  • Existe configuraciones para Java Util Logging, Log4J2 y Logback
  • Por defecto se utiliza la Consola para mostrar los logs. Opcionalmente podemos escribir en fichero
  • Logback es el sistema de log utilizado si utilizamos los Spring Boot Starters (spring-boot-starter-parent, etc)
  • Logback tiene niveles ERROR, WARN, INFO, DEBUG o TRACE pero no tiene FATAL
  • Se permite extender el comportamiento de logback mediante extensiones
  • Por defecto se muestran los niveles ERROR, WARN e INFO

Activación del nivel DEBUG

Como cualquier aplicación de Spring Boot podemos activar el nivel de DEBUG como cualquier configuración más. Eso significa que podemos indicarselo como argumento al arrancar la aplicación, como variable de entorno, en el application.properties o application.yml, etc

Es importante mencionar que la activacion del nivel de DEBUG solo afecta internamente a Spring Boot, no a los logs de nuestra aplicación, los cuales los tenemos que configurar mediante otro mecanismo.

Por ejemplo,

En el arranque de la aplicación

$ java -jar my-application.jar --debug

En el fichero application.properties o application.yml

...
debug=true
...
debug: true

Escribir logs a fichero

Por defecto Spring Boot escribe por consola pero opcionalmente le podemos decir que escriba a fichero.

Al igual que la activación del nivel a DEBUG la configuración para activar el fichero de log sigue el mismo principo de configuración de Spring Boot.

Los ficheros rotan por defecto cada 10Mb.

Las propiedades para indicar el fichero donde escribir los logs son:

  • logging.file
  • logging.path

Modificar los niveles de logs de nuestra aplicación o de librerías de terceros

Siguiendo los mismos principios de configuración de Spring Boot la modificación de los nieves de log de nuestra aplicación o de librerías de terceros es bastante fácil.

Por ejemplo,

En el arranque de la aplicación

java -jar my-application.jar --logging.level.org.myapp=DEBUG

En el fichero de configuración application.properties o application.yml

logging.level.org.myapp=DEBUG
...
logging:
   level:
     org:
       myapp: DEBUG

Activar otros sistemas de log

Se acivan por defecto al incluirlos en el classpath.

Podemos forzar a Spring Boot a utilzar un sistema de logging diferente al por defecto, configurando la propiedad de sistema:

org.springframework.boot.logging.LoggingSystem=Nombre completo de la clase que implementa el sistema de logging

o bien desactivar por completo el sistema de logging

org.springframework.boot.logging.LoggingSystem=none

Configuración de estos sistemas de logging

Una vez hemos cambiado el sistema de logging, Spring Boot se encargaría de leer lo ficheros de configuración de esos sistemas, aunque se recomienda que se utilicen la versión para Spring Boot.

Es decir, para los sistemas de logging como

  • log4j2 el fichero de configuración es log4j2.xml
  • Para Java Util Logging el fichero de configuración es logging.properties

pero Spring boot recomienda que utilicemos la versión para Spring Boot que serían respectivamente:

  • log4j2-spring.xml
  • logging-spring.properties