Monthly Archives: February 2017

OpenStack & Kubernetes: LBaaS y Self Service Provisioning

Ya que tenemos desplegado Kubernetes en OpenStack vamos a aprovechar las capacidades de este para desplegar nuestras aplicaciones.

Configurar Kubernetes para utilizar OpenStack

El primer paso que tenemos que dar es configurar nuestras credenciales de OpenStack en Kubernetes. Para ello editamos el fichero /etc/kubernetes/cloud_config y añadimos las siguientes líneas:

[Global]
auth-url=http://AUTH_URL:5000/v3
username=demo
password=s3cr3t
region=RegionOne
tenant-id=d245f207e6fc4e56b5a1d23e0716ad70
domain-name=Default

De esta forma el API de Kubernetes puede comunicar con el API de OpenStack y configurar los servicios.

El campo domain-name solo es necesario si usamos API v3 de OpenStack, como indica la AUTH_URL.

Ahora debemos cambiar añadir lo siguiente:

KUBE_API_ARGS=[...] --cloud-provider=openstack --cloud-config=/etc/kubernetes/cloud_config

al arranque de nuestro Kubernetes apiserver.

Igualmente en /etc/kubernetes/manifests/kube-controller-manager.yaml:

- [...]
- --cloud_config=/etc/sysconfig/kube_openstack_config
- --cloud_provider=openstack

