Kubernetes en premisa con MetalLB en modo BGP.

Kubernetes en premisa con MetalLB en modo BGP.

Una de las desventajas de tener un cluster de k8s en premisa es la falta de LoadBalancer. Gracias a MetalLB esto está resuelto de una manera fácil y elegante.

Cuando queremos publicar servicios en k8s, lo hacemos usando un Ingress Controller (nginx o Traefik por nombrar algunos). Este servicio se apoya de las direcciones IP de los hosts si no tenemos LoadBalancer. El tema se complica cuando queremos publicar servicios que no son HTTP o HTTPS, sé que nginx puede publicar otros protocolos. La ventaja de un IP via LoadBalancer es que podemos usarlos en varios servicios (pods) y publicar cualquier puerto en TCP o UDP.

MetalLB

Los requerimientos son los siguientes:

  • Un cluster de k8s en la versión 1.9.0 o más reciente y que no tenga un tipo de LoadBalancer en funcionamiento, esto quiere decir que tendríamos problemas usando esta solución en GKE por ejemplo.
  • Una configuración de cluster que pueda coexistir con MetalLB https://metallb.universe.tf/installation/network-addons/
  • Direcciones IPv4 para asignar usando este servicio.
  • Dependiendo del modo operativo, podríamos necesitar un router que soporte BGP.
  • https://metallb.universe.tf/#requirements

En mis primeras pruebas, MetalLB fue configurado usando Layer2 (capa 2), es la forma más rápida de probar esta solución, después de varios días de desplegar aplicaciones que hacían uso de LoadBalancer me di cuenta de que algunas direcciones IP de momento no respondían a las peticiones ARP que son necesarias para alcanzar dicha dirección IP. Por esta razón ahora desplegare MetalLB usando BGP.

En modo BGP, la configuración es más extensa y cuanta con campos que tendrán sentido si se ha usado BGP anteriormente.

En mi caso, ya tengo algo de experiencia usando este protocolo y por eso decidí cambiar de Layer2 a BGP en lugar de buscar una solución al problema descrito anteriormente. Además, mi router de core soporte BGP.

Configuración en Mikrotik RouterOS.

Debemos preparar el router (o en su defecto un Switch con L3 & BGP) para aceptar sesiones BGP desde los nodos de k8s, MetalLB ejecutara un agente en todos los nodos de k8s y estos iniciaran una sesión BGP con nuestro router.

Configuración básica en RouterOS – CLI:

/routing bgp instance
set default as=64635 redistribute-connected=yes redistribute-static=yes router-id=10.45.254.2
/routing bgp peer
add multihop=no name=kube1 remote-address=172.22.35.25 remote-as=64636 ttl=default
add multihop=no name=kube2 remote-address=172.22.35.26 remote-as=64636 ttl=default
add multihop=no name=kube3 remote-address=172.22.35.27 remote-as=64636 ttl=default

 

Instalando MetalLB.

kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/metallb.yaml

También se puede instalar usando Helm, para más información: https://metallb.universe.tf/installation/

Revisamos nuestro entorno k8s para validar que tenemos los componentes de MetalLB en un correcto estado.

¡Excelente! Tenemos tres speaker, uno en cada nodo.

Configurando MetalLB.

Necesitamos un kind tipo ConfigMap para aplicar la configuración deseada a MetalLB.


apiVersion: v1

kind: ConfigMap

metadata:

namespace: metallb-system

name: config

data: config: |

peers:

- peer-address: 172.22.35.1

peer-asn: 64635

my-asn: 64636

address-pools:

- name: default

protocol: bgp

addresses:

- 172.22.35.64/26

bgp-advertisements:

- aggregation-length: 32

localpref: 100

communities:

- name: public

protocol: bgp

addresses:

- 200.1.154.64/26

auto-assign: false

bgp-advertisements:

- aggregation-length: 32

localpref: 100

communities:

Aplicamos el configMap:

Si todos nuestros parámetros son correctos, revisamos en el core router y debemos tener las sesiones BGP establecidas.

¿Qué tenemos?

En este punto deberemos contar con la opción de seleccionar una dirección IP, en mi caso podría ser del pool llamado default o del pool llamado public, se puede diferenciar que las IP del pool llamado public son ruteables y existen en la tabla de Internet (200.1.154.0/24).

Vamos a inicializar un pod que haga uso de una dirección del pool default. Para esto usare un contenedor con un servicio de SMTP el cual no necesita almacenamiento.

Deployment + Service

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
app: smtp
name: smtp
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: smtp
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: smtp
spec:
containers:
- env:
- name: RELAY_NETWORKS
value: 172.22.35.0/24:10.45.0.0/16:200.1.154.0/24
image: namshi/smtp
imagePullPolicy: IfNotPresent
name: smtp
ports:
- containerPort: 25
name: smtp-port
---
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: smtp
name: smtp
annotations:
metallb.universe.tf/allow-shared-ip: ekvm
metallb.universe.tf/address-pool: default
spec:
externalTrafficPolicy: Local
ports:
- name: smtp
nodePort: 25
port: 25
protocol: TCP
targetport: smtp-port
selector:
app: smtp
loadBalancerIP: 172.22.35.70
type: LoadBalancer</pre>

¡Excelente!

¡Nuestro servicio de SMTP responde en el IP asignado por MetalLB!

El próximo paso es el almacenamiento.

Kubernetes – montándonos un entorno de pruebas y producción – homeLAB – Parte2

Kubernetes – montándonos un entorno de pruebas y producción – homeLAB – Parte2

Hace unos meses escribí como iniciaba un entorno k8s en casa para hacer pruebas y entender las ventajas de esta nueva plataforma que está revolucionando la forma en que manejamos contenedores.

En mi primer intento me auxilie de varios Raspberry Pi los cuales son excelentes para pequeños procesos y pruebas, lamentablemente en mi caso no me gustó mucho el resultado. En un segundo intento, use la distribución de Rancher junto a su plataforma de administración que permite provisionar un cluster ya sea en premisa o en la nube, en todos mis intentos lo hice en premisa ya que no cuento con un presupuesto para pagar horas en Amazon o Google.

En esta “segunda parte” he llegado mucho más lejos y con mejores resultados, digamos que ahora me he tomado más tiempo para entender cómo se conectan las partes y he decidido administrar k8s sin ningún front-end. Esta vez no he usado RPi, todo se ha instalado en Ubuntu 16.04 con la distribución de Rancher llamada RKE (Rancher Kubernetes Engine). https://github.com/rancher/rke

Rancher Kubernetes Engine, an extremely simple, lightning fast Kubernetes installer that works everywhere.

Esta es la descripción del Proyecto en Github, se puede decir que es una de las maneras más rápidas de tener un cluster de k8s, al menos que yo he probado hasta el momento.

BOM:

  • 3 Ubuntu Servers 16.04 – en mi caso, estos son tres máquinas virtuales.
  • 1 Management server – Otra VM con Ubuntu, no necesariamente debe ser la misma versión que los nodos del cluster.
  • Un rango de direcciones IP para MetalLB.

Instalando RKE:

Primero debemos revisar cumplimos con el Node Requriments. Rancher tiene una tabla con las recomendaciones de OS, hardware y Networking.

https://rancher.com/docs/rancher/v2.x/en/installation/requirements/

Luego procederemos a preparar el equipo que usaremos para levantar el cluster de RKE.

https://rancher.com/docs/rke/v0.1.x/en/installation/

En mi caso fue descargar el binario para Linux y colocarlo en mi PATH, crear un cluster configuration file, este archivo puede tener cualquier nombre, para simplificar los pasos le pondremos cluster.yml igual que la documentación de Rancher.

En este archivo [cluster.yml] colocaremos la información de los nodos que usaremos para formar el cluster, antes de poder lanzar este proceso debemos cumplir con algunos pasos.

  1. En la maquina usada para administración necesitamos contar con SSH keys, desplegar este key en los nodos del cluster, RKE no envía password para hacer login a estos nodos, por esta razón debemos tener ssh-passwordless.
  2. Docker ya instalado y el usuario que cuenta con los keys de SSH en el grupo de Docker.

