<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: martinsaporiti</title>
    <description>The latest articles on DEV Community by martinsaporiti (@martinsaporiti).</description>
    <link>https://dev.to/martinsaporiti</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F295053%2Ff27e7a8e-8913-4f3b-8cc5-c9bdc0cb656f.jpeg</url>
      <title>DEV Community: martinsaporiti</title>
      <link>https://dev.to/martinsaporiti</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/martinsaporiti"/>
    <language>en</language>
    <item>
      <title>Instalando k3d para jugar con k8s.</title>
      <dc:creator>martinsaporiti</dc:creator>
      <pubDate>Sun, 01 Nov 2020 23:51:16 +0000</pubDate>
      <link>https://dev.to/martinsaporiti/instalando-k3d-para-jugar-con-k8s-phg</link>
      <guid>https://dev.to/martinsaporiti/instalando-k3d-para-jugar-con-k8s-phg</guid>
      <description>&lt;p&gt;En este artículo veremos como configurar &lt;a href="https://k3d.io/"&gt;k3d&lt;/a&gt; en una máquina virtual con linux, con el objetivo de poder contar con un &lt;em&gt;mini&lt;/em&gt; cluster de kubernetes para apredener, practicar o, inclusive, tener aplicaciones corriendo.&lt;/p&gt;

&lt;p&gt;K3D es un wrapper livianito sobre 3ks, que justamente la mínima distribución de kubernetes que nos brinda &lt;a href="https://rancher.com/"&gt;Rancher Labs&lt;/a&gt;. K3D corre sobre Docker, por lo que puede ser instalado sin demasiada complejidad en un host que tenga instalado Docker. Además, K3D nos permite crear "nodos virtuales" que nos sirven para probar algunas de las características de K8s como son &lt;strong&gt;NodeAffinity&lt;/strong&gt;, &lt;strong&gt;Taints&lt;/strong&gt; y &lt;strong&gt;Tolerations&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Otra de las intenciones de este artículo es describir las configuraciones necesarias para poder conectarnos al cluster de kubernetes desde una máquina diferente a la que hostea el cluster, crear un ServiceAccount y darle permisos de administrador y crear otro ServiceAccount con capacidades limitadas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requerimientos Previos
&lt;/h2&gt;

&lt;p&gt;Alcanza con tener una máquina virtual (yo uso &lt;a href="https://www.virtualbox.org/"&gt;Virtaulbox&lt;/a&gt;) con ubuntu instalado. La imagen de Ubuntu se puede descargar de este &lt;a href="https://www.osboxes.org/virtualbox-images/"&gt;link&lt;/a&gt;. La instalación es muy sencilla y hay que tener en cuenta solamente que la máquina virtual debe tener acceso a internet y debe ser "visible" desde nuestra máquina (el host de la máquina virtual).&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalando Docker.
&lt;/h2&gt;

&lt;p&gt;Suponiendo que la ip de nuestra máquina virtual es 192.168.0.91, nos logueamos desde el host a la máquina virtual mediante ssh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh osboxes.org@192.168.0.91
&lt;span class="c"&gt;# El password es osboxes.org si bajaste la imagen desde el link que te pasé.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;luego ejecutamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;docker.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;configuramos el Docker para que arranque cuando iniciamos la máquina virtual:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start docker
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... finalmente, probamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;si nos muestra la versión, listo... ya tenemos Docker instalado.&lt;/p&gt;

&lt;p&gt;podemos ejecutar adicionalmente ;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; busybox &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello from Docker!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Ahora k3d
&lt;/h2&gt;

&lt;p&gt;Es muy simple la instalación para la última versión estable. Primero necesitamos instalar &lt;em&gt;curl&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;curl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos a necesitar también tener instalado kubectl para poder interactuar con el cluster. Lo instalamos, &lt;a href="https://kubernetes.io/docs/tasks/tools/install-kubectl/"&gt;acá&lt;/a&gt; dejo los pasos.&lt;/p&gt;

&lt;p&gt;Ya con Kubectl instalado, seguimos...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;-O&lt;/span&gt; - https://raw.githubusercontent.com/rancher/k3d/main/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Listo!. Ahora vamos a crear nuestro primer cluster teniendo en cuenta los sigiuentes requerimientos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tenemos que poder crear Persistent Volumes -&amp;gt; necesitamos entonces darle un folder a 3kd para poder crear los volúmenes.&lt;/li&gt;
&lt;li&gt;Tenemos que poder entrar al cluster desde otra máquina (desde el host de la máquina virtual por ejemplo).&lt;/li&gt;
&lt;li&gt;Necesitamos 3 nodos además del master para poder probar algunas cosas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bueno, ejecutamos entonces el siguiente comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Creamos un folder:&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /tmp/k3dvol

