tutoriales.com

Configuración y Despliegue de Microservicios Go con Docker y Kubernetes

Este tutorial te guiará a través del proceso de transformar tu aplicación Go en un microservicio contenerizado con Docker, para luego desplegarlo y gestionarlo de manera escalable y robusta usando Kubernetes. Cubriremos desde la creación de una imagen Docker hasta la configuración de despliegues, servicios y escalado automático.

Intermedio20 min de lectura4 views
Reportar error

🚀 Introducción: El Poder de Go, Docker y Kubernetes

En el mundo moderno del desarrollo de software, la velocidad, la escalabilidad y la fiabilidad son clave. Go, con su rendimiento excepcional y concurrencia nativa, es una elección fantástica para construir microservicios. Sin embargo, para que estos microservicios alcancen su máximo potencial en producción, necesitamos herramientas robustas para la contenerización y orquestación.

Aquí es donde Docker y Kubernetes entran en juego. Docker nos permite empaquetar nuestra aplicación Go junto con todas sus dependencias en una unidad portátil y reproducible, mientras que Kubernetes proporciona la plataforma para desplegar, escalar y gestionar esas unidades de manera eficiente en un clúster. Juntos, forman un trío imbatible para construir arquitecturas distribuidas modernas.

Este tutorial te equipará con los conocimientos necesarios para llevar tus microservicios Go desde el código fuente hasta un entorno de producción gestionado por Kubernetes, ¡paso a paso!

💡 Consejo: Asegúrate de tener Go instalado, junto con Docker Desktop (o Docker Engine y Docker Compose) y kubectl para interactuar con Kubernetes. También es útil tener una cuenta en un proveedor de nube o MiniKube para probar Kubernetes localmente.

🛠️ Requisitos Previos

Antes de sumergirnos en la acción, asegúrate de tener las siguientes herramientas instaladas en tu sistema:

  • Go: Versión 1.18 o superior.
go version
  • Docker: Docker Desktop para Windows/macOS o Docker Engine para Linux.
docker version
  • kubectl: La herramienta de línea de comandos de Kubernetes.
kubectl version --client
  • Minikube (opcional pero recomendado): Para ejecutar un clúster de Kubernetes localmente.
minikube version

📝 Creando un Microservicio Go Simple

Para este tutorial, crearemos un microservicio Go muy básico que expone un endpoint HTTP. Este será el servicio que luego contenerizaremos y desplegaremos.

Paso 1: Inicializar el Módulo Go

Crea un nuevo directorio para tu proyecto y inicializa un módulo Go:

mkdir go-microservice
cd go-microservice
go mod init go-microservice

Paso 2: Escribir el Código del Microservicio

Crea un archivo main.go con el siguiente contenido:

package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
)

func main() {
	// Obtener el puerto del entorno, o usar 8080 por defecto
	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		log.Printf("Recibida solicitud en: %s", r.URL.Path)
		fmt.Fprintf(w, "¡Hola desde mi microservicio Go! 🚀\n")
		fmt.Fprintf(w, "Versión: 1.0.0\n")
		fmt.Fprintf(w, "Puerto: %s\n", port)
	})

	http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		fmt.Fprintf(w, "OK\n")
	})

	log.Printf("Servidor Go escuchando en el puerto %s...", port)
	log.Fatal(http.ListenAndServe(":"+port, nil))
}

Este código crea un servidor HTTP simple que responde en la ruta / y tiene un endpoint /healthz para verificación de salud. El puerto se configura a través de la variable de entorno PORT, por defecto 8080.

Paso 3: Probar el Microservicio Localmente

Ejecuta tu aplicación Go:

go run main.go

Abre tu navegador o usa curl para acceder a http://localhost:8080 y http://localhost:8080/healthz. Deberías ver las respuestas correspondientes.


🐳 Contenerizando el Microservicio con Docker

Ahora que tenemos nuestro microservicio Go funcionando, es hora de empaquetarlo en una imagen Docker.

Paso 1: Crear un Dockerfile

Crea un archivo llamado Dockerfile (sin extensión) en la raíz de tu proyecto con el siguiente contenido:

# Etapa 1: Construcción de la aplicación Go
FROM golang:1.22-alpine AS builder

WORKDIR /app

COPY go.mod go.sum ./ 
RUN go mod download

COPY . .

RUN CGO_ENABLED=0 GOOS=linux go build -a -o /go-microservice .

# Etapa 2: Imagen final de ejecución más ligera
FROM alpine:latest

WORKDIR /root/

COPY --from=builder /go-microservice .

EXPOSE 8080

