Разглеждаме Custom Tooling в Argo CD

Разглеждаме Custom Tooling в Argo CD

След известно време след написването на първата статия, в която ловко работех с jsonnet и gitlab, разбрах, че пайплайните са разбира се добри, но прекалено сложни и неудобни.

В повечето случаи е необходима стандартна задача: "да генерирам YAML и да го поставя в Kubernetes". Именно с това Argo CD се справя чудесно.

Argo CD позволява свързване на Git-репозитории и синхронизиране на тяхното състояние в Kubernetes. По подразбиране се поддържат няколко вида приложения: Kustomize, Helm чарти, Ksonnet, чист Jsonnet или просто директории с YAML/JSON манифести.

На повечето потребители на този набор ще им бъде достатъчно, но не на всички. За да отговори на нуждите на всеки, в Argo CD има възможност за използване на custom tooling.

На първо място ме интересува възможността за добавяне на поддръжка qbec и git-crypt, които бяха напълно разгледани в предишната статия.

Преди да започнете конфигурацията, първо трябва да разберете как точно работи Argo CD.

За всяко добавено приложение той има две фази:

  • init — начална подготовка преди деплоя, тук може да се прави всичко: изтегляне на зависимости, разопаковане на секрети и друго.
  • generate — изпълнение на командата за генериране на манифести, изходът трябва да бъде валиден YAML поток, това е точно това, което ще бъде приложено в кластера.

Забележително е, че Argo прилага този подход за всеки тип приложения, включително и за Helm. Тоест в Argo CD Helm не отговаря за деплоя на релийзи в кластера, а се използва само за генериране на манифести.

От своя страна Argo умее нативно да обработва Helm-hooks, което позволява да не се нарушава логиката на прилагане на релийзи.

QBEC

Qbec позволява удобно описване на приложения с помощта на jsonnet, а освен това има възможност за рендериране на Helm-чарти, а тъй като Argo CD може да обработва нормално Helm-hooks, използването на тази възможност с Argo CD позволява постигане на още по-коректни резултати.

За да добавите поддръжка на qbec в argocd, са ви нужни две неща:

  • в конфигурацията на Argo CD трябва да е определен вашият custom plugin и командите за генериране на манифести.
  • нужните бинарни файлове трябва да са достъпни в образа argocd-repo-server.

Първата задача се решава доста просто:

# cm.yaml
data:
  configManagementPlugins: |
    - name: qbec
      generate:
        command: [sh, -xc]
        args: ['qbec show "$ENVIRONMENT" -S --force:k8s-namespace "$ARGOCD_APP_NAMESPACE"']

(командата init не се използва)

$ kubectl -n argocd patch cm/argocd-cm -p "$(cat cm.yaml)"

За добавяне на бинарни файлове се предлага да се събере нов образ, или да се използва трик с init-контейнер:

# deploy.yaml
spec:
  template:
    spec:
      # 1. Define an emptyDir volume which will hold the custom binaries
      volumes:
      - name: custom-tools
        emptyDir: {}
      # 2. Use an init container to download/copy custom binaries into the emptyDir
      initContainers:
      - name: download-tools
        image: alpine:3.12
        command: [sh, -c]
        args:
        - wget -qO- https://github.com/splunk/qbec/releases/download/v0.12.2/qbec-linux-amd64.tar.gz | tar -xvzf - -C /custom-tools/
        volumeMounts:
        - mountPath: /custom-tools
          name: custom-tools
      # 3. Volume mount the custom binary to the bin directory (overriding the existing version)
      containers:
      - name: argocd-repo-server
        volumeMounts:
        - mountPath: /usr/local/bin/qbec
          name: custom-tools
          subPath: qbec
        - mountPath: /usr/local/bin/jsonnet-qbec
          name: custom-tools
          subPath: jsonnet-qbec

$ kubectl -n argocd patch deploy/argocd-repo-server -p "$(cat deploy.yaml)"

Сега ще видим как ще изглежда манифестът на нашето приложение:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: qbec-app
  namespace: argocd
spec:
  destination: 
    namespace: default
    server: https://kubernetes.default.svc
  project: default
  source: 
    path: qbec-app
    plugin: 
      env: 
        - name: ENVIRONMENT
          value: default
      name: qbec
    repoURL: https://github.com/kvaps/argocd-play
  syncPolicy: 
    automated: 
      prune: true

В променливата ENVIRONMENT передаваме името на средата, за която трябва да се генерират манифестите.

приложим и ще видим какво получихме:

Разглеждаме Custom Tooling в Argo CD

приложението е внедрено, отлично!

git-crypt

Git-crypt позволява настройка на прозрачното криптиране на репозиторий. Това е прост и безопасен начин за съхранение на конфиденциални данни директно в git.

С имплементацията на git-crypt стана по-сложно.

Теоретично можем да изпълним git-crypt unlock в начален етап на нашия custom-плагин, но това не е много удобно, тъй като би ни попречило да използваме нативните методи за внедряване. Например, при Helm и Jsonnet, губим гъвкавия интерфейс, който улеснява настройката на приложението (values-файлове и др.).

Точно поради тази причина, искахме да извършим извличането на репозитория още на по-ранен етап, при клонирането.

Тъй като в момента Argo CD не предлага възможности за описание на каквито и да било хукове за синхронизация на репозитория, се наложи да заобиколим това ограничение с хитър shell скрипт, който заменя командата git:

