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: 定义了”被作用者”和”角色”的绑定关系

k8s1

角色(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集群的管理方式:

  1. 命令式: create,run,expose,delete,..

  2. 命令式配置文件: create -f /PATH/TO/RESOURCE_CONFGURATION_FILE ,delete -f ,replace -f

  3. 声明式配置文件: apply -f,patch

  4. 部署
    kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml

  5. 将Service改为NodePort

  6. 认证

  • 认证时账号必须为ServiceAccount,被dashboard pod拿来由kubernetes进行认证.
    token:
    1. 创建ServiceAccount,根据其管理目标,使用rolebinding或clusterrolebinding绑定至合理role或clusterrole;
    2. 获取此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
# 将此文件上传到电脑目录上.

posted @ 2020-07-03 21:51  常见-youmen  阅读(1030)  评论(0编辑  收藏  举报