Skip to content

switching from docker.io to docker-ce - #37

Open
vladimirhasko wants to merge 15 commits into
mainfrom
docker_switch
Open

switching from docker.io to docker-ce#37
vladimirhasko wants to merge 15 commits into
mainfrom
docker_switch

Conversation

@vladimirhasko

Copy link
Copy Markdown
Contributor

No description provided.

@vladimirhasko vladimirhasko changed the title switching from docker.io docker-ce switching from docker.io to docker-ce Aug 17, 2026
@vladimirhasko

Copy link
Copy Markdown
Contributor Author

recheck

- pod has no ansible_facts: drop fact templates, hardcode
  debian/bookworm/amd64 for the Docker CE apt repo and GPG URL
- pod has no systemd as PID 1: drop systemd/service modules,
  launch containerd and dockerd as nohup'd background processes
  and wait for the sockets before verifying with docker info
- gather_facts: false (facts unavailable/unnecessary in the pod)
The initial apt update runs before the Docker repo file is written,
so the package manager has no knowledge of docker-ce when install
fires. Add a second apt update after creating the .list file.
The socket appears early but dockerd hasn't fully initialized yet,
causing 'docker info' to fail on first attempt. Replace the single
verify task with a 15-attempt retry loop (5s delay, up to 75s total).

Also replace 'docker version --format' with 'docker --version' to
avoid Jinja2 brace escaping issues.
Replace the silent retry loop with tasks that dump:
- docker info output from last attempt
- dockerd process list (ps aux | grep dockerd)
- last 100 lines of /var/log/dockerd.log
- last 100 lines of /var/log/containerd.log
Then fail with all that context so we can see what went wrong.
Root cause from the Zuul log: the zuul-debian pod is not privileged
(no CAP_NET_ADMIN), so dockerd cannot create the DOCKER NAT chain
(iptables 'Permission denied') and exits during network-controller
init. The fix is a privileged nodepool label (system-config PR, same
pattern as zuul-debian-builder) plus dockerd flags suited to a
systemd-less pod:
  --exec-opt native.cgroupdriver=cgroupfs
  --iptables=false --ip6tables=false --bridge=none
containers will run with host networking (single-node localhost
inventory does not need a bridge).
@LukasCuperDT

Copy link
Copy Markdown

recheck

LukasCuperDT added a commit to opentelekomcloud-infra/system-config that referenced this pull request Aug 20, 2026
zuul-debian-docker (prod) and zuul-debian (preprod) declared
shell-type: /bin/bash. Zuul passes that to ansible as ansible_shell_type,
which is a plugin name, not a path, so every job on those labels died in
Gathering Facts with

  Could not find the shell plugin required (/bin/bash).

Ansible ships sh, csh, fish, powershell and cmd - there is no bash plugin;
bash is handled by sh, which is what the other three labels already use.

Found via stackmon/cloudmon#37, whose job is the first to request
zuul-debian-docker from its own playbooks. Our smoke test missed it
because the zuul-infra playbooks set ansible_shell_type explicitly.
* Fix the docker daemon diagnostic block

The 'Fail with diagnostic context' task had no when condition, so the
play failed even when docker started correctly. Conversely the wait_for
above it aborted the play on real failure, so the diagnostics it was
meant to collect never ran in the case they were written for.

Make wait_for non-fatal and put the diagnostics and the failure behind
'docker_sock is failed', so they run exactly when the socket never
appeared.

Also drop the reference to docker_info, which is never registered, and
use pgrep instead of 'ps aux | grep' under ansible.builtin.command,
which does not interpret pipes - those characters were being passed to
ps as literal arguments.

* Install python packaging and venv tooling before cloudmon roles

install_cloudmon failed on the zuul-debian-docker node with:
  ModuleNotFoundError: No module named 'packaging'

ansible.builtin.pip imports packaging on the target, and cloudmon_venv_path
defaults to ~/.venv so the module also has to build a virtualenv. The node
image provides neither, so install them before the roles run.

* Surface cloudmon provision output instead of a bare rc

The Deploy task ran graphite, statsd and postgres provisioning in one shell
block with no 'set -e', so rc came from the last command only and an earlier
failure would pass unnoticed. On failure Ansible reported just 'non-zero return
code' with no stdout/stderr, and job-output.json is not uploaded, so there was
nothing to debug from.