CMD ["/root/go-microservice"]
📌 Nota: Usamos un `Dockerfile` multi-stage para crear una imagen final muy pequeña. La primera etapa (`builder`) compila la aplicación, y la segunda etapa copia solo el binario compilado a una imagen `alpine` ligera. Esto reduce significativamente el tamaño de la imagen.

Paso 2: Construir la Imagen Docker

Desde el directorio raíz de tu proyecto, ejecuta el siguiente comando para construir la imagen. Sustituye tu-usuario-docker por tu nombre de usuario de Docker Hub o el prefijo que prefieras.

docker build -t tu-usuario-docker/go-microservice:v1.0.0 .

Esto creará una imagen Docker con la etiqueta v1.0.0.

Paso 3: Probar la Imagen Docker

Una vez construida la imagen, puedes ejecutarla localmente para verificar que funciona correctamente:

docker run -p 8080:8080 tu-usuario-docker/go-microservice:v1.0.0

De nuevo, accede a http://localhost:8080 en tu navegador. Deberías ver la misma respuesta que antes.

Paso 4: Subir la Imagen a un Registro (Opcional, pero recomendado para Kubernetes)

Para que Kubernetes pueda acceder a tu imagen, esta debe estar disponible en un registro de imágenes Docker (como Docker Hub o un registro privado).

docker push tu-usuario-docker/go-microservice:v1.0.0
🔥 Importante: Si usas Minikube o un clúster de Kubernetes local, puedes saltarte el `docker push` si configuras Minikube para usar el daemon Docker local (`eval $(minikube docker-env)`). Para clústeres remotos, el `push` es indispensable.
Go Go App Dockerfile Docker Build Docker Image PUSH Registry RUN (Local Test) genera Distribuir Ejecutar

☸️ Despliegue con Kubernetes: Conceptos Básicos

Ahora viene la parte emocionante: desplegar nuestro microservicio Go en Kubernetes. Necesitarás algunos archivos YAML para describir cómo quieres que Kubernetes gestione tu aplicación.

Conceptos Clave de Kubernetes

Antes de escribir YAML, revisemos algunos conceptos esenciales:

  • Pod: La unidad de despliegue más pequeña en Kubernetes. Un Pod contiene uno o más contenedores (nuestro microservicio Go). Los contenedores en un Pod comparten recursos y red.
  • Deployment: Un controlador que gestiona un conjunto de Pods idénticos. Asegura que un número específico de réplicas de tu aplicación estén siempre ejecutándose y facilita las actualizaciones.
  • Service: Un método para exponer tu aplicación (conjunto de Pods) a la red. Puede ser interno (para comunicación entre microservicios) o externo (para acceso desde fuera del clúster).
  • Namespace: Una forma de organizar los recursos de Kubernetes dentro de un clúster. Ayuda a aislar entornos (dev, prod) o aplicaciones.
Más sobre Tipos de Servicios Kubernetes

Kubernetes ofrece varios tipos de servicios para exponer tus aplicaciones:

  • ClusterIP: Por defecto. Expone el servicio en un IP interno del clúster. Solo accesible desde dentro del clúster.
  • NodePort: Expone el servicio en un puerto estático en cada Nodo del clúster. Permite el acceso desde fuera del clúster usando la IP de cualquier nodo y el puerto NodePort.
  • LoadBalancer: Para proveedores de nube, provisiona un balanceador de carga externo que dirige el tráfico a tu servicio.
  • **ExternalName: Mapea el servicio a un nombre DNS externo (CNAME). No proxy.

Para este tutorial, usaremos NodePort para facilitar el acceso desde fuera de Minikube. En un entorno de producción en la nube, LoadBalancer o un Ingress serían las opciones preferidas.


🚀 Desplegando el Microservicio Go en Kubernetes

Crearemos dos archivos YAML principales: uno para el Deployment y otro para el Service.

Paso 1: Configurar el Deployment YAML

Crea un archivo llamado deployment.yaml en la raíz de tu proyecto:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-microservice-deployment
  labels:
    app: go-microservice
spec:
  replicas: 2 # Queremos 2 instancias de nuestro microservicio
  selector:
    matchLabels:
      app: go-microservice
  template:
    metadata:
      labels:
        app: go-microservice
    spec:
      containers:
      - name: go-microservice-container
        image: tu-usuario-docker/go-microservice:v1.0.0 # ¡Asegúrate de usar tu imagen!
        ports:
        - containerPort: 8080
        env:
        - name: PORT
          value: "8080"
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5
        readinessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5
        resources:
          requests:
            memory: "64Mi"
            cpu: "100m"
          limits:
            memory: "128Mi"
            cpu: "200m"

