lunes, 30 de abril de 2018

Kubernetes [Best Practices] Organización con Namespaces

Hoy en google cloud español hablamos sobre la segunda entrega de una serie de videos y blogs en siete partes de Google Developer Advocate Sandeep Dinesh y sobre cómo aprovechar al máximo el entorno de Kubernetes.

A medida que comienzas a construir más y más servicios encima de Kubernetes, las tareas simples se vuelven más complicadas. Por ejemplo, los equipos no pueden crear Servicios de Kubernetes o Implementaciones con el mismo nombre.
Si tienes muchísimos pods, serviciosdeployments , solo listarlos tiene un coste alto de tiempo y de gestión, ¡y mucho menos administrarlos! Y estos son solo la punta del iceberg.

Veamos cómo Kubernetes Namespaces puede facilitar la gestión de los recursos de Kubernetes.



¿Qué es Namespace?

El mejor acercamiento como concepto al Namespace es  como un clúster virtual dentro de su clúster de Kubernetes. Puede tener múltiples namespaces dentro de un único clúster de Kubernetes, y todos están lógicamente aislados el uno del otro. ¡Te ayudara  en la gestión de  equipos con organización, seguridad e incluso rendimiento!

El "default" Namespace 

En la mayoría de las distribuciones de Kubernetes, el clúster de inicio por defecto esta dentro del Namespace "default". De hecho, hay tres namespaces con los que Kubernetes se crea: default, kube-system (utilizado para componentes de Kubernetes) y kube-public ( usado para recursos públicos). kube-public no se usa mucho actualmente, y generalmente es una buena idea dejar solo el kube-system, especialmente en un sistema administrado como Google Kubernetes Engine. Esto deja el namespace default como el lugar donde se crean sus servicios y aplicaciones por defecto.

No hay absolutamente nada de especial en este Espacio de nombres, excepto que las herramientas de Kubernetes están configuradas de serie para usar este espacio de nombres y no puede eliminarlo. Si bien es bueno para comenzar y para sistemas de producción más pequeños, recomendaría no usarlo en sistemas de producción grandes. Esto se debe a que es muy fácil para un equipo sobrescribir accidentalmente o interrumpir otro servicio sin siquiera darse cuenta. En su lugar, cree múltiples namespaces y úselos para segmentar sus servicios en zonas mas manejables.

Creando Namespaces

No tengas miedo de crear namespaces. No penalizan el  rendimiento, y en muchos casos pueden mejorar el rendimiento, ya que la API de Kubernetes tendrá un conjunto de objetos más pequeño para trabajar.

Crear un espacio de nombres se puede hacer con un solo comando. Si quisiera crear un espacio de nombres llamado 'test',  tendrías que ejecutar:


kubectl create namespace test

O puede crear un archivo YAML y aplicarlo como cualquier otro recurso de Kubernetes.
test.yaml:
kind: Namespace
apiVersion: v1
metadata:
  name: test
  labels:
    name: test
kubectl apply -f test.yaml

Visualización de Namespaces

Puede ver todos los namespaces con el siguiente comando:

kubectl get namespace


$kubectl get namespace
NAME         STATUS      AGE
default      Active      5d
kube-public  Active      5d
kube-sistem  Active      5d
test         Active      3m

Puede ver los tres namespaces basicos, así como el nuevo espacio de nombres llamado 'test'.

Crear recursos en el namespace

Echemos un vistazo a un simple YAML para crear un Pod:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
  labels:
    name: mypod
spec:
  containers:
  - name: mypod
    image: nginx

Normalmente en los ejemplos no se indica el namespace en ningún lado. Si ejecuta una aplicación `kubectl` en este archivo, creará el Pod en el espacio de nombres activo actual. Este será el espacio de nombres "default" a menos que lo cambie.

Hay dos formas de decirle explícitamente a Kubernetes en qué Namespace desea crear sus recursos.
Una forma es establecer el indicador de "namespace" al crear el recurso:

