在kubernets上有一些服务和客户端需要与api server交涉,并且集群内部会运行类似的pod资源,这些资源是需要访问api server的 ,如: CoreDNS,以及dashboard
dashboard提供一个web界面来管理kubernetes,通过service暴漏到外部,通过浏览器打开使用。当然会有通过dashboard来进行增删改查资源,那意味着dashboard这个pod就有可能去创建pod,甚至于名称空间等,那这种操作明显是需要与api server交涉的。如下图:
与api server交涉的有两类:
- 集群之外的客户端 ,集群之外的客户端每次访问api server使用api server监听的节点地址
如kubectl,kubectl并没有运行在节点之上,可以运行在任何系统上,只要有配置文件,都可以进行链接。外部的链接通过api server对外的通信监听的地址,与远程客户端通讯。如上图。
- 集群内部POD客户端
pod有pod网络,pod工作在内部的网段内
集群内部范围api server是通过名称空间当中的kubernetes的service ip 10.96.0.1 进行通讯。将一个集群外部的服务以service的方式引入到集群内部来,事实上也是同一个主机上的,10.96.0.1也就是serviec所在的网络地址,pod本身也是可以和service通讯的,从而使得POD可以请求api server之上的服务。pod请求api service上的服务就是通过10.96.0.1进行的。如上图
[root@linuxea volume]# kubectl describe svc kubernetes
Name: kubernetes
Namespace: default
Labels: component=apiserver
provider=kubernetes
Annotations: <none>
Selector: <none>
Type: ClusterIP
IP: 10.96.0.1
Port: https 443/TCP
TargetPort: 6443/TCP
Endpoints: 10.10.240.161:6443
Session Affinity: None
Events: <none>
但是,api server是需要认证的,api server将认证传递给客户端,客户端校验api server的身份,同时api server校验客户端的身份。那就意味着api server发送给客户端的身份中表明的ip地址不能只是宿主机10.10.240.161这一个ip地址,并且要有coredns的10.96.0.1这个ip地址。因为pod客户端在集群内访问的是10.96.0.1这个IP地址。那也就是说证书持有者名称必须有两条a记录解析到这两个ip。
serviceAccount
那也就是说证书持有者名称必须有两条a记录解析到这两个ip。任何pod只要需要访问到api server,api server必须要求认证pod,不认证就会被拒绝。而这个认证是由pod提供的,而serviceAccountName
(服务账号名称)就是让pod链接api server进行认证用的账号。
- kubernetes集群中有两类认证账号,一种是管理人员用户操作类(
`userAccountName
),第二种是服务账号(serviceAccountName
),指运行在k8s集群上的pod,想访问当前k8s集群的api server的用户认证信息,服务帐户等。事实上每一种pod都会与api交互,只是权限大小不同而已
默认pod在运行时候,都会有相关信息,如下:
[root@linuxea ~]# kubectl describe pods satefulset-2
......
Volumes:
default-token-k25gj:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-k25gj
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
.....
default-token-k25gj的认证资源保存在Secret vloume存储卷的方式关联到pod当中,从而来完成认证链接信息的
其次,在名称空间中默认会创建一个secret的名称空间。default-token-k25gj
[root@linuxea ~]# kubectl get secret
NAME TYPE DATA AGE
default-token-k25gj kubernetes.io/service-account-token 3 15d
redis-passwd Opaque 1 2d
tomcat-ingress-secret kubernetes.io/tls 2 14d
之前创建的 ingress-nginx
名称空间,也有default-token-s7f97
,这个token让这个名称空间所有的pod资源联系api server时候预置的认证信息,不过仅限获取当前pod于自身的相关属性,并不能去管理别人的
[root@linuxea ingress]# kubectl get secret -n ingress-nginx
NAME TYPE DATA AGE
default-token-s7f97 kubernetes.io/service-account-token 3 15d
nginx-ingress-serviceaccount-token-89ctc kubernetes.io/service-account-token 3 15d
如果要扩展一个pod,就是用来管理其他的pod,或者说是管理类的其他资源对象,就必须手动创建一个service-account-token
,并且创建pod时候附加手动定义的service-account-token
,不去使用默认的即可。
- 默认的
service-account-token
一般权限非常小,如果需要提升权限就需要手动定义。
创建serviceAccount
serviceAccount
属于k8s标准资源,可以创建完成后,使用serviceAccountname
加载定义的serviceAccount
可以使用create
创建serviceAccount
,而后指定属性即可创建,这些属性使用kubectl create serviceaccount -h
可以看到。如果不指定任何属性,也可以给定一个名称。
serviceAccount
本身是不带权限的,创建只是使他换了一个账号。而后使用RBAC授其他的权限给这个创建的serviceAccount
。授权并不属于serviceAccount
,可以使用一个专用的账号给POD使用,而后给这个专用的账号更大的权限使用。而默认的serviceAccount
会让名称空间当中所有的pod都拥有这个权限。如果有这种专用的需求,就需要定义一个专用的账号来赋予权限。
命令行创建
--dry-run=false
: If true, only print the object that would be sent, without sending it.。我们可在加上--dry-run
测试
[root@linuxea ingress]# kubectl create serviceaccount mysa --dry-run
serviceaccount/mysa created (dry run)
--o yaml
指明输出格式,清单类型yaml
[root@linuxea ingress]# kubectl create serviceaccount mysa -o yaml --dry-run
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: null
name: mysa
可以使用--dry-run
将结果>输出重定向到文件中,如:
kubectl create serviceaccount mysa -o yaml --dry-run > ./linuxea.yml
,支持create的都可以这么做。当然,也可以指定一个pod名称来查看,如:kubectl get pods linuxea-tomcat-group-b77666d76-4h5mz -o yaml --export
serviceAccount
简称sa,在使用kubectl get sa
即可。此时能看到默认的一个sa
[root@linuxea ingress]# kubectl get sa
NAME SECRETS AGE
default 1 16d
创建sa
创建一个名称为admin-linuxea
的serviceaccount
[root@linuxea ingress]# kubectl create serviceaccount admin-linuxea
serviceaccount/admin-linuxea created
[root@linuxea ingress]# kubectl get sa
NAME SECRETS AGE
admin-linuxea 1 3s
default 1 16d
创建完成系统会自动生成secret。而系统也会自动生成一个tokens信息
[root@linuxea ingress]# kubectl describe sa admin-linuxea
Name: admin-linuxea
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: admin-linuxea-token-4zpzk
Tokens: admin-linuxea-token-4zpzk
Events: <none>
生成的admin-linuxea-token-4zpzk
secret
- 这个secret仅用于这个sa链接当前api server的认证信息,并不包含权限信息,如果需要什么权限,则需要另外授权
[root@linuxea ingress]# kubectl get secret
NAME TYPE DATA AGE
admin-linuxea-token-4zpzk kubernetes.io/service-account-token 3 1m
应用sa到pod
创建一个linuxea-sa-demo的pod,在spec中添加serviceAccountName: admin-linuxea
,也就是之前创建的serviceAccount
[root@linuxea sa]# cat sa-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: linuxea-sa-demo
namespace: default
labels:
www: linuxea-com
tier: backend
annotations:
www.linuxea.com/ops-by: "linuxea admin"
spec:
containers:
- name: linuxea-pod1-com
image: "marksugar/nginx:1.14.a"
ports:
- containerPort: 80
serviceAccountName: admin-linuxea
用kubectl describe pods linuxea-sa-demo
查看volumes
,admin-linuxea-token-4zpzk:
已在其中,type为Secret,如下:
[root@linuxea sa]# kubectl describe pods linuxea-sa-demo|tail -20
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
admin-linuxea-token-4zpzk:
Type: Secret (a volume populated by a Secret)
SecretName: admin-linuxea-token-4zpzk
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 33s default-scheduler Successfully assigned default/linuxea-sa-demo to linuxea.node-3.com
Normal Pulled 31s kubelet, linuxea.node-3.com Container image "marksugar/nginx:1.14.a" already present on machine
Normal Created 30s kubelet, linuxea.node-3.com Created container
Normal Started 30s kubelet, linuxea.node-3.com Started container
私有镜象认证的两种方式
在每一次提交资源清单到api server,api server传递至kubelet,而后创建并允许一个pod,而这个pod内的容器想要启动,就需要pull一个镜象仓库的镜象,而这个镜象参考需要认证。这个认证信息在之前的配置中使用Secret
,并且定义,而后使用pod中的imagePullSecrets
指明使用那个Secret
对象,而这个Secret
对象中包含了认证私有镜象仓库的账号和密码。
我们也可以在pod当中不使用imagePullSecrets
来告诉pod怎么去认证下载镜象文件,而是用serviceAccountName
,serviceAccountName
相当于指定了sa账号,而这个sa账号附带可以认证到私有参考的认证信息的,如下:在之前创建的sa -> admin-linuxea中Image pull secrets
,也就是说创建的secrets
可以直接定义在sa上,然后在把sa定义到pod上,这样sa通过Image pull secrets
定义secrets
也能完成image的资源认证。相比较imagePullSecrets
,用户只能看见sa,对于sa来讲, 是或许不到secrets
信息的,相对安全些
[root@linuxea sa]# kubectl describe sa admin-linuxea
Name: admin-linuxea
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: admin-linuxea-token-4zpzk
Tokens: admin-linuxea-token-4zpzk
Events: <none>
这样一来获取私有镜象认证就 有两种方式:1,imagePullSecrets
字段指定认证的secrets
对象2,在pod上定义serviceAccount
,而后在pod附加即可Image pull secrets