Al finalizar el tutorial el estudiante estará en capacidad de:
En particular se utilizarán los siguientes recursos:
Para este tutorial manejaremos el repositorio de calculadora-numeros usado en los tutoriales pasados, en caso de no tenerlo clonado aún, puede consultarlo en el siguiente enlace. Trabajaremos sobre la rama feature/kubernetes-sum, para ello cambie la rama del repositorio actual al respectivo hash del tag, para hacerlo ejecute en su terminal:
user@192 ~ % git checkout feature/kubernetes-sum
En el repositorio hay una carpeta llamada saveNumber, esta contiene una aplicación de la calculador que se encarga de recibir un número por request (POST) y luego guardarlo en la base de datos. Pruebe un poco en su ambiente local este endpoint, para esto baje la siguiente imagen:
user@192 ~ % docker pull ghcr.io/misw-4301-desarrollo-apps-en-la-nube/s1-calculadora-numeros:vDatabase
Una vez descargada, ejecútela mediante:
user@192 ~ % docker run -d -p 4000:4000 ghcr.io/misw-4301-desarrollo-apps-en-la-nube/s1-calculadora-numeros:vDatabase
Una vez el contenedor esté en ejecución, pruebe el siguiente endpoint para almacenar un número.
user@192 ~ % curl --location --request POST 'http://0.0.0.0:4000/guardar_numero' \ --header 'Content-Type: application/json' \ --data-raw '{ "num_1": 399 }'
Obtendrá la confirmación de almacenamiento exitoso en una base de datos en disco de la contenedora (Usando SQLite).
{ "mensaje": "numero 399 guardado correctamente." }
Si se fija en esta línea, el código espera una variable de entorno llamada SQLALCHEMY_DATABASE_URI, si esta no es asignada por variable de entorno, simplemente redirecciona el ORM a la dirección de base de datos local. Ahora pruebe el endpoint para obtener el último número guardado en la base de datos, para esto ejecute el siguiente curl:
user@192 ~ % curl --location --request GET 'http://0.0.0.0:4000/ultimo_numero' \ --header 'Content-Type: application/json'
Obtendrá como respuesta el último número guardado:
{ "ultimo_valor": 399 }
Ahora pondremos en práctica el tutorial de container registry, necesitamos crear una imagen de este nuevo endpoint en su proyecto designado de GCP, para esto navegue al directorio /saveNumber y ejecute el siguiente comando para crear la respectiva imagen en el container registry:
user@192 ~ % cd saveNumber user@192 ~ % docker build -t us-central1-docker.pkg.dev/<PROYECTO-GCP>/<REPOSITORIO-ARTIFACT-REGISTRY>/memory:1.0 .
Para el caso del ejemplo el comando se verá de la siguiente forma:
user@192 ~ % docker build -t us-central1-docker.pkg.dev/uandes-native/uniandes-misw-native-calculadora-app/memory:1.0 .
Note que para el ejemplo hemos usado el tag db-save-1.0. Una vez termine la creación de la imagen, haga push al repositorio remoto:
user@192 ~ % docker push us-central1-docker.pkg.dev/<PROYECTO-GCP>/<REPOSITORIO-ARTIFACT-REGISTRY>/memory:1.0
en el ejemplo el comando se ve de la siguiente manera:
user@192 ~ % docker push us-central1-docker.pkg.dev/uandes-native/uniandes-misw-native-calculadora-app/memory:1.0
Una vez termine con esta instrucción, diríjase a artifact registry, allí podrá ver la imagen creada:
Para crear una red y una sub red privada puede remitirse al tutorial de la semana 3 de kubernetes, en este tutorial usaremos la misma red y subred allí creadas. Si ya las tiene, solo necesita crear una subred específicamente para la base de datos.
Cree el rango de direcciones que se utilizará para desplegar la instancia de base de datos:
user@192 ~ % gcloud compute addresses create red-dbs-tutoriales --global --purpose=VPC_PEERING --addresses=<RANGO-IPS> --prefix-length=24 --network=<RED> --project=<ID-PROYECTO>
Allí puede ver campos como:
Para el caso del ejemplo el comando es:
user@192 ~ % gcloud compute addresses create red-dbs-tutoriales --global --purpose=VPC_PEERING --addresses=192.168.0.0 --prefix-length=24 --network=vpn-tutoriales-misw --project=uandes-native
Por último, otorgue acceso a los servicios de administración de redes de GCP para que pueda realizar la gestión de la instancia a través de la red virtual creada:
user@192 ~ % gcloud services vpc-peerings connect --service=servicenetworking.googleapis.com --ranges=red-dbs-tutoriales --network=vpn-tutoriales-misw --project=<id-proyecto>
Finalmente, cree una regla de firewall para permitir el tráfico entre un cluster de kubernetes y la base de datos que vamos a utilizar:
user@192 ~ % gcloud compute firewall-rules create allow-db-ingress --direction=INGRESS --priority=1000 --network=<RED> --action=ALLOW --rules=tcp:5432 --source-ranges=<RANGO-IP> --target-tags=<TAG> --project=<ID-PROYECTO>
Para el caso del ejemplo:
user@192 ~ % gcloud compute firewall-rules create allow-db-ingress --direction=INGRESS --priority=1000 --network=vpn-tutoriales-misw --action=ALLOW --rules=tcp:5432 --source-ranges=192.168.1.0/24 --target-tags=basesdedatos --project=uandes-native
La aplicación como ya lo pudo evidenciar en pasos anteriores, requiere de una base de datos. Para ello, despliegue una base de datos relacional PostgreSQL 14 y configure su acceso dentro de la VPN recién creada. Siga los pasos a continuación para lograrlo.
En la consola de GCP, diríjase a la sección de SQL dentro del submenú de Bases de datos:
Una vez dentro, cree una nueva instancia de base de datos Postgres. Utilice los siguientes datos para crear la instancia:
Realice la configuración de la máquina a ser utilizada en la instancia. Utilice la siguiente configuración:
Configure la configuración de red de la instancia según los siguientes datos:
Puede que obtenga un mensaje de la base de datos que requiere conexión de acceso a servicios privados, de ser así, de click en configurar conexión y seleccione la red y subred creadas en etapas anteriores.
Luego de asignar la conexión puede esperar una vista como la siguiente:
Finalmente agregue la etiqueta de basesdedatos
a la instancia.
Por último de click en crear instancia. Al finalizar la creación debe poder ver la dirección asignada a la instancia en la red privada:
Para mayor información puede visitar la documentación oficial de Cloud SQL.
Ahora que ha experimentado un poco el endpoint de almacenamiento de números, conectaremos la base de datos creada en la nube en pasos anteriores con un cluster de kubernetes.
En diversas ocasiones es requerido configurar secretos y configuraciones que necesitan nuestras aplicaciones para que funcionen correctamente. Estas variables deben ser almacenadas correctamente asegurando atributos de confidencialidad e integridad, evitando así accesos no autorizados que puedan comprometer la seguridad de la infraestructura. En Kubernetes, el almacenamiento de estas variables se realiza mediante el recurso Secreto, el cual corresponde a un llavero con diversas claves cifradas que pueden ser empleadas en la definición de otros recursos como el despliegue.
Nuestra aplicación requiere de la definición de las siguientes variables en el archivo secrets.yaml que encontrará en la carpeta de la aplicación saveNumber:
Allí debe reemplazar los siguientes datos asociandolas al postgres desplegado previamente:
apiVersion: v1 stringData: uri : "postgresql+psycopg2://<POSTGRES_USER>:<POSTGRES_PASSWORD>@<POSTGRES_HOST>/<POSTGRES_DB>" kind: Secret metadata: name: <NAME-SECRETS>
Para el caso del ejemplo la modificación del archivo secrets.yaml se verá de la siguiente forma después de reemplazar la información:
apiVersion: v1 stringData: uri : "postgresql+psycopg2://postgres:1234@192.168.0.3/postgres" kind: Secret metadata: name: appsecrets
Haga uso del usuario postgres ya que este tiene los permisos necesarios para crear esquemas y tablas, lo cual es requerido en la carga inicial de la aplicación. Una buena práctica es definir un usuario con una serie de permisos limitados en la base de datos, dado el objetivo académico haremos uso del usuario por defecto.
Para hacer uso de la base de datos usaremos el cluster creado en el tutorial de kubernetes, por lo cual cargaremos los secrets en esta agrupación, mediante:
user@192 ~ % kubectl apply -f secrets.yaml
Podrá ver el siguiente mensaje de confirmación:
user@192 ~ % kubectl apply -f secrets.yaml To learn more, consult https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke secret/appsecrets created
Se preguntará como el cluster de kubernetes captura estos secretos, si se fija en el archivo k8s-service.yml de la carpeta saveNumber, en la línea 50 se indica un secretKeyRef, el cual se encarga de ir al archivo de secretos creado previamente (appsecrets) y extraer el valor de la key indicada, en esta ocasión la uri de la base de datos.
env: - name: "SQLALCHEMY_DATABASE_URI" valueFrom: secretKeyRef: name: appsecrets key: uri
Si va a la consola de GCP a la sección de Secrets y ConfigMaps podrá ver el secreto creado asociado a la dirección de la base de datos.
Luego de esto, el cluster de kubernetes asociado a la aplicación, estará almacenando el número capturado por body request en el sistema de persistencia de postgres creado en la nube.
Para mayor información puede visitar la documentación oficial de secrets.
Configure el archivo k8s-sservice.yml de la carpeta saveNumber cambiando el comodín <IMAGE-URI> (ubicado en la línea 39) por la URI de su repositorio privado y el tag de la imagen creada en pasos anteriores.
containers: - name: calculadora-numeros image: us-central1-docker.pkg.dev/uandes-native/uniandes-misw-native-calculadora-app/memory:1.0 ports: - containerPort: 4000 env: - name: "SQLALCHEMY_DATABASE_URI" valueFrom: secretKeyRef: name: appsecrets key: uri # Realizar pull siempre a la imagen imagePullPolicy: Always
Para culminar, construya el despliegue a partir del archivo yml ejecutando la instrucción:
user@192 ~ % kubectl apply -f k8s-service.yml
Valide que el cluster está corriendo exitosamente mediante kubectl get pods y pruebe el siguiente endpoint:
user@192 ~ % curl --location --request POST 'http://<URL-BALANCEADOR>/guardar_numero' \ --header 'Content-Type: application/json' \ --data-raw '{ "num_1": 399 }'
Recuerde reemplazar la URL en el curl, por la de su balanceador de carga, si no sabe cual es, puede consultarla en la sección de ingress:
Para el caso del ejemplo, el curl quedaría de la siguiente forma:
curl --location --request POST 'http://35.202.134.204:80/guardar_numero' \ --header 'Content-Type: application/json' \ --data-raw '{ "num_1": 399 }'
Obtendrá la confirmación de almacenamiento exitoso en una base de datos en la nube (Usando Postgres).
{ "mensaje": "numero 399 guardado correctamente." }
Finalmente valide el endpoint GET para traer el último número almacenado en la base datos, mediante el curl para el caso de ejemplo:
user@192 ~ % curl --location --request GET 'http://35.202.134.204:80/ultimo_numero' \ --header 'Content-Type: application/json' \ --data-raw '{ "num_1": 399 }'
Obtendrá como respuesta el último número guardado:
{ "ultimo_valor": 399 }
¡Éxitos en el desarrollo del tutorial y nos vemos en una próxima oportunidad!
[1] «Inicio rápido Cloud SQL», [Online]. Disponible en:https://cloud.google.com/sql/docs/postgres/quickstart