Fix etcd certificate lifecycle: prevent unnecessary regeneration and ensure restart on cert changes - #13354
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: AdeshDeshmukh The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
Hi @AdeshDeshmukh. Thanks for your PR. I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with Regular contributors should join the org to skip this step. Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
|
/ok-to-test |
6b60dbc to
ba0fb71
Compare
…ensure restart on cert changes
Bug fixes:
- Set force_etcd_cert_refresh default to false (prevents unnecessary cert regeneration on every run)
- Directly notify Restart etcd/e-events from gen_certs_script.yml (old gate-task pattern used dead when: etcd_secret_changed)
- Remove dead gate tasks that relied on non-functional etcd_secret_changed variable
- Add etcd_events_cluster_setup guard to both etcd-events handlers (Restart and Wait for up)
- Fix check_certs.yml patterns from comma-separated string to YAML list
- Guard etcd_cluster_is_healthy usage in backup.yml handlers with default({}) to prevent crash when variable is undefined on new nodes during scale-up
ba0fb71 to
353d8b0
Compare
|
@yankay Could you please review? CI is all green. 🙏 |
| filter: ansible_date_time | ||
| listen: Restart etcd | ||
| when: etcd_cluster_is_healthy.rc == 0 | ||
| when: (etcd_cluster_is_healthy | default(dict(rc=1))).rc == 0 |
There was a problem hiding this comment.
I don't really understand why you wrote it this way. Could you explain?
There was a problem hiding this comment.
@tico88612 .
The handler now fires on non-etcd nodes after the direct-notify change , but etcd_cluster_is_healthy is only defined on etcd members.
The default(dict(rc=1)) just prevents a crash on nodes where the variable doesn't exist... it evaluates to "unhealthy" and safely skips the backup there.
I kept the original condition intact rather than adding a separate group check because the health check already implies it.
|
Related, not conflicting in intent: I opened #13406, which removes the duplicate execution of the etcd cert tasks within a single run (every step of the role exists twice since #9173, and hosts that are in both This PR fixes how often certificates are regenerated across runs and the missing restart afterwards, #13406 fixes how often the tasks execute within one run — so the two are complementary rather than alternatives. They touch four files in common, but a test merge only conflicts in |
|
While testing #13406 on a live Vagrant cluster (3 dedicated etcd, 2 control plane, 1 worker, calico with In - name: "Check_certs | Set 'gen_*_certs' groups to track which nodes needs to have certs generated on first etcd node"
vars:
existing_certs: etcdcert_master.files | map(attribute='path')
ansible.builtin.group_by:
key: "gen_{{ item.node_type }}_certs_{{ force_etcd_cert_refresh or item.certs is not subset(existing_certs) }}"So Reproduced against real cluster state, running the task above verbatim next to a copy that only differs by adding the Same data, same flag — the only difference is the templating, and the master group flips from Since To be precise about what I did not verify: I cannot claim this alone defeats the purpose of flipping the default. In my run the corrected variant still yielded Not something #13406 touches or needs; raising it here because it sits right next to Bug 1. Happy to open a separate issue if you would rather keep this PR focused. |
What type of PR is this?
/kind bug
What this PR does / why we need it
Fixes three compounding bugs in the etcd certificate lifecycle that cause certificates to regenerate on every playbook run and etcd to never restart after regeneration, leading to in-memory/on-disk TLS context drift.
Bug 1 —
force_etcd_cert_refresh: trueforces regeneration every runroles/etcd_defaults/defaults/main.yml:18Changed default to
false. This flag was introduced in PR #7219 as a band-aid that bypassed the cert-existence checking logic. Users can still opt in withforce_etcd_cert_refresh: trueif needed.Bug 2 — Handler timing prevents etcd restart
roles/etcd/tasks/main.yml:81-87The
etcd_secret_changedfact was set by a handler (Set etcd_secret_changed) which fires at end-of-play, but was checked in awhencondition during the play — before the handler fired. Fixed by havinggen_certs_script.ymldirectly notifyRestart etcdandRestart etcd-eventsalongside the existingSet etcd_secret_changednotification, then removing the dead gate tasks.Bug 3 — Wrong handler name for etcd-events
roles/etcd/tasks/main.yml:91Copy-paste bug: "Restart etcd-events if certs changed" notified
Restart etcdinstead ofRestart etcd-events. TheRestart etcd-eventshandler also lacked theetcd_events_cluster_setupguard, which has been added.Additional changes
patternsincheck_certs.yml:5changed from comma-separated string to YAML list (idiomatic correctness)main.yml:81-95removed (16 lines deleted)etcd_events_cluster_setup | default(false)guard toRestart etcd-eventshandlerWhy direct notify instead of flush_handlers?
The
flush_handlersapproach would cause a double restart when both config and certs change. Direct notify avoids this entirely because Ansible automatically deduplicates handler notifications — only one restart fires per play regardless of how many tasks notify.Which issue(s) this PR fixes
Fixes #13353
Special notes for your reviewer
Notification flow after fix:
gen_certs_script.yml tasks that generate or sync certs now directly notify
Restart etcdandRestart etcd-eventsalongside the existingSet etcd_secret_changed. Ansible deduplication ensures exactly one restart per play.Guard moved to handler:
etcd_events_cluster_setupmoved from the deleted gate task to the handler itself — evaluated at the correct time (end-of-play).Cross-role preserved:
etcd_secret_changedinroles/kubernetes/control-plane/tasks/pre-upgrade.yml:9continues to work because that runs in a separate play (handlers fire between plays).Does this PR introduce a user-facing change?
Checklist