Fork me on GitHub
Fork me on GitHub

Kubernetes认证及serviceaccount

Kubernetes安全概述

对于k8s api接口的访问不会是任何人能够轻易使用的,此前我们是通过kubectl这个客户端工具进行访问的,如果人人都可以通过kubectl来访问,那么就很可能会删除别人的应用,这是非常危险的。因此k8s对于整个系统的认证、授权和所谓的后续的访问控制做了非常精密和精细的设计。当然考虑k8s从诞生到现在还不算太长,可能会陆续有一些漏洞和缺陷被发现,但至少到现在为止,它在模型设计上已经做得足够安全了。
对于管理员来讲,整个k8s集群的apiserver是访问控制的唯一入口,但是如果我们在集群上部署了应用程序,通过Ingress或者通过Service把后端服务暴露出去,这些服务是不需要通过apiserver来访问的,只需要通过节点的NodePort或Ingress中Ingress Controller中的DaemonSet共享宿主机节点网络名称所监听的宿主机的地址来访问。
apiserver中的 api 是分了群组的,而且每一个群组还可以迭代,但是不管怎么样,任何用户试图到这平台上来操作资源对象,他们必须要经历所谓三种安全相关的操作:

  • 1、认证:任何客户端访问之前,经过apiserver操作之前,得先完成认证操作。用户得有正确的账号。
  • 2、授权检查:认证通过以后,只是证明了他是当前系统合法的用户,是否拥有删除对应资源的权限,还需要做授权检查。
  • 3、准入控制:授权检查完后,我们可以操作某些资源了,但是有些资源的操作还要级联到其他资源和相应的环境,才能满足它的相应条件。因此,级联到的其他资源用户是否有权限,以及他是不是在我们所指定的操作范围内。

k8s是高度模块化设计的,它的认证、授权和准入控制各自都通过插件的方式,可由用户自定义选择经由什么样的插件来完成何种控制逻辑。

认证

对认证来讲,可能有n多个插件,支持多种不同的认证方式。

令牌认证

所谓令牌认证就是双方有一个域共享密钥,服务端存了一个密码,就像mysql认证一样,我们在服务器上先创建一个密码存放下来,随后登录时就拿这个密码登录。这种称为对称密钥登录方式。但是由于k8s提供的是restful风格的接口,它的所有服务都是通过http协议提供的,因此认证信息只能经由http协议的首部进行传递,这种首部在传递时,域共享密钥的编码信息我们称为认证令牌,就叫token。这是最简单的认证方式,但是这种认证,一般只是双方交换下是否拥有域共享密钥就足够了。

ssl认证

ssl认证能让客户端去确认服务器的身份。去和服务器端通信之前,先要求服务器发一个服务器证书过来,先看一看这个证书是否是我们认可的CA签署的。这是第一步。如果是我们认可的CA签署的,而且里面的签署信息与我们访问的服务器信息保持一致,那我们就认为这个服务器的身份得到认证了。但是在k8s通信当中,服务器还要认证客户端的身份。因此kubectl自己也应该有一个证书,有自己的私钥,而且这个证书必须是server端认可的CA所签署的证书。客户端身份也要与证书中标识的身份保持一致。所以双方都需要互相做双向证书认证。认证后双方实现ssl加密通信。

其它认证方式

其实认证还有很多种,以上只是比较常见的两种方式。认证插件可能会有很多,但是用户经过任何一个认证插件通过以后,即表示认证通过,无需经由其他插件进行检查。无需进行串行检查。

授权

k8s支持n种授权插件来完成用户的权限检查。k8s 1.6之后开始支持RBAC的认证,此前有ABAC之类的认证。现在用的比较广泛的、安全的就是RBAC。除此之外还有基于节点认证。最重要的是RBAC授权检查机制。Role Based Access Control,基于角色的访问控制机制。这种基于角色的访问控制机制一般只有许可授权,没有拒绝授权,因为默认都是拒绝的。
默认情况下使用kubeadm部署的k8s集群是强制启用了RBAC认证的,此前的操作到现在还没涉及到所谓授权操作控制逻辑,我们一直在使用k8s的最高管理权限,系统管理员cluster admin来实现操作,而不是普通用户。这就相当于在Linux上使用root用户去操作。随后如果使用admin这样的用户,或者其他普通用户,会发现很有可能这些用户只有只读权限,只能看见有哪些资源对象,而无法去创建、编辑和删除资源对象。所以RBAC可以做到非常灵活。
常见的插件:Node、ABAC、RBAC、Webhook。同样的,不需要串行检查。这些插件可以同时启用。我们也可以定义比较独特的访问控制逻辑。

