一、认证
访问k8s时,主要是通过访问apiserver进行操作,所以需要对访问apiserver的用户做认证。如果不做认证那么任何人都可以进行访问k8s,这种情况是非常危险的,所以需要对访问k8s的apiserver的用户进行认证,确保是符合要求的用户。
1.1 访问apiserver的集中认证方式
1.1.1~1.1.2 两种认证方式就是kubectl访问k8s集群,要找一个kubeconfig的文件,基于该文件里的用户访问apiserver,属于是外部访问apiserver的时候使用的方式。
1.1.3 认证方式属于是内部访问pod和apiserver交互时候采用的一种方式。
1.1.1 方式一:客户端认证
可称为双向TSL认证,kubectl访问apiserver的时候,apiserver需要认证kubectl是否符合要求,通常是通过ca根证书进行验证
1.1.2 方式二:Bearertoken
Bearertoken的方式,可以理解为apiserver将一个密码通过了非对称加密的方式告诉了kubectl,然后通过该密码进行相互访问
1.1.3 方式三:ServiceAccount
ServiceAccount(服务账号),创建一个pod,该pod访问k8s集群apiserver时用到的一个用户(就是pod想要访问apiserver时创建的一个ServiceAccount用户并将这个用户绑定到pod中),ServiceAccount包括了namespace、token、ca,他是通过目录的方式挂载给pod的,当pod运行起来的时候就会读取到这些信息,从而使用这种方式和apiserver进行通信。
1.2 kubeconfig文件
在K8S集群当中,当我们使用kubectl操作k8s资源时候,需要确定我们用哪个用户访问哪个k8s集群,kubectl操作k8s集群资源会去/root/.kube目录下找config文件。
可以通过kubectl config view 命令查看config文件配置,如下:
users: //用户信息
- name: kubernetes-admin //用户名称(该用户拥有证书和私钥,说明已经被ca证书签发,可被apiserver信任)
user:
client-certificate-data: DATA+OMITTED //用户证书
client-key-data: DATA+OMITTED //用户私钥
#在使用kubectl时默认找的就是/root/.kube/config文件,该文件中的kubernetes-admin用户就具有k8s集群中的访问和操作资源的权限,
#因为使用kubeadm安装的k8s集权,安装时就默认就对该用户做了rbac授权,拥有了管理员的权限,因此它有操作k8s集群中的权限
clusters:
- cluster: //定义的集群信息
certificate-authority-data: DATA+OMITTED
server: https://192.168.57.131:6443 //apiserver的地址(maser节点的地址)
name: kubernetes //该集群对应的名称
contexts: //上下文(环境)
- context:
cluster: kubernetes //上下文中定义的集群
user: kubernetes-admin //上下文中定义的用户(users则定义了该用户的权限)
name: kubernetes-admin@kubernetes //上下文的名称
current-context: kubernetes-admin@kubernetes //current-context(定义当前上下文):冒号后面定义了上下问的名称,表示当前使用的是哪个上下文。
#上下文(环境)中定义集群的信息即用户的信息,该集群及用户又分别定义了集群的信息及用户的权限。
#总结:使用kubectl时默认找到config配置文件中定义的kubernetes-admin用户,
#该用户通过当前上下文中定义的集群找到192.168.57.131:6443这个apiserver,然后进行操作。
#通过使用 --kubeconfig=“file” 也可以访问当前集群的pod
[root@k8s-master ~]# kubectl get pods --kubeconfig=/root/.kube/config
NAME READY STATUS RESTARTS AGE
pod-05 1/1 Running 0 20h
#将文件拷贝迁移之后验证
[root@k8s-master ~]# cp /root/.kube/config /tmp/
[root@k8s-master ~]# kubectl get pods --kubeconfig=/tmp/config
NAME READY STATUS RESTARTS AGE
pod-05 1/1 Running 0 20h
二、授权
用户经过认证之后,只能仅代表它是一个被apiserver信任的用户,能否访问apiserver,但是用户能否拥有在k8s集权内自由操作资源的权限,还需要进行授权的操作,常见的授权方式有rbac授权。
2.1 授权方式:RBAC
RBAC(基于角色的访问控制机制)将一个用户绑定到一个角色上,授权的时候给角色进行授权,该角色拥有权限,从而让绑定的用户也拥有权限
用户可以是useraccount或者是serviceaccount
2.1.1 绑定方式:用户基于rolebinding绑定到role
用户通过rolebinding绑定到role之后,只需要给role设置权限,那么绑定到role的用户也会有相同的权限,该方式只能限制在一个名称空间中,就是rolebinding和role在哪个名称空间,那么绑定的用户就只对哪个名称空间有权限。创建role有名称空间的限制,需要和rolebinding在一起。
2.2.2 绑定方式:用户基于rolebinding绑定到clusterrole
与role不同的是,创建clusterrole没有名称空间的限制,比如在a和b两个名称空间创建了rolebinding,这两个名称空间都可以绑定clusterrole,然后用户绑定clusterrole之后,用户就可以对a和b两个名称空间都具有操作权限。
2.2.3 绑定方式:clusterrolebindbing绑定到clusterrole
由于clusterrolebinding与clusterrole一样没有名称空间限制,如果用户通过clusterrolebinding绑定到clusterrole上,那么这个用户将对任何名称空间都具有clusterrole授予的权限
2.2.4 绑定方式总结
上面2.2.1绑定方式如果有多个名称空间,每个名称空间的用户都要对自己的名称空间具有管理员的权限,那么需要定义多个role和rolebinding,然后依次绑定,这种方法过于麻烦,所以引入了clusterrole 即2.2.2绑定方式,该方式直接定义一个clusterrole,然后对其授权,用户通过rolebinding绑定clusterrole就能拥有自己名称空间的权限。
PS: rolebinding 仅对当前名称空间具有对应的权限。
而2.2.3绑定方式则用户对任何名称空间都具有授予的管理员权限。
2.2 useraccount及serviceaccount的区别
k8s中账户分为useraccount(用户账号)和serviceaccount(服务账号)两种
useraccount是给k8s集群外部用户使用的,如kubectl访问k8s集群要使用useraccount用户,使用kubeadm安装的k8s默认的useraccount用户是kubernetes-admin
serviceaccount是创建pod时候pod里面所使用的账号,pod容器中的进程如果想要访问k8s中的apiserver那么就需要有一个serviceaccount账号,该账号创建的时候仅局限于所在的名称空间,创建的每一个名称空间都会自动创建一个default service account,如果创建pod的时候没有指定serviceaccount,那么pod则会使用pod所在的那个名称空间中自动生成的serviceaccount账号。
下面则是查看名称空间中自动生成的serviceaccount账号信息。
#创建一个名称空间
[root@k8s-master ~]# kubectl create ns test
namespace/test created
#查看该名称空间的sa账号 (sa是 serviceaccount的缩写)
[root@k8s-master ~]# kubectl get sa -n test
NAME SECRETS AGE
default 0 28s
#测试创建pod时使用的sa账号,创建一个pod的yaml文件
[root@k8s-master ~]# vim pod-01.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-01
namespace: test #指定创建pod所在名称空间
spec:
containers:
- name: my-nginx
image: nginx
imagePullPolicy: IfNotPresent
#创建
[root@k8s-master ~]# kubectl apply -f pod-01.yaml
pod/pod-01 created
[root@k8s-master ~]# kubectl get pods -n test
NAME READY STATUS RESTARTS AGE
pod-01 1/1 Running 0 8s
#查看pod详细信息挂载的sa账号信息
[root@k8s-master ~]# kubectl describe pod pod-01 -n test
Name: pod-01
Namespace: test
Priority: 0
Service Account: default //账号信息见左侧
2.3 serviceaccoun RBAC授权方式
(1)对my-namespace中的my-sa账号授予只读权限(view是系统自带的)
kubectl create rolebinding my-name --clusterrole=view --serviceaccount=my-namespace:my-sa --namespace=my-namespace
(2)为一个命名空间中名为default的Service Account授权
#如果一个应用没有指定 serviceAccount的名称,则会使用名为default的Service Account。注意,赋予Service Account “default”的权限会让所有没有指定serviceAccountName的Pod都具有这些权限
#例如,在my-namespace命名空间中为Service Account“default”授予只读权限:
kubectl create rolebinding my-name --clusterrole=view --serviceaccount=my-namespace:default --namespace=my-namespace
(3)为命名空间中所有Service Account都授予一个角色
#如果希望在一个命名空间中,任何Service Account应用都具有一个角色,则可以为这一命名空间的Service Account群组进行授权
kubectl create rolebinding my-name --clusterrole=view --group=system:serviceaccounts:my-namespace --namespace=my-namespace
(4)为集群范围内所有Service Account都授予一个低权限角色
#如果不想为每个命名空间管理授权,则可以把一个集群级别的角色赋给所有Service Account。
kubectl create clusterrolebinding my-name --clusterrole=view --group=system:serviceaccounts
(5)为所有Service Account授予超级用户权限
kubectl create clusterrolebinding my-name --clusterrole=cluster-admin --group=system:serviceaccounts
(6)在命名空间rbac中为用户es授权admin ClusterRole:
kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=es --namespace=rbac
(7)在命名空间rbac中为名为myapp的Service Account授予view ClusterRole:
kubctl create rolebinding myapp-role-binding --clusterrole=view --serviceaccount=rbac:myapp --namespace=rbac
(8)在全集群范围内为用户root授予cluster-admin ClusterRole:
kubectl create clusterrolebinding cluster-binding --clusterrole=cluster-admin --user=root
(9)在全集群范围内为名为myapp的Service Account授予view ClusterRole:
kubectl create clusterrolebinding service-account-binding --clusterrole=view --serviceaccount=myapp
#rbac授权yaml文件官方文档使用方式:https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/rbac/
2.4 serviceaccount 使用方法
需要创建一个 serviceaccount (缩写 sa)并将其绑定到pod中,并给账号赋予权限,使pod能够有权限访问k8s集群
2.4.1 创建sa及pod
#创建sa
[root@k8s-master ~]# kubectl create sa sa-01
serviceaccount/sa-01 created
[root@k8s-master ~]# kubectl get sa | grep -Ei "sa|name"
NAME SECRETS AGE
sa-01 0 32s
#创建pod 将sa账号绑定到pod中
[root@k8s-master ~]# vim pod-001.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-001
spec:
serviceAccount: sa-01 #指定sa的账号
containers:
- name: mynginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
#创建
[root@k8s-master ~]# kubectl apply -f pod-001.yaml
pod/pod-001 created
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
pod-001 1/1 Running 0 3s
2.4.2 对sa账号授权
进入pod中给sa账号授权
#进入pod容器
[root@k8s-master ~]# kubectl exec -it pod-001 -- /bin/bash
root@pod-001:/# ls /var/run/secrets/kubernetes.io/serviceaccount/
ca.crt namespace token
#创建pod时不管有没有指定sa账号,默认都会在pod中生成这个目录及目录下的这些文件, ca证书及token等。
#测试还未对sa账号授权时pod访问k8s集群
root@pod-001:/# cd /var/run/secrets/kubernetes.io/serviceaccount/
root@pod-001:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)" https://kubernetes/api/v1/namespaces/kube-system
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "namespaces \"kube-system\" is forbidden: User \"system:serviceaccount:default:sa-01\" cannot get resource \"namespaces\" in API group \"\" in the namespace \"kube-system\"",
"reason": "Forbidden",
"details": {
"name": "kube-system",
"kind": "namespaces"
},
"code": 403 //403 未授权无法请求k8s集权
ps: #使用ca.crt证书获取token中的内容去请求访问k8s集群
#kubernetes/api/v1/ //kubernetes是apiserver pod前端的四层代理(kubectl get svc 可以查看到),访问的是api namespace的版本是v1
#namespaces/kube-system //表示访问的是kube-system名称空间
#对sa账号进行rbac授权
#退出容器
root@pod-001:/var/run/secrets/kubernetes.io/serviceaccount# exit
exit
#授权(将sa账号通过clusterrolebinding绑定到clusterrole)
[root@k8s-master ~]# kubectl create clusterrolebinding sa-01-admin --clusterrole=cluster-admin --serviceaccount=default:sa-01
clusterrolebinding.rbac.authorization.k8s.io/sa-01-admin created
ps: #kubectl create clusterrolebinding sa-01-admin //创建的资源类型为 clusterrolebinding,并且给这个绑定起了一个名字 sa-01-admin
#--clusterrole=cluster-admin //指定了要绑定的 ClusterRole 名称为 cluster-admin
#-serviceaccount=default:sa-01 //指定了要授权的 sa账号名称,default 是 sa账号所在的命名空间,sa-01 是 ServiceAccount 的名称。
#授权之后再次测试pod访问k8s集群
[root@k8s-master ~]# kubectl exec -it pod-001 -- /bin/bash
root@pod-001:/# cd /var/run/secrets/kubernetes.io/serviceaccount/
root@pod-001:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)" https://kubernetes/api/v1/namespaces/kube-system
{
"kind": "Namespace",
"apiVersion": "v1",
"metadata": {
"name": "kube-system",
"uid": "0cbb283a-249c-4177-a5a8-6e6921ce7b97",
"resourceVersion": "3",
"creationTimestamp": "2024-03-20T07:09:36Z",
"labels": {
"kubernetes.io/metadata.name": "kube-system"
},
"managedFields": [
{
"manager": "kube-apiserver",
"operation": "Update",
"apiVersion": "v1",
"time": "2024-03-20T07:09:36Z",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:labels": {
".": {},
"f:kubernetes.io/metadata.name": {}
}
}
}
}
]
},
"spec": {
"finalizers": [
"kubernetes"
]
},
"status": {
"phase": "Active" //Active 表示能够访问
}
#也可以访问所有名称空间中的pod
root@pod-001:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)" https://kubernetes/api/v1/pods | more
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0{
"kind": "PodList",
"apiVersion": "v1",
"metadata": {
"resourceVersion": "21323"
},
"items": [
{
"metadata": {
"name": "pod-001",
"namespace": "default",
"uid": "956798c4-61d4-4318-b3c1-8ed130819dd8",
"resourceVersion": "16924",
"creationTimestamp": "2024-07-12T02:01:20Z",
..............
.............
.........
....
..
. (内容省略)
2.5 资源定义及角色(role)绑定
2.5.1 常用的角色(role)资源定义方式
rules: //定义角色信息
- apiGroups: //定义api组 [""] 什么都不写,表示对所有
resources: //定义pod或者控制器
verbs: //定义权限
get
: 读取。list
: 列出。watch
: 监听。create
: 创建。update
: 更新。patch
: 类似于update
,允许使用补丁操作来部分更新资源。delete
: 删除。
(1)允许读取核心API组的Pod资源
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
(2)允许读写apps API组中的deployment资源
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get","list","watch","create","update","patch","delete"]
(3)允许读取Pod以及读写job信息
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
- apiGroups: [""]
resources: ["jobs"]
verbs: ["get","list","watch","create","update","patch","delete"]
(4)允许读取一个名为my-config的ConfigMap(必须绑定到一个RoleBinding来限制到一个Namespace下的ConfigMap):
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["my-configmap"]
verbs: ["get"]
(5)读取核心组的Node资源(Node属于集群级的资源,所以必须存在于ClusterRole中,并使用ClusterRoleBinding进行绑定):
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get","list","watch"]
(6)允许对非资源端点“/healthz”及其所有子路径进行GET和POST操作(必须使用ClusterRole和ClusterRoleBinding):
rules:
- nonResourceURLs: ["/healthz","/healthz/*"]
verbs: ["get","post"]
2.5.2 常用的角色(role)绑定方式
(1)用户名 A
subjects:
- kind: User
name: A
apiGroup: rbac.authorization.k8s.io
(2)组名B
subjects:
- kind: Group
name: B
apiGroup: rbac.authorization.k8s.io
(3)kube-system命名空间中默认Service Account
subjects:
- kind: ServiceAccount
name: default
namespace: kube-system
2.6 pod资源引用方式
如上方2.4~2.4.2. 所示,创建一个完成的pod引用资源过程
#创建名称空间
[root@k8s-master ~]# kubectl create ns test-01
namespace/test-01 created
#在创建的名称空间下创建角色(role)
[root@k8s-master ~]# vim role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: test-01
name: role-01
rules: #定义角色信息
- apiGroups: [""] #定义api的组,空字符串表示核心 API 组
resources: ["pods","pods/log"] #定义对该名称空间中的pod及pod下的log拥有下面verbs字段定义的权限。
verbs: ["get","list","watch"] #读取(get)、监听(watch)和列表(list)权限
#role-01 角色对test-01名称空间下的所有pod及pod的log具有读取(get)、监听(watch)和列表(list)权限
[root@k8s-master ~]# kubectl apply -f role.yaml
role.rbac.authorization.k8s.io/role-01 created
[root@k8s-master ~]# kubectl get role -n test-01
NAME CREATED AT
role-01 2024-07-12T03:23:52Z
#在test-01名称空间下创建sa账号
[root@k8s-master ~]# kubectl create sa sa-01-test -n test-01
serviceaccount/sa-01-test created
#创建rolebonding并将sa账号绑定到role下(对sa账号做rbac授权)
[root@k8s-master ~]# kubectl create rolebinding name-sa -n test-01 --role=role-01 --serviceaccount=test-01:sa-01-test
rolebinding.rbac.authorization.k8s.io/name-sa created
PS: #kubectl create rolebinding name-sa -n test-01 //创建rolebinding并其名称为 name-sa 且指定在test-01名称空间下
#--role=role-01 //指定role的名称(上面创建好的)
#--serviceaccount=test-01:sa-01-test //指定test-01名称空间下sa的账号
#创建pod将sa账号绑定到pod中
[root@k8s-master ~]# cat pod-002.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-002
namespace: test-01
spec:
serviceAccount: sa-01-test #指定sa的账号
containers:
- name: mynginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
[root@k8s-master ~]# kubectl apply -f pod-002.yaml
pod/pod-002 created
[root@k8s-master ~]# kubectl get pods -n test-01
NAME READY STATUS RESTARTS AGE
pod-002 1/1 Running 0 15s
#进入到pod容器中验证权限
[root@k8s-master ~]# kubectl exec -it pod-002 -n test-01 -- /bin/bash
root@pod-002:/# cd /var/run/secrets/kubernetes.io/serviceaccount/
root@pod-002:/var/run/secrets/kubernetes.io/serviceaccount# ls
ca.crt namespace token
#查看test-01 名称空间下的pod信息
ps:#https://kubernetes.default/ //这里因为这个sa的账号在test-01名称空间下并绑定了test-01空间下的rolebonding和role,
//所以只能访问该名称空间的role所拥有的权限,因为该名称空间下的kebernetes的servic在default下,
//通过kubectl describe svc kubernetes | grep -i namespace 进行查看,所以需要加上defuts
root@pod-002:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)" https://kubernetes.default/api/v1/namespaces/test-01/pods/
{
"kind": "PodList",
"apiVersion": "v1",
"metadata": {
"resourceVersion": "16516"
},
"items": [
{
"metadata": {
"name": "pod-002",
"namespace": "test-01",
"uid": "1842b180-02b7-423a-b367-9cbb2caed97e",
"resourceVersion": "16240",
"creationTimestamp": "2024-07-12T05:18:44Z",
"annotations": {
"cni.projectcalico.org/podIP": "10.244.126.2/32",
"cni.projectcalico.org/podIPs": "10.244.126.2/32",
......
....
...
..
. (内容省略)
#查看pod日志
root@pod-002:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)" https://kubernetes.default/api/v1/namespaces/test-01/pods/pod-002/log
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2024/07/12 05:18:45 [notice] 1#1: using the "epoll" event method
2024/07/12 05:18:45 [notice] 1#1: nginx/1.21.5
2024/07/12 05:18:45 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
2024/07/12 05:18:45 [notice] 1#1: OS: Linux 3.10.0-1160.el7.x86_64
2024/07/12 05:18:45 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2024/07/12 05:18:45 [notice] 1#1: start worker processes
2024/07/12 05:18:45 [notice] 1#1: start worker process 31
2024/07/12 05:18:45 [notice] 1#1: start worker process 32
2024/07/12 05:18:45 [notice] 1#1: start worker process 33
2024/07/12 05:18:45 [notice] 1#1: start worker process 34
root@pod-002:/var/run/secrets/kubernetes.io/serviceaccount#
PS:如上过程所示,创建了role 指定了role可以对test-01名称空间下的pod及pod/log 拥有读取(get)、监听(watch)和列表(list)权限
创建的sa账号通过创建的rolebinding绑定到了role上,然后通过创建pod将具有role权限的sa账号绑定到了pod中,
故,进入该pod容器中可以访问test-01名称空间中的pod及pod/log信息。
2.7 限制不同的用户操作k8s集群
2.7.1 限制系统中普通用户操作k8s集群其中一个名称空间
在k8s集群中创建一个名为lucky的用户,让该用户只拥有对k8s集群中的lucky-test名称空间具有操作权限,并创建普通系统账户使之拥有这个lucky用户对k8s集群中的lucky-test名称空间的操作权限
[root@k8s-master ~]# cd /etc/kubernetes/pki/
#生成私钥
[root@k8s-master pki]# (umask 077; openssl genrsa -out lucky.key 2048)
Generating RSA private key, 2048 bit long modulus
......................+++
..........................................................................+++
e is 65537 (0x10001)
#生成证书请求
[root@k8s-master pki]# openssl req -new -key lucky.key -out lucky.csr -subj "/CN=lucky"
#生成证书
[root@k8s-master pki]# openssl x509 -req -in lucky.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out lucky.crt -days 3650
Signature ok
subject=/CN=lucky
Getting CA Private Key
#备份kubecofig文件
[root@k8s-master pki]# cp /root/.kube/config /root/.kube/config.bak
#在kubeconfig文件中添加用户lucky
#创建一个用户lucky并指定lucky.crt证书及lucky.key,创建之后这个用户lucky就会加入到kubeconfig文件中
[root@k8s-master pki]# kubectl config set-credentials lucky --client-certificate=./lucky.crt --client-key=./lucky.key --embed-certs=true
User "lucky" set.
#验证kubeconfig文件中的lucky
[root@k8s-master ~]# kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.57.131: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: DATA+OMITTED
client-key-data: DATA+OMITTED
- name: lucky //用户已添加并指定了证书及key
user:
client-certificate-data: DATA+OMITTED
client-key-data: DATA+OMITTED
#在kubeconfig文件中添加上下文
[root@k8s-master ~]# kubectl config set-context lucky@kubernetes --cluster=kubernetes --user=lucky
Context "lucky@kubernetes" created.
#验证文件中的上下文
[root@k8s-master ~]# kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.57.131:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
- context: //已添加
cluster: kubernetes
user: lucky
name: lucky@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: DATA+OMITTED
client-key-data: DATA+OMITTED
- name: lucky
user:
client-certificate-data: DATA+OMITTED
client-key-data: DATA+OMITTED
#切换账号到lucky,默认没有任何权限
[root@k8s-master ~]# kubectl config use-context lucky@kubernetes
Switched to context "lucky@kubernetes".
#然后kubeconfig文件中的current-context指定的用户就变成了lucky@kubernetes
[root@k8s-master ~]# kubectl config view | grep -i curren
current-context: lucky@kubernetes
#验证权限(切换用户后,只是被api信任,但没有授权所以没有权限无法访问k8s集群)
[root@k8s-master ~]# kubectl get pods
Error from server (Forbidden): pods is forbidden: User "lucky" cannot list resource "pods" in API group "" in the namespace "default"
#切换回去
[root@k8s-master ~]# kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".
[root@k8s-master ~]# kubectl config view | grep -i curren
current-context: kubernetes-admin@kubernetes
[root@k8s-master ~]# kubectl get ns
NAME STATUS AGE
default Active 114d
kube-node-lease Active 114d
kube-public Active 114d
kube-system Active 114d
#切回之后为lucky用户授权
#在lucky-test名称空间下创建 rolebinding 将lucky用户通过创建lucky-test名称空间下的rolebinding绑定到cluster-admin(clusterrole)上
#lucky绑定到 cluster-admin之后就拥有了对lucky-test名称空间下的权限。
[root@k8s-master ~]# kubectl create ns lucky-test
namespace/lucky-test created
[root@k8s-master ~]# kubectl create rolebinding lucky -n lucky-test --clusterrole=cluster-admin --user=lucky
rolebinding.rbac.authorization.k8s.io/lucky created
#再次切换用户到lucky下,使用kubectl命令时需要指定名称空间,看其他空间没权限
[root@k8s-master ~]# kubectl config use-context lucky@kubernetes
Switched to context "lucky@kubernetes".
[root@k8s-master ~]# kubectl config view | grep -i curren
current-context: lucky@kubernetes
[root@k8s-master ~]# kubectl get pods
Error from server (Forbidden): pods is forbidden: User "lucky" cannot list resource "pods" in API group "" in the namespace "default"
[root@k8s-master ~]# kubectl get pods -n lucky-test
No resources found in lucky-test namespace.
#验证在lucky-test名称空间下创建测试的sa账号
[root@k8s-master ~]# kubectl create sa sa-test -n lucky-test
serviceaccount/sa-test created
[root@k8s-master ~]# kubectl get sa -n lucky-test
NAME SECRETS AGE
default 0 6m50s
sa-test 0 11s
#创建系统普通账户test,使之拥有lucky的权限
#创建普通账户 设置密码
[root@k8s-master ~]# useradd test
[root@k8s-master ~]# echo test:'123456' | chpasswd
#修改k8s集群中的kubeconfig文件,使文件中只保留lucky账户的信息
[root@k8s-master ~]# mkdir test
[root@k8s-master ~]# cp -ar /root/.kube /root/test/
#进入到拷贝的新文件中修改文件,将kubernetes-admin相关的删除,只留lucky用户
#删除后大概保留内容如下图所示:
[root@k8s-master ~]# vim /root/test/.kube/config
#将修改后的文件连同整个kube目录传到普通用户test的家路径下并修改权限
[root@k8s-master ~]# cp -ar /root/test/.kube /home/test/
[root@k8s-master ~]# chown -R test:test /home/test/
#切换到test用户上进行访问k8s集群
[root@k8s-master ~]# su - test
[test@k8s-master ~]$ kubectl get pods
Error from server (Forbidden): pods is forbidden: User "lucky" cannot list resource "pods" in API group "" in the namespace "default"
[test@k8s-master ~]$ kubectl get pods -n lucky-test
No resources found in lucky-test namespace.
[test@k8s-master ~]$ kubectl get sa -n lucky-test
NAME SECRETS AGE
default 0 37m
sa-test 0 30m
#这样系统中的普通用户就能使用k8s集群中只对某一名称空间有操作权限的用户进行使用了。
PS: 关于kubeconfig文件内容详情说明可参考上面标题 1.2
2.7.2 限制系统中普通用户查看k8s集群所有名称空间的pod权限
#切换回k8s用户
[root@k8s-master pki]# kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".
[root@k8s-master ~]# cd /etc/kubernetes/pki/
#生成私钥 lucky01.key
[root@k8s-master pki]# (umask 077; openssl genrsa -out lucky01.key 2048)
Generating RSA private key, 2048 bit long modulus
...................................................................................................................................................................+++
............................+++
e is 65537 (0x10001)
#基于lucky01.key生成证书请求文件lucky01.csr,用户是lucky0002
[root@k8s-master pki]# openssl req -new -key lucky01.key -out lucky01.csr -subj "/CN=lucky0002"
#基于lucky01.csr ca.crt ca.key生成证书lucky01.crt
[root@k8s-master pki]# openssl x509 -req -in lucky01.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out lucky01.crt -days 3650
Signature ok
subject=/CN=lucky0002
Getting CA Private Key
#在kubeconfig文件中添加用户lucky0002
#创建set-credentials并指定用户lucky0002使用生成的lucky01.crt lucky01.key使该用户被apiserver信任
[root@k8s-master pki]# kubectl config set-credentials lucky0002 --client-certificate=./lucky01.crt --client-key=./lucky01.key --embed-certs=true
User "lucky0002" set.
#在kubeconfig文件中添加用户lucky0002上下文
[root@k8s-master pki]# kubectl config set-context lucky0002@kubernetes --cluster=kubernetes --user=lucky0002
Context "lucky222@kubernetes" created.
#创建clusterrole
[root@k8s-master pki]# vi /root/clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: lucky0002-pod-01
rules: #定义权限,对所有名称空前的pod具有查看权限
- apiGroups: [""] #所有名称空间
resources: ["pods"] #目标pod
verbs: ["get", "list", "watch"] #查看权限
[root@k8s-master pki]# kubectl apply -f /root/clusterrole.yaml
clusterrole.rbac.authorization.k8s.io/lucky0002-pod-01 created
[root@k8s-master pki]# kubectl get clusterrole | grep 0002
lucky0002-pod-01
#创建clusterrolebinding并将lucky0002用户通过clusterrolebinding绑定到clusterrole上
#绑定之后已被apiserver信任的lucky0002用户就拥有了clusterrole这个lucky0002-pod-01用户的权限,可以对集群内所有名称空间的pod拥有查看权限
[root@k8s-master pki]# kubectl create clusterrolebinding lucky0002-pod-02 --clusterrole=lucky0002-pod-01 --user=lucky0002
clusterrolebinding.rbac.authorization.k8s.io/lucky0002-pod-02 created
#创建一个普通用户进行切换测试
[root@k8s-master pki]# useradd test001
[root@k8s-master pki]# echo test001:'123456'|chpasswd
#拷贝kubeconfig配置文件并修改文件中删除所有用户相关信息,只保留lucky0002的信息
[root@k8s-master pki]# mkdir /root/test001
[root@k8s-master pki]# cp -ar /root/.kube/ /root/test001/
#修改文件中删除所有用户相关信息,只保留lucky0002的信息,参考上方图片
[root@k8s-master pki]# vim /root/test001/.kube/config
#还需要修改配置文件的current-context用户
[root@k8s-master pki]# cat /root/test001/.kube/config | grep current
current-context: lucky0002@kubernetes
#拷贝修改好的kubeconfig文件至test001用户的家目录下并赋予权限
[root@k8s-master pki]# cp -ar /root/test001/.kube /home/test001/
[root@k8s-master pki]# chown -R test001:test001 /home/test001/
#切换到 test001 用户
[root@k8s-master pki]# su - test001
#验证集群名称空间pod查看权限(只能查看pod,查看名称空间或这servic都没有权限)
[test001@k8s-master ~]$ kubectl get ns
Error from server (Forbidden): namespaces is forbidden: User "lucky0002" cannot list resource "namespaces" in API group "" at the cluster scope
[test001@k8s-master ~]$ kubectl get svc
Error from server (Forbidden): services is forbidden: User "lucky0002" cannot list resource "services" in API group "" in the namespace "default"
[test001@k8s-master ~]$ kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS
kube-system calico-kube-controllers-6744f6b6d5-2p7nh 1/1 Running 0
kube-system calico-node-cjx7d 1/1 Running 0
kube-system calico-node-j4f5g 1/1 Running 0
kube-system calico-node-qtbn6 1/1 Running 0
kube-system coredns-7f8cbcb969-9h9b2 1/1 Running 0
kube-system coredns-7f8cbcb969-wklp5 1/1 Running 0
kube-system etcd-k8s-master 1/1 Running 0
kube-system kube-apiserver-k8s-master 1/1 Running 0
kube-system kube-controller-manager-k8s-master 1/1 Running 0
kube-system kube-proxy-2rntj 1/1 Running 0
kube-system kube-proxy-7pphs 1/1 Running 0
kube-system kube-proxy-s2fb6 1/1 Running 0
kube-system kube-scheduler-k8s-master 1/1 Running 0
三、准入控制
当用户经过了认证和授权之后,最后一步就是准入控制,也就是准入控制器,经过准入控制器之后可以让它做变更和验证,之所以要使用准入控制器是因为,如果创建pod时定义了资源的上下限,但是不满足LimitRange(名称空间的资源上下限),那么LimitRange就会拒绝创建pod。比如名称空间设置了cpu使用是4核,内存是100G,创建pod时定义使用的是cpu5核,120G内存,那么超出了名称空间定义的上下限,pod将无法创建。
3.1 准入控制插件介绍
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction
在k8s上准入控制器的模块有很多,其中比较常用的有LimitRanger、ResourceQuota、ServiceAccount
如果使用的是kubeadm安装的k8s可以通过/etc/kubernetes/manifests/kube-apiserver.yaml 该文件查看或修改当前k8s使用的准入控制器
如下图所示,当前使用的的是NodeRestriction,如果什么都不写的话,默认启用的是LimitRanger、ResourceQuota、ServiceAccount,当前虽然没有指定这三个插件,但是也默认是开启的。
如果定义多个的话可以使用逗号进行分割如下:
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction
修改配置文件之后 需要重启kubelet (systemctl restart kubelet)
3.2 ResourceQuota准入控制器
它是k8s集群中内置的准入控制器,默认是启用状态,主要作用是用来限制一个名称空间下的资源使用,能防止在一个空间下创建的pod过多时,导致过多的占用k8s资源。
3.2.1 限制cpu、内存、pod、deployment数量
#创建名称空间
[root@k8s-master ~]# kubectl create ns test
namespace/test created
#创建ResourceQuota资源
[root@k8s-master ~]# vim rq.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: rq-01
namespace: test
spec:
hard:
pods: "4" #定义创建pod不能超过4个
requests.cpu: "2" #所有Pods请求的CPU总和不能超过2个单位(假设是2核)
requests.memory: 2Gi #所有Pods请求的memory总和不能超过2GiB
limits.cpu: "4" #所有Pods的CPU限制总和不能超过4个单位
limits.memory: 10Gi #所有Pods的memory限制总和不能超过10GiB
count/deployments.apps: "4" #定义创建的deploymen资源不能超过4个
persistentvolumeclaims: "4" #定义创建的pvc不能超过4个
[root@k8s-master ~]# kubectl apply -f rq.yaml
resourcequota/rq-01 created
#查看详细配置
[root@k8s-master ~]# kubectl describe quota -n test
Name: rq-01
Namespace: test
Resource Used Hard
-------- ---- ----
count/deployments.apps 0 4
limits.cpu 0 4
limits.memory 0 10Gi
persistentvolumeclaims 0 4
pods 0 4
requests.cpu 0 2
requests.memory 0 2Gi
#测试在test名称空间下创建超过定义数量的deploymen资源
[root@k8s-master ~]# vim dep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: dep
namespace: test
spec:
replicas: 5 #创建5个pod
selector:
matchLabels:
a01: b01
template:
metadata:
labels:
a01: b01
spec:
containers:
- name: mynginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
resources:
requests:
cpu: 1
memory: 1G
limits:
cpu: 1
memory: 1G
[root@k8s-master ~]# kubectl apply -f dep.yaml
deployment.apps/dep created
#由于限制了请求上限为两个cpu 定义的是创建5个pod,每个pod1个cpu,所以只创建完成了俩个pod
[root@k8s-master ~]# kubectl get deploy -n test
NAME READY UP-TO-DATE AVAILABLE AGE
dep 2/5 2 2 10s
[root@k8s-master ~]# kubectl get pods -n test
NAME READY STATUS RESTARTS AGE
dep-5454f6b78d-qs7k2 1/1 Running 0 2m11s
dep-5454f6b78d-rjs49 1/1 Running 0 2m11s
PS:定义的规则只要有一个不满足就无法创建完成。
3.2.2 限制存储空间的yaml文件配置方式
[root@k8s-master ~]# vim rq-2.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: rq-02
namespace: test
spec:
hard:
requests.storage: "5Gi" #(PVC)请求的存储总量不能超过5GiB
persistentvolumeclaims: "5" #在test命名空间中,最多允许存在5个PersistentVolumeClaim对象
requests.ephemeral-storage: "1Gi" #所有Pod请求的临时存储(Ephemeral Storage)总量不能超过1GiB
limits.ephemeral-storage: "2Gi" #所有Pod设置的临时存储(Ephemeral Storage)限制总量不能超过2GiB
[root@k8s-master ~]# kubectl apply -f rq-2.yaml
resourcequota/rq-02 created
[root@k8s-master ~]# kubectl describe quota rq-02 -n test
Name: rq-02
Namespace: test
Resource Used Hard
-------- ---- ----
limits.ephemeral-storage 0 2Gi
persistentvolumeclaims 0 5
requests.ephemeral-storage 0 1Gi
requests.storage 0 5Gi
3.3 LimitRanger准入控制器
它是k8s集群中内置的准入控制器,是k8s上的一个标准资源,主要用来定义某个名称空间下限制pod或pod里容器对k8s上的cpu和内存的资源使用。
它不仅可以定义pod及pod容器中创建时的使用资源上下限,还能定义默认上下限,默认上下限是指,在创建pod时,如没有定义使用的资源上下限,那么将会使用LimitRanger定义的默认上下限,而不会像ResourceQuota一样在不定义pod的上下限时,无法进行创建pod。它还可以限制单独的一个pod的资源上下限。
#创建名称空间lr
[root@k8s-master ~]# kubectl create ns lr
namespace/lr created
#创建LimitRanger的yaml文件
[root@k8s-master ~]# vim lr.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: lr-01
namespace: lr
spec:
limits:
- default: #定义默认限制 cpu 1核 1000兆内存(在创建pod时没有定义限制默认使用改值)
cpu: 1000m
memory: 1000Mi
defaultRequest: #定义默认限制 cpu 0.5核 500兆内存(在创建pod时没有定义限制默认使用改值)
cpu: 500m
memory: 500Mi
min: #不能小于0.5核cpu 500兆内存 (创建pod时定义了限制时使用该值)
cpu: 500m
memory: 500Mi
max: #不能大于2核cpu 2000兆内存 (创建pod时定义了限制时使用该值)
cpu: 2000m
memory: 2000Mi
maxLimitRequestRatio: #定义资源限制和请求之间的最大比例关系
cpu: 4 #设置为4,那么容器的CPU上下限制不能超过其CPU请求的4倍,内存上下限制也不能超过其内存请求的4倍
memory: 4
type: Container #限制的容器的层级
[root@k8s-master ~]# kubectl apply -f lr.yaml
limitrange/lr-01 created
#创建pod(这里不定义资源限制,那么该pod就会使用LimitRange定义的默认的资源限制)
[root@k8s-master ~]# vim pod-01.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-01
namespace: lr
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
[root@k8s-master ~]# kubectl apply -f pod-01.yaml
pod/pod-01 created
#验证查看使用的资源限制(如上方LimitRange定义的默认的资源限制一致)
[root@k8s-master ~]# kubectl describe pods pod-01 -n lr | grep -A 5 Limits
Limits:
cpu: 1
memory: 1000Mi
Requests:
cpu: 500m
memory: 500Mi
#创建第二个pod yaml文件中指定资源使用低于限制看是否能创建
[root@k8s-master ~]# vim pod-02.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-02
namespace: lr
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: nginx
resources:
requests:
cpu: 100m #指定使用cpu 100豪核(定义的最小要使用500豪核)
#创建失败
[root@k8s-master ~]# kubectl apply -f pod-02.yaml
Error from server (Forbidden): error when creating "pod-02.yaml": pods "pod-02" is forbidden: [minimum cpu usage per Container is 500m, but request is 100m, cpu max limit to request ratio per Container is 4, but provided ratio is 10.000000]
#修改为范围内的使用资源 (定义的范围内的cpu: 500m -- 2000m)
[root@k8s-master ~]# cat pod-02.yaml | grep cpu
cpu: 1000m
#再次创建(创建成功)
[root@k8s-master ~]# kubectl apply -f pod-02.yaml
pod/pod-02 created
[root@k8s-master ~]# kubectl describe pod pod-02 -n lr | grep -A 5 Limits
Limits:
cpu: 1
memory: 1000Mi //指定的是1000m 其他未指定的还是使用的默认的。
Requests:
cpu: 1
memory: 500Mi
标签:kubectl,认证,master,准入,test,pod,k8s,root
From: https://blog.51cto.com/cyfang/11999130