&lt;span class="c"&gt;# Ejecutamos:&lt;/span&gt;
k3d cluster create Kluster &lt;span class="nt"&gt;--api-port&lt;/span&gt; 192.168.0.91:6443 &lt;span class="nt"&gt;--volume&lt;/span&gt; /tmp/k3dvol:/tmp/k3dvol &lt;span class="nt"&gt;-p&lt;/span&gt; 8081:80@loadbalancer &lt;span class="nt"&gt;--agents&lt;/span&gt; 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;donde:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kluster&lt;/strong&gt; es el nombre del cluster&lt;/li&gt;
&lt;li&gt;La ip &lt;strong&gt;192.168.0.91&lt;/strong&gt; es la ip de la máquina virtual.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;--agents&lt;/strong&gt; especifica la cantidad de nodos virtuales adicionales al master.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-p 8081:80@loadbalancer&lt;/strong&gt; especifica el puerto (8081) a través del cual podremos ingresar al loadbalancer del cluster.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;probamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get nodes

&lt;span class="c"&gt;# Deberíamos obtener algo parecido a esto:&lt;/span&gt;

NAME                   STATUS   ROLES    AGE   VERSION
k3d-kluster-agent-0    Ready    &amp;lt;none&amp;gt;   12s   v1.18.9+k3s1
k3d-kluster-server-0   Ready    master   10s   v1.18.9+k3s1
k3d-kluster-agent-2    Ready    &amp;lt;none&amp;gt;   11s   v1.18.9+k3s1
k3d-kluster-agent-1    Ready    &amp;lt;none&amp;gt;   10s   v1.18.9+k3s1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Muy bien, tenemos un cluster con un nodo maestro y tres nodos esclavos. Vamos a usarlo!&lt;/p&gt;

&lt;h2&gt;
  
  
  Accediento al Cluster Desde otra Computadora.
&lt;/h2&gt;

&lt;p&gt;Tanto los sapiens como los no sapiens (pods por ejemplo) pueden comunicarse e interactuar con un cluster de K8s mediante una api. Generalmente los sapiens utilizan &lt;strong&gt;Kubectl&lt;/strong&gt; para hacerlo y el proceso para "conversar" con el cluster implica tres etapas: &lt;strong&gt;Authentication&lt;/strong&gt;, &lt;strong&gt;Authorization&lt;/strong&gt; y &lt;strong&gt;Admission Control&lt;/strong&gt;. En esta sección veremos entonces como crear un Service Account que nos permita esa conversación con el cluster en forma remota (por fuera del mismo cluster). Vamos a crear un usuario (ServiceAccount) y asignarle permisos de administrador.&lt;/p&gt;

&lt;h4&gt;
  
  
  Paso 1 - Creación del Service Account y Obtención del Secret.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Seteamos el usuario a crear (sapiens en este caso):&lt;/span&gt;
&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sapien

&lt;span class="c"&gt;# Creamos el Service Account en el namespace kube-system:&lt;/span&gt;
kubectl create sa &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; kube-system

&lt;span class="c"&gt;# Obtenemos el secret para el Service Account creado:&lt;/span&gt;
&lt;span class="nv"&gt;secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get sa &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; kube-system &lt;span class="nt"&gt;-o&lt;/span&gt; json | jq &lt;span class="nt"&gt;-r&lt;/span&gt; .secrets[].name&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"secret = &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;secret&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Paso 2 - Creación del Certificado y Obtención del Token
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get secret &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;secret&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; kube-system &lt;span class="nt"&gt;-o&lt;/span&gt; json | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.data["ca.crt"]'&lt;/span&gt; | &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ca.crt
&lt;span class="nv"&gt;user_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get secret &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;secret&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; kube-system &lt;span class="nt"&gt;-o&lt;/span&gt; json | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.data["token"]'&lt;/span&gt; | &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"token = &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user_token&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Paso 3 - Configuración del Contexto
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;kubectl config current-context&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"context = &lt;/span&gt;&lt;span class="nv"&gt;$c&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nv"&gt;cluster_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;kubectl config get-contexts &lt;span class="nv"&gt;$c&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $3}'&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 1&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"cluster_name= &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;cluster_name&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nv"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;kubectl config view &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"{.clusters[?(@.name == &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;cluster_name&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;)].cluster.server}"&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"endpoint = &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;endpoint&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Paso 4 - Configuración final del Service Account en el Cluster - Role Binding.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Se bindea el service account al rol de administrador existente...&lt;/span&gt;
kubectl create clusterrolebinding add-on-cluster-admin-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--clusterrole&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cluster-admin &lt;span class="nt"&gt;--serviceaccount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kube-system:&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Creamos el archivo de configuación para la conección.&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;KUBECONFIG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-kube&lt;/span&gt;.yml
&lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-kube&lt;/span&gt;.yml

