Tutorial

Cómo desarrollar aplicaciones en Kubernetes con Okteto

DevelopmentOpen SourceKubernetesDigitalOcean Managed Kubernetes

El autor seleccionó Girls Who Code para recibir una donación como parte del programa Write for DOnations.

Introducción

La CLI de Okteto es un proyecto de código abierto que ofrece una experiencia de desarrollo local para las aplicaciones que se ejecutan en Kubernetes. Le permite escribir código en su IDE local e insertar los cambios en su clúster de Kubernetes al guardar el archivo para actualizar su aplicación de inmediato.  Todo este proceso sucede sin la necesidad de crear imágenes de Docker o aplicar manifiestos de Kubernetes, lo que puede tardar bastante tiempo.

En este tutorial, usará Okteto para mejorar su productividad al desarrollar aplicaciones nativas de Kubernetes. Primero, creará un clúster de Kubernetes y lo utilizará para ejecutar una aplicación “Hello World” estándar. Luego, usará Okteto para desarrollar y actualizar su aplicación automáticamente sin necesidad de instalar nada de forma local.

Requisitos previos

Como requisito previo para este tutorial, necesitará lo siguiente:

Paso 1: Crear la aplicación Hello World

El programa “Hello World” es una tradición en el desarrollo web. En este caso, se trata de un servicio web sencillo que responde “Hello World” a cualquier solicitud. Ahora que creó su clúster de Kubernetes, vamos a crear una aplicación “Hello World” en Golang y los manifiestos que usará para implementarla en Kubernetes.

Primero, diríjase a su directorio de inicio:

  • cd ~

Ahora, cree un directorio nuevo denominado hello_world y posiciónese en él:

  • mkdir hello_world
  • cd hello_world

Cree y abra un archivo nuevo con el nombre main.go con el editor de texto o IDE que prefiera:

  • nano main.go

main.go será un servidor web de Golang que devolverá el mensaje Hello world!. Por lo tanto, vamos a usar el siguiente código:

main.go
package main

import (
    "fmt"
    "net/http"
)

func main() {
    fmt.Println("Starting hello-world server...")
    http.HandleFunc("/", helloServer)
    if err := http.ListenAndServe(":8080", nil); err != nil {
        panic(err)
    }
}

func helloServer(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello world!")
}

El código en main.go hace lo siguiente:

  • La primera instrucción de los archivos de origen de Go debe ser el nombre de package. Los comandos ejecutables siempre deben usar package main.
  • La sección import indica de qué paquetes depende el código. En este caso, utiliza fmt para la manipulación de cadenas y net/http para el servidor HTTP.
  • La función main es el punto de entrada de su binario. El método http.HandleFunc se utiliza para configurar el servidor para que invoque la función helloServer cuando se reciba una solicitud a la ruta /. http.ListenAndServe inicia un servidor HTTP que escucha en todas las interfaces de red del puerto 8080.
  • La función helloServer contiene la lógica de su controlador de solicitudes. En este caso, escribirá Hello world! como respuesta a la solicitud.

Debe crear una imagen de Docker y aplicarla a su registro de Docker para que Kubernetes pueda extraerla y ejecutar la aplicación.

Abra un archivo nuevo con el nombre Dockerfile con el editor de texto o IDE que prefiera:

  • nano Dockerfile

El Dockerfile contendrá los comandos necesarios para crear el contenedor de Docker de su aplicación. Usemos el siguiente código:

Dockerfile
FROM golang:alpine as builder
RUN apk --update --no-cache add bash
WORKDIR /app
ADD . .
RUN go build -o app

FROM alpine as prod
WORKDIR /app
COPY --from=builder /app/app /app/app
EXPOSE 8080
CMD ["./app"]

El Dockerfile contiene dos etapas: builder y prod:

  • La etapa builder contiene las herramientas de compilación de Go. Es responsable de copiar archivos y crear el binario Go.
  • La etapa prop es la imagen final. Contendrá solo un SO básico y el binario de la aplicación.

Esta es una práctica recomendable para seguir. Hace que sus contenedores de producción sean más pequeños y seguros, dado que solo contienen su aplicación y exactamente lo que se necesita para ejecutarla.

Configure la imagen del contenedor (reemplace your_DockerHub_username por su nombre de usuario de Docker Hub):

  • docker build -t your_DockerHub_username/hello-world:latest

Ahora, insértela en Docker Hub:

  • docker push your_DockerHub_username/hello-world:latest

A continuación, cree una nueva carpeta para los manifiestos de Kubernetes:

  • mkdir k8s

Al usar un manifiesto de Kubernetes, le indica a Kubernetes cómo desea que se ejecute su aplicación. Ahora, creará un objeto de implementación. Por lo tanto, cree un archivo nuevo denominado deployment.yaml con el editor de texto o IDE que prefiera:

  • nano k8s/deployment.yaml

El siguiente contenido describe un objeto de implementación de Kubernetes que ejecuta la imagen de Docker okteto/hello-world:latest. Añada este contenido a su archivo nuevo, pero, en su caso, sustituya okteto, enumerado después de la etiqueta image, por your_DockerHub_username:

~/hello_world/k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-world
spec:
  selector:
    matchLabels:
      app: hello-world
  replicas: 1
  template:
    metadata:
      labels:
        app: hello-world
    spec:
      containers:
      - name: hello-world
        image: your_DockerHub_username/hello-world:latest
        ports:
        - containerPort: 8080

El manifiesto de implementación tiene tres secciones principales:

  • metadata define el nombre de su implementación.
  • replicas define cuántas copias de ella quiere tener en ejecución.
  • template le indica a Kubernetes qué implementar y qué etiquetas añadir. En este caso, un solo contenedor, con la imagen okteto/hello-world:latest, que escucha en el puerto 8080 y tiene la etiqueta app: hello-world. Observe que esta etiqueta es la misma que se utiliza en la sección selector.

Ahora necesitará una forma de acceder a su aplicación. Puede exponer una aplicación en Kubernetes creando un objeto de servicio. Vamos a seguir utilizando manifiestos para hacerlo. Cree un archivo nuevo denominado service.yaml con el editor de texto o IDE que prefiera:

  • nano k8s/service.yaml

El siguiente contenido describe un servicio que expone el objeto de implementación hello-world, que, en segundo plano, utilizará el equilibrador de carga de DigitalOcean:

k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: hello-world
spec:
  type: LoadBalancer
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
      name: http
  selector:
    app: hello-world

El manifiesto de servicio tiene cuatro secciones principales:

  • metadata le indica a Kubernetes qué nombre darle a su servicio.
  • type le indica a Kubernetes cómo desea exponer su servicio. En este caso, lo expondrá externamente a través de equilibrador de carga de Digital Ocean.
  • La etiqueta ports le indica a Kubernetes qué puertos desea exponer y cómo asignarlos a su implementación. En este caso, expondrá el puerto 80 de forma externa y lo dirigirá al puerto 8080 de su implementación.
  • selector le indica a Kubernetes cómo dirigir el tráfico. En este caso, cualquier pod que contenga la etiqueta app:hello-world recibirá tráfico.

Ahora, tiene todo listo para implementar su aplicación “Hello World” en Kubernetes. Lo haremos a continuación.

Paso 2: Implementar su aplicación Hello World

En este paso, implementará su aplicación “Hello World” en Kubernetes, y, luego, verificará que funcione correctamente.

Comience por implementar su aplicación en Kubernetes:

  • kubectl apply -f k8s

Verá el siguiente resultado:

Output
deployment.apps "hello-world" created service "hello-world" created

Después de, aproximadamente, un minuto, podrá obtener la IP de su aplicación. Utilice este comando kubectl para verificar su servicio:

  • kubectl get service hello-world

Verá un resultado similar a este, en el que se enumerarán los objetos de servicio de Kubernetes. Tome nota de la IP de su aplicación en la columna EXTERNAL-IP:

Output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-world ClusterIP your_cluster_ip your_external_ip 8080/TCP 37s

Abra su navegador y vaya a your_external_ip, enumerada para su aplicación “Hello World”. Confirme que su aplicación esté funcionando de forma correcta antes de continuar con el siguiente paso.

Hello World Okteto

Hasta ahora, ha seguido una manera bastante tradicional de desarrollar aplicaciones con Kubernetes. Sin embargo, más adelante, cuando quiera cambiar el código de su aplicación, deberá crear y aplicar una imagen de Docker nueva y, luego, extraerla de Kubernetes. Este proceso puede tardar bastante tiempo. Okteto está diseñado para optimizar este desarrollo en un bucle interno. Veamos la CLI de Okteto y cómo puede ayudar.

Paso 3: Instalar la CLI de Okteto

Ahora, mejorará su productividad de desarrollo con Kubernetes al instalar la CLI de Okteto. La interfaz de línea de comandos de Okteto es un proyecto de código abierto que le permite sincronizar cambios en el código de la aplicación con una aplicación en ejecución en Kubernetes. Puede continuar usando el IDE, los depuradores y los compiladores que prefiera sin necesidad de confirmar, compilar, insertar o volver a implementar contenedores para probar su aplicación, tal como lo hizo en los pasos anteriores.

Para instalar la CLI de Okteto en una máquina con macOS o Linux, ejecute el siguiente comando:

  • curl https://get.okteto.com -sSfL | sh

Veamos este comando con mayor detenimiento:

  • El comando curl se utiliza para transferir datos desde y hacia un servidor.
  • El indicador -s suprime cualquier resultado.
  • El indicador -S muestra errores.
  • El indicador -f hace que se produzca un error en la solicitud ante errores de HTTP.
  • El indicador -L hace que la solicitud siga redireccionamientos.
  • El operador | canaliza el resultado al comando sh, que descargará e instalará el último binario de okteto en su máquina local.

Si está ejecutando Windows, de forma alternativa, puede descargar el archivo utilizando su navegador web y añadirlo manualmente a su $PATH.

