☸️ Как создать в Kubernetes службу / аккаунт пользователя и ограничить его одним пространством имен с помощью RBAC

by itisgood

Как создать пользователя и ограничить доступ пользователя только к одному пространству имен в Kubernetes?

Kubernetes дает вам возможность регулировать доступ к кластерам и ресурсам Kubernetes на основе ролей отдельных пользователей с помощью функции, называемой управлением доступом на основе ролей (RBAC).

Начиная с выпуска 1.8 Kubernetes, режим RBAC стабилен и поддерживается API rbac.authorization.k8s.io/v1.

Есть несколько определений, которые вы должны понять, прежде чем мы продолжим:

  • Role: роль содержит правила, которые представляют собой набор прав. Роль используется для предоставления доступа к ресурсам в пространстве имен.
  • RoleBinding: Используется для предоставления прав, определенных в роли, пользователю или группе пользователей. Она содержит список субъектов (пользователей, групп или учетных записей служб) и ссылку на предоставленную роль.
  • Service Account: Предназначен для процессов, которые запускаются в модулях.

Чтобы добиться полной изоляции в Kubernetes, мы будем использовать концепции пространств имен и управления доступом на основе ролей.

Идея сервисных учетных записей основана на принципе наименьших привилегий.

Учетная запись создается для конкретных задач.

Как создать и ограничить учетную запись службы пространством имен в Kubernetes

Шаг 1: Создайте пространство имен


Давайте начнем с создания пространства имен, которое будет использоваться для этой демонстрации.

$ 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

Шаг 2. Создание учетной записи службы


Мы создадим учетную запись службы под названием demo-user в пространстве имен demo

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

Вы получите такой вывод:

serviceaccount/demo-user created

Шаг 3: Создать роль

Как объяснялось ранее, роль содержит правила, которые представляют собой набор прав, которые предоставляют доступ к ресурсам в пространстве имен.

Сначала подтвердите версии API для RBAC, доступные в вашем кластере Kubernetes:

$ kubectl api-versions| grep  rbac      
rbac.authorization.k8s.io/v1rbac.authorization.k8s.io/v1beta1
Давайте создадим роль, которая предоставит созданной учетной записи полный доступ к ресурсам пространства имен.
cat <<EOF | kubectl apply -f -
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: admin
  namespace: demo
rules:
- apiGroups: ["", "extensions", "apps"]
  resources: ["*"]
  verbs: ["*"]
- apiGroups: ["batch"]
  resources:
  - jobs
  - cronjobs
  verbs: ["*"]
EOF

Подтвердите создание:

$ kubectl get roles -n demo          
NAME                   AGE
admin   94s
Роль также может быть создана с ограниченным доступом к ресурсам в пространстве имен, например:
cat <<EOF | kubectl apply -f -
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: demo
  name: deployment-admin
rules:
- apiGroups: ["", "extensions", "apps"]
  resources: ["deployments", "replicasets", "pods", "services", "ingresses"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # You can also use ["*"]
EOF

Шаг 4: Привязать роль к пользователю

Теперь, когда у нас есть учетная запись пользователя и роль, мы можем перейти к привязке роли к пользователю.

cat <<EOF | kubectl apply -f -
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: admin-view
  namespace: demo
subjects:
- kind: ServiceAccount
  name: demo-user
  namespace: demo
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: admin
EOF

Подтверждение:

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

Проверьте имя токена пользователя:

$ kubectl describe sa demo-user -n demo
Name:                demo-user
Namespace:           demo
Labels:              
Annotations:         kubectl.kubernetes.io/last-applied-configuration:
                       {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"demo-user","namespace":"demo"}}
Image pull secrets:  
Mountable secrets:   demo-user-token-k9qbl
Tokens:              demo-user-token-k9qbl
Events:
Получите токен учетной записи службы, который будет использоваться для доступа к Kubernetes на панели инструментов или через командную строку kubectl.
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

Мой вывод:

