diff --git a/es/README.md b/es/README.md index afe9c547..b421866a 100644 --- a/es/README.md +++ b/es/README.md @@ -11,7 +11,7 @@ El enfoque del curso es capacitar a la persona para trabajar con Kubernetes de m ## Contenido
-DÍA 1 +DAY-1 - [Simplificando Kubernetes](day-1/README.md#simplificando-kubernetes) - [Día 1](day-1/README.md##día-1) @@ -231,12 +231,68 @@ El enfoque del curso es capacitar a la persona para trabajar con Kubernetes de m
DAY-8 -TO DO + +- [Simplificando Kubernetes](day-8/#simplificando-kubernetes) + - [Día 8](day-8/#día-8) + - [Contenido del Día 8](day-8/#contenido-del-día-8) + - [¿Qué veremos hoy?](day-8/#qué-veremos-hoy) + - [¿Qué son los Secrets?](day-8/#qué-son-los-secrets) + - [¿Cómo funcionan los Secrets?](day-8/#cómo-funcionan-los-secrets) + - [Tipos de Secrets](day-8/#tipos-de-secrets) + - [Antes de crear un Secret, el Base64](day-8/#antes-de-crear-un-secret-el-base64) + - [Creando nuestro primer Secret](day-8/#creando-nuestro-primer-secret) + - [Usando nuestro primer Secret](day-8/#usando-nuestro-primer-secret) + - [Creando un Secreto para almacenar credenciales de Docker](day-8/#creando-un-secreto-para-almacenar-credenciales-de-docker) + - [Creando un Secret TLS](day-8/#creando-un-secret-tls) + - [ConfigMaps](day-8/#configmaps) + - [Operador de Secretos Externos](day-8/#operador-de-secretos-externos) + - [El Rol Destacado del ESO](day-8/#el-rol-destacado-del-eso) + - [Conceptos Clave del Operador de Secretos Externos](day-8/#conceptos-clave-del-operador-de-secretos-externos) + - [SecretStore](day-8/#secretstore) + - [ExternalSecret](day-8/#externalsecret) + - [ClusterSecretStore](day-8/#clustersecretstore) + - [Control de Acceso y Seguridad](day-8/#control-de-acceso-y-seguridad) + - [Configurando el External Secrets Operator](day-8/#configurando-el-external-secrets-operator) + - [¿Qué es Vault?](day-8/#qué-es-vault) + - [¿Por Qué Usar Vault?](day-8/#por-qué-usar-vault) + - [Comandos Básicos de Vault](day-8/#comandos-básicos-de-vault) + - [El Vault en el Contexto de Kubernetes](day-8/#el-vault-en-el-contexto-de-kubernetes) + - [Instalación y Configuración de Vault en Kubernetes](day-8/#instalación-y-configuración-de-vault-en-kubernetes) + - [Requisitos Previos](day-8/#requisitos-previos) + - [Instalando y Configurando Vault con Helm](day-8/#instalando-y-configurando-vault-con-helm) + - [Agregar el Repositorio del Operador de Secretos Externos a Helm](day-8/#agregar-el-repositorio-del-operador-de-secretos-externos-a-helm) + - [Instalando el Operador de Secretos Externos](day-8/#instalando-el-operador-de-secretos-externos) + - [Verificación de la Instalación de ESO](day-8/#verificación-de-la-instalación-de-eso) + - [Creación de un Secreto en Kubernetes](day-8/#creación-de-un-secreto-en-kubernetes) + - [Configuración del ClusterSecretStore](day-8/#configuración-del-clustersecretstore) + - [Creación de un ExternalSecret](day-8/#creación-de-un-externalsecret) + - [Final del Día 8](day-8/#final-del-día-8) + + 
DAY-9 -TO DO + +- [Simplificando Kubernetes](day-9/#simplificando-kubernetes) + - [DÍA 9](day-9/#día-9) + - [¿Qué veremos hoy?](day-9/#qué-veremos-hoy) + - [Contenido del Día 9](day-9/#contenido-del-día-9) +- [¿Qué es Ingress?](day-9/#qué-es-ingress) +- [Componentes de Ingress](day-9/#componentes-de-ingress) + - [Componentes Clave](day-9/#componentes-clave) + - [Ingress Controller](day-9/#ingress-controller) + - [Ingress Resources](day-9/#ingress-resources) + - [Anotaciones y Personalizaciones](day-9/#anotaciones-y-personalizaciones) + - [Instalación del Nginx Ingress Controller](day-9/#instalación-del-nginx-ingress-controller) + - [Instalación del Ingress Controller Nginx en Kind](day-9/#instalación-del-ingress-controller-nginx-en-kind) + - [Creación del Clúster con Configuraciones Especiales](day-9/#creación-del-clúster-con-configuraciones-especiales) + - [Instalación de un Ingress Controller](day-9/#instalación-de-un-ingress-controller) + - [Instalación de Giropops-Senhas en el Cluster](day-9/#instalación-de-giropops-senhas-en-el-cluster) + - [Creación de un Recurso de Ingress](day-9/#creación-de-un-recurso-de-ingress) +- [TBD (Por determinar)](day-9/#tbd-por-determinar) + + 
@@ -246,22 +302,172 @@ TO DO
DAY-11 -TO DO + +- [Simplificando Kubernetes](day-11/#simplificando-kubernetes) + - [Día 11](day-11/#día-11) + - [Contenido del Día 11](day-11/#contenido-del-día-11) + - [Comienzo de la lección del Día 11](day-11/#comienzo-de-la-lección-del-día-11) + - [¿Qué veremos hoy?](day-11/#qué-veremos-hoy) + - [Introducción al Escalador Automático de Pods Horizontales (HPA)](day-11/#introducción-al-escalador-automático-de-pods-horizontales-hpa) + - [¿Cómo funciona el HPA?](day-11/#cómo-funciona-el-hpa) + - [Introducción al Metrics Server](day-11/#introducción-al-metrics-server) + - [¿Por qué es importante el Metrics Server para el HPA?](day-11/#por-qué-es-importante-el-metrics-server-para-el-hpa) + - [Instalación del Metrics Server](day-11/#instalación-del-metrics-server) + - [En Amazon EKS y la mayoría de los clústeres Kubernetes](day-11/#en-amazon-eks-y-la-mayoría-de-los-clústeres-kubernetes) + - [En Minikube](day-11/#en-minikube) + - [En KinD (Kubernetes in Docker)](day-11/#en-kind-kubernetes-in-docker) + - [Verificando la Instalación del Metrics Server](day-11/#verificando-la-instalación-del-metrics-server) + - [Obteniendo Métricas](day-11/#obteniendo-métricas) + - [Creando un HPA](day-11/#creando-un-hpa) + - [Ejemplos Prácticos con HPA](day-11/#ejemplos-prácticos-con-hpa) + - [Escalado automático basado en el uso de CPU](day-11/#escalado-automático-basado-en-el-uso-de-cpu) + - [Escalado automático basado en el uso de Memoria](day-11/#escalado-automático-basado-en-el-uso-de-memoria) + - [Configuración Avanzada de HPA: Definición del Comportamiento de Escalado](day-11/#configuración-avanzada-de-hpa-definición-del-comportamiento-de-escalado) + - [ContainerResource](day-11/#containerresource) + - [Detalles del Algoritmo de Escalado](day-11/#detalles-del-algoritmo-de-escalado) + - [Configuraciones Avanzadas y Uso Práctico](day-11/#configuraciones-avanzadas-y-uso-práctico) + - [Integración del HPA con Prometheus para Métricas Personalizadas](day-11/#integración-del-hpa-con-prometheus-para-métricas-personalizadas) + - [Tu Tarea](day-11/#tu-tarea) + - [Fin del Día 11](day-11/#fin-del-día-11) + + 
-TO DO +
DAY-12 -TO DO + +- [Simplificando Kubernetes](day-12/#simplificando-kubernetes) + - [Día 12: Dominando Taints y Tolerations](day-12/#día-12-dominando-taints-y-tolerations) + - [Contenido del Día 12](day-12/#contenido-del-día-12) + - [Introducción](day-12/#introducción) + - [¿Qué son Taints y Tolerations?](day-12/#qué-son-taints-y-tolerations) + - [¿Por qué usar Taints y Tolerations?](day-12/#por-qué-usar-taints-y-tolerations) + - [Anatomía de un Taint](day-12/#anatomía-de-un-taint) + - [Anatomía de una Tolerations](day-12/#anatomía-de-una-tolerations) + - [Aplicación de Taints](day-12/#aplicación-de-taints) + - [Configuración de Tolerations](day-12/#configuración-de-tolerations) + - [Escenarios de Uso](day-12/#escenarios-de-uso) + - [Aislamiento de Cargas de Trabajo](day-12/#aislamiento-de-cargas-de-trabajo) + - [Nodos Especializados](day-12/#nodos-especializados) + - [Toleration en un Pod que Requiere GPU:](day-12/#toleration-en-un-pod-que-requiere-gpu) + - [Evacuación y Mantenimiento de Nodos](day-12/#evacuación-y-mantenimiento-de-nodos) + - [Combinando Taints y Tolerations con Reglas de Afinidad](day-12/#combinando-taints-y-tolerations-con-reglas-de-afinidad) + - [Ejemplos Prácticos](day-12/#ejemplos-prácticos) + - [Ejemplo 1: Aislamiento de Cargas de Trabajo](day-12/#ejemplo-1-aislamiento-de-cargas-de-trabajo) + - [Ejemplo 2: Utilización de Hardware Especializado](day-12/#ejemplo-2-utilización-de-hardware-especializado) + - [Ejemplo 3: Mantenimiento de Nodos](day-12/#ejemplo-3-mantenimiento-de-nodos) + - [Conclusión](day-12/#conclusión) + - [Tareas del Día](day-12/#tareas-del-día) + - [DÍA 12+1: Comprendiendo y Dominando los Selectores](day-12/#día-121-comprendiendo-y-dominando-los-selectores) + - [Introducción 12+1](day-12/#introducción-121) + - [¿Qué son los Selectors?](day-12/#qué-son-los-selectors) + - [Tipos de Selectors](day-12/#tipos-de-selectors) + - [Equality-based Selectors](day-12/#equality-based-selectors) + - [Set-based Selectors](day-12/#set-based-selectors) + - [Selectors en acción](day-12/#selectors-en-acción) + - [En Services](day-12/#en-services) + - [En ReplicaSets](day-12/#en-replicasets) + - [En Jobs y CronJobs](day-12/#en-jobs-y-cronjobs) + - [Selectores y Namespaces](day-12/#selectores-y-namespaces) + - [Escenarios de uso](day-12/#escenarios-de-uso-1) + - [Enrutamiento de tráfico](day-12/#enrutamiento-de-tráfico) + - [Escalado horizontal](day-12/#escalado-horizontal) + - [Desastre y recuperación](day-12/#desastre-y-recuperación) + - [Consejos y trampas](day-12/#consejos-y-trampas) + - [Ejemplos prácticos](day-12/#ejemplos-prácticos-1) + - [Ejemplo 1: Selector en un Service](day-12/#ejemplo-1-selector-en-un-service) + - [Ejemplo 2: Selector en un ReplicaSet](day-12/#ejemplo-2-selector-en-un-replicaset) + - [Ejemplo 3: Selectors avanzados](day-12/#ejemplo-3-selectors-avanzados) + - [Conclusión 12+1](day-12/#conclusión-121) +
-TO DO +
DAY-13 -TO DO + +- [Simplificando Kubernetes](day-13/#simplificando-kubernetes) + - [Día 13: Simplificando Kyverno y las Policies en Kubernetes](day-13/#día-13-simplificando-kyverno-y-las-policies-en-kubernetes) + - [Contenido del Día 13](day-13/#contenido-del-día-13) + - [¿Qué veremos hoy?](day-13/#qué-veremos-hoy) + - [Comienzo del Día 13](day-13/#comienzo-del-día-13) + - [Introducción a Kyverno](day-13/#introducción-a-kyverno) + - [Instalación de Kyverno](day-13/#instalación-de-kyverno) + - [Usando Helm](day-13/#usando-helm) + - [Verificación de la Instalación](day-13/#verificación-de-la-instalación) + - [Creación de nuestra primera política](day-13/#creación-de-nuestra-primera-política) + - [Ejemplo de Política: Agregar Etiqueta al Namespace](day-13/#ejemplo-de-política-agregar-etiqueta-al-namespace) + - [Detalles de la Política: Agregar Etiqueta al Namespace](day-13/#detalles-de-la-política-agregar-etiqueta-al-namespace) + - [Archivo de Política: `add-label-namespace.yaml`](day-13/#archivo-de-política-add-label-namespaceyaml) + - [Uso de la Política: Agregar Etiqueta al Namespace](day-13/#uso-de-la-política-agregar-etiqueta-al-namespace) + - [Ejemplo de Política: Prohibir Usuario Root](day-13/#ejemplo-de-política-prohibir-usuario-root) + - [Detalles de la Política: Prohibir Usuario Root](day-13/#detalles-de-la-política-prohibir-usuario-root) + - [Archivo de la Política: `disallow-root-user.yaml`](day-13/#archivo-de-la-política-disallow-root-useryaml) + - [Implementación y Efecto](day-13/#implementación-y-efecto) + - [Ejemplo de Política: Generar ConfigMap para Namespace](day-13/#ejemplo-de-política-generar-configmap-para-namespace) + - [Detalles de la Política: Generar ConfigMap para Namespace](day-13/#detalles-de-la-política-generar-configmap-para-namespace) + - [Archivo de Política: `generar-configmap-para-namespace.yaml`](day-13/#archivo-de-política-generar-configmap-para-namespaceyaml) + - [Implementación y Utilidad](day-13/#implementación-y-utilidad) + - [Ejemplo de Política: Permitir Solo Repositorios de Confianza](day-13/#ejemplo-de-política-permitir-solo-repositorios-de-confianza) + - [Detalles de la Política: Permitir Solo Repositorios de Confianza](day-13/#detalles-de-la-política-permitir-solo-repositorios-de-confianza) + - [Archivo de Política: `repositorio-permitido.yaml`](day-13/#archivo-de-política-repositorio-permitidoyaml) + - [Implementación e Impacto](day-13/#implementación-e-impacto) + - [Ejemplo de Política: Require Probes](day-13/#ejemplo-de-política-require-probes) + - [Detalles de la Política: Require Probes](day-13/#detalles-de-la-política-require-probes) + - [Archivo de Política: `require-probes.yaml`](day-13/#archivo-de-política-require-probesyaml) + - [Implementación e Impacto: Require Probes](day-13/#implementación-e-impacto-require-probes) + - [Ejemplo de Política: Uso del Exclude](day-13/#ejemplo-de-política-uso-del-exclude) + - [Detalles de la Política: Uso del Exclude](day-13/#detalles-de-la-política-uso-del-exclude) + - [Archivo de Política](day-13/#archivo-de-política) + - [Implementación y Efectos: Uso del Exclude](day-13/#implementación-y-efectos-uso-del-exclude) + - [Conclusión](day-13/#conclusión) + - [Puntos Clave Aprendidos](day-13/#puntos-clave-aprendidos) +
-TO DO +
DAY-14 -TO DO + +- [Simplificando Kubernetes](day-14/#simplificando-kubernetes) + - [Día 14: Network Policies no Kubernetes](day-14/#día-14-network-policies-no-kubernetes) + - [Contenido del Día 14](day-14/#contenido-del-día-14) + - [Lo que veremos hoy](day-14/#lo-que-veremos-hoy) + - [¿Qué son las Network Policies?](day-14/#qué-son-las-network-policies) + - [¿Para qué sirven las Network Policies?](day-14/#para-qué-sirven-las-network-policies) + - [Conceptos Fundamentales: Ingress y Egress](day-14/#conceptos-fundamentales-ingress-y-egress) + - [¿Cómo funcionan las Network Policies?](day-14/#cómo-funcionan-las-network-policies) + - [Aún no es estándar](day-14/#aún-no-es-estándar) + - [Creación de un clúster EKS con Network Policies](day-14/#creación-de-un-clúster-eks-con-network-policies) + - [Instalación de EKSCTL](day-14/#instalación-de-eksctl) + - [Instalación de AWS CLI](day-14/#instalación-de-aws-cli) + - [Creación del Cluster EKS](day-14/#creación-del-cluster-eks) + - [Instalando el complemento AWS VPC CNI](day-14/#instalando-el-complemento-aws-vpc-cni) + - [Habilitación de Network Policy en las Configuraciones Avanzadas del CNI](day-14/#habilitación-de-network-policy-en-las-configuraciones-avanzadas-del-cni) + - [Instalación del Controlador de Ingress Nginx](day-14/#instalación-del-controlador-de-ingress-nginx) + - [Instalando un Controlador de Ingress Nginx](day-14/#instalando-un-controlador-de-ingress-nginx) + - [Nuestra Aplicación de Ejemplo](day-14/#nuestra-aplicación-de-ejemplo) + - [Creación de Reglas de Política de Red](day-14/#creación-de-reglas-de-política-de-red) + - [Ingress](day-14/#ingress) + - [Egress](day-14/#egress) + +
+ +
+DAY-15 + +- [Simplificando Kubernetes](day-15/#simplificando-kubernetes) + - [Día 15: Descomplicando RBAC e controle de acesso no Kubernetes](day-15/#día-15-descomplicando-rbac-e-controle-de-acesso-no-kubernetes) + - [Contenido del Día 15](day-15/#contenido-del-día-15) +- [¿Qué vamos a aprender hoy?](day-15/#qué-vamos-a-aprender-hoy) +- [RBAC](day-15/#rbac) + - [¿Qué es RBAC?](day-15/#qué-es-rbac) + - [Primer ejemplo de RBAC](day-15/#primer-ejemplo-de-rbac) + - [Creación de un Usuario para Acceso al clúster](day-15/#creación-de-un-usuario-para-acceso-al-clúster) + - [Creando un Rol para nuestro usuario](day-15/#creando-un-rol-para-nuestro-usuario) + - [apiGroups](day-15/#apigroups) + - [Verbos](day-15/#verbos) + - [Agregando el certificado del usuario al kubeconfig](day-15/#agregando-el-certificado-del-usuario-al-kubeconfig) + - [Accediendo al clúster con el nuevo usuario](day-15/#accediendo-al-clúster-con-el-nuevo-usuario) +
  diff --git a/es/day-13/README.md b/es/day-13/README.md index f61a0dc7..f673e59e 100644 --- a/es/day-13/README.md +++ b/es/day-13/README.md @@ -143,6 +143,7 @@ Si no especifica ningún namespace en la política o utiliza `ClusterPolicy`, Ky 1. **Política de Límites de Recursos:** Asegurar que todos los contenedores en un Pod tengan límites de CPU y memoria definidos. Esto puede ser importante para evitar el uso excesivo de recursos en un clúster compartido. **Archivo `require-resources-limits.yaml`:** + ```yaml apiVersion: kyverno.io/v1 kind: ClusterPolicy diff --git a/es/day-14/README.md b/es/day-14/README.md new file mode 100644 index 00000000..2eaa0dac --- /dev/null +++ b/es/day-14/README.md @@ -0,0 +1,1066 @@ +# Simplificando Kubernetes + +## Día 14: Network Policies no Kubernetes + +## Contenido del Día 14 + +- [Simplificando Kubernetes](#simplificando-kubernetes) + - [Día 14: Network Policies no Kubernetes](#día-14-network-policies-no-kubernetes) + - [Contenido del Día 14](#contenido-del-día-14) + - [Lo que veremos hoy](#lo-que-veremos-hoy) + - [¿Qué son las Network Policies?](#qué-son-las-network-policies) + - [¿Para qué sirven las Network Policies?](#para-qué-sirven-las-network-policies) + - [Conceptos Fundamentales: Ingress y Egress](#conceptos-fundamentales-ingress-y-egress) + - [¿Cómo funcionan las Network Policies?](#cómo-funcionan-las-network-policies) + - [Aún no es estándar](#aún-no-es-estándar) + - [Creación de un clúster EKS con Network Policies](#creación-de-un-clúster-eks-con-network-policies) + - [Instalación de EKSCTL](#instalación-de-eksctl) + - [Instalación de AWS CLI](#instalación-de-aws-cli) + - [Creación del Cluster EKS](#creación-del-cluster-eks) + - [Instalando el complemento AWS VPC CNI](#instalando-el-complemento-aws-vpc-cni) + - [Habilitación de Network Policy en las Configuraciones Avanzadas del CNI](#habilitación-de-network-policy-en-las-configuraciones-avanzadas-del-cni) + - [Instalación del Controlador de Ingress Nginx](#instalación-del-controlador-de-ingress-nginx) + - [Instalando un Controlador de Ingress Nginx](#instalando-un-controlador-de-ingress-nginx) + - [Nuestra Aplicación de Ejemplo](#nuestra-aplicación-de-ejemplo) + - [Creación de Reglas de Política de Red](#creación-de-reglas-de-política-de-red) + - [Ingress](#ingress) + - [Egress](#egress) + +## Lo que veremos hoy + +Hoy dedicaremos nuestro tiempo a comprender el mundo de las Network Policies en Kubernetes. Esta es una herramienta esencial para la seguridad y la gestión efectiva de la comunicación entre los Pods en un clúster de Kubernetes. Aprenderemos cómo funcionan las Network Policies, sus aplicaciones prácticas y cómo puede implementarlas para proteger sus aplicaciones en Kubernetes. Seguro que será un día lleno de contenido y aprendizaje. ¡Vamos allá! + +### ¿Qué son las Network Policies? + +En Kubernetes, una Network Policy es un conjunto de reglas que define cómo los Pods pueden comunicarse entre sí y con otros puntos finales de la red. Por defecto, los Pods en un clúster de Kubernetes pueden comunicarse libremente entre sí, lo que puede no ser ideal para todos los escenarios. Las Network Policies le permiten restringir este acceso, asegurando que solo el tráfico permitido pueda fluir entre los Pods o hacia/desde direcciones IP externas. + +#### ¿Para qué sirven las Network Policies? + +Las Network Policies se utilizan para: + +- **Aislar** los Pods del tráfico no autorizado. +- **Controlar** el acceso a servicios específicos. +- **Implementar** estándares de seguridad y cumplimiento. + +#### Conceptos Fundamentales: Ingress y Egress + +- **Ingress**: Las reglas de ingreso controlan el tráfico de entrada a un Pod. +- **Egress**: Las reglas de egreso controlan el tráfico de salida de un Pod. + +Comprender estos conceptos es fundamental para entender cómo funcionan las Network Policies, ya que deberá especificar si una regla se aplica al tráfico de entrada o de salida. + +#### ¿Cómo funcionan las Network Policies? + +Las Network Policies utilizan `SELECTORS` para identificar grupos de Pods y establecer reglas de tráfico para ellos. La política puede especificar: + +- **Ingress (entrada)**: qué Pods o direcciones IP pueden conectarse a los Pods seleccionados. +- **Egress (salida)**: a qué Pods o direcciones IP pueden conectarse los Pods seleccionados. + +#### Aún no es estándar + +Desafortunadamente, las Network Policies aún no son una característica estándar en todos los clústeres de Kubernetes. Recientemente, AWS anunció el soporte de Network Policies en EKS, pero aún no es una característica estándar. Para usar Network Policies en EKS, debe instalar el CNI de AWS y luego habilitar Network Policy en la configuración avanzada del CNI. + +Para verificar si su clúster admite Network Policies, puede ejecutar el siguiente comando: + +```bash +kubectl api-versions | grep networking +``` + +Si recibe el mensaje `networking.k8s.io/v1`, significa que su clúster admite Network Policies. Si recibe el mensaje `networking.k8s.io/v1beta1`, significa que su clúster no admite Network Policies. + +Si su clúster no admite Network Policies, puede utilizar Calico para implementar Network Policies en su clúster. Para hacerlo, debe instalar Calico en su clúster. Puede encontrar más información sobre Calico [aquí](https://docs.projectcalico.org/getting-started/kubernetes/). + +Otros CNIs que admiten Network Policies son Weave Net y Cilium, entre otros. + +#### Creación de un clúster EKS con Network Policies + +Supongo que, a estas alturas de la formación, ya sabe lo que es un clúster EKS, ¿verdad? + +Pero aún así, haré una breve presentación solo para refrescar su memoria o ayudar a quienes acaban de unirse aquí. Hahaha. + +EKS es Kubernetes gestionado por AWS, pero, ¿qué significa eso? + +Cuando hablamos de clústeres Kubernetes gestionados, nos referimos a que no tendremos que preocuparnos por la instalación y configuración de Kubernetes, ya que AWS se encargará de ello. Solo necesitaremos crear nuestro clúster y gestionar nuestras aplicaciones. + +Como ya sabe, tenemos dos tipos de nodos, los nodos del plano de control y los nodos trabajadores. En EKS, los nodos del plano de control son gestionados por AWS, es decir, no tendremos que preocuparnos por ellos. En cuanto a los trabajadores, en la mayoría de los casos, deberemos crearlos y gestionarlos nosotros mismos. + +Antes de empezar, entendamos los tres tipos de clústeres EKS que podemos tener: + +- **Grupos de nodos administrados**: en este tipo de clúster, los nodos trabajadores son gestionados por AWS, es decir, no tendremos que preocuparnos por ellos. AWS creará y gestionará los nodos trabajadores para nosotros. Este tipo de clúster es ideal para quienes no desean preocuparse por la administración de los nodos trabajadores. +- **Grupos de nodos autoadministrados**: en este tipo de clúster, los nodos trabajadores son gestionados por nosotros, lo que significa que deberemos crearlos y gestionarlos. Este tipo de clúster es ideal para quienes desean tener un control total sobre los nodos trabajadores. +- **Fargate**: en este tipo de clúster, los nodos trabajadores son gestionados por AWS, pero no tendremos que preocuparnos por ellos, ya que AWS creará y gestionará los nodos trabajadores para nosotros. Este tipo de clúster es ideal para quienes no desean preocuparse por la administración de los nodos trabajadores, pero tampoco quieren preocuparse por crearlos y gestionarlos. + +Claramente, cada tipo tiene sus ventajas y desventajas, y debe analizar su situación para elegir el tipo de clúster que mejor se adapte a sus necesidades. + +En la mayoría de los casos de entornos de producción, optaremos por el tipo de "Grupos de nodos autoadministrados", ya que de esta manera tendremos un control total sobre los nodos trabajadores, pudiendo personalizarlos y gestionarlos de la manera que consideremos mejor. Ahora bien, si no desea preocuparse por la administración de los nodos trabajadores, puede optar por "Grupos de nodos administrados" o "Fargate". + +Cuando optamos por "Fargate", debemos tener en cuenta que no tendremos acceso a los nodos trabajadores, ya que son gestionados por AWS. Esto significa menos libertad y recursos, pero también menos preocupación y menos trabajo en la administración de los nodos trabajadores. + +Para nuestro ejemplo, elegiremos el tipo de "Grupos de nodos administrados", ya que de esta manera no tendremos que preocuparnos por la administración de los nodos trabajadores. Sin embargo, recuerde que puede elegir el tipo que mejor se adapte a sus necesidades. + +Para crear el clúster, utilizaremos EKSCTL, que es una herramienta de línea de comandos que nos ayuda a crear y gestionar clústeres EKS. Puede encontrar más información sobre EKSCTL [aquí](https://eksctl.io/). + +Se ha convertido en una de las formas oficiales de crear y gestionar clústeres EKS y es la herramienta que más utilizo para ello. De hecho, creo que es la herramienta más utilizada para crear clústeres EKS cuando no estamos utilizando una herramienta de infraestructura como código (IaC) como Terraform, por ejemplo. + +#### Instalación de EKSCTL + +Para instalar EKSCTL, puede seguir las instrucciones [aquí](https://eksctl.io/installation/). + +Está disponible para Linux, MacOS y Windows. También es posible ejecutarlo en un contenedor Docker. + +En nuestro ejemplo, vamos a utilizar Linux, ¡por supuesto! jajaja + +Para instalar EKSCTL en Linux, puede ejecutar el siguiente comando: + +```bash +# for ARM systems, set ARCH to: `arm64`, `armv6` or `armv7` +ARCH=amd64 +PLATFORM=$(uname -s)_$ARCH + +curl -sLO "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_$PLATFORM.tar.gz" + +# (Optional) Verify checksum +curl -sL "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_checksums.txt" | grep $PLATFORM | sha256sum --check + +tar -xzf eksctl_$PLATFORM.tar.gz -C /tmp && rm eksctl_$PLATFORM.tar.gz + +sudo mv /tmp/eksctl /usr/local/bin +``` + +Literalmente copié y pegué el comando anterior del sitio web de EKSCTL, así que no hay margen de error. Sin embargo, recuerde siempre consultar el sitio oficial para asegurarse de que no haya habido cambios. + +Aquí estamos haciendo lo siguiente: + +- Definiendo la arquitectura de nuestro sistema, en mi caso, `amd64`. Puede verificar la arquitectura de su sistema ejecutando el comando `uname -m`. +- Definiendo la plataforma de nuestro sistema, en mi caso, `Linux_amd64`. +- Descargando el binario de EKSCTL. +- Descomprimiendo el binario de EKSCTL. +- Moviendo el binario de EKSCTL al directorio `/usr/local/bin`. + +Validación de la instalación de EKSCTL: + +```bash +eksctl version +``` + +La salida debe ser algo similar a esto: + +```bash +0.169.0 +``` + +Esta es la versión de EKSCTL que estamos utilizando en el momento de la creación de este curso, pero es posible que esté utilizando una versión más reciente. + +#### Instalación de AWS CLI + +Ahora que tenemos EKSCTL instalado, necesitamos tener AWS CLI instalado y configurado, ya que EKSCTL utiliza AWS CLI para comunicarse con AWS. Puede encontrar más información sobre AWS CLI [aquí](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html). + +AWS CLI es una herramienta de línea de comandos que nos ayuda a interactuar con los servicios de AWS. Es muy poderosa y una de las herramientas más utilizadas para interactuar con los servicios de AWS. + +Aquí están los comandos para instalar AWS CLI en Linux, pero recuerde que siempre es bueno consultar el sitio web oficial para verificar si ha habido algún cambio. + +```bash +curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" +unzip awscliv2.zip +sudo ./aws/install +``` + +Validación de la instalación de AWS CLI: + +```bash +aws --version +``` + +En mi caso, la versión que estoy utilizando es la siguiente: + +```bash +aws-cli/2.15.10 Python/3.11.6 Linux/6.5.0-14-generic exe/x86_64.zorin.17 prompt/off +``` + +Ahora que tenemos AWS CLI instalado, necesitamos configurar AWS CLI. Para hacerlo, puede ejecutar el siguiente comando: + +```bash +aws configure +``` + +Aquí deberá proporcionar sus credenciales de AWS, que puede encontrar [aquí](https://console.aws.amazon.com/iam/home?#/security_credentials). + +La información que debe proporcionar incluye: + +- AWS Access Key ID +- AWS Secret Access Key +- Default region name +- Default output format + +Su Access Key ID y Secret Access Key se pueden encontrar [aquí](https://console.aws.amazon.com/iam/home?#/security_credentials). Luego, la región es a su elección; yo usaré la región `us-east-1`, pero puede elegir la región que prefiera. Finalmente, el formato de salida, yo usaré el formato `json`, pero puede elegir otra opción, como `text`, por ejemplo. + +##### Creación del Cluster EKS + +Ahora que tenemos AWS CLI instalado y configurado, podemos crear nuestro cluster EKS. + +Podemos crearlo solo a través de la línea de comandos o podemos crear un archivo de configuración para facilitar la creación del cluster. + +Primero proporcionaré el comando que utilizaremos y luego explicaré lo que estamos haciendo y proporcionaré el archivo de configuración. + +```bash +eksctl create cluster --name=eks-cluster --version=1.28 --region=us-east-1 --nodegroup-name=eks-cluster-nodegroup --node-type=t3.medium --nodes=2 --nodes-min=1 --nodes-max=3 --managed +``` + +Aquí estamos haciendo lo siguiente: + +- `eksctl create cluster`: Comando para crear el cluster. +- `--name`: Nombre del cluster. +- `--version`: Versión de Kubernetes que utilizaremos, en mi caso, `1.28`. +- `--region`: Región donde se creará el cluster, en mi caso, `us-east-1`. +- `--nodegroup-name`: Nombre del grupo de nodos. +- `--node-type`: Tipo de instancia que utilizaremos para los nodos workers, en mi caso, `t3.medium`. +- `--nodes`: Cantidad de nodos workers que crearemos, en mi caso, `2`. +- `--nodes-min`: Cantidad mínima de nodos workers que crearemos, en mi caso, `1`. +- `--nodes-max`: Cantidad máxima de nodos workers que crearemos, en mi caso, `3`. +- `--managed`: Tipo de grupo de nodos que utilizaremos, en mi caso, `managed`. + +La salida del comando debería verse algo como esto: + +```bash +2024-01-26 16:12:39 [ℹ] eksctl version 0.168.0 +2024-01-26 16:12:39 [ℹ] using region us-east-1 +2024-01-26 16:12:40 [ℹ] skipping us-east-1e from selection because it doesn't support the following instance type(s): t3.medium +2024-01-26 16:12:40 [ℹ] setting availability zones to [us-east-1c us-east-1d] +2024-01-26 16:12:40 [ℹ] subnets for us-east-1c - public:192.168.0.0/19 private:192.168.64.0/19 +2024-01-26 16:12:40 [ℹ] subnets for us-east-1d - public:192.168.32.0/19 private:192.168.96.0/19 +2024-01-26 16:12:40 [ℹ] nodegroup "eks-cluster-nodegroup" will use "" [AmazonLinux2/1.28] +2024-01-26 16:12:40 [ℹ] using Kubernetes version 1.28 +2024-01-26 16:12:40 [ℹ] creating EKS cluster "eks-cluster" in "us-east-1" region with managed nodes +2024-01-26 16:12:40 [ℹ] will create 2 separate CloudFormation stacks for cluster itself and the initial managed nodegroup +2024-01-26 16:12:40 [ℹ] if you encounter any issues, check CloudFormation console or try 'eksctl utils describe-stacks --region=us-east-1 --cluster=eks-cluster' +2024-01-26 16:12:40 [ℹ] Kubernetes API endpoint access will use default of {publicAccess=true, privateAccess=false} for cluster "eks-cluster" in "us-east-1" +2024-01-26 16:12:40 [ℹ] CloudWatch logging will not be enabled for cluster "eks-cluster" in "us-east-1" +2024-01-26 16:12:40 [ℹ] you can enable it with 'eksctl utils update-cluster-logging --enable-types={SPECIFY-YOUR-LOG-TYPES-HERE (e.g. all)} --region=us-east-1 --cluster=eks-cluster' +2024-01-26 16:12:40 [ℹ] +2 sequential tasks: { create cluster control plane "eks-cluster", + 2 sequential sub-tasks: { + wait for control plane to become ready, + create managed nodegroup "eks-cluster-nodegroup", + } +} +2024-01-26 16:12:40 [ℹ] building cluster stack "eksctl-eks-cluster-cluster" +2024-01-26 16:12:40 [ℹ] deploying stack "eksctl-eks-cluster-cluster" +2024-01-26 16:13:10 [ℹ] waiting for CloudFormation stack "eksctl-eks-cluster-cluster" +2024-01-26 16:13:41 [ℹ] waiting for CloudFormation stack "eksctl-eks-cluster-cluster" +2024-01-26 16:14:41 [ℹ] waiting for CloudFormation stack "eksctl-eks-cluster-cluster" +2024-01-26 16:24:48 [ℹ] building managed nodegroup stack "eksctl-eks-cluster-nodegroup-eks-cluster-nodegroup" +2024-01-26 16:24:49 [ℹ] deploying stack "eksctl-eks-cluster-nodegroup-eks-cluster-nodegroup" +2024-01-26 16:24:49 [ℹ] waiting for CloudFormation stack "eksctl-eks-cluster-nodegroup-eks-cluster-nodegroup" +2024-01-26 16:27:40 [ℹ] waiting for the control plane to become ready +2024-01-26 16:27:40 [✔] saved kubeconfig as "/home/jeferson/.kube/config" +2024-01-26 16:27:40 [ℹ] no tasks +2024-01-26 16:27:40 [✔] all EKS cluster resources for "eks-cluster" have been created +2024-01-26 16:27:41 [ℹ] nodegroup "eks-cluster-nodegroup" has 2 node(s) +2024-01-26 16:27:41 [ℹ] node "ip-192-168-55-232.ec2.internal" is ready +2024-01-26 16:27:41 [ℹ] node "ip-192-168-7-245.ec2.internal" is ready +2024-01-26 16:27:41 [ℹ] waiting for at least 1 node(s) to become ready in "eks-cluster-nodegroup" +2024-01-26 16:27:41 [ℹ] nodegroup "eks-cluster-nodegroup" has 2 node(s) +2024-01-26 16:27:41 [ℹ] node "ip-192-168-55-232.ec2.internal" is ready +2024-01-26 16:27:41 [ℹ] node "ip-192-168-7-245.ec2.internal" is ready +2024-01-26 16:27:42 [ℹ] kubectl command should work with "/home/jeferson/.kube/config", try 'kubectl get nodes' +2024-01-26 16:27:42 [✔] EKS cluster "eks-cluster" in "us-east-1" region is ready +``` + +¡Cluster de EKS creado con éxito! :D + +Para visualizar nuestro cluster, podemos ejecutar el siguiente comando: + +```bash +kubectl get nodes +``` + +La salida debería verse algo como esto: + +```bash +ip-192-168-22-217.ec2.internal Ready 20m v1.28.5-eks-5e0fdde +ip-192-168-50-0.ec2.internal Ready 20m v1.28.5-eks-5e0fdde +``` + +Ahora, vamos a crear un archivo de configuración para EKSCTL que facilitará la creación del cluster la próxima vez. Para hacerlo, vamos a crear un archivo llamado `eksctl.yaml` y agregar el siguiente contenido: + +```yaml +apiVersion: eksctl.io/v1alpha5 # Versión de la API de EKSCTL +kind: ClusterConfig # Tipo de recurso que estamos creando + +metadata: # Metadatos del recurso + name: eks-cluster # Nombre del cluster + region: us-east-1 # Región donde se creará el cluster + +managedNodeGroups: # Grupos de nodos que se crearán, estamos utilizando el tipo Managed Node Groups +- name: eks-cluster-nodegroup # Nombre del grupo de nodos + instanceType: t3.medium # Tipo de instancia que utilizaremos para los nodos workers + desiredCapacity: 2 # Cantidad de nodos workers que crearemos + minSize: 1 # Cantidad mínima de nodos workers que crearemos + maxSize: 3 # Cantidad máxima de nodos workers que crearemos +``` + +Como puedes ver, estamos creando un cluster EKS con la misma configuración que utilizamos anteriormente, pero ahora estamos utilizando un archivo de configuración para hacerlo más fácil y ordenado. :D + +Para crear el cluster utilizando el archivo de configuración, puedes ejecutar el siguiente comando: + +```bash +eksctl create cluster -f eksctl.yaml +``` + +La salida debería ser similar a la que obtuvimos anteriormente, no hay nada nuevo que agregar aquí. + +Ahora que tenemos nuestro cluster de EKS creado, vamos a instalar el CNI de AWS y habilitar la Network Policy en la configuración avanzada del CNI. + +##### Instalando el complemento AWS VPC CNI + +El complemento AWS VPC CNI es un complemento de red que permite que los Pods se comuniquen entre sí y con los servicios dentro del clúster. También permite que los Pods se comuniquen con servicios fuera del clúster, como Amazon S3, por ejemplo. + +Usaremos EKSCTL para instalar el complemento AWS VPC CNI. Para hacerlo, puedes ejecutar el siguiente comando: + +```bash +eksctl create addon --name vpc-cni --version v1.16.0-eksbuild.1 --cluster eks-cluster --force +``` + +Recuerda que debes reemplazar el nombre del clúster y la versión del CNI por la versión de tu clúster. + +Puedes consultar el enlace a continuación para verificar la versión del CNI que debes usar: + + + +Debes elegir la versión del CNI de acuerdo con la versión de Kubernetes que estás utilizando, así que tenlo en cuenta. + +Bueno, volviendo al comando, lo que estamos haciendo aquí es lo siguiente: + +- `eksctl create addon`: Comando para instalar un complemento en el clúster. +- `--name`: Nombre del complemento. +- `--version`: Versión del complemento. +- `--cluster`: Nombre del clúster. +- `--force`: Forzar la instalación del complemento. + +La salida debería verse algo como esto: + +```bash +2024-01-28 14:12:44 [!] no IAM OIDC provider associated with cluster, try 'eksctl utils associate-iam-oidc-provider --region=us-east-1 --cluster=eks-cluster' +2024-01-28 14:12:44 [ℹ] Kubernetes version "1.28" in use by cluster "eks-cluster" +2024-01-28 14:12:44 [!] OIDC is disabled but policies are required/specified for this addon. Users are responsible for attaching the policies to all nodegroup roles +2024-01-28 14:12:45 [ℹ] creating addon +2024-01-28 14:13:49 [ℹ] addon "vpc-cni" active +``` + +A pesar de ser el CNI predeterminado de EKS, no se instala por defecto, por lo que debemos instalarlo manualmente. + +Si deseas ver los complementos instalados en tu clúster, puedes ejecutar el siguiente comando: + +```bash +eksctl get addon --cluster eks-cluster +``` + +La salida debería verse algo como esto: + +```bash +2024-01-28 14:16:44 [ℹ] Kubernetes version "1.28" in use by cluster "eks-cluster" +2024-01-28 14:16:44 [ℹ] getting all addons +2024-01-28 14:16:45 [ℹ] to see issues for an addon run `eksctl get addon --name --cluster ` +NAME VERSION STATUS ISSUES IAMROLE UPDATE AVAILABLE CONFIGURATION VALUES +vpc-cni v1.16.0-eksbuild.1 ACTIVE 0 v1.16.2-eksbuild.1 +``` + +O puedes acceder a la consola de AWS y verificar los complementos instalados en tu clúster, como se muestra en la siguiente imagen: + +![Imagen](images/image-1.png?raw=true "EKS Cluster") + +¡Listo, el CNI se ha instalado con éxito! :D + +##### Habilitación de Network Policy en las Configuraciones Avanzadas del CNI + +Ahora que tenemos el CNI de AWS instalado, debemos habilitar la Network Policy en las configuraciones avanzadas del CNI. Para hacerlo, debemos acceder a la consola de AWS y seguir los siguientes pasos: + +- Acceder a la consola de AWS. +- Acceder al servicio EKS. +- Seleccionar su clúster. +- Seleccionar la pestaña `Add-ons` (Complementos). +- Hacer clic en Edit en el Addon `vpc-cni`. +- Configuración Avanzada del CNI. +- Habilitar el Network Policy. + +![Alt text](images/image-2.png?raw=true "Clúster de EKS") + +Después de algunos minutos, puede volver a acceder al Addon `vpc-cni` y verificar si la Network Policy está habilitada y actualizada con el Network Policy habilitado. + +![Alt text](images/image-3.png?raw=true "Clúster de EKS") + +¡Listo, el clúster está configurado! Ahora podemos continuar con nuestro ejemplo. :D + +#### Instalación del Controlador de Ingress Nginx + +### Instalando un Controlador de Ingress Nginx + +Para que todo funcione correctamente en nuestro ejemplo, debemos instalar el Controlador de Ingress Nginx. Es importante tener en cuenta la versión del Controlador de Ingress que está instalando, ya que las versiones más recientes o más antiguas pueden no ser compatibles con la versión de Kubernetes que está utilizando. Para este tutorial, utilizaremos la versión 1.9.5. + +En su terminal, ejecute los siguientes comandos: + +```bash +kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.9.5/deploy/static/provider/cloud/deploy.yaml +``` + +Verifique si el Controlador de Ingress se ha instalado correctamente: + +```bash +kubectl get pods -n ingress-nginx +``` + +También puede usar la opción `wait` de `kubectl`, que esperará hasta que los pods estén listos antes de liberar la terminal. Vea: + +```bash +kubectl wait --namespace ingress-nginx \ + --for=condition=ready pod \ + --selector=app.kubernetes.io/component=controller \ + --timeout=90s +``` + +¡Listo, el Controlador de Ingress se ha instalado correctamente! :D + +Ahora continuemos y creemos nuestra aplicación de ejemplo. + +#### Nuestra Aplicación de Ejemplo + +Para demostrar el funcionamiento de las Network Policies, utilizaremos una aplicación de ejemplo llamada "Giropops-Senhas". Esta aplicación consta de una aplicación Flask que utiliza Redis para almacenar las últimas contraseñas generadas. La aplicación Flask utiliza el puerto 5000, mientras que Redis utiliza el puerto 6379. + +Para permitir que los usuarios accedan a nuestro clúster, la aplicación se expone a través de un Controlador de Ingress configurado con la dirección `giropops-senhas.containers.expert`. Redis se expone a través de un Service con tipo ClusterIP configurado con la dirección `redis-service.giropops.svc.cluster.local`. La dirección interna de nuestra aplicación dentro del clúster es `giropops.giropops.svc.cluster.local`. Como puede ver, tenemos tres direcciones diferentes para nuestra aplicación, cada una con un propósito diferente. + +Recuerde que nuestra aplicación se ejecuta en el espacio de nombres `giropops`. + +Para implementar nuestra aplicación, cree un archivo llamado `giropops-deployment.yaml` con el siguiente contenido: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: giropops-senhas + name: giropops-senhas +spec: + replicas: 2 + selector: + matchLabels: + app: giropops-senhas + template: + metadata: + labels: + app: giropops-senhas + spec: + containers: + - image: linuxtips/giropops-senhas:1.0 + name: giropops-senhas + ports: + - containerPort: 5000 + imagePullPolicy: Always +``` + +E para crear nuestro Service, crearemos un archivo llamado `giropops-service.yaml` con el siguiente contenido: + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: giropops-senhas +spec: + selector: + app: giropops-senhas + ports: + - protocol: TCP + port: 5000 + targetPort: 5000 + type: ClusterIP +``` + +Necesitamos el servicio Redis, que vamos a crear con el archivo `redis-deployment.yaml`: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: redis + name: redis-deployment +spec: + replicas: 1 + selector: + matchLabels: + app: redis + template: + metadata: + labels: + app: redis + spec: + containers: + - image: redis + name: redis + ports: + - containerPort: 6379 + resources: + limits: + memory: "256Mi" + cpu: "500m" + requests: + memory: "128Mi" + cpu: "250m" +``` + +Y el servicio de Redis lo crearemos con el archivo `redis-service.yaml`: + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: redis-service +spec: + selector: + app: redis + ports: + - protocol: TCP + port: 6379 + targetPort: 6379 + type: ClusterIP +``` + +Finalmente, crearemos nuestro controlador de Ingress con el archivo `giropops-ingress.yaml`: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: giropops-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / +spec: + ingressClassName: nginx + rules: + - host: giropops-senhas.containers.expert + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: giropops-senhas + port: + number: 5000 +``` + +Crearemos el espacio de nombres (namespace) `giropops` utilizando el siguiente comando: + +```bash +kubectl create namespace giropops +``` + +Listo, ahora que tenemos todos los archivos necesarios, desplegaremos nuestra aplicación con los siguientes comandos: + +```bash +kubectl apply -f giropops-deployment.yaml -n giropops +kubectl apply -f giropops-service.yaml -n giropops +kubectl apply -f redis-deployment.yaml -n giropops +kubectl apply -f redis-service.yaml -n giropops +kubectl apply -f giropops-ingress.yaml -n giropops +``` + +Verifiquemos si nuestra aplicación se está ejecutando correctamente: + +```bash +kubectl get pods -n giropops +``` + +Asegúrese de que los servicios y el controlador de Ingress estén funcionando correctamente: + +```bash +kubectl get svc -n giropops +kubectl get ingress -n giropops +``` + +Parece que todo funciona correctamente. Probemos nuestra aplicación: + +```bash +curl giropops-senhas.containers.expert +``` + +Recuerde que la dirección `giropops-senhas.containers.expert` solo funcionará en mi ejemplo, ya que ya tengo la configuración DNS para esta dirección. Para probar su aplicación, deberá agregar la dirección de su aplicación en el archivo `/etc/hosts` de su computadora. Para hacerlo, agregue su dirección IP y la dirección `giropops-senhas.containers.expert` al archivo `/etc/hosts`. Por ejemplo: + +```bash +192.168.100.10 giropops-senhas.containers.expert +``` + +### Creación de Reglas de Política de Red + +#### Ingress + +En nuestro ejemplo, tanto nuestra aplicación como Redis se están ejecutando en el mismo espacio de nombres, el espacio de nombres `giropops`. Por defecto, los Pods pueden comunicarse libremente entre sí. Vamos a crear una Política de Red para restringir el acceso a Redis, permitiendo que solo los Pods del espacio de nombres `giropops` puedan acceder a Redis. + +Para hacerlo, creemos el archivo `permitir-redis-somente-mesmo-ns.yaml` con el siguiente contenido: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: redis-allow-same-namespace + namespace: giropops +spec: + podSelector: + matchLabels: + app: redis + ingress: + - from: + - podSelector: {} +``` + +Vamos a entender lo que estamos haciendo aquí: + +- `apiVersion`: La versión de la API que estamos utilizando. +- `kind`: El tipo de recurso que estamos creando. +- `metadata`: Metadatos del recurso. + - `name`: El nombre de la Política de Red. + - `namespace`: El espacio de nombres donde se creará la Política de Red. +- `spec`: La especificación de la Política de Red. + - `podSelector`: El selector de Pods que se verán afectados por la Política de Red. + - `matchLabels`: Las etiquetas de los Pods que se verán afectadas por la Política de Red. + - `ingress`: Las reglas de entrada. + - `from`: El origen del tráfico. + - `podSelector`: El selector de Pods que pueden acceder a los Pods seleccionados, en este caso, todos los Pods del espacio de nombres `giropops`. + +Siempre que vea `{}`, significa que estamos seleccionando todos los Pods que cumplen con los criterios especificados, en este caso, todos los Pods del espacio de nombres `giropops`, ya que no estamos especificando ningún criterio adicional. + +Vamos a aplicar nuestra Política de Red: + +```bash +kubectl apply -f permitir-redis-somente-mesmo-ns.yaml -n giropops +``` + +Vamos a probar el acceso a Redis desde un Pod fuera del espacio de nombres `giropops`, para ello utilizaremos el comando `redis ping`: + +```bash +kubectl run -it --rm --image redis redis-client -- redis-cli -h redis-service.giropops.svc.cluster.local ping +``` + +Si todo está funcionando correctamente, no recibirás ninguna respuesta ya que el acceso a Redis está bloqueado para los Pods fuera del espacio de nombres `giropops`. + +Ahora, si ejecutas el mismo comando desde dentro del espacio de nombres `giropops`, deberías recibir el mensaje `PONG`, ya que el acceso a Redis está permitido para los Pods dentro del espacio de nombres `giropops`. :D + +Vamos a probarlo: + +```bash +kubectl run -it --rm -n giropops --image redis redis-client -- redis-cli -h redis-service.giropops.svc.cluster.local ping +``` + +La salida debe ser algo similar a esto: + +```bash +If you don't see a command prompt, try pressing enter. + +PONG +Session ended, resume using 'kubectl attach redis-client -c redis-client -i -t' command when the pod is running +pod "redis-client" deleted +``` + +Listo, ahora que nuestra Política de Red está funcionando. + +Ahora, queremos bloquear todo el acceso de entrada a los Pods en el espacio de nombres `giropops`. Para ello, crearemos el archivo `nao-permitir-nada-externo.yaml` con el siguiente contenido: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-same-ns + namespace: giropops +spec: + podSelector: {} + policyTypes: + - Ingress + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: giropops +``` + +Listo, ahora que nuestra Política de Red está funcionando. + +Ahora deseamos bloquear todo el acceso de entrada a los Pods del espacio de nombres `giropops`. Para ello, crearemos el archivo `nao-permitir-nada-externo.yaml` con el siguiente contenido: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-same-ns + namespace: giropops +spec: + podSelector: {} + policyTypes: + - Ingress + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: giropops +``` + +Lo que ha cambiado aquí es lo siguiente: + +- `policyTypes`: Tipo de política que estamos creando, en este caso, estamos creando una política de entrada. +- `ingress`: Reglas de entrada. + - `from`: Origen del tráfico. + - `namespaceSelector`: Selector de Espacios de nombres que pueden acceder a los Pods seleccionados, en este caso, solo el espacio de nombres `giropops`. + - `matchLabels`: Etiquetas de los Espacios de nombres que pueden acceder a los Pods seleccionados, en este caso, solo el espacio de nombres `giropops`. + - `kubernetes.io/metadata.name`: Nombre del Espacio de nombres. + - `giropops`: Valor del Nombre del Espacio de nombres. + +De esta manera, estamos bloqueando todo el tráfico de entrada a los Pods del espacio de nombres `giropops`, excepto para los Pods del propio espacio de nombres `giropops`. + +Aplicaremos nuestra Política de Red de la siguiente manera: + +```bash +kubectl apply -f nao-permitir-nada-externo.yaml -n giropops +``` + +Vamos probar el acceso a Redis desde un Pod fuera del espacio de nombres `giropops` utilizando el comando `redis ping`: + +```bash +kubectl run -it --rm --image redis redis-client -- redis-cli -h redis-service.giropops.svc.cluster.local ping +``` + +Nada nuevo hasta ahora, ¿verdad? Sin embargo, vamos a probar el acceso a nuestra aplicación desde un Pod fuera del espacio de nombres `giropops` utilizando el comando `curl`: + +```bash +kubectl run -it --rm --image curlimages/curl curl-client -- curl giropops-senhas.giropops.svc +``` + +Si todo funciona correctamente, no recibirás ninguna respuesta, ya que el acceso a nuestra aplicación está bloqueado para Pods fuera del espacio de nombres `giropops`. + +Ahora, si ejecutas el mismo comando desde dentro del espacio de nombres `giropops`, deberías recibir el mensaje `Giropops Senhas`, ya que el acceso a nuestra aplicación está permitido para los Pods dentro del espacio de nombres `giropops`. ¡Probemoslo! + +```bash +kubectl run -it --rm -n giropops --image curlimages/curl curl-client -- curl giropops-senhas.giropops.svc +``` + +Todo funciona de manera excelente. Desde el mismo espacio de nombres, podemos acceder a nuestra aplicación y a Redis, pero desde fuera del espacio de nombres, ¡no podemos acceder a nada! :D + +Sin embargo, surge un problema: nuestro controlador de ingreso (Ingress Controller) no puede acceder a nuestra aplicación porque se encuentra fuera del espacio de nombres `giropops`. Así que vamos a crear una Política de red para permitir el acceso a nuestro Controlador de Ingreso. + +Para ello, crearemos el archivo `permitir-ingress-controller.yaml` con el siguiente contenido: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-same-ns-and-ingress-controller + namespace: giropops +spec: + podSelector: {} + policyTypes: + - Ingress + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: ingress-nginx + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: giropops +``` + +Aquí, la solución fue muy simple: simplemente agregamos un selector de espacios de nombres adicional para permitir el acceso a nuestro Controlador de Ingreso. Con esto, todo lo que esté dentro del espacio de nombres `ingress-nginx` y `giropops` podrá acceder a los Pods del espacio de nombres `giropops`. + +Podríamos mejorar el código utilizando `matchExpressions`, así: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-same-ns-and-ingress-controller + namespace: giropops +spec: + podSelector: {} + policyTypes: + - Ingress + ingress: + - from: + - namespaceSelector: + matchExpressions: + - key: kubernetes.io/metadata.name + operator: In + values: ["ingress-nginx", "giropops"] +``` + +El resultado sería el mismo, pero el código estaría más limpio y sería más fácil de entender. + +Ahora puedes probar el acceso a nuestra aplicación desde un Pod fuera del espacio de nombres `giropops` utilizando el comando `curl`: + +```bash +kubectl run -it --rm --image curlimages/curl curl-client -- curl giropops-senhas.giropops.svc +``` + +Aquí no podrás acceder a nuestra aplicación porque el acceso está bloqueado para Pods fuera del espacio de nombres `giropops`. Sin embargo, si ejecutas el mismo comando desde el espacio de nombres `giropops`, todo funcionará correctamente. + +Sin embargo, siempre que utilices la dirección de ingreso (Ingress) de nuestra aplicación, podrás acceder normalmente, ya que hemos permitido el acceso a nuestro Controlador de Ingreso. Por lo tanto, los clientes de nuestra aplicación que accedan desde Internet podrán hacerlo con normalidad, pero los Pods fuera del espacio de nombres `giropops` no podrán acceder a nuestra aplicación. ¿No es genial? :D + +Solo una nota importante: + +```yaml + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: ingress-nginx + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: giropops +``` + +Una cosa que debes comprender claramente al crear tus reglas son los operadores lógicos, ya que pueden cambiar por completo el resultado de tu Política de red. En nuestro ejemplo, estamos utilizando el operador lógico `OR`, es decir, estamos permitiendo el acceso a nuestro Controlador de Ingreso O a nuestro espacio de nombres `giropops`. + +Si deseas permitir el acceso tanto a nuestro Ingress Controller COMO a nuestro namespace `giropops`, debes utilizar el operador lógico `AND`, como se muestra a continuación: + +```yaml + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: ingress-nginx + namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: giropops +``` + +En este caso, la regla funcionará de la siguiente manera: solo los Pods que estén en el espacio de nombres `ingress-nginx` Y en el espacio de nombres `giropops` podrán acceder a los Pods del espacio de nombres `giropops`. Esto podría causar problemas. + +Puedes probarlo y ver qué sucede. :D + +Podemos seguir un enfoque diferente, donde primero bloqueamos todo el tráfico de entrada y luego creamos reglas para permitir el tráfico de entrada a los Pods que lo necesitan. Observa: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: default-deny-all +spec: + podSelector: {} + policyTypes: + - Ingress + - Egress +``` + +En este caso, bloqueamos completamente el tráfico de entrada para los Pods en el espacio de nombres `giropops`. Esto se logra utilizando `ingress: []` para bloquear todo el tráfico de entrada. Nuevamente, utilizamos `[]` vacío para seleccionar todos los Pods y bloquear todo el tráfico de entrada, ya que no especificamos ningún criterio. + +El campo `policyTypes` es obligatorio, y en él debes especificar el tipo de política que estás creando. En este caso, estamos creando una política que afecta tanto al tráfico de entrada (Ingress) como al tráfico de salida (Egress). + +Vamos aplicar estas reglas: + +```bash +kubectl apply -f deny-all-ingress.yaml -n giropops +kubectl apply -f allow-redis-app-only.yaml -n giropops +``` + +Ahora, vamos crear una regla para permitir que nuestra aplicación acceda al Redis. Observa: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-redis-app-only + namespace: giropops +spec: + podSelector: + matchLabels: + app: redis + policyTypes: + - Ingress + ingress: + - from: + - podSelector: + matchLabels: + app: giropops-senhas + namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: giropops + ports: + - protocol: TCP + port: 6379 +``` + +Con esto, hemos creado una regla adicional que permite el acceso entre nuestra aplicación y el Redis, pero solo entre ellos y solo en los puertos 6379 y 5000. + +Vamos aplicar esta regla: + +```bash +kubectl apply -f permitir-ingress-controller.yaml -n giropops +``` + +Hemos añadido otra capa de seguridad; ahora solo nuestra aplicación puede acceder al Redis, y solo en los puertos 6379 y 5000. Sin embargo, todavía enfrentamos un problema: nuestro Controlador de Ingreso no puede acceder a nuestra aplicación, lo que significa que nuestros clientes no podrán acceder a ella. Para solucionar esto, creemos una Network Policy para permitir el acceso a nuestro Controlador de Ingreso, como se muestra a continuación: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-ingress-controller + namespace: giropops +spec: + podSelector: {} + policyTypes: + - Ingress + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: ingress-nginx + ports: + - protocol: TCP + port: 5000 +``` + +Ahora, nuestro Controlador de Ingreso puede acceder a nuestra aplicación, y como resultado, nuestros clientes también pueden hacerlo. + +Vamos aplicar esta regla para permitir el acceso al DNS del clúster, lo que permitirá que los Pods de nuestra aplicación accedan al Redis sin problemas: + +```bash +kubectl apply -f permitir-acceso-dns.yaml -n giropops +``` + +Hemos resuelto un problema, ¡pero aún hay otro por resolver! + +Cuando creamos la regla de Egress que bloquea todo el tráfico de salida, también bloqueamos el tráfico de salida de todos los Pods en el espacio de nombres `giropops`. Esto significa que nuestro Pod de la aplicación no puede acceder al Redis. + +Para solucionar esto, creamos una Network Policy adicional para permitir el tráfico de salida hacia el Redis en el mismo espacio de nombres: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-egress-redis + namespace: giropops +spec: + podSelector: + matchLabels: {} + policyTypes: + - Egress + egress: + - to: + - podSelector: + matchLabels: + app: redis +``` + +Ahora, con estas reglas, creo que hemos resuelto todos los problemas y deberíamos poder acceder a nuestra aplicación y al Redis con normalidad. ¡Listo! :D + +Otra opción interesante que puedes utilizar es `ipBlock`, que te permite especificar una dirección IP o un CIDR para permitir el acceso. Aquí tienes un ejemplo: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: ip-block + namespace: giropops +spec: + podSelector: {} + policyTypes: + - Ingress + ingress: + - from: + - ipBlock: + cidr: 172.18.0.0/16 +``` + +Con la regla anterior, estamos permitiendo el acceso solo desde el rango de direcciones IP dentro del CIDR `172.18.0.0/16`. Esto significa que solo los Pods que estén dentro de ese rango de direcciones IP podrán acceder a los Pods en el espacio de nombres `giropops`. + +Todavía podemos agregar una regla de excepción, como se muestra a continuación: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: ip-block + namespace: giropops +spec: + policyTypes: + - Ingress + podSelector: {} + ingress: + - from: + - ipBlock: + cidr: 172.18.0.0/16 + except: + - 172.18.0.112/32 +``` + +Con la regla anterior, toda la red `172.18.0.0/16` tendrá acceso, excepto la IP `172.18.0.112`, que no tendrá acceso a los Pods en el espacio de nombres `giropops`. + +Hemos creado muchas Network Policies, pero no nos hemos centrado en cómo verificar si están creadas y en sus detalles. Así que veamos cómo hacerlo. + +Para ver las Network Policies creadas en tu clúster, puedes ejecutar el siguiente comando: + +```bash +kubectl get networkpolicies -n giropops +``` + +Para ver los detalles de una Network Policy en particular, puedes ejecutar el siguiente comando: + +```bash +kubectl describe networkpolicy -n giropops +``` + +Para eliminar una Network Policy, puedes ejecutar el siguiente comando: + +```bash +kubectl delete networkpolicy -n giropops +``` + +Es tan sencillo como volar, ¿verdad? + +#### Egress + +Hemos hablado mucho sobre cómo crear reglas de Ingress, es decir, reglas de entrada, pero ¿qué hay de las reglas de Egress? ¿Cómo podemos crear reglas de salida? + +Para esto, tenemos el `egress`, que es muy similar al `ingress`, pero con algunas diferencias, como se muestra a continuación: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-egress + namespace: giropops +spec: + podSelector: {} + policyTypes: + - Egress + egress: + - to: + - podSelector: + matchLabels: + app: redis + ports: + - protocol: TCP + port: 6379 +``` + +Con la regla anterior, estamos permitiendo el acceso a los Pods que cumplen con los criterios especificados, en este caso, solo los Pods que tengan la etiqueta `app: redis` podrán acceder a los Pods del espacio de nombres `giropops` en el puerto 6379. Con esto, todos los Pods del espacio de nombres `giropops` podrán acceder a los Pods que tengan la etiqueta `app: redis` en el puerto 6379. + +Ahora bien, si deseamos que solo nuestra aplicación pueda acceder a Redis, podemos hacer lo siguiente: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-egress-only-app + namespace: giropops +spec: + policyTypes: + - Egress + podSelector: + matchLabels: + app: giropops-senhas + egress: + - to: + - podSelector: + matchLabels: + app: redis + ports: + - protocol: TCP + port: 6379 +``` + +Con la regla anterior, solo nuestra aplicación podrá acceder a Redis, ya que estamos utilizando `podSelector` para seleccionar solo los Pods que tengan la etiqueta `app: giropops-senhas`, es decir, solo nuestra aplicación tendrá acceso a Redis. + +¡Es realmente sencillo! diff --git a/es/day-14/images/image-1.png b/es/day-14/images/image-1.png new file mode 100644 index 00000000..01ebd862 Binary files /dev/null and b/es/day-14/images/image-1.png differ diff --git a/es/day-14/images/image-2.png b/es/day-14/images/image-2.png new file mode 100644 index 00000000..2b4bef81 Binary files /dev/null and b/es/day-14/images/image-2.png differ diff --git a/es/day-14/images/image-3.png b/es/day-14/images/image-3.png new file mode 100644 index 00000000..38dd912a Binary files /dev/null and b/es/day-14/images/image-3.png differ diff --git a/es/day-15/README.md b/es/day-15/README.md new file mode 100644 index 00000000..7a3c0b06 --- /dev/null +++ b/es/day-15/README.md @@ -0,0 +1,642 @@ +# Simplificando Kubernetes + +## Día 15: Descomplicando RBAC e controle de acesso no Kubernetes + +## Contenido del Día 15 + +- [Simplificando Kubernetes](#simplificando-kubernetes) + - [Día 15: Descomplicando RBAC e controle de acesso no Kubernetes](#día-15-descomplicando-rbac-e-controle-de-acesso-no-kubernetes) + - [Contenido del Día 15](#contenido-del-día-15) +- [¿Qué vamos a aprender hoy?](#qué-vamos-a-aprender-hoy) +- [RBAC](#rbac) + - [¿Qué es RBAC?](#qué-es-rbac) + - [Primer ejemplo de RBAC](#primer-ejemplo-de-rbac) + - [Creación de un Usuario para Acceso al clúster](#creación-de-un-usuario-para-acceso-al-clúster) + - [Creando un Rol para nuestro usuario](#creando-un-rol-para-nuestro-usuario) + - [apiGroups](#apigroups) + - [Verbos](#verbos) + - [Agregando el certificado del usuario al kubeconfig](#agregando-el-certificado-del-usuario-al-kubeconfig) + - [Accediendo al clúster con el nuevo usuario](#accediendo-al-clúster-con-el-nuevo-usuario) + +# ¿Qué vamos a aprender hoy? + +Hoy hablaremos de... + +# RBAC + +## ¿Qué es RBAC? + +RBAC es un acrónimo que significa Control de Acceso Basado en Roles (Role-Based Access Control). Es un método de control de acceso que permite a un administrador definir permisos específicos para usuarios y grupos de usuarios. Esto significa que los administradores pueden controlar quién tiene acceso a qué recursos y qué pueden hacer con esos recursos. + +En Kubernetes, es fundamental comprender cómo funciona RBAC, ya que a través de él se definen los permisos de acceso a los recursos del clúster, como quién puede crear un Pod, un Deployment, un Service, entre otros. + +### Primer ejemplo de RBAC + +Supongamos que necesitamos dar acceso al clúster a un desarrollador de nuestra empresa, pero no queremos que tenga acceso a todos los recursos del clúster, sino solo a los recursos necesarios para desarrollar su aplicación. + +Para lograrlo, crearemos un usuario llamado `developer` y le daremos acceso para crear y administrar los Pods en el espacio de nombres `dev`. + +Existen dos formas de hacerlo. La primera y más antigua es mediante la creación de un Token de acceso, y la segunda y más nueva es mediante la creación de un usuario. + +#### Creación de un Usuario para Acceso al clúster + +Bueno, ahora que ya sabemos cuáles serán los permisos de nuestro nuevo usuario, podemos comenzar a crearlo. + +Lo primero que necesitamos hacer es generar una clave privada para nuestro usuario. Para ello, utilizaremos el comando `openssl`: + +```bash +openssl genrsa -out developer.key 2048 +``` + +Con el comando anterior, estamos creando una clave privada de 2048 bits y guardándola en el archivo `developer.key`. El parámetro `genrsa` indica que queremos generar una clave privada, y el parámetro `-out` indica el nombre del archivo en el que queremos guardar la clave. + +Una vez creada la clave, debemos generar una Solicitud de Firma de Certificado (Certificate Signing Request o CSR), que es un archivo que contiene el certificado que hemos creado y que se enviará a Kubernetes para que lo firme y genere el certificado final. + +```bash +openssl req -new -key developer.key -out developer.csr -subj "/CN=developer" +``` + +En el comando anterior, estamos creando un certificado para nuestro usuario utilizando la clave privada que creamos anteriormente. El parámetro `req` indica que queremos crear un certificado, el parámetro `-key` indica el nombre del archivo de la clave privada que queremos utilizar, el parámetro `-out` indica el nombre del archivo en el que queremos guardar el certificado, y el parámetro `-subj` indica el nombre del usuario que queremos crear. + +Ahora, con los dos archivos en mano, podemos comenzar a crear nuestro usuario en el clúster, pero antes, necesitamos crear una Solicitud de Firma de Certificado (Certificate Signing Request o CSR), que es un archivo que contiene el certificado que hemos creado y que se enviará a Kubernetes para que lo firme y genere el certificado final. + +Pero para crear el archivo, primero debemos tener el contenido del certificado en base64. Para ello, utilizaremos el comando `base64`: + +```bash +cat developer.csr | base64 | tr -d '\n' +``` + +Con el comando anterior, estamos leyendo el contenido del archivo `developer.csr`, convirtiéndolo a base64 y eliminando el salto de línea. + +El contenido del certificado en base64 será algo similar a esto: + +```bash +LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1dUQ0NBVUVDQVFBd0ZERVNNQkFHQTFVRUF3d0paR1YyWld4dmNHVnlNSUlCSWpBTkJna3Foa2lHOXcwCgpBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF5OFN1Y25JWjJjL0k3dXQvS0EwSXhvN0RZa0hkSUxrbmxZOWNwMkVlClJJSzRzU1NzZnA2SzBhbWZlYWtRaEdXT2NWMmFaeEtTM0xrNERNNlVmb3ZucEQvOXpidDl0em44UUpMTDZxREEKeHFxbzVSbEt4QnpEV3lQT2JkUStMWnI2VjFQZ2wxYms2c3o0d2lWek52a2NhT0doSDdlSU90QVI0U096MjNJdAowZ0xiZHBDalFITFIvNlFuSXBjY3h3bDBGa1FtL3RVeHdRa0x1NXNpSTNKOGRiUkQwcnlFdGxReWQ5elhLM29rCjBRbVpLZDVpV1p2aDU3R1lrV1kweGMzV0J5aXY5OURQYVE3WTB4MFNaWGlPL2w0bTRzazJ3RjYwa2dUa1NJZmQKdEMxN2Y1ZzVWVzhOTW02amNpMFRXeDk5Z0REcmpHanJpaExHeTBLUWdRa2p3d0lEQVFBQm9BQXdEUVlKS29aSQpodmNOQVFFTEJRQURnZ0VCQUllZVdLbjAwZkk5ekw3MUVQNFNpOUVxVUFNUnBYT0dkT1Aybm8rMTV2VzJ5WmpwCmhsTWpVTjMraVZubkh2QVBvWFVLKzBYdXdmaklHMjBQTjA5UEd1alU4aUFIeVZRbFZRS0VaOWpRcENXYnQybngKVlZhYUw0N0tWMUpXMnF3M1YybmNVNkhlNHdtQzVqUE9vU29vVGtrVlF5Uml4bkcyVVQrejI3M2xpaTY3RkFXegpBZ1QvczlVa3gvS1dxRjIzczVuUk9TTlZUS2xCSG5LMU40YkN6RHBqZnN5V01GUXdnazhxRCtlOXp0cTh2c1VhCi9Say9jUWNyS2wxVDMyM0xDcG1TekhnM3hDdjFqdzJUVFFINm1yWlBBa2doa2R2YlNnalp6Y1JRZWNqSEpNeTMKTzFJQXJ6V3pWbU1hRTJqeGhUV1JwbkJkcVZjZERTUERiNkNXaktVPQotLS0tLUVORCBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0K% +``` + +Recuerda eliminar el salto de línea al final del archivo, que se representa con el `%`. + +Agora que tenemos el contenido del certificado en base64, cópielo y péguelo en el archivo `developer.yaml` que vamos a crear a continuación: + +```yaml +apiVersion: certificates.k8s.io/v1 +kind: CertificateSigningRequest +metadata: + name: developer +spec: + request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1dUQ0NBVUVDQVFBd0ZERVNNQkFHQTFVRUF3d0paR1YyWld4dmNHVnlNSUlCSWpBTkJna3Foa2lHOXcwQgpBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF5OFN1Y25JWjJjL0k3dXQvS0EwSXhvN0RZa0hkSUxrbmxZOWNwMkVlClJJSzRzU1NzZnA2SzBhbWZlYWtRaEdXT2NWMmFaeEtTM0xrNERNNlVmb3ZucEQvOXpidDl0em44UUpMTDZxREEKeHFxbzVSbEt4QnpEV3lQT2JkUStMWnI2VjFQZ2wxYms2c3o0d2lWek52a2NhT0doSDdlSU90QVI0U096MjNJdAowZ0xiZHBDalFITFIvNlFuSXBjY3h3bDBGa1FtL3RVeHdRa0x1NXNpSTNKOGRiUkQwcnlFdGxReWQ5elhLM29rCjBRbVpLZDVpV1p2aDU3R1lrV1kweGMzV0J5aXY5OURQYVE3WTB4MFNaWGlPL2w0bTRzazJ3RjYwa2dUa1NJZmQKdEMxN2Y1ZzVWVzhOTW02amNpMFRXeDk5Z0REcmpHanJpaExHeTBLUWdRa2p3d0lEQVFBQm9BQXdEUVlKS29aSQpodmNOQVFFTEJRQURnZ0VCQUllZVdLbjAwZkk5ekw3MUVQNFNpOUVxVUFNUnBYT0dkT1Aybm8rMTV2VzJ5WmpwCmhsTWpVTjMraVZubkh2QVBvWFVLKzBYdXdmaklHMjBQTjA5UEd1alU4aUFIeVZRbFZRS0VaOWpRcENXYnQybngKVlZhYUw0N0tWMUpXMnF3M1YybmNVNkhlNHdtQzVqUE9vU29vVGtrVlF5Uml4bkcyVVQrejI3M2xpaTY3RkFXegpBZ1QvczlVa3gvS1dxRjIzczVuUk9TTlZUS2xCSG5LMU40YkN6RHBqZnN5V01GUXdnazhxRCtlOXp0cTh2c1VhCi9Say9jUWNyS2wxVDMyM0xDcG1TekhnM3hDdjFqdzJUVFFINm1yWlBBa2doa2R2YlNnalp6Y1JRZWNqSEpNeTMKTzFJQXJ6V3pWbU1hRTJqeGhUV1JwbkJkcVZjZERTUERiNkNXaktVPQotLS0tLUVORCBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0K + signerName: kubernetes.io/kube-apiserver-client + expirationSeconds: 31536000 # 1 year + usages: + - client auth +``` + +En el archivo anterior, estamos definiendo la siguiente información: + +- `apiVersion`: La versión de la API que estamos utilizando para crear nuestro usuario. +- `kind`: El tipo de recurso que estamos creando, en este caso, una Solicitud de Firma de Certificado (CSR). +- `metadata.name`: El nombre de nuestro usuario. +- `spec.request`: El contenido del certificado en base64. +- `spec.signerName`: El nombre del firmante del certificado, que en este caso es el kube-apiserver, que será responsable de firmar nuestro certificado. +- `spec.expirationSeconds`: El tiempo de cad + +ucidad del certificado, que en este caso es de 1 año. + +- `spec.usages`: El tipo de uso del certificado, que en este caso es `client auth` (autenticación de cliente). + +Una vez que haya creado este archivo y copiado el contenido del certificado en base64, puede aplicar el recurso utilizando el siguiente comando: + +```bash +kubectl apply -f developer.yaml +``` + +Esto enviará la solicitud de firma de certificado al clúster Kubernetes para que sea firmada y se genere el certificado final para el usuario "developer". + +```bash +kubectl apply -f developer.yaml +``` + +Vamos listar los CSR del clúster para ver el estado de nuestro usuario: + +```bash +kubectl get csr +``` + +El resultado será algo similar a esto: + +```bash +NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION +csr-4zd8k 15m kubernetes.io/kube-apiserver-client-kubelet system:bootstrap:abcdef Approved,Issued +csr-68wsv 15m kubernetes.io/kube-apiserver-client-kubelet system:bootstrap:abcdef Approved,Issued +csr-jkm8t 15m kubernetes.io/kube-apiserver-client-kubelet system:bootstrap:abcdef Approved,Issued +csr-r2hcr 15m kubernetes.io/kube-apiserver-client-kubelet system:bootstrap:abcdef Approved,Issued +csr-x52kj 15m kubernetes.io/kube-apiserver-client-kubelet system:bootstrap:abcdef Approved,Issued +developer 3s kubernetes.io/kube-apiserver-client kubernetes-admin 365d Pending +``` + +Observe que nuestro usuario tiene el estado `Pending` porque el kube-apiserver aún no ha firmado nuestro certificado. Puede seguir el estado de su usuario con el siguiente comando: + +```bash +kubectl describe csr developer +``` + +El resultado será algo similar a esto: + +```bash +Name: developer +Labels: +Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"certificates.k8s.io/v1","kind":"CertificateSigningRequest","metadata":{"annotations":{},"name":"developer"},"spec":{"expirationSeconds":31536000,"request":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1dUQ0NBVUVDQVFBd0ZERVNNQkFHQTFVRUF3d0paR1YyWld4dmNHVnlNSUlCSWpBTkJna3Foa2lHOXcwQgpBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF5OFN1Y25JWjJjL0k3dXQvS0EwSXhvN0RZa0hkSUxrbmxZOWNwMkVlClJJSzRzU1NzZnA2SzBhbWZlYWtRaEdXT2NWMmFaeEtTM0xrNERNNlVmb3ZucEQvOXpidDl0em44UUpMTDZxREEKeHFxbzVSbEt4QnpEV3lQT2JkUStMWnI2VjFQZ2wxYms2c3o0d2lWek52a2NhT0doSDdlSU90QVI0U096MjNJdAowZ0xiZHBDalFITFIvNlFuSXBjY3h3bDBGa1FtL3RVeHdRa0x1NXNpSTNKOGRiUkQwcnlFdGxReWQ5elhLM29rCjBRbVpLZDVpV1p2aDU3R1lrV1kweGMzV0J5aXY5OURQYVE3WTB4MFNaWGlPL2w0bTRzazJ3RjYwa2dUa1NJZmQKdEMxN2Y1ZzVWVzhOTW02amNpMFRXeDk5Z0REcmpHanJpaExHeTBLUWdRa2p3d0lEQVFBQm9BQXdEUVlKS29aSQpodmNOQVFFTEJRQURnZ0VCQUllZVdLbjAwZkk5ekw3MUVQNFNpOUVxVUFNUnBYT0dkT1Aybm8rMTV2VzJ5WmpwCmhsTWpVTjMraVZubkh2QVBvWFVLKzBYdXdmaklHMjBQTjA5UEd1alU4aUFIeVZRbFZRS0VaOWpRcENXYnQybngKVlZhYUw0N0tWMUpXMnF3M1YybmNVNkhlNHdtQzVqUE9vU29vVGtrVlF5Uml4bkcyVVQrejI3M2xpaTY3RkFXegpBZ1QvczlVa3gvS1dxRjIzczVuUk9TTlZUS2xCSG5LMU40YkN6RHBqZnN5V01GUXdnazhxRCtlOXp0cTh2c1VhCi9Say9jUWNyS2wxVDMyM0xDcG1TekhnM3hDdjFqdzJUVFFINm1yWlBBa2doa2R2YlNnalp6Y1JRZWNqSEpNeTMKTzFJQXJ6V3pWbU1hRTJqeGhUV1JwbkJkcVZjZERTUERiNkNXaktVPQotLS0tLUVORCBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0K","signerName":"kubernetes.io/kube-apiserver-client","usages":["client auth"]}} + +CreationTimestamp: Wed, 31 Jan 2024 11:52:24 +0100 +Requesting User: kubernetes-admin +Signer: kubernetes.io/kube-apiserver-client +Requested Duration: 365d +Status: Pending +Subject: + Common Name: developer + Serial Number: +Events: +``` + +Hasta ahora todo va bien, ahora debemos aprobar nuestro certificado utilizando el comando `kubectl certificate approve`: + +```bash +kubectl certificate approve developer +``` + +Ahora vamos listar los CSR (Solicitudes de firma de certificado) del clúster nuevamente: + +```bash +kubectl get csr +``` + +El resultado será algo parecido a esto: + +```bash +NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION +csr-4zd8k 17m kubernetes.io/kube-apiserver-client-kubelet system:bootstrap:abcdef Approved,Issued +csr-68wsv 17m kubernetes.io/kube-apiserver-client-kubelet system:bootstrap:abcdef Approved,Issued +csr-jkm8t 17m kubernetes.io/kube-apiserver-client-kubelet system:bootstrap:abcdef Approved,Issued +csr-r2hcr 17m kubernetes.io/kube-apiserver-client-kubelet system:bootstrap:abcdef Approved,Issued +csr-x52kj 16m kubernetes.io/kube-apiserver-client-kubelet system:bootstrap:abcdef Approved,Issued +developer 88s kubernetes.io/kube-apiserver-client kubernetes-admin 365d Approved,Issued +``` + +Listo, nuestro certificado ha sido firmado con éxito. Ahora podemos obtener el certificado de nuestro usuario y guardarlo en un archivo. Para ello, utilizaremos el comando `kubectl get csr`: + +```bash +kubectl get csr developer -o jsonpath='{.status.certificate}' | base64 --decode > developer.crt +``` + +En el comando anterior, estamos obteniendo el certificado de nuestro usuario, decodificándolo en base64 y guardándolo en el archivo `developer.crt`. + +Para obtener el certificado, estamos utilizando el parámetro `-o jsonpath='{.status.certificate}'` para que el comando devuelva solo el certificado del usuario y no toda la información del CSR. + +Puede verificar el contenido del certificado mediante el comando: + +```bash +cat developer.crt +``` + +Ahora tenemos nuestro certificado final creado y podemos utilizarlo para acceder al clúster, pero antes debemos definir lo que nuestro usuario puede hacer en el clúster. + +#### Creando un Rol para nuestro usuario + +Cuando creamos un nuevo usuario o ServiceAccount en Kubernetes, no tiene acceso a nada en el clúster. Para que pueda acceder a los recursos del clúster, debemos crear un Rol y asociarlo al usuario. + +La definición de un Rol consiste en un archivo donde especificamos qué permisos tendrá el usuario en el clúster y para qué recursos tendrá acceso. Dentro del Rol es donde definimos: + +- En qué espacio de nombres (namespace) tendrá acceso el usuario. +- A qué grupos de API (apiGroups) tendrá acceso el usuario. +- A qué recursos tendrá acceso el usuario. +- A qué verbos tendrá acceso el usuario. + +#### apiGroups + +Los grupos de API (apiGroups) son los grupos de recursos de Kubernetes, que se dividen en `core` y `named`. Puede consultar todos los grupos de recursos de Kubernetes mediante el comando `kubectl api-resources`. + +Veamos la lista de grupos de recursos de Kubernetes: + +```bash +kubectl api-resources +``` + +La lista es larga, pero el resultado será algo similar a esto: + +```bash +NAME SHORTNAMES APIVERSION NAMESPACED KIND +bindings v1 true Binding +componentstatuses cs v1 false ComponentStatus +configmaps cm v1 true ConfigMap +endpoints ep v1 true Endpoints +events ev v1 true Event +limitranges limits v1 true LimitRange +namespaces ns v1 false Namespace +nodes no v1 false Node +persistentvolumeclaims pvc v1 true PersistentVolumeClaim +persistentvolumes pv v1 false PersistentVolume +pods po v1 true Pod +podtemplates v1 true PodTemplate +replicationcontrollers rc v1 true ReplicationController +resourcequotas quota v1 true ResourceQuota +secrets v1 true Secret +serviceaccounts sa v1 true ServiceAccount +services svc v1 true Service +mutatingwebhookconfigurations admissionregistration.k8s.io/v1 false MutatingWebhookConfiguration +validatingwebhookconfigurations admissionregistration.k8s.io/v1 false ValidatingWebhookConfiguration +customresourcedefinitions crd,crds apiextensions.k8s.io/v1 false CustomResourceDefinition +apiservices apiregistration.k8s.io/v1 false APIService +controllerrevisions apps/v1 true ControllerRevision +daemonsets ds apps/v1 true DaemonSet +deployments deploy apps/v1 true Deployment +replicasets rs apps/v1 true ReplicaSet +statefulsets sts apps/v1 true StatefulSet +tokenreviews authentication.k8s.io/v1 false TokenReview +localsubjectaccessreviews authorization.k8s.io/v1 true LocalSubjectAccessReview +selfsubjectaccessreviews authorization.k8s.io/v1 false SelfSubjectAccessReview +selfsubjectrulesreviews authorization.k8s.io/v1 false SelfSubjectRulesReview +subjectaccessreviews authorization.k8s.io/v1 false SubjectAccessReview +horizontalpodautoscalers hpa autoscaling/v2 true HorizontalPodAutoscaler +cronjobs cj batch/v1 true CronJob +jobs batch/v1 true Job +certificatesigningrequests csr certificates.k8s.io/v1 false CertificateSigningRequest +leases coordination.k8s.io/v1 true Lease +endpointslices discovery.k8s.io/v1 true EndpointSlice +events ev events.k8s.io/v1 true Event +flowschemas flowcontrol.apiserver.k8s.io/v1beta3 false FlowSchema +prioritylevelconfigurations flowcontrol.apiserver.k8s.io/v1beta3 false PriorityLevelConfiguration +ingressclasses networking.k8s.io/v1 false IngressClass +ingresses ing networking.k8s.io/v1 true Ingress +networkpolicies netpol networking.k8s.io/v1 true NetworkPolicy +runtimeclasses node.k8s.io/v1 false RuntimeClass +poddisruptionbudgets pdb policy/v1 true PodDisruptionBudget +clusterrolebindings rbac.authorization.k8s.io/v1 false ClusterRoleBinding +clusterroles rbac.authorization.k8s.io/v1 false ClusterRole +rolebindings rbac.authorization.k8s.io/v1 true RoleBinding +roles rbac.authorization.k8s.io/v1 true Role +priorityclasses pc scheduling.k8s.io/v1 false PriorityClass +csidrivers storage.k8s.io/v1 false CSIDriver +csinodes storage.k8s.io/v1 false CSINode +csistoragecapacities storage.k8s.io/v1 true CSIStorageCapacity +storageclasses sc storage.k8s.io/v1 false StorageClass +volumeattachments storage.k8s.io/v1 false VolumeAttachment +``` + +Donde la primera columna es el nombre del recurso, la segunda columna es el nombre abreviado del recurso, la tercera columna es la versión de la API a la que pertenece el recurso, la cuarta columna indica si el recurso se encuentra o no en un espacio de nombres (Namespaced), y la quinta columna es el tipo de recurso. + +Echemos un vistazo a un recurso específico, por ejemplo, el recurso `pods`: + +```bash +kubectl api-resources | grep pods +``` + +El resultado será algo similar a esto: + +```bash +NAME SHORTNAMES APIVERSION NAMESPACED KIND +pods po v1 true Pod +``` + +Donde: + +- `NAME`: Nombre del recurso. +- `SHORTNAMES`: Nombre abreviado del recurso. +- `APIVERSION`: Versión de la API a la que pertenece el recurso. +- `NAMESPACED`: Indica si el recurso se encuentra o no en un espacio de nombres. +- `KIND`: Tipo de recurso. + +Pero, ¿qué significa que un recurso esté en un espacio de nombres (Namespaced)? Un recurso Namespaced es un recurso que puede crearse dentro de un espacio de nombres (namespace), por ejemplo, un Pod, un Deployment, un Service, etc. Por otro lado, un recurso que no es Namespaced es un recurso que no puede crearse dentro de un espacio de nombres, como un Nodo (Node), un Volumen Persistente (PersistentVolume), un ClusterRole, etc. ¿Sencillo, verdad? + +Ahora bien, ¿cómo sabemos cuál es el apiGroup de un recurso? El apiGroup de un recurso es el nombre del grupo de recursos al que pertenece. Por ejemplo, el recurso `pods` pertenece al grupo de recursos `core`, y el recurso `deployments` pertenece al grupo de recursos `apps`. Cuando un recurso es de tipo `core`, no es necesario especificar su apiGroup, ya que Kubernetes asume automáticamente que pertenece al grupo de recursos `core`, y esto se refleja en `apiVersion: v1`. + +Por otro lado, `apiVersion: apps/v1` indica que el recurso pertenece al grupo de recursos `apps`, y su versión de API es `v1`. Dentro del grupo `apps`, encontramos recursos importantes como `deployments`, `replicasets`, `daemonsets`, `statefulsets`, entre otros. + +Los recursos son las entidades que Kubernetes administra y gestiona. Estos recursos se dividen en dos categorías principales: `core` y `named`. Puede consultar todos los recursos de Kubernetes utilizando el comando `kubectl api-resources`. + +Los recursos denominados `core` son recursos predefinidos que vienen instalados con Kubernetes. Por otro lado, los recursos denominados `named` son recursos que se instalan mediante Custom Resource Definitions (CRD), como por ejemplo, el recurso `ServiceMonitor` utilizado por Prometheus. + +A continuación, listaremos los recursos de Kubernetes que no están en un espacio de nombres (non-namespaced): + +```bash +kubectl api-resources --namespaced=false +``` + +El resultado será similar a lo siguiente: + +```bash +NAME SHORTNAMES APIVERSION NAMESPACED KIND +componentstatuses cs v1 false ComponentStatus +namespaces ns v1 false Namespace +nodes no v1 false Node +persistentvolumes pv v1 false PersistentVolume +mutatingwebhookconfigurations admissionregistration.k8s.io/v1 false MutatingWebhookConfiguration +validatingwebhookconfigurations admissionregistration.k8s.io/v1 false ValidatingWebhookConfiguration +customresourcedefinitions crd,crds apiextensions.k8s.io/v1 false CustomResourceDefinition +apiservices apiregistration.k8s.io/v1 false APIService +tokenreviews authentication.k8s.io/v1 false TokenReview +selfsubjectaccessreviews authorization.k8s.io/v1 false SelfSubjectAccessReview +selfsubjectrulesreviews authorization.k8s.io/v1 false SelfSubjectRulesReview +subjectaccessreviews authorization.k8s.io/v1 false SubjectAccessReview +certificatesigningrequests csr certificates.k8s.io/v1 false CertificateSigningRequest +flowschemas flowcontrol.apiserver.k8s.io/v1beta3 false FlowSchema +prioritylevelconfigurations flowcontrol.apiserver.k8s.io/v1beta3 false PriorityLevelConfiguration +ingressclasses networking.k8s.io/v1 false IngressClass +runtimeclasses node.k8s.io/v1 false RuntimeClass +clusterrolebindings rbac.authorization.k8s.io/v1 false ClusterRoleBinding +clusterroles rbac.authorization.k8s.io/v1 false ClusterRole +priorityclasses pc scheduling.k8s.io/v1 false PriorityClass +csidrivers storage.k8s.io/v1 false CSIDriver +csinodes storage.k8s.io/v1 false CSINode +storageclasses sc storage.k8s.io/v1 false StorageClass +volumeattachments storage.k8s.io/v1 false VolumeAttachment +``` + +De esta manera, podemos identificar cuáles son los recursos nativos de Kubernetes y cuáles son los recursos instalados a través de CRD (Definiciones de Recursos Personalizados, por sus siglas en inglés), como por ejemplo, `ServiceMonitor` de Prometheus. + +Por lo tanto, el nombre del recurso es el nombre que utilizamos para crear el recurso, como por ejemplo, `pods`, `deployments`, `services`, etc. + +#### Verbos + +Los verbos definen las acciones que un usuario puede realizar en un recurso determinado. Por ejemplo, los verbos pueden incluir crear, listar, actualizar, eliminar, etc. + +Para que pueda ver los verbos que se pueden utilizar, vamos a utilizar el comando `kubectl api-resources` con la opción `-o wide`: + +```bash +kubectl api-resources -o wide +``` + +El resultado se verá similar a esto: + +```bash +NAME SHORTNAMES APIVERSION NAMESPACED KIND VERBS CATEGORIES +bindings v1 true Binding create +componentstatuses cs v1 false ComponentStatus get,list +configmaps cm v1 true ConfigMap create,delete,deletecollection,get,list,patch,update,watch +endpoints ep v1 true Endpoints create,delete,deletecollection,get,list,patch,update,watch +events ev v1 true Event create,delete,deletecollection,get,list,patch,update,watch +limitranges limits v1 true LimitRange create,delete,deletecollection,get,list,patch,update,watch +namespaces ns v1 false Namespace create,delete,get,list,patch,update,watch +nodes no v1 false Node create,delete,deletecollection,get,list,patch,update,watch +persistentvolumeclaims pvc v1 true PersistentVolumeClaim create,delete,deletecollection,get,list,patch,update,watch +persistentvolumes pv v1 false PersistentVolume create,delete,deletecollection,get,list,patch,update,watch +pods po v1 true Pod create,delete,deletecollection,get,list,patch,update,watch all +podtemplates v1 true PodTemplate create,delete,deletecollection,get,list,patch,update,watch +replicationcontrollers rc v1 true ReplicationController create,delete,deletecollection,get,list,patch,update,watch all +resourcequotas quota v1 true ResourceQuota create,delete,deletecollection,get,list,patch,update,watch +secrets v1 true Secret create,delete,deletecollection,get,list,patch,update,watch +serviceaccounts sa v1 true ServiceAccount create,delete,deletecollection,get,list,patch,update,watch +services svc v1 true Service create,delete,deletecollection,get,list,patch,update,watch all +mutatingwebhookconfigurations admissionregistration.k8s.io/v1 false MutatingWebhookConfiguration create,delete,deletecollection,get,list,patch,update,watch api-extensions +validatingwebhookconfigurations admissionregistration.k8s.io/v1 false ValidatingWebhookConfiguration create,delete,deletecollection,get,list,patch,update,watch api-extensions +customresourcedefinitions crd,crds apiextensions.k8s.io/v1 false CustomResourceDefinition create,delete,deletecollection,get,list,patch,update,watch api-extensions +apiservices apiregistration.k8s.io/v1 false APIService create,delete,deletecollection,get,list,patch,update,watch api-extensions +controllerrevisions apps/v1 true ControllerRevision create,delete,deletecollection,get,list,patch,update,watch +daemonsets ds apps/v1 true DaemonSet create,delete,deletecollection,get,list,patch,update,watch all +deployments deploy apps/v1 true Deployment create,delete,deletecollection,get,list,patch,update,watch all +replicasets rs apps/v1 true ReplicaSet create,delete,deletecollection,get,list,patch,update,watch all +statefulsets sts apps/v1 true StatefulSet create,delete,deletecollection,get,list,patch,update,watch all +tokenreviews authentication.k8s.io/v1 false TokenReview create +localsubjectaccessreviews authorization.k8s.io/v1 true LocalSubjectAccessReview create +selfsubjectaccessreviews authorization.k8s.io/v1 false SelfSubjectAccessReview create +selfsubjectrulesreviews authorization.k8s.io/v1 false SelfSubjectRulesReview create +subjectaccessreviews authorization.k8s.io/v1 false SubjectAccessReview create +horizontalpodautoscalers hpa autoscaling/v2 true HorizontalPodAutoscaler create,delete,deletecollection,get,list,patch,update,watch all +cronjobs cj batch/v1 true CronJob create,delete,deletecollection,get,list,patch,update,watch all +jobs batch/v1 true Job create,delete,deletecollection,get,list,patch,update,watch all +certificatesigningrequests csr certificates.k8s.io/v1 false CertificateSigningRequest create,delete,deletecollection,get,list,patch,update,watch +leases coordination.k8s.io/v1 true Lease create,delete,deletecollection,get,list,patch,update,watch +endpointslices discovery.k8s.io/v1 true EndpointSlice create,delete,deletecollection,get,list,patch,update,watch +events ev events.k8s.io/v1 true Event create,delete,deletecollection,get,list,patch,update,watch +flowschemas flowcontrol.apiserver.k8s.io/v1beta3 false FlowSchema create,delete,deletecollection,get,list,patch,update,watch +prioritylevelconfigurations flowcontrol.apiserver.k8s.io/v1beta3 false PriorityLevelConfiguration create,delete,deletecollection,get,list,patch,update,watch +ingressclasses networking.k8s.io/v1 false IngressClass create,delete,deletecollection,get,list,patch,update,watch +ingresses ing networking.k8s.io/v1 true Ingress create,delete,deletecollection,get,list,patch,update,watch +networkpolicies netpol networking.k8s.io/v1 true NetworkPolicy create,delete,deletecollection,get,list,patch,update,watch +runtimeclasses node.k8s.io/v1 false RuntimeClass create,delete,deletecollection,get,list,patch,update,watch +poddisruptionbudgets pdb policy/v1 true PodDisruptionBudget create,delete,deletecollection,get,list,patch,update,watch +clusterrolebindings rbac.authorization.k8s.io/v1 false ClusterRoleBinding create,delete,deletecollection,get,list,patch,update,watch +clusterroles rbac.authorization.k8s.io/v1 false ClusterRole create,delete,deletecollection,get,list,patch,update,watch +rolebindings rbac.authorization.k8s.io/v1 true RoleBinding create,delete,deletecollection,get,list,patch,update,watch +roles rbac.authorization.k8s.io/v1 true Role create,delete,deletecollection,get,list,patch,update,watch +priorityclasses pc scheduling.k8s.io/v1 false PriorityClass create,delete,deletecollection,get,list,patch,update,watch +csidrivers storage.k8s.io/v1 false CSIDriver create,delete,deletecollection,get,list,patch,update,watch +csinodes storage.k8s.io/v1 false CSINode create,delete,deletecollection,get,list,patch,update,watch +csistoragecapacities storage.k8s.io/v1 true CSIStorageCapacity create,delete,deletecollection,get,list,patch,update,watch +storageclasses sc storage.k8s.io/v1 false StorageClass create,delete,deletecollection,get,list,patch,update,watch +volumeattachments storage.k8s.io/v1 false VolumeAttachment create,delete,deletecollection,get,list,patch,update,watch +``` + +Ahora, observe que tenemos una nueva columna llamada `VERBS`, que contiene todos los verbos que se pueden utilizar con el recurso, y la columna `CATEGORIES`, que muestra la categoría del recurso. Sin embargo, nuestro enfoque aquí está en los verbos, así que echemos un vistazo a ellos. + +Los verbos se dividen en: + +- `create`: Permite que el usuario cree un recurso. +- `delete`: Permite que el usuario elimine un recurso. +- `deletecollection`: Permite que el usuario elimine una colección de recursos. +- `get`: Permite que el usuario obtenga un recurso. +- `list`: Permite que el usuario liste los recursos. +- `patch`: Permite que el usuario actualice un recurso. +- `update`: Permite que el usuario actualice un recurso. +- `watch`: Permite que el usuario siga los cambios en un recurso. + +Por ejemplo, tomemos la línea del recurso `pods`: + +```bash +NAME SHORTNAMES APIVERSION NAMESPACED KIND VERBS CATEGORIES +pods po v1 true Pod create,delete,deletecollection,get,list,patch,update,watch all +``` + +Con esto, sabemos que el usuario puede crear, eliminar, eliminar una colección, obtener, listar, actualizar y seguir los cambios en un Pod. ¡Muy sencillo! + +Ahora que conocemos bien los `resources`, `apiGroups` y `verbs`, crearemos nuestra Role para nuestro usuario. + +Para ello, crearemos un archivo llamado `developer-role.yaml` con el siguiente contenido: + +```yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: developer + namespace: dev +rules: +- apiGroups: [""] # "" indica el grupo de recursos principal + resources: ["pods"] + verbs: ["get", "watch", "list", "update", "create", "delete"] +``` + +En el archivo anterior, definimos la siguiente información: + +- `apiVersion`: Versión de la API que estamos utilizando para crear nuestro usuario. +- `kind`: Tipo de recurso que estamos creando, en este caso, una Role. +- `metadata.name`: Nombre de nuestra Role. +- `metadata.namespace`: Namespace en el que se creará nuestra Role. +- `rules`: Reglas de nuestra Role. +- `rules.apiGroups`: Grupos de recursos a los que tendrá acceso nuestra Role. +- `rules.resources`: Recursos a los que tendrá acceso nuestra Role. +- `rules.verbs`: Verbos a los que tendrá acceso nuestra Role. + +Estoy seguro de que le resulta fácil comprender la Role, que básicamente establece lo que nuestro usuario puede hacer en el clúster. En resumen, estamos diciendo que el usuario que utilice esta Role podrá realizar todas las operaciones con el recurso `pods` en el espacio de nombres `dev`. ¡Tan sencillo como volar! + +Recuerde que esta Role puede ser reutilizada por otros usuarios y que puede crear tantas Roles como desee, así como crear Roles para otros perfiles de usuarios y otros recursos, como `deployments`, `services`, `configmaps`, etc. + +¡Ah, antes de continuar, creemos el espacio de nombres `dev`: + +```bash +kubectl create ns dev +``` + +Ahora que hemos creado nuestro archivo y el espacio de nombres, vamos a aplicarlo en el clúster: + +```bash +kubectl apply -f developer-role.yaml +``` + +Para verificar si nuestra Role se ha creado correctamente, enumeremos las Roles en el clúster: + +```bash +kubectl get roles -n dev +``` + +La salida será algo como: + +```bash +NAME CREATED AT +developer 2024-01-31T11:32:08Z +``` + +Para ver los detalles de la Role, utilizaremos el comando `kubectl describe`: + +```bash +kubectl describe role developer -n dev +``` + +La salida será algo parecida a esto: + +```bash +Name: developer +Labels: +Annotations: +PolicyRule: + Resources Non-Resource URLs Resource Names Verbs + --------- ----------------- -------------- ----- + pods [] [] [get watch list update create delete] +``` + +Listo, nuestra Role ya está creada, pero aún no la hemos asociado a nuestro usuario. Para hacerlo, crearemos un RoleBinding. + +El RoleBinding es el recurso que asocia un usuario a una Role, es decir, a través del RoleBinding definimos qué usuario tiene acceso a qué Role. Puedes pensar en ello como si fuera una insignia de Desarrollador, donde la Role sería la insignia y el RoleBinding sería la insignia con el nombre del usuario. ¿Tiene sentido? + +Para ello, crearemos un archivo llamado `developer-rolebinding.yaml` con el siguiente contenido: + +```yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: DeveloperRoleBinding + namespace: dev +subjects: +- kind: User + name: developer +roleRef: + kind: Role + name: developer + apiGroup: rbac.authorization.k8s.io +``` + +En el archivo anterior, estamos definiendo la siguiente información: + +- `apiVersion`: La versión de la API que estamos utilizando para crear nuestro usuario. +- `kind`: El tipo de recurso que estamos creando, en este caso, un RoleBinding. +- `metadata.name`: El nombre de nuestro RoleBinding. +- `metadata.namespace`: El espacio de nombres en el que se creará nuestro RoleBinding. +- `subjects`: Los usuarios que tendrán acceso a la Role. +- `subjects.kind`: El tipo de usuario, que en este caso es `User`. +- `subjects.name`: El nombre del usuario, que en este caso es `developer`. +- `roleRef`: La referencia a la Role a la que el usuario tendrá acceso. +- `roleRef.kind`: El tipo de Role, que en este caso es `Role`. +- `roleRef.name`: El nombre de la Role, que en este caso es `developer`. +- `roleRef.apiGroup`: El grupo de recursos de la Role, que en este caso es `rbac.authorization.k8s.io`. + +No es nada complicado, y una vez más, está muy claro lo que estamos haciendo, que es darle acceso al usuario `developer` con la Role `developer` en el espacio de nombres `dev`. + +Ahora que tenemos nuestro archivo creado, apliquémoslo: + +```bash +kubectl apply -f developer-rolebinding.yaml +``` + +Para verificar si nuestro RoleBinding se creó correctamente, enumeremos los RoleBindings en el clúster: + +```bash +kubectl get rolebindings -n dev +``` + +La salida será: + +```bash +NAME ROLE AGE +DeveloperRoleBinding Role/developer 9s +``` + +Para ver los detalles del RoleBinding, utilizaremos el comando `kubectl describe`: + +```bash +kubectl describe rolebinding DeveloperRoleBinding -n dev +``` + +La salida será algo similar a esto: + +```bash +Name: DeveloperRoleBinding +Labels: +Annotations: +Role: + Kind: Role + Name: developer +Subjects: + Kind Name Namespace + ---- ---- --------- + User developer +``` + +Listo, el RoleBinding se ha creado con éxito. Ahora, vamos a probar nuestro usuario. + +#### Agregando el certificado del usuario al kubeconfig + +Ahora que hemos creado con éxito nuestro usuario, debemos agregar el certificado del usuario al kubeconfig para poder acceder al clúster con nuestro usuario. + +Para hacerlo, utilizaremos el comando `kubectl config set-credentials`: + +```bash +kubectl config set-credentials developer --client-certificate=developer.crt --client-key=developer.key --embed-certs=true +``` + +El comando `kubectl config set-credentials` se utiliza para agregar un nuevo usuario al kubeconfig y recibe los siguientes parámetros: + +- `--client-certificate`: Ruta del certificado del usuario. +- `--client-key`: Ruta de la clave del usuario. +- `--embed-certs`: Indica si el certificado debe incrustarse en el kubeconfig. + +En nuestro caso, estamos proporcionando la ruta del certificado y la clave del usuario, y estamos indicando que el certificado debe incrustarse en el kubeconfig. + +Ahora debemos crear un contexto para nuestro usuario utilizando el comando `kubectl config set-context`: + +```bash +kubectl config set-context developer --cluster=NOMBRE-DEL-CLÚSTER --namespace=dev --user=developer +``` + +Si no recuerdas qué es un contexto en Kubernetes, te ayudaré a recordarlo. Un contexto es un conjunto de configuraciones que define el acceso a un clúster, es decir, un contexto está compuesto por un clúster, un usuario y un espacio de nombres (namespace). Cuando creas un nuevo usuario, debes crear un nuevo contexto para él, de modo que pueda acceder al clúster. + +Para obtener los nombres de los clústeres, puedes utilizar el comando `kubectl config get-clusters`, de esta manera podrás obtener el nombre del clúster que deseas utilizar. + +Con esto, nuestro nuevo usuario está listo para ser utilizado, pero antes verifiquemos si funciona correctamente. + +#### Accediendo al clúster con el nuevo usuario + +Una vez que hemos creado nuestro usuario y que el certificado del usuario se ha agregado al kubeconfig, y que ya tenemos un contexto para el usuario, podemos probar el acceso al clúster. + +Para hacerlo, debemos cambiar al contexto del usuario utilizando el comando `kubectl config use-context`: + +```bash +kubectl config use-context developer +```