创建限于一个命名空间的Kubernetes服务/用户帐户
如何创建用户并限制用户只能访问Kubernetes中的一个名称空间? Kubernetes通过基于角色的访问控制(RBAC)功能为我们提供了一种基于单个用户的角色来规范对Kubernetes集群和资源的访问的方法。从Kubernetes 1.8版开始,RBAC模式是稳定的并由rbac.authorization.k8s.io/v1 API支持。
在进行下一步之前,我们需要了解一些定义:角色:角色包含代表一组权限的规则。角色用于授予对命名空间中资源的访问权限。角色绑定:角色绑定用于向用户或者一组用户授予在角色中定义的权限。它包含一个主题列表(用户,组或者服务帐户),以及对要授予的角色的引用服务帐户:该帐户用于在pod中运行的流程。
为了在Kubernetes中实现完全隔离,请很好地使用有关名称空间和基于角色的访问控制的概念。服务帐户背后的想法基于最小特权原则。将为特定任务创建一个帐户。
在Kubernetes中创建服务帐户并将其限制为名称空间
创建名称空间
让我们先创建一个将用于此演示的名称空间。
$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
建立服务帐户
在演示名称空间中创建一个名为demo-user的服务帐户。
cat <<EOF | kubectl apply -f apiVersion: v1 kind: ServiceAccount metadata: name: demo-user namespace: demo EOF
我们将获得如下输出:
serviceaccount/demo-user created
建立角色
如前所述,角色包含代表代表一组权限的规则,这些权限授予对命名空间中资源的访问权限。
首先确认Kubernetes集群中可用的RBAC的API版本:
$kubectl api-versions| grep rbac rbac.authorization.k8s.io/v1 rbac.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
将角色绑定到用户
现在我们已经创建了用户帐户和角色,我们可以继续将角色绑定到用户。
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:
获取用于在仪表板上或者通过kubectl命令行访问Kubernetes的服务帐户令牌。
export NAMESPACE="demo" export K8S_USER="demo-user" kubectl -n ${NAMESPACE} describe secret $(kubectl -n ${NAMESPACE} get secret | (grep ${K8S_USER} || echo "$_") | awk '{print }') | grep token: | awk '{print }'\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 }'` -o "jsonpath={.data['ca\.crt']}"
我的输出:
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJXRENCL3FBREFnRUNBZ0VBTUFvR0NDcUdTTTQ5QkFNQ01DTXhJVEFmQmdOVkJBTU1HR3N6Y3kxelpYSjIKWlhJdFkyRkFNVFUzTmpNd01qVXdNakFlRncweE9URXlNVFF3TlRRNE1qSmFGdzB5T1RFeU1URXdOVFE0TWpKYQpNQ014SVRBZkJnTlZCQU1NR0dzemN5MXpaWEoyWlhJdFkyRkFNVFUzTmpNd01qVXdNakJaTUJNR0J5cUdTTTQ5CkFnRUdDQ3FHU000OUF3RUhBMElBQlBiSmdKQ2w0elZsNFlaQUJ4dThnbFk1c2hEeDYwaVd6cXY0RU96MS93K24KKzJpMG5heUxuRTF1MjZmT1ZkY3dlMFdjUFJCb2J0M2ViNnNtYWRKQUhBV2pJekFoTUE0R0ExVWREd0VCL3dRRQpBd0lDcERBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDSVFEczN4YTArK0E4CktVd0w2NUZyR25vWW9sTWNUei81QnoxSmNJc292VkxncUFJaEFJV0xRUXpyWkpDem9TaVlEMFZvUXhlaXIwOUEKVWhnTDBucFlzRDVUUlVYKwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
创建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