kubectl apply -f pod.yaml --namespace=test

También puede especificar un espacio de nombres en la declaración YAML.

apiVersion: v1
kind: Pod
metadata:
  name: mypod
  namespace: test
  labels:
    name: mypod
spec:
  containers:
  - name: mypod
    image: nginx

Si especifica un espacio de nombre en la declaración YAML, el recurso siempre se creará en ese espacio de nombres. Si intenta utilizar el indicador "namespace" para establecer otro espacio de nombres, el comando fallará.

Visualización de recursos en el Namespace

Si intentas encontrar tus Pod, ¡es posible que notes que no los ves!

$ kubectl get pods
No resources found.

No se encontraron recursos. Esto se debe a que todos los comandos se ejecutan contra el namespace actualmente activo. Para encontrar su Pod, debe usar el indicador "namespace".

$ kubectl get pods --namespace=test
NAME      READY     STATUS    RESTARTS   AGE
mypod     1/1       Running   0          10s

Esto puede ser incomdo, especialmente si es un desarrollador que trabaja en un equipo que usa su propio Espacio de nombres para todo y no desea usar el indicador de "espacio de nombre" para cada comando. Veamos un ejemplo de cómo podemos facilitar este caso.

Administrar tu namespace activo

Por defecto al iniciar el namespace es "default". A menos que especifique un Namespace en el YAML, todos los comandos de Kubernetes usarán el Namespace activo.

Desafortunadamente, tratar de administrar tu espacio de nombre activo con kubectl puede ser una incomodo. Afortunadamente, hay una herramienta realmente buena llamada kubens (creada por  Ahmet Alp Balkan) que hace que sea muy fácil.

Cuando ejecuta el comando 'kubens', debería ver todos los namespaces, con el espacio de nombres activo resaltado:

$ kubens
default
kube-public
kube-system
test


Para cambiar su espacio de nombres activo al espacio de nombres 'test', ejecuta:

kubens test

Ahora puede ver que el espacio de nombres de 'prueba' está activo:

$ kubens
default
kube-public
kube-system
test

Ahora, si ejecuta los comandos kubectl, namespace será 'test' en lugar de 'default'. Esto significa que no necesita el indicador de espacio de nombres para ver el pod en el namespace de test.

$ kubectl get pods
NAME      READY     STATUS    RESTARTS   AGE
mypod     1/1       Running   0          10m

Comunicación entre distintos Namespaces

Los namespaces están "ocultos" entre sí, pero no están completamente aislados por defecto. Un servicio en un namespaces puede hablar con un servicio en otro namespaces. Esto a menudo puede ser muy útil, por ejemplo para que el servicio de su equipo en su namespaces se comunique con el servicio de otro equipo en otro namespaces.

Cuando su aplicación quiere acceder a los servicios de Kubernetes, puede usar el descubrimiento del servicio DNS integrado y simplemente apuntar su aplicación a nombre del Servicio. Sin embargo, puede crear un servicio con el mismo nombre en múltiples namespaces. Afortunadamente, es fácil evitar esto al usar la forma expandida de la dirección DNS.

Los servicios en Kubernetes exponen su punto final utilizando un patrón DNS común. Se parece a esto:

<Service Aame>.<Namespace Name>.svc.cluster.local

Normalmente, solo necesita el nombre del Servicio y el DNS se resolverá automáticamente en la dirección completa. Sin embargo, si necesita acceder a un Servicio en otro Espacio de nombre simplemente use el Nombre del servicio más el nombre del namespaces.

Por ejemplo, si desea conectarse al servicio de "base de datos" en el espacio de nombres de "test", puede usar la siguiente dirección:

database.test

Si desea conectarse al servicio de "base de datos" en el espacio de nombres de "production", puede usar la siguiente dirección:

database.production

