How can I create a user and restrict user to access only one namespace in Kubernetes?. Kubernetes gives you a way to regulate access to Kubernetes clusters and resources based on the roles of individual users through a feature called Role-based access control (RBAC). As of Kubernetes release 1.8, RBAC mode is stable and backed by the API.

There are few definitions you need to understand before we proceed:

  • Role: A role contains rules that represent a set of permissions. A role is used to grant access to resources within a namespace.
  • RoleBinding: A role binding is used to grant the permissions defined in a role to a user or set of users. It holds a list of subjects (users, groups, or service accounts), and a reference to the role being granted
  • Service Account: Account meant for for processes, which run in pods.

To achieve a complete isolation in Kubernetes, we’ll use the concepts on namespaces and role based access control. The idea behind service accounts is based on the principle of least privilege. An account is created for specific tasks.

Setup Pre-requisites

  • A running Kubernetes cluster – check below guides:

How To Deploy Lightweight Kubernetes Cluster in 5 minutes with K3s

Deploy Production Ready Kubernetes Cluster with Ansible & Kubespray

How To run Local Kubernetes Cluster in Docker Containers

Deploy Lightweight Kubernetes with MicroK8s and Snap

How to setup 3 node Kubernetes Cluster on Ubuntu with Weave Net CNI

  • Configured kubectl Kubernetes management command line tool

Easily Manage Multiple Kubernetes Clusters with kubectl & kubectx

Create and Limit Service account to a namespace in Kubernetes

Step 1: Create a namespace

Let’s start by creating a namespace that will be used for this demo.

$ kubectl create namespace demo   
namespace/demo created

$ kubectl get namespaces
NAME              STATUS   AGE
default           Active   6d14h
kube-system       Active   6d14h
kube-public       Active   6d14h
kube-node-lease   Active   6d14h
ingress-nginx     Active   4d21h
demo              Active   24s

Step 2: Create a Service Account

We’ll create a service account called demo-user in the demo namespace.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
  name: demo-user
  namespace: demo

You’ll get an output like this:

serviceaccount/demo-user created

Step 3: Create a Role

As explained earlier, a role contains rules that represent a set of permissions that grant access to resources within a namespace.

First confirm API versions for RBAC available in your Kubernetes cluster:

$ kubectl api-versions| grep  rbac

Let’s create a role which will give created account complete access to namespace resources.

cat <<EOF | kubectl apply -f -
kind: Role
  name: admin
  namespace: demo
- apiGroups: ["", "extensions", "apps"]
  resources: ["*"]
  verbs: ["*"]
- apiGroups: ["batch"]
  - jobs
  - cronjobs
  verbs: ["*"]

Confirm creation:

$ kubectl get roles -n demo          
NAME                   AGE
admin   94s

A role can also be created with limited access to resources in a namespace, example:

cat <<EOF | kubectl apply -f -
kind: Role
  namespace: demo
  name: deployment-admin
- apiGroups: ["", "extensions", "apps"]
  resources: ["deployments", "replicasets", "pods", "services", "ingresses"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # You can also use ["*"]

Step 4: Bind the role to a user

Now that we have a user account and role created, we can proceed to bind a role to user.

cat <<EOF | kubectl apply -f -
kind: RoleBinding
  name: admin-view
  namespace: demo
- kind: ServiceAccount
  name: demo-user
  namespace: demo
  kind: Role
  name: admin


$ kubectl get rolebindings --namespace demo
NAME         AGE
admin-view   30s

Check user token name:

$ kubectl describe sa demo-user -n demo
Name:                demo-user
Namespace:           demo
Image pull secrets:  
Mountable secrets:   demo-user-token-k9qbl
Tokens:              demo-user-token-k9qbl

Get service account token to be used to access Kubernetes on dashboard or through kubectl command line.

export NAMESPACE="demo"
export K8S_USER="demo-user"
kubectl -n ${NAMESPACE} describe secret $(kubectl -n ${NAMESPACE} get secret | (grep ${K8S_USER} || echo "$_") | awk '{print $1}') | grep token: | awk '{print $2}'\n

My output is:


Get certificate data

kubectl  -n ${NAMESPACE} get secret `kubectl -n ${NAMESPACE} get secret | (grep ${K8S_USER} || echo "$_") | awk '{print $1}'` -o "jsonpath={.data['ca\.crt']}"

My output:


Step 5: Creating kubectl configuration

If you want to configure kubectl with obtained credentials, it will look something like below.

$ cat .kube/config
apiVersion: v1
- cluster:
    server: https://k3s-master01:6443
  name: mycluster

- context:
    cluster: mycluster
    namespace: demo
    user: demo-user
  name: demo

current-context: demo
kind: Config
preferences: {}

- name: demo-user
    token: eyJhbGciOiJSUzI1NiIsImtpZCI6IkRrUEFveUZGUGZZS0Q3Tzl5eVZpcFE5elFYZEI5SWZ6ZlVhYXFzLU04ZTQifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZW1vIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlbW8tdXNlci10b2tlbi1rOXFibCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJkZW1vLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJjOWRhNGVmOC1jNmQ5LTQ0NTEtYTQ5Ny02ODc1MjY1MzAwMzQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVtbzpkZW1vLXVzZXIifQ.CnrAkziL_Qr8QNQCV_PDkXCi2H-4MoPUGoPVxjSWGZUTXd6V-a9_JKv6t5Vqhrh5vXNTkDSaR1BtLCpKYdXTyqY6CjbyI7gYYcA2M22nkCDjUiwDhxInlios29SAtoOAXq7rwg_cdgdA7XWAWEcWDtT1vRe5LLbXsnORuJ5BtYXynQXWjWjbcC6T9XqRL7iZX4VUk4YCAkX7N89OGzvyycUjjHzOne67qzqOawzjYqeSzHiXIXILwHk4KKhU8tdGG6shYF7niazdp6ZyssdQ24lQext9jzDeUZf3iXPJ_bvZUv4Jo0_eZjldi9WW0dgN5PXe5r-cD1nOJHE8sClBsg

Let’s confirm that it works:

$ kubectl get secrets
NAME                    TYPE                                  DATA   AGE
default-token-25lbj   3      55m
demo-user-token-k9qbl   3      50m

$ kubectl get nodes
Error from server (Forbidden): nodes is forbidden: User "system:serviceaccount:demo:demo-user" cannot list resource "nodes" in API group "" at the cluster scope

We can also create test deployments:

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
  name: busybox-sleep
  - name: busybox
    image: busybox
    - sleep
    - "1000000"
apiVersion: v1
kind: Pod
  name: busybox-sleep-less
  - name: busybox
    image: busybox
    - sleep
    - "1000"

Confirm and clean:

$ kubectl get pods
NAME                 READY   STATUS    RESTARTS   AGE
busybox-sleep-less   1/1     Running   0          65s
busybox-sleep        1/1     Running   0          65s

$ for i in busybox-sleep-less busybox-sleep; do kubectl delete pod $i; done 
pod "busybox-sleep-less" deleted
pod "busybox-sleep" deleted

For multi-cluster configurations, check: Easily Manage Multiple Kubernetes Clusters with kubectl & kubectx


Your support is our everlasting motivation,
that cup of coffee is what keeps us going!

As we continue to grow, we would wish to reach and impact more people who visit and take advantage of the guides we have on our blog. This is a big task for us and we are so far extremely grateful for the kind people who have shown amazing support for our work over the time we have been online.

Thank You for your support as we work to give you the best of guides and articles. Click below to buy us a coffee.


Please enter your comment!
Please enter your name here