KI für DevOps-Engineers – Teil 1: Die Grundlagen von DevOps-KI
DevOps ist ein entscheidender Erfolgsfaktor in der Softwareentwicklung, und wir sind definitiv alle auf die eine oder andere Weise auf KI gestoßen. Eine
In früheren Beiträgen haben wir bereits verschiedene Möglichkeiten gezeigt, wie man mit HashiCorp Packer Golden Images erstellt. In diesem Beitrag zeigen wir, wie man den Prozess mit Github Actions automatisiert. Wir werden HashiCorp Vault verwenden, um die Geheimnisse für Packer zu speichern, Terraform in Kombination mit Terratest, um die tatsächlich erstellten Images bereitzustellen, und das Ergebnis von Packer mit Mondoo zu verifizieren. Unsere Images werden auf HCP Packer veröffentlicht, um sie verfügbar zu machen und die Versionsinformationen in verschiedenen Release-Kanälen (Entwicklung, Staging, Produktion) zu pflegen.
Zusätzlich fügen wir einige Sequenzen hinzu, um den Github-Workflow mit act ausführbar zu machen, wie [in diesem Artikel] (/blog/2024-08-14-github-actions-locally/) bereits beschrieben wurde.
Zuerst richten wir in unserem Workflow die benötigten Tools ein, indem wir entsprechende Github Actions verwenden:
Um auf verschiedene Ressourcen zugreifen zu können, müssen wir in unserem Workflow diese Geheimnisse abrufen. Wir verwenden HCP Vault, um diese Werte zu speichern, und nutzen die vault-action, um auf diese Geheimnisse zuzugreifen und sie für die kommenden Schritte verfügbar zu machen. Momentan erstellen wir Golden Images parallel für Azure und AWS. Außerdem benötigen wir Zugang zur HCP-Plattform, um Informationen über unsere erstellten Images zu speichern, und zuletzt stellen wir Sicherheits- und Compliance-Scan-Informationen durch Mondoo bereit. Dafür müssen wir also noch die folgenden Secrets mittels der Vault Github Action abholen:
1- name: Import Secrets
2 id: import-secrets
3 uses: hashicorp/vault-action@v2
4 with:
5 url: ${{ vars.VAULT_ADDRESS }}
6 namespace: ${{ vars.VAULT_NAMESPACE}}
7 method: approle
8 path: github_ci
9 roleId: ${{ secrets.VAULT_APPROLE_ID}}
10 secretId: ${{ secrets.VAULT_APPSECRET_ID }}
11 secrets: |
12 secret/data/ci/aws accessKey | AWS_ACCESS_KEY_ID ;
13 secret/data/ci/aws secretKey | AWS_SECRET_ACCESS_KEY;
14
15 secret/data/ci/hcp username | HCP_CLIENT_ID;
16 secret/data/ci/hcp password | HCP_CLIENT_SECRET;
17
18 secret/data/ci/mondoo password | MONDOO_AGENT_ACCOUNT;
19
20 secret/data/ci/azure subscriptionId | ARM_SUBSCRIPTION_ID;
21 secret/data/ci/azure tentantId | ARM_TENANT_ID;
22 secret/data/ci/azure clientId | ARM_CLIENT_ID;
23 secret/data/ci/azure clientSecret | ARM_CLIENT_SECRET;
24
25 secret/data/ci/ssh private;
26 secret/data/ci/ssh public;
In unserem Bereitstellungsprozess für den eigentlichen Packer-Build verwenden wir Ansible-Playbooks, um die eigentlichen Image-Vorlagen zu provisionieren. Daher müssen wir Python einrichten, um sicherzustellen, dass alle erforderlichen Abhängigkeiten installiert und für unsere Ansible-Playbooks verfügbar sind.
1- uses: actions/setup-python@v5
2 with:
3 python-version: ${{ env.PYTHON_VERSION }}
4
5- name: Install Packertools
6 run: |
7 python -m pip install --upgrade pip
8 pip install -r requirements.txt
9 ansible-galaxy install -r ansible/requirements.yaml
Da wir die eigentliche Build-Quelle über die Umgebungsvariablen CLOUD
, DISTRIBUTION
und PLAY
steuern können, haben wir Wrapper implementiert, die die Packer-Konfigurationsdatei und die Packer-Variablen-Datei erstellen. So können wir das gleiche Image für verschiedene Clouds (AWS, Azure, VMware, ...) und Distributionen (z. B. Windows, Ubuntu, CentOS, ...) mit denselben Playbooks erstellen.
In diesen Playbooks werden alle Geheimnisse (host_vars
und group_vars
) von einem Key/Value-Secret-Store innerhalb von HashiCorp Vault verwaltet – dies wird in einem separaten Beitrag ausführlich beschrieben.
1- name: Create Packer Configuration
2 run: ./scripts/create_packer_config.sh
3
4- name: Packer Build
5 id: build
6 run: |
7 packer init "${CI_PROJECT_DIR}/packer/current_${GITHUB_RUN_ID}.pkr.hcl"
8
9 packer build ${EXTRA_ARGS} \
10 -var-file="${CI_PROJECT_DIR}/packer/current_${GITHUB_RUN_ID}.pkrvars.hcl" \
11 "${CI_PROJECT_DIR}/packer/current_${GITHUB_RUN_ID}.pkr.hcl" | tee "${GITHUB_RUN_ID}.log"
12
13 ./scripts/post-build.sh
Der Build-Schritt ruft einfach packer init
auf, um alle notwendigen Plugins herunterzuladen, und baut dann die eigentliche Konfiguration. Der tee
-Befehl wird verwendet, um die Protokolldatei für eine spätere Referenz zu speichern, und das post-build.sh
-Skript kümmert sich um das Parsen der Protokolldatei und das Speichern der eigentlichen Build-Informationen zur späteren Verwendung im Workflow.
Vom Build-Schritt erhalten wir Informationen über die tatsächlichen Image-Vorlagennamen oder IDs, die wir testen möchten. Das test-wrapper.sh
-Skript prüft lediglich, ob Tests gestartet werden können, und zieht die Testkonfiguration für die tatsächliche Cloud, Distribution und das Play. Die eigentlichen Tests werden von terratest
durchgeführt, um das Image bereitzustellen, und anschließend von Mondoo gescannt. Weitere Informationen darüber haben wir in einem separaten Beitrag hier veröffentlicht.
1- name: Test Packer Image
2 id: test
3 run: ./scripts/test-wrapper.sh
Nach einem erfolgreichen Test werden die Images auf den folgenden HCP-Packer-Kanal veröffentlicht. Das Image wird nach dem Packer-Build auf dem latest
-Kanal veröffentlicht und mit etwas Terraform-Code auf andere Kanäle verschoben.
1
2data "hcp_packer_version" "src" {
3 bucket_name = local.hcp_bucket_name
4 channel_name = var.hcp_channel_source
5}
6
7resource "hcp_packer_channel" "destination" {
8 name = var.hcp_channel_destination
9 bucket_name = local.hcp_bucket_name
10}
11
12resource "hcp_packer_channel_assignment" "destination" {
13 bucket_name = local.hcp_bucket_name
14 channel_name = var.hcp_channel_destination
15 version_fingerprint = data.hcp_packer_version.src.fingerprint
16}
Innerhalb des Skripts werden terraform init
und terraform apply
aufgerufen. Da wir jedoch den Terraform-Zustand nicht verwalten, rufen wir terraform import
auf, um den aktuellen hcp_packer_channel.destination
und hcp_packer_channel_assignment.destination
mit ihren Werten zu verknüpfen.
1- name: Publish Packer Image
2 id: publish
3 if: github.ref_type == 'tag'
4 run: ./scripts/promote.sh
Manchmal wird ein Job abgebrochen oder es warten bereits neuere Commits in der Warteschlange. In diesem Fall möchten wir einige Bereinigungsschritte ausführen, falls bereits Ressourcen durch unseren Workflow-Lauf erstellt wurden.
Möglicherweise müssen Sie nachsehen, ob noch von Packer erstellte Maschinen laufen, oder ob Ihr Testcode bestimmte Ressourcen erstellt hat, die zerstört werden müssen.
Zum Beispiel können Sie innerhalb der Packer-Konfiguration Tags definieren, die diese Maschinen als Packer-bezogen markieren, vielleicht auch den Commit-Hash als Tag hinzufügen.
1- name: Execute if the job was cancelled
2 if: ${{ cancelled() }}
3 run: ./scripts/cancel.sh
Beim Lesen aller Blog-Beiträge werden Sie auf unseren act-Artikel stoßen, der es Ihnen ermöglicht, Ihre Github-Workflows auf Ihrer lokalen Maschine auszuführen. So müssen Sie keine andere Methode definieren, um die eigentlichen Schritte zum Erstellen der Maschinen während der Entwicklung Ihrer Playbooks und Definitionen auszuführen.
act
injiziert eine Umgebungsvariable ACT
, die für diesen Zweck verwendet werden kann.
1- name: Install Act dependencies
2 if: ${{ env.ACT != '' }}
3 run: |
4 apt-get update && apt-get install -y $MISSING_ACT_PACKAGES
Dieser GitHub-Workflow ist umfassend und gut konzipiert, um den Packer-Image-Erstellungsprozess auf sichere und effiziente Weise zu automatisieren. Die Integration mit HashiCorp Vault für das Geheimnismanagement gewährleistet einen sicheren Umgang mit sensiblen Informationen, während die Multi-Cloud-Unterstützung, die Automatisierung von Tests und Bereinigungsprozessen ihn für eine Vielzahl von Anwendungsfällen geeignet machen. Insgesamt bietet der Workflow eine ausgewogene Mischung aus Flexibilität, Sicherheit und Automatisierung und ist eine starke Wahl für den Einsatz in CI/CD-Produktionspipelines.
Sie interessieren sich für unsere Trainings oder haben einfach eine Frage, die beantwortet werden muss? Sie können uns jederzeit kontaktieren! Wir werden unser Bestes tun, um alle Ihre Fragen zu beantworten.
Hier kontaktieren