Master Kubernetes ServiceAccounts and RBAC: From Basics to Custom Roles
This guide explains the difference between Kubernetes UserAccounts and ServiceAccounts, shows how default and custom ServiceAccounts create associated secrets, demonstrates mounting credentials in pods, adds image pull secrets, and walks through RBAC concepts with Roles, ClusterRoles, and bindings to restrict a user to a specific namespace.
1. ServiceAccount
1.1 ServiceAccount Introduction
Kubernetes distinguishes between User Accounts (used by external users such as operators via kubectl) and Service Accounts (used by processes running inside Pods). User Accounts are global and unique across all namespaces, while Service Accounts are scoped to a namespace and a default one is created automatically.
UserAccount: for external users, global, default admin.
ServiceAccount: for Pods, namespace‑scoped, default SA created per namespace; Pods use the default SA if none is specified.
1.2 Secret and ServiceAccount Relationship
Kubernetes automatically creates a kubernetes.io/service-account-token Secret for each ServiceAccount. Users can also create custom opaque Secrets.
1.3 Default ServiceAccount
When a namespace is created, a default ServiceAccount and its corresponding Secret are generated. The Secret is mounted into Pods at /var/run/secrets/kubernetes.io/serviceaccount.
# kubectl create ns vfan
namespace/vfan created
# kubectl get sa -n vfan
NAME SECRETS AGE
default 1 67s
# kubectl describe sa default -n vfan
Name: default
Namespace: vfan
Mountable secrets: default-token-wwbc8
Tokens: default-token-wwbc8
# kubectl get secret -n vfan
NAME TYPE DATA AGE
default-token-wwbc8 kubernetes.io/service-account-token 3 3m15sCreating a namespace automatically creates a ServiceAccount, which in turn creates a service-account-token Secret.
Creating a Pod using the default ServiceAccount:
apiVersion: v1
kind: Pod
metadata:
name: test-sa
namespace: vfan
spec:
containers:
- name: test-sa
image: nginx:1.2.1
ports:
- containerPort: 80 # kubectl create -f pods.yaml
pod/test-sa created
# kubectl describe pod test-sa -n vfan
...Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-wwbc8 (ro)
...Without specifying a ServiceAccount, a Pod uses the namespace's default ServiceAccount, and its token Secret is automatically mounted.
Inside the Pod you can view the three files:
# cd /var/run/secrets/kubernetes.io/serviceaccount/
# ls
ca.crt namespace tokenThese are the CA certificate, the namespace identifier, and a JWT token signed by the API server.
1.4 Using a Custom ServiceAccount
# kubectl create sa vfansa -n vfan
serviceaccount/vfansa created
# kubectl get sa -n vfan
NAME SECRETS AGE
default 1 19m
vfansa 1 7s
# kubectl describe sa vfansa -n vfan
Name: vfansa
Namespace: vfan
Mountable secrets: vfansa-token-9s8f7
Tokens: vfansa-token-9s8f7Creating a ServiceAccount also creates a corresponding Secret.
Update the Pod definition to use the custom ServiceAccount:
apiVersion: v1
kind: Pod
metadata:
name: test-sa
namespace: vfan
spec:
containers:
- name: test-sa
image: nginx:1.2.1
ports:
- containerPort: 80
serviceAccountName: vfansa # added # kubectl create -f pods.yaml
pod/test-sa created
# kubectl describe pod test-sa -n vfan
...Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from vfansa-token-9s8f7 (ro)
...1.5 Adding Image Pull Secrets to a ServiceAccount
First create a docker-registry Secret that stores private registry credentials:
# kubectl create secret docker-registry myregistrykey \
--docker-server=hub.vfancloud.com \
--docker-username=admin \
--docker-password=admin@123 \
[email protected] -n vfan
secret/myregistrykey createdThen edit the ServiceAccount to reference the secret:
apiVersion: v1
kind: ServiceAccount
metadata:
name: vfansa
namespace: vfan
secrets:
- name: vfansa-token-9s8f7
imagePullSecrets:
- name: myregistrykey # kubectl describe sa vfansa -n vfan
Name: vfansa
Namespace: vfan
Image pull secrets: myregistrykey
Mountable secrets: vfansa-token-9s8f7Pods that use this ServiceAccount can now pull images from the private registry without additional login steps.
2. RBAC
2.1 RBAC Introduction
All Kubernetes resources are accessed via the API server, which authenticates requests (e.g., using ServiceAccount tokens) and authorizes them using Role‑Based Access Control (RBAC).
2.2 Role and ClusterRole
A Role defines permissions within a single namespace, while a ClusterRole defines cluster‑wide permissions.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: test-role
namespace: vfan
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","watch","list"]This Role grants get , watch , and list permissions on Pods in the vfan namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: test-clusterrole
rules:
- apiGroups: [""]
resources: ["services"]
verbs: ["get","create","list"]This ClusterRole grants get , create , and list permissions on Services across the entire cluster.
2.3 RoleBinding and ClusterRoleBinding
RoleBindingassigns a Role (or ClusterRole) to a user, group, or ServiceAccount within a namespace; ClusterRoleBinding does the same cluster‑wide.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: test-rolebinding
namespace: vfan
subjects:
- kind: User
name: vfan
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: test-role
apiGroup: rbac.authorization.k8s.ioThis binds the test-role permissions to the user vfan in the vfan namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: test-rolebinding2
namespace: vfan
subjects:
- kind: User
name: vfan
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: test-clusterrole
apiGroup: rbac.authorization.k8s.ioThis binds a ClusterRole to a user within a single namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: test-clusterrolebinding
subjects:
- kind: Group
name: vfan
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: test-clusterrole
apiGroup: rbac.authorization.k8s.ioThis grants every member of the vfan group the permissions defined in test-clusterrole across the whole cluster.
3. Practical Example: Restrict a User to Manage Only the vfan Namespace
3.1 Create a System User
# useradd vfan
# su - vfan
# kubectl get pod
The connection to the server localhost:8080 was refused - did you specify the right host or port?The user cannot access the cluster until a client certificate is created.
3.2 Generate a Client Certificate for vfan
Download cfssl tools, create a CSR JSON, and generate the certificate:
# wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
# wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
# chmod +x cfssl cfssljson
# mkdir /usr/local/vfancert && cd /usr/local/vfancert
# cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes /usr/local/vfancert/vfan-csr.json | cfssljson -bare vfanuserThis creates vfanuser.pem, vfanuser-key.pem, and vfanuser.csr in /etc/kubernetes/pki.
3.3 Create a kubeconfig for vfan
# export KUBE_APISERVER="https://192.168.152.53:6443"
# kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/pki/ca.crt \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=vfan.kubeconfig
# kubectl config set-credentials vfanuser \
--client-certificate=/etc/kubernetes/pki/vfanuser.pem \
--client-key=/etc/kubernetes/pki/vfanuser-key.pem \
--embed-certs=true \
--kubeconfig=vfan.kubeconfig
# kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=vfan \
--namespace=vfan \
--kubeconfig=vfan.kubeconfigCopy the kubeconfig to /home/vfan/.kube/config and adjust ownership.
3.4 Verify RoleBinding Permissions
# kubectl create -f vfanrolebind.yamlNow as vfan:
$ kubectl get pod
No resources found.
$ kubectl get svc
Error from server (Forbidden): services is forbidden: User "vfan" cannot list resource "services" in API group "" in the namespace "vfan"The user can list Pods but not Services, matching the permissions defined in the Role.
Creating a Deployment as root in the vfan namespace:
# kubectl run deployment test-vfan --replicas=3 --image=nginx:1.2.1 --namespace=vfanWhen logged in as vfan, the Pods are visible, confirming the default namespace is correctly set.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
MaGe Linux Operations
Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