kubectl config set-cluster &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;cluster_name&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--embed-certs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--server&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;endpoint&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--certificate-authority&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;./ca.crt

kubectl config set-credentials &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;cluster_name&lt;/span&gt;&lt;span class="p"&gt;#cluster-&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user_token&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

kubectl config set-context &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;cluster_name&lt;/span&gt;&lt;span class="p"&gt;#cluster-&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--cluster&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;cluster_name&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;cluster_name&lt;/span&gt;&lt;span class="p"&gt;#cluster-&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora queda copiar el archivo sapiens-kube.yml a la máquina desde la cual nos queremos  conectar a cluster (supongamos el host de la máquina virtual) y agregarlo el path a la variable de entorno &lt;strong&gt;KUBECONFIG&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;KUBECONFIG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;somepath/sapien-kube.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lo probamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#Seteamos el contexto (el nombre del contexto dependerá del nombre del SA):&lt;/span&gt;
k config set-context sapiens-k3d-Kluster

k get nodes
...
NAME                   STATUS   ROLES    AGE   VERSION
k3d-kluster-agent-1    Ready    &amp;lt;none&amp;gt;   8h    v1.18.9+k3s1
k3d-kluster-agent-0    Ready    &amp;lt;none&amp;gt;   8h    v1.18.9+k3s1
k3d-kluster-agent-2    Ready    &amp;lt;none&amp;gt;   8h    v1.18.9+k3s1
k3d-kluster-server-0   Ready    master   8h    v1.18.9+k3s1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos crear un namespace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create namespace testadmin
...
namespace/testadmin created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bien, accedimos al cluster desde otra máquina a través utilizando un Service Account creado por nostros y bindeado a un rol de adminitrador. Misión cumplida.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comó crear un usuario con privilegios limitados?
&lt;/h2&gt;

&lt;p&gt;En la sección anterior vimos como crear un Service Account y cómo bindearlo con un rol con permisos de adminitrador. Ese rol &lt;strong&gt;cluster-admin&lt;/strong&gt; ya estaba creado por defecto por el mismo K8s en su instalación y es un cluster role. Atención con esto, K8s nos proporciona dos tipos de roles, los &lt;strong&gt;Role&lt;/strong&gt; y los &lt;strong&gt;ClusterRole&lt;/strong&gt;. Los &lt;strong&gt;ClusterRole&lt;/strong&gt; son roles para operar sobre todo el cluster, son roles cross, mientras que los &lt;strong&gt;ROLE&lt;/strong&gt; sirven para operar dentro de un namespace determinado.&lt;/p&gt;

&lt;p&gt;Ahora vamos a ver como crear nosotros un rol con privilegios limitados. Antes, vamos a plantear el siguiente requerimiento: "necesitamos que el usuario amy solamente pueda listar pods en su propio namespace".&lt;/p&gt;

&lt;p&gt;Con el requimiento en mente, lo primero que hay que hacer es crear el namespace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;k create namespace amy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El siguiente paso es crear el rol dentro del mismo namespace. Creamos el archivo amy-role.yaml con el siguiente contenido.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Role&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;amy&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pod-and-pod-logs-reader&lt;/span&gt;
&lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;apiGroups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pods"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pods/log"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;verbs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;list"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;lo creamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;k create &lt;span class="nt"&gt;-f&lt;/span&gt; amy-role.yaml
...
role.rbac.authorization.k8s.io/pod-and-pod-logs-reader created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora tenemos que repetir los mismos haciendo algunos cambios:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Seteamos el usuario a crear (amy en este caso):&lt;/span&gt;
&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;amy

&lt;span class="c"&gt;# Creamos el Service Account en el namespace amy:&lt;/span&gt;
kubectl create sa &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-namespace&lt;/span&gt; amy

&lt;span class="nv"&gt;secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get sa &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; amy &lt;span class="nt"&gt;-o&lt;/span&gt; json | jq &lt;span class="nt"&gt;-r&lt;/span&gt; .secrets[].name&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"secret = &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;secret&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

