This guide covers Role-Based Access Control (RBAC) for the Antfly Operator.
Overview
The Antfly Operator requires specific Kubernetes RBAC permissions to manage cluster resources. The installation includes all necessary RBAC configuration.
Operator RBAC
Service Account
The operator uses the ServiceAccount antfly-operator-service-account in the antfly-operator-namespace:
apiVersion: v1
kind: ServiceAccount
metadata:
name: antfly-operator-service-account
namespace: antfly-operator-namespaceThe exact name antfly-operator-service-account is required. Mismatches cause permission errors.
ClusterRole
The operator's ClusterRole (antfly-operator-cluster-role) grants permissions for:
| Resource | Permissions |
|---|---|
| StatefulSets | create, delete, get, list, patch, update, watch |
| Services | create, delete, get, list, patch, update, watch |
| ConfigMaps | create, delete, get, list, patch, update, watch |
| PersistentVolumeClaims | create, delete, get, list, patch, update, watch |
| Pods | get, list, watch |
| Secrets | get, list, watch |
| Events | create, patch |
| PodDisruptionBudgets | create, delete, get, list, patch, update, watch |
| AntflyClusters | get, list, watch, create, update, patch, delete |
| AntflyBackups | get, list, watch, create, update, patch, delete |
| AntflyRestores | get, list, watch, create, update, patch, delete |
| Metrics API | get, list |
Full ClusterRole definition:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: antfly-operator-cluster-role
rules:
# Core resources for cluster management
- apiGroups: ["apps"]
resources: ["statefulsets"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
- apiGroups: [""]
resources: ["services", "configmaps", "persistentvolumeclaims"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "patch"]
# Pod Disruption Budgets
- apiGroups: ["policy"]
resources: ["poddisruptionbudgets"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
# Antfly CRDs
- apiGroups: ["antfly.io"]
resources: ["antflyclusters", "antflybackups", "antflyrestores"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
- apiGroups: ["antfly.io"]
resources: ["antflyclusters/status", "antflybackups/status", "antflyrestores/status"]
verbs: ["get", "patch", "update"]
- apiGroups: ["antfly.io"]
resources: ["antflyclusters/finalizers", "antflybackups/finalizers", "antflyrestores/finalizers"]
verbs: ["update"]
# Metrics for autoscaling
- apiGroups: ["metrics.k8s.io"]
resources: ["pods"]
verbs: ["get", "list"]ClusterRoleBinding
The ClusterRoleBinding connects the ClusterRole to the ServiceAccount:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: antfly-operator-cluster-role-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: antfly-operator-cluster-role
subjects:
- kind: ServiceAccount
name: antfly-operator-service-account
namespace: antfly-operator-namespaceVerifying RBAC Configuration
Check ServiceAccount
# Verify ServiceAccount exists
kubectl get serviceaccount -n antfly-operator-namespace antfly-operator-service-account
# Check ServiceAccount details
kubectl describe serviceaccount -n antfly-operator-namespace antfly-operator-service-accountCheck Deployment ServiceAccount
# Verify deployment uses correct ServiceAccount
kubectl get deployment antfly-operator -n antfly-operator-namespace \
-o jsonpath='{.spec.template.spec.serviceAccountName}'Check ClusterRole
# Verify ClusterRole exists
kubectl get clusterrole antfly-operator-cluster-role
# View ClusterRole permissions
kubectl describe clusterrole antfly-operator-cluster-role
# Check for PDB permissions specifically
kubectl get clusterrole antfly-operator-cluster-role -o yaml | grep -A5 poddisruptionbudgetsCheck ClusterRoleBinding
# Verify ClusterRoleBinding exists
kubectl get clusterrolebinding antfly-operator-cluster-role-binding
# View binding details
kubectl describe clusterrolebinding antfly-operator-cluster-role-bindingTest Permissions
# Test if operator can create StatefulSets
kubectl auth can-i create statefulsets \
--as=system:serviceaccount:antfly-operator-namespace:antfly-operator-service-account
# Test if operator can list PodDisruptionBudgets
kubectl auth can-i list poddisruptionbudgets \
--as=system:serviceaccount:antfly-operator-namespace:antfly-operator-service-account
# Test if operator can watch AntflyClusters
kubectl auth can-i watch antflyclusters.antfly.io \
--as=system:serviceaccount:antfly-operator-namespace:antfly-operator-service-accountNamespace-Scoped RBAC
By default, the operator watches all namespaces. To restrict to specific namespaces:
1. Use Role Instead of ClusterRole
Create a Role in each target namespace:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: antfly-operator-role
namespace: production
rules:
# Same rules as ClusterRole, but namespaced
- apiGroups: ["apps"]
resources: ["statefulsets"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
# ... (remaining rules)2. Create RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: antfly-operator-rolebinding
namespace: production
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: antfly-operator-role
subjects:
- kind: ServiceAccount
name: antfly-operator-service-account
namespace: antfly-operator-namespace3. Configure Operator Watch Namespace
Set the WATCH_NAMESPACE environment variable:
apiVersion: apps/v1
kind: Deployment
metadata:
name: antfly-operator
namespace: antfly-operator-namespace
spec:
template:
spec:
containers:
- name: manager
env:
- name: WATCH_NAMESPACE
value: "production,staging" # Comma-separated namespacesUser RBAC
Cluster Administrator Role
Grant users permission to manage Antfly clusters:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: antfly-admin
rules:
- apiGroups: ["antfly.io"]
resources: ["antflyclusters", "antflybackups", "antflyrestores"]
verbs: ["*"]
- apiGroups: ["antfly.io"]
resources: ["antflyclusters/status", "antflybackups/status", "antflyrestores/status"]
verbs: ["get"]Read-Only Role
Grant users read-only access to Antfly resources:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: antfly-viewer
rules:
- apiGroups: ["antfly.io"]
resources: ["antflyclusters", "antflybackups", "antflyrestores"]
verbs: ["get", "list", "watch"]
- apiGroups: ["antfly.io"]
resources: ["antflyclusters/status", "antflybackups/status", "antflyrestores/status"]
verbs: ["get"]Backup Operator Role
Grant users permission to manage backups only:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: antfly-backup-operator
rules:
- apiGroups: ["antfly.io"]
resources: ["antflybackups", "antflyrestores"]
verbs: ["*"]
- apiGroups: ["antfly.io"]
resources: ["antflyclusters"]
verbs: ["get", "list", "watch"]Bind to User
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: user-antfly-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: antfly-admin
subjects:
- kind: User
name: alice@example.com
apiGroup: rbac.authorization.k8s.ioPod ServiceAccount
Custom ServiceAccount for Pods
Configure a custom ServiceAccount for Antfly pods (used for Workload Identity):
apiVersion: v1
kind: ServiceAccount
metadata:
name: antfly-workload-sa
namespace: production
annotations:
# For GKE Workload Identity
iam.gke.io/gcp-service-account: antfly@myproject.iam.gserviceaccount.com
# OR for AWS IRSA
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/antfly-role
---
apiVersion: antfly.io/v1
kind: AntflyCluster
metadata:
name: my-cluster
namespace: production
spec:
serviceAccountName: antfly-workload-sa
# ... rest of specTroubleshooting
Permission Denied Errors
If you see errors like:
poddisruptionbudgets.policy is forbidden: User "system:serviceaccount:antfly-operator-namespace:WRONG-NAME" cannot list resource "poddisruptionbudgets"-
Check ServiceAccount name matches:
kubectl get deployment antfly-operator -n antfly-operator-namespace \ -o jsonpath='{.spec.template.spec.serviceAccountName}' -
Verify ClusterRoleBinding:
kubectl get clusterrolebinding antfly-operator-cluster-role-binding -o yaml -
Ensure ServiceAccount exists:
kubectl get sa -n antfly-operator-namespace
Missing Permissions
If the operator can't perform certain actions:
-
Check the ClusterRole has the permission:
kubectl get clusterrole antfly-operator-cluster-role -o yaml | grep -A 10 "apiGroups" -
Test the permission:
kubectl auth can-i <verb> <resource> \ --as=system:serviceaccount:antfly-operator-namespace:antfly-operator-service-account -
Update ClusterRole if needed:
kubectl edit clusterrole antfly-operator-cluster-role
Infrastructure-as-Code Issues
When using Pulumi, Terraform, or Helm:
-
Verify resource names match exactly:
- ServiceAccount:
antfly-operator-service-account - ClusterRole:
antfly-operator-cluster-role - ClusterRoleBinding:
antfly-operator-cluster-role-binding
- ServiceAccount:
-
Check for naming conventions that append suffixes:
- Helm may add release names
- Pulumi/Terraform may add random suffixes
-
Use the exact names from the install manifest:
curl -s https://antfly.io/antfly-operator-install.yaml | grep "name:" | head -20
Best Practices
- Use Least Privilege: Grant only necessary permissions
- Namespace Isolation: Consider namespace-scoped RBAC for multi-tenant clusters
- Audit RBAC: Regularly review permissions granted
- Separate Roles: Create different roles for admins, operators, and viewers
- Document Custom Roles: Keep track of custom RBAC configurations
- Test Permissions: Verify permissions with
kubectl auth can-i
See Also
- Installation: Initial RBAC setup
- Secrets Management: Managing secrets access
- Troubleshooting: Common RBAC issues