Run one component per loop item, print rc/stdout/stderr for each, then fail
listing the components that actually failed.

* Fix inventory template: group hosts must be a mapping

Every child group declared its hosts as a list:

    statsd:
      hosts:
        - localhost

Ansible's yaml inventory plugin requires a mapping there and rejected the
whole file:

    Invalid "hosts" entry for "statsd" group, requires a dictionary

With no inventory parsed, every provisioning play matched no hosts. graphite
still exited 0 while doing nothing ('skipping: no hosts matched'), so the
failure surfaced only as statsd/postgres rc=1.

Reproduced with ansible-inventory: the old template raises the exact error,
the new one resolves all 8 groups to localhost.

* Use local connection for localhost in cloudmon inventory

Provisioning failed with:

    ssh: connect to host localhost port 22: Connection refused
    fatal: [localhost]: UNREACHABLE!

Listing localhost explicitly in the inventory overrides Ansible's implicit
local connection, so it fell back to ssh. The zuul-debian pod runs no sshd,
so set ansible_connection: local.

* Allow skipping host firewall management

Graphite provisioning failed in the pod-based job with:

    Could not find the requested service firewalld: host

The firewalld role is pulled in unconditionally by seven install playbooks and
manages host services. A container has no service manager and no host
firewall, so those tasks cannot succeed. 'Disable iptables' already had
ignore_errors; 'Enable firewalld' did not, so it aborted the play.

Gate the role body behind cloudmon_manage_firewall, defaulting to true so
VM-based deployments are unchanged, and set it false in the k8s job
inventory.

* Use the block keyword instead of ansible.builtin.block

Provisioning aborted with:

    unexpected parameter type in action: <class ..._AnsibleTaggedList>
    Origin: roles/graphite/tasks/main.yaml:38:3

'block' is a task keyword, not a module -- there is no ansible.builtin.block
action, so ansible-core treats it as a module receiving a list.

Fixes all 22 occurrences across 11 roles, introduced in 685afcf.

* Use netcat-openbsd on Debian

Package installation failed on the Debian bookworm node:

    E: Package 'netcat' has no installation candidate
    Package netcat is a virtual package provided by:
      netcat-openbsd 1.219-1
      netcat-traditional 1.10-47

'netcat' is virtual on bookworm and cannot be installed directly. Use
netcat-openbsd, which provides nc, in the graphite, statsd and carbonapi
Debian vars.

* Gate per-role firewalld tasks too

Graphite provisioning still failed after gating the firewalld role:

    TASK [graphite : Allow graphite port]
    Failed to import the required Python library (firewall)
    Origin: roles/graphite/tasks/firewall.yml:4:3

Six roles include their own firewall.yml to open ports via ansible.posix
.firewalld, which needs the firewall python library and a running firewalld.
Neither exists in a container, so gate these includes behind the same
cloudmon_manage_firewall variable.
Graphite provisioning failed with:

    Failed to find required executable "crontab" in paths: ...

The rewritten Debian vars dropped 'cron', which main still lists. The graphite
role is the only one using ansible.builtin.cron ('Run periodic cleanup'), and
that module needs the crontab binary.

apparmor-profiles was dropped in the same rewrite but is never referenced by
any task, so it stays out.
@LukasCuperDT

Copy link
Copy Markdown

recheck

Provisioning failed once it reached the application layer:

    System has not been booted with systemd as init system (PID 1).
    Can't operate. Failed to connect to bus: Host is down

cloudmon deploys through systemd -- 15 unit templates, 68 systemd tasks and 14
daemon_reload calls -- so the node needs a real init. Switch the nodeset to the
new zuul-debian-systemd label, which runs systemd as PID 1.

With systemd present, let it own containerd and dockerd instead of starting
them with nohup; hand-started daemons would collide with the units the
cloudmon roles enable. The daemon settings now come from /etc/docker/daemon.json
seeded by the pod spec. Diagnostics read the journal instead of the log files
the manual start used to write.

Verified on a probe pod on the cluster: PID 1 is systemd, is-system-running
reports running, daemon-reload succeeds, and a unit written at runtime can be
enabled and started.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants