Skip to content

examples/ubuntu: splitting prepare-ubuntu.yml and k3s.orchestration.site silently drops cozystack k3s flags #43

@lexfrei

Description

@lexfrei

Environment

  • Ansible version: ansible-core 2.20.5
  • Collection version: v1.3.2 (commit edbd8ad)
  • Kubernetes distribution (k3s/kubeadm/RKE2): k3s
  • OS: Ubuntu 24.04 LTS (kernel 6.8)

Expected behavior

examples/ubuntu/ is structured as four playbooks (prepare-sudo.yml, prepare-ubuntu.yml, k3s.orchestration.site, cozystack.installer.site). Any tooling layer that wants to checkpoint between OS prep and k3s install can naturally invoke them separately:

ansible-playbook --inventory inventory.yml prepare-ubuntu.yml
ansible-playbook --inventory inventory.yml k3s.orchestration.site

I expected this to produce the same k3s installation as ansible-playbook site.yml.

Actual behavior

The split invocation produces an upstream-default k3s install — traefik, servicelb, local-storage, metrics-server, flannel, and kube-proxy are all enabled. The cozystack-required disables and overrides are absent from /etc/systemd/system/k3s.service and /etc/rancher/k3s/config.yaml:

  • missing flags: --disable=traefik, --disable=servicelb, --disable=local-storage, --disable=metrics-server, --disable-network-policy, --disable-kube-proxy, --flannel-backend=none, --cluster-domain=cozy.local, --kubelet-arg=max-pods=220
  • missing config: cluster-cidr, service-cidr

Before that, the second invocation also fails outright with:

TASK [k3s.orchestration.k3s_server : Add TLS SAN to config if needed]
[ERROR]: Error while evaluating conditional: 'ansible_hostname' is undefined

because the dynamically-created k3s_cluster group is empty in the new process. After adding the group explicitly to inventory.yml:

k3s_cluster:
  children:
    server:
    agent:

the second invocation succeeds — but produces the misconfigured k3s described above.

Root cause

prepare-ubuntu.yml uses two ansible mechanisms that only live inside one ansible-playbook process:

  1. add_host populates the k3s_cluster group (task "Create k3s_cluster group for k3s.orchestration").
  2. set_fact populates extra_server_args (from cozystack_k3s_server_args + cozystack_k3s_extra_args) and server_config_yaml (the CIDRs). The k3s.orchestration.k3s_server role reads these to assemble the systemd unit and /etc/rancher/k3s/config.yaml.

Across separate ansible-playbook invocations, both pieces of in-memory state are gone. The k3s role then takes its own defaults, and the cozystack-tuned configuration silently disappears. Ansible does not warn.

The current site.yml works because import_playbook chains everything in a single executor — but that contract is not documented anywhere a reader of examples/ubuntu/ would find before splitting the invocations.

Steps to reproduce

  1. Clone the repo, cd examples/ubuntu.

  2. Edit inventory.yml for a single-node Ubuntu 24.04 host.

  3. Run:

    ansible-playbook --inventory inventory.yml prepare-ubuntu.yml
    ansible-playbook --inventory inventory.yml k3s.orchestration.site
  4. Observe the second run failing with 'ansible_hostname' is undefined.

  5. Add k3s_cluster: {children: {server: , agent: }} to inventory.

  6. Re-run step 3 — both playbooks succeed.

  7. sudo systemctl cat k3s | grep -- --disable returns nothing; kubectl -n kube-system get pods shows traefik / servicelb / metrics-server / local-path-provisioner running; node has flannel-managed pod network.

Suggested fixes (any subset would help)

  1. Document the contract. Add to examples/ubuntu/README.md: Always run via ansible-playbook site.yml. Splitting prepare-ubuntu.yml and k3s.orchestration.site into separate invocations drops cozystack-tuned k3s flags (they cross the boundary via set_fact, which does not survive across ansible-playbook processes).

  2. Declare k3s_cluster in the inventory template. Remove the runtime add_host dependency. The prepare-ubuntu.yml task can keep the add_host as a fallback for old inventories.

  3. Move the cozystack k3s defaults out of set_fact into group_vars/all/cozystack.yml (or similar). Then cozystack_k3s_server_args and cozystack_k3s_server_config_yaml are available to any playbook in examples/ubuntu/ regardless of execution order, and the second set_fact step in prepare-ubuntu.yml becomes a no-op fallback.

  4. Fast-fail in k3s.orchestration.site if the expected vars are not set. An assert at the top of the play with that: extra_server_args is defined and a fail_msg: pointing at the README is much friendlier than the silent default-application path.

Items 2 + 3 together make the playbooks runnable independently — which matches the structure of examples/ubuntu/ and what a user reading it would expect.

Relevant logs

TASK [k3s.orchestration.k3s_server : Add TLS SAN to config if needed]
[ERROR]: Task failed: Error while evaluating conditional: 'ansible_hostname' is undefined
Origin: k3s/orchestration/roles/k3s_server/tasks/main.yml:48:7
fatal: [<HOST>]: FAILED! => {"changed": false, "msg": "Task failed: Error while evaluating conditional: 'ansible_hostname' is undefined"}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions