Categoría: Ubuntu

  • VRF en Linux con BIRD para OSPF/BGP

    VRF en Linux con BIRD para OSPF/BGP.

    Desde hace mucho tiempo estoy jugando con BGP, inicialmente tenía BGP en pfSense, algo sencillo y con solo algunas rutas, eso fue en los tiempos de dn42.

    En el 2016 encontré una comunidad de varios entusiastas de redes al nivel de Internet y pude conseguir un ASN registrado en RIPE.

    Muchas cosas han cambiado desde esos días, he aprendido y experimentado, aprender es la razón de ser de aaNetworks. Lo complicado de mi red con direcciones IP Publicas y ASN es que localmente en mi casa no hay forma posible de tener una sesión BGP y publicar los prefijos desde ahí (imagínate que CLARO te permita hacer un túnel L2TP a un router con BGP!), dependo de VPS con Linux y BIRD.

    (más…)

  • Homelab – no es solo hardware.

    Homelab – no es solo hardware.

    Hace unos días decidí actualizar la pagina donde trato de llevar un listado del hardware que compone mi homelab. Desde hace un tiempo muchas personas han querido introducirse en esta practica, muchos lo logran, otros no, desde mi punto de vista el tema es mas que solo tener hardware, es tener una meta y cumplirla haciendo uso de un sofware en ese hardware.

    https://arielantigua.com/weblog/home-lab/

    Luego de la introducción un poco desconectada, aquí les presento el sofware que uso en casa para mantenerme actualizado.

    Virtualización:

    Siempre seré un fiel seguidor de las soluciones de visualización, aunque a simple viste se podría decir que solo uso la solución de VMware para esto, déjenme decirles (escribirles) que no es así, he usado varias soluciones y antes de conocer VMware, era fanático de Xen (hasta que lo adquirió Citrix…).

    (más…)

  • Kubernetes – Almacenamiento con Rancher Longhorn, Parte2.

    Kubernetes – Almacenamiento con Rancher Longhorn, Parte2.

    Announcing Longhorn: an open source project for microservices-based distributed block storage

    En esta edición de mis aventuras con #k8s, acabo de instalar una implementación de almacenamiento desarrollada por Rancher. Desde mi punto de vista es parte2 porque fue la primera solución de almacenamiento distribuido que utilice hace meses, pero tenía varios temas, por ejemplo, cuando un pod era eliminado y este tenía un pvc montado, muchas veces no eran eliminados junto con su pod/deployment, otras veces si el pod/deployment era relanzado, el pvc tardaba minutos en montarse al pod.

    Hace unos meses lanzaron nueva versión y tiene bastantes mejoras, además he tenido experiencias con Linstor que en mi pequeño ambiente son algo incomodas, actualmente tengo un controller de Linstor, si esta falla, falla la creación de volúmenes y por consecuente la creación de pods.

    Instalar Longhorn es increíblemente fácil, con tan solo ejecutar kubectl -f url/de/yaml tendremos en marcha nuestro almacenamiento distribuido. Usando Rancher UI es mucho mas fácil, así lo he hecho esta vez, la ventaja de hacerlo desde Rancher UI es que podemos acceder al Dashboard de Longhorn desde Rancher usando las mismas credenciales.

    https://rancher.com/blog/2017/announcing-longhorn-microservices-block-storage/

    En ese enlace se puede leer sobre el diseño de Longhorn:

    Storage Orchestration
    Replica Operations
    Replica Rebuild
    Backup of Snapshots
    Deployment Models

    Documentar el proceso de instalación está de más, en YouTube podemos ver el video de Adrian Goins.

    https://www.youtube.com/watch?v=q5JzZbiw4LE

    Y para los que quieren entender más a profundidad como funciona Longhorn, les recomiendo ver un video de Rancher Labs titulado: Kubernetes Master Class – Using Persistent Storage in Kubernetes and Project Longhorn.

    https://www.youtube.com/watch?v=BnHMAJ8azBU&t=

    En los próximos días estaré moviendo todo lo que tengo en Linstor a Longhorn, espero no perder información en el proceso!!!

  • Kubernetes – Almacenamiento con Linstor.

    Kubernetes – Almacenamiento con Linstor.

    Hace ya un tiempo que escribí sobre k8s, otros proyectos han tomado tiempo y recursos, hace unas semanas retome el clúster que tengo en casa para terminar las configuraciones necesarias y mover lo más que pueda de algunas máquinas virtuales que tengo en vSphere y que entiendo desempeñarían mejor estando en Kubernetes.

    Inicialmente las pruebas fueron realizadas con longhorn, algunos problemas los cuales no inspiran mucha confianza me hicieron no escribir sobre esa implementación, claramente Rancher dice que es un proyecto aun en beta.

    Hace unas semanas leí sobre Linstor [ http://vitobotta.com/2019/08/07/linstor-storage-with-kubernetes/ ], la instalación fue realizada en Ubuntu que es la misma distribución que estoy usando. He decidido usar esta implementación porque usa LVM como backend en los equipos que aportaran almacenamiento para el clúster, además de esto los nodos que están aportando almacenamiento no necesariamente deben tener k8s, al menos eso es lo que entiendo y algo que debo validar.

    Instalando Linstor.

    Prepararemos nuestros equipos con los siguientes pasos:

    apt-get install linux-headers-$(uname -r)
    add-apt-repository ppa:linbit/linbit-drbd9-stack
    apt-get update
    apt install drbd-utils drbd-dkms lvm2
    modprobe drbd
    lsmod | grep -i drbd
    echo drbd > /etc/modules-load.d/drbd.conf

     

    En este punto ya los equipos están listos para instalar los componentes de Linstor. Para estar seguro de que todo estaba bien procedí a reiniciar el nodo.

    Seleccionamos un equipo para que sea controlador del cluster de Linstor, además este mismo equipo puede aportar almacenamiento así que también instalaremos el componente de satellite.

    apt install linstor-controller linstor-satellite linstor-client

    Ahora habilitamos e inicializamos los componentes.

    systemctl enable --now linstor-controller
    systemctl start linstor-controller

    En los demás equipos instalamos el componente de satélite.

    apt install linstor-satellite linstor-client

    Habilitamos el servicio y lo iniciamos.

    systemctl enable --now linstor-satellite
    systemctl start linstor-satellite

    Desde el controller agregamos los equipos satélites.

    linstor node create kube1 172.22.35.25
    linstor node create kube2 172.22.35.26
    linstor node create kube3 172.22.35.27

    Esperamos unos minutos y ejecutamos:

    linstor node list

    Este comando nos mostrará la lista de nodos disponibles, será algo así:

    Ya contamos con un clúster de Linstor pero aun no estamos presentando almacenamiento a este, procederemos a crear almacenamiento administrado por LVM, Linstor soporta ZFS, esta es una herramienta que nunca he usado en el pasado de manera seria así que prefiero LVM que tiene años disponible en las distribuciones Linux.

    En cada máquina virtual para Kubernetes agregue dos discos, uno para el sistema operativo y otro para almacenamiento que ahora será usado en su totalidad con Linstor.

    Lo primero es preparar el disco físico para ser usado en LVM.

    pvcreate /dev/sdb

    Luego creamos un volumen group (vg).

    vgcreate kube /dev/sdb

    He seleccionado kube para que sea el nombre del Volume Group.

    Procederemos a crear un thin pool, esto nos permitirá crear volúmenes más grandes que el espacio físico del cual disponemos.

    lvcreate -l 100%FREE --thinpool kube/lvmthinpool

    Una vez realizados estos pasas en cada nodo que aportara almacenamiento al cluster, volvemos al controller para crear un storage-pool.

    linstor storage-pool create lvmthin kube1 linstor-pool kube/lvmthinpool
    linstor storage-pool create lvmthin kube2 linstor-pool kube/lvmthinpool
    linstor storage-pool create lvmthin kube3 linstor-pool kube/lvmthinpool

    validamos que nuestro storage-pool fue creado.

    linstor storage-pool list

    Debemos recibir lo siguiente:

    Listo, ya contamos con una plataforma para provisionar almacenamiento a Kubernetes, lo interesante es que también podría provisionar almacenamiento a otras plataformas tales como Proxmox.

    Kubernetes – que necesitamos?

    Para habilitar que Kubernetes pueda usar almacenamiento proveniente de Linstor, debemos contar con el plugin CSI y crear StorageClass, recomiendo tener una versión de Kubernetes mínimo 1.13 para que todo funcione bien ya que ahí plugins que no están habilitados por defecto antes de esta versión. Al momento de crear los CRD estos fallaban con un mensaje que especificaba la falta de CSINodeInfo, actualizando RKE a 1.14.6 se resolvió.

    Instalaremos todo lo necesario para usar Linstor usando esta línea la cual descargar la versión 0.7.2 del CSI y usando sed estamos cambian un valor de ejemplo por el controlador de Linstor que en mi caso es 172.22.35.25. Esto debe ser ejecutado en la misma maquina de donde administramos k8s.

    curl https://raw.githubusercontent.com/LINBIT/linstor-csi/v0.7.0/examples/k8s/deploy/linstor-csi-1.14.yaml | sed "s/linstor-controller.example.com/172.22.35.25/g" | kubectl apply -f -

    Podemos ver el avance del de la instalación con:

    watch kubectl -n kube-system get all

    Procederemos a crear un Storage Class usando este yaml

    El número de réplicas debe ser el número de nodos de Kubernetes.

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: linstor
    provisioner: linstor.csi.linbit.com
    parameters:
      autoPlace: "3"
      storagePool: "linstor-pool"

    Para este punto ya podemos hacer solicitudes de volúmenes usando un PresistentVolumeClaim

    En mi caso ya tenia varios yaml con requerimientos de pvc, aquí uno.

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      namespace: services
      name: adguard-config
    spec:
      storageClassName: linstor
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
           storage: 2Gi

    Podemos ver que el STATUS es Bound, esto quiere decir que satisfactoriamente Linstor asigno espacio a Kubernetes para este volumen.

    Desde el punto de vista de Linstor usando

    linstor volume list

    Podemos ver lo siguiente:

    Estos son todos los volúmenes que están siendo usados por contenedores en Kubernetes.

    Listo!

    Ya puedo usar el cluster de Kubernetes, bueno por la cantidad de volúmenes que se ven en la imagen se puede deducir que lo estoy usando. He movido varios servicios hacia el clúster y hasta ahora muy feliz con Kubernetes.

    El próximo paso es los respaldos, para esto estaré usando Velero de Heptio/VMware.

     

  • 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.