Brendan Burns

Guía práctica de Kubernetes


Скачать книгу

kubectl create namespace ${ns} kubectl annotate namespace ${ns} annotation_key= annotation_value

      Cuando se crea el espacio de nombres, necesitamos dotarlo de seguridad para tener la garantía de que podemos conceder acceso a un usuario específico. Para ello, podemos vincular un rol a un usuario en el contexto de ese espacio de nombres. Esto lo conseguimos creando el objeto RoleBinding dentro del propio espacio de nombres. RoleBindig podría tener este aspecto:

      apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: example namespace: my-namespace roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: edit subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: myuser

      Para crearlo, lo único que tenemos que hacer es ejecutar kubectl create -f role-binding.yaml. Hay que tener en cuenta que podemos reutilizar este vínculo tanto como deseemos, siempre y cuando actualicemos el espacio de nombres en el vínculo para apuntar al espacio de nombres correcto. Si tenemos la seguridad de que el usuario no tiene ningún otro vínculo de rol, podemos estar seguros de que este espacio de nombres es la única parte del clúster a la que el usuario tiene acceso. Otra práctica razonable es conceder acceso a los lectores a todo el clúster; de esta manera, los desarrolladores pueden ver lo que otros están haciendo en caso de que interfieran con su trabajo. Sin embargo, debemos tener cuidado al conceder dicho acceso de lectura porque este incluirá el acceso a recursos secretos en el clúster. Generalmente, en un clúster de desarrollo esto está bien porque todo el mundo está en la misma organización y los datos secretos se utilizan solo en desarrollo. Sin embargo, si es motivo de preocupación, podemos crear un rol más detallado en el que se elimine la posibilidad de leer datos secretos.

      Si deseamos limitar la cantidad de recursos que consume un espacio de nombres determinado, podemos utilizar el recurso ResourceQuota para fijar un límite al número total de recursos que consume ese espacio de nombres en particular. Por ejemplo, la siguiente cuota limita el espacio de nombres a 10 núcleos y 100 GB de memoria, para Request y Limit, para las cápsulas en ese espacio de nombres:

      apiVersion: v1 kind: ResourceQuota metadata: name: limit-compute namespace: my-namespace spec: hard: requests.cpu: "10" requests.memory: 100Gi limits.cpu: "10" limits.memory: 100Gi

      Ahora que hemos visto cómo incorporar a un nuevo usuario y cómo crear un espacio de nombres para utilizarlo como espacio de trabajo, la pregunta sigue siendo cómo asignar un desarrollador a un espacio de nombres. Como con muchas otras cosas, no hay una sola respuesta; en este caso hay dos enfoques. El primero es dar a cada usuario su propio espacio de nombres como parte del proceso de integración. Esto es útil porque después de que un usuario se haya registrado, siempre tiene un espacio de trabajo donde puede desarrollar y gestionar sus aplicaciones. Sin embargo, hacer que el espacio de nombres del desarrollador se extienda demasiado en el tiempo anima a este a dejar las cosas en el espacio de nombres después de haber terminado de usarlas, y la recogida de basura y la contabilidad de los recursos individuales se complican. Un enfoque alternativo consiste en crear y asignar temporalmente un espacio de nombres con un time to live (tiempo de vida) (TTL) limitado. Esta opción asegura que el desarrollador tenga en cuenta que los recursos en el clúster son transitorios y que es fácil automatizar la eliminación de espacios de nombres completos cuando su TTL expire.

      En este modelo, cuando el desarrollador quiere iniciar un nuevo proyecto, utiliza una herramienta para asignar un nuevo espacio de nombres al proyecto. Cuando creamos el espacio de nombres, este tiene una selección de metadatos asociados a él para la gestión y la contabilidad. Obviamente, estos metadatos incluyen el TTL para el espacio de nombres, pero también incluyen al desarrollador al que está asignado, los recursos que deben asignarse al espacio de nombres (por ejemplo, CPU y memoria), el equipo de trabajo y el propósito del espacio de nombres. Estos metadatos garantizan que podamos realizar un seguimiento del uso de los recursos y eliminar el espacio de nombres en el momento adecuado.

      El desarrollo de herramientas para asignar espacios de nombres a petición puede parecer un reto, pero las herramientas sencillas son relativamente fáciles de desarrollar. Por ejemplo, se puede lograr la asignación de un nuevo espacio de nombres con un sencillo script que crea el espacio de nombres y solicita los metadatos relevantes para adjuntarlos al mismo.

      Si queremos tener una mayor integración con Kubernetes, podemos usar las custom resources definitions (definiciones de recursos personalizados) (CRD), que permiten a los usuarios crear y asignar dinámicamente nuevos espacios de nombres mediante la herramienta kubectl. Si tienes tiempo y ganas, esta es definitivamente una buena opción porque hace que la gestión de los espacios de nombres sea declarativa y también permite el uso de RBAC de Kubernetes.

      Una vez disponemos de las herramientas para habilitar la asignación de espacios de nombres, necesitamos añadir algunas herramientas para reutilizarlos cuando su TTL haya expirado. Una vez más, podemos conseguirlo con un sencillo script que examina los espacios de nombres y borra aquellos que tienen una TTL caducada.

      Podemos crear este script en un contenedor y usar ScheduledJob para ejecutarlo con una frecuencia de una hora. Combinadas entre sí, estas herramientas pueden garantizar que los desarrolladores puedan asignar fácilmente recursos independientes para su proyecto en la medida en que lo necesiten. Pero esos recursos también se obtendrán en el intervalo adecuado para tener la seguridad de que no estamos malgastando recursos y de que los recursos antiguos no se interponen en el camino del nuevo desarrollo.

      Además de las herramientas para asignar y gestionar espacios de nombres, también hay servicios útiles a nivel de clúster, y es una buena idea habilitarlos en nuestro clúster de desarrollo. El primero es la agregación de registros a un sistema central de Logging as a Service (administración de registros como servicio) (LaaS). Una de las cosas más fáciles de hacer para que los desarrolladores entiendan el funcionamiento de sus aplicaciones es escribir algo en STDOUT. Aunque podemos acceder a estos registros a través de kubectl logs, estos tienen una longitud limitada y no son localizables particularmente. Si, en cambio, enviamos automáticamente esos registros a un sistema LaaS —como puede ser un servicio en la nube o un clúster de búsqueda elástica—, los desarrolladores pueden buscar fácilmente información relevante en los registros, así como información de registros añadida a través de varios contenedores a su servicio.

      Ahora que hemos tenido éxito en la configuración de un clúster compartido y que podemos registrar nuevos desarrolladores en el clúster, necesitamos conseguir que estos desarrollen sus aplicaciones. Recordemos que uno de los KPI clave que medimos es el tiempo que transcurre desde la incorporación hasta la aplicación inicial que se ejecuta en el clúster. Está claro que, a través de lo que acabamos de describir, podemos autenticar con rapidez a un usuario en un clúster y asignarle un espacio de nombres. Pero, ¿qué hay de empezar con la aplicación? Desafortunadamente, aunque hay algunas técnicas que ayudan en este proceso, por lo general poner en marcha la aplicación inicial requiere más de convención que de automatización. En las siguientes secciones, describimos un enfoque para lograrlo. De ninguna manera se trata de un único enfoque o una única solución. Opcionalmente, podemos aplicar el enfoque tal cual o inspirarnos en ideas para llegar a nuestra propia solución.

      Uno de los principales retos para implementar una aplicación es la instalación de todas las dependencias. En muchos casos, especialmente en las arquitecturas modernas de microservicios, incluso para empezar la labor de desarrollo en uno de los microservicios se requiere el despliegue de múltiples dependencias, ya sean bases de datos u otros microservicios. Aunque el despliegue de la aplicación en sí es relativamente sencillo, la tarea de identificar e implementar todas las dependencias para crear la aplicación completa es a menudo una tarea frustrante de prueba y error combinada con instrucciones incompletas o desactualizadas.

      Para