La forma más rápida de cumplir con este paso es usando un script ya preparado para realizar esta tarea, este script es oficialmente soportado por Rancher.

https://rancher.com/docs/rke/v0.1.x/en/os/

curl https://releases.rancher.com/install-docker/17.03.sh | sh
  1. Tener las herramientas necesarias en la máquina de administración, una de ellas es kubelet. En el caso de Ubuntu se instala como cualquier otro paquete usando APT.

En la siguiente imagen se puede apreciar el mensaje final del script para instalar Docker versión 17.03.

Ya podemos continuar con la preparación del cluster.yaml. Yo he usado uno bastante sencillo:

Ejecutando RKE para inicializar el cluster.

rke up –config rancher-cluster.yml

Al finalizar este proceso, tendremos un mensaje como:

Para probar que nuestros nodos responden y que tenemos un cluster de k8s, copiamos el archivo resultante de la operación anterior [kube_config_rancher-cluster.yml] a la ubicación por defecto usada por kubectl.

cp kube_config_rancher-cluster.yml ~./kube/config

Una alternativa cargarlo en la variable KUBECONFIG:

export KUBECONFIG=$(pwd)/kube_config_rancher-cluster.yml

Hacemos un kubectl get nodes:

… Houston, we have a cluster.

Alguien preguntara: ¿Ya témenos un cluster, ahora que hacemos con él?

En el estado actual, se pueden desplegar aplicaciones que no hagan uso de almacenamiento persistente (no me gusta el hostPath) y que hagan uso del host IP ya que no tenemos un LoadBalacer instalado. Para el próximo articulo estaré desplegando dos soluciones para que nuestro cluster se parezca más a un GKE o un EKS.

Kubernetes – usando Rancher 2.0 para crear y administrar clusters de k8s!

Kubernetes – usando Rancher 2.0 para crear y administrar clusters de k8s!

Desde hace semanas estoy jugando con Kubernetes. La idea inicial ha sido armar un cluster usando herramientas nativas de k8s (kubeadm), de esta forma aprendería el funcionamiento base de la plataforma, lo gracioso es que pensé que lo estaba haciendo “de la manera difícil”, pero creo que no era así. Al parecer existe la manera “The hard way” la cual asusta por el simple hecho que todas las configuraciones e instalaciones son de manera manual, sin usar herramientas que autogeneran como es el caso de kubeadm. Al final, la razón de realizar la instalación de esta manera es con fin educativos, es recomendable conocer el porqué de las cosas.

Kubernetes the hard way.

https://github.com/kelseyhightower/kubernetes-the-hard-way

Con Kubernetes, aprender como funcionan los componentes se ha alargado más de la cuenta ya que el ecosistema es inmenso, y cada vez que pensé “Ya está instalado, ahora a desplegar algunos contenedores”, me topaba con que tenía que instalar otras herramientas antes de (¡nginx-ingress, te miro a ti!). otro factor fue que intente mezclar arquitecturas, quería tener adm64 y arm64.

Por ejemplo, cuando ya tenía el cluster creado, surgió la necesidad de acceder a las aplicaciones desde el exterior (¿Internet?), esto se resuelve muy fácil, Ingress Controller! Luego tenemos el tema del almacenamiento y así surgieron otras necesidades que cubrir para tener una solución que funcionara completamente.

Rancher 2.0

Ya había escuchado (leído…) de esta plataforma, al principio me había confundido y pensaba que era de pago también la había confundido con RancherOS, este es un Linux con lo necesario para correr contenedores, igual que CoreOS.

Rancher es una plataforma para la administración de cluster de Kubernetes, esto es así en la versión 2.0, está basada totalmente en Kubernetes.

Instalando Rancher.

La instalación de esta plataforma es tan sencilla como correr cualquier otro Docker container, leyendo en Quick Start Guide, podemos ver que se usa Docker run para inicializar el contenedor. En mi caso he agregado varios valores que no están en la guía de inicio.