kubectl get secret &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;secret&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; amy &lt;span class="nt"&gt;-o&lt;/span&gt; json | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.data["ca.crt"]'&lt;/span&gt; | &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ca.crt
&lt;span class="nv"&gt;user_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get secret &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;secret&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; amy &lt;span class="nt"&gt;-o&lt;/span&gt; json | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.data["token"]'&lt;/span&gt; | &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"token = &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user_token&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;


&lt;span class="nv"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;kubectl config current-context&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"context = &lt;/span&gt;&lt;span class="nv"&gt;$c&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nv"&gt;cluster_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;kubectl config get-contexts &lt;span class="nv"&gt;$c&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $3}'&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 1&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"cluster_name= &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;cluster_name&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nv"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;kubectl config view &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"{.clusters[?(@.name == &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;cluster_name&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;)].cluster.server}"&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"endpoint = &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;endpoint&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;


&lt;span class="c"&gt;# Acá realizamos el binding al role creado unos pasos antes... al rol con privilegios limitados y en el namespace amy.&lt;/span&gt;
&lt;span class="c"&gt;# Prestar atención: ahora creamos un rolebinding en lugar de un clusterrolebinding y además lo creamos en el namespace amy,&lt;/span&gt;
&lt;span class="c"&gt;# el mismo namespace en donde creamos el role.&lt;/span&gt;
kubectl create rolebinding add-on-cluster-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;pod-and-pod-logs-reader &lt;span class="nt"&gt;--serviceaccount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;amy:&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-namespace&lt;/span&gt; amy

&lt;span class="c"&gt;# Creamos el archivo de configuación para la conección.&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;KUBECONFIG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-kube&lt;/span&gt;.yml
&lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;-kube&lt;/span&gt;.yml

kubectl config set-cluster &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;cluster_name&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--embed-certs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--server&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;endpoint&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--certificate-authority&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;./ca.crt

kubectl config set-credentials &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;cluster_name&lt;/span&gt;&lt;span class="p"&gt;#cluster-&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user_token&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

kubectl config set-context &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;cluster_name&lt;/span&gt;&lt;span class="p"&gt;#cluster-&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--cluster&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;cluster_name&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;cluster_name&lt;/span&gt;&lt;span class="p"&gt;#cluster-&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si todo fue bien, deberíamos tener un archivo &lt;strong&gt;amy-kube.yml&lt;/strong&gt; listo para ser utilizado.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vamos a probarlo
&lt;/h3&gt;

&lt;p&gt;Nuevamente, vamos a realizar la prueba desde una máquina diferente a la que tiene corriendo el cluster.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;KUBECONFIG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;somepath/amy-kube.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nos paramos en el contexto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;k config set-context amy-k3d-Kluster &lt;span class="nt"&gt;--namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;amy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;y ejecutamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;k get nodes
...
Error from server &lt;span class="o"&gt;(&lt;/span&gt;Forbidden&lt;span class="o"&gt;)&lt;/span&gt;: nodes is forbidden: User &lt;span class="s2"&gt;"system:serviceaccount:amy:amy"&lt;/span&gt; cannot list resource &lt;span class="s2"&gt;"nodes"&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;API group &lt;span class="s2"&gt;""&lt;/span&gt; at the cluster scope
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfecto, no nos permitió listar los nodos porque el Service Account amy no tiene permisos. Qué pasa si queremos listar los pods?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;k get pod
...
No resources found &lt;span class="k"&gt;in &lt;/span&gt;amy namespace.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Funciona, nos permite listarlos (aunque no hay ninguno). &lt;/p&gt;

&lt;h2&gt;
  
  
  Comentarios Finales
&lt;/h2&gt;

&lt;p&gt;Hemos visto como instalar de forma muy simple un cluster K3d, cluster que es muy liviano y útil para aprender, realizar pruebas y hasta tenerlo operativo en máquinas con recursos limitados, K3d se monta sobre Docker y es una alternativa interesante.&lt;/p&gt;

&lt;p&gt;Si bien en la actualidad existen herramientas con interfaces amigables como &lt;a href="https://k8slens.dev/"&gt;Lens&lt;/a&gt; para realizar configuraciones sobre un cluster de kubernetes de forma mucho más simple, entender como funcionan la autenticación y autorización es importante. Este artículo solamente muestra una parte, la parte práctica para crear un Service Account y darle permisos de administrador o permisos limitados sobre un deterinado namespace y permitir operar sobre el cluster 3kd de forma remota. Recomiendo leer más sobre el tema en la página oficial de Kubernetes.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
