[TOC]

0x01 Kubernetes 中安装metrics以获取客户端资源监控指标

描述: 通常在集群安装完成后,我们需要对其设置持久卷、网络存储等插件, 除此之外我们还需安装metrics-server以便于获取Node与Pod相关资源消耗等信息,否则你在执行kubectl top命令时会提示error: Metrics API not available, 所以本小节将针对Metrics-server的安装进行讲解。

项目地址: https://github.com/kubernetes-sigs/metrics-server

Q: 什么是metrics-server?

Metrics Server 是 Kubernetes 内置自动缩放管道的可扩展、高效的容器资源指标来源。
Metrics Server 从 Kubelets 收集资源指标,并通过 Metrics API 在 Kubernetes apiserver 中公开它们,供 Horizo​​ntal Pod Autoscaler 和 Vertical Pod Autoscaler 使用。

简单的说: Metrics Server 是集群解析监控数据的聚合器,安装后用户可以通过标准的API(/apis/metrics.k8s.io)来访问监控数据,此处值得注意的是Metrics-Server并非kube-apiserver的一部分,而是通过Aggregator这种插件机制,在独立部署的情况下同kube-apiserver一起统一对外服务的,当进行api请求时kube-aggregator统一接口会分析访问api具体的类型,帮我们负载到具体的api上。

1
2
3
4
5
GET /apis/metrics.k8s.io/V1beta1
|
Kube-aggregator
| | |
Kube-apiserver Metrics-server another-add-onapiserver


Metrics Server 特点:

  • 适用于大多数集群的单一部署(请参阅要求)
  • 快速自动缩放,每 15 秒收集一次指标。
  • 资源效率,集群中每个节点使用 1 mili 的 CPU 核心和 2 MB 的内存。
  • 可扩展支持多达 5,000 个节点集群。


Metrics Server 功能:(horizontalpodautoscalers.autoscaling 水平扩展必备)

  • 基于CPU/内存的水平自动缩放
  • 自动调整/建议容器所需的资源


Metrics Server 访问流程图

WeiyiGeek.访问流程图

WeiyiGeek.访问流程图

温馨提示: 我们可以通过 kubectl top 命令来访问 Metrics API 获取资源监控相关数据。
温馨提示: 注意 Metrics API 只可以查询当前度量数据,并不保存历史数据。


安装使用
步骤 01.Metrics Server 可以直接从 YAML 清单安装,也可以通过官方 Helm 图表安装。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 下载 YAML 清单
wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

# 提前下载相应的镜像加快部署
grep "image:" components.yaml
# image: k8s.gcr.io/metrics-server/metrics-server:v0.6.1

# 由于其镜像国内无法访问此处我们采用阿里云k8s.gcr.io镜像源
sed -i 's#k8s.gcr.io/metrics-server#registry.cn-hangzhou.aliyuncs.com/google_containers#g' components.yaml

# 部署资源清单
kubectl apply -f components.yaml
# serviceaccount/metrics-server created
......
# apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created


步骤 02.Metrics Server 默认是安装在kube-system名称空间下,我们可以查看其deployment、Pod运行以及SVC情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1.部署清单状态查看
kubectl get deploy,pod,svc -n kube-system -l k8s-app=metrics-server
# NAME READY UP-TO-DATE AVAILABLE AGE
# deployment.apps/metrics-server 1/1 1 0 91s

# NAME READY STATUS RESTARTS AGE
# pod/metrics-server-6ffc8966f5-cf2qh 1/1 Running 0 91s

# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# service/metrics-server ClusterIP 10.96.28.153 <none> 443/TCP 91s

# 2.注册到K8S集群中的 metrics.k8s.io API 查看
kubectl get apiservices.apiregistration.k8s.io | grep "metrics"
# v1beta1.metrics.k8s.io kube-system/metrics-server True 14h

步骤 03.查看各个节点以及Pod的资源指标(CPU/MEM)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
master-223 102m 2% 1147Mi 61%
master-224 119m 2% 2188Mi 57%
master-225 139m 3% 3773Mi 48%
node-1 54m 1% 921Mi 49%
node-2 61m 1% 824Mi 44%

