更新时间:2024-05-31 GMT+08:00
参考:Jenkins对接Kubernetes集群的RBAC
前提条件
集群需要开启RBAC。
场景一:基于namespace的权限控制
新建ServiceAccount和role,然后做rolebinding
$ kubectl create ns dev $ kubectl -n dev create sa dev $ cat <<EOF > dev-user-role.yml kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: dev name: dev-user-pod rules: - apiGroups: ["*"] resources: ["deployments", "pods", "pods/log"] verbs: ["get", "watch", "list", "update", "create", "delete"] EOF kubectl create -f dev-user-role.yml $ kubectl create rolebinding dev-view-pod \ --role=dev-user-pod \ --serviceaccount=dev:dev \ --namespace=dev
生成指定ServiceAccount的kubeconfig文件
- 1.21以前版本的集群中,Pod中获取Token的形式是通过挂载ServiceAccount的Secret来获取Token,这种方式获得的Token是永久的。该方式在1.21及以上的版本中不再推荐使用,并且根据社区版本迭代策略,在1.25及以上版本的集群中,ServiceAccount将不会自动创建对应的Secret。
1.21及以上版本的集群中,直接使用TokenRequest API获得Token,并使用投射卷(Projected Volume)挂载到Pod中。使用这种方法获得的Token具有固定的生命周期,并且当挂载的Pod被删除时这些Token将自动失效。详情请参见Token安全性提升说明。
- 如果您在业务中需要一个永不过期的Token,您也可以选择手动管理ServiceAccount的Secret。尽管存在手动创建永久ServiceAccount Token的机制,但还是推荐使用TokenRequest的方式使用短期的Token,以提高安全性。
$ SECRET=$(kubectl -n dev get sa dev -o go-template='{{range .secrets}}{{.name}}{{end}}') $ API_SERVER="https://172.22.132.51:6443" $ CA_CERT=$(kubectl -n dev get secret ${SECRET} -o yaml | awk '/ca.crt:/{print $2}') $ cat <<EOF > dev.conf apiVersion: v1 kind: Config clusters: - cluster: certificate-authority-data: $CA_CERT server: $API_SERVER name: cluster EOF $ TOKEN=$(kubectl -n dev get secret ${SECRET} -o go-template='{{.data.token}}') $ kubectl config set-credentials dev-user \ --token=`echo ${TOKEN} | base64 -d` \ --kubeconfig=dev.conf $ kubectl config set-context default \ --cluster=cluster \ --user=dev-user \ --kubeconfig=dev.conf $ kubectl config use-context default \ --kubeconfig=dev.conf
命令行中验证
$ kubectl --kubeconfig=dev.conf get po Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:dev:dev" cannot list pods in the namespace "default" $ kubectl -n dev --kubeconfig=dev.conf run nginx --image nginx --port 80 --restart=Never $ kubectl -n dev --kubeconfig=dev.conf get po NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 39s
Jenkins中验证权限是否符合预期
- 添加有权限控制的kubeconfig到Jenkins系统中
- 启动Jenkins任务,部署到namespace default失败,部署到namespace dev成功。
场景二:基于具体资源的权限控制
- 生成SA和role及绑定:
kubectl -n dev create sa sa-test0304 cat <<EOF > test0304-role.yml kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: dev name: role-test0304 rules: - apiGroups: ["*"] resources: ["deployments"] resourceNames: ["tomcat03", "tomcat04"] verbs: ["get", "update", "patch"] EOF kubectl create -f test0304-role.yml kubectl create rolebinding test0304-bind \ --role=role-test0304 \ --serviceaccount=dev:sa-test0304\ --namespace=dev
- 生成kubeconfig文件:
- 1.21以前版本的集群中,Pod中获取Token的形式是通过挂载ServiceAccount的Secret来获取Token,这种方式获得的Token是永久的。该方式在1.21及以上的版本中不再推荐使用,并且根据社区版本迭代策略,在1.25及以上版本的集群中,ServiceAccount将不会自动创建对应的Secret。
1.21及以上版本的集群中,直接使用TokenRequest API获得Token,并使用投射卷(Projected Volume)挂载到Pod中。使用这种方法获得的Token具有固定的生命周期,并且当挂载的Pod被删除时这些Token将自动失效。详情请参见Token安全性提升说明。
- 如果您在业务中需要一个永不过期的Token,您也可以选择手动管理ServiceAccount的Secret。尽管存在手动创建永久ServiceAccount Token的机制,但还是推荐使用TokenRequest的方式使用短期的Token,以提高安全性。
SECRET=$(kubectl -n dev get sa sa-test0304 -o go-template='{{range .secrets}}{{.name}}{{end}}') API_SERVER=" https://192.168.0.153:5443" CA_CERT=$(kubectl -n dev get secret ${SECRET} -o yaml | awk '/ca.crt:/{print $2}') cat <<EOF > test0304.conf apiVersion: v1 kind: Config clusters: - cluster: certificate-authority-data: $CA_CERT server: $API_SERVER name: cluster EOF TOKEN=$(kubectl -n dev get secret ${SECRET} -o go-template='{{.data.token}}') kubectl config set-credentials test0304-user \ --token=`echo ${TOKEN} | base64 -d` \ --kubeconfig=test0304.conf kubectl config set-context default \ --cluster=cluster \ --user=test0304-user \ --kubeconfig=test0304.conf kubectl config use-context default \ --kubeconfig=test0304.conf
- 1.21以前版本的集群中,Pod中获取Token的形式是通过挂载ServiceAccount的Secret来获取Token,这种方式获得的Token是永久的。该方式在1.21及以上的版本中不再推荐使用,并且根据社区版本迭代策略,在1.25及以上版本的集群中,ServiceAccount将不会自动创建对应的Secret。
- Jenkins中的运行效果符合预期。
Pipeline脚本,依次更新tomcat03/04/05的deployment。
try { kubernetesDeploy( kubeconfigId: "test0304", configs: "test03.yaml") println "hooray, success" } catch (e) { println "oh no! Deployment failed! " println e } echo "test04" try { kubernetesDeploy( kubeconfigId: "test0304", configs: "test04.yaml") println "hooray, success" } catch (e) { println "oh no! Deployment failed! " println e } echo "test05" try { kubernetesDeploy( kubeconfigId: "test0304", configs: "test05.yaml") println "hooray, success" } catch (e) { println "oh no! Deployment failed! " println e }
查看运行效果:
图1 test03
图2 test04