eyJhbGciOiJSUzI1NiIsImtpZCI6IkRrUEFveUZGUGZZS0Q3Tzl5eVZpcFE5elFYZEI5SWZ6ZlVhYXFzLU04ZTQifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZW1vIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlbW8tdXNlci10b2tlbi1rOXFibCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJkZW1vLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJjOWRhNGVmOC1jNmQ5LTQ0NTEtYTQ5Ny02ODc1MjY1MzAwMzQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVtbzpkZW1vLXVzZXIifQ.CnrAkziL_Qr8QNQCV_PDkXCi2H-4MoPUGoPVxjSWGZUTXd6V-a9_JKv6t5Vqhrh5vXNTkDSaR1BtLCpKYdXTyqY6CjbyI7gYYcA2M22nkCDjUiwDhxInlios29SAtoOAXq7rwg_cdgdA7XWAWEcWDtT1vRe5LLbXsnORuJ5BtYXynQXWjWjbcC6T9XqRL7iZX4VUk4YCAkX7N89OGzvyycUjjHzOne67qzqOawzjYqeSzHiXIXILwHk4KKhU8tdGG6shYF7niazdp6ZyssdQ24lQext9jzDeUZf3iXPJ_bvZUv4Jo0_eZjldi9WW0dgN5PXe5r-cD1nOJHE8sClBsg

Получите данные сертификата:

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

Мой вывод:

LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJXRENCL3FBREFnRUNBZ0VBTUFvR0NDcUdTTTQ5QkFNQ01DTXhJVEFmQmdOVkJBTU1HR3N6Y3kxelpYSjIKWlhJdFkyRkFNVFUzTmpNd01qVXdNakFlRncweE9URXlNVFF3TlRRNE1qSmFGdzB5T1RFeU1URXdOVFE0TWpKYQpNQ014SVRBZkJnTlZCQU1NR0dzemN5MXpaWEoyWlhJdFkyRkFNVFUzTmpNd01qVXdNakJaTUJNR0J5cUdTTTQ5CkFnRUdDQ3FHU000OUF3RUhBMElBQlBiSmdKQ2w0elZsNFlaQUJ4dThnbFk1c2hEeDYwaVd6cXY0RU96MS93K24KKzJpMG5heUxuRTF1MjZmT1ZkY3dlMFdjUFJCb2J0M2ViNnNtYWRKQUhBV2pJekFoTUE0R0ExVWREd0VCL3dRRQpBd0lDcERBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDSVFEczN4YTArK0E4CktVd0w2NUZyR25vWW9sTWNUei81QnoxSmNJc292VkxncUFJaEFJV0xRUXpyWkpDem9TaVlEMFZvUXhlaXIwOUEKVWhnTDBucFlzRDVUUlVYKwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==

Шаг 5: Создание конфигурации kubectl

Если вы хотите настроить kubectl с полученными учетными данными, это будет выглядеть примерно так:

$ cat .kube/config
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJXRENCL3FBREFnRUNBZ0VBTUFvR0NDcUdTTTQ5QkFNQ01DTXhJVEFmQmdOVkJBTU1HR3N6Y3kxelpYSjIKWlhJdFkyRkFNVFUzTmpNd01qVXdNakFlRncweE9URXlNVFF3TlRRNE1qSmFGdzB5T1RFeU1URXdOVFE0TWpKYQpNQ014SVRBZkJnTlZCQU1NR0dzemN5MXpaWEoyWlhJdFkyRkFNVFUzTmpNd01qVXdNakJaTUJNR0J5cUdTTTQ5CkFnRUdDQ3FHU000OUF3RUhBMElBQlBiSmdKQ2w0elZsNFlaQUJ4dThnbFk1c2hEeDYwaVd6cXY0RU96MS93K24KKzJpMG5heUxuRTF1MjZmT1ZkY3dlMFdjUFJCb2J0M2ViNnNtYWRKQUhBV2pJekFoTUE0R0ExVWREd0VCL3dRRQpBd0lDcERBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDSVFEczN4YTArK0E4CktVd0w2NUZyR25vWW9sTWNUei81QnoxSmNJc292VkxncUFJaEFJV0xRUXpyWkpDem9TaVlEMFZvUXhlaXIwOUEKVWhnTDBucFlzRDVUUlVYKwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    server: https://k3s-master01:6443
  name: mycluster


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

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


