Zum Inhalt

📦 Artefakte

Was sind Artefakte?

Artefakte (Artifacts) sind Dateien, die während der Ausführung von Actions generiert, benötigt oder persistiert werden. Sie dienen als Schnittstelle zwischen verschiedenen Actions und Blocks und ermöglichen das Speichern von Zustandsinformationen, Konfigurationsdateien und generierten Ressourcen.

Typische Artefakte sind: - Ansible-Inventories - Dynamisch generierte oder kopierte Host-Listen - Kubeconfigs - Kubernetes-Cluster-Zugriffskonfigurationen - Terraform-State - Terraform-Zustandsdateien - SSH-Host-Cache - Cache für SSH-Verbindungen - Generierte Manifeste - YAML/JSON-Dateien für Kubernetes oder andere Systeme - Zertifikate - TLS-Zertifikate, CA-Bundles - Backup-Dateien - Datenbank-Dumps, Konfigurationssicherungen - Log-Snapshots - Spezifische Log-Auszüge

Artifacts-Struktur

graph TB
    WS[Workspace] --> ArtRoot[artifacts/]
    ArtRoot --> BlocksDir[blocks/]

    BlocksDir --> B1[block-1/]
    BlocksDir --> B2[block-2/]
    BlocksDir --> B3[block-3/]

    B1 --> Inv1[inventory.yml]
    B1 --> Kube1[kubeconfig.yml]
    B1 --> Cache1[hosts_cache.json]
    B1 --> Custom1[custom-data.yml]

    B2 --> Inv2[inventory.yml]
    B2 --> TFState[terraform.tfstate]
    B2 --> Certs[certs/]

    B3 --> Kube3[kubeconfig.yml]
    B3 --> Manifests[generated/]

    Manifests --> M1[deployment.yml]
    Manifests --> M2[service.yml]

    Certs --> CA[ca.crt]
    Certs --> TLS[tls.crt]

    style ArtRoot fill:#e1f5ff
    style BlocksDir fill:#f0ffe1
    style B1 fill:#fff4e1
    style B2 fill:#fff4e1
    style B3 fill:#fff4e1

Standard-Verzeichnisstruktur

my-workspace/
├── artifacts/                  # Artifacts-Root (konfigurierbar)
│   └── blocks/                 # Block-Artifacts
│       ├── my-cluster/
│       │   ├── kubeconfig.yml
│       │   └── cluster-info.json
│       ├── infrastructure/
│       │   ├── inventory.yml
│       │   ├── hosts_cache.json
│       │   └── terraform.tfstate
│       └── my-app/
│           ├── inventory.yml   # geerbt oder eigenes
│           ├── kubeconfig.yml  # geerbt oder eigenes
│           └── generated/
│               ├── deployment.yml
│               └── configmap.yml
├── .logs/                      # Transaction-Logs (kein Artifact)
└── blocks/                     # Block-Definitionen

Artifacts-Root konfigurieren

Die Artifacts-Root Directory kann in workspace.poly konfiguriert werden:

name: my-workspace

config:
  artifacts_root: artifacts  # Standard
  # oder ein anderer Pfad:
  # artifacts_root: .artifacts
  # artifacts_root: /tmp/polycrate-artifacts

Alternativ per CLI-Flag:

polycrate run my-block install --artifacts-root /custom/path

Block Artifacts Directory

Für jeden Block wird automatisch eine Block Artifacts Directory erstellt:

artifacts/blocks/<BLOCK_NAME>/

Diese Directory: - Wird automatisch angelegt beim ersten Laden des Blocks - Ist persistent zwischen Action-Ausführungen - Wird in den Container gemountet - Ist Teil des Snapshots

Standard-Artefakte

1. Ansible-Inventory

Polycrate sucht automatisch nach inventory.yml in der Block Artifacts Directory:

# artifacts/blocks/my-app/inventory.yml
all:
  hosts:
    web1:
      ansible_host: 192.168.1.10
      ansible_user: deploy
      ansible_port: 22
    web2:
      ansible_host: 192.168.1.11
      ansible_user: deploy
  vars:
    ansible_python_interpreter: /usr/bin/python3
  children:
    webservers:
      hosts:
        web1: {}
        web2: {}

Suchpfade (in dieser Reihenfolge): 1. artifacts/blocks/<BLOCK>/inventory.yml 2. Geerbtes Inventory (wenn inventory.from gesetzt) 3. Workspace-Root inventory.yml

2. Kubeconfig

Polycrate sucht automatisch nach kubeconfig.yml in der Block Artifacts Directory:

