Releases: arillso/ansible.container
Release list
2.0.0
[2.0.0] - 2026-08-16
Removed
- Five unused helm variables:
helm_target_groups,helm_target_host,
helm_kubectl_context,helm_validation_timeoutandhelm_log_levelare
gone fromroles/helm/defaults/main.ymland
roles/helm/meta/argument_specs.yml. No task file in the role ever read
them, so setting them changed nothing and produced no warning.
helm_target_groupsandhelm_target_hostwere especially misleading: they
suggested the role filters its own target hosts, which it does not — host
selection belongs in the play (hosts:). Validation behaviour is unaffected:
helm_validation_retriesandhelm_validation_delayare read by
roles/helm/tasks/charts.yml,helm_validation_enabledby
roles/helm/tasks/prerequisites.yml, and together they cover the validation
flow.
Added
-
apt_version_pinfilter plugin: resolves a version prefix to the full
version string apt reports, replacing four hand-rolled Jinja regex copies in
the docker anddocker_compose_v2roles. Documented in
plugins/filter/DOCUMENTATION.ymland covered by
tests/unit/plugins/filter/test_apt_filters.py. -
Configurable fleet bundle readiness wait:
fleet_bundle_wait(true)
andfleet_bundle_wait_timeout(300) inroles/fleet/defaults/main.yml,
both overridable per bundle viawait/wait_timeouton the item and
declared inmeta/argument_specs.yml. The "Manage Fleet Bundles" task
previously applied each bundle with a hardcoded wait forReady, so a serial
loop over many bundles stacked up the 300s timeout per item. Stable bundles
can now be applied fire-and-forget and let Fleet reconcile them
asynchronously; the registered result shape is unchanged. -
k3s container log rotation defaults:
k3s_container_log_max_size
(10Mi) andk3s_container_log_max_files(5) now have defaults in
defaults/main.ymland entries inmeta/argument_specs.yml. Both were
previously only read by anis definedguard in the agent config template,
so out of the box kubelet never receivedcontainer-log-max-size/
container-log-max-filesand container logs grew unbounded. The guards stay
in place, so settingk3s_container_log_max_sizeto""or
k3s_container_log_max_filesto0still omits the respective flag. -
k3s hardening variables: eight new variables defined in both
defaults/main.ymlandmeta/argument_specs.yml—
k3s_secrets_encryption,k3s_protect_kernel_defaults,
k3s_audit_log_enabled,k3s_audit_log_maxage,k3s_anonymous_auth,
k3s_node_restriction,k3s_kubelet_read_only_port_disabled,
k3s_audit_log_levelandk3s_pod_security_admission_profile. All are gated
byk3s_security_hardening, which previously only covered SELinux/AppArmor. -
k3s audit policy: renders
audit-policy.yamland passes
audit-policy-fileto the kube-apiserver when audit logging is enabled.
Without a policy file the apiserver matches no events and the audit log stays
empty. Drops high-volume node/proxy and health-endpoint traffic, caps secrets
and configmaps atMetadata, and logs everything else at
k3s_audit_log_level. -
k3s Pod Security Admission: optional cluster-wide default profile via
k3s_pod_security_admission_profile(empty by default, so no behaviour
change). Renderspsa-config.yamlwithkube-systemexempt and wires it as
admission-control-config-file. -
k3s molecule hardening assertions:
verify.ymlchecks the rendered
config for the hardening flags,k3s secrets-encrypt statusforEnabled,
the credential directory for0700, and that a user-supplied
kube-apiserver-argsurvives the hardening merge. -
Molecule coverage for the five previously-untested roles, each with a
defaultscenario underroles/<role>/molecule/default/and a matching
molecule-<role>job wired intopull-request.yml(qemu/KVM driver,
Ubuntu 22.04 cloud image, pinned toci-ansible-molecule.yml@2026-06-18). -
docker_login molecule — full converge: a
prepare.ymlinstalls Docker via
thedockerrole and starts a throwaway localregistry:2container,
converge logs intolocalhost:5000, and verify asserts the registry appears
underauthsin the Docker client config. -
docker_compose_v2 molecule — full converge:
prepare.ymlinstalls Docker,
converge deploys a minimalnginxcompose project, and verify asserts the
compose plugin, the rendered project file, the systemd unit and a running
container. -
helm, fleet, tailscale molecule — full converge against an
ephemeral k3s cluster. Each scenario gained aprepare.ymlthat installs
arillso.container.k3sin the same QEMU VM and adds whatever upstream
controller the role needs, soconverge,idempotenceandverifyare now
part of thetest_sequence. No external cluster and no repository secret is
involved, which keeps the jobs working on fork pull requests. These scenarios
assert that the roles emit schema-valid resources the API accepts; they do not
assert that the upstream controllers act on them. -
helm molecule exercises the whole deployment chain: the role applies a
HelmChart CR, the k3s Helm controller turns it into an install Job, and verify
asserts the CR, the completed Job and the running Pod. -
fleet molecule installs standalone Fleet (
fleet-crd, thenfleet) and
asserts that the GitRepo and Bundle CRs the role emits are accepted by the
fleet.cattle.ioAPI with the expected spec and labels. Workspaces
(Rancher-onlymanagement.cattle.io/v3), registration tokens (the controller
rotates the secret) and clusters (need a second cluster's kubeconfig) stay out
of the fixture. -
tailscale molecule installs the operator chart with dummy OAuth
credentials and without waiting for the Pod, which registers the
tailscale.comCRDs without a real tailnet, then asserts the ProxyGroup the
role creates.
Fixed
-
docker version pin never matched on the Debian family: apt matches an
=
pin against the full version string and does not expand globs in it, so the
shippeddocker_versiondefault (docker-ce=28.5.2) was unusable on Debian
and Ubuntu — apt reports the version with an epoch and a distro release
suffix.install_docker_debian.ymlandinstall_docker_ubuntu.ymlnow
resolve the full version string on the host before pinning. Every existing
docker scenario blankeddocker_version, so the shipped default had never
been exercised; a newpinnedmolecule scenario runs the role without that
override and asserts the installed server version equals the pin. -
docker_compose_v2 pin was built in one form for three package managers:
apt needed the full version string it never got, and dnf does not know the
pkg=versionsyntax at all, so every pinned run failed on a role that
advertises Debian, Ubuntu and EL 9. The pin form now lives in
per-distributionvars/files, and the apt string is resolved on the host
through the newapt_version_pinfilter. -
helm applied charts to only one host per play:
charts.yml,
prerequisites.ymlandrepositories.ymlcarriedrun_once, but each host
the role targets is its own k3s cluster, so the HelmChart CRs reached a single
host and left the other clusters empty. Removingrun_oncealso unmasks the
kubeconfig autodetection, which promised the first existing candidate but let
the loop overwrite it down to the last; it now selects the first match in one
pass. -
helm_kubeconfig_pathwas undocumented and unvalidated: the role read it
in 13 task lines, including askubeconfigfor everykubernetes.corecall,
but declared it in neitherdefaults/main.ymlnormeta/argument_specs.yml.
Both now declare it. The default stays empty, sinceprerequisites.ymlonly
autodetects the path while the value is unset or empty. -
lefthook could not lint without Galaxy access: the
ansible-linthook
resolved the collections declared in the molecule requirements against
galaxy.ansible.com, so a machine without Galaxy egress could not commit any
file under the hook's glob and had to reach for--no-verify, which drops the
gitleaks hook too. The hook now lints offline. -
Renovate could not refresh the pinned nginx digest: the
image:lines in
roles/docker_compose_v2/molecule/default/converge.ymlandverify.yml
carried a# renovate: datasource=docker depName=nginxcomment, which the
comment manager from the sharedrenovate-basepreset read as
currentValue: nginx:alpine. The resulting request for the
library/nginx:nginx:alpinemanifest returned400 DIGEST_INVALIDand every
Renovate run reported "Could not determine new digest for update" as a
repository problem, leaving the digest frozen. The comments are gone and
.github/renovate.jsongained acustomManagerthat parses theimage:
line itself, sodepNameisnginx,currentValueisalpineand the
digest updates again. The match requires an@sha256:suffix, which keeps
tag-only test images such asregistry:2indocker_loginuntracked, while
the tag itself is optional so a digest-only pin (image: nginx@sha256:…) is
still tracked rather than silently frozen. Excluding/from the tag keeps a
port-qualified registry (registry.example.com:5000/nginx) insidedepName
instead of splitting it at the port. -
k3s AppArmor profile survived being disabled: setting
k3s_apparmor_profiletofalseonly stopped
roles/k3s/tasks/security.ymlfrom writing/etc/apparmor.d/k3s; a copy
left from an earlier run stayed on disk and was reloaded by
apparmor.serviceon every boot, so turning the variable off never took
effect on hosts that once had it on. The role now mirrors the cri-containerd
disable path — it unloads the profile withapparmor_parser -R, removes the
file and clears a hand-pla...
1.4.0
[1.4.0] - 2026-06-12
Added
- New
k3s_etcd_s3_access_key/k3s_etcd_s3_secret_keyvariables in the k3s
role: renderetcd-s3-access-key/etcd-s3-secret-keyinto the server
config so scheduled etcd snapshots can authenticate against S3-compatible
storage (e.g. Cloudflare R2). The config file is deployed with mode0600,
so credentials stay root-only on disk. Both variables are optional and
omitted when unset — existing consumers are unaffected. - New
k3s_health_check_delay/k3s_health_check_timeout/
k3s_health_check_sleepvariables (defaults30/600/10,
backwards-compatible) parametrise the server API readiness probe in the
k3s role. Thewait_fortask previously hard-codeddelay: 30, an
unconditional pre-sleep on every run; consumers running against an
already-converged server can now setk3s_health_check_delay: 0to skip
the idle wait whiletimeout/sleepstill cover the cold-bootstrap race.
Changed
- Documented the full etcd snapshot variable family in the k3s role's
argument_specs.yml(k3s_etcd_expose_metrics,
k3s_etcd_snapshot_schedule_cron,k3s_etcd_snapshot_retention,
k3s_etcd_snapshot_dir,k3s_etcd_s3,k3s_etcd_s3_endpoint,
k3s_etcd_s3_region,k3s_etcd_s3_bucket,k3s_etcd_s3_folderplus the two
new credential variables). These were previously template-only and
undocumented. All arerequired: falseand carry no spec default — the
template gates each withis defined, so a default would change behaviour —
and the two credential keys are markedno_log: true.
Fixed
docker_compose_v2role: removed bogus"{{ omit }}"defaults for optional
variables. The literal placeholder string broke argument-spec validation for
non-str-typed vars (docker_compose_v2_scaleasdict,
_files/_profiles/_servicesaslist[str]) under Ansible 2.18+.
Optional vars are now intentionally undefined and the module-call kwargs
apply| default(omit)to emit a real omit sentinel. End behaviour is
unchanged for consumers that did not override these vars.
1.3.13
[1.3.13] - 2026-05-03
Added
- New
k3s_cri_apparmor_profile_enabledvariable (defaulttrue,
backwards-compatible) to opt out of deploying thecri-containerd.apparmor.d
profile in the k3s role; when set tofalsethe role unloads the profile
from the kernel, removes the file, and notifiesRestart k3s. Workaround
for kernel 6.17 AppArmor profile-stacking bugs
(k3s-io/k3s#13625,
containerd/containerd#12886)
which cause pod termination to hang and flood dmesg with SIGURG denials
1.3.12
[1.3.12] - 2026-04-01
Changed
- Reverted unrestricted
signal,AppArmor rule back to targeted peer-specific rules in k3s security profile; restricts signal operations to known peers (host and containerd manager) for a tighter security posture while maintaining full functionality - Added
signal (send) peer=cri-containerd.apparmor.drule to allow container processes to signal each other (e.g. PID 1 sending SIGTERM to children during graceful shutdown)
1.3.11
[1.3.11] - 2026-03-31
Fixed
- Replaced restrictive AppArmor signal rules (
signal (receive) peer=unconfinedandsignal (receive) peer=cri-containerd.apparmor.d) with unrestrictedsignal,in k3s security profile; runc requires full signal capabilities (send/receive) to deliver SIGTERM/SIGKILL to container init processes during pod termination
1.3.10
[1.3.10] - 2026-03-28
Fixed
- Deploy
/etc/apparmor.d/cri-containerd.apparmor.dwithchange_profile -> **,in k3s role;
on Ubuntu 24.04 (kernel 6.8, AppArmor 4.x) containerd generates this profile dynamically
without the rule, causingkubectl execto fail with
apparmor failed to apply profile: write fsmount:fscontext:proc/thread-self/attr/apparmor/exec: operation not permitted. Pre-deploying the fixed profile ensures runc can apply AppArmor
profiles to exec'd container processes.
1.3.9
[1.3.9] - 2026-03-28
Fixed
- Replaced invalid
fsmount,AppArmor rule (parse error:unexpected TOK_END_OF_RULE, expecting TOK_MODE) withchange_profile -> **,in k3s security profile; this allows containerd to write the target profile name to/proc/thread-self/attr/apparmor/execbefore exec, which is how AppArmor profiles are applied to container processes
1.3.8
[1.3.8] - 2026-03-28
Fixed
- Added
fsmount,AppArmor rule to k3s security profile; required for AppArmor 4.x (kernel >= 6.x) where containerd writes the AppArmor exec profile via thefsmountLSM hook when applying profiles to container processes (apparmor failed to apply profile: write fsmount:fscontext:proc/thread-self/attr/apparmor/exec: operation not permitted) - Moved Docker GPG key from deprecated
/etc/apt/trusted.gpg.d/to/etc/apt/keyrings/and added task to create the keyrings directory; fixes apt warnings on Ubuntu 22.04+ that treat keys outside/etc/apt/keyrings/as untrusted
1.3.7
[1.3.7] - 2026-03-21
Fixed
- Added AppArmor rule
/proc/thread-self/attr/** rwto k3s security profile; required for containerd to apply AppArmor profiles to container exec processes (apparmor failed to apply profile: write /proc/thread-self/attr/apparmor/exec: operation not permitted)
1.3.6
[1.3.6] - 2026-03-21
Fixed
- Fixed k3s binary upgrade being skipped due to HTTP 304 Not Modified from cached ETag; replaced
force: trueworkaround with proper SHA256 checksum verification fetched from the k3s GitHub release — Ansible now compares the local binary against the expected checksum locally, bypassing HTTP cache entirely