Previously, an Kubernetes cluster environment was set up using Ansible. The current requirement is to add a user for daily management, restricted to a specific namespace. Below are the steps:

Kubernetes Users

In Kubernetes, there are two types of users: ServiceAccounts and regular users (User). ServiceAccounts are managed by Kubernetes, while regular users are typically managed externally. Kubernetes does not store user lists—meaning user creation, modification, or deletion must be handled externally, without interacting with the Kubernetes API. Although Kubernetes does not manage users directly, it can recognize the identity of users making API requests. In fact, every API request to Kubernetes must be associated with an identity (either a User or a ServiceAccount), allowing us to assign permissions within the cluster to specific users.

When Kubernetes receives API requests from users, it commonly uses one of three authentication methods: client certificates, static token files, or static password files. Here, we focus only on certificate-based authentication.

Generate User Certificate

Prepare a Certificate Signing Request (CSR) file, which will be signed by the Kubernetes CA. The default path for the Kubernetes API server’s CA is /etc/kubernetes/pki/. This process generates cicd-admin-key.pem (private key) and cicd-admin.pem (certificate). For details on generating CSR files, refer to: https://wnote.com/post/linux-openssl-issue-private-certificate/

The username passed in the CSR file is cicd-admin.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# vim cicd-admin-csr.json
{
  "CN": "cicd-admin",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
1
2
3
4
5
6
7
# cd /etc/kubernetes/pki/
# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes cicd-admin-csr.json | cfssljson -bare cicd-admin
# ls -l cicd-admin*
-rw-r--r-- 1 root root 1001 Dec 19 16:51 cicd-admin.csr
-rw-r--r-- 1 root root  224 Dec 19 16:50 cicd-admin-csr.json
-rw------- 1 root root 1675 Dec 19 16:51 cicd-admin-key.pem
-rw-r--r-- 1 root root 1387 Dec 19 16:51 cicd-admin.pem

User Permission Control (RBAC)

Create Role

In Kubernetes, RBAC roles come in two types: Role and ClusterRole. A ClusterRole is a special kind of Role:

  • A Role belongs to a specific namespace; a ClusterRole applies across the entire cluster, including all namespaces.
  • A ClusterRole can grant cluster-wide permissions (e.g., managing Node resources) and can access resources across all namespaces (using --all-namespaces). By default, Kubernetes includes a built-in ClusterRole named admin, which is usually sufficient and doesn’t require manual creation.

Create a role named cicd-admin in the cicd namespace:

1
2
3
4
5
6
7
8
9
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: cicd
  name: cicd-admin
rules:
- apiGroups: [""]
  resources: ["*"]
  verbs: ["*"]

Bind User to Role

subjects specifies the account type, which can be either User or ServiceAccount. Here, we bind the user cicd-admin. roleRef defines the role referenced by the RoleBinding.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: cicd-admin-binding
  namespace: cicd
subjects:
- kind: User
  name: cicd-admin
  apiGroup: ""
roleRef:
  kind: Role
  name: admin
  apiGroup: ""

Alternatively, use kubectl to create the binding:

1
kubectl create rolebinding cicd-admin-binding --role=admin --user=cicd-admin --namespace=cicd

Or bind the user to the default ClusterRole admin, which will limit the user’s permissions to the cicd namespace:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: cicd-admin-binding
  namespace: cicd
subjects:
- kind: User
  name: cicd-admin
  apiGroup: ""
roleRef:
  kind: ClusterRole
  name: admin
  apiGroup: ""

Client Configuration

Set Cluster Parameters

1
2
3
4
5
6
export KUBE_APISERVER="https://cicd-k8s.test.cn:8443"
kubectl config set-cluster kubernetes \
  --certificate-authority=/etc/kubernetes/ssl/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=cicd-admin.kubeconfig

Set Client Authentication Parameters

1
2
3
4
5
kubectl config set-credentials cicd-admin \
  --client-certificate=/etc/kubernetes/ssl/cicd-admin.pem \
  --client-key=/etc/kubernetes/ssl/cicd-admin-key.pem \
  --embed-certs=true \
  --kubeconfig=cicd-admin.kubeconfig

Set Context Parameters

1
2
3
4
5
kubectl config set-context kubernetes \
  --cluster=kubernetes \
  --user=cicd-admin \
  --namespace=cicd \
  --kubeconfig=cicd-admin.kubeconfig

Set Default Context

1
kubectl config use-context kubernetes --kubeconfig=cicd-admin.kubeconfig

Client Usage

Copy the kubeconfig file to override ~/.kube/config:

1
cp cicd-admin.kubeconfig ~/.kube/config

With this, the setup for adding a user and granting them authorized access to the Kubernetes cluster is complete.