11 . KubernetesRBAC认证及ServiceAccount、Dashboard
简介
简介摘自Kubernetes权威指南
RBAC(Role-Based Access Control,基于角色的访问控制)在Kubernetes的1.5版本中引入,在1.6版本时升级为Beta版本,在1.8版本时升级为GA。作为kubeadm安装方式的默认选项,足见其重要程度。相对于其他访问控制方式,新的RBAC具有如下优势。
◎ 对集群中的资源和非资源权限均有完整的覆盖。
◎ 整个RBAC完全由几个API对象完成,同其他API对象一样,可以用kubectl或API进行操作”
◎ 可以在运行时调整,无须重新启动API Server
# 要想使用RBAC授权模式,需要在API Server的启动参数加上--authorization-mode=RBAC.
Kubernetes RBAC角色权限控制
RBAC是基于角色的访问控制 (Role-Based Access Control) 在RBAC中,权限与角色相关联。Kubernetes 基于角色的访问控制使用rbac.authorization.k8s.io API组来实现权限控制,RBAC允许管理员通过Kubernetes API动态的配置权限策略。如果需要开启RBAC授权需要在apiserver组件中指定--authorization-mode=Node,RBAC
ServiceAccount
什么是service account? 顾名思义,相对于user account(比如:kubectl访问APIServer时用的就是user account),service account就是Pod中的Process用于访问Kubernetes API的account,它为Pod中的Process提供了一种身份标识。相比于user account的全局性权限,service account更适合一些轻量级的task,更聚焦于授权给某些特定Pod中的Process所使用。
Dashboard
Dashboard 是基于网页的 Kubernetes 用户界面。您可以使用 Dashboard 将容器应用部署到 Kubernetes 集群中,也可以对容器应用排错,还能管理集群本身及其附属资源。您可以使用 Dashboard 获取运行在集群中的应用的概览信息,也可以创建或者修改 Kubernetes 资源(如 Deployment,Job,DaemonSet 等等)。例如,您可以对 Deployment 实现弹性伸缩、发起滚动升级、重启 Pod 或者使用向导创建新的应用。
Kubernetes RBAC
在Kubernetes中所有的API对象都保存在ETCD里,可是,对这些API对象的操作,却一定是通过访问kube-apiserver实现的。我们需要APIServer来帮助我们授权工作,而在Kubernetes项目中,负责完成授权(Authorization)的工作机制就是RBAC: 基于角色的访问控制 (Role-Based Access Control)
RBAC是基于角色的访问控制 (Role-Based Access Control) 在RBAC中,权限与角色相关联。Kubernetes 基于角色的访问控制使用
rbac.authorization.k8s.io
API组来实现权限控制,RBAC允许管理员通过Kubernetes API动态的配置权限策略。如果需要开启RBAC授权需要在apiserver组件中指定--authorization-mode=Node,RBAC
修改完毕后需要重启apiserver,在我提供的二进制安装已经将下面参数添加进去。如果使用的是kubeadm安装在1.6版本默认已经启用了RBAC
RBAC API对象
Kubernetes有一个很基本的特性就是它的所有资源都是模型化的API对象,允许执行CRUD(Create、Read、Update、Delete)操作。资源如下
# Pods
# ConfigMaps
# Deployments
# Nodes
# Secrets
# Namespaces
# 资源对象可能存在的操作有如下
# create
# get
# delete
# list
# update
# edit
# watch
# exec
# 这些资源和API Group进行关联,比如Pods属于Core API Group,而Deployment属于apps API Group,
# 要在kubernetes中进行RBAC授权
RBAC概念
RBAC引入了4个新的顶级资源对象: Role, ClusterRole,RoleBinding和ClusterRoleBinding. 同其他API资源对象一样,用户可以使用kubectl 或者API调用等方式操作这些资源对象.
我们首先要明确下面三个概念
# Role: 角色,它定义了一组规则,定义了一组对Kubernetes API对象的操作权限
# Subject: 被作用者,既可以是”人”,也可以是机器,
# 当然也可以是我们Kubernetes中定义的用户(ServiceAccount主要负责kubernetes内置用户)
# RoleBinding: 定义了”被作用者”和”角色”的绑定关系
角色(Role)
一个角色就是一组权限的集合,这里的权限都是许可形式的,不存在拒绝的规则,在一个命名空间中,可以用角色来定义一个角色,如果是集群级别的,就需要使用ClusterRole了.
角色只能对命名空间内的资源进行授权,在下面例子中定义的角色具备读取Pod的权限:
实际上, Role 本身就是一个kubernetes的API对象,定义文件如下:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: test
name: test-role
rules:
- apiGroups: [""] # ""空字符串,表示核心API群
resources: ["pods"]
verbs: ["get", "watch", "list"]
文件解释
# 首先,Role对象指定了它能产生作用的Namespace(mynamespace)。# Namespace是kubernetes项目中的一个逻辑管理单位。不同Namespace的API对象,
# 在通过kubectl命令进行操作的时候,是互相隔离的
# namespace并不会提供任何实际的隔离或者多租户能力,如果没有设置namespace默认则是default
# apiGroups: 支持的API组列表,例如"“apiVersion: batch/v1”“apiVersion: extensions:v1beta1”“apiVersion: apps/v1beta1”等”
# resources: 支持的资源对象列表,例如Pods,deployments,jobs等
# verbs: 对资源对象的操作方法列表,例如get,watch,list,delete,replace,patch等
# rules字段定义它的是权限规则,这条规则的含义就是允许"被作用者" ,对namespace下面Pod(resources中定义)有哪些权限;
# 用户的权限对应的API资源对象已经创建了,但是还没有绑定,也就是只有一个规则没有规定哪些用户有这个权限
集群角色(ClusterRole)
对于某一个role想要作用的namespace的时候,就必须需要使用ClusterRole和ClusterRoleBinding两个组合。这两个API 对象的用法跟Role和Rolebinding完全一样
集群角色除了具有和角色一致的命名空间内资源的管理能力,因其集群级别的范围,还可以用于以下特殊元素的授权.
# 集群范围的资源,例如Node.
# 非资源型的路径, 例如"/ealthz"
# 包含全部命名空间的资源,例如Pods(用于kubectl get pods --all-namespaces这样的操作授权)
# 下面的集群角色可以让用户有权访问任意一个或所有命名空间的secrets(视其绑定方式而定)
Example
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
# ClusterRole 不受限于命名空间,所以无需设置namespace的名称
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: example-clusterrolebinding
subjects:
- kind: User
name: example-user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: example-clusterrole
apiGroup: rbac.authorization.k8s.io
在上面的例子中,ClusterRole和ClusterRoleBinding的组合,意味着名叫example-user的用户,拥有对所有namespace里的Pod进行Get、Watch、List操作的权限。
类似的,Role对象的rules字段也可以进一步细化,可以只针对某一个具体权限对象进行设置
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["my-config"]
verbs: ["get"]
上面的例子表示,这条规则的”被作用者”,只对my-config的configmap对象有权限进行get操作
前面也说过,在Kubernetes中已经内置了很多个位系统保留的ClusterRole,它们的名字都是以system:开头。一般来说,这些内置的ClusterRole,是绑定给Kubernetes系统组件对应的ServiceAccount使用
#我们可以通过下面的命令获取到
[root@master ~]# kubectl get clusterroles
此外,kubernetes还提供了预先定义好的ClusterRole来提供用户直接使用
cluster-admin
admin
edit
view
# 我们可以通过下面的命令查看clusterrole的权限
[root@master ~]# kubectl describe clusterrole cluster-admin -n kube-system
Name: cluster-admin
Labels: kubernetes.io/bootstrapping=rbac-defaults
Annotations: rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
*.* [] [] [*]
[*] [] [*]
(角色绑定)Rolebinding和集群角色绑定(ClusterRoleBinding)
角色绑定或集群角色绑定用来把一个角色绑定到一个目标上,绑定目标可以是User(用户)、Group(组)或者Service Account。使用RoleBinding为某个命名空间授权,使用ClusterRoleBinding为集群范围内授权。
RoleBinding可以引用Role进行授权。下面的例子中的RoleBinding将在default命名空间中把pod-reader角色授予用户jane,这一操作可以让jane读取default命名空间中的Pod:
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: example-rolebinding
namespace: default
subjects:
- kind: User
name: youmen
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: example-role
apiGroup: rbac.authorization.k8s.io
在Rolebinding中定义了一个subject字段,即”被作用者”。它的类型是User,即Kubernetes里的用户,名称为youmen
在kubernetes里的User,也就是用户,只是一个授权系统里的逻辑概念。它需要通过外部认证服务,比如Keystone,来提供。或者直接给APIServer指定一个用户名、密码文件。那么kubernetes的授权系统就能够从这个文件里找到对象的用户.
Rolebinding对象通过roleRef字段可以直接通过名字,来引用前面定义的Role对象(example-role),从而定义了”被作用者(Subject)”和”角色(Role)”之间的绑定关系
Role和RoleBinding 他们的权限限制规则仅仅在他们自己的namespace内有效,roleRef也只能引用当前namespace里的Role对象
“RoleBinding也可以引用ClusterRole,对属于同一命名空间内ClusterRole定义的资源主体进行授权。一种常见的做法是集群管理员为集群范围预先定义好一组ClusterRole,然后在多个命名空间中重复使用这些ClusterRole。
例如,在下面的例子中,虽然secret-reader是一个集群角色,但是因为使用了RoleBinding,所以dave只能读取development命名空间中的secret
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-secrets
namespace: development
# 集群角色中,只有development命名空间的权限才能赋予davesubjects
subjects:
- kind: User
name: dave
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
对资源的引用方式
多数资源可以用其名称的字符串来表达,也就是Endpoint中的URL相对路径,例如pods。然而,某些Kubernetes API包含下级资源,例如Pod的日志(logs)。Pod日志的Endpoint是GET/ api/v1/namespaces/{namespace}/pods/{name}/log。
在这个例子中,Pod是一个命名空间内的资源,log就是一个下级资源。要在一个RBAC角色中体现,就需要用斜线“/”来分隔资源和下级资源。若想授权让某个主体同时能够读取Pod和Pod log,则可以配置resources为一个数组
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: test
name: test-role
rules:
- apiGroups: [""] # ""空字符串,表示核心API群
resources: ["pods","pods/log"]
verbs: ["get", "watch", "list"]
资源还可以通过名称(ResourceName)进行引用,在指定ResourceName后,使用get,delete,update和patch动词的请求,就会被限制在这个资源实例范围内,例如,下面,下面的声明让一个主体只能对一个ConFigmap进行get和update操作
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: test
name: test-role
rules:
- apiGroups: [""] # ""空字符串,表示核心API群
resources: ["configmap]
verbs: ["get", "watch", "list"]
可想而知,resourceName这种用法对list,watch,create或deletecollection的操作是无效的,这是因为必须要通过URL进行授权,而资源名称在list,watch,create或deletecollection请求中只是请求Body数据的一部分.
常见角色实例
我们先创建一个角色
[root@master serviceaccount]# cat read-pods.yaml
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-pods
namespace: test
subjects:
- kind: User
name: youmen
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pods-reader
apiGroup: rbac.authorization.k8s.io
[root@master serviceaccount]# cat pods-reader.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: test
name: pods-reader
rules:
- apiGroups: [""]
resources: ["pods","pods/log"]
verbs: ["get","list","watch"]
[root@master serviceaccount]# kubectl get roles -n test
NAME CREATED AT
pods-reader 2020-07-04T09:21:50Z
允许读取核心API组中的Pod资源
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
允许读写extensions和apps两个API组中的deployment资源
rules:
- apiGroups: ["extensions","apps"]
resources: ["deployments"]
verbs: ["get","list","watch","create","update","pathch","delete"]
允许读取Pods及读写Jobs
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
- apiGroups: ["batch","extensions"]
resources: ["jobs"]
verbs: ["get","list","watch","create","update","pathch","delete"]
允许读取一个名为my-config的ConfigMap(必须绑定到一个RoleBinding来限制到一个Namespace下的ConfigMap)
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["my-config"]
verbs: ["get"]
常用角色绑定示例
注意,下面例子只包含subjects部分内容
用户名alice@example.com
subjects:
- kind: User
name: "alice@example.com"
apiGroup: rbac.authorization.k8s.io
组名frontend-admins
subjects:
- kind: Group
name: "frontend-admins"
apiGroup: rbac.authorization.k8s.io
kube-system命名空间中的默认Service Account
subjects:
- kind: ServiceAccount
name: default
namespace: kube-system
所有Service Account
subjects:
- kind: Group
name: system:serviceaccounts
apiGroup: rbac.authorization.k8s.io
所有认证用户和未认证用户
# 认证用户
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
# 未认证用户
subjects:
- kind: Group
name: system:unauthenticated
apiGroup: rbac.authorization.k8s.io
ServiceAccount
ServiceAccount主要负责kubernetes内置用户,下面简单定义一个ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: mynamespace
name: example-sa
我们定义了一个ServerAccount对象,只需要name以及namespace最基础字段就可以,然后通过编写rolebinding的yaml文件,来为这个ServiceAccount分配权限
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: example-rolebinding
namespace: mynamespace
subjects:
- kind: ServiceAccount
name: example-sa
namespace: mynamespace
roleRef:
kind: Role
name: example-role
apiGroup: rbac.authorization.k8s.io
在Rolebinding对象里,subject字段的类型(kind),不在是一个User,而是一个名叫example-sa的ServerAccount。而roleRef引用的Role对象,依然名叫example-role。也就是我们上面定义的;
Example
[root@master rbac]# cat namespace.yaml
---
apiVersion: v1
kind: Namespace
metadata:
name: test
labels:
name: test
[root@master rbac]# cat pod-sa.yaml
apiVersion: v1
kind: Pod
metadata:
namespace: test
name: test
spec:
containers:
- name: nginx
image: daocloud.io/library/nginx
serviceAccountName: test
APIServer是整个访问请求进入的网关接口,认证用于实现身份识别,授权用于权限检查.
K8s有两类账号
# 一种是用户账号user,一般是现实中人使用账号
# 第二种是service账号,服务账号,Pod运行在K8s集群上,想访问K8s集群APIServer里面要用到的认证信息,账号密码等.
API
Request path
http://localhost:6443/apis/apps/v1/namespaces/defaults/myapp-deplyoy/
HTTP requests verb:
get,post,put,delete
API requets verb:
get,list,create,update,patch,watch,proxy,redirect,delete,deletecollection
Resource:
Subresource:
Namespace
API group
创建Serviceaccount
快速创建一个yaml框架
kubectl create serviceaccount mysa -o yaml --dry-run > serviceaccount.yaml
kubectl get pods nginx-deployment-5dcb7cf7db-mjlsq -o yaml --export
创建ServiceAccount
kubectl create serviceaccount admin
kubectl get sa
NAME SECRETS AGE
admin 1 4s
default 1 4d8h
mysa 1 3m45s
# 这些认证不一定等于授权
kubectl get secret
NAME TYPE DATA AGE
admin-token-9sxbn kubernetes.io/service-account-token 3 35s
default-token-kr5s2 kubernetes.io/service-account-token 3 4d8h
mysa-token-rg974 kubernetes.io/service-account-token 3 4m16s
cat pod-demo1.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-sa-demo
namespace: default
labels:
app: myapp
tier: frontend
annotations:
youmen.com/create-by: "youmen admin"
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
kubectl describe pod pod-sa-demo |grep token
/var/run/secrets/kubernetes.io/serviceaccount from admin-token-9sxbn (ro)
admin-token-9sxbn:
SecretName: admin-token-9sxbn
Serviceaccount认证
我们正常敲kubectl get pods时候有哪些认证
kubectl config view
apiVersion: v1
clusters: # 集群列表
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.78.7: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
创建自己的一个用户
cd /etc/kubernetes/pki/
# 创建私钥
(umask 077;openssl genrsa -out youmen.key 2048)
openssl req -new -key youmen.key -out youmen.csr -subj "/CN=youmen"
openssl x509 -req -in youmen.csr -CA ./ca.crt \
-CAkey ./ca.key -CAcreateserial -out youmen.crt -days 365
openssl x509 -in youmen.crt -text -noout
Certificate:
Data:
Version: 1 (0x0)
Serial Number:
e6:1c:db:0b:a5:ca:01:db
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=kubernetes
Validity
Not Before: Dec 25 15:35:54 2019 GMT
Not After : Dec 24 15:35:54 2020 GMT
Subject: CN=youmen
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
kubectl config set-credentials youmen --client-certificate=./youmen.crt --client-key=./youmen.key --embed-certs=true
kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.78.7: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
- name: youmen
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
创建一个上下文可以访问集群
kubectl config set-context youmen@kubernetes --cluster=kubernetes --user=youmen
Context "youmen@kubernetes" created.
[root@master pki]# kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.78.7:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
- context:
cluster: kubernetes
user: youmen
name: youmen@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
- name: youmen
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
我们切换到youmen用户尝试一下
kubectl config use-context youmen@kubernetes
Switched to context "youmen@kubernetes".
kubectl get pods
Error from server (Forbidden): pods is forbidden: User "youmen" cannot list resource "pods" in API group "" in the namespace "default"
自己创建一个cluster集群
kubectl config set-cluster mycluster \
--kubeconfig=/tmp/test.conf \
--server="https://172.19.0.41:6443" \
--certificate-authority=/etc/kubernetes/pki/ca.crt \
--embed-certs=true
kubectl config view --kubeconfig=/tmp/test.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://172.19.0.41:6443
name: mycluster
contexts: null
current-context: ""
kind: Config
preferences: {}
users: null
RBAC授权
之前我们切换用户get pods时候发现报错,还未赋予权限
k8s授权请求是http的请求
/apis/[GROUP]/[VERSION]/namespace/[NAMESPACE_NAME]/[KIND]/[OBJECT_ID]
k8s授权方式分为:
serviceccount和自己签证ca证书的账号,及签证ca的用户组(group)上(授权给这个组的权限)
role:
# 1. 允许的操作,如get,list等
# 2. 允许操作的对象,如pod,svc等
rolebinding:
# 将那个用户绑定到那个role或clusterrrole上
# clusterrole: (集群角色)
# clusterolebinding:(绑定到集群)
如果使用rolebinding绑定到clusterrole上,表示绑定的用户只能用于当前namespace的权限
kubectl create role pods-reader --verb=get,list,watch --resource=pods --dry-run -o yaml>role-demo.yaml
cat role-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
creationTimestamp: null
name: pods-reader
namespace: default
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
kubectl get role
NAME AGE
pods-reader 48s
kubectl describe role pods-reader
Name: pods-reader
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"rbac.authorization.k8s.io/v1","kind":\
"Role","metadata":{"annotations":{},"creationTimestamp":null,"name":"pods-reader","nam...
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
pods [] [] [get list watch]
# 绑定rolebinding
kubectl create rolebinding youmen-read-pods --role=pods-reader --user=youmen
kubectl create rolebinding youmen-read-pods --role=pods-reader --user=youmen --dry-run \
-o yaml > rolebind-demo.yaml
查看并验证绑定授权用户
kubectl describe rolebinding youmen-read-pods
Name: youmen-read-pods
Labels: <none>
Annotations: <none>
Role:
Kind: Role
Name: pods-reader
Subjects:
Kind Name Namespace
---- ---- ---------
User youmen
kubectl config use-context youmen@kubernetes
Switched to context "youmen@kubernetes".
[root@master pki]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-0 1/1 Running 0 16h
myapp-1 1/1 Running 0 16h
myapp-2 1/1 Running 0 16h
myapp-3 1/1 Running 0 16h
# 但是如果换了一个明成空间就会失效
kubectl get pods -n kube-system
Error from server (Forbidden): pods is forbidden: User "youmen" cannot list resource "pods" in API group "" in the namespace "kube-system"
创建clusterrole,可以访问全部的namespace
kubectl create clusterrole cluster-reader --verb=get,list,watch --resource=pods -o yaml --dry-run \
> clusterrole-demo.yaml
useradd k8s
cp -rp .kube/ /home/k8s/
chown -R k8s:k8s /home/k8s/
su - k8s
kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://172.19.0.26:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
- context:
cluster: kubernetes
user: youmen
name: youmen@kubernetes
current-context: youmen@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
- name: youmen
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
cat cluterrole-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-reader
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
kubectl apply -f cluterrole-demo.yaml
# 我们将之前的role删掉,然后会发现立马就没权限查看Pod了
kubectl delete rolebinding youmen-read-pods
kubectl get pods
Error from server (Forbidden): pods is forbidden: User "youmen" cannot list resource "pods" in API group "" in the namespace "default"
# 接下来我们使用clusterrolebinding更大的权限**
kubectl create clusterrolebinding youmen-read-all-pods --clusterrole=cluster-reader --user=youmen
kubectl create clusterrolebinding youmen-read-all-pods --clusterrole=cluster-reader --user=youmen --dry-run -o yaml \> clusterrolebinding-demo.yaml
vim clusterrolebinding-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
creationTimestamp: null
name: youmen-read-all-pods
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: youmen
kubectl get clusterrolebinding |grep youmen
youmen-read-all-pods 2m18s
kubectl describe clusterrolebinding youmen-read-all-pods
Name: youmen-read-all-pods
Labels: <none>
Annotations: <none>
Role:
Kind: ClusterRole
Name: cluster-reader
Subjects:
Kind Name Namespace
---- ---- ---------
User youmen
验证clusterrolebinding
kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-6955765f44-5jlbk 1/1 Running 1 7d17h
coredns-6955765f44-xnr7f 1/1 Running 1 7d17h
etcd-master 1/1 Running 1 7d17h
kube-apiserver-master 1/1 Running 1 7d17h
kubectl delete clusterrolebinding youmen-read-all-pods
# 我们将它删除,在创建一个新的clusterrolebinding
kubectl create rolebinding youmen-read-pods \
--clusterrole=cluster-reader \
--user=youmen --dry-run -o yaml > rolebinding-clusterrole.demo.yaml
cat rolebinding-clusterrole.demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
creationTimestamp: null
name: youmen-read-pods
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: youmen
kubectl apply -f rolebinding-clusterrole.demo.yaml
kubectl describe rolebinding youmen-read-pods
Name: youmen-read-pods
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"RoleBinding",\
"metadata":{"annotations":{},"creationTimestamp":null,"name":"youmen-rea...
Role:
Kind: ClusterRole
Name: cluster-reader
Subjects:
Kind Name Namespace
---- ---- ---------
User youmen
kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-0 1/1 Running 0 17h
myapp-1 1/1 Running 0 17h
myapp-2 1/1 Running 0 17h
myapp-3 1/1 Running 0 17h
# 我们可以发现服务被降级了
[k8s@master ~]$ kubectl get pods -n kube-system
Error from server (Forbidden): pods is forbidden: User "youmen" cannot list resource "pods" in API group "" in the namespace "kube-system"
flannel控制
kubectl get pods -n kube-system kube-flannel-ds-amd64-jw4xk -o yaml
Dashboard
Kubernetes集群的管理方式:
-
命令式: create,run,expose,delete,..
-
命令式配置文件: create -f /PATH/TO/RESOURCE_CONFGURATION_FILE ,delete -f ,replace -f
-
声明式配置文件: apply -f,patch
-
部署
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml
-
将Service改为NodePort
-
认证
- 认证时账号必须为ServiceAccount,被dashboard pod拿来由kubernetes进行认证.
token:- 创建ServiceAccount,根据其管理目标,使用rolebinding或clusterrolebinding绑定至合理role或clusterrole;
- 获取此ServiceAccount的secret,查看secret的详细信息,其中就有token;
config: (把ServiceAccount的token封装为kubeconfig文件)
1. 创建ServiceAccount,根据其管理目标,使用rolebinding或clusterrolebinding绑定至合理role或clusterrole;
2.kubectl get secret |awk '/^ServiceAccount/{print $1}'
DEF_NS_ADMIN_TOKEN=$(kubectl get secret def-ns-admin-token-mnpph -o jsonpath={.data.token} |base64 -d )
3. 生成kubeconfig文件
kubectl config set-cluster --kubeconfig=/PATH/TO/SOMEFILE
kubectl config set-credentials NAME --token=$KUBE_TOKEN --kubeconfig=/PATH/TO/SOMEFILE
kubectl config set-context
kubectl config use-context
# 我们通过打补丁实现NodePort外部访问k8sUI (不建议)
kubectl patch -n kubernetes-dashboard svc kubernetes-dashboard -p '{"spec":{"type":"NodePort"}}'
service/kubernetes-dashboard patched
[root@master dashboard]# kubectl get svc -n kubernetes-dashboard
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
dashboard-metrics-scraper ClusterIP 10.96.191.177 <none> 8000/TCP 27m
kubernetes-dashboard NodePort 10.96.123.181 <none> 443:32630/TCP 27m
# 此时访问需要用Pod所在节点的IP,但是因为证书问题,需要部署Dashboard指定有效的证书,才可以访问.
# 谷歌浏览器必须要换证书,火狐可以忽略跳过去.
因为其他浏览器打不开是因为证书过期,我们可以解决证书过期问题
# 首先需要生成证书
API Server访问Dashboard(推荐)
# 如果Kubernetes API服务器是公开的,并可以从外部访问,我们可以直接使用API Server的方式来访问.
# https://<master-ip>:<apiserver-port>/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/
# https://172.19.0.26:6443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/
# 如果返回一下结果不要慌,这是因为新版的K8s默认启用了RBAC,并未认证用户赋予了一个默认的身份: anconymous
# 对于API Server来说,他是使用证书进行认证的,我们需要创建一个证书
# 1. 首先找到kubectl命令的配置文件,默认情况下为/etc/kubernetes/admin.conf
# 2. 然后我们使用client-certificate-data和client-key-data生成一个*p12*文件,可使用下列命令:
# 生成client-certificate-data
grep 'client-certificate-data' ~/.kube/config | head -n 1 | awk '{print $2}' | base64 -d >> kubecfg.crt
# 生成client-key-data
grep 'client-key-data' ~/.kube/config | head -n 1 | awk '{print $2}' | base64 -d >> kubecfg.key
# 生成p12
openssl pkcs12 -export -clcerts -inkey kubecfg.key -in kubecfg.crt -out kubecfg.p12 -name "kubernetes-client"
ls
kubecfg.crt kubecfg.key kubecfg.p12
# 最后导入上面生成的p12文件,重新打开浏览器,显示如下
使用Token登录
kubectl create serviceaccount dashboard-admin -n kube-system
kubectl create clusterrolebinding dashboard-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
kubectl get secret -n kube-system |grep dashboard
dashboard-admin-token-drb8d kubernetes.io/service-account-token 3 2m43s
dashboard-cert Opaque 2 21m
kubectl describe secret dashboard-admin-token-drb8d -n kube-system
在创建一个账号,拥有对default名称空间的权限
kubectl create serviceaccount def-ns-admin -n default
kubectl create rolebinding def-ns-admin --clusterrole=admin --serviceaccount=default:def-ns-admin
kubectl get secret
NAME TYPE DATA AGE
def-ns-admin-token-mnpph kubernetes.io/service-account-token 3 2m29s
default-token-qw5gz kubernetes.io/service-account-token 3 18h
[root@master pki]# kubectl describe secret def-ns-admin-token-mnpph
配置文件认证
kubectl config set-cluster kubernetes --certificate-authority=./ca.crt --server="https://172.19.0.26:6443" --embed-certs=true --kubeconfig=/root/def-ns-admin.conf
Cluster "kubernetes" set.
[root@master pki]# kubectl config view --kubeconfig=/roo/def-ns-admin.conf
apiVersion: v1
clusters: null
contexts: null
current-context: ""
kind: Config
preferences: {}
users: null
kubectl get secret def-ns-admin-token-mnpph -o json
DEF_NS_ADMIN_TOKEN=$(kubectl get secret def-ns-admin-token-mnpph -o jsonpath={.data.token} |base64 -d )
kubectl config set-credentials def-ns-admin --token=$DEF_NS_ADMIN_TOKEN --kubeconfig=/root/def-ns-admin.conf
kubectl config view --kubeconfig=/root/def-ns-admin.conf
kubectl config set-context def-ns-admin@kubernetes --cluster=kubernetes --user=def-ns-admin --kubeconfig=/root/def-ns-admin.conf
kubectl config use-context def-ns-admin@kubernetes --kubeconfig=/root/def-ns-admin.conf
kubectl config view --kubeconfig=/root/def-ns-admin.conf
# 将此文件上传到电脑目录上.