Galería de fotos con Kubernetes

En este artículo vamos a ver cómo podemos publicar una galería de fotos usando herramientas de kubernetes.

Este caso de uso no deja de ser una práctica básica de conceptos kubernetes como crear volúmenes, desplegar un servicio o ejecutar un job. Para ello podemos usar los servicios de cloud de cualquier provedor como Google, AWS, DigitalOcean, etc. En concreto voy a usar el cloud de Okteto por lo que si quieres seguir este ejemplo deberás haber creado una cuenta en él aunque en principio todo lo que voy a utilizar es kubernetes puro por lo que debería dar igual el proveedor.
Estoy dando mis primeros pasos en Kubernetes, aprendiendo sobre lo que leo y practico, así que puede ser (seguro) que alguna o todas las cosas que aquí cuente no tengan por ser la mejor solución.

Existen muchas plataformas para publicar fotos, tipo Instagram, Google Photos, etc pero en mi opinión todas tienen la "pega" de que pierdes la oportunidad de aprender así como que una vez subidas a estas plataformas pierdes el control de lo que subes. Como alternativa tenemos herramientas tipo Piwigo que es un gestor completo orientado a la fotografía (una especie de "el WordPress de la fotografía ) pero requiere una base de datos MySQL, tener PHP instalado …​ y sufrir los ataques típicos.

Sin embargo también existen multitud de programas que dado un directorio/subdirectorio con fotos nos generan un site estático (no necesita base de datos, ni lenguajes, puritito html y javascript para ejecutar en el browser del cliente). He probado varios pero para este ejercicio voy a usar Thumbshup https://thumbsup.github.io/ básicamente porque me ha parecido de los más rápidos y con suficientes opciones para poder tunear el resultado a tu gusto.

La idea final es tener desplegado un servicio Nginx que sirva un directorio generado previamente.

Idea

El siguiente diagrama resume la arquitectura que vamos a usar para desplegar nuestra static-gallery

diag b137384d70f1e3bedf1a9f859e441d04

Como se puede apreciar, básicamente tendremos dos "discos", uno donde copiaremos nuestras fotos y otro que contendrá el site ya convertido, un servidor Nginx que ofrecerá vía http el site convertido y un Job que ejecutará la generación del contenido cuando tengamos nuevas fotos.

El administrador (nosotros) copiaremos las fotos en el volumen photos usando el container nginx mientras que el visitante accederá a nginx vía http para verlas ya convertidas en el volumen generated

Preparación

Como se ha comentado lo primero que deberás tener es una cuenta en algún proveedor de Kubernetes (podrías usar minikube en local pero la idea es llegar a publicar el album en Internet). En este caso voy a usar mi cuenta en Okteto

En segundo lugar vamos a necesitar la herramienta de consola kubectl. Si prefieres usar herramientas gráficas en lugar de la línea de consola …​ este no es tu sitio.

En tercer lugar necesitaremos (obviamente) un directorio/subdirectorios con las fotos que queremos publicar

Por último necesitaremos bajarnos las credenciales de nuestro proveedor y configurar kubectl para que las use . Por ejemplo, en una consola lo primero que ejecutaré será:

$ export KUBECONFIG=$(pwd)/okteto-kube.config (1)
1 con $(pwd) ajusto a kubectl para que use una ruta absoluta a las credenciales

Volumenes

Lo primero que vamos a preparar son 2 volúmenes, uno donde copiaremos nuestros fotos que tenemos en local y otro donde volcaremos el static-site generado para que nginx lo lea

storage.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: example-source
spec:
  storageClassName: standard
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: example-gallery
spec:
  storageClassName: standard
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

En este fichero estamos especificando que queremos crear 2 volumenes (en realidad el volumen es uno y ya está creado en nuestra cuenta, lo que hacemos es reservar "trozos" de nuestro volumen)

Usaremos example-source como lugar donde copiar las fotos y example-gallery como lugar donde ubicar el static

$ kubectl apply -f storage.yaml

Copiar fotos

En kubernetes necesitas "montar" un volumen a alguna instancia para poder copiar (o extraer) ficheros de el mismo. Para este ejemplo vamos a usar el mismo container de nginx (aunque podríamos usar un busybox por ejemplo que es una imagen mínima)

nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ejemplo
spec:
  selector:
    matchLabels:
      app: ejemplo
  replicas: 1
  template:
    metadata:
      labels:
        app: ejemplo
    spec:
      containers:
      - name: ejemplo
        image: nginx:1.7.9
        ports:
        - containerPort: 80
        resources:
          limits:
            memory: "1024Mi"
          requests:
            memory: "1024Mi"
        volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: gallery
        - mountPath: /photos
          name: photos
      volumes:
        - name: gallery
          persistentVolumeClaim:
            claimName: 'example-gallery'
        - name: photos
          persistentVolumeClaim:
            claimName: 'example-source'

En este punto el volumen de interés es el llamado photos que se montará en la ruta /photos del contenedor.

Una vez desplegado podremos transferir nuestras fotos al volumen:

$ kubectl apply -f nginx.yaml (1)
$ kubectl  cp photos nginx:/input  (2)
$ kubectl delete -f nginx.yaml  (2)
deployment.apps "ejemplo" deleted
1 Habrá que esperar unos segundos para que el pod se cree
2 Copiamos nuestras fotos en local, photos, al volumen input
3 Una vez copiadas ya no necesitamos este container

Generar el site

Para generar el site vamos a usar una instancia de Thumbshup y la vamos a ejecutar como un job de una sóla ejecución

job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: thumbsup
spec:
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: thumbsup
        image: thumbsupgallery/thumbsup
        command: ["thumbsup","--input","/photos/photos","--output","/gallery"]
        volumeMounts:
          - mountPath: /photos
            name: input
          - mountPath: /gallery
            name: output
      volumes:
        - name: input
          persistentVolumeClaim:
            claimName: 'example-source'
        - name: output
          persistentVolumeClaim:
            claimName: 'example-gallery'

En este job montamos los dos volumenes y le indicamos a thumbsup cúal es el de entrada y cúal el de salida. Una vez que se ejecute el job tendremos en 'gallery' el site generado

$ kubectl apply -f job.yaml
job.batch/thumbsup created

$ kubectl get jobs.batch
NAME       COMPLETIONS   DURATION   AGE
thumbsup   1/1           25s        46s

Podemos ver que para este ejemplo, con solo un par de fotos, thumbsup ha tardado unos segundos

Nginx

Por último simplemente nos queda crear un pod donde un Nginx pueda servir el site generado previamente. Para ello vamos a volver a desplegar el mismo deployment de la parte de copy

$ kubectl apply -f nginx.yaml

y por último desplegaremos un service que conecte nuestro nginx con el mundo exterior

service.yaml
apiVersion: v1
kind: Service
metadata:
  name: ejemplo
  annotations:
    dev.okteto.com/auto-ingress: "true"
spec:
  type: ClusterIP
  ports:
    - name: "ejemplo"
      port: 80
  selector:
    app: ejemplo
$ kubectl apply -f service.yaml

Resultado

Si todo ha ido bien tendremos un site estático como este

Custom domain y Okteto

Actualmente Okteto no ofrece la posibilidad de customizar la aplicación con tu propio dominio pues es un producto orientado más al desarrollo pero quién sabe en un futuro próximo

Follow comments at Telegram channel

2019 - 2020 | Mixed with Bootstrap | Baked with JBake v2.6.4