docker run -d –restart=unless-stopped -p 80:80 -p 443:443 -v /var/lib/rancher:/var/lib/rancher rancher/rancher:latest –acme-domain rancher.aanetworks.org

-v /var/lib/rancher:/var/lib/rancher

Luego de varios días de usar Rancher, me toco reiniciar el contenedor y para mi sorpresa perdí todos los cambios que había hecho, todo muy básico, pero es poco alentador ver algo así. Resulta que toda la configuración generada por etcd es almacenada en /var/lib/rancher/ junto a otras informaciones de la plataforma.

–acme-domain rancher.aanetworks.org

Luego de la aparición de Let’s Encrypt, ¡porque no tener SSL en los dominios de acceso público o privados!

Con esta línea conseguimos que Rancher solicite un SSL para el dominio que usaremos con la plataforma, debemos tener los puertos 80 y 443 accesible desde Internet para que proceda la validación de dicho dominio.

Esperamos varios minutos (5?) y luego procedemos a acceder al portal de administración, en mi caso es https://rancher.aanetworks.org, lo primero que recibiremos es un mensaje solicitando un cambio de password para el usuario admin, luego de especificar el password, tendremos acceso a la plataforma.

Clusters!

La primera opción ofrecida por Rancher luego de hacer login es la creación de un cluster, a diferencia de la versión 1.x la cual no he usado, la versión 2.0 ofrece crear clusters de Kubernetes o importarlos si ya se tiene alguno.

Tenemos opción de crear Google Kubernetes Engine (GKE), Amazon EKS, Azure Container Service (AKS), hasta se puede conectar con Digital Ocean para provisionar VM allí y agregarlas a un cluster. Por el momento solo he podido jugar con la integración de vSphere y Custom. En caso de Custom, luego de crear el cluster, se nos entrega un comando docker run para ser ejecutado en los nodos que deseamos agregar, estos ya deben tener una versión de Linux soportada junto a docker en una de las versiones soportadas.

En esta captura se pueden ver las opciones ofrecidas por Rancher para la creación de un cluster tipo Custom.

En la versión 2.0 GA, se disponen de las versiones de Kubernetes listadas aqui para ser desplegadas a los nodos.

Como CNI (Container Network Interface) tenemos Flannel, Calico y Canal. Tengo entendido que Canal es una mezcla entre Flannel y Calico. Me gustaría que en lo adelante agregaran wave, aunque entiendo que necesito investigar más sobre Canal.

Pod Security, aún no he usado esta opción, entiendo que es un mecanismo para controlar el acceso a pods cuando están en namespace diferentes.

Rancher publica una lista de versiones de Docker soportadas, pero en la creación del cluster podemos elegir si deseamos que las versiones no soportadas puedan ser usadas.

Podemos ver en el mensaje, debemos ejecutar ese docker run en uno o más servidores que deseamos formen parte de este cluster.

Node Role, necesitamos al menos un etcd, un control y un worker para comenzar a jugar con este cluster, los siguientes equipos que agreguemos al cluter pueden tener el role de Worker.

Así es como se ve un cluster de Kubernetes desde el dashboard de Rancher.

Al hacer click “Launch kubectl”, tendremos esta linda ventana que nos permitirá hacer todo tipo de operaciones usando kubectl. Otra opción es descargar el archivo de configuración, colocarlo en una maquina con kubectl para poder interactuar con el cluster de Kubernetes. Debemos tener en cuenta que de esta manera todas las operaciones son atreves del servidor con Rancher.

Kubernetes – montándonos un entorno de pruebas – homeLAB!

Hace ya unas semanas estuve en vBrownBagLATAM mostrando lo fácil que es montarnos un LAB de Kubernetes, si buscamos en Internet podremos ver muchos posts de clusters usando Raspberry Pi. En mi caso intente usar LXD como base para las maquinas (contenedores) que tendrán Kubernetes, tanto el master como los nodos. Resulta que el host con Ubuntu/LXD usado para este proyecto no tiene bastante capacidad de CPU para correr varios contenedores y dentro de estos tener Kubernetes.

