<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>OpenBits Labs!</title>
    <link>https://blog.labs.openbits.com.ar/</link>
    <description>Personal projects, this platform is running on a Raspberry Pi!</description>
    <pubDate>Fri, 29 May 2026 18:56:59 +0000</pubDate>
    <item>
      <title>Instalar awx-operator en k3s</title>
      <link>https://blog.labs.openbits.com.ar/instalar-awx-operator-en-k3s</link>
      <description>&lt;![CDATA[Esto es una pequeña guía de cómo instalar awx utilizando awx-operator en k3s. &#xA;&#xA;Los pasos los adapté de esta guía de linuxtechi&#xA;&#xA;El requisito previo es tener k3s y helm instalado en nuestra máquina, si no sabes como, me preguntas por X&#xA;&#xA;Como primer paso agregamos el repositorio de awx-operator a helm:&#xA;&#xA;helm repo add awx-operator https://ansible.github.io/awx-operator/&#xA;&#xA;Luego, instalamos el operador en nuestro cluster k3s, utilizando helm&#xA;&#xA;helm install ansible-awx-operator awx-operator/awx-operator -n awx --create-namespace&#xA;&#xA;Validamos que el pod del operador (que luego nos instalará los componentes que necesitemos) se encuentre en estado Running:&#xA;&#xA;pulpo@pop-os:~$ kubectl get pods -n awx | grep opera&#xA;awx-operator-controller-manager-6569d67f4c-x5dbp   2/2     Running   5 (72m ago)   24h&#xA;&#xA;Dado que k3s ya viene con un storage class por defecto para crear volúmenes dentro de la máquina donde se esté ejecutando, el siguiente paso es simplemente definir un volume claim, y un custom resource definition (si queremos explorar la lista completa de los crds de awx instalados podemos ejecutar kubectl get crds awxs.awx.ansible.com  -o yaml; para nuestro caso de uso vamos a crear un archivo yaml con el siguiente contenido:&#xA;&#xA;---&#xA;apiVersion: v1&#xA;kind: PersistentVolumeClaim&#xA;metadata:&#xA;  name: postgres-13-ansible-awx-postgres-13-0&#xA;  namespace: awx&#xA;spec:&#xA;  storageClassName: local-path&#xA;  accessModes:&#xA;    ReadWriteOnce&#xA;  resources:&#xA;    requests:&#xA;      storage: 10Gi&#xA;---&#xA;apiVersion: awx.ansible.com/v1beta1&#xA;kind: AWX&#xA;metadata:&#xA;  name: ansible-awx&#xA;  namespace: awx&#xA;spec:&#xA;  servicetype: nodeport&#xA;  postgresstorageclass: local-path&#xA;En mi caso le di un nombre al yaml, y luego lo apliqué contra el cluster ejecutando kubectl apply -f awxmanifestforoperator.yaml&#xA;&#xA;Después de unos momentos, el namespace awx deberá tener los pods en ejecución:&#xA;&#xA;pulpo@pop-os:~$ kubectl get pods -n awx&#xA;NAME                                               READY   STATUS    RESTARTS      AGE&#xA;awx-operator-controller-manager-6569d67f4c-x5dbp   2/2     Running   5 (79m ago)   24h&#xA;ansible-awx-postgres-13-0                          1/1     Running   0             55m&#xA;ansible-awx-task-6b4b565686-cbdg5                  4/4     Running   0             54m&#xA;ansible-awx-web-799c7f78b5-dwr7k                   3/3     Running   0             52m&#xA;&#xA;Finalmente, exponemos el deployment de awx&#xA;&#xA;kubectl expose deployment ansible-awx-web --name ansible-awx-web-svc --type NodePort -n awx&#xA;Obtenemos la password de admin que está guardada en un secreto de kubernetes:&#xA;kubectl get secret ansible-awx-admin-password -o jsonpath=&#34;{.data.password}&#34; -n awx | base64 --decode ; echo&#xA;Y accedemos al puerto que haya creado el deployment (si no lo sabemos, lo obtenemos listando los svc):&#xA;&#xA;pulpo@pop-os:~$ kubectl get svc -n awx ansible-awx-web-svc&#xA;NAME                  TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE&#xA;ansible-awx-web-svc   NodePort   10.43.66.87   none        8052:30087/TCP   53m&#xA;&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>Esto es una pequeña guía de cómo instalar <a href="https://github.com/ansible/awx" rel="nofollow">awx</a> utilizando <a href="https://github.com/ansible/awx-operator/" rel="nofollow">awx-operator</a> en k3s.</p>

<p>Los pasos los adapté de <a href="https://www.linuxtechi.com/install-ansible-awx-on-kubernetes-cluster/" rel="nofollow">esta guía de linuxtechi</a></p>

<p>El requisito previo es tener <a href="https://k3s.io/" rel="nofollow">k3s</a> y helm instalado en nuestra máquina, si no sabes como, me preguntas por <a href="https://twitter.com/pulpox" rel="nofollow">X</a></p>

<p>Como primer paso agregamos el repositorio de awx-operator a helm:</p>

<pre><code class="language-bash">helm repo add awx-operator https://ansible.github.io/awx-operator/
</code></pre>

<p>Luego, instalamos el operador en nuestro cluster k3s, utilizando helm</p>

<pre><code class="language-bash">helm install ansible-awx-operator awx-operator/awx-operator -n awx --create-namespace
</code></pre>

<p>Validamos que el pod del operador (que luego nos instalará los componentes que necesitemos) se encuentre en estado Running:</p>

<pre><code class="language-bash">pulpo@pop-os:~$ kubectl get pods -n awx | grep opera
awx-operator-controller-manager-6569d67f4c-x5dbp   2/2     Running   5 (72m ago)   24h
</code></pre>

<p>Dado que k3s ya viene con un storage class por defecto para crear volúmenes dentro de la máquina donde se esté ejecutando, el siguiente paso es simplemente definir un <em>volume claim</em>, y un <em>custom resource definition</em> (si queremos explorar la lista completa de los crds de awx instalados podemos ejecutar <code>kubectl get crds awxs.awx.ansible.com  -o yaml</code>; para nuestro caso de uso vamos a crear un archivo yaml con el siguiente contenido:</p>

<pre><code class="language-yaml">---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-13-ansible-awx-postgres-13-0
  namespace: awx
spec:
  storageClassName: local-path
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
  name: ansible-awx
  namespace: awx
spec:
  service_type: nodeport
  postgres_storage_class: local-path
</code></pre>

<p>En mi caso le di un nombre al yaml, y luego lo apliqué contra el cluster ejecutando <code>kubectl apply -f awx_manifest_for_operator.yaml</code></p>

<p>Después de unos momentos, el namespace <code>awx</code> deberá tener los pods en ejecución:</p>

<pre><code class="language-bash">pulpo@pop-os:~$ kubectl get pods -n awx
NAME                                               READY   STATUS    RESTARTS      AGE
awx-operator-controller-manager-6569d67f4c-x5dbp   2/2     Running   5 (79m ago)   24h
ansible-awx-postgres-13-0                          1/1     Running   0             55m
ansible-awx-task-6b4b565686-cbdg5                  4/4     Running   0             54m
ansible-awx-web-799c7f78b5-dwr7k                   3/3     Running   0             52m
</code></pre>

<p>Finalmente, exponemos el deployment de awx</p>

<pre><code class="language-bash">kubectl expose deployment ansible-awx-web --name ansible-awx-web-svc --type NodePort -n awx
</code></pre>

<p>Obtenemos la password de admin que está guardada en un secreto de kubernetes:</p>

<pre><code class="language-bash">kubectl get secret ansible-awx-admin-password -o jsonpath=&#34;{.data.password}&#34; -n awx | base64 --decode ; echo
</code></pre>

<p>Y accedemos al puerto que haya creado el deployment (si no lo sabemos, lo obtenemos listando los svc):</p>

<pre><code>pulpo@pop-os:~$ kubectl get svc -n awx ansible-awx-web-svc
NAME                  TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
ansible-awx-web-svc   NodePort   10.43.66.87   &lt;none&gt;        8052:30087/TCP   53m
</code></pre>

<p><img src="https://codimd.labs.openbits.com.ar/uploads/upload_0b9a75fd8f4ea89fcd266f14f89ffb27.png" alt=""></p>
]]></content:encoded>
      <guid>https://blog.labs.openbits.com.ar/instalar-awx-operator-en-k3s</guid>
      <pubDate>Sun, 14 Jan 2024 15:03:21 +0000</pubDate>
    </item>
    <item>
      <title>Multiarch build en k3s con tekton</title>
      <link>https://blog.labs.openbits.com.ar/multiarch-build-en-k3s-con-tekton</link>
      <description>&lt;![CDATA[Mi hijo me pidió que le arme un blog, como me gusta complicar las cosas,   esto me llevó a revivir una vieja raspberry que tenía problemas con el voltaje y por lo tanto no estaba usando, y aprovechando unos días de vacaciones, me puse a trabajar (era el cable el problema, y no la placa como alguna vez pensé). &#xA;&#xA;Durante muchos años tuve este blog en linea corriendo en su propio hardware,  en ese momento me parecía buena idea mantenerme con la arquitectura ARM v7 (32 bits) ya que era lo mas popular por fuera del mundo intel/amd, pero siendo que estamos en 2023, cobra sentido montar algo utilizando una arquitectura acorde a los tiempos que vivimos, y decidí armar una imagen ARM v8 (64 bits). &#xA;&#xA;Hace varios años había armado con un gran amigo a Ñamandú, una solución que por lo divertido que estuvimos los últimos tres años no hemos vuelto a tocar, al medio era obvio que alguna solución iba a aparecer y que el costo de actualizar lo que habíamos hecho iba a ser superior a adaptar algo ya existente, es por eso que me puse a ver tekton y a  retomar las pruebas de multiarch building en el universo de buildah. &#xA;&#xA;Escapa al objetivo de este texto cubrir los fundamentos de tekton, que se pueden encontrar en la documentación oficial, me voy a enfocar en dejarme documentado para mi yo del futuro, las modificaciones que tuve que realizar sobre la task de buildah oficial &#xA;&#xA;Lo primero fue entender cuáles eran los comandos necesarios para hacer un build con buildah, generando un manifiesto mutliarquitectura, subiéndolo luego junto con las imágenes resultantes a un registro. &#xA;&#xA;Modificaciones en la task&#xA;&#xA;Dentro del script de la task, lo primero que hice fue agregar una configuración en /etc/containers/registries.conf que permitiese buscar imágenes en el registry de docker (docker.io), de esta forma si queremos buildear imágenes con referencias del tipo FROM alpine:latest no tendremos que modificarlas a algo como FROM docker.io/alpine:latest, como la idea es buildear imágenes de terceros, esto nos puede ser de mucha utilidad. &#xA;&#xA;echo &#39;unqualified-search-registries = [&#34;docker.io&#34;]&#39;     /etc/containers/registries.conf&#xA;&#xA;Luego, le agrego al script la creación de un manifest, utilizando buildah manifest create multiarchmanifest (el nombre del manifest no me importa, ya que lo uso temporalmente durante el tiempo de vida de la ejecución del pipeline). &#xA;&#xA;Posteriormente, modifico la linea de buildah bud para incluir el uso del manifest creado:&#xA;&#xA;buildah ${CERTDIRFLAG} --storage-driver=$(params.STORAGEDRIVER) bud \&#xA;      $(params.BUILDEXTRAARGS) --format=$(params.FORMAT) --manifest multiarchmanifest \&#xA;        --tls-verify=$(params.TLSVERIFY) --no-cache \&#xA;      -f $(params.DOCKERFILE) -t $(params.IMAGE):$(params.TAG) $(params.CONTEXT)&#xA;Luego reemplazo la linea de push (en el archivo final dejo los comments para que se entienda dónde fue el reemplazo), por un buildah manifest push&#xA;&#xA;buildah ${CERTDIRFLAG} --storage-driver=$(params.STORAGEDRIVER) manifest push \&#xA;               $(params.PUSHEXTRAARGS) --tls-verify=$(params.TLSVERIFY) \&#xA;               --digestfile /tmp/image-digest --rm multiarchmanifest \&#xA;               --format=$(params.FORMAT) docker://$(params.IMAGE):$(params.TAG) &#xA;También agregué un parámetro TAG a la tarea, de forma tal de que pueda luego definir en el pipelinerun el tag multiarch que quiero construir. &#xA;&#xA;El archivo resultante queda entonces definido como:&#xA;&#xA;---&#xA;apiVersion: tekton.dev/v1beta1&#xA;kind: Task&#xA;metadata:&#xA;  name: buildah&#xA;  labels:&#xA;    app.kubernetes.io/version: &#34;0.5&#34;&#xA;  annotations:&#xA;    tekton.dev/categories: Image Build&#xA;    tekton.dev/pipelines.minVersion: &#34;0.17.0&#34;&#xA;    tekton.dev/tags: image-build&#xA;    tekton.dev/platforms: &#34;linux/amd64,linux/s390x,linux/ppc64le,linux/arm64&#34;&#xA;spec:&#xA;  description:   -&#xA;    Buildah task builds source into a container image and&#xA;    then pushes it to a container registry.&#xA;&#xA;    Buildah Task builds source into a container image using Project Atomic&#39;s&#xA;    Buildah build tool.It uses Buildah&#39;s support for building from Dockerfiles,&#xA;    using its buildah bud command.This command executes the directives in the&#xA;    Dockerfile to assemble a container image, then pushes that image to a&#xA;    container registry.&#xA;&#xA;  params:&#xA;  name: IMAGE&#xA;    description: Reference of the image buildah will produce.&#xA;  name: BUILDERIMAGE&#xA;    description: The location of the buildah builder image.&#xA;    default: quay.io/buildah/stable:v1.30.0&#xA;  name: STORAGEDRIVER&#xA;    description: Set buildah storage driver&#xA;    default: overlay&#xA;  name: DOCKERFILE&#xA;    description: Path to the Dockerfile to build.&#xA;    default: ./Dockerfile&#xA;  name: CONTEXT&#xA;    description: Path to the directory to use as context.&#xA;    default: .&#xA;  name: TLSVERIFY&#xA;    description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS registry)&#xA;    default: &#34;true&#34;&#xA;  name: FORMAT&#xA;    description: The format of the built container, oci or docker&#xA;    default: &#34;oci&#34;&#xA;  name: BUILDEXTRAARGS&#xA;    description: Extra parameters passed for the build command when building images.&#xA;    default: &#34;&#34;&#xA;  name: PUSHEXTRAARGS&#xA;    description: Extra parameters passed for the push command when pushing images.&#xA;    type: string&#xA;    default: &#34;&#34;&#xA;  name: SKIPPUSH&#xA;    description: Skip pushing the built image&#xA;    default: &#34;false&#34;&#xA;  name: TAG&#xA;    description: Image tag &#xA;    default: &#34;latest&#34;&#xA;  workspaces:&#xA;  name: source&#xA;  name: sslcertdir&#xA;    optional: true&#xA;  name: dockerconfig&#xA;    description:   -&#xA;      An optional workspace that allows providing a .docker/config.json file&#xA;      for Buildah to access the container registry.&#xA;      The file should be placed at the root of the Workspace with name config.json.&#xA;    optional: true&#xA;  results:&#xA;  name: IMAGEDIGEST&#xA;    description: Digest of the image just built.&#xA;  name: IMAGEURL&#xA;    description: Image repository where the built image would be pushed to&#xA;  steps:&#xA;  name: build&#xA;    image: $(params.BUILDERIMAGE)&#xA;    workingDir: $(workspaces.source.path)&#xA;    script: |&#xA;      # add some extra config to search on docker.io and don&#39;t broke already well knowed images&#xA;      echo &#39;unqualified-search-registries = [&#34;docker.io&#34;]&#39;     /etc/containers/registries.conf&#xA;&#xA;      [[ &#34;$(workspaces.sslcertdir.bound)&#34; == &#34;true&#34; ]] &amp;&amp; CERTDIRFLAG=&#34;--cert-dir $(workspaces.sslcertdir.path)&#34;&#xA;      [[ &#34;$(workspaces.dockerconfig.bound)&#34; == &#34;true&#34; ]] &amp;&amp; export DOCKERCONFIG=&#34;$(workspaces.dockerconfig.path)&#34;&#xA;      buildah manifest create multiarchmanifest &#xA;      buildah ${CERTDIRFLAG} --storage-driver=$(params.STORAGEDRIVER) bud \&#xA;      $(params.BUILDEXTRAARGS) --format=$(params.FORMAT) --manifest multiarchmanifest \&#xA;        --tls-verify=$(params.TLSVERIFY) --no-cache \&#xA;      -f $(params.DOCKERFILE) -t $(params.IMAGE):$(params.TAG) $(params.CONTEXT)&#xA;      [[ &#34;$(params.SKIPPUSH)&#34; == &#34;true&#34; ]] &amp;&amp; echo &#34;Push skipped&#34; &amp;&amp; exit 0&#xA;      #      buildah ${CERTDIRFLAG} --storage-driver=$(params.STORAGEDRIVER) push \&#xA;      #        $(params.PUSHEXTRAARGS) --tls-verify=$(params.TLSVERIFY) \&#xA;      #        --digestfile /tmp/image-digest $(params.IMAGE):$(params.IMAGE) \&#xA;      #        docker://$(params.IMAGE):$(params.IMAGE) &#xA;      buildah ${CERTDIRFLAG} --storage-driver=$(params.STORAGEDRIVER) manifest push \&#xA;               $(params.PUSHEXTRAARGS) --tls-verify=$(params.TLSVERIFY) \&#xA;               --digestfile /tmp/image-digest --rm multiarchmanifest \&#xA;               --format=$(params.FORMAT) docker://$(params.IMAGE):$(params.TAG) &#xA; &#xA;      cat /tmp/image-digest | tee $(results.IMAGEDIGEST.path)&#xA;      echo -n &#34;$(params.IMAGE)&#34; | tee $(results.IMAGEURL.path)&#xA;    volumeMounts:&#xA;    name: varlibcontainers&#xA;      mountPath: /var/lib/containers&#xA;    securityContext:&#xA;      privileged: true&#xA;  volumes:&#xA;  name: varlibcontainers&#xA;    emptyDir: {}&#xA;&#xA;Creando el pipeline&#xA;&#xA;Vamos ahora a definir un archivo para alimentar tekton, para que este cree un pipelinerun. En el mismo llamamos a la tarea oficial de git-clone, con parámetros especifiando el repositorio de código que queremos construir, el nombre de la imagen (incluyendo el registry), y algunos parámetros adicionales para el build, y otros para el push. &#xA;&#xA;Para el build vamos a agregarle --jobs 3 --platform linux/arm,linux/arm64,linux/amd64, esto define las plataformas para las que vamos a construir la imagen, y adicionalmente le paso la cantidad de jobs en paralelo que quiero que ejecute (3, por las 3 plataformas). &#xA;&#xA;Para el caso del push, el parámetro --all permite que al hacer push del manifest, también se suban las imágenes contenidas en el índice de dicho manifesto. &#xA;&#xA;apiVersion: tekton.dev/v1beta1&#xA;kind: PipelineRun&#xA;metadata:&#xA;  generateName: buildah-writefreely-pipeline-run-&#xA;spec:&#xA;  pipelineSpec:&#xA;    workspaces:&#xA;      name: shared-workspace&#xA;      name: sslcertdir&#xA;        optional: true&#xA;      name: dockerconfig-ws&#xA;        optional: true&#xA;    tasks:&#xA;      name: fetch-repository&#xA;        taskRef:&#xA;          name: git-clone&#xA;        workspaces:&#xA;          name: output&#xA;            workspace: shared-workspace&#xA;        params:&#xA;          name: url&#xA;            value: https://github.com/writefreely/writefreely.git &#xA;          name: subdirectory&#xA;            value: &#34;&#34;&#xA;          name: deleteExisting&#xA;            value: &#34;true&#34;&#xA;      name: buildah&#xA;        taskRef:&#xA;          name: buildah&#xA;        runAfter:&#xA;        fetch-repository&#xA;        workspaces:&#xA;        name: source&#xA;          workspace: shared-workspace&#xA;        name: dockerconfig&#xA;          workspace: dockerconfig-ws&#xA;        params:&#xA;        name: IMAGE&#xA;          value: docker.io/jinetessl/writefreely &#xA;        name: BUILDEXTRAARGS&#xA;          value: --jobs 3 --platform linux/arm,linux/arm64,linux/amd64&#xA;        name: PUSHEXTRAARGS&#xA;          value: --all&#xA;        name: SKIPPUSH&#xA;          value: false &#xA;        name: FORMAT&#xA;          value: docker&#xA;  workspaces:&#xA;    name: shared-workspace&#xA;      volumeClaimTemplate:&#xA;        spec:&#xA;          accessModes:&#xA;            ReadWriteOnce&#xA;          resources:&#xA;            requests:&#xA;              storage: 1000Mi&#xA;    name: dockerconfig-ws&#xA;      secret:&#xA;        secretName: dockerconfig-secret&#xA;&#xA;Adicionalmente armé un secreto con las credenciales de auth para poder subir al registro de docker las imágenes resultantes:&#xA;&#xA;apiVersion: v1&#xA;kind: Secret&#xA;metadata:&#xA;  name: dockerconfig-secret&#xA;stringData:&#xA;  config.json: |&#xA;    {&#xA;      &#34;auths&#34;: {&#xA;        &#34;docker.io&#34;: {&#xA;          &#34;auth&#34;: &#34;XXXXXXXXXXXXXXX==&#34;&#xA;        }&#xA;      }&#xA;    }&#xA;Luego, tras realizar un kubectl create -f  con el archivo del pipeline run, tras unos minutos tengo una imagen multiarchitectura subida en el repositorio de imágenes, un amor!&#xA;&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>Mi hijo me pidió que le arme un blog, como me gusta complicar las cosas,   esto me llevó a revivir una vieja raspberry que tenía problemas con el voltaje y por lo tanto no estaba usando, y aprovechando unos días de vacaciones, me puse a trabajar (era el cable el problema, y no la placa como alguna vez pensé).</p>

<p>Durante muchos años tuve este blog en linea corriendo en su propio hardware,  en ese momento me parecía buena idea mantenerme con la arquitectura ARM v7 (32 bits) ya que era lo mas popular por fuera del mundo intel/amd, pero siendo que estamos en 2023, cobra sentido montar algo utilizando una arquitectura acorde a los tiempos que vivimos, y decidí armar una imagen ARM v8 (64 bits).</p>

<p><img src="https://buildah.io/images/buildah.png" alt=""></p>

<p>Hace varios años había armado con un gran amigo a <a href="https://gitlab.com/iotops/container-images/namandu" rel="nofollow">Ñamandú</a>, una solución que por lo divertido que estuvimos los últimos tres años no hemos vuelto a tocar, al medio era obvio que alguna solución iba a aparecer y que el costo de actualizar lo que habíamos hecho iba a ser superior a adaptar algo ya existente, es por eso que me puse a ver <a href="https://tekton.dev/" rel="nofollow"><strong>tekton</strong></a> y a  retomar las pruebas de multiarch building en el universo de <a href="https://buildah.io/" rel="nofollow"><strong>buildah</strong></a>.</p>

<p><img src="https://tekton.dev/images/tekton-horizontal-color.png" alt=""></p>

<p>Escapa al objetivo de este texto cubrir los fundamentos de tekton, que se pueden encontrar en la documentación oficial, me voy a enfocar en dejarme documentado para mi yo del futuro, las modificaciones que tuve que realizar sobre la <a href="https://hub.tekton.dev/tekton/task/buildah" rel="nofollow">task de buildah oficial</a></p>

<p>Lo primero fue entender cuáles eran los comandos necesarios para hacer un build con buildah, generando un manifiesto mutliarquitectura, subiéndolo luego junto con las imágenes resultantes a un registro.</p>

<h2 id="modificaciones-en-la-task">Modificaciones en la task</h2>

<p>Dentro del script de la task, lo primero que hice fue agregar una configuración en <code>/etc/containers/registries.conf</code> que permitiese buscar imágenes en el registry de docker (docker.io), de esta forma si queremos buildear imágenes con referencias del tipo <code>FROM alpine:latest</code> no tendremos que modificarlas a algo como <code>FROM docker.io/alpine:latest</code>, como la idea es buildear imágenes de terceros, esto nos puede ser de mucha utilidad.</p>

<pre><code class="language-bash">echo &#39;unqualified-search-registries = [&#34;docker.io&#34;]&#39; &gt;&gt; /etc/containers/registries.conf
</code></pre>

<p>Luego, le agrego al script la creación de un manifest, utilizando <code>buildah manifest create multiarchmanifest</code> (el nombre del manifest no me importa, ya que lo uso temporalmente durante el tiempo de vida de la ejecución del pipeline).</p>

<p>Posteriormente, modifico la linea de <code>buildah bud</code> para incluir el uso del manifest creado:</p>

<pre><code class="language-bash">buildah ${CERT_DIR_FLAG} --storage-driver=$(params.STORAGE_DRIVER) bud \
      $(params.BUILD_EXTRA_ARGS) --format=$(params.FORMAT) --manifest multiarchmanifest \
        --tls-verify=$(params.TLSVERIFY) --no-cache \
      -f $(params.DOCKERFILE) -t $(params.IMAGE):$(params.TAG) $(params.CONTEXT)
</code></pre>

<p>Luego reemplazo la linea de push (en el archivo final dejo los comments para que se entienda dónde fue el reemplazo), por un <code>buildah manifest push</code></p>

<pre><code class="language-bash">buildah ${CERT_DIR_FLAG} --storage-driver=$(params.STORAGE_DRIVER) manifest push \
               $(params.PUSH_EXTRA_ARGS) --tls-verify=$(params.TLSVERIFY) \
               --digestfile /tmp/image-digest --rm multiarchmanifest \
               --format=$(params.FORMAT) docker://$(params.IMAGE):$(params.TAG) 
</code></pre>

<p>También agregué un parámetro TAG a la tarea, de forma tal de que pueda luego definir en el pipelinerun el tag multiarch que quiero construir.</p>

<p>El archivo resultante queda entonces definido como:</p>

<pre><code class="language-yaml">---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: buildah
  labels:
    app.kubernetes.io/version: &#34;0.5&#34;
  annotations:
    tekton.dev/categories: Image Build
    tekton.dev/pipelines.minVersion: &#34;0.17.0&#34;
    tekton.dev/tags: image-build
    tekton.dev/platforms: &#34;linux/amd64,linux/s390x,linux/ppc64le,linux/arm64&#34;
spec:
  description: &gt;-
    Buildah task builds source into a container image and
    then pushes it to a container registry.

    Buildah Task builds source into a container image using Project Atomic&#39;s
    Buildah build tool.It uses Buildah&#39;s support for building from Dockerfiles,
    using its buildah bud command.This command executes the directives in the
    Dockerfile to assemble a container image, then pushes that image to a
    container registry.

  params:
  - name: IMAGE
    description: Reference of the image buildah will produce.
  - name: BUILDER_IMAGE
    description: The location of the buildah builder image.
    default: quay.io/buildah/stable:v1.30.0
  - name: STORAGE_DRIVER
    description: Set buildah storage driver
    default: overlay
  - name: DOCKERFILE
    description: Path to the Dockerfile to build.
    default: ./Dockerfile
  - name: CONTEXT
    description: Path to the directory to use as context.
    default: .
  - name: TLSVERIFY
    description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS registry)
    default: &#34;true&#34;
  - name: FORMAT
    description: The format of the built container, oci or docker
    default: &#34;oci&#34;
  - name: BUILD_EXTRA_ARGS
    description: Extra parameters passed for the build command when building images.
    default: &#34;&#34;
  - name: PUSH_EXTRA_ARGS
    description: Extra parameters passed for the push command when pushing images.
    type: string
    default: &#34;&#34;
  - name: SKIP_PUSH
    description: Skip pushing the built image
    default: &#34;false&#34;
  - name: TAG
    description: Image tag 
    default: &#34;latest&#34;
  workspaces:
  - name: source
  - name: sslcertdir
    optional: true
  - name: dockerconfig
    description: &gt;-
      An optional workspace that allows providing a .docker/config.json file
      for Buildah to access the container registry.
      The file should be placed at the root of the Workspace with name config.json.
    optional: true
  results:
  - name: IMAGE_DIGEST
    description: Digest of the image just built.
  - name: IMAGE_URL
    description: Image repository where the built image would be pushed to
  steps:
  - name: build
    image: $(params.BUILDER_IMAGE)
    workingDir: $(workspaces.source.path)
    script: |
      # add some extra config to search on docker.io and don&#39;t broke already well knowed images
      echo &#39;unqualified-search-registries = [&#34;docker.io&#34;]&#39; &gt;&gt; /etc/containers/registries.conf

      [[ &#34;$(workspaces.sslcertdir.bound)&#34; == &#34;true&#34; ]] &amp;&amp; CERT_DIR_FLAG=&#34;--cert-dir $(workspaces.sslcertdir.path)&#34;
      [[ &#34;$(workspaces.dockerconfig.bound)&#34; == &#34;true&#34; ]] &amp;&amp; export DOCKER_CONFIG=&#34;$(workspaces.dockerconfig.path)&#34;
      buildah manifest create multiarchmanifest 
      buildah ${CERT_DIR_FLAG} --storage-driver=$(params.STORAGE_DRIVER) bud \
      $(params.BUILD_EXTRA_ARGS) --format=$(params.FORMAT) --manifest multiarchmanifest \
        --tls-verify=$(params.TLSVERIFY) --no-cache \
      -f $(params.DOCKERFILE) -t $(params.IMAGE):$(params.TAG) $(params.CONTEXT)
      [[ &#34;$(params.SKIP_PUSH)&#34; == &#34;true&#34; ]] &amp;&amp; echo &#34;Push skipped&#34; &amp;&amp; exit 0
      #      buildah ${CERT_DIR_FLAG} --storage-driver=$(params.STORAGE_DRIVER) push \
      #        $(params.PUSH_EXTRA_ARGS) --tls-verify=$(params.TLSVERIFY) \
      #        --digestfile /tmp/image-digest $(params.IMAGE):$(params.IMAGE) \
      #        docker://$(params.IMAGE):$(params.IMAGE) 
      buildah ${CERT_DIR_FLAG} --storage-driver=$(params.STORAGE_DRIVER) manifest push \
               $(params.PUSH_EXTRA_ARGS) --tls-verify=$(params.TLSVERIFY) \
               --digestfile /tmp/image-digest --rm multiarchmanifest \
               --format=$(params.FORMAT) docker://$(params.IMAGE):$(params.TAG) 
 
      cat /tmp/image-digest | tee $(results.IMAGE_DIGEST.path)
      echo -n &#34;$(params.IMAGE)&#34; | tee $(results.IMAGE_URL.path)
    volumeMounts:
    - name: varlibcontainers
      mountPath: /var/lib/containers
    securityContext:
      privileged: true
  volumes:
  - name: varlibcontainers
    emptyDir: {}
</code></pre>

<h2 id="creando-el-pipeline">Creando el pipeline</h2>

<p>Vamos ahora a definir un archivo para alimentar tekton, para que este cree un pipelinerun. En el mismo llamamos a la <a href="https://hub.tekton.dev/tekton/task/git-clone" rel="nofollow">tarea oficial de git-clone</a>, con parámetros especifiando el repositorio de código que queremos construir, el nombre de la imagen (incluyendo el registry), y algunos parámetros adicionales para el build, y otros para el push.</p>

<p>Para el <strong>build</strong> vamos a agregarle <code>--jobs 3 --platform linux/arm,linux/arm64,linux/amd64</code>, esto define las plataformas para las que vamos a construir la imagen, y adicionalmente le paso la cantidad de jobs en paralelo que quiero que ejecute (3, por las 3 plataformas).</p>

<p>Para el caso del <strong>push</strong>, el parámetro <code>--all</code> permite que al hacer push del manifest, también se suban las imágenes contenidas en el índice de dicho manifesto.</p>

<pre><code class="language-yaml">apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  generateName: buildah-writefreely-pipeline-run-
spec:
  pipelineSpec:
    workspaces:
      - name: shared-workspace
      - name: sslcertdir
        optional: true
      - name: dockerconfig-ws
        optional: true
    tasks:
      - name: fetch-repository
        taskRef:
          name: git-clone
        workspaces:
          - name: output
            workspace: shared-workspace
        params:
          - name: url
            value: https://github.com/writefreely/writefreely.git 
          - name: subdirectory
            value: &#34;&#34;
          - name: deleteExisting
            value: &#34;true&#34;
      - name: buildah
        taskRef:
          name: buildah
        runAfter:
        - fetch-repository
        workspaces:
        - name: source
          workspace: shared-workspace
        - name: dockerconfig
          workspace: dockerconfig-ws
        params:
        - name: IMAGE
          value: docker.io/jinetessl/writefreely 
        - name: BUILD_EXTRA_ARGS
          value: --jobs 3 --platform linux/arm,linux/arm64,linux/amd64
        - name: PUSH_EXTRA_ARGS
          value: --all
        - name: SKIP_PUSH
          value: false 
        - name: FORMAT
          value: docker
  workspaces:
    - name: shared-workspace
      volumeClaimTemplate:
        spec:
          accessModes:
            - ReadWriteOnce
          resources:
            requests:
              storage: 1000Mi
    - name: dockerconfig-ws
      secret:
        secretName: dockerconfig-secret

</code></pre>

<p>Adicionalmente armé un secreto con las credenciales de auth para poder subir al registro de docker las imágenes resultantes:</p>

<pre><code class="language-yaml">apiVersion: v1
kind: Secret
metadata:
  name: dockerconfig-secret
stringData:
  config.json: |
    {
      &#34;auths&#34;: {
        &#34;docker.io&#34;: {
          &#34;auth&#34;: &#34;XXXXXXXXXXXXXXX==&#34;
        }
      }
    }
</code></pre>

<p>Luego, tras realizar un <code>kubectl create -f</code> con el archivo del pipeline run, tras unos minutos tengo una imagen multiarchitectura subida en el repositorio de imágenes, un amor!</p>

<p><img src="https://codimd.labs.openbits.com.ar/uploads/upload_86e79b9d2142b9790caeed1eb6dc6e74.png" alt=""></p>
]]></content:encoded>
      <guid>https://blog.labs.openbits.com.ar/multiarch-build-en-k3s-con-tekton</guid>
      <pubDate>Sun, 07 May 2023 14:56:23 +0000</pubDate>
    </item>
    <item>
      <title>Acer Predator Helios 300 and Manjaro GNU/Linux</title>
      <link>https://blog.labs.openbits.com.ar/acer-predator-helios-300-and-manjaro-gnu-linux</link>
      <description>&lt;![CDATA[I recently decided to upgrade my notebook, after doing some research I found the Acer&#39;s Predator very attractive in terms of hardware features, so I decided to get one. &#xA;&#xA;The equipment has an intel i7 10th generation, 16 GB of RAM, an nvidia rtx2060, an incredible screen, and a badass look. &#xA;&#xA;When the equipment arrived, the first thing after unboxing it, was to try to install Manjaro on it. And this is how our journey starts. &#xA;&#xA;Enabling more possibilities, disabling Optane Data Raid&#xA;&#xA;To be able to let Manjaro recognize our hard disk, the first thing to do (and maybe the lazy path, because with researching maybe a better solution come up), it&#39;s to disable the Raid mode (useless in case you have one disk, and something that I prefer to solve by other ways if I need it in the future, for example, with LVM). &#xA;&#xA;To do it, you need to enter to the Predator&#39;s bios (pressing F2 after power up the machine), and enable a secret feature pressing Ctrl+s at the Main tab of the bios (in advance mode). From there, you will see the option SATA Mode, with can now be changed to AHCI.&#xA;&#xA;From there, you can advance into a standard installation, it&#39;s up to you to remove the windorch partition or resize it, and install our operative system. &#xA;&#xA;Installing nvidia drivers, i32 libs and optimus-manager&#xA;&#xA;After installing our system, we will need to install the nvidia&#39;s propietary drivers, they perfom really great with GNU/Linux. &#xA;&#xA;See which kernel do you have&#xA;&#xA;$ uname -a&#xA;Linux predatora 5.4.67-1-MANJARO #1 SMP PREEMPT Wed Sep 23 14:20:18 UTC 2020 x8664 GNU/Linux&#xA;&#xA;After that, install a matched driver&#xA;&#xA;sudo pacman -Sy nvidia&#xA;&#xA;And if it makes you any question, respond with something like linux54-rt-nvidia-450xx-450 that should match your kernel version and nvidia driver version (today, 450 was the latest).&#xA;&#xA;Also you will need some libs from the AUR if you want to play games with 32bits support (I like to use pikaur, but yay, yaourt, or another AUR manager can be used):&#xA;&#xA;pikaur lib32-nvidia-utils&#xA;&#xA;You will need to install optimus-manager to controll which GPU use, you can use the intel one, the nvidia one, or both&#xA;&#xA;pikaur optimus-manager&#xA;&#xA;It has a nice UI to config, that you can launch with optimus-manager-qt, but you will need first to enable and start the service&#xA;&#xA;sudo systemctl enable optimus-manager &amp;&amp; sudo systemctl start optimus-manager&#xA;&#xA;Enjoy&#xA;&#xA;Now you can choose whatever you want to play, at the time of this writting I&#39;m enjoying a lot to exlore a universe at No Man&#39;s Sky. &#xA;&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>I recently decided to upgrade my notebook, after doing some research I found the Acer&#39;s Predator very attractive in terms of hardware features, so I decided to get one.</p>

<p>The equipment has an intel i7 10th generation, 16 GB of RAM, an nvidia rtx2060, an incredible screen, and a badass look.</p>

<p>When the equipment arrived, the first thing after unboxing it, was to try to install Manjaro on it. And this is how our journey starts.</p>

<h2 id="enabling-more-possibilities-disabling-optane-data-raid">Enabling more possibilities, disabling Optane Data Raid</h2>

<p>To be able to let Manjaro recognize our hard disk, the first thing to do (and maybe the lazy path, because with researching maybe a better solution come up), it&#39;s to disable the Raid mode (useless in case you have one disk, and something that I prefer to solve by other ways if I need it in the future, for example, with LVM).</p>

<p>To do it, you need to enter to the Predator&#39;s bios (pressing F2 after power up the machine), and enable a <strong>s</strong>ecret feature pressing <strong>Ctrl+s</strong> at the <strong>Main</strong> tab of the bios (in advance mode). From there, you will see the option SATA Mode, with can now be changed to AHCI.</p>

<p><img src="https://codimd.labs.openbits.com.ar/uploads/upload_3939090d0ef31300853dc3e7f961e538.png" alt=""></p>

<p>From there, you can advance into a standard installation, it&#39;s up to you to remove the windorch partition or resize it, and install our operative system.</p>

<h2 id="installing-nvidia-drivers-i32-libs-and-optimus-manager">Installing nvidia drivers, i32 libs and optimus-manager</h2>

<p>After installing our system, we will need to install the nvidia&#39;s propietary drivers, they perfom really great with GNU/Linux.</p>

<p>See which kernel do you have</p>

<pre><code class="language-bash">$ uname -a
Linux predatora 5.4.67-1-MANJARO #1 SMP PREEMPT Wed Sep 23 14:20:18 UTC 2020 x86_64 GNU/Linux

</code></pre>

<p>After that, install a matched driver</p>

<pre><code class="language-bash">sudo pacman -Sy nvidia
</code></pre>

<p>And if it makes you any question, respond with something like <code>linux54-rt-nvidia-450xx-450</code> that should match your kernel version and nvidia driver version (today, 450 was the latest).</p>

<p>Also you will need some libs from the AUR if you want to play games with 32bits support (I like to use pikaur, but yay, yaourt, or another AUR manager can be used):</p>

<pre><code class="language-bash">pikaur lib32-nvidia-utils
</code></pre>

<p>You will need to install <strong>optimus-manager</strong> to controll which GPU use, you can use the intel one, the nvidia one, or both</p>

<pre><code class="language-bash">pikaur optimus-manager
</code></pre>

<p>It has a nice UI to config, that you can launch with <code>optimus-manager-qt</code>, but you will need first to enable and start the service</p>

<pre><code>sudo systemctl enable optimus-manager &amp;&amp; sudo systemctl start optimus-manager
</code></pre>

<p><img src="https://codimd.labs.openbits.com.ar/uploads/upload_d406d05775773ab286b67f7fcb530507.png" alt=""></p>

<h2 id="enjoy">Enjoy</h2>

<p>Now you can choose whatever you want to play, at the time of this writting I&#39;m enjoying a lot to exlore a universe at No Man&#39;s Sky.</p>

<p><img src="https://codimd.labs.openbits.com.ar/uploads/upload_255db326ea13cfd43e5ba52ec4a32081.png" alt=""></p>
]]></content:encoded>
      <guid>https://blog.labs.openbits.com.ar/acer-predator-helios-300-and-manjaro-gnu-linux</guid>
      <pubDate>Sun, 11 Oct 2020 21:26:42 +0000</pubDate>
    </item>
    <item>
      <title>chkrootkit with docker</title>
      <link>https://blog.labs.openbits.com.ar/chkrootkit-with-docker</link>
      <description>&lt;![CDATA[I had the need to do some chkrootkit scans, so I decided to use docker to do it. The reason? I was needing to perform scans on machines not beeing able to install anything, but with permission to execute docker. &#xA;&#xA;I wasn&#39;t comfortable with the idea of using someone&#39;s else container, so I got an autobuild system that I made with a friend some time ago, and put it to build and publish a fresh image which I&#39;m more comfortable with, that you can find at the docker hub. &#xA;&#xA;To lunch a scan, you only need to run&#xA;&#xA;You can find the source code here&#xA;&#xA;Enjoy!&#xA;&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>I had the need to do some chkrootkit scans, so I decided to use docker to do it. The reason? I was needing to perform scans on machines not beeing able to install anything, but with permission to execute docker.</p>

<p>I wasn&#39;t comfortable with the idea of using someone&#39;s else container, so I got an autobuild system that I made with a friend some time ago, and put it to build and publish a fresh image which I&#39;m more comfortable with, that you can find at the <a href="https://hub.docker.com/r/iotops/chkrootkit" rel="nofollow">docker hub</a>.</p>

<p><img src="https://codimd.labs.openbits.com.ar/uploads/upload_4feb89d689d4bfe1dc6bef72cf104cf5.png" alt=""></p>

<p>To lunch a scan, you only need to run</p>

<p><code>docker run --rm -it -v /:/target iotops/chkrootkit</code></p>

<p>You can find the source code <a href="https://gitlab.com/iotops/container-images/chkrootkit" rel="nofollow">here</a></p>

<p>Enjoy!</p>
]]></content:encoded>
      <guid>https://blog.labs.openbits.com.ar/chkrootkit-with-docker</guid>
      <pubDate>Sat, 26 Sep 2020 12:24:57 +0000</pubDate>
    </item>
    <item>
      <title>Nvidia, proton, archlinux, and Risk of Rain 2</title>
      <link>https://blog.labs.openbits.com.ar/nvidia-proton-archlinux-and-risk-of-rain-2</link>
      <description>&lt;![CDATA[&#xA;&#xA;I&#39;ve purchased an nvidia 1030 card to give some extra life to my old desktop (a 10 years old equipment that today belongs to my son, an 8 years old kid), I was surprised about the fact that the card was fully compatible with my hardware!&#xA;&#xA;The problems came when my friends, the ones with whom I made my engineering career, wanted to remember the old times, when we made groups to study and get our first jobs (and instead of that were spent playing video games). &#xA;&#xA;Some of those beloved friends (all were GNU/Linux users when they were young), now are using Mac, and for playing, Windows (except the aBatar, who still remain in the right path, and plays in a GNU/Linux box with an ati card). &#xA;&#xA;One of them, asked us to move the Friday&#39;s match of Risk of Rain, to the brand new Risk of Rain 2, and guess what, I found no excuses, today is possible to play Windows games on GNU/Linux, wine has evolved a lot, and with the Steam&#39;s Proton everything should work out of the box... until you try it!&#xA;&#xA;The problems started to appear, I was not even close to have the game working, and it were Thursday! I started to duckduckgo everything, but no clues were appearing.... until I read someone asking to someone else to run a vkcube, I tried at my system, and what I had was....&#xA;&#xA;$ vkcube &#xA;failed to initialize wayland, falling back to xcb&#xA;No Vulkan devices found.&#xA;&#xA;Going a little dipper into the problem, someone pointed to someone else to check if vulkan files were in place, I made and ls and I got:&#xA;&#xA;$ ls -l /usr/share/vulkan/icd.d/&#xA;total 12&#xA;-rwxr-xr-x 1 root root 126 ago  7 10:11 amdicd32.json&#xA;-rwxr-xr-x 1 root root 124 ago  7 09:55 amdicd64.json&#xA;-rw-r--r-- 1 root root 140 jul  9 13:06 nvidiaicd.json&#xA;&#xA;I have another friend, that once told me that computers are not deterministic systems, besides his joke, what I think is that is because the variables that make a system to be deterministic, should be set up... &#xA;&#xA;So, trying to kill the entropy of this old box, I found the missed variable:&#xA;&#xA;export VKICDFILENAMES=/usr/share/vulkan/icd.d/nvidiaicd.json&#xA;&#xA;And yes, the precious cube is at my screen! And it&#39;s not sucking at all! &#xA;&#xA;So, time to load the configuration into the Steam&#39;s client has arrived:&#xA;&#xA;My Fridays will be fun once again! &#xA;&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://codimd.labs.openbits.com.ar/uploads/upload_9b9d9293e5d7243222537c5c015731fb.png" alt=""></p>

<p>I&#39;ve purchased an nvidia 1030 card to give some extra life to my old desktop (a 10 years old equipment that today belongs to my son, an 8 years old kid), I was surprised about the fact that the card was fully compatible with my hardware!</p>

<p>The problems came when my friends, the ones with whom I made my engineering career, wanted to remember the old times, when we made groups to study and get our first jobs (and instead of that were spent playing video games).</p>

<p>Some of those beloved friends (all were GNU/Linux users when they were young), now are using Mac, and for playing, Windows (except the aBatar, who still remain in the right path, and plays in a GNU/Linux box with an ati card).</p>

<p>One of them, asked us to move the Friday&#39;s match of Risk of Rain, to the brand new <strong>Risk of Rain 2</strong>, and guess what, I found no excuses, today is possible to play Windows games on GNU/Linux, wine has evolved a lot, and with the Steam&#39;s Proton everything should work out of the box... until you try it!</p>

<p>The problems started to appear, I was not even close to have the game working, and it were Thursday! I started to duckduckgo everything, but no clues were appearing.... until I read someone asking to someone else to run a <code>vkcube</code>, I tried at my system, and what I had was....</p>

<pre><code>$ vkcube 
failed to initialize wayland, falling back to xcb
No Vulkan devices found.

</code></pre>

<p>Going a little dipper into the problem, someone pointed to someone else to check if vulkan files were in place, I made and <code>ls</code> and I got:</p>

<pre><code>$ ls -l /usr/share/vulkan/icd.d/
total 12
-rwxr-xr-x 1 root root 126 ago  7 10:11 amd_icd32.json
-rwxr-xr-x 1 root root 124 ago  7 09:55 amd_icd64.json
-rw-r--r-- 1 root root 140 jul  9 13:06 nvidia_icd.json
</code></pre>

<p>I have another friend, that once told me that computers are <strong>not deterministic systems</strong>, besides his joke, what I think is that is because the variables that make a system to be deterministic, should be set up...</p>

<p>So, trying to kill the entropy of this old box, I found the missed variable:</p>

<pre><code>export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json
</code></pre>

<p>And yes, the precious cube is at my screen! And it&#39;s not sucking at all!</p>

<p><img src="https://codimd.labs.openbits.com.ar/uploads/upload_0d6c6b9d0e26a52514166d0ae0e21f31.png" alt=""></p>

<p>So, time to load the configuration into the Steam&#39;s client has arrived:</p>

<p><img src="https://codimd.labs.openbits.com.ar/uploads/upload_bc50d29ecc7e0e4d283bcc5b2017b5b9.png" alt=""></p>

<p>My Fridays will be fun once again!</p>

<p><img src="https://codimd.labs.openbits.com.ar/uploads/upload_9100e11b8e3ce9de5220445766bdd3f7.png" alt=""></p>
]]></content:encoded>
      <guid>https://blog.labs.openbits.com.ar/nvidia-proton-archlinux-and-risk-of-rain-2</guid>
      <pubDate>Thu, 13 Aug 2020 23:13:57 +0000</pubDate>
    </item>
    <item>
      <title>K3s y Raspbian buster</title>
      <link>https://blog.labs.openbits.com.ar/k3s-y-raspbian-buster</link>
      <description>&lt;![CDATA[Si estás usando Raspbian buster, hay que tener en cuenta que para que funcione la conectividad de los pods hay que habilitar iptables ya que k3s no es capaz de trabajar con nftables.&#xA;&#xA;Dato adicional, si actualizan los paquetes y deja de funcionar, posiblemente actualizaron el kernel ;), hay que repetir los pasos. &#xA;---&#xA;&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>Si estás usando Raspbian buster, hay que tener en cuenta que para que funcione la conectividad de los pods hay que <a href="https://rancher.com/docs/k3s/latest/en/advanced/#enabling-legacy-iptables-on-raspbian-buster" rel="nofollow">habilitar iptables</a> ya que k3s no es capaz de trabajar con nftables.</p>

<p><img src="https://media.giphy.com/media/XUOa9APB3C2EE/giphy.gif" alt=""></p>

<p>Dato adicional, si actualizan los paquetes y deja de funcionar, posiblemente actualizaron el kernel ;), hay que repetir los pasos.</p>

<hr>
]]></content:encoded>
      <guid>https://blog.labs.openbits.com.ar/k3s-y-raspbian-buster</guid>
      <pubDate>Sat, 20 Jun 2020 13:41:30 +0000</pubDate>
    </item>
    <item>
      <title>Cómo manejar múltiples clusters de kubernetes</title>
      <link>https://blog.labs.openbits.com.ar/como-manejar-multiples-clusters-de-kubernetes</link>
      <description>&lt;![CDATA[A medida que empiezas a ver kubernetes como la solución universal para la gestión de tus contenedores (on-prem, cloud, dispositivos edge de IoT o red), empiezas a tener un problema, una gran cantidad de clusters. Si a esto le sumamos que no siempre trabajamos desde la misma máquina, llevar las múltiples configuraciones de un lugar a otro, suele ser un gran dolor de cabeza. &#xA;&#xA;Si el párrafo anterior te identifica en alguna forma, voy a mostrar cómo solucioné esto con dos herramientas, keybase y kubie.&#xA;&#xA;Keybase&#xA;&#xA;Si no conoces keybase quizás te estés perdiendo de una de las mejores soluciones de mensajería segura y servicio de intercambio de archivos, todo basado en PGP. Puntualmente de este sevicio lo que más interés me despierta es la posibilidad de poder contar con un disco de 250GB, encriptado, que puedo montar en la terminal que esté usando. &#xA;&#xA;Kubie&#xA;&#xA;Kubie es una alternativa a kubectx y kubens, y como indica su README, nos permite cambiar de contexto, namespace, y lo mejor, soporta archivos de configuración separados, es decir, puedo tener un archivo KUBECONFIG para cada uno de mis clusters, todos en diferentes locaciones. &#xA;&#xA;Cómo utilizo lo anterior&#xA;&#xA;El esquema que utilizo es bastante simple, considerando que keybase me da un filesystem privado en /run/user/1000/keybase/kbfs/private/${USER}, dentro creo un directorio donde coloco todas las configuraciones:&#xA;&#xA;$ ls -l /run/user/1000/keybase/kbfs/private/pulpo/configs/&#xA;total 25&#xA;-rw------- 1 pulpo root 1052 may 17 15:07 configbrawne.yaml&#xA;-rw------- 1 pulpo root 1057 mar 11 11:27 configcerebro.yaml&#xA;-rw------- 1 pulpo root 1050 mar  5 12:51 configpinky.yaml&#xA;-rw------- 1 pulpo root 1055 may 31 11:03 configpita.yaml&#xA;-rw------- 1 pulpo root 1052 abr 21 16:00 config_wendy.yaml&#xA;&#xA;Por lo que edito el archivo ~/.kube/kubie.yaml, apuntando a dicho directorio. &#xA;&#xA;configs:&#xA;    # Salida truncada para ejemplo&#xA;    # Include these globs.&#xA;    # Default: values listed below.&#xA;    include:&#xA;        /run/user/1000/keybase/kbfs/private/pulpo/configs/*.yaml&#xA;&#xA;    # Exclude these globs.&#xA;    # Default: values listed below.&#xA;    # Note: kubie&#39;s own config file is always excluded.&#xA;    exclude:&#xA;        ~/.kube/kubie.yaml&#xA;&#xA;Con esto, al ejecutar kubie ctx, puedo elegir sobre qué cluster trabajar. &#xA;&#xA;Una aclaración, el nombre que se muestra es el del contexto dentro de cada archivo .yaml, por lo que al armar cada configuración, cambia el context name. &#xA; &#xA;apiVersion: v1&#xA;clusters:&#xA;cluster:&#xA;    certificate-authority-data: DATA+OMITTED&#xA;    server: https://someip:6443&#xA;  name: default&#xA;contexts:&#xA;context:&#xA;    cluster: default&#xA;    namespace: dns&#xA;    user: default&#xA;  name: pita #Este es el nombre de contexto que deberías modificar&#xA;current-context: pita&#xA;kind: Config&#xA;preferences: {}&#xA;&#xA;---]]&gt;</description>
      <content:encoded><![CDATA[<p>A medida que empiezas a ver kubernetes como la solución universal para la gestión de tus contenedores (on-prem, cloud, dispositivos edge de IoT o red), empiezas a tener un problema, <strong>una gran cantidad de clusters</strong>. Si a esto le sumamos que no siempre trabajamos desde la misma máquina, llevar las múltiples configuraciones de un lugar a otro, suele ser un gran dolor de cabeza.</p>

<p>Si el párrafo anterior te identifica en alguna forma, voy a mostrar cómo solucioné esto con dos herramientas, <strong>keybase</strong> y <strong>kubie</strong>.</p>

<h2 id="keybase">Keybase</h2>

<p>Si no conoces <a href="https://keybase.io/" rel="nofollow">keybase</a> quizás te estés perdiendo de una de las mejores soluciones de mensajería segura y servicio de intercambio de archivos, todo basado en PGP. Puntualmente de este sevicio lo que más interés me despierta es la posibilidad de poder contar con un disco de 250GB, encriptado, que puedo montar en la terminal que esté usando.</p>

<h2 id="kubie">Kubie</h2>

<p><a href="https://github.com/sbstp/kubie" rel="nofollow">Kubie</a> es una alternativa a kubectx y kubens, y como indica su README, nos permite cambiar de contexto, namespace, y lo mejor, <strong>soporta archivos de configuración separados</strong>, es decir, puedo tener un archivo KUBECONFIG para cada uno de mis clusters, todos en diferentes locaciones.</p>

<h2 id="cómo-utilizo-lo-anterior">Cómo utilizo lo anterior</h2>

<p>El esquema que utilizo es bastante simple, considerando que keybase me da un filesystem privado en <code>/run/user/1000/keybase/kbfs/private/${USER}</code>, dentro creo un directorio donde coloco todas las configuraciones:</p>

<pre><code class="language-bash">$ ls -l /run/user/1000/keybase/kbfs/private/pulpo/configs/
total 25
-rw------- 1 pulpo root 1052 may 17 15:07 config_brawne.yaml
-rw------- 1 pulpo root 1057 mar 11 11:27 config_cerebro.yaml
-rw------- 1 pulpo root 1050 mar  5 12:51 config_pinky.yaml
-rw------- 1 pulpo root 1055 may 31 11:03 config_pita.yaml
-rw------- 1 pulpo root 1052 abr 21 16:00 config_wendy.yaml

</code></pre>

<p>Por lo que edito el archivo <code>~/.kube/kubie.yaml</code>, apuntando a dicho directorio.</p>

<pre><code class="language-yaml">configs:
    # Salida truncada para ejemplo
    # Include these globs.
    # Default: values listed below.
    include:
        - /run/user/1000/keybase/kbfs/private/pulpo/configs/*.yaml

    # Exclude these globs.
    # Default: values listed below.
    # Note: kubie&#39;s own config file is always excluded.
    exclude:
        - ~/.kube/kubie.yaml

</code></pre>

<p>Con esto, al ejecutar <code>kubie ctx</code>, puedo elegir sobre qué cluster trabajar.</p>

<p>Una aclaración, el nombre que se muestra es el del contexto dentro de cada archivo .yaml, por lo que al armar cada configuración, cambia el context name.</p>

<pre><code class="language-yaml">apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://someip:6443
  name: default
contexts:
- context:
    cluster: default
    namespace: dns
    user: default
  name: pita #Este es el nombre de contexto que deberías modificar
current-context: pita
kind: Config
preferences: {}

</code></pre>

<p><img src="https://raw.githubusercontent.com/sbstp/kubie/master/assets/logo.svg" alt=""></p>

<hr>
]]></content:encoded>
      <guid>https://blog.labs.openbits.com.ar/como-manejar-multiples-clusters-de-kubernetes</guid>
      <pubDate>Sun, 31 May 2020 21:34:43 +0000</pubDate>
    </item>
    <item>
      <title>CuentaCuentos</title>
      <link>https://blog.labs.openbits.com.ar/cuentacuentos</link>
      <description>&lt;![CDATA[&#xA;&#xA;Objetivo Principal&#xA;&#xA;Crear una plataforma para que alumnas y alumnos de instituciones educativas puedan compartir cuentos con sus compañeros de forma audiovisual.&#xA;&#xA;Objetivo Secundario&#xA;&#xA;La institución debe ser la dueña del contenido, entendiendo como dueño a quien pueda:&#xA;&#xA;Subir material a la plataforma&#xA;Compartir el material&#xA;Limitar los grupos de exposición del mismo&#xA;Destruir el material&#xA;&#xA;El uso de la plataforma idealmente debe ser lo más parecido posible a plataformas como YouTube, para facilitar su adopción y consumo, pero removiendo los componentes de ludificación que posee la misma, a fin de evitar la manipulación en el comportamiento que dichos componentes generan (likes, dislikes, contador de vistas).&#xA;&#xA;Motivación&#xA;&#xA;La necesidad de distanciamiento físico necesaria para disminuir la propagación del virus COVID-19 ha obligado a las instituciones educativas a cambiar su modalidad de dictados de clases, y buscar por lo tanto nuevas herramientas que ofrezcan a los alumnos la motivación suficiente para estudiar desde sus hogares. En el marco de dicha situación, fue que en la Escuela Domingo Faustino Sarmiento, ubicada en el barrio Amuchástegui (La Quebrada) del Municipio de Río Ceballos, el curso de 2do grado, turno tarde, coordinado por la maestra María Laura, para fomentar la lectura de cuentos fue compartiendo mediante un grupo de WhatsApp videos de los alumnos realizando lecturas de textos a sus compañeros. &#xA;&#xA;Dado el alcance que hoy tienen los videos de la plataforma YouTube, fue como Nati, madre de uno de los alumnos, propuso conjuntamente con la maestra de grado, el armado de una plataforma para que el alumnado pueda compartir dichos videos, teniendo en cuenta algunos puntos:&#xA;&#xA;No subir el material en una plataforma cuyo objetivo es la monetización de contenido&#xA;Evitar técnicas de ludificación que destaquen cierto contenido sobre otro&#xA;Permitir a la institución ser la efectiva dueña de sus datos, entendiendo que para ello se debe tener control de todo el ciclo de vida de la información, incluso de su destrucción&#xA;Los cuentos estarán accesibles tanto de forma audiovisual (en diferentes resoluciones para permitir su consumo desde diversos dispositivos y con acceso limitado a internet) como así también solamente en audio (para aquellas familias que no cuenten con una conexión estable, y solamente puedan descargar audio)&#xA;Se debe permitir la incrustación de subtítulos&#xA;Se debe permitir realizar comentarios sobre los videos&#xA;&#xA;Tecnologías utilizadas&#xA;&#xA;Teniendo en cuenta los puntos de la sección Motivación, se armó una plataforma utilizando herramientas de Código Abierto, ya que quienes estamos colaborando en la creación de la misma la misma creemos en las libertades que garantiza el Software Libre:&#xA;&#xA;La libertad de usar el programa, con cualquier propósito (uso)&#xA;La libertad de estudiar cómo funciona el programa y modificarlo, adaptándolo a las propias necesidades (estudio)&#xA;La libertad de distribuir copias del programa, con lo cual se puede ayudar a otros usuarios (distribución)&#xA;La libertad de mejorar el programa y hacer públicas esas mejoras a los demás, de modo que la comunidad se beneficie (mejora)&#xA;&#xA;Requerimientos Software&#xA;&#xA;A tal efecto utilizamos para dicho proyecto:&#xA;&#xA;Sistema Operativo: GNU/Linux&#xA;Orquestación de contenedores: k3s&#xA;Plataforma de video: PeerTube&#xA;Sistema de Base de Datos: PostgreSQL&#xA;Cache: Redis&#xA;&#xA;Requerimientos Infraestructura&#xA;&#xA;A nivel hardware, se necesita un servidor con 2 CPU Cores (1 CPU se dedicará a hacer transcode), 2 GB de RAM, y espacio de almacenamiento para los videos (esto determinará cuántos videos se podrán subir a la plataforma). &#xA;&#xA;Según lo reportado en la página de PeerTube, la operación de la plataforma realiza el siguiente consumo:&#xA;&#xA;    CPU -  nginx ~ 20%, peertube ~ 10%, postgres ~ 1%, redis ~ 3%&#xA;    RAM -  nginx ~ 6MB, peertube ~ 120MB, postgres ~ 10MB, redis ~ 5MB&#xA;&#xA;También se necesita contar con un dominio válido a fin de poder disponibilizar el sitio mediante una URL, y un certificado SSL para validar dicho dominio. El mecanismo de obtención y renovación de dicho certificado se automatizará utilizando cert-manager y letsencrypt. &#xA;&#xA;Arquitectura&#xA;&#xA;---&#xA;&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://pulpo.keybase.pub/img/cuentacuentos/banner.jpeg" alt=""></p>

<h2 id="objetivo-principal">Objetivo Principal</h2>

<p>Crear una plataforma para que alumnas y alumnos de instituciones educativas puedan compartir cuentos con sus compañeros de forma audiovisual.</p>

<h3 id="objetivo-secundario">Objetivo Secundario</h3>

<p>La institución debe ser la dueña del contenido, entendiendo como dueño a quien pueda:</p>
<ul><li>Subir material a la plataforma</li>
<li>Compartir el material</li>
<li>Limitar los grupos de exposición del mismo</li>
<li>Destruir el material</li></ul>

<p>El uso de la plataforma idealmente debe ser lo más parecido posible a plataformas como YouTube, para facilitar su adopción y consumo, pero removiendo los componentes de ludificación que posee la misma, a fin de evitar la manipulación en el comportamiento que dichos componentes generan (likes, dislikes, contador de vistas).</p>

<h2 id="motivación">Motivación</h2>

<p>La necesidad de distanciamiento físico necesaria para disminuir la propagación del virus COVID-19 ha obligado a las instituciones educativas a cambiar su modalidad de dictados de clases, y buscar por lo tanto nuevas herramientas que ofrezcan a los alumnos la motivación suficiente para estudiar desde sus hogares. En el marco de dicha situación, fue que en la Escuela Domingo Faustino Sarmiento, ubicada en el barrio Amuchástegui (La Quebrada) del Municipio de Río Ceballos, el curso de 2do grado, turno tarde, coordinado por la maestra María Laura, para fomentar la lectura de cuentos fue compartiendo mediante un grupo de WhatsApp videos de los alumnos realizando lecturas de textos a sus compañeros.</p>

<p>Dado el alcance que hoy tienen los videos de la plataforma YouTube, fue como Nati, madre de uno de los alumnos, propuso conjuntamente con la maestra de grado, el armado de una plataforma para que el alumnado pueda compartir dichos videos, teniendo en cuenta algunos puntos:</p>
<ul><li>No subir el material en una plataforma cuyo objetivo es la monetización de contenido</li>
<li>Evitar técnicas de ludificación que destaquen cierto contenido sobre otro</li>
<li>Permitir a la institución ser la efectiva dueña de sus datos, entendiendo que para ello se debe tener control de todo el ciclo de vida de la información, incluso de su destrucción</li>
<li>Los cuentos estarán accesibles tanto de forma audiovisual (en diferentes resoluciones para permitir su consumo desde diversos dispositivos y con acceso limitado a internet) como así también solamente en audio (para aquellas familias que no cuenten con una conexión estable, y solamente puedan descargar audio)</li>
<li>Se debe permitir la incrustación de subtítulos</li>
<li>Se debe permitir realizar comentarios sobre los videos</li></ul>

<h2 id="tecnologías-utilizadas">Tecnologías utilizadas</h2>

<p>Teniendo en cuenta los puntos de la sección Motivación, se armó una plataforma utilizando herramientas de Código Abierto, ya que quienes estamos colaborando en la creación de la misma la misma creemos en las libertades que garantiza el Software Libre:</p>
<ol><li>La libertad de usar el programa, con cualquier propósito (<strong>uso</strong>)</li>
<li>La libertad de estudiar cómo funciona el programa y modificarlo, adaptándolo a las propias necesidades (<strong>estudio</strong>)</li>
<li>La libertad de distribuir copias del programa, con lo cual se puede ayudar a otros usuarios (<strong>distribución</strong>)</li>
<li>La libertad de mejorar el programa y hacer públicas esas mejoras a los demás, de modo que la comunidad se beneficie (<strong>mejora</strong>)</li></ol>

<h3 id="requerimientos-software">Requerimientos Software</h3>

<p>A tal efecto utilizamos para dicho proyecto:</p>
<ul><li>Sistema Operativo: GNU/Linux</li>
<li>Orquestación de contenedores: <a href="https://github.com/rancher/k3s/blob/master/LICENSE" rel="nofollow">k3s</a></li>
<li>Plataforma de video: <a href="https://github.com/Chocobozzz/PeerTube/blob/develop/LICENSE" rel="nofollow">PeerTube</a></li>
<li>Sistema de Base de Datos: <a href="https://www.postgresql.org/about/licence/" rel="nofollow">PostgreSQL</a></li>
<li>Cache: <a href="https://redis.io/topics/license" rel="nofollow">Redis</a></li></ul>

<h3 id="requerimientos-infraestructura">Requerimientos Infraestructura</h3>

<p>A nivel hardware, se necesita un servidor con 2 CPU Cores (1 CPU se dedicará a hacer transcode), 2 GB de RAM, y espacio de almacenamiento para los videos (esto determinará cuántos videos se podrán subir a la plataforma).</p>

<p>Según lo reportado en la página de <a href="https://github.com/Chocobozzz/PeerTube/blob/develop/FAQ.md#should-i-have-a-big-server-to-run-peertube" rel="nofollow">PeerTube</a>, la operación de la plataforma realiza el siguiente consumo:</p>

<p>    CPU –&gt; nginx ~ 20%, peertube ~ 10%, postgres ~ 1%, redis ~ 3%
    RAM –&gt; nginx ~ 6MB, peertube ~ 120MB, postgres ~ 10MB, redis ~ 5MB</p>

<p>También se necesita contar con un dominio válido a fin de poder disponibilizar el sitio mediante una URL, y un certificado SSL para validar dicho dominio. El mecanismo de obtención y renovación de dicho certificado se automatizará utilizando cert-manager y letsencrypt.</p>

<h2 id="arquitectura">Arquitectura</h2>

<p><img src="https://pulpo.keybase.pub/img/cuentacuentos/DiagramaCC.png" alt=""></p>

<hr>
]]></content:encoded>
      <guid>https://blog.labs.openbits.com.ar/cuentacuentos</guid>
      <pubDate>Sat, 23 May 2020 17:02:43 +0000</pubDate>
    </item>
    <item>
      <title>How to use the Jinete&#39;s Repository for helm charts</title>
      <link>https://blog.labs.openbits.com.ar/how-to-use-the-jinetes-repository</link>
      <description>&lt;![CDATA[Based on IoTops repo at https://iotops.gitlab.io/charts&#xA;&#xA;To add our repo to your helm, just type:&#xA;&#xA;    helm repo add jinetes https://jsl3.gitlab.io/helmrepo&#xA;&#xA;To add a new chart, add it like a git submodule.&#xA;&#xA;Charts available&#xA;&#xA;PeerTube&#xA;&#xA;Peertube is an ActivityPub-federated video streaming platform using P2P directly in your web browser https://joinpeertube.org/&#xA;&#xA;helm install jinetes/peertube&#xA;&#xA;For customization see the chart at our Repository. &#xA;&#xA;Writefreely&#xA;&#xA;WriteFreely is free and open source software for building a writing space on the web — whether a publication, internal blog, or writing community in the fediverse.&#xA;&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>Based on IoTops repo at <a href="https://iotops.gitlab.io/charts" rel="nofollow">https://iotops.gitlab.io/charts</a></p>

<p>To add our repo to your helm, just type:</p>

<pre><code class="language-bash">    helm repo add jinetes https://jsl3.gitlab.io/helmrepo
</code></pre>

<p>To add a new chart, add it like a git submodule.</p>

<h2 id="charts-available">Charts available</h2>

<h3 id="peertube">PeerTube</h3>

<p><a href="https://github.com/Chocobozzz/PeerTube" rel="nofollow">Peertube</a> is an ActivityPub-federated video streaming platform using P2P directly in your web browser <a href="https://joinpeertube.org/" rel="nofollow">https://joinpeertube.org/</a></p>

<pre><code class="language-bash">helm install jinetes/peertube
</code></pre>

<p>For customization see the <a href="https://gitlab.com/jsl3/helmcharts/-/tree/master/peertube" rel="nofollow">chart at our Repository</a>.</p>

<h3 id="writefreely">Writefreely</h3>

<p><a href="https://writefreely.org/" rel="nofollow">WriteFreely</a> is free and open source software for building a writing space on the web — whether a publication, internal blog, or writing community in the fediverse.</p>

<p><img src="https://gitlab.com/jsl3/charla-k8s-la-punta-del-iceberg/-/raw/master/presentation/slides/images/jinetes-01.png" alt=""></p>
]]></content:encoded>
      <guid>https://blog.labs.openbits.com.ar/how-to-use-the-jinetes-repository</guid>
      <pubDate>Wed, 20 May 2020 03:01:48 +0000</pubDate>
    </item>
  </channel>
</rss>