Explicación del deployment.yaml:

  • apiVersion: apps/v1, kind: Deployment: Define que estamos creando un despliegue.
  • metadata.name, metadata.labels: Nombre y etiquetas para identificar el despliegue.
  • spec.replicas: 2: Le decimos a Kubernetes que queremos mantener 2 instancias (Pods) de nuestra aplicación ejecutándose.
  • spec.selector.matchLabels: Utilizado por el Deployment para encontrar qué Pods gestionar. Debe coincidir con las etiquetas del template.metadata.labels.
  • spec.template: Define la plantilla para los Pods que creará este Deployment.
  • spec.template.spec.containers: Lista de contenedores dentro de cada Pod.
    • name: Nombre del contenedor.
    • image: La imagen Docker que creamos y subimos.
    • ports: El puerto que expone el contenedor (8080 en nuestro caso).
    • env: Variables de entorno para el contenedor.
    • livenessProbe: Indica si el contenedor está vivo. Si falla, Kubernetes reiniciará el contenedor. Usa nuestro endpoint /healthz.
    • readinessProbe: Indica si el contenedor está listo para servir tráfico. Si falla, el Pod se eliminará del Service endpoint hasta que esté listo. También usa /healthz.
    • resources: Define los recursos (CPU, memoria) que un contenedor solicita (requests) y los límites máximos (limits). ¡Crucial para la estabilidad y el costo en producción!

Paso 2: Configurar el Service YAML

Crea un archivo llamado service.yaml en la raíz de tu proyecto:

apiVersion: v1
kind: Service
metadata:
  name: go-microservice-service
  labels:
    app: go-microservice
spec:
  selector:
    app: go-microservice # Selecciona los Pods con esta etiqueta
  ports:
    - protocol: TCP
      port: 80 # Puerto del Service
      targetPort: 8080 # Puerto del contenedor
      nodePort: 30007 # Opcional: un puerto específico en el nodo (rango 30000-32767)
  type: NodePort # Expone el servicio fuera del clúster a través de los nodos

Explicación del service.yaml:

  • apiVersion: v1, kind: Service: Define que estamos creando un servicio.
  • metadata.name, metadata.labels: Nombre y etiquetas para el servicio.
  • spec.selector.app: go-microservice: Este es el selector clave. El Service enviará tráfico a cualquier Pod que tenga la etiqueta app: go-microservice (nuestros Pods creados por el Deployment).
  • spec.ports: Configura el mapeo de puertos.
    • port: 80: El puerto en el que el Service escuchará internamente en el clúster.
    • targetPort: 8080: El puerto al que el Service enviará el tráfico dentro del contenedor.
    • nodePort: 30007: Especifica un puerto estático en cada nodo del clúster. Esto permite acceder a la aplicación desde fuera del clúster usando la IP del nodo y este puerto. Si no se especifica, Kubernetes asignará uno aleatoriamente en el rango 30000-32767.
  • type: NodePort: Expone el servicio en un puerto estático en cada nodo seleccionado del clúster.
⚠️ Advertencia: Para `NodePort`, asegúrate de que el puerto elegido (ej. `30007`) no esté ya en uso y esté dentro del rango permitido (normalmente 30000-32767). Si no especificas `nodePort`, Kubernetes elegirá uno por ti.

Paso 3: Desplegar en Kubernetes

Primero, si usas Minikube, asegúrate de que esté iniciado:

minikube start

Ahora, aplica tus archivos YAML a tu clúster de Kubernetes:

kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

Verifica el estado de tus recursos:

kubectl get deployments
kubectl get pods
kubectl get services

Deberías ver tu despliegue, tus dos Pods (uno o dos pueden estar en estado ContainerCreating por un momento) y tu servicio.

NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
go-microservice-deployment   2/2     2            2           2m

NAME                                            READY   STATUS    RESTARTS   AGE
go-microservice-deployment-7bb45c7b7b-abcdg   1/1     Running   0          2m
go-microservice-deployment-7bb45c7b7b-efghi   1/1     Running   0          2m

NAME                      TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
go-microservice-service   NodePort   10.101.10.101   <none>        80:30007/TCP   2m

Paso 4: Acceder al Microservicio

Si estás usando Minikube, puedes obtener la URL del servicio usando:

minikube service go-microservice-service --url

Esto te dará una URL como http://192.168.49.2:30007. Pega esta URL en tu navegador o usa curl para acceder a tu microservicio desplegado en Kubernetes.

Si estás en un clúster de Kubernetes remoto con un NodePort service, necesitarías la IP pública de uno de tus nodos de Kubernetes y el puerto NodePort (30007 en nuestro ejemplo).

