Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions ansible/mke-post-install-playbook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,27 @@
tasks:
- name: Install machine-config-controller
ansible.builtin.include_tasks: tasks/machine-config-controller-tasks.yml

# Runs last, deliberately: cluster-upgrade-controller/machine-config-controller
# (and SUC, above) each apply CRDs/namespaces/Deployments of their own, and
# doing so was observed to trigger MKE re-syncing its baseline kube-system
# manifests — reverting this patch minutes after it was applied and long
# after its own hold-and-reassert window (tasks/calico-kdd-patch-tasks.yml)
# had already declared success. Running this after every other mutating
# step in this playbook means nothing later in the same run can re-trigger
# that reconciliation and undo the fix.
- name: Patch calico-kube-controllers service account for KDD
hosts: localhost
gather_facts: false
vars_files:
- vars/common-vars.yml
- vars/mke-creds.yml
vars:
# mke_url lives in inventory all.vars; pull it from a real host's hostvars
# since localhost is not part of the inventory group.
mke_url: "{{ hostvars[groups['managers'][0]]['mke_url'] }}"
bundle_dest: "{{ playbook_dir }}/mke-bundle"
tasks:
- name: Patch calico-kube-controllers service account
ansible.builtin.include_tasks: tasks/calico-kdd-patch-tasks.yml
when: calico_datastore_type_kdd | bool

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium - KDD repair task is skipped for clusters that enable the datastore through existing install-flag overrides

The new service-account patch runs only when calico_datastore_type_kdd is true, but the code still exposes the generic mke_install_flags override and documents mke-post-install-playbook.yml as a standalone flow. That means a cluster can be installed with --calico-datastore-type-kdd through the existing flag list while this new boolean stays at its default false, causing post-install to skip the fix entirely. In that state calico-kube-controllers keeps running as calico-node and hits the RBAC-forbidden/CrashLoop behavior this PR is meant to prevent, so the repair is unreliable for valid KDD deployments.

Show fix

Drive the patch from the effective install configuration or live cluster state instead of a second manually-synchronized boolean, or at least fail fast when KDD is present in mke_install_flags but calico_datastore_type_kdd is false.

More info - Reply on this comment to give feedback or ignore the issue.

50 changes: 50 additions & 0 deletions ansible/tasks/calico-kdd-patch-tasks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Patches the calico-kube-controllers Deployment in kube-system to run
# under the calico-kube-controllers ServiceAccount instead of calico-node.
#
# Known MKE3 issue: when Calico is installed with the Kubernetes Datastore
# (KDD) backend (--calico-datastore-type-kdd at `mke install` time — see
# calico_datastore_type_kdd in vars/common-vars.yml), MKE brings up the
# calico-kube-controllers Deployment still wired to the calico-node
# ServiceAccount. calico-node's RBAC is scoped for the per-node agent, not
# the cluster-wide controller, so calico-kube-controllers cannot sync from
# the Kubernetes API (CrashLoopBackOff / RBAC "forbidden" errors in its
# logs) until it runs as the calico-kube-controllers ServiceAccount that MKE
# also creates but never wires up.
#
# Installing cluster-upgrade-controller/machine-config-controller/SUC each
# apply their own CRDs/namespaces/Deployments, which was observed to trigger
# MKE to re-sync its baseline kube-system manifests — reverting this patch
# if it ran before them. mke-post-install-playbook.yml therefore runs this
# task last, after every other mutating step, so nothing later in the same
# run can undo it.
#
# Required vars (inherited from the enclosing play):
# admin_user – MKE administrator username (from vars/mke-creds.yml)
# admin_pass – MKE administrator password (from vars/mke-creds.yml)
# mke_url – MKE load-balancer IP/hostname (from inventory all.vars)
# bundle_dest – local directory for the bundle (default: playbook_dir/mke-bundle)
#
# Ref: https://docs.mirantis.com/mke/3.7/cli-ref/mke-cli-install.html

- name: Fetch MKE client bundle
ansible.builtin.include_tasks: tasks/mke-client-bundle-tasks.yml

- name: Patch calico-kube-controllers service account
ansible.builtin.command:
argv:
- kubectl
- patch
- deployment
- calico-kube-controllers
- -n
- kube-system
- --kubeconfig
- "{{ bundle_dest }}/kube.yml"
- --type
- merge
- --patch
- '{"spec":{"template":{"spec":{"serviceAccountName":"calico-kube-controllers"}}}}'
delegate_to: localhost
run_once: true
register: _calico_kdd_patch
changed_when: "'patched' in _calico_kdd_patch.stdout"
6 changes: 6 additions & 0 deletions ansible/tasks/mke-install-tasks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@
when: mke_external_certs_enabled | bool
run_once: true

- name: Append the --calico-datastore-type-kdd MKE flag to the list
ansible.builtin.set_fact:
mke_install_flags: "{{ mke_install_flags + ['--calico-datastore-type-kdd'] }}"
when: calico_datastore_type_kdd | bool
run_once: true

- name: Get target MKE version
ansible.builtin.include_tasks: tasks/helpers/get_target_mke_version.yml

Expand Down
16 changes: 16 additions & 0 deletions ansible/vars/common-vars.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ mke_install_flags:
"--force-minimums",
]

# When true, `mke install` is run with --calico-datastore-type-kdd, switching
# Calico's datastore backend from etcd to the Kubernetes API (KDD).
#
# Known MKE3 issue: with KDD enabled, MKE brings up the
# calico-kube-controllers Deployment (kube-system) still wired to the
# calico-node ServiceAccount instead of the calico-kube-controllers
# ServiceAccount it also creates — calico-node's RBAC is scoped for the node
# agent, not the controller, so the pod cannot sync from the Kubernetes API.
# tasks/calico-kdd-patch-tasks.yml (run from mke-post-install-playbook.yml)
# patches the Deployment's serviceAccountName once the cluster is up. Keep
# this var and that task's `when` in sync if you flip this.
#
# NOTE: MKE team engineers don't recommend to use KDD by default, because
# it is not yet fully hardened from a product perspective
calico_datastore_type_kdd: false

# Use your own TLS certificate for the MKE web server/API instead of the
# self-signed certificate MKE generates. Applied only at install time, via
# `--external-server-cert` (tasks/mke-external-certs-tasks.yml populates the
Expand Down
Loading