Así que termine con un cluster de tres Raspberry Pi y otro sin terminar basado en LXD.

En esta entrada se detalla como iniciar con tres Raspberry Pi + Hypriot + Kubernetes.

Ingredientes!

Hypriot tiene una guía en su propio portal donde describen la inicialización y configuración de un cluster de Kubernetes, es recomendable leer esa guía.

https://blog.hypriot.com/post/setup-kubernetes-raspberry-pi-cluster/

 

 

  1. Luego de introducir la imagen de Hypriot en el SD Card que usaremos en cada RPi, podremos hacer un:
  • Por defecto el RPi solicitara IP median DHCP, es recomendable cambiarlo a estático. Ha diferencia de una imagen Raspbian, la dirección IP puede ser configurada en /etc/network.

 

sudo apt update
sudo apt upgrade -y

 

  1. Lo interesante de Hypriot es que viene con Docker preinstalado, esto nos ahorra algunos minutos ya que no tenemos que hacer cambios como deshabilitar SWAP y editar la opción de cgroups. El siguiente paso es instalar Kubernetes:

 

sudo su -

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -

echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" > /etc/apt/sources.list.d/kubernetes.list

apt update

apt install -y kubeadm kubelet

 

  1. Ahora toca inicializar el master node:

 

kubeadm init --pod-network-cidr 10.244.0.0/16 --service-cidr 10.96.0.0/12 --service-dns-domain "k8s.do" --apiserver-advertise-address 44.164.67.227 --ignore-preflight-errors=all
  • Recibiremos un mensaje de confirmación relacionado a la creación del cluster, un dato importante es el $TOKEN que más adelante usaremos para asociar los nodos.
  • No es recomendable iniciar el cluster con –ignore-preflight-errors=all, esta opción se usaría como última alternativa si tenemos errores que no podemos evitar, tal como Swap en LXD.

 

  1. Usando el Usuario pirate prepararemos el ambiente para usar kubectl sin especificar config o credenciales ya que estas serán cargadas desde el ambiente de usuario.

 

mkdir -p $HOME/.kube

sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

sudo chown $(id -u):$(id -g) $HOME/.kube/config

echo "export KUBECONFIG=${HOME}/.kube/config" >> ~/.bashrcsource ~/.bashrc

 

  1. Veo que muchos usan flannel como su CNI, en este cluster instalare wave, en el basado en LXD probare nuevamente con flannel. De esta manera tendría ambos CNI para comparar funcionalidades, luego se podría preparar una lista con las diferencias.

 

$ kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"

 

  1. Para este momento ya contamos con un master, tenemos listo el CNI, podemos proceder a agregar nodos a nuestro cluster.
  • Validamos que el CNI fue desplegado haciendo un kubectl get nodes, si nuestro nodo master tiene el estado de Ready esto quiere decir que estamos listos para el próximo paso.

 

sudo kubeadm join --token=$TOKEN

 

  • $TOKEN es el valor que recibimos cuando iniciamos nuestro master.
  • Recibiremos un mensaje indicándonos que todo aconteció correctamente y que revisemos nuestro cluster.

 

  1. Verificamos que nuestro cluster cuenta con los nodos en los cuales ejecutamos kubeadm join.
kubectl get nodes
kubectl get pods –all-namespaces

 

 

  1. Validaremos que nuestro cluster puede ejecutar “Pods”.
  • En este ejemplo, utilizare la imagen oficial de nginx y será configurada para escuchar en el puerto 80 de todos los nodos.

 

$ kubectl run nginx --image=nginx --replicas=3 --port=80

deployment "nginx" created

 

  • exponemos los Pods de nginx.

 

$ kubectl expose deployment nginx --port 80service "nginx" exposed

 

  • validamos que el puerto 80 está escuchando en los IP de nuestros nodos.

 

$ kubectl get endpoints

NAME         ENDPOINTS                                   AGE