users:
- name: demo-user
  user:
    token: eyJhbGciOiJSUzI1NiIsImtpZCI6IkRrUEFveUZGUGZZS0Q3Tzl5eVZpcFE5elFYZEI5SWZ6ZlVhYXFzLU04ZTQifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZW1vIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlbW8tdXNlci10b2tlbi1rOXFibCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJkZW1vLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJjOWRhNGVmOC1jNmQ5LTQ0NTEtYTQ5Ny02ODc1MjY1MzAwMzQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVtbzpkZW1vLXVzZXIifQ.CnrAkziL_Qr8QNQCV_PDkXCi2H-4MoPUGoPVxjSWGZUTXd6V-a9_JKv6t5Vqhrh5vXNTkDSaR1BtLCpKYdXTyqY6CjbyI7gYYcA2M22nkCDjUiwDhxInlios29SAtoOAXq7rwg_cdgdA7XWAWEcWDtT1vRe5LLbXsnORuJ5BtYXynQXWjWjbcC6T9XqRL7iZX4VUk4YCAkX7N89OGzvyycUjjHzOne67qzqOawzjYqeSzHiXIXILwHk4KKhU8tdGG6shYF7niazdp6ZyssdQ24lQext9jzDeUZf3iXPJ_bvZUv4Jo0_eZjldi9WW0dgN5PXe5r-cD1nOJHE8sClBsg
    client-key-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJXRENCL3FBREFnRUNBZ0VBTUFvR0NDcUdTTTQ5QkFNQ01DTXhJVEFmQmdOVkJBTU1HR3N6Y3kxelpYSjIKWlhJdFkyRkFNVFUzTmpNd01qVXdNakFlRncweE9URXlNVFF3TlRRNE1qSmFGdzB5T1RFeU1URXdOVFE0TWpKYQpNQ014SVRBZkJnTlZCQU1NR0dzemN5MXpaWEoyWlhJdFkyRkFNVFUzTmpNd01qVXdNakJaTUJNR0J5cUdTTTQ5CkFnRUdDQ3FHU000OUF3RUhBMElBQlBiSmdKQ2w0elZsNFlaQUJ4dThnbFk1c2hEeDYwaVd6cXY0RU96MS93K24KKzJpMG5heUxuRTF1MjZmT1ZkY3dlMFdjUFJCb2J0M2ViNnNtYWRKQUhBV2pJekFoTUE0R0ExVWREd0VCL3dRRQpBd0lDcERBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDSVFEczN4YTArK0E4CktVd0w2NUZyR25vWW9sTWNUei81QnoxSmNJc292VkxncUFJaEFJV0xRUXpyWkpDem9TaVlEMFZvUXhlaXIwOUEKVWhnTDBucFlzRDVUUlVYKwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== 

Давайте подтвердим, что это работает:

$ kubectl get secrets
NAME                    TYPE                                  DATA   AGE
default-token-25lbj     kubernetes.io/service-account-token   3      55m
demo-user-token-k9qbl   kubernetes.io/service-account-token   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

Мы также можем создать тестовые развертывания:

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: busybox-sleep
spec:
  containers:
  - name: busybox
    image: busybox
    args:
    - sleep
    - "1000000"
---
apiVersion: v1
kind: Pod
metadata:
  name: busybox-sleep-less
spec:
  containers:
  - name: busybox
    image: busybox
    args:
    - sleep
    - "1000"
EOF
Подтвердите и очистите:
$ 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

 

You may also like

Leave a Comment