K8s
,这块官方文档的翻译的有点生涩,不太好明白。所以整理下Service Account
的简述Service Account
的Demo真正的坚持归于平静,靠的是温和的发力,而不是时时刻刻的刺激。
学习环境
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl get nodes
NAME STATUS ROLES AGE VERSION
vms81.liruilongs.github.io Ready control-plane,master 134d v1.22.2
vms82.liruilongs.github.io Ready <none> 134d v1.22.2
vms83.liruilongs.github.io NotReady <none> 134d v1.22.2
┌──[root@vms81.liruilongs.github.io]-[~]
└─$
学习Service Account
之前,简单介绍下K8s的安全体系,K8s中通过一系列机制来实现集群的安全控制,其中包括API Server的认证和授(鉴)权
,关于认证
和授(鉴)权
,感兴趣小伙伴可以看看之前的博文,我们这里简单介绍下
关于授(鉴)权
,现在用的比较多的是RBAC(Role-Based Access Control,基于角色的访问控制)
的方式
RBAC
在Kubernetes的1.5版本
中引入,在1.6版本时升级为Beta版本
,在1.8版本时升级为GA
。现在作为kubeadm安装方式的默认选项
,相对于其他访问控制方式,RBAC对集群中的资源和非资源权限均有完整的覆盖。整个RBAC完全由(Role,ClusterRole,RoleBinding,ClusterRoleBinding
)API对象完成,同其他API对象一样,可以用kubectl或API进行操作。可以在运行时进行调整,无须重新启动 API Server。
K8s的授权策略
设置通过通过API Server
的启动参数"--authorization-mode
"设置。 除了RBAC外,授权策略还包括:
策略 | 描述 |
---|---|
ABAC | (Attribute-Based Access Control)基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制。 |
Webhook | 通过调用外部REST服务对用户进行授权。 |
Node | 是一种专用模式,用于对kubelet发出的请求进行访问控制。 |
关于认证机制
,在K8s的认证中,如果按照集群内外认证分的话,分为集群外认证和集群内认证:
集群外认证一般三种,也可以理解为通过kubectl
或者编程语言编写的客户端API访问:
HTTP Token
认证:通过一个Token
来识别合法用户。HTTPS 证书
认证:基于CA根证书签名的双向数字证书认证方式(Kubeconfig文件)HTTP Base
认证:通过用户名+密码的方式认证(用户账户),这个只有1.19之前的版本适用,之后的版本不在支持
集群内的认证也就是我们今天要讲的:Service Account
对象,也叫服务账户
所以说Service Account
它并不是给Kubernetes集群的用户
(系统管理员、运维人员)用的,而是给运行在K8s上的Pod里的进程用的,为Pod里的进程提供认证。
比如我们要编写一个类似kubectl
一样的K8s的管理工具
,如一些面板工具(kubernetes-dashboard)
,而且这个工具是运行在我们的K8s环境里的,那么这个时候,我们如何给这个工具访问集群做认证授权,就要用到Service Account
,简写为sa
,所以我们一般直接叫sa
,或者服务账户
当我们创建任何一个Pod的时候,必须要有sa,否则会创建失败,如果没有显示的指定对应的sa
,即服务账户,Pod会默认使用当前的命令空间的default服务账户(每个命名空间都有一个名为 default 的sa资源。)
这里要说明的是每个sa
服务账户都会生成一个secret
,这个secret
里面包含一个token
凭证。所以说sa
实际认证是通过token
实现的认证。(token
)
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl get sa default
NAME SECRETS AGE
default 1 67d
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl run podcommon --image=nginx --image-pull-policy=IfNotPresent --labels="name=liruilong" --env="name=liruilong"
pod/podcommon created
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl get pods podcommon -o yaml | grep serviceAccountserviceAccount: defaultserviceAccountName: default- serviceAccountToken:
┌──[root@vms81.liruilongs.github.io]-[~]
└─$
可以使用自动挂载给Pod
的default服务账户
token访问 API,但是前提是需要给default授权,对于RBAC的方式来讲,需要给角色授权,然后绑定角色。
在 1.6 以上版本中,可以通过在sa上设置automountServiceAccountToken: false
来实现不给服务账号自动挂载 API token
:
apiVersion: v1
kind: ServiceAccount
metadata:name: build-robot
automountServiceAccountToken: false
...
在 1.6 以上版本中,你也可以选择不给特定 Pod 自动挂载 API token
:
apiVersion: v1
kind: Pod
metadata:name: my-pod
spec:serviceAccountName: build-robotautomountServiceAccountToken:
如果 Pod 和服务账户都指定了automountServiceAccountToken
值,则 Pod 的 spec 优先于服务帐户。
下面看一下kubernetes-dashboard
对sa
的应用,下面是一个已经部署好的dashboard
关于kubernetes-dashboard
是K8s官网提供的Kubernetes的Web UI网页管理工具,可提供部署应用、资源对象管理、容器日志查询、系统监控等常用的集群管理功能。
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODENOMINATED NODE READINESS GATES
dashboard-metrics-scraper-669c88c9d9-2qp62 1/1 Running 8 (7d11h ago) 61d 10.244.88.83 vms81.liruilongs.github.io <none> <none>
kubernetes-dashboard-5d66bcd8fd-l22jm 1/1 Running 13 (7d3h ago) 61d 10.244.88.80 vms81.liruilongs.github.io <none> <none>
┌──[root@vms81.liruilongs.github.io]-[~]
└─$
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl get svc -n kubernetes-dashboard
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
dashboard-metrics-scraper ClusterIP 10.109.92.159 <none> 8000/TCP 67d
kubernetes-dashboard NodePort 10.106.48.37 <none> 443:32360/TCP 67d
┌──[root@vms81.liruilongs.github.io]-[~]
└─$
上面是一个我们之前部署好的面板工具,在部署的过程中,我们要主动创建一个sa(kubernetes-dashboard),并且为这个sa授权,而后,我们的这个面板工具才具有管理K8s集群的能力
创建sa
的资源文件
apiVersion: v1
kind: ServiceAccount
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboardnamespace: kubernetes-dashboard
查看kubernetes-dashboard
sa,可以看到对应的token
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl get sa
NAME SECRETS AGE
......
kubernetes-dashboard 1 67d
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl get secrets
NAME TYPE DATA AGE
.........
kubernetes-dashboard-token-wnqqg kubernetes.io/service-account-token 3 67d
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl describe secrets kubernetes-dashboard-token-wnqqg
Name: kubernetes-dashboard-token-wnqqg
Namespace: kubernetes-dashboard
Labels: <none>
Annotations: kubernetes.io/service-account.name: kubernetes-dashboardkubernetes.io/service-account.uid: 8e209de5-14a0-4dd5-bd19-2264170531f5Type: kubernetes.io/service-account-tokenData
====
token: Jpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9
ca.crt: 1099 bytes
namespace: 20 bytes
┌──[root@vms81.liruilongs.github.io]-[~]
└─$
然后对sa
授权,一般通过RBAC的方式.创建角色
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboard
rules:# Allow Metrics Scraper to get metrics from the Metrics server- apiGroups: ["metrics.k8s.io"]resources: ["pods", "nodes"]verbs: ["get", "list", "watch"]
然后绑定角色到sa
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: kubernetes-dashboard
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: kubernetes-dashboard
subjects:- kind: ServiceAccount name: kubernetes-dashboardnamespace: kubernetes-dashboard
然后pod
通过serviceAccount
和serviceAccountName
来绑定sa
,当然这两个参数指定一个就可以了。
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl get pod kubernetes-dashboard-5d66bcd8fd-l22jm -o yaml | grep -C 5 serviceAccountpreemptionPolicy: PreemptLowerPrioritypriority: 0restartPolicy: AlwaysschedulerName: default-schedulersecurityContext: {}serviceAccount: kubernetes-dashboardserviceAccountName: kubernetes-dashboardterminationGracePeriodSeconds: 30
通过yaml文件我们可以看到,值sa为kubernetes-dashboard
,当然在资源文件中,是在Deployment
和Servcie
中指定,
如果sa
的automountServiceAccountToken
或Pod
的automountServiceAccountToken
都未显式设置为 false,那么会为对应的 Pod 创建一个 volume
,在其中包含用来访问 API 的令牌。
如果为sa对应的token创建了卷,则为 Pod 中的每个容器添加一个 volumeSource
,挂载在其 /var/run/secrets/kubernetes.io/serviceaccount
目录下。
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl get pod kubernetes-dashboard-5d66bcd8fd-l22jm -o yaml | grep -C 20 -i serviceAccount
...........volumeMounts:
...........- mountPath: /var/run/secrets/kubernetes.io/serviceaccountname: kube-api-access-8jlj7readOnly: true
.........serviceAccount: kubernetes-dashboardserviceAccountName: kubernetes-dashboard
.........volumes:
..........- name: kube-api-access-8jlj7projected:defaultMode: 420sources:- serviceAccountToken:expirationSeconds: 3607path: token
........
┌──[root@vms81.liruilongs.github.io]-[~]
└─$
通过配置文件可以看到,token通过卷的方式挂载到了容器里的/var/run/secrets/kubernetes.io/serviceaccount
目录,但是需要注意的是,这个token和sa对应的token在1.20版本之后进行了处理,不一样,在之前的版本中是一样的。
创建一个sa
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl create sa sa-demo
serviceaccount/sa-demo created
查看对应的secret和token
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl get secrets sa-demo-token-pdrs8
NAME TYPE DATA AGE
sa-demo-token-pdrs8 kubernetes.io/service-account-token 3 43s
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl describe secrets sa-demo-token-pdrs8
Name: sa-demo-token-pdrs8
Namespace: kubernetes-dashboard
Labels: <none>
Annotations: kubernetes.io/service-account.name: sa-demokubernetes.io/service-account.uid: 7003de88-803a-4dae-a6e3-d647d0517c92Type: kubernetes.io/service-account-tokenData
====
ca.crt: 1099 bytes
namespace: 20 bytes
token: Jpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJzYS1kZW1vLXRva2VuLXBkcnM4Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6InNhLWRlbW8iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI3MDAzZGU4OC04MDNhLTRkYWUtYTZlMy1kNjQ3ZDA1MTdjOTIiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6c2EtZGVtbyJ9.sVAmtpfqFREjUCd9bkQvMuHpasXOcKYLJvVsJLLe6ufP4zs8ZVt6HqH4ylsxbmwtibNXBV9hVNEU_2X3T2enOjOSYuiyaEP4BifDQN7DmZbu2uXQCBglixaNB7ZIIPX_oQsW0ndBNonVqMSMm-ZItYDzLo-QTOxTxc5OQZ3zSBJqITAvWFlshWA7mKntNmWw6m5KunjhYZs14Lpa-NhknYS9G6ur8SKY4XdE44hzQhD7h4y01ZezZGR3IdGd3HktA5dWYTRXXr9H00odey2YtGfj40Vql3rMrdMPJOFbAozjyaWxhmSpjHVGcbXawai8znKPCdGlW4l2aRmbghovsw
┌──[root@vms81.liruilongs.github.io]-[~]
└─$
编写pod资源文件,指定sa为刚才创建的sa
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl run pod-sa --image=nginx --image-pull-policy=IfNotPresent --dry-run=client -o yaml > pod-sa.yaml
┌──[root@vms81.liruilongs.github.io]-[~]
└─$vim pod-sa.yaml
┌──[root@vms81.liruilongs.github.io]-[~]
└─$cat pod-sa.yaml
apiVersion: v1
kind: Pod
metadata:creationTimestamp: nulllabels:run: pod-demoname: pod-demo
spec:serviceAccount: sa-democontainers:- image: nginximagePullPolicy: IfNotPresentname: pod-demoresources: {}dnsPolicy: ClusterFirstrestartPolicy: Always
status: {}
┌──[root@vms81.liruilongs.github.io]-[~]
└─$
查看创建的pod
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl apply -f pod-sa.yaml
pod/pod-demo created
┌──[root@vms81.liruilongs.github.io]-[~]
└─$kubectl get pods pod-demo
NAME READY STATUS RESTARTS AGE
pod-demo 1/1 Running 0 95s
┌──[root@vms81.liruilongs.github.io]-[~]
└─$
对于deplay的sa修改可以直接通过set的方式设置,时间关系这里不多讲啦,文末的资源文件中有demo
下面我们来看一道Service Account
相关习题,这是某一期CKA认证的一道考题
创建一个名为deployment-clusterrole且仅允许创建以下资源类型的新ClusterRole:
- Deployment
- StatefulSet
- DaemonSet
在现有的 namespace app-team 中创建一个名为cicd-token的新 ServiceAccount。
限于 namespace app-team 中,将新的ClusterRole deployment-clusterrole绑定到新的 ServiceAccount cicd-token。
题目很简单,一般的生产我们也会涉及,指定权限创建一个集群角色,然后把这个集群角色绑定到一个新建的sa上。
# 创建集群角色
kubectl create clusterrole deployment-clusterrole --verb=create --resource=deployments,statefulsets,daemonsets
# 创建服务账户
kubectl -n app-team create serviceaccount cicd-token
# 绑定角色到服务账户
kubectl -n app-team create rolebinding cicd-token-rolebinding --clusterrole=deployment-clusterrole --serviceaccount=app-team1:cicd-token
对应sa学习,感觉kubernetes-dashboard的是一个很好的Demo。这里把面板的资源文件贴出来,感兴趣小伙伴可以研究下
# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# .0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.apiVersion: v1
kind: Namespace
metadata:name: kubernetes-dashboard---apiVersion: v1
kind: ServiceAccount
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboardnamespace: kubernetes-dashboard---kind: Service
apiVersion: v1
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboardnamespace: kubernetes-dashboard
spec:ports:- port: 443targetPort: 8443selector:k8s-app: kubernetes-dashboard---apiVersion: v1
kind: Secret
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboard-certsnamespace: kubernetes-dashboard
type: Opaque---apiVersion: v1
kind: Secret
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboard-csrfnamespace: kubernetes-dashboard
type: Opaque
data:csrf: ""---apiVersion: v1
kind: Secret
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboard-key-holdernamespace: kubernetes-dashboard
type: Opaque---kind: ConfigMap
apiVersion: v1
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboard-settingsnamespace: kubernetes-dashboard---kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboardnamespace: kubernetes-dashboard
rules:# Allow Dashboard to get, update and delete Dashboard exclusive secrets.- apiGroups: [""]resources: ["secrets"]resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"]verbs: ["get", "update", "delete"]# Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.- apiGroups: [""]resources: ["configmaps"]resourceNames: ["kubernetes-dashboard-settings"]verbs: ["get", "update"]# Allow Dashboard to get metrics.- apiGroups: [""]resources: ["services"]resourceNames: ["heapster", "dashboard-metrics-scraper"]verbs: ["proxy"]- apiGroups: [""]resources: ["services/proxy"]resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"]verbs: ["get"]---kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboard
rules:# Allow Metrics Scraper to get metrics from the Metrics server- apiGroups: ["metrics.k8s.io"]resources: ["pods", "nodes"]verbs: ["get", "list", "watch"]---apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboardnamespace: kubernetes-dashboard
roleRef:apiGroup: rbac.authorization.k8s.iokind: Rolename: kubernetes-dashboard
subjects:- kind: ServiceAccountname: kubernetes-dashboardnamespace: kubernetes-dashboard---apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: kubernetes-dashboard
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: kubernetes-dashboard
subjects:- kind: ServiceAccountname: kubernetes-dashboardnamespace: kubernetes-dashboard---kind: Deployment
apiVersion: apps/v1
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboardnamespace: kubernetes-dashboard
spec:replicas: 1revisionHistoryLimit: 10selector:matchLabels:k8s-app: kubernetes-dashboardtemplate:metadata:labels:k8s-app: kubernetes-dashboardspec:containers:- name: kubernetes-dashboard#image: kubernetesui/dashboard:v2.0.0-beta8image: registry-hangzhou.aliyuncs/kube-iamges/dashboard:v2.0.0-beta8#imagePullPolicy: AlwaysimagePullPolicy: IfNotPresentports:- containerPort: 8443protocol: TCPargs:- --auto-generate-certificates- --namespace=kubernetes-dashboard# Uncomment the following line to manually specify Kubernetes API server Host# If not specified, Dashboard will attempt to auto discover the API server and connect# to it. Uncomment only if the default does not work.# - --apiserver-host=my-address:portvolumeMounts:- name: kubernetes-dashboard-certsmountPath: /certs# Create on-disk volume to store exec logs- mountPath: /tmpname: tmp-volumelivenessProbe:httpGet:scheme: HTTPSpath: /port: 8443initialDelaySeconds: 30timeoutSeconds: 30securityContext:allowPrivilegeEscalation: falsereadOnlyRootFilesystem: truerunAsUser: 1001runAsGroup: 2001volumes:- name: kubernetes-dashboard-certssecret:secretName: kubernetes-dashboard-certs- name: tmp-volumeemptyDir: {}serviceAccountName: kubernetes-dashboardnodeSelector:"kubernetes.io/os": linux# Comment the following tolerations if Dashboard must not be deployed on mastertolerations:- key: node-role.kubernetes.io/mastereffect: NoSchedule---kind: Service
apiVersion: v1
metadata:labels:k8s-app: dashboard-metrics-scrapername: dashboard-metrics-scrapernamespace: kubernetes-dashboard
spec:ports:- port: 8000targetPort: 8000selector:k8s-app: dashboard-metrics-scraper---kind: Deployment
apiVersion: apps/v1
metadata:labels:k8s-app: dashboard-metrics-scrapername: dashboard-metrics-scrapernamespace: kubernetes-dashboard
spec:replicas: 1revisionHistoryLimit: 10selector:matchLabels:k8s-app: dashboard-metrics-scrapertemplate:metadata:labels:k8s-app: dashboard-metrics-scraperannotations:seccompProfile: 'runtime/default'spec:containers:- name: dashboard-metrics-scraper#image: kubernetesui/metrics-scraper:v1.0.1image: registry-hangzhou.aliyuncs/kube-iamges/metrics-scraper:v1.0.1imagePullPolicy: IfNotPresentports:- containerPort: 8000protocol: TCPlivenessProbe:httpGet:scheme: HTTPpath: /port: 8000initialDelaySeconds: 30timeoutSeconds: 30volumeMounts:- mountPath: /tmpname: tmp-volumesecurityContext:allowPrivilegeEscalation: falsereadOnlyRootFilesystem: truerunAsUser: 1001runAsGroup: 2001serviceAccountName: kubernetes-dashboardnodeSelector:"kubernetes.io/os": linux# Comment the following tolerations if Dashboard must not be deployed on mastertolerations:- key: node-role.kubernetes.io/mastereffect: NoSchedulevolumes:- name: tmp-volumeemptyDir: {}
本文发布于:2024-02-02 00:29:06,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170681041240202.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |