Galería de fotos con Kubernetes
Tags: photos, kubernetes, okteto
Published: 2019-11-19 18:51:42

---
title: Galería de fotos con Kubernetes
published: true
date: 2019-11-19 00:00:00 UTC
tags: photos,kubernetes,okteto
canonical_url: https://jorge.aguilera.soy/blog/2019/okteto-gallery.html
---

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/](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](https://jorge.aguilera.soy/images/diag-b137384d70f1e3bedf1a9f859e441d04.png)

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

[https://viajes-jagedn.cloud.okteto.net](https://viajes-jagedn.cloud.okteto.net)

## 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