Con la CLI de Okteto instalada, está listo para poner su aplicación “Hello World” en modo de desarrollo.

Paso 4: Poner la aplicación Hello World en modo de desarrollo

La CLI de Okteto está diseñada para sustituir la aplicación que se está ejecutando en un clúster de Kubernetes con el código que tiene en su máquina. Para hacerlo, Okteto utiliza la información proporcionada en un archivo de manifiesto de Okteto. Este archivo declara el objeto de implementación de Kubernetes que se intercambiará con su código local.

Cree un archivo nuevo denominado okteto.yaml con el editor de texto o IDE que prefiera:

  • nano okteto.yaml

Vamos a escribir un manifiesto básico en el que definirá el nombre del objeto de implementación, la imagen base de Docker que se utilizará y un shell.  Retomaremos esta información más adelante. Utilice el siguiente archivo de información de ejemplo:

okteto.yaml
name: hello-world
image: okteto/golang:1
workdir: /app
command: ["bash"]

Prepárese para poner su aplicación en modo de desarrollo ejecutando el siguiente comando:

  • okteto up
Output
✓ Development environment activated ✓ Files synchronized Namespace: default Name: hello-world Welcome to your development environment. Happy coding! default:hello-world /app>

El comando okteto up intercambia la aplicación “Hello World” en un entorno de desarrollo, lo que significa lo siguiente:

  • El contenedor de la aplicación Hello World se actualiza con la imagen de Docker okteto/golang:1. Esta imagen contiene las herramientas de desarrollo necesarias para compilar, probar, depurar y ejecutar la aplicación “Hello World”.

  • Se crea un servicio de sincronización de archivos para mantener sus cambios actualizados entre su sistema de archivos local y los pods de su aplicación.

  • Se inicia un shell remoto en su entorno de desarrollo. Ahora, puede compilar, probar y ejecutar su aplicación como si estuviera en su máquina local.

  • Cualquier proceso que ejecute en el shell remoto tendrá el mismo tráfico entrante, las mismas variables de entorno y los mismos volúmenes o secretos que los pods de la aplicación “Hello World” original. Esto, a su vez, le proporciona un entorno de desarrollo similar al de producción sumamente realista.

Ahora, en la misma consola, ejecute la aplicación como lo haría normalmente (sin compilar ni insertar una imagen de Docker) de la siguiente manera:

  • go run main.go
Output
Starting hello-world server...

La primera vez que ejecute la aplicación, Go descargará sus dependencias y compilará su aplicación. Espere a que este proceso termine y pruebe su aplicación abriendo su navegador y actualizando la página de su aplicación, tal como lo hizo anteriormente.

Ahora, está listo para comenzar a desarrollar directamente en Kubernetes.

Paso 5: Desarrollar directamente en Kubernetes

Vamos a comenzar a realizar cambios en la aplicación “Hello World” y, luego, veremos cómo se reflejan en Kubernetes.

Abra el archivo main.go con el editor de texto o IDE que prefiera. Por ejemplo, abra una consola separada y ejecute el siguiente comando:

  • nano main.go

Luego, cambie el mensaje de respuesta a Hello world from DigitalOcean!:

main.go
package main

import (
    "fmt"
    "net/http"
)

func main() {
    fmt.Println("Starting hello-world server...")
    http.HandleFunc("/", helloServer)
    if err := http.ListenAndServe(":8080", nil); err != nil {
        panic(err)
    }
}

func helloServer(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello world from DigitalOcean!")
}

Aquí es donde cambia su flujo de trabajo. En lugar de crear imágenes y volver a implementar contenedores para actualizar la aplicación “Hello World”, de Okteto sincronizará los cambios con su entorno de desarrollo de Kubernetes.

En la consola donde ejecutó el comando okteto up, cancele la ejecución go run main.go pulsando CTRL + C. Ahora, vuelva a ejecutar la aplicación:

  • default:hello-world /app> go run main.go
Output
Starting hello-world server...

Regrese al navegador y vuelva a cargar la página de su aplicación “Hello World”.

Hello world DigitalOcean”

Los cambios de su código se aplicaron de forma instantánea a Kubernetes, y sin necesidad de realizar ninguna confirmación, compilación o inserción.

Conclusión

Okteto transforma su clúster de Kubernetes en una plataforma de desarrollo completamente equipada con un solo clic. En este tutorial, instaló y configuró la CLI de Okteto para iterar los cambios de código directamente en Kubernetes tan rápido como los escribe. Ahora, puede dirigirse al repositorio de muestras de Okteto para aprender a usar Okteto con diferentes lenguajes de programación y depuradores.

Además, si comparte un clúster de Kubernetes con su equipo, considere darle a cada miembro acceso a un espacio de nombres de Kubernetes seguro, aislado de otros desarrolladores que trabajen en el mismo clúster. Okteto App, disponible en el Mercado de Kubernetes de DigitalOcean, también ofrece esta excelente funcionalidad.

Creative Commons License