Kubernetes RBAC and Namespaces for Access Control


Introduction

In Kubernetes, everything looks easy — until multiple teams start using the same cluster.

Without proper access control:

  • Developers can delete production workloads
  • Apps can access secrets they shouldn’t
  • One mistake can impact the entire cluster

That’s where Namespaces + RBAC come in.

👉 Namespace = Isolation
👉 RBAC = Control who can do what

In this blog, we’ll build a real working example step-by-step.


What We Are Building

We will:

✅ Create a namespace
✅ Create a service account (user)
✅ Create a Role (permissions)
✅ Bind it using RoleBinding
✅ Verify access


Step 1: Create a Namespace

Namespaces isolate resources in Kubernetes.

kubectl create namespace dev-team

Verify:

kubectl get ns

Step 2: Create a Service Account

In real setups, pods or applications use ServiceAccounts.

kubectl create serviceaccount dev-user -n dev-team

👉 ServiceAccounts act as identities inside Kubernetes
👉 They are used in RBAC as “subjects”


Step 3: Create a Role (Permissions)

A Role defines what actions are allowed in a namespace
Roles are always namespace-scoped


✅ Example: Allow user to read pods

Create file: role-pod-reader.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: dev-team
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]

Apply it:

kubectl apply -f role-pod-reader.yaml

🧠 What this means

  • apiGroups: “” → core resources (pods, services)
  • resources: pods → target resource
  • verbs: get, list, watch → read-only

👉 If not explicitly allowed → access is denied (default deny model)


Step 4: Create a RoleBinding

Role alone does nothing.

👉 You must attach it to a user/service account using RoleBinding


Create file: rolebinding.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: dev-user-binding
  namespace: dev-team
subjects:
- kind: ServiceAccount
  name: dev-user
  namespace: dev-team
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Apply:

kubectl apply -f rolebinding.yaml

🧠 What this does

  • Links dev-user → pod-reader Role
  • Only inside dev-team namespace

👉 RoleBinding grants permissions within a namespace only.


Step 5: Verify RBAC Permissions

Now comes the most important part ✅


Check what user can do

kubectl auth can-i get pods \
--as system:serviceaccount:dev-team:dev-user \
-n dev-team

👉 Expected output:

yes

Try restricted action

kubectl auth can-i delete pods \
--as system:serviceaccount:dev-team:dev-user \
-n dev-team

👉 Expected output:

no

👉 This proves:

  • User can read pods ✅
  • User cannot delete pods ❌

Step 6: Validate with Real Resource

Create a test pod:

kubectl run test-pod --image=nginx -n dev-team

Now test from the user perspective:

kubectl get pods \
--as system:serviceaccount:dev-team:dev-user \
-n dev-team

👉 Works ✅


Try delete:

kubectl delete pod test-pod \
--as system:serviceaccount:dev-team:dev-user \
-n dev-team

👉 Fails ❌ (expected)


✅ Step 1: Create a User Certificate

We simulate a user: dev-user


Generate private key

openssl genrsa -out dev-user.key 2048

Generate CSR (Certificate Signing Request)

openssl req -new -key dev-user.key -out dev-user.csr -subj "/CN=dev-user/O=dev-team"

👉 CN = username
👉 O = group


✅ Step 2: Create CSR in Kubernetes

Create file: csr.yaml

apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: dev-user-csr
spec:
  request: <base64-encoded-csr>
  signerName: kubernetes.io/kube-apiserver-client
  usages:
  - client auth

Encode CSR

cat dev-user.csr | base64 | tr -d '\n'

👉 Paste output into request: field


Apply:

kubectl apply -f csr.yaml

✅ Step 3: Approve the Certificate

kubectl certificate approve dev-user-csr

Get certificate:

kubectl get csr dev-user-csr -o jsonpath='{.status.certificate}' | base64 -d > dev-user.crt

✅ Step 4: Create kubeconfig for User

kubectl config set-credentials dev-user \
  --client-certificate=dev-user.crt \
  --client-key=dev-user.key

kubectl config set-context dev-user-context \
  --cluster=<cluster-name> \
  --namespace=dev-team \
  --user=dev-user

Switch user:

kubectl config use-context dev-user-context

👉 Now user exists BUT has no permissions yet ❌


✅ Step 5: Create Role (Same as before)

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: dev-team
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]

Apply:

kubectl apply -f role.yaml

✅ Step 6: Bind Role to User (IMPORTANT DIFFERENCE)

Now instead of ServiceAccount → we bind to User


Create file: rolebinding-user.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: user-access
  namespace: dev-team
subjects:
- kind: User
  name: dev-user
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Apply:

kubectl apply -f rolebinding-user.yaml

✅ Step 7: Test Access

Now as dev-user:

kubectl get pods -n dev-team

👉 ✅ Should work


Try something restricted:

kubectl delete pods --all -n dev-team

👉 ❌ Should fail


✅ Important Difference (ServiceAccount vs Certificate User)

TypeUsed for
ServiceAccountApps/pods
Certificate UserReal users (developers/admins)

✅ Key Concepts You Just Learned

ConceptMeaning
NamespaceLogical isolation
RoleDefines permissions
RoleBindingAssigns permissions
ServiceAccountIdentity
RBACAuthorization layer

⚠️ Common Mistakes (Very Important)

❌ Using cluster-admin everywhere

Gives full permissions → dangerous

❌ Not using namespaces

Everything becomes shared → no control

❌ Giving too many verbs

Always follow:

👉 Least privilege principle
Only give minimum required permissions


🚀 Real-World Use Case

Imagine:

  • Dev team → access only dev namespace
  • QA team → access staging
  • CI/CD → update deployments only

RBAC ensures:

👉 No cross-access
👉 No accidental deletion
👉 Secure multi-team setup


🚀 InfraDecode Takeaway

Namespaces isolate — RBAC protects.
Every request in Kubernetes is checked by RBAC.

If you don’t define access → everything is denied.
If you overdefine access → everything is at risk.

Balance is the key.


Discover more from

Subscribe to get the latest posts sent to your email.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top