背景信息:
某客户反馈,新建的ingress不显示ingress关联slb的公网ip了,与客户沟通后确认创建了两套ingress-controller后出现的问题,创建ingress后的显示效果如下:
需求沟通:
沟通客户部署两套ingress的需求原因,是因为默认ingress-controller的service关联公网slb,需要在内网再部署一套关联内网slb的ingress-controller,便于内部的其他应用走内网slb调用,
需求实现:
这个需求无论是多套,或者多个slb都是有现成的文档可以参考进行设置的如:
《如何配置阿里云容器服务Kubernetes Ingress Controller使用私网SLB》
《如何在ACK集群中部署多个Ingress Controller》
问题排查:
我们知道多套ingress-controller区分ingress要关联的ingress-controller是要使用ingressClass关键字的,因此我们先看ingress的yaml里面的字段,而客户的yaml里面并没有写ingress.class相关字段
缺少下面的字段
annotations:
kubernetes.io/ingress.class: "<YOUR_INGRESS_CLASS>"
添加了ingress.class的annotations后问题依然如故,将视线从配置本身转移到关联显示ip的角度上,将kubectl 的get日志级别调整到最大,未见明显异常
# kubectl get ing web -v 10(v10调整日志级别,后补日志)
I0904 14:05:39.618631 30866 loader.go:375] Config loaded from file: /root/.kube/config
I0904 14:05:39.623263 30866 round_trippers.go:423] curl -k -v -XGET -H "User-Agent: kubectl/v1.16.9 (linux/amd64) kubernetes/4f7ea78" -H "Accept: application/json, */*" 'https://192.168.0.128:6443/apis/external.metrics.k8s.io/v1beta1?timeout=32s'
I0904 14:05:39.654111 30866 round_trippers.go:443] GET https://192.168.0.128:6443/apis/external.metrics.k8s.io/v1beta1?timeout=32s 200 OK in 30 milliseconds
I0904 14:05:39.654133 30866 round_trippers.go:449] Response Headers:
I0904 14:05:39.654138 30866 round_trippers.go:452] Cache-Control: no-cache, private
I0904 14:05:39.654143 30866 round_trippers.go:452] Content-Type: application/json
I0904 14:05:39.654147 30866 round_trippers.go:452] Date: Fri, 04 Sep 2020 06:05:39 GMT
I0904 14:05:39.654151 30866 round_trippers.go:452] Content-Length: 109
I0904 14:05:39.654155 30866 round_trippers.go:452] Audit-Id: e4e508e5-ac55-4c9b-becf-4e77a5114ef6
I0904 14:05:39.656979 30866 request.go:968] Response Body: {"kind":"APIResourceList","apiVersion":"v1","groupVersion":"external.metrics.k8s.io/v1beta1","resources":[]}
I0904 14:05:39.659221 30866 cached_discovery.go:82] skipped caching discovery info, no resources found
I0904 14:05:39.663461 30866 round_trippers.go:423] curl -k -v -XGET -H "Accept: application/json, */*" -H "User-Agent: kubectl/v1.16.9 (linux/amd64) kubernetes/4f7ea78" 'https://192.168.0.128:6443/apis/external.metrics.k8s.io/v1beta1?timeout=32s'
I0904 14:05:39.671174 30866 round_trippers.go:449] Response Headers:
I0904 14:05:39.671179 30866 round_trippers.go:452] Audit-Id: 4b8e7e46-3269-4c6e-9283-e95818954158
I0904 14:05:39.671184 30866 round_trippers.go:452] Cache-Control: no-cache, private
I0904 14:05:39.671188 30866 round_trippers.go:452] Content-Type: application/json
I0904 14:05:39.671192 30866 round_trippers.go:452] Date: Fri, 04 Sep 2020 06:05:39 GMT
I0904 14:05:39.671196 30866 round_trippers.go:452] Content-Length: 109
I0904 14:05:39.674712 30866 request.go:968] Response Body: {"kind":"APIResourceList","apiVersion":"v1","groupVersion":"external.metrics.k8s.io/v1beta1","resources":[]}
I0904 14:05:39.678065 30866 cached_discovery.go:82] skipped caching discovery info, no resources found
I0904 14:05:39.680165 30866 round_trippers.go:423] curl -k -v -XGET -H "Accept: application/json, */*" -H "User-Agent: kubectl/v1.16.9 (linux/amd64) kubernetes/4f7ea78" 'https://192.168.0.128:6443/apis/external.metrics.k8s.io/v1beta1?timeout=32s'
I0904 14:05:39.686710 30866 round_trippers.go:443] GET https://192.168.0.128:6443/apis/external.metrics.k8s.io/v1beta1?timeout=32s 200 OK in 5 milliseconds
I0904 14:05:39.686725 30866 round_trippers.go:449] Response Headers:
I0904 14:05:39.686734 30866 round_trippers.go:452] Audit-Id: 441b3b75-5376-409e-93f6-e1fd5e4f7798
I0904 14:05:39.686739 30866 round_trippers.go:452] Cache-Control: no-cache, private
I0904 14:05:39.686744 30866 round_trippers.go:452] Content-Type: application/json
I0904 14:05:39.686757 30866 round_trippers.go:452] Date: Fri, 04 Sep 2020 06:05:39 GMT
I0904 14:05:39.686761 30866 round_trippers.go:452] Content-Length: 109
I0904 14:05:39.689455 30866 request.go:968] Response Body: {"kind":"APIResourceList","apiVersion":"v1","groupVersion":"external.metrics.k8s.io/v1beta1","resources":[]}
I0904 14:05:39.691663 30866 cached_discovery.go:82] skipped caching discovery info, no resources found
I0904 14:05:39.693421 30866 round_trippers.go:423] curl -k -v -XGET -H "Accept: application/json;as=Table;v=v1beta1;g=meta.k8s.io, application/json" -H "User-Agent: kubectl/v1.16.9 (linux/amd64) kubernetes/4f7ea78" 'https://192.168.0.128:6443/apis/extensions/v1beta1/namespaces/default/ingresses/web'
I0904 14:05:39.696346 30866 round_trippers.go:443] GET https://192.168.0.128:6443/apis/extensions/v1beta1/namespaces/default/ingresses/web 200 OK in 2 milliseconds
I0904 14:05:39.696359 30866 round_trippers.go:449] Response Headers:
I0904 14:05:39.696364 30866 round_trippers.go:452] Audit-Id: 99bff432-cd2a-4692-b030-09e237b88731
I0904 14:05:39.696370 30866 round_trippers.go:452] Cache-Control: no-cache, private
I0904 14:05:39.696393 30866 round_trippers.go:452] Content-Type: application/json
I0904 14:05:39.696401 30866 round_trippers.go:452] Content-Length: 1987
I0904 14:05:39.696406 30866 round_trippers.go:452] Date: Fri, 04 Sep 2020 06:05:39 GMT
I0904 14:05:39.696458 30866 request.go:968] Response Body: {"kind":"Table","apiVersion":"meta.k8s.io/v1beta1","metadata":{"selfLink":"/apis/extensions/v1beta1/namespaces/default/ingresses/web","resourceVersion":"200490461"},"columnDefinitions":[{"name":"Name","type":"string","format":"name","description":"Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names","priority":0},{"name":"Hosts","type":"string","format":"","description":"Hosts that incoming requests are matched against before the ingress rule","priority":0},{"name":"Address","type":"string","format":"","description":"Address is a list containing ingress points for the load-balancer","priority":0},{"name":"Ports","type":"string","format":"","description":"Ports of TLS configurations that open","priority":0},{"name":"Age","type":"string","format":"","description":"CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC.\n\nPopulated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata","priority":0}],"rows":[{"cells":["web","m*****.w***b.com","","80","99d"],"object":{"kind":"PartialObjectMetadata","apiVersion":"meta.k8s.io/v1beta1","metadata":{"name":"web","namespace":"default","selfLink":"/apis/extensions/v1beta1/namespaces/default/ingresses/web","uid":"226ccb92-cd23-4af9-a899-06afc459d0f0","resourceVersion":"200490461","generation":8,"creationTimestamp":"2020-05-28T01:36:19Z","annotations":{"nginx.ingress.kubernetes.io/service-weight":""}}}}]}
NAME HOSTS ADDRESS PORTS AGE
web m***.***8.com 80 99d
查看ingress-controller的日志,看看是否可以找到蛛丝马迹,果然发现了一些errorlog,如下
error updating ingress rule: ingresses.networking.k8s.io "wh03" is forbidden: User "system:serviceaccount:kube-system:nginx-ingress-controller" cannot update resource "ingresses/status" in API group "networking.k8s.io" in the namespace "default"
问题定位:
上面的报错意思是ingress-controller使用的sa权限不足,导致更新ingresses/status缺少了权限,在k8s的RBAC权限配置里面,某个service account的权限取决于绑定的clusterrole,我们先看下ingress-controller使用的service account绑定的clusterrole是哪个?
# kubectl get clusterrolebindings.rbac.authorization.k8s.io nginx-ingress-controller -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"rbac.authorization.k8s.io/v1beta1","kind":"ClusterRoleBinding","metadata":{"annotations":{},"name":"nginx-ingress-controller"},"roleRef":{"apiGroup":"rbac.authorization.k8s.io","kind":"ClusterRole","name":"nginx-ingress-controller"},"subjects":[{"kind":"ServiceAccount","name":"nginx-ingress-controller","namespace":"kube-system"}]}
creationTimestamp: 2019-05-15T02:21:45Z
name: nginx-ingress-controller
resourceVersion: "72216951"
selfLink: /apis/rbac.authorization.k8s.io/v1/clusterrolebindings/nginx-ingress-controller
uid: 2f43dbc8-76b8-11e9-864c-62cf21d8490a
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: nginx-ingress-controller
subjects:
- kind: ServiceAccount
name: nginx-ingress-controller
namespace: kube-system
可以看到 ingress-controller使用的service account绑定的clusterrole是nginx-ingress-controller,我们再看下nginx-ingress-controller clusterrole的具体权限是什么?是否缺少了报错中提到的 networking.k8s.io
# kubectl get clusterroles nginx-ingress-controller -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
...
rules:
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- nodes
- pods
- secrets
- namespaces
- services
verbs:
...
报错的是update ingresses/status 的时候没有networking.k8s.io的授权,因此在apigroup里面添加即可
- apiGroups:
- extensions 这里缺一条 - networking.k8s.io
resources:
- ingresses/status
verbs:
- update
- ...
- apiGroups:
- ""
resourceNames:
- ingress-controller-leader-nginx
resources:
- configmaps
verbs:
- get
- update
完整的demo如下:(不同集群版本在rbac的授权上可能有所不同,请根据实际报错去检查)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"rbac.authorization.k8s.io/v1beta1","kind":"ClusterRole","metadata":{"annotations":{},"name":"nginx-ingress-controller"},"rules":[{"apiGroups":[""],"resources":["configmaps","endpoints","nodes","pods","secrets","namespaces","services"],"verbs":["get","list","watch"]},{"apiGroups":["extensions","networking.k8s.io"],"resources":["ingresses"],"verbs":["get","list","watch"]},{"apiGroups":[""],"resources":["events"],"verbs":["create","patch"]},{"apiGroups":["extensions","networking.k8s.io"],"resources":["ingresses/status"],"verbs":["update"]},{"apiGroups":[""],"resources":["configmaps"],"verbs":["create"]},{"apiGroups":[""],"resourceNames":["ingress-controller-leader-nginx"],"resources":["configmaps"],"verbs":["get","update"]}]}
creationTimestamp: "2019-05-13T06:08:48Z"
name: nginx-ingress-controller
resourceVersion: "128875243"
selfLink: /apis/rbac.authorization.k8s.io/v1/clusterroles/nginx-ingress-controller
uid: 92cc75b7-7545-11e9-b617-00163e06992d
rules:
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- nodes
- pods
- secrets
- namespaces
- services
verbs:
- get
- list
- watch
- apiGroups:
- extensions
- networking.k8s.io
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- extensions
- networking.k8s.io
resources:
- ingresses/status
verbs:
- update
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- apiGroups:
- ""
resourceNames:
- ingress-controller-leader-nginx
resources:
- configmaps
verbs:
- get
- update
注意:还有一个报错的版本是由于在配置私有Ingress Controller Pod时是引用集群默认的ServiceAccount,新生成的ingress-controller配置项没有更新到默认的ClusterRole所以导致发布ingress规则报没权限从而显示不了ip,此时需要在默认的ClusterRole中的resourceNames下添加ingress-controller。
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
name: nginx-ingress-role
namespace: ingress-nginx
...
resourceNames:
# Defaults to "<election-id>-<ingress-class>"
# Here: "<ingress-controller-leader>-<nginx>"
# This has to be adapted if you change either parameter
# when launching the nginx-ingress-controller.
- "ingress-controller-leader-nginx"
verbs:
- get
- update
...
RBAC扩展:
基于角色的访问控制(Role-Based Access Control, 即”RBAC”)使用”rbac.authorization.k8s.io” API Group实现授权决策,允许管理员通过Kubernetes API动态配置策略。
API概述
RBAC API声明了四个最高级别的类型(本文介绍),RBAC 的授权策略可以利用 kubectl 或者 Kubernetes API 直接进行配置。RBAC 可以授权给用户,让用户有权进行授权管理,这样就无需接触节点,直接进行授权管理。RBAC 在 Kubernetes 中被映射为 API 资源和操作。相关资源的图示如下:
Kubernetes 仅审查以下 API 请求属性:
- user - 身份验证期间提供的
user
字符串。 - group - 经过身份验证的用户所属的组名列表。
- extra - 由身份验证层提供的任意字符串键到字符串值的映射。
- API - 指示请求是否针对 API 资源。
- Request path - 各种非资源端点的路径,如
/api
或/healthz
。 - API request verb - API 动词
get
,list
,create
,update
,patch
,watch
,proxy
,redirect
,delete
和deletecollection
用于资源请求。 - HTTP request verb - HTTP 动词
get
,post
,put
和delete
用于非资源请求。 - Resource - 正在访问的资源的 ID 或名称(仅限资源请求) - 对于使用
get
,update
,patch
和delete
动词的资源请求,您必须提供资源名称。 - Subresource - 正在访问的子资源(仅限资源请求)。
- Namespace - 正在访问的对象的名称空间(仅适用于命名空间资源请求)。
- API group - 正在访问的 API 组(仅限资源请求)。空字符串表示核心 API 组。(可以理解为不限制具体哪个apigroup)
Role 和 ClusterRole
在 RBAC API 中,一个角色包含一组相关权限的规则。权限是纯粹累加的(不存在拒绝某操作的规则)。 角色可以用 Role
来定义到某个命名空间上, 或者用 ClusterRole
来定义到整个集群作用域。
一个 Role
只可以用来对某一命名空间中的资源赋予访问权限。 下面的 Role
示例定义到名称为 "default" 的命名空间,可以用来授予对该命名空间中的 Pods 的读取权限:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" 指定核心 API 组
resources: ["pods"]
verbs: ["get", "watch", "list"]
ClusterRole
可以授予的权限和 Role
相同, 但是因为 ClusterRole
属于集群范围,所以它也可以授予以下访问权限:
- 集群范围资源 (比如 nodes)
- 非资源端点(比如 "/healthz")
- 跨命名空间访问的有名字空间作用域的资源(如 Pods),比如运行命令
kubectl get pods --all-namespaces
时需要此能力
下面的 ClusterRole
示例可用来对某特定命名空间下的 Secrets 的读取操作授权, 或者跨所有命名空间执行授权(取决于它是如何绑定的):
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# 此处的 "namespace" 被省略掉是因为 ClusterRoles 是没有命名空间的。集群级别的授权
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
RoleBinding 和 ClusterRoleBinding
角色绑定(RoleBinding)是将角色中定义的权限赋予一个或者一组用户。 它包含若干主体(用户,组和服务账户)的列表和对这些主体所获得的角色的引用。 可以使用 RoleBinding
在指定的命名空间中执行授权, 或者在集群范围的命名空间使用 ClusterRoleBinding
来执行授权。
一个 RoleBinding
可以引用同一的命名空间中的 Role
。 下面的例子 RoleBinding
将 "pod-reader" 角色授予在 "default" 命名空间中的用户 "jane"; 这样,用户 "jane" 就具有了读取 "default" 命名空间中 pods 的权限。
roleRef
里的内容决定了实际创建绑定的方法。kind
可以是 Role
或 ClusterRole
, name
将引用你要指定的 Role
或 ClusterRole
的名称。在下面的例子中,角色绑定使用 roleRef
将用户 "jane" 绑定到前文创建的角色 Role
,其名称是 pod-reader
。
apiVersion: rbac.authorization.k8s.io/v1
# 此角色绑定使得用户 "muyuan" 能够读取 "default" 命名空间中的 Pods
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: muyuan # 需要注意name字段的大小写是敏感的
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role #this must be Role or ClusterRole
name: pod-reader # 这里的名称必须与你想要绑定的 Role 或 ClusterRole 名称一致
apiGroup: rbac.authorization.k8s.io
RoleBinding
也可以引用 ClusterRole
,对 ClusterRole
所定义的、位于 RoleBinding
命名空间内的资源授权。 这可以允许管理者在 整个集群中定义一组通用的角色,然后在多个命名空间中重用它们。
例如下面的例子,RoleBinding
指定的是 ClusterRole
, "dave" (主体,区分大小写)将只可以读取在"development" 命名空间( RoleBinding
的命名空间)中的"secrets"。
apiVersion: rbac.authorization.k8s.io/v1
# 这个角色绑定允许 "muyuan" 用户在 "myns" 命名空间中有读取 secrets 的权限。
kind: RoleBinding
metadata:
name: read-secrets
namespace: myns # 这里只授予 "myns" 命名空间的权限。
subjects:
- kind: User
name: muyuan # 需要注意name字段的大小写是敏感的
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
最后,ClusterRoleBinding
可用来在集群级别或对所有命名空间执行授权。 下面的例子允许 "manager" 组中的任何用户读取任意命名空间中 "secrets"。
apiVersion: rbac.authorization.k8s.io/v1
# 这个集群角色绑定允许 "muyuangroup" 组中的任何用户读取任意命名空间中 "secrets"。
kind: ClusterRoleBinding
metadata:
name: read-secrets-global
subjects:
- kind: Group
name: muyuangroup # 名称区分大小写
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
你不能修改绑定对象所引用的 Role
或 ClusterRole
。 试图改变绑定对象的 roleRef
将导致验证错误。想要 改变现有绑定对象中 roleRef
字段的内容,必须删除并 重新创建绑定对象。这种限制有两个主要原因:
1.关于不同角色的绑定是完全不一样的。更改 roleRef
需要删除/重建绑定,确保要赋予绑定的完整主体列表是新 的角色(而不是只是启用修改 roleRef
在不验证所有现有 主体的情况下的,应该授予新角色对应的权限)。
2.使得 roleRef
不可以改变现有绑定主体用户的 update
权限, 这样可以让它们能够管理主体列表,而不能更改授予这些主体相关 的角色。
对资源的引用
大多数资源都是使用名称的字符串表示,例如在相关的 API 端点的 URL 之中出现的 "pods" 。 然而有一些 Kubernetes API 涉及 "子资源(subresources)",例如 pod 的日志。Pod 日志相关的端点 URL 如下:
GET /api/v1/namespaces/{namespace}/pods/{name}/log
在这种情况下,"pods" 是有命名空间的资源,而 "log" 是 pods 的子资源。在 RBAC 角色中, 使用"/"分隔资源和子资源。允许一个主体要同时读取 pods 和 pod logs,你可以这么写:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list"]
对于某些请求,也可以通过 resourceNames
列表按名称引用资源。 在指定时,可以将请求类型限制资源的单个实例。限制只可以 "get" 和 "update" 的单一configmap,你可以这么写:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: configmap-updater
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["my-configmap"]
verbs: ["update", "get"]
需要注意的是,create
请求不能被 resourceName 限制,因为在鉴权时还不知道对象名称。 另一个例外是 deletecollection
。
对主体的引用
RoleBinding
或者 ClusterRoleBinding
需要绑定角色到 主体。 主体可以是组,用户或者服务账户。
用户是由字符串表示,它们可以是普通的用户名,像 "alice",或者是 邮件格式 "bob@example.com",或者是数字ID。由 Kubernetes 管理员配置身份认证模块 需要的格式。RBAC 鉴权系统不对格式作任何要求,但是前缀 system:
是 Kubernetes 系统保留的, 所以管理员要确保配置的用户名不能出现上述前缀格式。
用户组信息是 Kubernetes 现在提供的一种身份验证模块,与用户一样,对组的字符串没有格式要求, 只是不能使用保留的前缀 system:
。
服务账号 的用户名前缀为system:serviceaccount:
, 属于前缀为 system:serviceaccounts:
的用户组。
RoleBinding的示例
下面的示例只是展示 RoleBinding
中 subjects
的部分。
用户的名称为 "muyuanuser":
subjects:
- kind: User
name: "muyuanuser"
apiGroup: rbac.authorization.k8s.io
组的名称为 "muyuangroups":
subjects:
- kind: Group
name: "muyuangroups"
apiGroup: rbac.authorization.k8s.io
服务账号在 kube-system 命名空间中:
subjects:
- kind: ServiceAccount
name: default
namespace: kube-system
好的,看到这里我相信你已经大概明白了RBAC的授权方式了,我来大致总结一下
RBAC通过角色绑定将角色和主体相关联,角色负责授权相关资源,主体绑定角色后就对授权资源有了授权
话不多说,我们来做一个场景实验,新建muyuantest用户,并生成该用户所属的kubeconfig,具备操作muyuanns命名空间所有权限,测试环境为master节点,托管集群请走ram+rbac授权(请不要直接跟着动手做,看完本篇文章之后想要尝试的话,再在测试环境上尝试)
一,创建证书
1.1 创建user私钥
[root@iZwz99lmwvr1f2s76mrv6mZ pki]# pwd
/etc/kubernetes/pki
# umask 077;openssl genrsa -out muyuantest.key 2048
Generating RSA private key, 2048 bit long modulus
............+++
.....................................................+++
e is 65537 (0x10001)
1.2 创建证书签署请求
O=组织信息,CN=用户名
# openssl req -new -key muyuantest.key -out muyuantest.csr -subj "/O=k8s/CN=muyuantest"
1.3 签署证书
pki]# openssl x509 -req -in muyuantest.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out muyuantest.crt -days 365
Signature ok
subject=/O=k8s/CN=muyuantest
Getting CA Private Key
二,创建配置文件
2.1 创建集群配置(注意里面的server写的是master的ip,不是api-server的slb的ip)
pki]# kubectl config set-cluster k8s --server=https://192.168.0.128:6443 --certificate-authority=ca.crt --embed-certs=true --kubeconfig=/root/muyuantest.conf
Cluster "k8s" set.
# kubectl config view --kubeconfig=/root/muyuantest.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.0.128:6443
name: k8s
contexts: []
current-context: ""
kind: Config
preferences: {}
users: []
2.2 创建用户配置
# kubectl config set-credentials muyuantest --client-certificate=muyuantest.crt --client-key=muyuantest.key --embed-certs=true --kubeconfig=/root/muyuantest.conf
User "muyuantest" set.
# kubectl config view --kubeconfig=/root/muyuantest.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.0.128:6443
name: k8s
contexts: []
current-context: ""
kind: Config
preferences: {}
users:
- name: muyuantest
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
2.3 创建context配置
# kubectl config set-context muyuantest@k8s --cluster=k8s --user=muyuantest --kubeconfig=/root/muyuantest.conf
Context "muyuantest@k8s" created.
# kubectl config view --kubeconfig=/root/muyuantest.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.0.128:6443
name: k8s
contexts:
- context:
cluster: k8s
user: muyuantest
name: muyuantest@k8s
current-context: ""
kind: Config
preferences: {}
users:
- name: muyuantest
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
2.4 切换context
# kubectl config use-context muyuantest@k8s --kubeconfig=/root/muyuantest.conf
2.5 创建系统用户
# mkdir -p /home/muyuantest/.kube
# cp /root/muyuantest.conf /home/muyuantest/.kube/config
# chown -R muyuantest:muyuantest /home/muyuantest/
# su - muyuantest
-bash-4.2$
2.6 未做role的绑定,验证权限
-bash-4.2$ kubectl get pods
Error from server (Forbidden): pods is forbidden: User "muyuantest" cannot list resource "pods" in API group "" in the namespace "default"
2.7,创建role
# cat muyuantest-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: muyuanns
name: muyuannsall
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
# kubectl apply -f muyuantest-role.yaml
role.rbac.authorization.k8s.io/muyuannsall created
2.8 创建rolebindings
# kubectl apply -f muyuan-rolebindings.yaml
rolebinding.rbac.authorization.k8s.io/muyuantestrolebindings created
# cat muyuan-rolebindings.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: muyuantestrolebindings
namespace: muyuanns
subjects:
- kind: User
name: muyuantest
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: muyuannsall
apiGroup: rbac.authorization.k8s.io
2.9 验证授权,授权通过
# su - muyuantest
Last login: Mon Sep 7 13:02:02 CST 2020 on pts/0
-bash-4.2$ kubectl get pods -n muyuanns
NAME READY STATUS RESTARTS AGE
nginx-muyuanns-test-54f57cf6bf-8qkm7 1/1 Running 0 89s
注意:使用阿里云的子账号授权是没有这么复杂的,我们只需要关注,子账号授权的时候,默认权限的角色定义是否匹配我们的需求,不匹配的话就使用自定义规则去创建(控制台使用clusterrole进行授权,clusterrole需要提前创建)
=====命令扩展=====
下面这几个命令是api相关的资源
# kubectl get apiservices
# kubectl api-versions
# kubectl api-resources
=====RBAC 子资源list=====
# cat list_subresource.sh
#!/bin/bash
_list=($(kubectl get --raw / |grep "^ \"/api"|sed 's/[",]//g'));
for _api in ${_list[@]}; do
_aruyo=$(kubectl get --raw ${_api} | jq .resources);
if [ "x${_aruyo}" != "xnull" ]; then
echo;
echo "===${_api}===";
kubectl get --raw ${_api} | jq -r ".resources[].name";
fi;
done
# bash list_subresource.sh
===/api/v1===
bindings
componentstatuses
configmaps
endpoints
events
limitranges
namespaces
namespaces/finalize
namespaces/status
nodes
nodes/proxy
nodes/status
persistentvolumeclaims
persistentvolumeclaims/status
persistentvolumes
persistentvolumes/status
pods
pods/attach
pods/binding
pods/eviction
pods/exec
pods/log
pods/portforward
pods/proxy
pods/status
podtemplates
replicationcontrollers
replicationcontrollers/scale
replicationcontrollers/status
resourcequotas
resourcequotas/status
secrets
serviceaccounts
services
services/proxy
services/status
===/apis/admissionregistration.k8s.io/v1===
mutatingwebhookconfigurations
validatingwebhookconfigurations
...
by 思葵 牧原
参考资料:
https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/