Hallo zusammen,
seit kurzem beschäftige ich mich mit Ansible und erkunde die Möglichkeiten.
Einbetten von Daten in einem Playbook
Um Abhängigkeiten eines Playbooks möglichst gering zu halten, bette ich Dateien als base64 enkodierte Zeichenketten in das Playbook ein. Diese werden dann mit der Ausführung des Playbooks dekodiert, auf dem Manged Host gespeichert und für die Playbook-Ausführung verwendet. Beim Abschluss des Playbooks werden diese Dateien auch wieder gelöscht. Das sieht zum Beispiel ungefähr so aus:
- name: Test playbook which contains pip and use it
hosts: localhost
gather_facts: false
vars:
# Name: pip-25.2-py3-none-any.whl
# Size: 1752557 Bytes
# SHA256: 6d67a2b4e7f14d8b31b8b52648866fa717f45a1eb70e83002f4331d07e953717
base64_pip: UEsDBBQAAAAIA ... ACqz5MAAAA=
tasks:
- name: Write pip wheel
ansible.builtin.copy:
content: "{{ base64_pip | b64decode }}"
dest: /tmp/pip-25.2-py3-none-any.whl
mode: "0777"
- name: List installed Python packages
ansible.builtin.command:
cmd: /usr/bin/python3 /tmp/pip-25.2-py3-none-any.whl/pip list
register: result
changed_when: result.rc != 0
- name: Show output
ansible.builtin.debug:
var: result
- name: Delete pip wheel
ansible.builtin.file:
path: /tmp/pip-25.2-py3-none-any.whl
state: absent
Das funktioniert einwandfrei und sehr gut. Es entspricht meinen Erwartungen und verschafft mir Freiräume meine Playbooks deutlich leistungsfähiger auszuprägen.
Aber wie es immer so ist: Überall wo Licht ist, ist auch Schatten.
Sicherheitsrisiken
Durch die base64 Enkodierung entziehen sich diese Inhalte einer direkten Prüfung. Es sind im Vorfeld entsprechende Analysen durchzuführen und sicherzustellen dass die Inhalte auch wirklich dem entsprechen was sie beinhalten sollen. Die Playbooks werden im Git gespeichert, somit ist der Entwickler bekannt. Damit relativieren sich nach meiner Auffassung die Sicherheitsrisiken.
Fragen
Deshalb meine Fragen in die Runde:
Was seht ihr für Problemstellungen die aus diesem Ansatz erwachsen können?
Haltet ihr diesen Ansatz für ein valides Vorgehen um die Leistungsfähigkeit von Playbooks zu verbessern?
Vielen Dank für Antworten und Tipps.
Beste Grüße
Stefan
Summary: Pros & Cons with respect to embedding artifacts/assets as base64 strings, particularly with respect to reducing project file count.
When I first started my Ansible journey, I was not at all comfortable with the proliferation of files and the directory trees that contained them. I was convinced that there should be a way to express any project as a single YAML file. Part of me still thinks that way, but at any practical level, I was wrong.
Tooling is set up to expect a certain layout of directories.
Separation of code from data assets is an established guideline. Like any guideline, use your own experience and specific micro-goals to determine when to set it aside. There may be single instances where you want to do this, but in general this doesn’t seem to me like a source of joy in the long run.
If you do embed assets into your playbook files like this, then your playbook is no longer the canonical source of your project. Rather, it will be the output of some other home-grown process to assemble these assets into a single file. In that case, you haven’t achieved your goal of reducing file counts; you’ve simply moved the problem “upstream”.
I seriously doubt that you would gain any noticeable performance by pursuing this approach. I’ll gladly stand corrected; I have no actual data to argue the point either way. But I can’t realistically imagine enough improvement to justify this technique in the general case.
There is a satisfying sense of achievement when you get such novel tricks working. Don’t confuse that positive feeling with actual progress. The long-term goal isn’t to reduce file counts or improve performance. It’s to configure your apps and the infrastructure they run on. While interesting and instructive, I’m not sure whether the effort spent — again, in general — advances achievement of that goal.
Kleiner Hinweis: ich würde eine block:/always:-Konstruktion verwenden, damit die temporäre Datei auch gelöscht wird, wenn zwischendurch etwas schief geht. Weiterhin würde ich das ansible.builtin.tempfile-Modul verwenden, um einen zufälligen Dateinamen zu wählen, um Kollisionen zu vermeiden, wenn z.B. das gleiche Playbook von zwei verschiedenen Benutzern ausgeführt wird.
Zur Idee selber: ich würde Daten vom Playbook trennen. Wenn das ganze eh in einem git-Repository ist und man davon ausgeht, dass alle die das Playbook nutzen dieses Repository gecloned haben, gibt es keinen Grund die Datei so zu verstecken.
Vorteile einer separaten Datei aus meiner Sicht:
Es ist schneller. Die Daten müssen nicht erst durch den YAML-Parser, dann Base64-dekodiert werden, als temporäre Datei auf Disk geschrieben werden, bevor sie kopiert werden können.
Updates der Binärdatei sind in der git-History besser und einfacher von Updates des Playbooks zu unterscheiden.
Updates der Binärdatei sind einfacher zu machen: einfach Datei ersetzen, anstelle die Datei Base64 kodieren und den Inhalt per Copy’n’paste ins Playbook kopieren.
Das Risiko für Fehler beim Updaten ist geringer. (Beim Copy’n’paste kann einfacher was schiefgehen. Beim Kopieren einer ganzen Datei ist das Risiko viel geringer.)
Gerade bei grossen Dateien kann git-lfs richtig genutzt werden, ohne dass man das ganze Playbook damit handeln muss (was das Arbeiten mit der History erschwert).
Hallo Felix [@felixfontein],
vielen Dank für Deine sehr interessanten Ausführungen.
Die Idee einer separaten Datei im Git habe ich noch gar nicht betrachtet, das werde ich mal ausprobieren denn die Vorteile liegen ja wirklich auf der Hand.
Beste Grüße
Stefan
Hello Todd [@utoddl],
thank you very much for your post.
Yes, I tried to make everything as compact as possible. Your experiences are very valuable. I see that it seems sensible to use this approach only in exceptional cases. I will think about that.
Best regards
Stefan