# 默认名称空间中Pod的资源信息
$ kubectl top pod
NAME CPU(cores) MEMORY(bytes)
hello-nginx-7f4ff84cb-mjw79 0m 6Mi
nginx-web-0 0m 6Mi
nginx-web-1 0m 5Mi


问题解决:

问题1.部署 metrics-server 资源清单后 Pod 状态为 0/1 并报出annot validate certificate for 10.10.107.223 because it doesn't contain any IP SANs"错误问题解决。

  • 错误信息:
    1
    2
    3
    4
    5
    6
    $ kubectl describe pod -n kube-system metrics-server-6ffc8966f5-cf2qh
    # Warning Unhealthy 8s (x17 over 2m27s) kubelet Readiness probe failed: HTTP probe failed with statuscode: 500

    $ kubectl logs -f --tail 50 -n kube-system metrics-server-6ffc8966f5-cf2qh
    # E0520 11:13:17.379944 1 scraper.go:140] "Failed to scrape node" err="Get \"https://10.10.107.226:10250/metrics/resource\": x509: cannot validate certificate for 10.10.107.226 because it doesn't contain any IP SANs" node="node-1"
    # E0520 11:13:17.382948 1 scraper.go:140] "Failed to scrape node" err="Get \"https://10.10.107.223:10250/metrics/resource\": x509: cannot validate certificate for 10.10.107.223 because it doesn't contain any IP SANs" node="master-223"
  • 问题原因: 由于 metrics-server 未获得TLS Bootstrap 签发证书的导致访问各节点资源时报错。
  • 解决办法: 启用 TLS BootStrap 证书签发
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    # 1.分别在 Master 与 Node 节点中启用TLS BootStrap 证书签发,在 kubelet 的 yaml 配置中追加入如下K/V.
    # 方式1.Kubeadm 搭建的集群
    $ vim /var/lib/kubelet/config.yaml
    ...
    serverTLSBootstrap: true

    # 方式2.二进制搭建的集群(注意此路径根据你的kubelet.service进行配置), 此处我们定义的路径为 /etc/kubernetes/cfg/kubelet-config.yaml
    $ tee -a /etc/kubernetes/cfg/kubelet-config.yaml <<'EOF'
    serverTLSBootstrap: true
    EOF

    # 2.最后分别重启各个节点kubelet服务即可
    systemctl daemon-reload && systemctl restart kubelet.service

    # 3.查看节点的证书签发请求
    kubectl get csr
    # NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
    # csr-2m5d6 2m27s kubernetes.io/kubelet-serving system:node:master-223 <none> Pending
    # csr-ff7vb 19m kubernetes.io/kubelet-serving system:node:master-225 <none> Pending
    # csr-gg8gq 86s kubernetes.io/kubelet-serving system:node:master-224 <none> Pending
    # csr-56k9s 55s kubernetes.io/kubelet-serving system:node:node-1 <none> Pending
    # csr-dmghl 3s kubernetes.io/kubelet-serving system:node:node-2 <none> Pending

    # 4.手动允许节点证书签发请求
    kubectl certificate approve csr-2m5d6
    kubectl certificate approve csr-56k9s
    kubectl certificate approve csr-ff7vb
    kubectl certificate approve csr-gg8gq
    # certificatesigningrequest.certificates.k8s.io/csr-gg8gq approved

    # 5.查看签发的 certificate 特征
    kubectl get csr csr-dmghl
    # NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
    # csr-dmghl 10m kubernetes.io/kubelet-serving system:node:node-2 <none> Approved,Issued

0x02 Kubernetes 中Session的会话保持

背景说明: 基于kubernetes集群中部署Java项目,您发现在多pod模式下会出现登录成功但是页面无法跳转的问题,或验证明明输入正确却提示验证码错误无法登陆,而在单一pod时却可以成功登录并页面正常跳转,于是推测是cookie的问题。

解决方式: 进行K8S会话粘粘与保持, 但是针对于不同的实践环境又有所不同,例如采用ClusterIP、NodePort方式或者Ingress访问来访问我们的应用。

