Otro de los flujos que está muy de moda a día de hoy es la generación de imágenes y el despliegue de estas en Kubernetes. Hoy quiero compartir contigo un workflow para GitHub Actions usando Azure Kubernetes Service:
name: Deploy web app on AKS
on:
push:
branches:
- master
paths:
- .github/workflows/k8s-webapp.yml
- "BethanysPieShopHRM.server/**"
env:
CLUSTER_NAME: gisaks
CLUSTER_RESOURCE_GROUP: AKS-Refresh
NAMESPACE: bethanyshop
IMAGE_NAME: bethanys-webapp
jobs:
build-and-push-docker-image:
runs-on: ubuntu-latest
steps:
- name: "Get code from the repo"
uses: actions/checkout@master
- uses: azure/docker-login@v1
with:
login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }}
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Build and push
run: |
docker build . --file ./BethanysPieShopHRM.server/Dockerfile -t ${{ secrets.REGISTRY_LOGIN_SERVER }}/${{env.IMAGE_NAME}}:${{ github.sha }}
docker push ${{ secrets.REGISTRY_LOGIN_SERVER }}/${{env.IMAGE_NAME}}:${{ github.sha }}
deploy-to-aks:
needs: [build-and-push-docker-image]
runs-on: ubuntu-latest
steps:
- name: "Get code from the repo"
uses: actions/checkout@master
- name: "Set the context"
uses: azure/aks-set-context@v1
with:
creds: "${{secrets.AZURE_CREDS_AKS_SCOPE}}"
cluster-name: ${{env.CLUSTER_NAME}}
resource-group: ${{env.CLUSTER_RESOURCE_GROUP}}
- name: "Create the namespace if it does not exist"
run: |
kubectl create ns ${{env.NAMESPACE}} --dry-run -o json | kubectl apply -f -
- name: "Create imagePullSecret for Azure Container Registry"
uses: azure/k8s-create-secret@v1
with:
container-registry-url: ${{ secrets.REGISTRY_LOGIN_SERVER }}
container-registry-username: ${{secrets.REGISTRY_USERNAME}}
container-registry-password: ${{secrets.REGISTRY_PASSWORD}}
secret-name: acr-connection
namespace: ${{env.NAMESPACE}}
- name: "Deploy app"
id: deployment
uses: azure/k8s-deploy@v1
timeout-minutes: 5
with:
manifests: k8s/webapp-manifest.yaml
images: ${{secrets.REGISTRY_LOGIN_SERVER}}/${{env.IMAGE_NAME}}:${{github.sha}}
imagepullsecrets: acr-connection
namespace: ${{env.NAMESPACE}}
- name: "If the deployment was not succeeded"
if: failure()
run: kubectl rollout undo deployment/bethanyspieshopweb --namespace ${{env.NAMESPACE}}
Muchas de las cosas que aparecen en este YAML las expliqué en el primer artículo sobre GitHub Actions. Este flujo tiene dos jobs:
build-and-push-docker-image
El primero se centra en la creación y publicación de la imagen, a partir del código que se encuentra en el repositorio de GitHub. Para ello, utilizo la acción azure/docker-login@v1 para poder hacer el push en el repositorio privado y, a través del shell, ejecuto docker build y push de la imagen.
deploy-to-aks
Como segundo paso llevo a cabo el despliegue, el cual debe esperar a que finalice el job anterior a través de la propiedad needs (porque sino no tenemos imagen que desplegar). Como son dos jobs diferentes, necesitas volver a hacer el checkout del código, establezco el contexto para kubectl, creo el namespace en el clúster si no existe, añado en el mismo un secreto del tipo imagePullSecret, para poder recuperar la imagen del repositorio privado, y despliego a través de la acción azure/k8s-deploy@v1, la cual entenderás mejor con este artículo sobre el objeto Deployment 🙂
Como novedad a lo explicado hasta ahora, a este paso le he establecido un timeout de 5 minutos por si el despliegue se ha quedado atascado. De ser así, se ejecutaría la última acción donde se comprueba, a través de un condicionante con if: failure(), si el último paso ejecutado ha fallado (en este ejemplo, el despliegue) y de ser así se lanzará un rollout undo sobre el la actualización que estabas intentando.
¡Saludos!

Bootcamp DevOps
Si tienes ganas de meterte en el área de DevOps, formo parte del
equipo de docentes del Bootcamp DevOps Lemoncode, ¿Te animas a
aprender con nosotros?