Introduction
Backing up and restoring Kubernetes ClusterRoles is a critical operational task for maintaining the security and functionality of your cluster. ClusterRoles define permissions at the cluster level, and losing them due to accidental deletion, misconfiguration, or a failed upgrade can disrupt workloads and compromise security. This guide provides a practical, step-by-step approach to backing up, restoring, and validating ClusterRoles using native Kubernetes tools and commands. Whether you are a developer, DevOps engineer, or technical startup team, you will learn how to implement a reliable backup strategy, perform restores, and avoid common pitfalls.
The goal of this article is operational safety: observe before changing, limit the blast radius, use placeholders instead of secrets, verify results, and document recovery paths. We will cover version and environment inventory, safe configuration paths, verification and diagnostics, failure modes and recovery, and an operations checklist. All examples are tested with Kubernetes v1.25+ and use kubectl commands that work in most environments.
Version and Environment Inventory
Before you back up or restore ClusterRoles, you need to understand your cluster version, the ClusterRole API version in use, and the current state of your RBAC configuration. Kubernetes ClusterRoles have been stable since v1.8, but newer versions may add fields or change behavior. Check your cluster version:
kubectl version --short
Output example:
Client Version: v1.26.0
Kustomize Version: v4.5.7
Server Version: v1.26.0
The API version for ClusterRole is rbac.authorization.k8s.io/v1 in modern clusters. Verify by checking the resource definition:
kubectl explain clusterrole
You should see API Version: rbac.authorization.k8s.io/v1. If you are using an older cluster, the version might be v1beta1, which is deprecated and should be migrated.
Next, inventory existing ClusterRoles and their bindings. This provides a baseline for backup and helps identify dependencies:
kubectl get clusterroles --sort-by=.metadata.creationTimestamp
Example output (truncated):
NAME CREATED AT
admin 2023-01-01T00:00:00Z
cluster-admin 2023-01-01T00:00:00Z
edit 2023-01-01T00:00:00Z
view 2023-01-01T00:00:00Z
custom-role 2023-06-15T14:30:00Z
To see bindings that reference these roles:
kubectl get clusterrolebindings -o wide
If you are using namespaced Roles and RoleBindings, also list them:
kubectl get roles --all-namespaces
kubectl get rolebindings --all-namespaces
This inventory is read-only and safe. It helps you understand what needs to be backed up and whether there are any unusual custom roles.
Prerequisites for backup and restore:
kubectlconfigured with cluster-admin privileges (or at least permissions to read and write ClusterRoles and ClusterRoleBindings).yqorjqfor transforming YAML if needed (optional but recommended).- A secure location to store backup files (git repository, S3 bucket, etc.).
Verify your permissions:
kubectl auth can-i get clusterroles
kubectl auth can-i create clusterroles
kubectl auth can-i delete clusterroles
Each should return yes. If not, you need to adjust your RBAC or ask an administrator.
Safe Configuration Path
Backing up ClusterRoles should be non-destructive and repeatable. The recommended method is to export the YAML definitions to files, optionally strip metadata (like resourceVersion and uid), and store them in version control.
Step 1: Export all ClusterRoles
Use the following command to dump all ClusterRoles to a single YAML file:
kubectl get clusterroles -o yaml > clusterroles-backup-$(date +%Y%m%d-%H%M%S).yaml
This file contains a List object with all ClusterRole definitions. However, it includes cluster-specific metadata like creationTimestamp, resourceVersion, uid, and selfLink, which are not needed for restore and can cause conflicts if applied to a new cluster.
To create a cleaner backup, use a combination of kubectl and yq (or jq) to remove unnecessary fields. For example, using yq:
kubectl get clusterroles -o json | yq eval 'del(.items[].metadata.creationTimestamp, .items[].metadata.resourceVersion, .items[].metadata.uid, .items[].metadata.selfLink, .items[].metadata.generation)' - > clusterroles-clean.yaml
If you prefer to back up each ClusterRole individually (useful for version control and selective restore), use a loop:
for role in $(kubectl get clusterroles -o name); do
role_name=$(echo $role | cut -d'/' -f2)
kubectl get $role -o yaml | kubectl neat > clusterrole-$role_name.yaml
done
kubectl neat is a plugin that removes clutter from Kubernetes manifests. You can install it via kubectl krew install neat. If you don't have it, you can manually edit.
Store these files in a git repository. Commit with a meaningful message, e.g., "Backup ClusterRoles as of 2024-06-01".
Step 2: Backup ClusterRoleBindings
ClusterRoles alone do not grant permissions; they must be bound to subjects. Therefore, backing up ClusterRoleBindings is equally important:
kubectl get clusterrolebindings -o yaml > clusterrolebindings-backup-$(date +%Y%m%d-%H%M%S).yaml
Similarly, you can clean and split into individual files.
Step 3: Test Restore in a Non-Production Environment
Before relying on backups, test a restore in a separate namespace or a disposable cluster (e.g., kind, minikube). For a single ClusterRole, you can apply it to a test cluster:
kubectl apply -f clusterrole-custom-role.yaml
Verify it is created correctly:
kubectl get clusterrole custom-role -o yaml
Compare with the original. Ensure that rules and aggregation rules are preserved.
Step 4: Automate Backups
For recurring backups, set up a CronJob inside the cluster or use an external scheduler. Here is an example CronJob that runs daily and stores backups in a PersistentVolume (simplified for illustration):
apiVersion: batch/v1
kind: CronJob
metadata:
name: clusterrole-backup
namespace: kube-system
spec:
schedule: "0 2 * * *"
jobTemplate:
spec:
template:
spec:
serviceAccountName: backup-sa
containers:
- name: backup
image: bitnami/kubectl:latest
command:
- /bin/sh
- -c
- |
kubectl get clusterroles -o yaml > /backup/clusterroles-$(date +\%Y\%m\%d).yaml
kubectl get clusterrolebindings -o yaml > /backup/clusterrolebindings-$(date +\%Y\%m\%d).yaml
volumeMounts:
- name: backup-storage
mountPath: /backup
restartPolicy: OnFailure
volumes:
- name: backup-storage
persistentVolumeClaim:
claimName: backup-pvc
Ensure the service account backup-sa has appropriate RBAC permissions: get and list clusterroles and clusterrolebindings. Also, the PVC must have sufficient capacity.
Verification and Diagnostics
After creating a backup, you should verify its integrity and completeness. Here are concrete steps:
Check Backup File Content
Validate that the YAML is syntactically correct and contains the expected resources.
kubectl apply --dry-run=client -f clusterroles-backup.yaml
If there are syntax errors, kubectl will report them. Also, count the number of ClusterRoles in the backup vs. live cluster:
grep -c '^ name:' clusterroles-backup.yaml # Adjust if your format differs
kubectl get clusterroles --no-headers | wc -l
They should match.
Simulate a Restore in Dry Run
For individual ClusterRole files, use kubectl apply --dry-run=server to validate against the API server without actually creating or updating resources.
kubectl apply --dry-run=server -f clusterrole-custom-role.yaml
The output should indicate clusterrole.rbac.authorization.k8s.io/custom-role created (server dry run) or configured.
Validate Permissions Post-Restore
After restoring a ClusterRole, test that the permissions work as expected. Create a test ServiceAccount, bind the ClusterRole to it, and use kubectl auth can-i to check specific actions.
Example: Suppose we restored a ClusterRole named pod-reader that allows reading pods in all namespaces. Create a test ServiceAccount in default namespace:
kubectl create serviceaccount test-sa
kubectl create clusterrolebinding test-sa-pod-reader --clusterrole=pod-reader --serviceaccount=default:test-sa
Then, impersonate the ServiceAccount to check permissions:
kubectl auth can-i list pods --as=system:serviceaccount:default:test-sa
If it returns yes, the ClusterRole is functioning. For cluster-wide permissions, also test:
kubectl auth can-i list nodes --as=system:serviceaccount:default:test-sa
Clean up after test:
kubectl delete clusterrolebinding test-sa-pod-reader
kubectl delete serviceaccount test-sa
Monitor for Unexpected Behavior
After a restore, monitor audit logs and application logs for authorization errors. If you have auditing enabled, check for Forbidden or Unauthorized responses related to the restored roles.
Failure Modes and Recovery
Despite careful planning, restore operations can fail. Here are common failure modes and how to recover.
1. Restore Fails Due to Existing Resource
If you attempt to kubectl apply a ClusterRole that already exists with different content, it may update it. However, if the existing resource is managed by another controller or has immutable fields, the apply might fail.
Scenario: You try to apply a backup of a ClusterRole that was deleted, but a new one with the same name was created manually.
Diagnosis: kubectl apply returns an error like Error from server (Conflict): Operation cannot be fulfilled on clusterroles.rbac.authorization.k8s.io "custom-role": the object has been modified; please apply your changes to the latest version and try again.
Recovery: Compare the existing ClusterRole with the backup. Decide which one is authoritative. If you want to restore the backup, you can first delete the existing one (if safe) and then apply the backup:
kubectl delete clusterrole custom-role
kubectl apply -f clusterrole-custom-role.yaml
Alternatively, use kubectl replace with --force after backing up the current state.
2. Missing ClusterRoleBindings After Restore
If you restore ClusterRoles but forget ClusterRoleBindings, users and service accounts lose their permissions. Symptoms include 403 Forbidden errors in applications.
Diagnosis: Check if bindings are missing:
kubectl get clusterrolebindings -l backup=missing # if you label them
Or inspect which subjects are bound to a specific ClusterRole:
kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name=="custom-role") | .subjects'
Recovery: Restore the ClusterRoleBindings from backup using kubectl apply -f clusterrolebindings-backup.yaml. Ensure that the subjects (users, groups, service accounts) exist; if not, you may need to recreate them.
3. Aggregated ClusterRoles Not Working
Some ClusterRoles use aggregation rules (e.g., system:aggregate-to-admin) to combine permissions from multiple roles. If labels are missing on the source roles, aggregation may not work.
Example: The built-in admin ClusterRole has an aggregation rule that collects all ClusterRoles with label rbac.authorization.k8s.io/aggregate-to-admin: "true". If you restore a custom role that has that label but the label is missing in the backup, the admin role loses those permissions.
Diagnosis: Inspect the ClusterRole's aggregationRule and verify that matching roles exist and have the correct labels:
kubectl get clusterrole admin -o yaml | grep -A 10 aggregationRule
kubectl get clusterroles -l rbac.authorization.k8s.io/aggregate-to-admin=true
Recovery: Add the missing labels to the relevant ClusterRoles:
kubectl label clusterrole my-custom-role rbac.authorization.k8s.io/aggregate-to-admin=true
Then verify that the admin role now includes the permissions by checking its rules field.
4. Backup File Corrupted or Incomplete
If your backup file is truncated or contains invalid YAML, restore will fail.
Prevention: Always verify backup file size and content. Store backups in reliable storage with checksums. For critical roles, consider storing individual YAML files.
Recovery: If individual files are missing, you may need to reconstruct the ClusterRole from documentation or from a live replica if available. In worst case, you can use the Kubernetes audit log to see the original definition (if audit logging is configured to log RBAC changes).
Operations Checklist
Use this checklist to ensure you have a robust ClusterRole backup and restore process.
- [ ] Inventory current ClusterRoles and bindings: Run
kubectl get clusterroles,clusterrolebindingsand save output. - [ ] Identify custom ClusterRoles: Note any non-default roles that are critical for your applications.
- [ ] Create a backup plan: Decide frequency (daily, weekly), storage location, and retention policy.
- [ ] Export all ClusterRoles and ClusterRoleBindings to YAML files: Use
kubectl get -o yamland clean metadata. - [ ] Store backups in version control and/or object storage: Ensure access controls and encryption.
- [ ] Test restore in a staging environment: Apply backups to a test cluster and verify functionality.
- [ ] Document the restore procedure: Include exact commands, order of operations, and validation steps.
- [ ] Set up monitoring and alerting for RBAC changes: Watch for unexpected deletions or modifications using tools like Kubernetes audit logs or external monitoring.
- [ ] Regularly review and update backup procedures: Especially after upgrading Kubernetes or changing RBAC policies.
- [ ] Train team members on restore drills: Conduct regular fire drills to ensure everyone knows how to recover.
Sample Backup and Restore Runbook
Here is a concise runbook for a quick restore of a single ClusterRole:
- Locate the backup file for the ClusterRole, e.g.,
clusterrole-my-role.yaml. - Verify the file content:
cat clusterrole-my-role.yaml
- Check if the ClusterRole currently exists:
kubectl get clusterrole my-role
- If it does not exist, proceed to apply.
- If it exists, compare with backup:
kubectl get clusterrole my-role -o yaml > current-my-role.yamland diff.
- Apply the backup (if safe):
kubectl apply -f clusterrole-my-role.yaml
- Verify the restored ClusterRole:
kubectl get clusterrole my-role -o yaml
- Test permissions with
kubectl auth can-iusing a test ServiceAccount or user. - If the restore fails, check error messages and consult failure modes section.
- Document the incident and update the backup if necessary.
Conclusion
Backing up and restoring Kubernetes ClusterRoles is essential for disaster recovery and operational continuity. By following the practices outlined in this guide, you can ensure that your RBAC configuration is always recoverable. Start with a thorough inventory, implement automated backups, test restores regularly, and document everything. Remember to verify after every operation and keep your team trained. With these steps, you can minimize the risk of losing critical access controls and maintain a secure, functioning cluster.
As a next step, choose one low-risk verification: export a single custom ClusterRole, inspect it, delete it in a test environment, and restore it from the backup. This hands-on exercise will build confidence in your backup and restore procedures.