Service
描述: 网上的大部分文章提供的解决方案都是在service的配置文件中加入sessionAffinity: ClientIP,功能是选择与请求来源ip更接近的pod,这样就会固定同一个session但可能会出现流量负载不均衡的情况。

演示案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: Service
metadata:
name: tomcat
namespace: default
spec:
selector:
app: tomcat
release: canary
ports:
- name: http
targetPort: 8280
port: 8280
sessionAffinity: ClientIP


ingress-nginx
在ingress-nginx配置中应做以下操作:

  • 设置 nginx.ingress.kubernetes.io/affinity 属性,启用会话保持, 其值仅仅支持Cookie。
  • 设置 nginx.ingress.kubernetes.io/affinity-mode 属性,设置为balanced在集群扩大pod时,会自动分配一些会话到新创建的pod上,用于平衡服务器的负载;设置为persistent则永远保证用户访问pod的一致性,不会访问到其他pod,其值支持balanced (默认设置) or persistent
  • 设置 nginx.ingress.kubernetes.io/session-cookie-name 属性,自定义cookie名称, 其默认设置为 INGRESSCOOKIE,但我们可自定义。

演示案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/affinity-mode: "persistent"
nginx.ingress.kubernetes.io/session-cookie-name: "route"
nginx.ingress.kubernetes.io/cors-allow-origin: '*'
nginx.ingress.kubernetes.io/cors-max-age: "64800"
labels:
app: front-web
ref: front
name: front-app
namespace: web
spec:
ingressClassName: ingress-nginx
rules:
- host: app.weiyigeek.top
http:
paths:
- path: /
pathType: ImplementationSpecific
backend:
service:
name: front-index
port:
number: 80
- path: /sub/
pathType: ImplementationSpecific
backend:
service:
name: front-sub
port:
number: 80
tls:
- hosts:
- app.weiyigeek.top
secretName: app-weiyigeek-top

官方参考: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#session-affinity


0x03 Kubernetes 中多集群接入管理实践

描述: 在pipeline中的CD环节,常常需要将业务产品部署到不同的K8S集群,比如开发环境、测试环境、生产环境,此时可以使用 kubectl config相关命令来进行多个远程集群的配置并采用rbac授权机制来创建指定用户的权限 。

下面我们从两个方面进行验证,一是在本地集群创建指定用户只能访问特定名称空间的资源,二是指定用户接入远程集群中并且只能访问特定名称空间的资源, 我们需要重点关注三大要素即 集群(clusters)、上下文(contexts)、用户(user)

config 命令下重要配置项说明:

  • clusters :配置要访问的kubernetes集群
  • contexts :配置访问kubernetes集群的具体上下文环境
  • current-context : 配置当前使用的上下文环境
  • users : 配置访问的用户信息,用户名以及证书信息


1.本地集群创建指定用户管理集群

为当前集群创建一个只管理指定名称空间权限的devopsuser用户
描述: kubernetes 中我们可将权限进行细化、使得使用者可以拥有最小的运行权限,保证集群的安全,特别是CI/CD环境中,下面将演示在kubernetes集群中创建一个只管理名称空间为devtest的devopsuser用户。

步骤 01.创建一个devtest的名称空间, 执行如下命令kubectl create namespace devtest.

步骤 02.执行kubectl config get-clusters命令查看当前集群名称,通常默认为kubernetes.

步骤 03.准备cfssl工具以及生成用户证书的相关json文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
$ tee ca-config.json << 'EOF'
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}
EOF

$ tee devopsuser-csr.json << 'EOF'
{
"CN": "devopsuser",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "ChongQing",
"L": "ChongQing",
"O": "k8s",
"OU": "System"
}
]
}
EOF