kubernetes   192.168.7.220:6443                          37

mnginx        10.244.4.2:80,10.244.4.3:80,10.244.3.2:80   23s

 

  1. Rápidamente usando la herramienta curl, podemos validar que nginx está respondiendo en el puerto especificado.
$ curl 10.244.4.2 | head -n 5

 

  • deberíamos recibir una respuesta como la siguiente:
<DOCTYPE html>

<html>

<head>

<title>Welcome to nginx!</title>

<style>

 

  • esto confirma que nuestro Pod está siendo ejecutado correctamente en el cluster de Kubernetes, aun faltarían muchos puntos por cubrir. Acceso desde fuera del cluster es importante ya que esta es la forma que nuestros usuarios/clientes consumirán servicios como nginx.

 

Hasta el momento solo hemos realizado configuraciones básicas en un entorno de Kubernetes y posiblemente algunos lleguen a la conclusión de que es mucho trabajo para simplemente tener un nginx o alguna otra aplicación la cual se puede levantar con Docker on LXC. Lo interesante de Kubernetes es la poca diferencia en administrar un cluster con 3 nodos a uno con 40 nodos.

En las próximas entradas escribiere como instalar y utilizar Helm, así también como instalar Istio para controlar el consumo de los servicios instalados en Kubernetes.

Kubernetes – el orquestrador!

Pido disculpas por el título, fue el primero que me llego a la cabeza.

 

Kubernetes.

Desde hace unos años esta plataforma ha estado disponible para ser usada de manera gratuita, por lo menos el nombre ha estado apareciendo en búsquedas relacionadas a Containers. La instalación de la misma, por lo que he podido investigar era algo complicada, luego aparecieron herramientas para facilitar esto y proveer un método fácil de seguir para montar esta plataforma y poder crear ambientes de prueba para luego poder desplegar en producción.

 

Minukbe:

https://github.com/kubernetes/minikube

Minikube is a tool that makes it easy to run Kubernetes locally. Minikube runs a single-node Kubernetes cluster inside a VM on your laptop for users looking to try out Kubernetes or develop with it day-to-day.”

Kubeadm:

https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/

kubeadm is a toolkit that helps you bootstrap a best-practice Kubernetes cluster in an easy, reasonably secure and extensible way. It also supports managing Bootstrap Tokens for you and upgrading/downgrading clusters.”

 

Kubernetes on Ubuntu: Conjure-UP

https://kubernetes.io/docs/getting-started-guides/ubuntu/

https://docs.conjure-up.io/2.4.0/en/walkthrough

There are multiple ways to run a Kubernetes cluster with Ubuntu. These pages explain how to deploy Kubernetes on Ubuntu on multiple public and private clouds, as well as bare metal.”

conjure-up provides the quickest way to deploy Kubernetes on Ubuntu for multiple clouds and bare metal. It provides a user-friendly UI that prompts you for cloud credentials and configuration options

 

 

He iniciado mis pruebas usando kubeadm, debido a que la mayoría de los “blog posts y how to” son para crear un cluster de k8s usando Raspberry Pi. En mi caso he iniciado usando LXD para correr el master y los worker estarían siendo ejecutados en RPi con Raspbian.

Luego de mirar un poco y leer sobre el concepto de k8s decidí probar con Conjure-up, con esta solución terminamos con un Cluster de Kubernetes listo para recibir despliegues de software ya que el “conjuro” usado crea todos los componentes necesarios. El siguiente en mi lista es Minukube.

Mi objetivo final es tener una infraestructura de k8s la cual pueda usar no solo para aprender de que trata todo esto, si no también, ejecutar tareas las cuales serán partes de mi homelab.

Más adelante publicare un post donde explico paso a paso como montarnos un cluster de Kubernetes usando Ubuntu + LXD, de esta manera podremos tener todo ejecutando en una misma máquina, este es el mismo objetivo que se consigue con Conjure-up pero con la ventaja que se hace todo paso a paso y así entendemos mejor el proceso de inicialización de un cluster.