Advertencia: si crea un espacio de nombres que se asigna a un TLD como "com" u "org", y luego crea un servicio que tiene el mismo nombre que un sitio web, como "google" o "reddit", Kubernetes interceptará las solicitudes a " google.com "o" reddit.com "y envíelos a su Servicio. Esto a menudo puede ser muy útil para probar, ¡pero también puede liar las cosas fácilmente en su clúster!

Nota: Si desea aislar los namespaces, debe usar las políticas de red para lograr esto. Estén atentos para más sobre esto en un episodio futuro!

Granularidad del Namespaces

Una pregunta común que recibo es cuántos namespaces crear y con qué propósito. ¿Cuantos son necesarios para ser manejable? Si se crean demasiados namespaces  se interpongan en su camino, pero haga muy pocos y se pierden  los beneficios.
Creo que la respuesta radica en en qué etapa se encuentra su proyecto o compañía: desde un equipo pequeño hasta una gran empresa, cada uno tiene su propia estructura organizativa. Dependiendo de su situación, puede adoptar la estrategia concrete en su namespaces.

En una empresa pequeña

En este escenario, usted es parte de un pequeño equipo que está trabajando en 5-10 microservicios y puede reunir fácilmente a todos al rededor de unas pizzas. En esta situación, tiene sentido lanzar todos los servicios de producción en el espacio de nombres "default". Es posible que desee tener un espacio de nombres de "producción" y "desarrollo" si quiere gestionar mas fino, pero probablemente esté probando su entorno de desarrollo en su máquina local usando algo como Minikube.

En una empresa que se expande

En este escenario, tiene un equipo en rápido crecimiento que está trabajando en más de 10 microservicios. Está empezando a dividir el equipo en múltiples sub-equipos que cada uno posee sus propios microservicios. Si bien todos pueden saber cómo funciona el sistema completo, cada vez es más difícil coordinar cada cambio con los demás. Tratar de hacer girar la pila completa en su máquina local se vuelve más complicado cada día.

En este punto, es necesario usar múltiples clusters o namespaces para producción y desarrollo. Cada equipo puede elegir tener su propio espacio de nombre para una administración más fácil.

Empresa que crece

En una gran empresa, no todos conocen a los demás. Los equipos están trabajando en funciones que otros equipos podrían no conocer. Los equipos están utilizando contratos de servicios para comunicarse con otros microservicios (por ejemplo, gRPC) y mallas de servicio para coordinar la comunicación (por ejemplo, istio). Tratar de ejecutar toda la pila localmente es imposible. Se recomienda encarecidamente utilizar un sistema de CD compatible con Kubernetes (p. Ej., Spinnaker).

En este punto, cada equipo definitivamente necesita su propio namespaces. Cada equipo incluso puede optar por múltiples namespaces para ejecutar sus entornos de desarrollo y producción. Configurar RBAC y ResourceQuotas es una buena idea también. Múltiples clusters comienzan a tener mucho sentido, pero pueden no ser necesarios.

Gran empresa

En esta escala, hay grupos que ni siquiera conocen la existencia de otros grupos. Los grupos también pueden ser compañías externas, y los servicios se consumen a través de API bien documentadas. Cada grupo tiene múltiples equipos que tienen múltiples microservicios. Usar todas las herramientas que mencioné anteriormente son necesarias; las personas no deberían desplegar servicios a mano y deberían estar bloqueados fuera de los namespaces que no les pertenecen.
En este punto, probablemente tenga sentido tener múltiples clusters para reducir el radio de infestación de aplicaciones mal configuradas y facilitar la administración de recursos y facturación.

Conclusión

Los namespaces pueden ayudar significativamente a organizar sus recursos de Kubernetes y pueden aumentar la velocidad de sus equipos. Estén atentos para futuros episodios de Kubernetes Best Practices donde les mostraré cómo pueden bloquear recursos en un Namespace e introducir más seguridad y aislamiento en su clúster.