准入控制

一般而言,准入控制本身只是用来定义对应授权检查完后,后续的其他安全检查操作。了解即可。

apiserver如何校验请求

客户端对apiserver发起操作请求,apiserver要识别这个用户能不能执行他请求的操作:
1、用户账号user:username、uid
2、用户所属的组group:
3、extra:用来提供一些额外信息

用户拿着这用户账号去请求时,一定会请求某个特定的api资源,而k8s的apiserver是分了组的,所以到底向哪个组的哪个版本的api资源对象发出请求,必须要进行标识,而标识则通过用户在http协议当中,request path来标识,比如访问apps下的v1版本的某个资源,资源要么属于集群,要么在名称空间下,名称空间属于集群级别的,所有名称空间级别的资源访问时都要指明名称空间:

1
http://172.20.0.70:6443/apis/apps/v1/namespaces/default/deployments/myapp-deploy/

我们可以基于请求这个url来增删改查,此前执行的kubectl create、delete等事实上都被转换成一个http协议的请求来请求的。
可以演示下,api服务只监听在6443上,它是https的,双向都要做证书认证。我们的curl本地是没有认证的。可以换一种方式。在本地启一个代理。这是kubectl自带的功能。首先kubectl自身有认证能力,其自带的配置文件中拥有认证信息,如下:

1
[root@spark32 ~]# cat .kube/config


所以如果要使用curl请求apiserver是要带着认证信息的,但是curl没有认证信息。在kubectl节点上,运行kubectl proxy命令,就相当于这个家伙在本地作为服务运行了,它监听在我们指定的端口上,为了安全起见,一般监听在127.0.0.1:8080,端口可以自己指定。随后使用curl命令,就访问本地的8080端口,然后由kubectl反向代理至apiserver。

1
2
[root@spark32 ~]# kubectl proxy --port=8080
Starting to serve on 127.0.0.1:8080

在另一个终端上使用curl访问apiserver:

1
[root@spark32 ~]# curl http://localhost:8080/api/v1/namespaces


【注意】:只有是核心群组的资源,访问时是/api/,其他的都是/apis/group_name/version/

1
[root@spark32 ~]# curl http://localhost:8080/apis/apps/v1/namespaces/kube-system/deployments


只看某个具体的对象:

1
[root@spark32 ~]# curl http://localhost:8080/apis/apps/v1/namespaces/kube-system/deployments/coredns

  • HTTP request verb: 对于指定的资源做什么操作。在restful风格中我们称为action,操作,verb也是操作的。
    get, post, put, delete API
  • requests verb: 上面http的请求方法要转成对API对象的请求。也就是映射到k8s语境中对应的请求有哪些:
    get, list, create, update, patch, watch, proxy, redirect, delete, deletecollection
  • Resource: 请求哪个资源,一般是资源的id,或者资源的名称,不同的方法中可能不一样
  • Subresource: 有些资源可能还有子资源,restful风格中允许有子资源的
  • Namespace:名称空间
  • API group:所属的api群组

上述示例中的request path中已经把上述的都表达出来了。

serviceaccount

  • 1、集群外部的客户端:比如访问apiserver对外通信的监听地址 6443端口
  • 2、Pod中容器里的应用程序访问api
    比如运行系统级的服务CoreDNS,需要从api获取用户到底创建什么Service,给Service创建解析记录。创建k8s的图形控制接口Dashboard,这个Dashboard的Pod可以通过Service暴露到集群外部去,可以通过一个浏览器打开它,而用户有可能通过此Dashboard在当前集群中增删改查资源,所以这个Pod也得跟apiserver打交道。Pod和apiserver通信使用的是apiserver在集群内的地址。


客户端与apiserver通信,首先apiserver要把自己的证书传给客户端,客户端去校验apiserver身份,同时apiserver还要去校验客户端身份。服务器apiserver发给它的客户端Pod的时候,证书中标明自己的身份不能是172.16.206.32这个地址,而应该是10.96.0.1,因为客户端访问的是10.96.0.1。所以在apiserver上,如果自己手动建立证书,那么必须确保这个证书的持有者的名称能解析到两条A记录。或者在证书里使用IP地址,这两个地址都得包含进来。另外,Pod客户端也得有证书,apiserver也得验证客户端。此前我们使用kubectl,我们给它提供了配置文件,能进行认证。Pod跟apiserver打交道,怎么认证呢?认证不应该是由Pod内的应用程序来提供的,而是应该由Pod来提供。这些信息在哪里?

1
[root@spark32 manifests]# kubectl explain pod.spec


整个k8s的apiserver的账号有两类:

  • 一类是实实在在的现实中的人类用户。kubectl不会自己去访问,一定是人去发起它去访问的;
  • 第二类用户叫 Pod客户端。人用的账号叫useraccount,Pod去连接apiserver时使用的账号叫serviceaccount。事实上每一个Pod都需要与apiserver打交道,只不过它的权限有大有小而已。默认每一个Pod在运行时,它都会有相关信息的。
1
2
3
4
5
6
7
8
[root@spark32 ~]# kubectl get pods
kubeNAME READY STATUS RESTARTS AGE
myapp-0 1/1 Running 0 2d15h
myapp-1 1/1 Running 0 2d15h
myapp-2 1/1 Running 0 2d15h
myapp-3 1/1 Running 0 2d15h
myapp-4 1/1 Running 0 2d15h
[root@spark32 ~]# kubectl describe pod myapp-0


随便看一个Pod,里面默认就有一个存储卷下面有个default-token,token是令牌,这就是Pod serviceaccount认证时用到认证信息,因为认证信息毕竟是敏感信息,所以通过secret来定义。并以存储卷的形式关联到Pod之上,从而让Pod内运行的应用通过secret中保存的认证信息来连接apiserver,并完成认证的。这就是每一个名称空间中都有一个默认的secret的原因。让名称空间所有的Pod资源试图去联系apiserver时预置的一个认证信息。所以所有Pod都可以连接apiserver。当然这个secret中包含的认证信息仅仅是获取当前Pod自身的相关属性,不能随便看别人的。如果我们想扩展一个Pod,比如有个pod,打算让它去管其他pod的,那我们就必须得自己手动创建一个serviceaccount,并且创建pod时附加这个我们自己定义的serviceaccount。

serviceaccount示例

serviceaccount也属于标准的k8s资源,可以创建一个serviceaccount,创建完以后,然后在定义Pod时,有个spec.serviceAccountName字段可以加载这个我们定义的serviceaccount。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[root@spark32 ~]# kubectl create serviceaccount --help
Create a service account with the specified name.
Aliases:
serviceaccount, sa
Examples:
# Create a new service account named my-service-account
kubectl create serviceaccount my-service-account
Options:
--allow-missing-template-keys=true: If true, ignore any errors in templates when a field or map key is missing in
the template. Only applies to golang and jsonpath output formats.
--dry-run=false: If true, only print the object that would be sent, without sending it.
--generator='serviceaccount/v1': The name of the API generator to use.
-o, --output='': Output format. One of:
json|yaml|name|go-template|go-template-file|template|templatefile|jsonpath|jsonpath-file.
--save-config=false: If true, the configuration of current object will be saved in its annotation. Otherwise, the
annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
--template='': Template string or path to template file to use when -o=go-template, -o=go-template-file. The
template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
--validate=true: If true, use a schema to validate the input before sending it
Usage:
kubectl create serviceaccount NAME [--dry-run] [options]
Use "kubectl options" for a list of global command-line options (applies to all commands).

创建时可以只给个serviceaccount名字,因为serviceaccount本身不带权限,只不过是个账号而已,我们将来可以使用RBAC来实现对这个serviceaccount授予更大的权限。所以授权不属于serviceaccount,我们只不过可以换个专用账号给这个Pod。回头可以给这个专用账号授予更大的权限。肯定不能把权限授予默认的serviceaccount,会导致这个名称空间的所有Pod都会拥有这个serviceaccount所拥有的权限。能认证不代表权限。

1
2
3
4
5
6
7
8
9
[root@spark32 ~]# kubectl create serviceaccount mysa --dry-run
serviceaccount/mysa created (dry run)
You have mail in /var/spool/mail/root
[root@spark32 ~]# kubectl create serviceaccount mysa -o yaml --dry-run
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: null
name: mysa