步骤 04.执行如下命令为devopsuser用户生成相应的证书,并将证书复制到 /etc/kubernetes/pki/user/目录中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 生成用户证书
cfssl gencert -ca=/etc/kubernetes/pki/ca.crt -ca-key=/etc/kubernetes/pki/ca.key -config ./ca-config.json -profile=kubernetes ./devopsuser-csr.json | cfssljson -bare devopsuser
# 2022/03/16 19:40:19 [INFO] generate received request
# 2022/03/16 19:40:19 [INFO] received CSR
# 2022/03/16 19:40:19 [INFO] generating key: rsa-2048
# 2022/03/16 19:40:19 [INFO] encoded CSR
# 2022/03/16 19:40:19 [INFO] signed certificate with serial number 648194491978037048405922455454162128168023396626

# 查看生成的证书以及申请文件 (后三个新生成)
ls
ca-config.json devopsuser-csr.json devopsuser.csr devopsuser-key.pem devopsuser.pem

# 证书到期时间
openssl x509 -in devopsuser.pem -noout -text | grep -E 'Not'
Not Before: Mar 16 11:35:00 2022 GMT
Not After : Mar 13 11:35:00 2032 GMT

# 新建用户证书存放目录创建并将生成的证书密钥与证书复制到该目录中。
mkdir -vp /etc/kubernetes/pki/user/
cp -a devopsuser*.pem /etc/kubernetes/pki/user/


步骤 05.查看本地或者远程集群的API_SERVER地址,并将其写入到devopsuser.kubeconfig文件之中。

1
2
3
4
5
6
7
8
9
10
11
kubectl cluster-info  | grep "control plan"
# Kubernetes control plane is running at https://slb-vip.k8s:16443

# 设置集群参数写入到devopsuser.kubeconfig文件中
KUBE_APISERVER="https://slb-vip.k8s:16443"
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/pki/ca.crt \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=/root/.kube/devopsuser.kubeconfig
# Cluster "kubernetes" set.


步骤 06.为devopsuser用户创建一个devops-ctx上下文,并指定名称空间为devtest(在此上下文中在有rbac权限的情况下,只能操作该空间下的资源)并将配置写入到devopsuser.kubeconfig中。

1
2
kubectl config set-context devopsuser-ctx --cluster=kubernetes --user=devopsuser --namespace=devtest --kubeconfig=/root/.kube/devopsuser.kubeconfig
# Context "devopsuser-ctx" created.


步骤 07.在kubeconfig中设置devopsuser用户条目客户端参数,并将配置写入到devopsuser.kubeconfig中。

1
2
3
4
5
6
kubectl config set-credentials devopsuser --cluster=kubernetes \
--client-certificate=/etc/kubernetes/pki/user/devopsuser.pem \
--client-key=/etc/kubernetes/pki/user/devopsuser-key.pem \
--embed-certs=true \
--kubeconfig=/root/.kube/devopsuser.kubeconfig
# User "devopsuser" set.


步骤 08.查看生成的devopsuser.kubeconfig文件.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ cat devopsuser.kubeconfig
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: [api-server CA证书-base64编码]
server: https://slb-vip.k8s:16443 # API Server 地址
name: kubernetes
contexts:
- context:
cluster: kubernetes # 集群名称
namespace: devtest # 名称空间
user: devopsuser # 此上下文中的用户
name: devopsuser-ctx # 上下文名称
current-context: ""
kind: Config
preferences: {}
users:
- name: devopsuser # 创建的用户,认证方式为CA签名的证书。
user:
client-certificate-data: [客户端证书-base64编码]
client-key-data: [客户端密钥-base64编码]


步骤 09.RoleBinding 角色绑定,为devopsuser用户创建rolerolebinding,利用rbac进行资源访问操作权限的管控。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# 方式1.命令行方式(一步到位),生产环境中间建议为指定用户划分需要资源的权限。
kubectl create rolebinding devopsuser-admin --clusterrole=admin --user=devopsuser --namespace=devtest