Usuario / Cliente Minikube IP:NodePort (o LoadBalancer) Service go-microservice-service Deployment go-microservice-deployment Pod 1 Contenedor: go-microservice-container Pod 2 Contenedor: go-microservice-container KUBERNETES CLUSTER (Minikube)

📈 Escalado y Actualizaciones en Kubernetes

Una de las mayores ventajas de Kubernetes es su capacidad para escalar y gestionar las actualizaciones de tus aplicaciones de forma sencilla.

Escalado Manual

Puedes escalar el número de réplicas de tu Deployment fácilmente:

kubectl scale deployment go-microservice-deployment --replicas=5

Verifica los Pods de nuevo. Deberías ver 5 Pods ejecutándose:

kubectl get pods -l app=go-microservice

Para escalar hacia abajo, simplemente reduce el número de réplicas.

Escalado Automático (Horizontal Pod Autoscaler - HPA)

Para un entorno de producción, es más eficiente que Kubernetes escale tus Pods automáticamente en función de métricas como el uso de CPU o memoria. Esto se logra con el Horizontal Pod Autoscaler (HPA).

Primero, asegúrate de que tu clúster de Kubernetes tenga Metrics Server instalado (Minikube lo incluye por defecto).

Crea un HPA para tu despliegue:

kubectl autoscale deployment go-microservice-deployment --cpu-percent=50 --min=2 --max=10

Esto le dice a Kubernetes que escale el despliegue go-microservice-deployment a un mínimo de 2 y un máximo de 10 Pods, manteniendo el uso de CPU promedio por debajo del 50%.

Para ver el estado del HPA:

kubectl get hpa

Realizar una Actualización (Rolling Update)

Supongamos que queremos actualizar nuestro microservicio a una nueva versión (v1.0.1) con algún cambio menor.

1. Modificar el Código Go

Edita main.go para cambiar la versión:

	// ...
	fmt.Fprintf(w, "Versión: 1.0.1\n") // Cambiamos la versión aquí
	// ...

2. Reconstruir y Subir la Nueva Imagen Docker

docker build -t tu-usuario-docker/go-microservice:v1.0.1 .
docker push tu-usuario-docker/go-microservice:v1.0.1

3. Actualizar el Deployment en Kubernetes

Edita deployment.yaml para cambiar la imagen a la nueva versión (v1.0.1). Luego, aplica el cambio:

kubectl apply -f deployment.yaml

Kubernetes realizará un rolling update: creará nuevos Pods con la nueva versión mientras elimina gradualmente los Pods antiguos. Esto asegura que no haya tiempo de inactividad durante la actualización.

Puedes observar el progreso del rolling update:

kubectl rollout status deployment/go-microservice-deployment

Una vez completado, accede a tu microservicio de nuevo. Deberías ver la Versión: 1.0.1.

Deshacer una Actualización (Rollback)

Si la nueva versión tiene problemas, puedes revertir fácilmente a la versión anterior:

kubectl rollout undo deployment/go-microservice-deployment

Kubernetes revertirá a la revisión anterior del despliegue, creando Pods con la imagen anterior.

Despliegue Completo

🧹 Limpieza de Recursos

Cuando hayas terminado de experimentar, es una buena práctica limpiar los recursos de Kubernetes para evitar el consumo innecesario de recursos.

kubectl delete -f service.yaml
kubectl delete -f deployment.yaml

Si usaste Minikube, puedes detenerlo o eliminarlo completamente:

minikube stop # Para detener el clúster
minikube delete # Para eliminar el clúster completamente

✨ Conclusión

¡Felicidades! Has completado un viaje crucial en el desarrollo de microservicios Go. Has aprendido a crear una aplicación Go, contenerizarla con Docker y desplegarla eficientemente en Kubernetes.

Esta combinación de tecnologías te permite construir sistemas altamente escalables, robustos y fáciles de gestionar, sentando las bases para arquitecturas distribuidas modernas.

Paso 1: Desarrollar el microservicio Go.
Paso 2: Crear un Dockerfile y construir la imagen.
Paso 3: Subir la imagen a un registro Docker.
Paso 4: Definir Deployment y Service en YAML.
Paso 5: Desplegar en Kubernetes con `kubectl apply`.
Paso 6: Escalar y actualizar tu aplicación.

Explora más a fondo el ecosistema de Kubernetes: Ingress, ConfigMaps, Secrets, Persistent Volumes, Helm y mucho más para llevar tus microservicios al siguiente nivel.

Tutoriales relacionados

Comentarios (0)

Aún no hay comentarios. ¡Sé el primero!