Files
cluster-autoscaler-with-capi/docs/plans-executions/2026-09-27-0058-mgmt-cluster-ansible.md
T
kacerrandClaude Opus 5.5 605d6ebf0d Accept cloud-init rc 2 (recoverable errors) in the k3s play
PVE's cloud-init user-data triggers a deprecation warning that makes
`cloud-init status --wait` exit 2 even though provisioning succeeded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 09:40:28 +02:00

89 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Execution log: idempotent management cluster (Ansible + cluster-api-operator)
Pairs with [docs/plans/2026-09-27-0058-mgmt-cluster-ansible.md](../plans/2026-09-27-0058-mgmt-cluster-ansible.md).
## Status
- [x] Step 0 — Initial import commit + plan commit
- [x] Step 1 — Scaffold `ansible/`, `.gitignore` exception, syntax/lint checks
- [ ] Step 2 — Run the playbook tag by tag against the lab (owner)
- [ ] Step 3 — Idempotency check (second full run `changed=0`)
- [ ] Step 4 — Docs, versions, decisions, changelog
## Step 0 — Initial import + plan
The repo had no commits, so the existing tree went in first as `5fd998c` (after a grep for
token/secret/key material found only placeholders), then the plan alone as `ac7d5a4`.
## Step 1 — Scaffold `ansible/` (2026-09-27 01:02 CEST)
Wrote `ansible/{ansible.cfg,inventory.yml,group_vars/all.yml,secrets.yml.example,mgmt.yml}` and
four templates as planned. `ansible/secrets.yml` was already ignored by `*secret*`; added
`!ansible/secrets.yml.example`.
`ansible-core` is not installed on the laptop, so checks ran through `uvx` (cached, nothing
installed globally), pinned to ansible-core 2.18 (resolved 2.18.19):
```bash
cd ansible
uvx --from 'ansible-core>=2.18,<2.19' ansible-playbook mgmt.yml --syntax-check
uvx --with 'ansible-core>=2.18,<2.19' ansible-lint --profile production mgmt.yml
```
First lint run: 6× `name[casing]`, 5× `no-changed-when`. The commands flagged are the
create/resize/start/install tasks that only run behind a `when:` guard, so they got
`changed_when: true` rather than a fake condition. Second run: production profile passed.
Rendered all templates with dummy values (`-e mgmt_ip=192.0.2.10`, secret `DUMMY`) through a
throwaway local playbook: provider manifest parses as 11 documents (5 Namespaces, Secret, 5
provider CRs), k3s config and kubeconfig rewrite (`server` → VM IP, every `default` name →
`lab-mgmt`) come out as intended.
Connectivity to the PVE host:
```bash
uvx --from 'ansible-core>=2.18,<2.19' ansible pve -m ping -o
# pv1-1 | UNREACHABLE!: ... root@192.168.0.8: Permission denied (publickey,password).
```
**Worth noting:**
- The plan's assumption "root SSH from the laptop to `pv1-1` works" does not hold yet; the host
answers but rejects the laptop's keys. Needed before Step 2.
- Condition-based waits: the playbook waits for `Available` Deployments in each provider
namespace instead of a condition on the provider CRs, so it doesn't depend on the operator's
condition naming (plan left that open).
- VM params (`mgmt_vmid`, `mgmt_ip`, `mgmt_gateway`, `mgmt_dns`) are empty in `group_vars/all.yml`;
Play 1 asserts on them.
- `clusterctl` is not installed on the laptop either (needed for phase-1 Step 3, not for this playbook).
## Step 2 — Playbook runs (in progress)
### `--tags vm`, first attempt (2026-09-27 09:30 CEST, owner)
Owner authorised the laptop key on `pv1-1`, installed ansible locally and filled in VM params
(`mgmt_vmid: 201`, `mgmt_ip: 192.168.4.21/24`, gateway `192.168.4.8`).
```bash
ansible-playbook mgmt.yml --tags vm
# TASK [Create the VM]
# "cmd": [..., "--nameserver", "8.8.8.8,", "2.2.2.2"]
# stderr: 400 too many arguments
```
`mgmt_dns` was the string `"8.8.8.8, 2.2.2.2"`; the command module splits on whitespace, so
`qm` got two positional leftovers. Fix: `mgmt_dns` is now a list and the task passes
`--nameserver '{{ mgmt_dns | join(' ') }}'` as one argument (space-separated is PVE's format for
the cloud-init nameserver list). Image download and key staging had already succeeded and are
idempotent on re-run; `qm status 201` confirmed no half-created VM was left behind.
### `--tags vm` second attempt, `--tags k3s` first attempt (2026-09-27 ~09:39 CEST, owner)
`--tags vm` created VM 201; the owner logged in as `ubuntu`. `resolvectl dns` on the VM shows
`eth0: 8.8.8.8 2.2.2.2`, so PVE's space-separated nameserver list works.
`--tags k3s` failed on the first task: `cloud-init status --wait` → `status: done`, rc 2.
`cloud-init status --long` showed `extended_status: degraded done`, `errors: []`, and only a
recoverable DEPRECATED warning: PVE's generated user-data sets `user:` as a string (deprecated
since cloud-init 22.2). rc 2 = "done with recoverable errors", so the task now fails only on rc
other than 0/2.