# 方式2.资源清单方式
# Role 名称:devtest-role
# RoleBinding 名称:devopsuser-admin
tee devopsuser-rolebinding.yaml <<'EOF'
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: devtest-role
namespace: devtest
rules:
- apiGroups:
- ""
resources:
- pods
- pods/attach
- pods/exec
- pods/portforward
- pods/proxy
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- persistentvolumeclaims
- replicationcontrollers
- replicationcontrollers/scale
- secrets
- serviceaccounts
- services
- services/proxy
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:
- bindings
- events
- limitranges
- pods/log
- pods/status
- replicationcontrollers/status
- resourcequotas
- resourcequotas/status
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- serviceaccounts
verbs:
- impersonate
- apiGroups:
- apps
resources:
- deployments
- deployments/rollback
- deployments/scale
- statefulsets
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch
- apiGroups:
- autoscaling
resources:
- horizontalpodautoscalers
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch
- apiGroups:
- batch
resources:
- cronjobs
- jobs
- scheduledjobs
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch
- apiGroups:
- extensions
resources:
- daemonsets
- deployments
- deployments/rollback
- deployments/scale
- ingresses
- replicasets
- replicasets/scale
- replicationcontrollers/scale
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch
- apiGroups:
- authorization.k8s.io
resources:
- localsubjectaccessreviews
verbs:
- create
---
# roleRef 角色来源为 devtest-role
# subjects 赋予角色给 devopsuser 用户
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: devopsuser-admin
namespace: devtest
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: devtest-role
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: devopsuser
EOF

kubectl apply -f devopsuser-rolebinding.yaml
# role.rbac.authorization.k8s.io/devtest-role unchanged
# rolebinding.rbac.authorization.k8s.io/devopsuser-admin created


步骤 10.指定devopsuser用的kubeconfig并切换用户上下文。

1
2
3
4
5
6
7
8
9
10
11
12
# 切换用户上下文
kubectl config use-context devopsuser-ctx --kubeconfig=/root/.kube/devopsuser.kubeconfig
# Switched to context "devopsuser-ctx".

# 查看当前上下文
kubectl config current-context --kubeconfig=/root/.kube/devopsuser.kubeconfig
# devopsuser-ctx

# 当前上下文中的用户
kubectl config get-users --kubeconfig=/root/.kube/devopsuser.kubeconfig
# NAME
# devopsuser


步骤 11.验证创建devopsuser用户的权限。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 无权限查看节点以及操作其它名称空间的资源
kubectl --kubeconfig=/root/.kube/devopsuser.kubeconfig get node
# Error from server (Forbidden): nodes is forbidden: User "devopsuser" cannot list resource "nodes" in API group "" at the cluster scope

# 创建一个pod
kubectl --kubeconfig=/root/.kube/devopsuser.kubeconfig run nginx --image=nginx:latest --namespace devtest --labels="app=nginx" --port=8080
# pod/nginx created

# 查看Pod运行状态
kubectl --kubeconfig=/root/.kube/devopsuser.kubeconfig get pod -n devtest
# NAME READY STATUS RESTARTS AGE
# nginx 1/1 Running 0 37s

# 保留Pod服务
kubectl --kubeconfig=/root/.kube/devopsuser.kubeconfig expose pod nginx -n devtest --port=8080 --name=nginx-frontend
# service/nginx-frontend exposed

# 查看服务
kubectl --kubeconfig=/root/.kube/devopsuser.kubeconfig get pod -n devtest -l app=nginx -o wide
# NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
# nginx 1/1 Running 0 3h29m 10.66.182.255 weiyigeek-226 <none> <none>

至此完毕!


2.外部集群创建指定用户管理集群

描述: 在本地集群接入外部集群时我们需要获得其api-server地址(注意如果没有域名解析请做硬解析),以及ca证书, 此处同样以访问devtes名称空间为例。

步骤 01.外部集群信息及其CA证获取。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 远程集群中执行如下命令查看集群相关
$ kubectl cluster-info
# Kubernetes control plane is running at https://apiserver.cluster.weiyigeek:6443

$ ping apiserver.cluster.weiyigeek
# PING apiserver.cluster.weiyigeek (192.168.12.102) 56(84) bytes of data.
# 64 bytes from weiyigeek-102 (192.168.12.102): icmp_seq=1 ttl=64 time=0.134 ms

# 配置硬解析
sudo tee -a /etc/hosts <<'EOF'
192.168.12.102 apiserver.cluster.weiyigeek
EOF