此前创建每个资源都是自己手动写yaml文件,现在这是快捷方法了。如果某个资源支持在命令行创建,那么可以使用–dry-run这种方式生成一个框架。可以使用输出重定向保存到文件中,拿来改一改就行了。还有一种方式:

1
[root@spark32 ~]# kubectl get pods myapp-0 -o yaml --export

–export:显示的内容比较贴切我们手动写的yaml文件的内容。

1
2
3
4
5
6
[root@spark32 ~]# kubectl create sa admin
serviceaccount/admin created
[root@spark32 ~]# kubectl get sa
NAME SECRETS AGE
admin 1 47s
default 1 152d

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@spark32 manifests]# vim pod-sa-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-sa-demo
namespace: default
labels:
app: myapp
tier: frontend
annotations:
wisedu.com/created-by: "cluster admin"
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
serviceAccountName: admin
[root@spark32 manifests]# kubectl apply -f pod-sa-demo.yaml
pod/pod-sa-demo created
[root@spark32 manifests]# kubectl describe pod pod-sa-demo

【补充】:我们写的资源清单,提交给apiserver时,apiserver告诉kubelet,node节点要创建运行一个Pod,而这个Pod中的容器的启动要依赖于一个私有registry之上的镜像时,认证信息是放到secret中的。然后Pod清单文件中,pods.spec.imagePullSecrets引用secret。但是这种认证方式可能有一些缺陷,因此我们也可以在Pod中不使用imagePullSecrets,而是直接使用serviceAccountName。这个sa账号是可以附带认证到私有registry上的secret信息的。这样子我们在Pod配置文件清单中就不会泄露出去secret到底用的是哪个相关信息了。因为只能看见sa。

上面我们已经看到了serviceaccount可以使用token信息,而token其实就是一串base64编码的子串,它实际上是个域共享密钥。我们系统会自动生成,当然你也可以手动创建。
TLS认证,双向认证无非是双方都配置证书和私钥,而且双方都要认可CA颁发的证书。不过这在k8s上用的证书一般都是私有CA做的证书,而且这个私有CA千万不要轻易授权证书出去,因为做的任何一个证书出去,都可以被人家拿来当做客户端来连接apiserver完成认证。所以这个CA应该是专用CA,不会去做任何其他事情。

kubectl认证

kubectl使用配置文件来认证。
kubectl config –help 用来管理kubectl的配置文件。所有连往apiserver的客户端,在认证时,如果我们要基于配置文件来保存认证信息,而不是刚才看到serviceaccount使用token来认证,我们就应该为它配置一个配置文件。
k8s集群中的所有组件,除了apiserver之外的组件,像controller-manager、Scheduler都想要连入apiserver,都需要被apiserver所认证。所以它们都算的上是apiserver的客户端,包括kubectl。那么这每个组件为了能够连入正确的apiserver,需要提供正确的账号、证书、私钥等认证需要的信息,或者token。我们需要把这些信息保存为一个配置文件。这个配置文件有个专门的称呼,叫kubeconfig。是apiserver的客户端连入apiserver时使用的认证格式的客户端配置文件。kubectl也是这样的客户端,它也有自己的配置文件,可以使用kubectl config view来查看。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@spark32 ~]# kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://172.16.206.32:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED

kubectl的配置文件是 ~/.kube/config。
这个配置文件格式和资源清单文件有点像,解释几个字段:

  • clusters:集群列表。可以有多个集群。
    • certificate-authority-data: REDACTED 认证到这个集群,这个集群发过来的证书用什么方式去检验
    • server: https://172.20.0.70:6443 –集群的apiserver监听的外部地址
  • users:用户列表,可以有多个。
    • certificate-authority-data: REDACTED –客户端证书
    • client-key-data: REDACTED –客户端私钥
  • contents:上下文列表。用哪个账号访问哪个集群。
    列表,每个content还有个name
  • current-content:当前上下文。当前是用哪个账号访问哪个集群的。

这个配置文件不单单是用来访问一个集群的,如果有多个k8s集群,但是只有一台机器作为客户端,一会想访问A集群,一会想访问B集群。为了让一个kubectl能控制多个集群,比如下面有3个集群,每个集群上所用的账号可能是不一样的,所以配置文件中有这么几项配置:

  • 集群列表,A、B、C三个集群
  • 对于每个集群来讲,可能会用到不同的账号,于是有了用户列表。
  • 打算用哪个用户访问哪个集群,假设第一个账号和第二个账号都是访问第一个集群的,而第二个集群和第三个集群的账号都是第三个账号,两个集群有着同一个名字的账号,这是有这种可能性的。因此就需要定义contents了,使用哪个账号访问哪个集群。

