ci / test (push) Failing after 24s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
104 lines
5.0 KiB
YAML
104 lines
5.0 KiB
YAML
# Portainer CE in k3s mit der Datenbank von appsrv08 (Portainer EE 2.45.1). Läuft auf ops:
|
|
# ansible-playbook playbooks/portainer-k3s.yml
|
|
#
|
|
# Voraussetzung: Sicherung des Docker-Volumes portainer_data von appsrv08 als /root/.config/knaster/portainer_data.tgz
|
|
# (Inhalt: data/portainer.db, data/portainer.key, …; erzeugt mit
|
|
# docker run --rm -v portainer_data:/data:ro alpine tar -C / -czf - data > portainer_data.tgz ).
|
|
# Beim ersten Lauf wird das Volume befüllt und die Datenbank mit dem offiziellen Werkzeug der EE
|
|
# (`--rollback-to-ce`) auf Community Edition zurückgesetzt; danach bleibt der Datenstand im Cluster.
|
|
# Benutzer, API-Schlüssel und Umgebungen bleiben erhalten (getestet 15.10.2026). Die Umgebung 4 (Docker-Socket
|
|
# von appsrv08) funktioniert im Cluster nicht mehr; appsrv08 wird als Agent-Umgebung neu angebunden.
|
|
- name: Portainer CE nach k3s
|
|
hosts: localhost
|
|
connection: local
|
|
gather_facts: false
|
|
vars:
|
|
manifest: "{{ playbook_dir }}/../../../../deploy/k8s/portainer/portainer.yaml"
|
|
backup: /root/.config/knaster/portainer_data.tgz
|
|
ns: portainer-ce
|
|
version: 2.45.1
|
|
tasks:
|
|
- name: Namespace, PVC, RBAC (noch ohne Deployment, damit das Volume zuerst befüllt wird)
|
|
ansible.builtin.shell: >
|
|
set -o pipefail;
|
|
python3 -c "import sys,yaml; docs=[d for d in yaml.safe_load_all(open('{{ manifest }}')) if d and d['kind']!='Deployment' and d['kind']!='Service']; yaml.safe_dump_all(docs, sys.stdout)"
|
|
| kubectl apply -f -
|
|
args: {executable: /bin/bash}
|
|
register: base
|
|
changed_when: "'created' in base.stdout"
|
|
|
|
- name: Ist das Volume schon befüllt?
|
|
ansible.builtin.command: kubectl -n {{ ns }} get configmap portainer-seeded
|
|
register: seeded
|
|
failed_when: false
|
|
changed_when: false
|
|
|
|
- name: Sicherung vorhanden?
|
|
ansible.builtin.stat:
|
|
path: "{{ backup }}"
|
|
register: bk
|
|
when: seeded.rc != 0
|
|
failed_when: not bk.stat.exists
|
|
|
|
- name: Volume aus der Sicherung befüllen (Hilfs-Pod auf dem Knoten k3s)
|
|
ansible.builtin.shell: |
|
|
set -e
|
|
kubectl -n {{ ns }} delete pod seed --ignore-not-found >/dev/null
|
|
cat <<EOF | kubectl apply -f - >/dev/null
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata: {name: seed, namespace: {{ ns }}}
|
|
spec:
|
|
nodeSelector: {knaster.role: control}
|
|
restartPolicy: Never
|
|
containers:
|
|
- name: seed
|
|
image: alpine:3.20
|
|
command: ["sleep", "600"]
|
|
volumeMounts: [{name: data, mountPath: /data}]
|
|
volumes: [{name: data, persistentVolumeClaim: {claimName: portainer-data}}]
|
|
EOF
|
|
kubectl -n {{ ns }} wait --for=condition=Ready pod/seed --timeout=180s >/dev/null
|
|
kubectl -n {{ ns }} cp {{ backup }} seed:/tmp/pd.tgz
|
|
kubectl -n {{ ns }} exec seed -- sh -c "cd /tmp && tar xzf pd.tgz && cp -a data/. /data/ && test -s /data/portainer.db"
|
|
kubectl -n {{ ns }} delete pod seed --wait=true >/dev/null
|
|
when: seeded.rc != 0
|
|
|
|
- name: Datenbank auf Community Edition zurücksetzen (offizielles Werkzeug der EE, fragt per stdin)
|
|
ansible.builtin.shell: |
|
|
set -e
|
|
kubectl -n {{ ns }} delete pod rollback --ignore-not-found >/dev/null
|
|
echo y | kubectl -n {{ ns }} run rollback -i --restart=Never --image=portainer/portainer-ee:{{ version }} \
|
|
--overrides='{"spec":{"nodeSelector":{"knaster.role":"control"},"containers":[{"name":"rollback","image":"portainer/portainer-ee:{{ version }}","args":["--rollback-to-ce"],"stdin":true,"volumeMounts":[{"name":"data","mountPath":"/data"}]}],"volumes":[{"name":"data","persistentVolumeClaim":{"claimName":"portainer-data"}}]}}' >/dev/null 2>&1 || true
|
|
sleep 5
|
|
kubectl -n {{ ns }} logs rollback | grep -q "rolled back to CE Edition"
|
|
kubectl -n {{ ns }} delete pod rollback --wait=false >/dev/null
|
|
kubectl -n {{ ns }} create configmap portainer-seeded --from-literal=source={{ backup | basename }} --from-literal=date="$(date -Is)"
|
|
when: seeded.rc != 0
|
|
|
|
- name: Deployment und Service
|
|
ansible.builtin.command: kubectl apply -f {{ manifest }}
|
|
register: dep
|
|
changed_when: "'configured' in dep.stdout or 'created' in dep.stdout"
|
|
|
|
- name: Warten, bis bereit
|
|
ansible.builtin.command: kubectl -n {{ ns }} rollout status deployment/portainer --timeout=300s
|
|
changed_when: false
|
|
|
|
- name: Version und Edition über NodePort (Knoten k3s)
|
|
ansible.builtin.uri:
|
|
url: "https://{{ hostvars['k3s'].ansible_host }}:30779/api/system/version"
|
|
validate_certs: false
|
|
return_content: true
|
|
register: ver
|
|
until: ver.status == 200
|
|
retries: 6
|
|
delay: 5
|
|
|
|
- name: Ergebnis
|
|
ansible.builtin.assert:
|
|
that:
|
|
- ver.json.ServerEdition == 'CE'
|
|
- ver.json.ServerVersion == version
|
|
success_msg: "Portainer {{ ver.json.ServerEdition }} {{ ver.json.ServerVersion }} unter https://{{ hostvars['k3s'].ansible_host }}:30779"
|