# artifacts/blocks/my-app/kubeconfig.yml
apiVersion: v1
kind: Config
clusters:
  - name: prod-cluster
    cluster:
      server: https://k8s.example.com:6443
      certificate-authority-data: LS0tLS...
contexts:
  - name: prod
    context:
      cluster: prod-cluster
      user: admin
      namespace: production
current-context: prod
users:
  - name: admin
    user:
      client-certificate-data: LS0tLS...
      client-key-data: LS0tLS...

Suchpfade: 1. artifacts/blocks/<BLOCK>/kubeconfig.yml 2. Geerbter Kubeconfig (wenn kubeconfig.from gesetzt) 3. Workspace-Root kubeconfig.yml 4. System-Default (~/.kube/config)

3. SSH-Host-Cache

Polycrate cached SSH-Verbindungsdaten für Performance:

// artifacts/blocks/my-app/hosts_cache.json
{
  "web1": {
    "ansible_host": "192.168.1.10",
    "ansible_port": 22,
    "ansible_user": "deploy",
    "last_seen": "2025-01-30T10:30:00Z",
    "fingerprint": "SHA256:abc123..."
  }
}

Dieser Cache wird automatisch verwaltet und beschleunigt SSH-Operationen.

Artefakte in Actions nutzen

In Ansible-Playbooks

Artifacts sind automatisch verfügbar über Snapshot-Variablen:

---
- name: Deploy Application
  hosts: localhost
  connection: local

  tasks:
    - name: Lade generiertes Manifest
      set_fact:
        manifest: "{{ lookup('file', workspace.config.artifacts_root + '/blocks/' + block.name + '/generated/deployment.yml') }}"

    - name: Apply Manifest
      kubernetes.core.k8s:
        state: present
        definition: "{{ manifest }}"

In Bash-Scripts

Nutzen Sie die Template-Syntax oder Environment-Variablen:

actions:
  - name: deploy
    script:
      - |
        ARTIFACTS_DIR="{{ .workspace.config.artifacts_root }}/blocks/{{ .block.name }}"

        # Manifest generieren und als Artifact speichern
        cat > $ARTIFACTS_DIR/generated/deployment.yml <<EOF
        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: {{ .block.name }}
        spec:
          replicas: 3
        EOF

        # Artifact nutzen
        kubectl apply -f $ARTIFACTS_DIR/generated/deployment.yml

Artefakte generieren

Beispiel 1: Kubeconfig generieren

actions:
  - name: create-cluster
    playbook: playbooks/create-cluster.yml

  - name: get-kubeconfig
    script:
      - |
        ARTIFACTS_DIR="{{ .workspace.config.artifacts_root }}/blocks/{{ .block.name }}"

        # Kubeconfig von Cluster abrufen
        kubectl config view --flatten > $ARTIFACTS_DIR/kubeconfig.yml

        echo "Kubeconfig saved to $ARTIFACTS_DIR/kubeconfig.yml"

Andere Blocks können diesen Kubeconfig dann erben:

name: my-app
from: base-app

kubeconfig:
  from: my-cluster  # Erbt kubeconfig.yml von Block "my-cluster"

Beispiel 2: Inventory generieren

actions:
  - name: provision-infrastructure
    playbook: playbooks/provision.yml

  - name: generate-inventory
    script:
      - |
        ARTIFACTS_DIR="{{ .workspace.config.artifacts_root }}/blocks/{{ .block.name }}"

        # Inventory dynamisch aus Terraform-Output generieren
        terraform output -json | jq -r '.hosts.value' | \
          python3 scripts/generate-inventory.py > $ARTIFACTS_DIR/inventory.yml

        echo "Inventory saved to $ARTIFACTS_DIR/inventory.yml"

Beispiel 3: Terraform-State persistieren

actions:
  - name: terraform-apply
    script:
      - |
        ARTIFACTS_DIR="{{ .workspace.config.artifacts_root }}/blocks/{{ .block.name }}"

        cd terraform/
        terraform init
        terraform apply -auto-approve

        # State als Artifact speichern
        cp terraform.tfstate $ARTIFACTS_DIR/terraform.tfstate
        cp terraform.tfstate.backup $ARTIFACTS_DIR/terraform.tfstate.backup

Artefakte zwischen Blocks teilen

Via Vererbung

Der einfachste Weg ist Vererbung:

# Block: infrastructure
name: infrastructure
kind: generic

actions:
  - name: generate-inventory
    script:
      - # ... generiert inventory.yml in Artifacts

# Block: my-app
name: my-app
kind: linuxapp

inventory:
  from: infrastructure  # Verwendet inventory.yml von "infrastructure"

actions:
  - name: install
    playbook: playbooks/install.yml  # Nutzt geerbtes Inventory