使用kubeadm创建集群,它会把当前这个集群初始化的过程中创建多个私有CA,其中有一个CA是跟apiserver相关的。如下:

1
2
3
[root@spark32 ~]# ls /etc/kubernetes/pki/
apiserver.crt apiserver-etcd-client.key apiserver-kubelet-client.crt ca.crt etcd front-proxy-ca.key front-proxy-client.key sa.pub
apiserver-etcd-client.crt apiserver.key apiserver-kubelet-client.key ca.key front-proxy-ca.crt front-proxy-client.crt sa.key

其中ca.crt 和 ca.key。
如果有需要,我们也可以自己用这个ca来签署一个自己自定义的证书和私钥,拿来做认证都没问题。只要是apiserver信任的ca签署的证书,都可以认证连入集群的。
接下来可以来创建自己的账号了,不可以使用这个目录下的其他证书和私钥,主要证书里的CN是用户名,pki下面的证书的里的CN都是已经定义了的名字。这里自做一组证书和私钥,作为另外一个账号去认证到apiserver上的证书文件。
创建的账号不是操作系统账号,而是连接apiserver的账号,需要先创建一个私钥,生成一个签署证书,证书中的证书持有者跟用户的用户名必须保持一致,就是证书的subject。

生成私钥:

1
2
3
4
5
6
[root@spark32 ~]# cd /etc/kubernetes/pki/
[root@spark32 pki]# (umask 077; openssl genrsa -out wisedu.key 2048)
Generating RSA private key, 2048 bit long modulus
.+++
....+++
e is 65537 (0x10001)

生成证书签署请求:

1
[root@spark32 pki]# openssl req -new -key wisedu.key -out wisedu.csr -subj "/CN=wisedu"

使用CA去签署证书:

1
2
3
4
[root@spark32 pki]# openssl x509 -req -in wisedu.csr -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -out wisedu.crt -days 3650
Signature ok
subject=/CN=wisedu
Getting CA Private Key

查看证书内容,以文本输出:

1
[root@spark32 pki]# openssl x509 -in wisedu.crt -text -noout

接下来我们把这个用户账号信息添加到kubectl配置文件中,这个账号是由Kubernetes集群的CA创建的证书,所以认证不会有任何问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
[root@spark32 pki]# kubectl config --help
Modify kubeconfig files using subcommands like "kubectl config set current-context my-context"
The loading order follows these rules:
1. If the --kubeconfig flag is set, then only that file is loaded. The flag may only be set once and no merging takes
place.
2. If $KUBECONFIG environment variable is set, then it is used as a list of paths (normal path delimiting rules for
your system). These paths are merged. When a value is modified, it is modified in the file that defines the stanza. When
a value is created, it is created in the first file that exists. If no files in the chain exist, then it creates the
last file in the list.
3. Otherwise, ${HOME}/.kube/config is used and no merging takes place.
Available Commands:
current-context Displays the current-context
delete-cluster Delete the specified cluster from the kubeconfig
delete-context Delete the specified context from the kubeconfig
get-clusters Display clusters defined in the kubeconfig
get-contexts Describe one or many contexts
rename-context Renames a context from the kubeconfig file.
set Sets an individual value in a kubeconfig file
set-cluster Sets a cluster entry in kubeconfig
set-context Sets a context entry in kubeconfig
set-credentials Sets a user entry in kubeconfig
unset Unsets an individual value in a kubeconfig file
use-context Sets the current-context in a kubeconfig file
view Display merged kubeconfig settings or a specified kubeconfig file
Usage:
kubectl config SUBCOMMAND [options]
Use "kubectl <command> --help" for more information about a given command.
Use "kubectl options" for a list of global command-line options (applies to all commands).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
[root@spark32 pki]# kubectl config set-credentials --help
Sets a user entry in kubeconfig
Specifying a name that already exists will merge new fields on top of existing values.
Client-certificate flags:
--client-certificate=certfile --client-key=keyfile
Bearer token flags:
--token=bearer_token
Basic auth flags:
--username=basic_user --password=basic_password
Bearer token and basic auth are mutually exclusive.
Examples:
# Set only the "client-key" field on the "cluster-admin"
# entry, without touching other values:
kubectl config set-credentials cluster-admin --client-key=~/.kube/admin.key
# Set basic auth for the "cluster-admin" entry
kubectl config set-credentials cluster-admin --username=admin --password=uXFGweU9l35qcif
# Embed client certificate data in the "cluster-admin" entry
kubectl config set-credentials cluster-admin --client-certificate=~/.kube/admin.crt --embed-certs=true
# Enable the Google Compute Platform auth provider for the "cluster-admin" entry
kubectl config set-credentials cluster-admin --auth-provider=gcp
# Enable the OpenID Connect auth provider for the "cluster-admin" entry with additional args
kubectl config set-credentials cluster-admin --auth-provider=oidc --auth-provider-arg=client-id=foo
--auth-provider-arg=client-secret=bar
# Remove the "client-secret" config value for the OpenID Connect auth provider for the "cluster-admin" entry
kubectl config set-credentials cluster-admin --auth-provider=oidc --auth-provider-arg=client-secret-
Options:
--auth-provider='': Auth provider for the user entry in kubeconfig
--auth-provider-arg=[]: 'key=value' arguments for the auth provider
--embed-certs=false: Embed client cert/key for the user entry in kubeconfig
Usage:
kubectl config set-credentials NAME [--client-certificate=path/to/certfile] [--client-key=path/to/keyfile]
[--token=bearer_token] [--username=basic_user] [--password=basic_password] [--auth-provider=provider_name]
[--auth-provider-arg=key=value] [options]
Use "kubectl options" for a list of global command-line options (applies to all commands).