#!/bin/sh
$(dirname $0)/git.bin "$@"
ec=$?
[ "$1" = fetch ] && [ -d .git-crypt ] || exit $ec
GNUPGHOME=/app/config/gpg/keys git-crypt unlock 2>/dev/null
exit $ec

Argo CD извършва git fetch всеки път преди операцията на внедряване. Точно на тази команда ще прикачим изпълнението git-crypt unlock за отключване на репозитория.

за тестове можете да използвате моето docker-изображение в което вече има всичко необходимо:

$ kubectl -n argocd set image deploy/argocd-repo-server argocd-repo-server=docker.io/kvaps/argocd-git-crypt:v1.7.3

Сега трябва да помислим как Argo ще разшифрова нашите репозитории. А именно да генерира gpg-ключ за него:

$ kubectl exec -ti deploy/argocd-repo-server -- bash

$ printf "%sn" 
    "%no-protection" 
    "Key-Type: default" 
    "Subkey-Type: default" 
    "Name-Real: YOUR NAME" 
    "Name-Email: YOUR EMAIL@example.com" 
    "Expire-Date: 0" 
    > genkey-batch 

$ gpg --batch --gen-key genkey-batch
gpg: WARNING: unsafe ownership on homedir '/home/argocd/.gnupg'
gpg: keybox '/home/argocd/.gnupg/pubring.kbx' created
gpg: /home/argocd/.gnupg/trustdb.gpg: trustdb created
gpg: key 8CB8B24F50B4797D marked as ultimately trusted
gpg: directory '/home/argocd/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/argocd/.gnupg/openpgp-revocs.d/9A1FF8CAA917CE876E2562FC8CB8B24F50B4797D.rev'

Да запомним името на ключа 8CB8B24F50B4797D за следващите стъпки. Експортиране на самия ключ:

$ gpg --list-keys
gpg: WARNING: unsafe ownership on homedir '/home/argocd/.gnupg'
/home/argocd/.gnupg/pubring.kbx
-------------------------------
pub   rsa3072 2020-09-04 [SC]
      9A1FF8CAA917CE876E2562FC8CB8B24F50B4797D
uid           [ultimate] YOUR NAME 
sub   rsa3072 2020-09-04 [E]

$ gpg --armor --export-secret-keys 8CB8B24F50B4797D

И ще го добавим като отделна тайна:

# argocd-gpg-keys-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: argocd-gpg-keys-secret
  namespace: argocd
stringData:
  8CB8B24F50B4797D: |-
    -----BEGIN PGP PRIVATE KEY BLOCK-----

    lQVYBF9Q8KUBDACuS4p0ctXoakPLqE99YLmdixfF/QIvXVIG5uBXClWhWMuo+D0c
    ZfeyC5GvH7XPUKz1cLMqL6o/u9oHJVUmrvN/g2Mnm365nTGw1M56AfATS9IBp0HH
    O/fbfiH6aMWmPrW8XIA0icoOAdP+bPcBqM4HRo4ssbRS9y/i
    =yj11
    -----END PGP PRIVATE KEY BLOCK-----

$ kubectl apply -f argocd-gpg-keys-secret.yaml

Единственото, което ни остава, е да го пробутаме в контейнера argocd-repo-server, затова ще редактираме деплоймента:

$ kubectl -n argocd edit deploy/argocd-repo-server

И ще заменим съществуващия gpg-keys обем с projected, където ще посочим нашата тайна:

   spec:
     template:
       spec:
         volumes:
         - name: gpg-keys
           projected:
             defaultMode: 420
             sources:
             - secret:
                 name: argocd-gpg-keys-secret
             - configMap:
                 name: argocd-gpg-keys-cm

Argo CD автоматично зарежда gpg-ключове от тази директория при стартиране на контейнера, така че ще зареди и нашия частен ключ.

Да проверим:

$ kubectl -n argocd exec -ti deploy/argocd-repo-server -- bash
$ GNUPGHOME=/app/config/gpg/keys gpg --list-secret-keys
gpg: WARNING: unsafe ownership on homedir '/app/config/gpg/keys'
/app/config/gpg/keys/pubring.kbx
--------------------------------
sec   rsa2048 2020-09-05 [SC] [expires: 2021-03-04]
      ED6285A3B1A50B6F1D9C955E5E8B1B16D47FFC28
uid           [ultimate] Anon Ymous (ArgoCD key signing key) 

sec   rsa3072 2020-09-03 [SC]
      9A1FF8CAA917CE876E2562FC8CB8B24F50B4797D
uid           [ultimate] YOUR NAME 
ssb   rsa3072 2020-09-03 [E]

Отлично, ключът е зареден! Сега ни остава само да добавим Argo CD в нашия репозиторий като колаборатор и той ще може автоматично да го дешифрира на летене.

Импортираме ключа на локалния компютър:

$ gpg --armor --export-secret 8CB8B24F50B4797D > 8CB8B24F50B4797D.pem
$ gpg --import 8CB8B24F50B4797D.pem

Настройваме нивото на доверие:

$ gpg --edit-key 8CB8B24F50B4797D
trust
5

Добавяме argo като колаборатор в нашия проект:

$ git-crypt add-gpg-user 8CB8B24F50B4797D

Линкове по темата:

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster