When the predefined ClusterRoles in Container Service for Kubernetes (ACK) don't cover your permission requirements, create custom Roles or ClusterRoles for fine-grained role-based access control (RBAC) on cluster resources.
Before creating a custom role, check whether the built-in ClusterRoles (cluster-admin, admin, edit, view) already meet your needs. Custom roles are only necessary when built-in roles are too broad or too restrictive.
| Built-in ClusterRole | Access level |
|---|---|
cluster-admin |
Full access to all resources across the cluster |
admin |
Read/write access to most resources within a namespace |
edit |
Read/write access to most objects in a namespace, excluding RBAC resources |
view |
Read-only access to most objects in a namespace |
Prerequisites
Before you begin, ensure that you have:
-
An ACK cluster
-
kubectl configured to connect to the cluster
-
Sufficient permissions to create RBAC resources in the cluster
Key concepts
Kubernetes RBAC uses two role types with different scopes:
-
Role: grants permissions within a specific namespace.
-
ClusterRole: grants permissions at the cluster level, across all namespaces. A namespace cannot be specified in a ClusterRole YAML manifest.
Both role types use the same three-field rule structure: apiGroups, resources, and verbs.
Permission verbs
| Category | Verbs | Description |
|---|---|---|
| Read | get |
Retrieve details of a specific resource |
| Read | list |
List a collection of resources |
| Read | watch |
Stream real-time updates for resource changes |
| Write | create |
Create a new resource instance |
| Write | update |
Replace an existing resource |
| Write | patch |
Partially modify an existing resource |
| Write | delete |
Remove a resource |
Avoid using wildcards (["*"]) in resources or verbs. Wildcards grant access to all current and future resources or verbs, including any new ones added later. Always list specific resources and verbs to follow the principle of least privilege.
Supported resources
Use the following table to build your rules field. Each row maps a resource type to its resources value, apiGroups value, and the verbs it supports.
| Resource | resources |
apiGroups |
Supported verbs |
|---|---|---|---|
| Pod | ["pods"] |
[""] |
get, list, watch, update, create, patch, delete, exec, proxy |
| Service | ["services"] |
[""] |
get, list, watch, update, create, patch, delete |
| ConfigMap | ["configmaps"] |
[""] |
get, list, watch, update, create, patch, delete |
| Secret | ["secrets"] |
[""] |
get, list, watch, update, create, patch, delete |
| PersistentVolume | ["persistentvolumes"] |
[""] |
get, list, watch, update, create, patch, delete |
| PersistentVolumeClaim | ["persistentvolumeclaims"] |
[""] |
get, list, watch, update, create, patch, delete |
| Namespace | ["namespaces"] |
[""] |
get, list, watch, update, create, patch, delete |
| Deployment | ["deployments"] |
["apps"] |
get, list, watch, update, create, patch, delete |
| DaemonSet | ["daemonsets"] |
["apps"] |
get, list, watch, update, create, patch, delete |
| StatefulSet | ["statefulsets"] |
["apps"] |
get, list, watch, update, create, patch, delete |
| Ingress | ["ingresses"] |
["networking.k8s.io"] |
get, list, watch, update, create, patch, delete |
| NetworkPolicy | ["networkpolicies"] |
["networking.k8s.io"] |
get, list, watch, update, create, patch, delete |
| Job | ["jobs"] |
["batch"] |
get, list, watch, update, create, patch, delete |
| CronJob | ["cronjobs"] |
["batch"] |
get, list, watch, update, create, patch, delete |
| StorageClass | ["storageclasses"] |
["storage.k8s.io"] |
get, list, watch, update, create, patch, delete |
| HorizontalPodAutoscaler | ["horizontalpodautoscalers"] |
["autoscaling"] |
get, list, watch, update, create, patch, delete |
Subresources
Some resources expose subresources that require separate grants. Use a slash (/) to specify a subresource. For example, to allow reading pod logs in addition to pods:
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list"]
Common pod subresources: pods/log, pods/exec, pods/portforward, pods/proxy.
Create and bind a custom RBAC role
The ACK console supports binding custom ClusterRoles only. To bind a custom Role scoped to a specific namespace, use kubectl.
-
ACK console: create a ClusterRole and bind it to a RAM user or RAM role
-
kubectl: create a ClusterRole or Role, then create the corresponding binding
Console
Step 1: Create a ClusterRole
The following steps create a ClusterRole named my-clusterrole that grants read-only access to pods and Services across the cluster.
-
Log on to the ACK console. In the left-side navigation pane, click Clusters.
-
On the Clusters page, click the name of the target cluster. In the left-side pane, choose Security > Role.
-
On the Role page, select the Cluster Role tab, then click OK.
-
In the Create YAML panel, enter the ClusterRole manifest and click OK. The following manifest grants read-only access (
get,list,watch) to pods and Services:apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: my-clusterrole rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["services"] verbs: ["get", "list", "watch"]After creation,
my-clusterroleappears under the Cluster Role tab.
Step 2: Bind the ClusterRole to a RAM user or RAM role
-
In the left-side navigation pane, click Authorizations.
-
On the Authorizations page, select the authorization target:
-
RAM user: click the RAM Users tab, find the target RAM user, and click Modify Permissions.
-
RAM role: click the RAM Roles tab, enter or select the RAM role name in the RAM Role Name field, and click Modify Permissions.
-
-
In the Permission Management panel, click + Add Permissions. In the Add Permissions section:
-
Select the Clusters associated with
my-clusterrole. -
Select the target Namespace.
-
Under Permission Management, select Custom, then select my-clusterrole from the drop-down list.
-
Click Submit.
-
kubectl
Step 1: Create a custom role
ClusterRole — grants permissions across the entire cluster.
The following manifest creates a ClusterRole named my-clusterrole with read-only access to pods and Services:
# my-clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: my-clusterrole
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list", "watch"]
Role — grants permissions within a specific namespace.
The following manifest creates a Role named my-role with read access to pods in the default namespace:
# my-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: my-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
Apply the manifest:
kubectl apply -f my-clusterrole.yaml
Step 2: Get the authorization object ID
To bind the role to a RAM user or RAM role, you need the corresponding ID:
Step 3: Create the binding
The following manifest binds my-clusterrole to a RAM user or RAM role. Replace 20811XXXXXXXXX2288 with the UserId or RoleId from the previous step.
# my-clusterrole-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: my-clusterrole-binding
subjects:
- kind: User
name: "20811XXXXXXXXX2288" # UserId or RoleId from Step 2
roleRef:
kind: ClusterRole
name: my-clusterrole
apiGroup: rbac.authorization.k8s.io
Apply the binding:
kubectl apply -f my-clusterrole-binding.yaml
Verify the permissions
After binding, verify that the RAM user has the expected access. Retrieve the kubeconfig of the cluster and connect using kubectl, then run a command that the role permits:
kubectl get pods
To confirm that access outside the granted permissions is correctly denied, run a command not covered by the role — for example, listing Deployments when only pod access was granted:
kubectl get deployments
The expected output is:
Error from server (Forbidden): deployments.apps is forbidden: User "20811XXXXXXXXX2288" cannot list resource "deployments" in API group "apps" at the cluster scope
This error confirms the permission boundary is working correctly.