Via Workflows

Workflows können Artifacts zwischen Blocks orchestrieren:

# In workspace.poly
name: my-workspace

blocks:
  - name: infrastructure
    # ...
  - name: my-app
    # ...

workflows:
  - name: deploy-stack
    steps:
      - name: provision-infra
        block: infrastructure
        action: provision

      - name: generate-inventory
        block: infrastructure
        action: generate-inventory

      - name: deploy-app
        block: my-app
        action: install  # Nutzt Inventory von vorherigem Step

Nach generate-inventory lädt Polycrate den Workspace neu und das neue Inventory steht my-app zur Verfügung.

Best Practices

1. Artifacts für reproduzierbare Builds

Speichern Sie alle generierten Dateien als Artifacts:

actions:
  - name: build
    script:
      - |
        ARTIFACTS_DIR="{{ .workspace.config.artifacts_root }}/blocks/{{ .block.name }}"

        # Build durchführen
        make build

        # Artifacts speichern
        mkdir -p $ARTIFACTS_DIR/build
        cp -r dist/* $ARTIFACTS_DIR/build/
        cp build.log $ARTIFACTS_DIR/build/build.log

2. Artifacts in .gitignore

Artifacts sollten nicht in Git committed werden:

# .gitignore
artifacts/

Ausnahmen: Manche Artifacts (wie manuell erstellte Inventories) können committed werden.

3. Artifacts-Cleanup

Implementieren Sie Cleanup-Actions:

actions:
  - name: clean
    script:
      - |
        ARTIFACTS_DIR="{{ .workspace.config.artifacts_root }}/blocks/{{ .block.name }}"
        rm -rf $ARTIFACTS_DIR/*
        echo "Artifacts cleaned"

4. Artifacts dokumentieren

Dokumentieren Sie, welche Artifacts ein Block erstellt:

# my-block

## Generierte Artifacts:
- `kubeconfig.yml` - Kubernetes-Cluster-Zugriff
- `inventory.yml` - Ansible-Hosts-Liste
- `certs/` - TLS-Zertifikate
  - `ca.crt` - Root-CA
  - `tls.crt` - Server-Zertifikat
  - `tls.key` - Private Key

5. Artifacts validieren

Validieren Sie Artifacts nach der Generierung:

actions:
  - name: generate-inventory
    script:
      - |
        ARTIFACTS_DIR="{{ .workspace.config.artifacts_root }}/blocks/{{ .block.name }}"

        # Inventory generieren
        python3 scripts/generate-inventory.py > $ARTIFACTS_DIR/inventory.yml

        # Validieren
        ansible-inventory -i $ARTIFACTS_DIR/inventory.yml --list

        if [ $? -ne 0 ]; then
          echo "ERROR: Invalid inventory generated!"
          exit 1
        fi

Artifacts im Lifecycle

sequenceDiagram
    participant User
    participant CLI
    participant Block
    participant Artifacts

    User->>CLI: polycrate run block provision
    CLI->>Artifacts: Lade existierende Artifacts
    Artifacts-->>CLI: inventory.yml, kubeconfig.yml
    CLI->>Block: Führe Action aus
    Block->>Artifacts: Generiere neue Artifacts
    Artifacts-->>Block: Gespeichert
    Block-->>CLI: Action erfolgreich
    CLI->>Artifacts: Workspace-Reload: Lade neue Artifacts
    Artifacts-->>CLI: Aktualisierte Artifacts
    CLI-->>User: Fertig

    User->>CLI: polycrate run app deploy
    CLI->>Artifacts: Lade Artifacts (inkl. neu generierte)
    Artifacts-->>CLI: inventory.yml, kubeconfig.yml
    CLI->>Block: Führe Action mit Artifacts aus
  1. Vor Action: Bestehende Artifacts werden geladen
  2. Während Action: Neue Artifacts werden generiert/modifiziert
  3. Nach Action: Workspace wird neu geladen (neue Artifacts verfügbar)
  4. Nächste Action: Verwendet aktualisierte Artifacts

Zusammenhang mit anderen Konzepten

  • Snapshot: Artifacts sind Teil des Snapshots
  • Vererbung: Artifacts können vererbt werden (inventory.from, kubeconfig.from)
  • Workflows: Workflows orchestrieren Artifact-Generation zwischen Blocks
  • Container: Artifacts werden in den Container gemountet
  • Transactions: Änderungen an Artifacts werden geloggt

Artifact-basierte Architektur

Nutzen Sie Artifacts als Schnittstelle zwischen Blocks. Block A generiert Kubeconfig, Block B nutzt ihn. So bleiben Blocks entkoppelt und wiederverwendbar!