Aquí la cosa se complica y depende de tu instalación. Si tienes el binario en el sistema solo tienes que ajustar en /etc/kubernetes/* pero si estás usando contenedores, deberás volver a construir los contenedores y añadir estos parámetros.

Utilizar el LBaaS de OpenStack en Kubernetes

Para habilitar el balanceador debemos añadir los siguientes datos en nuestro fichero de cloud_config:

  1. La subred donde se va a construir el balanceador.
  2. Debemos indicar que maneje los security groups.
  3. El security group que se debe aplicar al puerto del balanceador. Es el vip_port_id anterior.
  4. Y por último la id de la red de la que tomará la IP flotante.

Deberiamos tener algo así:

[LoadBalancer]
lb-version=v2
subnet-id=82f277d7-1b29-49b3-94ee-40424c4e36d9
manage-security-groups=true
node-security-group=b063453a-41fb-47e5-ac3e-fbe270fc2232
floating-network-id=ccee1f8b-c813-4a69-a072-ee1e10aba677

¿Qué tiene que pasar? Ahora, cuando en el service pongamos LoadBalancer Kubernetes utilizará las credenciales que le hemos proporcionado y construirá un balanceador completo para la aplicación. De la red que le hemos proporcionado cogerá un IP flotante libre. Esta es la IP a la que debemos atacar cuando queramos utilizar el servicio recién publicado.

Self Service Provisioning

Para que nuestras aplicaciones conserven los datos que generen en su tiempo de vida es necesario proporcionarles volúmenes de persistencia. Para ello comenzamos creando un nuevo objeto de Kubernetes llamado StorageClass donde vamos a definir como debe pedir el volumen a OpenStack y como vamos a llamarlo desde nuestra aplicación. Podemos definir tantos como sistemas de aprovisionamiento tengamos. El StorageClass tiene esta pinta:

kind: StorageClass
apiVersion: storage.k8s.io/v1beta1
metadata:
  name: gold #-> este es el nombre con el que nos referiremos a el cuando hagamos el claim
provisioner: kubernetes.io/cinder
parameters:
  type: kube-storage #-> Esto hay que definirlo en openstack
  availability: nova

Como vemos los dos valores que tenemos que definir son name y type. Entonces, cuando queramos que nuestra aplicación haga uso de esta persistencia dinámica usaremos algo como esto:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: claim1
  annotations:
    volume.beta.kubernetes.io/storage-class: gold #-> Este es el nombre que le hemos dado
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 30Gi

Antes había que hacer uso de PersistentVolume pero está siendo reemplazado por este nuevo objeto que creará el volumen dinámicamente.

Referencias

OpenStack: LoadBalancer as a Service v2

Vamos a ver como instalar y configurar LBaaSv2 en OpenStack Newton. Está montado sobre Ubuntu 16.04

Instalación

Toda la operación se desarrolla en el nodo controlador de OpenStack o donde esté configurada la red de Neutron

Puede parecer obvio, pero la documentación oficial no te dice que hay que instalar primero el plugin, para esto hacemos:

apt-get install neutron-lbaasv2-agent

Dependiendo de tu entorno instalará estas dependencias

python-pyasn1-modules:amd64 (0.0.7-0.1, automatic), haproxy:amd64 (1.6.3-1ubuntu0.1, automatic), liblua5.3-0:amd64 (5.3.1-1ubuntu2, automatic), python-neutron-lbaas:amd64 (2:9.0.0-0ubuntu1~cloud0, automatic), neutron-lbaasv2-agent:amd64 (2:9.0.0-0ubuntu1~cloud0), neutron-lbaas-common:amd64

Configuración

Vamos a editar los archivos de configuración:

En /etc/neutron/neutron.conf añadimos el plugin a la lista de plugins que haya.

service_plugins = [existing service plugins],neutron_lbaas.services.loadbalancer.plugin.LoadBalancerPluginv2

En /etc/neutron/neutron_lbaas.conf añadimos una linea en la sección [service_providers]. Si ya tenemos otros proveedores de servicios como FWaaS o VPNaaS añadimos una linea nueva, Esta directiva de configuración permite repetición.

service_provider = LOADBALANCERV2:Haproxy:neutron_lbaas.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default

En /etc/neutron/lbaas_agent.ini añadimos el driver que maneja la interfaces virtuales:

interface_driver = INTERFACE_DRIVER

Yo uso linuxbridge, luego la línea quedaría así:

interface_driver = neutron.agent.linux.interface.BridgeInterfaceDriver

Finalizamos con el migrate de la base de datos.

neutron-db-manage --subproject neutron-lbaas upgrade head

Reiniciamos neutron

systemctl neutron-server restart

Reiniciamos el agente

systemctl restart Neutron-lbaasv2-agent

Y con esto termina la configuración.

Crear un LoadBalancer

Tenemos dos servidores web corriendo en nuestro Tenant y queremos balancear la carga. Los dos servidores son:

webserver-1 172.31.1.25
webserver-2 172.31.1.16

Deben estar incluidos en alguna regla que permita el trafico HTTP hacia ellos, en caso contrario podemos crearlo:

# Cargar en openrc
. openrc
# Crear el security group
neutron security-group-create http
# Crear la regla
neutron security-group-rule-create --direction ingress --protocol tcp --port-range-min 80 --port-range-max 80 --remote-ip-prefix 0.0.0.0/0 http

Vamos a crear el balanceador

neutron lbaas-loadbalancer-create --name test-lb private-subnet

private-subnet es una subred privada. Podemos consultar las redes disponibles haciendo:

openstack network list

El balanceador se crea en unos segundos, podemos verlo así:

neutron lbaas-loadbalancer-show test-lb

Que mostrará algo como esto:

+---------------------+------------------------------------------------+
| Field               | Value                                          |
+---------------------+------------------------------------------------+
| admin_state_up      | True                                           |
| description         |                                                |
| id                  | 12826d46-9854-4123-9193-37b8c2511729           |
| listeners           | {"id": "75d5218b-948e-482b-b7a9-d831d0feb476"} |
| name                | test-lb                                        |
| operating_status    | ONLINE                                         |
| pools               | {"id": "860726ba-1997-453f-9e32-7879254e3306"} |
| provider            | haproxy                                        |
| provisioning_status | ACTIVE                                         |
| tenant_id           | d245f207e6fc4e56b5a1d23e0716ad70               |
| vip_address         | 172.31.1.23                                    |
| vip_port_id         | 1e090071-2800-4468-8ab7-0493d0881e10           |
| vip_subnet_id       | a03252b6-e67e-48d9-89fc-edc3872d83ae           |
+---------------------+------------------------------------------------+

Apuntar el valor de vip_port_id porque lo necesitaremos más adelante.

Vamos a crear los grupos de seguridad necesarios para dirigir tráfico al balanceador:

$ neutron security-group-create lbaas
$ neutron security-group-rule-create \
  --direction ingress \
  --protocol tcp \
  --port-range-min 80 \
  --port-range-max 80 \
  --remote-ip-prefix 0.0.0.0/0 \
  lbaas
$ neutron security-group-rule-create \
  --direction ingress \
  --protocol tcp \
  --port-range-min 443 \
  --port-range-max 443 \
  --remote-ip-prefix 0.0.0.0/0 \
  lbaas
$ neutron security-group-rule-create \
  --direction ingress \
  --protocol icmp \
  lbaas

Hemos permitido trafico HTTP, HTTPS y el ping. Ahora aplicamos las reglas al puerto del balanceador. El vip_port_id que apuntamos antes.

$ neutron port-update \
  --security-group lbaas \
  1e090071-2800-4468-8ab7-0493d0881e10

Podemos comprobar que está activo al hacer ping.

ping -c3 172.31.1.23
PING 172.31.1.23 (172.31.1.23) 56(84) bytes of data.
64 bytes from 172.31.1.23: icmp_seq=1 ttl=62 time=19.2 ms
64 bytes from 172.31.1.23: icmp_seq=2 ttl=62 time=0.491 ms
64 bytes from 172.31.1.23: icmp_seq=3 ttl=62 time=0.312 ms

--- 172.31.1.23 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.312/6.678/19.232/8.877 ms

Creamos los listeners para el balanceador:

$ neutron lbaas-listener-create \
  --name test-lb-http \
  --loadbalancer test-lb \
  --protocol HTTP \
  --protocol-port 80

Y por último el pool de servidores a los que se balancea:

$ neutron lbaas-pool-create \
  --name test-lb-pool-http \
  --lb-algorithm ROUND_ROBIN \
  --listener test-lb-http \
  --protocol HTTP
$ neutron lbaas-member-create \
  --subnet private-subnet \
  --address 172.31.1.16 \
  --protocol-port 80 \
  test-lb-pool-http
$ neutron lbaas-member-create \
  --subnet private-subnet \
  --address 172.31.1.25  \
  --protocol-port 80 \
  test-lb-pool-http

Ya sólo nos queda comprobar que funciona:

$ for i in $(seq 1 4); do curl 172.31.1.23; done
webserver-1
webserver-2
webserver-1
webserver-2