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
  • Secrets - Verschlüsselte sensitive Dateien (Passwörter, Zertifikate, Keys)
  • SSH-Keys - SSH-Schlüsselpaare für Remote-Zugriff
  • Generierte Manifeste - YAML/JSON-Dateien für Kubernetes oder andere Systeme
  • Zertifikate - TLS-Zertifikate, CA-Bundles
  • Backup-Dateien - Datenbank-Dumps, Konfigurationssicherungen

Artifacts-Struktur

Pfad Beschreibung Sensibel
artifacts/ Artifacts-Root -
artifacts/secrets/ Workspace-weite Secrets ⚠️ Ja
artifacts/secrets/id_rsa SSH Private Key ⚠️ Ja
artifacts/secrets/id_rsa.pub SSH Public Key Nein
artifacts/secrets/kubeconfig.yml Kubernetes Config ⚠️ Ja
artifacts/secrets/<block>/ Block-spezifische Secrets ⚠️ Ja
artifacts/blocks/ Block-Artefakte Nein
artifacts/blocks/<block>/inventory.yml Ansible Inventory Nein
artifacts/blocks/<block>/hosts_cache.json SSH Host Cache Nein
artifacts/blocks/<block>/generated/ Generierte Manifeste Nein

Standard-Verzeichnisstruktur

my-workspace/
├── artifacts/                  # Artifacts-Root (konfigurierbar)
│   ├── secrets/                # 🔐 Verschlüsselte Secrets
│   │   ├── id_rsa              # Workspace SSH-Key (verschlüsselt)
│   │   ├── id_rsa.pub          # Workspace SSH-Pubkey
│   │   ├── kubeconfig.yml      # Workspace Kubeconfig (verschlüsselt)
│   │   └── my-app/             # Block-spezifische Secrets
│   │       ├── database.pwd    # Datenbank-Passwort
│   │       └── api-key.txt     # API-Key
│   └── blocks/                 # Block-Artifacts
│       ├── my-cluster/
│       │   └── cluster-info.json
│       ├── infrastructure/
│       │   ├── inventory.yml
│       │   └── hosts_cache.json
│       └── my-app/
│           └── generated/
│               ├── deployment.yml
│               └── configmap.yml
├── secrets.poly.age            # 🔐 Verschlüsselte secrets.poly
└── blocks/                     # Block-Definitionen

Secrets-Verschlüsselung

Dateien in artifacts/secrets/ werden automatisch verschlüsselt, wenn Sie polycrate workspace encrypt ausführen. Siehe Workspace-Verschlüsselung für Details.

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

Secrets Directory

Die Secrets Directory (artifacts/secrets/) ist ein spezieller Bereich für sensitive Dateien, die bei der Workspace-Verschlüsselung automatisch verschlüsselt werden.

Struktur

artifacts/secrets/
├── id_rsa              # Workspace SSH-Key
├── id_rsa.pub          # Workspace SSH-Pubkey
├── kubeconfig.yml      # Workspace Kubeconfig
└── <block-name>/       # Block-spezifische Secrets
    ├── database.pwd    # Passwort-Datei
    ├── api-key.txt     # API-Key
    └── cert.pem        # Zertifikat

Workspace-Secrets vs Block-Secrets

Typ Pfad Zugriff in Ansible
Workspace-Secrets artifacts/secrets/ {{ workspace.secrets['filename'] }}
Block-Secrets artifacts/secrets/<block>/ {{ block.secrets['filename'] }}

Beispiel: Secrets in Ansible nutzen

# playbooks/deploy.yml
- name: Deploy mit Secrets
  hosts: all
  tasks:
    # Workspace-Secret nutzen
    - name: Kubeconfig aus Workspace-Secrets
      shell: kubectl --kubeconfig={{ workspace.secrets['kubeconfig.yml'] }} get pods

    # Block-Secret nutzen
    - name: Datenbank-Passwort aus Block-Secrets
      shell: mysql -p$(cat {{ block.secrets['database.pwd'] }}) -h localhost

Verschlüsselung

Alle Dateien in artifacts/secrets/ werden automatisch verschlüsselt, wenn Sie den Workspace verschlüsseln:

# Workspace verschlüsseln (inkl. Secrets)
polycrate workspace encrypt

# Status anzeigen
polycrate workspace status

# Entschlüsseln für Bearbeitung
polycrate workspace decrypt

Nach der Verschlüsselung:

  • secrets.polysecrets.poly.age
  • artifacts/secrets/id_rsaartifacts/secrets/id_rsa.age
  • artifacts/secrets/kubeconfig.ymlartifacts/secrets/kubeconfig.yml.age

Git-Sicherheit

Committen Sie niemals unverschlüsselte Secrets. Fügen Sie artifacts/secrets/ zu .gitignore hinzu oder verschlüsseln Sie den Workspace vor dem Commit.

Ausführliche Dokumentation zur Workspace-Verschlüsselung

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 }}"

Best Practice: Ansible-Playbooks

Alle Actions sollten mit Ansible-Playbooks implementiert werden:

actions:
  - name: status
    playbook: playbooks/status.yml

  - name: deploy
    playbook: playbooks/deploy.yml

Im Playbook haben Sie Zugriff auf alle Workspace- und Block-Variablen via Jinja2-Templating.

Artefakte generieren

Beispiel 1: Kubeconfig generieren

Komplexe Artefakt-Generierung sollte in einem Ansible-Playbook erfolgen:

# block.poly
actions:
  - name: create-cluster
    playbook: playbooks/create-cluster.yml

  - name: get-kubeconfig
    playbook: playbooks/get-kubeconfig.yml
# playbooks/get-kubeconfig.yml
- name: Kubeconfig abrufen und speichern
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Kubeconfig exportieren
      shell: kubectl config view --flatten
      register: kubeconfig_output

    - name: Kubeconfig als Artifact speichern
      copy:
        content: "{{ kubeconfig_output.stdout }}"
        dest: "{{ block.artifacts.local_path }}/kubeconfig.yml"
        mode: '0600'

    - name: Bestätigung
      debug:
        msg: "Kubeconfig saved to {{ block.artifacts.local_path }}/kubeconfig.yml"

Andere Blocks können diese Kubeconfig dann in der workspace.poly referenzieren:

# workspace.poly
blocks:
  - name: my-cluster
    from: registry.my-org.com/blocks/k8s/cluster:1.0.0

  - name: my-app
    from: registry.my-org.com/blocks/k8s/my-app:1.0.0
    kubeconfig:
      from: my-cluster  # Nutzt kubeconfig.yml von Block "my-cluster"

Beispiel 2: Inventory aus Cloud-API generieren

# playbooks/generate-inventory.yml
- name: Inventory aus Cloud-API generieren
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Cloud-Instanzen abrufen
      amazon.aws.ec2_instance_info:
        region: "{{ block.config.region }}"
        filters:
          "tag:Environment": "{{ block.config.environment }}"
      register: ec2_instances

    - name: Inventory generieren
      template:
        src: inventory.yml.j2
        dest: "{{ block.artifacts.local_path }}/inventory.yml"
      vars:
        hosts: "{{ ec2_instances.instances }}"

Beispiel 3: Generierte Konfiguration persistieren

# playbooks/generate-config.yml
- name: Konfiguration generieren und persistieren
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Konfiguration generieren
      template:
        src: config.yml.j2
        dest: "{{ block.artifacts.local_path }}/config.yml"
      vars:
        namespace: "{{ block.config.namespace }}"
        replicas: "{{ block.config.replicas }}"

    - name: Cache-Datei erstellen
      copy:
        content: "{{ block.config | to_nice_json }}"
        dest: "{{ block.artifacts.local_path }}/config_cache.json"

Artefakte zwischen Blocks teilen

Via Referenzierung

Blocks können Artifacts von anderen Blocks referenzieren (in workspace.poly):

# workspace.poly
blocks:
  - name: infrastructure
    from: registry.my-org.com/blocks/infra/base:1.0.0
    # Generiert inventory.yml in artifacts/blocks/infrastructure/

  - name: my-app
    from: registry.my-org.com/blocks/k8s/my-app:1.0.0
    inventory:
      from: infrastructure  # Nutzt inventory.yml von "infrastructure"

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 (in einem Playbook):

# playbooks/build.yml
- name: Build und Artifacts speichern
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Build durchführen
      command: make build

    - name: Artifacts-Verzeichnis erstellen
      file:
        path: "{{ block.artifacts.local_path }}/build"
        state: directory

    - name: Build-Artifacts kopieren
      copy:
        src: "{{ item }}"
        dest: "{{ block.artifacts.local_path }}/build/"
      loop:
        - dist/
        - 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 als Playbook:

# playbooks/clean.yml
- name: Artifacts aufräumen
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Artifacts-Verzeichnis leeren
      file:
        path: "{{ block.artifacts.local_path }}"
        state: absent

    - name: Artifacts-Verzeichnis neu erstellen
      file:
        path: "{{ block.artifacts.local_path }}"
        state: directory

    - name: Bestätigung
      debug:
        msg: "Artifacts cleaned: {{ block.artifacts.local_path }}"

4. Artifacts dokumentieren

Dokumentieren Sie, welche Artifacts ein Block erstellt (im Block-README):

# my-block

## Generierte Artifacts

| Datei | Beschreibung |
|-------|-------------|
| `kubeconfig.yml` | Kubernetes-Cluster-Zugriff |
| `inventory.yml` | Ansible-Hosts-Liste |
| `certs/ca.crt` | Root-CA |
| `certs/tls.crt` | Server-Zertifikat |
| `certs/tls.key` | Private Key (verschlüsselt) |

5. Artifacts validieren

Validieren Sie Artifacts nach der Generierung:

# playbooks/generate-inventory.yml
- name: Inventory generieren und validieren
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Inventory generieren
      command: python3 scripts/generate-inventory.py
      register: inventory_output

    - name: Inventory speichern
      copy:
        content: "{{ inventory_output.stdout }}"
        dest: "{{ block.artifacts.local_path }}/inventory.yml"

    - name: Inventory validieren
      command: ansible-inventory -i {{ block.artifacts.local_path }}/inventory.yml --list
      register: validation

    - name: Validierung erfolgreich
      debug:
        msg: "Inventory validated: {{ (validation.stdout | from_json).all.hosts | length }} hosts"

        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

Artifact-basierte Architektur

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