# 将外部集群ca证书将其复制到现有机器上
ls /etc/kubernetes/pki/ca.crt && cat /etc/kubernetes/pki/ca.crt
cat > cluster.prod.ca.crt <<'EOF'
-----BEGIN CERTIFICATE-----
[上面显示的 base64 编码]
-----END CERTIFICATE-----
EOF


步骤02.在本地集群中利用kubectl config set-cluster命令设置远程集群。

1
2
3
4
5
6
KUBE_APISERVER="https://apiserver.cluster.weiyigeek:6443"
kubectl config set-cluster k8s-cluster \
--certificate-authority=./cluster.prod.ca.crt \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=/root/.kube/devops.kubeconfig


步骤03.在本地集群中利用 kubectl confi set-context 命令设置上下文。

1
2
3
4
5
6
kubectl config set-context devops-ctx \
--cluster=k8s-cluster \
--user=devops \
--namespace=devtest \
--kubeconfig=/root/.kube/devops.kubeconfig
# Context "devopsuser-ctx" created.


步骤04.在本地集群中,同样利用cfssl工具生成devops用户证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# 证书相关配置文件
$ tee ca-config.json << 'EOF'
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}
EOF

$ tee devops-csr.json << 'EOF'
{
"CN": "devops",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "ChongQing",
"L": "ChongQing",
"O": "k8s",
"OU": "System"
}
]
}
EOF

# 证书生成
tee cluster.prod.ca.key <<'EOF'
-----BEGIN RSA PRIVATE KEY-----
[远程集群 ca 私钥 base64 编码 ]
-----END RSA PRIVATE KEY-----
EOF

# 证书生成
cfssl gencert -ca=./cluster.prod.ca.crt -ca-key=./cluster.prod.ca.key -config ./ca-config.json -profile=kubernetes ./devops-csr.json | cfssljson -bare devops

# 将生成的证书以及密钥复制到/etc/kubernetes/pki/user目录中
sudo cp devops*.pem /etc/kubernetes/pki/user

步骤 05.在本地集群中利用 kubectl confi set-credentials 命令设置devops用户, 注意集群、上下文以及用户认证拼接都是写入到/root/.kube/devops.kubeconfig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
kubectl config set-credentials devops \
--cluster=k8s-cluster \
--client-certificate=/etc/kubernetes/pki/user/devops.pem \
--client-key=/etc/kubernetes/pki/user/devops-key.pem \
--embed-certs=true \
--kubeconfig=/root/.kube/devops.kubeconfig

# 切换上下文为devops-ctx
kubectl config use-context devops-ctx --kubeconfig=/root/.kube/devops.kubeconfig
# Switched to context "devops-ctx".

# 查看当前上下文
kubectl config current-context --kubeconfig=/root/.kube/devops.kubeconfig
# devops-ctx

步骤 06.在远端集群中执行如下命令给devops用户绑定指定名称空间中(devtest)拥有的角色及其赋予的权限。

1
2
3
4
kubectl create rolebinding devops --clusterrole=admin --user=devops --namespace=devtest 
kubectl get rolebindings.rbac.authorization.k8s.io -n devtest
# NAME ROLE AGE
# devops ClusterRole/admin 2s

温馨提示: 上面为了演示采用了kubernetes默认的admin角色,在实践环境中建议自己按照所需权限创建role然后再绑定给指定用户。

步骤 07.在本地集群中使用–kubeconfig指定前面生成集群连接配置,访问远端集群中devtest名称空间下的资源, 如果访问其它名称空间的资源是没有权限的。

1
2
3
4
5
6
7
8
kubectl --kubeconfig=/root/.kube/devops.kubeconfig get pod -n devtest
# NAME READY STATUS RESTARTS AGE
# oa-dev-0 1/1 Running 24 (2d17h ago) 16d
# redis-single-0 1/1 Running 0 47d

# 非 devtest 名称空间下的 资源是无权限的。
kubectl --kubeconfig=/root/.kube/devops.kubeconfig get pod -n devops
# Error from server (Forbidden): pods is forbidden: User "devops" cannot list resource "pods" in API group "" in the namespace "devops"