Whats difference between "kubectl auth reconcile" and "kubectl apply" for working with RBAC?

3/25/2021

I have some average yaml file defining some average role resource, all yaml should reflect my resource's desired state.

To get new average role into cluster I usually run kubectl apply -f my-new-role.yaml but now I see this (recommended!?) alternative kubectl auth reconcile -f my-new-role.yaml

Ok, there may be RBAC relationships, ie Bindings, but shouldn't an apply do same thing?

Is there ever a case where one would update (cluster) roles but not want their related (cluster) bindings updated?

-- siwasaki
kubernetes
rbac
roles

1 Answer

3/26/2021

The kubectl auth reconcile command-line utility has been added in Kubernetes v1.8.
Properly applying RBAC permissions is a complex task because you need to compute logical covers operations between rule sets.

As you can see in the CHANGELOG-1.8.md:

Added RBAC reconcile commands with kubectl auth reconcile -f FILE. When passed a file which contains RBAC roles, rolebindings, clusterroles, or clusterrolebindings, this command computes covers and adds the missing rules. The logic required to properly apply RBAC permissions is more complicated than a JSON merge because you have to compute logical covers operations between rule sets. This means that we cannot use kubectl apply to update RBAC roles without risking breaking old clients, such as controllers.

The kubectl auth reconcile command will ignore any resources that are not Role, RoleBinding, ClusterRole, and ClusterRoleBinding objects, so you can safely run reconcile on the full set of manifests (see: Use 'kubectl auth reconcile' before 'kubectl apply')


I've created an example to demonstrate how useful the kubectl auth reconcile command is.

I have a simple secret-reader RoleBinding and I want to change a binding's roleRef (I want to change the Role that this binding refers to):
NOTE: A binding to a different role is a fundamentally different binding (see: A binding to a different role is a fundamentally different binding).

# BEFORE
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: secret-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: secret-reader
subjects:
- kind: ServiceAccount
  name: service-account-1
  namespace: default
  
# AFTER
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: secret-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: secret-creator
subjects:
- kind: ServiceAccount
  name: service-account-1
  namespace: default

As we know, roleRef is immutable, so it is not possible to update this secret-admin RoleBinding using kubectl apply:

$ kubectl apply -f secret-admin.yml
The RoleBinding "secret-admin" is invalid: roleRef: Invalid value: rbac.RoleRef{APIGroup:"rbac.authorization.k8s.io", Kind:"Role", Name:"secret-creator"}: cannot change roleRef

Instead, we can use kubectl auth reconcile. If a RoleBinding is updated to a new roleRef, the kubectl auth reconcile command handles a delete/recreate related objects for us.

$ kubectl auth reconcile -f secret-admin.yml
rolebinding.rbac.authorization.k8s.io/secret-admin reconciled
        reconciliation required recreate

Additionally, you can use the --remove-extra-permissions and --remove-extra-subjects options.

Finally, we can check if everything has been successfully updated:

$ kubectl describe rolebinding secret-admin
Name:         secret-admin
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  Role
  Name:  secret-creator
Subjects:
  Kind            Name               Namespace
  ----            ----               ---------
  ServiceAccount  service-account-1  default
-- matt_j
Source: StackOverflow