1
2
[root@spark32 pki]# kubectl config set-credentials wisedu --client-certificate=./wisedu.crt --client-key=./wisedu.key --embed-certs=true
User "wisedu" set.

–embed-certs=true 表示把证书隐藏起来。

1
[root@spark32 pki]# kubectl config view

设置个上下文,让wisedu这个用户账号也能访问k8s集群。

1
2
3
[root@spark32 pki]# kubectl config set-context wisedu@kubernetes --cluster=kubernetes --user=wisedu
Context "wisedu@kubernetes" created.
[root@spark32 pki]# kubectl config view

设置当前上下文,即设置使用这个用户wisedu访问集群kubernetes:

1
2
[root@spark32 pki]# kubectl config use-context wisedu@kubernetes
Switched to context "wisedu@kubernetes".

1
2
[root@spark32 pki]# kubectl get pods
Error from server (Forbidden): pods is forbidden: User "wisedu" cannot list resource "pods" in API group "" in the namespace "default"

这个用户可没有管理员权限。
以上少演示了一个步骤,就是添加集群,因为这里只有一个集群。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@spark32 pki]# kubectl config set-cluster --help
Sets a cluster entry in kubeconfig.
Specifying a name that already exists will merge new fields on top of existing values for those fields.
Examples:
# Set only the server field on the e2e cluster entry without touching other values.
kubectl config set-cluster e2e --server=https://1.2.3.4
# Embed certificate authority data for the e2e cluster entry
kubectl config set-cluster e2e --certificate-authority=~/.kube/e2e/kubernetes.ca.crt
# Disable cert checking for the dev cluster entry
kubectl config set-cluster e2e --insecure-skip-tls-verify=true
Options:
--embed-certs=false: embed-certs for the cluster entry in kubeconfig
Usage:
kubectl config set-cluster NAME [--server=server] [--certificate-authority=path/to/certificate/authority]
[--insecure-skip-tls-verify=true] [options]
Use "kubectl options" for a list of global command-line options (applies to all commands).

现在把当前上下文切换回来,使用一个新的配置文件来演示,有一个选项–kubeconfig可以指定配置文件路径。

1
2
[root@spark32 pki]# kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".

设置一个集群:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@spark32 pki]# kubectl config set-cluster mycluster --kubeconfig=/tmp/test.conf --server="https://172.16.206.32:6443" --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true
Cluster "mycluster" set.
You have mail in /var/spool/mail/root
[root@spark32 pki]# kubectl config view --kubeconfig=/tmp/test.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://172.16.206.32:6443
name: mycluster
contexts: []
current-context: ""
kind: Config
preferences: {}
users: []