Github Action Pipeline fuer Kubernetes

Github bietet seit einiger Zeit jetzt schon das Feature `Action` an - ein CI/CD-Werkzeug, was noch bischen ein Nischendasein fristet neben den ganzen anderen Platzhirschen wie Travis, CircleCI usw. Voellig unbegruendet! Heute zeige ich Euch, wie man in 5 Minuten Github Action Pipeline erfolgreich einrichtet, um eine Applikation in einem Kubernetes-Cluster neu zu deployen.

Posted by on July 24, 2020 · 5 mins read

Github Action ist in jedem Github-Repo zu finden und wird automatisch im Menue mit angezeigt, wenn man ein Repo erstellt.

Man kann sich GitHub Action ein bischen wie Kubernetes Operator vorstellen: Da ist irgendwo hinten eine Business-Logik, die das umsetzt, was weiter vorne in einer Metasprache und einer Instanz beschrieben ist. Letztlich liegt dort ein Dockerfile, welches ein Ubuntu-Image startet und kubectl installiert und ueber den Entrypoint aufruft. Eine action.yml beschreibt, welche Aktionen vom Github-Worker ausgefuehrt werden sollen. Ganz stumpfsinnig ist das hier: Starte docker. Die Credentials brauchen wir vom Cluster, etwa angelegt im letzten Blog-Artikel. Die Cluster-URL/IP-Adresse muss natuerlich aus der Welt erreichbar sein! Diese Datei codieren wir base64:

cat /opt/k3s-clients/gen/kube/github.kubeconfig | base64

Den Inhalt kopieren wir in die Zwischenablage, gehen zu Settings/Secrets in unserem Repo:

Dort legen wir das neue Secret KUBE_CONFIG_DATA an und fuegen den Inhalt der Zwischenablage, als die base64 codierte KubeConfig ein.

Im Repo erstellen wir eine Datei: .github/workflows/nginx.yml

on: 
  push: 
    paths: 
    - 'html/**'
name: Deploy nginx
jobs:
  deploy:
    name: Deploy to cluster
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
      with:
        ref: master
    - name: Deploy to cluster
      uses: gnuu-de/kubectl@master
      env:
        KUBE_CONFIG_DATA: $
      with:
        args: rollout restart deployment/nginx
    - name: Verify deployment
      uses: gnuu-de/kubectl@master
      env:
        KUBE_CONFIG_DATA: $
      with:
        args: get pods -l app=nginx

Was passiert hier? Bei Pushs in das Verzeichnis html wird der Job “Deploy to Cluster” angeschmissen. Der laeuft auf Ubuntu (momentan wird auch nur Ubuntu als Linux-Betriebssystem unterstuetzt - deswegen brauchen wir auch ein Ubuntu-Docker-Image). Als Environment-Variable wird KUBE_CONFIG_DATA uebergeben. Der Inhalt wird im Docker-Container dekodiert und als KUBECONFIG-Variable abgelegt. Der Entrypoint von dem Container, dessen Manifest als Dockerfile im Github Reopo gnuu-de/kubectl liegt, ist “kubectl”. Demnach reicht als Argument “rollout restart deployment/nginx”, um auf meinem Kubernetes-Cluster ein Redeployment von Nginx anzustossen, um meine Aenderungen der HTML-Seiten sichtbar zu machen, da das Deployment das Repo im InitContainer auscheckt und lokal im POD abspeichert. Ein zweiter Job zeigt mit “get pods” an, ob da wirklich was passiert ist:

Fertig! Bei jeder Aenderung im Repo im Verzeichnis html wird die Github Action ausgefuehrt.

Ein weiterer Anwendungsfall ist docker build & push, also das Erstellen von Images und veroeffentlichen dieser auf hub.docker.io. Ein passener Github Action findet man auf https://github.com/marketplace/actions/build-and-push-docker-images Ein passender Workflow ist hier im Einsatz und kann so aussehen:

on: 
  push: 
    paths: 
    - 'Dockerfile.nginx'
name: Build & Push Dockerfile.nginx
jobs:
  deploy:
    name: Docker Build & Push
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
 
      - name: Build and push image
        uses: docker/build-push-action@v1
        with:
          username: $
          password: $
          dockerfile: Dockerfile.nginx
          repository: gnuu/nginx
          tags: latest

DOCKER_USERNAME und DOCKER_PASSWORD werden als Secret Variable in den Settungs gespeichert (Klartext, nicht base64).

Ein paar Fallstricke:

  • Die Github-Action Datei liegt im Verzeichnis .github/workflows/. Der Dateiname ist egal, der Verzeichnisname ist wichtig!
  • Wie schon erwaehnt, werden nur Ubuntu Images unterstuetzt, sowie Windows und Mac
  • Neben Docker gibt es noch Umgebungen fuer NodeJS, Python und Java
  • Urspruenglich war fuer das Projekt hier angedacht, die Kube-API nur ueber Wireguard zugaenglich zu machen. Die Schluessel haette man auch mit Secrets injecten koennen, leider funktioniert dann das Tunneldevice im Docker nicht. Dazu muesste man seine eigenen Runner laufen lassen, waere aber auch doppelt-gemoppelt, da die Komunikation zum Cluster sowieso schon verschluesselt ist.

Fazit: Github Action ist sehr schnell. Und sicher. Secret-Verwaltung findet nur innerhalb des Jobs statt. Es gibt einen Marktplatz, auf dem jeder seinen Action Operator veroeffentlichen kann. Github selber steuert natuerlich auch welche bei. Die Dokumentation ist sehr umfangreich und mit diesem Beispiel hier das Ganze vielleicht jetzt etwas leichter verstaendlich. Viel Spass. Und: Action!