2026-04-30
复习和预习
昨天课堂内容
- Pod Scheduler
- Metric Server and HPA
课前复习
默写
今天课堂内容
- Quota and Limits
- 健康检查
- 认证和授权
Quota and Limits
学习参考:
环境准备
-
创建一个独立的名字空间quota,并切换到该ns
bash[root@master30 ~]# kubectl create ns quota [root@master30 ~]# kubectl config set-context --current --namespace quota -
提前部署好 Metric Server
ResourceQuota
**问题:**当多个用户或团队共享Kubernetes集群时,有人会使用超过其基于公平原则所分配到的资源量。
**解决:**可以使用资源配额限制 Namespace 使用的资源。
资源配额 ,通过 ResourceQuota 对象来定义,对每个命名空间的资源消耗总量提供限制。
资源配额的工作方式如下:
-
不同的团队在不同的命名空间下工作。这可以通过 RBAC 强制执行。
-
集群管理员可以为每个命名空间创建一个或多个 ResourceQuota 对象。
-
当用户在命名空间下创建资源(如 Pod、Service 等)时,Kubernetes 的配额系统会跟踪集群的资源使用情况, 以确保使用的资源用量不超过 ResourceQuota 中定义的硬性资源限额。
-
如果资源创建或者更新请求违反了配额约束,那么该请求会报错(HTTP 403 FORBIDDEN), 并在消息中给出有可能违反的约束。
-
如果命名空间下的计算资源 (如
cpu和memory)的配额被启用, 则用户必须为这些资源设定请求值(request)和约束值(limit),否则配额系统将拒绝 Pod 的创建。提示: 可使用
LimitRanger准入控制器来为没有设置计算资源需求的 Pod 设置默认值。
启用资源配额
Kubernetes 默认启用了资源配额功能 。 当 API 服务器 的命令行标志 --enable-admission-plugins= 中包含 ResourceQuota 时, 资源配额会被启用。
当命名空间中存在一个 ResourceQuota 对象时,对于该命名空间而言,资源配额就是开启的。
配额类型
Kubernetes可以限制两种类型资源:
-
对象数量:Kubernetes 资源数量,例如pods,services等。
实施资源数量配额可以提高kubernetes稳定性,避免Etcd数据库无限增长,还可以避免占用node中其他功能资源(例如ip地址服务)。
-
计算资源:物理或者虚拟资源容量,例如 CPU,memory 和存储容量。
实施计算资源配额可以避免消耗 kubernetes 集群中单个node所有计算资源,避免单个namespace中应用消耗所有集群资源,导致其他namespace中应用无法正常运行。
**kubernetes 通过 ResourceQuota 类型资源实施配额。**一个namespace可以包含多个ResourceQuota对象,这些限制是累加的,一般情况,多个ResourceQuota对象不会限定同一个资源。
-
对象数量:
persistentvolumeclaimsservicessecretsconfigmapsreplicationcontrollersdeployments.appsreplicasets.appsstatefulsets.appsjobs.batchcronjobs.batch
-
资源名称 描述 limits.cpu在所有处于非终止状态的 Pod 中,CPU 限制的总和不能超过此值。 limits.memory在所有处于非终止状态的 Pod 中,内存限制的总和不能超过这个值。 requests.cpu在所有处于非终止状态的 Pod 中,CPU 请求的总和不能超过此值。 requests.memory在所有处于非终止状态的 Pod 中,内存请求的总和不能超过这个值。 requests.storage在所有持久卷声明中,存储请求的总和不能超过此值。 cpu与 requests.cpu一样memory与 requests.memory一样
单位说明:
- CPU :1 cpu 等于1000 m,默认单位是 cpu核心数量。
- memory :支持两种格式。
- Ki | Mi | Gi | Ti | Pi | Ei,进制是1024,例如1024 = 1Ki
- k | M | G | T | P | E,进制是1000,例如1000 = 1k
- 默认单位是 G,例如1.5,代表1500M。
配额管理
重要说明: 如果项目级别配额限定了 request 和 limit,那么创建pod的时候必须指定 request 和 limit。
创建 ResourceQuota 对象
bash
[root@master30 ~]# kubectl create quota myquota --hard=pods=2,services=3,secrets=5,persistentvolumeclaims=10
[root@master30 ~]# kubectl get resourcequotas
NAME AGE REQUEST LIMIT
my-quota 10s persistentvolumeclaims: 0/10, pods: 0/2, secrets: 1/5, services: 0/3
[root@master30 ~]# kubectl describe quota myquota
Name: myquota
Namespace: quota
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 10
pods 0 2
secrets 1 5
services 0 3
通过 yaml 文件创建
yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: myquota
spec:
hard:
persistentvolumeclaims: "10"
pods: "2"
secrets: "5"
services: "3"
测试配额
bash
[root@master30 ~]# kubectl create deployment web --image=docker.io/library/nginx --replicas=3
[root@master30 ~]# kubectl get all
NAME READY STATUS RESTARTS AGE
pod/web-96d5df5c8-dl7qk 1/1 Running 0 40s
pod/web-96d5df5c8-j7fhh 1/1 Running 0 40s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/web 2/3 2 2 40s
NAME DESIRED CURRENT READY AGE
replicaset.apps/web-96d5df5c8 3 2 2 40s
[root@master30 ~]# kubectl describe rs web-96d5df5c8
LAST SEEN TYPE REASON OBJECT MESSAGE
......
33s Warning FailedCreate replicaset/web-96d5df5c8 Error creating: pods "web-96d5df5c8-xg6c9" is forbidden: exceeded quota: myquota, requested: pods=1, used: pods=2, limited: pods=2
2s Warning FailedCreate replicaset/web-96d5df5c8 (combined from similar events): Error creating: pods "web-96d5df5c8-89p7j" is forbidden: exceeded quota: myquota, requested: pods=1, used: pods=2, limited: pods=2
25s Normal SuccessfulCreate replicaset/web-96d5df5c8 Created pod: web-96d5df5c8-bkzmd
34s Normal ScalingReplicaSet deployment/web Scaled up replica set web-96d5df5c8 to 3
# 超过配额,创建失败
# 修改配额 pod数量为10
[root@master30 ~]# kubectl patch resourcequotas myquota -p '{"spec":{"hard":{"pods":10}}}'
# 此时重新扩展rs
[root@master30 ~]# kubectl scale rs web-96d5df5c8 --replicas 3
# 再次验证pod数量
[root@master30 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
pod/web-96d5df5c8-ajcz2 1/1 Running 0 2s
pod/web-96d5df5c8-dl7qk 1/1 Running 0 60s
pod/web-96d5df5c8-j7fhh 1/1 Running 0 60s
# 清理环境
[root@master30 ~]# kubectl delete deployments.apps web
[root@master30 ~]# kubectl delete resourcequotas myquota
思考: 如果一个用户可以管理多个 namespace,能否限定该用户配额呢?
Request 和 Limits
如果命名空间下的计算资源 (如 cpu 和 memory)的配额被启用, 则用户必须为这些资源设定请求值(request)和约束值(limit),否则配额系统将拒绝 Pod 的创建。
pod.containers.resources 定义包含两部分:
-
requests ,指明pod运行需要的最少计算资源,调度器查找具有充足计算资源的nodes。
-
limits ,指明pod运行可以获得节点最多计算资源,用于阻止pod占用node太多计算资源。node使用Linux内核功能cgroup,限制pod资源使用。
测试-不指定计算资源
配额示例
bash
[root@master30 ~]# vim resourcequota.yaml
yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: myquota
spec:
hard:
persistentvolumeclaims: "10"
pods: "2"
secrets: "5"
services: "3"
requests.cpu: 1000m
requests.memory: "2048Mi"
limits.cpu: 1000m
limits.memory: "2048Mi"
bash
[root@master30 ~]# kubectl apply -f resourcequota.yaml
pod 示例
bash
[root@master30 ~]# vim pod-without-quota.yaml
yaml
apiVersion: v1
kind: Pod
metadata:
name: web
labels:
app: web
spec:
containers:
- name: web
image: httpd
imagePullPolicy: IfNotPresent
ports:
- name: web
containerPort: 80
protocol: TCP
bash
[root@master30 ~]# kubectl apply -f pod-without-quota.yaml
Error from server (Forbidden): error when creating "pod-without-quota.yaml": pods "web" is forbidden: failed quota: myquota: must specify limits.cpu for: web; limits.memory for: web; requests.cpu for: web; requests.memory for: web
# 清理环境
[root@master30 ~]# kubectl delete resourcequotas myquota
测试-Request
配额示例
bash
[root@master30 ~]# vim resourcequota.yaml
yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: myquota
spec:
hard:
requests.cpu: 1000m
requests.memory: "2048Mi"
bash
[root@master30 ~]# kubectl apply -f resourcequota.yaml
pod 示例1:超上限
bash
[root@master30 ~]# vim pod-request-1.yaml
yaml
apiVersion: v1
kind: Pod
metadata:
name: web
labels:
app: web
spec:
containers:
- name: web
image: docker.io/library/httpd
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 2000m
memory: 4096Mi
ports:
- name: web
containerPort: 80
protocol: TCP
bash
[root@master30 ~]# kubectl apply -f pod-request-1.yaml
Error from server (Forbidden): error when creating "pod-request-1.yaml": pods "web" is forbidden: exceeded quota: myquota, requested: requests.cpu=2,requests.memory=4Gi, used: requests.cpu=0,requests.memory=0, limited: requests.cpu=1,requests.memory=2Gi
pod 示例2:未超上限
bash
[root@master30 ~]# vim pod-request-2.yaml
yaml
apiVersion: v1
kind: Pod
metadata:
name: web
labels:
app: web
spec:
containers:
- name: web
image: docker.io/library/httpd
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 200m
memory: 1024Mi
ports:
- name: web
containerPort: 80
protocol: TCP
bash
[root@master30 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
web 1/1 Running 0 43s
# 验证使用情况
[root@master30 ~]# kubectl describe resourcequotas myquota
Name: myquota
Namespace: quota
Resource Used Hard
-------- ---- ----
requests.cpu 200m 1
requests.memory 1Gi 2Gi
# 删除pod和quota
[root@master30 ~]# kubectl delete pod web
[root@master30 ~]# kubectl delete resourcequotas myquota
测试-Limits
压力测试镜像
可以直接使用镜像 docker.io/progrium/stress 进行压力测试,该镜像中运行stress命令。
找讲师索取镜像。
bash
Usage: stress [OPTION [ARG]] ...
-?, --help show this help statement
--version show version statement
-v, --verbose be verbose
-q, --quiet be quiet
-n, --dry-run show what would have been done
-t, --timeout N timeout after N seconds
--backoff N wait factor of N microseconds before work starts
-c, --cpu N spawn N workers spinning on sqrt()
-i, --io N spawn N workers spinning on sync()
-m, --vm N spawn N workers spinning on malloc()/free()
--vm-bytes B malloc B bytes per vm worker (default is 256MB)
--vm-stride B touch a byte every B bytes (default is 4096)
--vm-hang N sleep N secs before free (default none, 0 is inf)
--vm-keep redirty memory instead of freeing and reallocating
-d, --hdd N spawn N workers spinning on write()/unlink()
--hdd-bytes B write B bytes per hdd worker (default is 1GB)
Example: stress --cpu 8 --io 4 --vm 2 --vm-bytes 128M --timeout 10s
Note: Numbers may be suffixed with s,m,h,d,y (time) or B,K,M,G (size).
常用选项:
-
-c, --cpu N spawn N workers spinning on sqrt()
-
-m, --vm N spawn N workers spinning on malloc()/free()
--vm-bytes B malloc B bytes per vm worker (default is 256MB)
-
-d, --hdd N spawn N workers spinning on write()/unlink()
--hdd-bytes B write B bytes per hdd worker (default is 1GB)
示例:
bash
# 压力测试内存
$ docker run --name stress docker.io/progrium/stress -m 1 --vm-bytes 512M
# 压力测试CPU
$ docker run --name stress docker.io/progrium/stress -c 1
# 压力测试IO
$ docker run --name stress docker.io/progrium/stress --d 1 --hdd-bytes 3G
对于 pod:
yaml
apiVersion: v1
kind: Pod
metadata:
name: stress
spec:
containers:
- name: stress
image: docker.io/progrium/stress
imagePullPolicy: IfNotPresent
command: ['sh','-c','sleep 3600']
# 或者不用command,而是使用args作为参数传递给镜像的Entrypoint。
#args: ['-m','1','--vm-bytes','512M']
#args: ['-c','1']
#args: ['-d','1','--hdd-bytes','3G']
配额示例
bash
[root@master30 ~]# vim resourcequota.yaml
yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: myquota
spec:
hard:
limits.cpu: 1000m
limits.memory: "2048Mi"
bash
[root@master30 ~]# kubectl apply -f resourcequota.yaml
测试 CPU 资源
pod示例:
bash
[root@master30 ~]# vim pod-limit-cpu.yaml
yaml
apiVersion: v1
kind: Pod
metadata:
name: stress
spec:
containers:
- name: stress
image: docker.io/progrium/stress
imagePullPolicy: IfNotPresent
args: ['-c','1']
resources:
limits:
cpu: 200m
memory: "256Mi"
bash
[root@master30 ~]# kubectl apply -f pod-limit-cpu.yaml
打开一个终端监控
kubectl top 命令需要提前部署Metrics-Server
bash
[root@master30 ~]# kubectl top pods
NAME CPU(cores) MEMORY(bytes)
stress 201m 0Mi
**可以发现:**CPU 使用率维持在 200m 左右。
bash
# 删除 pod
[root@master30 ~]# kubectl delete pod stress --force
测试 MEMORY 资源
pod示例:
bash
[root@master30 ~]# vim pod-limit-memory.yaml
yaml
apiVersion: v1
kind: Pod
metadata:
name: stress
spec:
containers:
- name: stress
image: docker.io/progrium/stress
imagePullPolicy: IfNotPresent
args: ['-m','1','--vm-bytes','512M']
resources:
limits:
cpu: 200m
memory: "256Mi"
bash
[root@master30 ~]# kubectl apply -f pod-limit-memory.yaml
打开一个终端监控
bash
[root@master30 ~]# kubectl get pods -w
NAME READY STATUS RESTARTS AGE
stress 0/1 OOMKilled 1 (2s ago) 3s
stress 0/1 CrashLoopBackOff 1 (2s ago) 4s
可以发现: Pod 状态为 OOMKilled,并进行restart。
bash
# 删除 pod he
[root@master30 ~]# kubectl delete pod stress --force
[root@master30 ~]# kubectl delete resourcequotas myquota
总结
-
计算资源的 limits 总和是否会超过节点上资源总和?
答案:可能会。 假设 node可用MEMORY为1G。
每个pod内存 requests是256M,limit是512M。创建5个pod,pod实际占用内存也为256M(有可能小于256M)。
node上大概可以创建4个pod,而此时的limits总和是2G。
-
当计算资源的limits总和超过节点上资源总和时,kubernetes如何处理?
- 对于 cpu ,kubernetes 认为 cpu 是可被压缩的资源,在应用达到limits时,减少该容器的调度时间,并不会杀死应用。
- 对于 memory ,kubernetes 认为 memory 是无法被压缩的资源 ,此时k8s 会杀死占用资源超过其request的应用(1.9版本之后的版本)。首当其冲的是没有指定request的container,然后是使用资源超过其request更多的container。同等情况下优先级更低的container更容易被杀死。
LimitRange
kubernetes创建pod时,默认不指定资源请求和限制。如果namespace设置了配额,那么创建不指定资源请求和资源限制的pod是不允许的。为了在设定配额的namespace中使用pod,namespace还需要为pod资源请求设定默认范围。
LimitRange 资源,也称为limits,定义了单个pod的资源请求和资源限制default、minimum、maximum值。pod的资源请求是其中所有容器请求的总和。
LimitRange 资源用于限定特定 namespace。
namespace设定了LimitRange,创建资源规则:
- 如果项目中请求一个未提供计算资源的对象,那么此时namespace将使用limit范围default值创建该对象。
- 如果项目中请求一个计算资源的对象,请求的资源小于limit最小值 ,那么该资源**无法创建**。
- 如果项目中请求一个计算资源的对象,请求的资源大于limit最大值 ,那么该资源**无法创建**。
LimitRange 示例
bash
[root@master30 ~]# vim limits.yaml
yaml
apiVersion: v1
kind: LimitRange
metadata:
name: mylimit
spec:
limits:
- type: Container
max:
memory: 1024Mi
cpu: 1
min:
memory: 128Mi
cpu: 100m
default:
memory: 512Mi
cpu: 500m
defaultRequest:
memory: 256Mi
cpu: 200m
说明:
name:只能使用小写字母,数字, '-' 和 '.',而且只能是数字或字母开头和结尾。default:即该namespace配置resourceQuota时,创建container的默认limit上限defaultRequest:即该namespace配置resourceQuota时,创建container的默认request上限max:即该namespace下创建container的资源最大值min:即该namespace下创建container的资源最小值
其中: min <= defaultRequest <= default <= max
bash
[root@master30 ~]# kubectl apply -f limits.yaml
[root@master30 ~]# kubectl get limitranges
NAME CREATED AT
mylimit 2021-09-09T04:09:15Z
[root@master30 ~]# kubectl describe limitranges mylimit
Name: mylimit
Namespace: quota
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container cpu 100m 1 200m 500m -
Container memory 128Mi 1Gi 256Mi 512Mi -
未指定 resources
示例1:
bash
[root@master30 ~]# vim pod-without-limits.yaml
yaml
apiVersion: v1
kind: Pod
metadata:
name: stress
spec:
containers:
- name: stress
image: docker.io/progrium/stress
imagePullPolicy: IfNotPresent
args: ['-c','1']
**结论:**创建出来的pod的resources 与 limitranage 指定的相关默认值一致。
bash
[root@master30 ~]# kubectl apply -f pod-without-limits.yaml
[root@master30 ~]# kubectl top pods
NAME CPU(cores) MEMORY(bytes)
stress 501m 0Mi
[root@master30 ~]# kubectl get pod stress -o yaml
yaml
......
spec:
containers:
image: docker.io/progrium/stress
imagePullPolicy: IfNotPresent
name: stress
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 200m
memory: 256Mi
......
bash
# 清理资源
[root@master30 ~]# kubectl delete limitranges mylimit
[root@master30 ~]# kubectl delete pod web --force
只指定 limit 值
示例 2-1:limit 值大于 max 值
yaml
apiVersion: v1
kind: Pod
metadata:
name: web
spec:
containers:
- name: web
image: docker.io/library/nginx
resources:
limits:
cpu: 1.1
memory: 1100Mi
bash
[root@master30 ~]# kubectl apply -f limit.yml
Error from server (Forbidden): error when creating "limit.yml": pods "web" is forbidden: [maximum cpu usage per Container is 1, but limit is 1100m, maximum memory usage per Container is 1Gi, but limit is 1181116006400m]
示例 2-2:limit 值小于 min 值
yaml
apiVersion: v1
kind: Pod
metadata:
name: web
spec:
containers:
- name: web
image: docker.io/library/nginx
resources:
limits:
cpu: 60m
memory: 60Mi
bash
[root@master30 ~]# kubectl apply -f limit.yml
Error from server (Forbidden): error when creating "limit.yml": pods "web" is forbidden: [minimum cpu usage per Container is 100m, but request is 60m, minimum memory usage per Container is 128Mi, but request is 60Mi]
示例 2-3:min 值< limit 值< max 值
yaml
apiVersion: v1
kind: Pod
metadata:
name: web
spec:
containers:
- name: web
image: docker.io/library/nginx
resources:
limits:
cpu: 600m
memory: 600Mi
结论:
-
创建的容器limits值必须满足条件:min值<指定的limit值<max值
-
当只指定limits值时,requests值与limits值保持一致,而不是default request。
yaml[root@master30 ~]# kubectl get pod web -o yaml ...... spec: containers: - image: docker.io/library/nginx imagePullPolicy: Always name: web resources: limits: cpu: 600m memory: 600Mi requests: cpu: 600m memory: 600Mi ......
只指定 requests
示例 3-1:requests 大于 max 值
yaml
apiVersion: v1
kind: Pod
metadata:
name: web
spec:
containers:
- name: web
image: docker.io/library/nginx
resources:
requests:
cpu: 1600m
memory: 600Mi
bash
[root@master30 ~]# kubectl apply -f limit4.yml
The Pod "web" is invalid:
* spec.containers[0].resources.requests: Invalid value: "1600m": must be less than or equal to cpu limit
* spec.containers[0].resources.requests: Invalid value: "1600Mi": must be less than or equal to memory limit
示例 3-2:requests 小于 min 值
yaml
apiVersion: v1
kind: Pod
metadata:
name: web
spec:
containers:
- name: web
image: docker.io/library/nginx
resources:
requests:
cpu: 60m
memory: 60Mi
bash
[root@master30 ~]# kubectl apply -f limit.yml
Error from server (Forbidden): error when creating "limit.yml": pods "web" is forbidden: [minimum cpu usage per Container is 100m, but request is 60m, minimum memory usage per Container is 128Mi, but request is 60Mi]
示例 3-3:min 值< request 值< max 值
yaml
apiVersion: v1
kind: Pod
metadata:
name: web
spec:
containers:
- name: web
image: docker.io/library/nginx
resources:
requests:
cpu: 400m
memory: 400Mi
结论:
-
创建的容器requests值必须满足条件:min值<requests值<limits值
-
当只指定requests值时,limits值与default值保持一致。
yaml[root@master30 ~]# kubectl get pod web -o yaml ...... spec: containers: - image: docker.io/library/nginx imagePullPolicy: Always name: web resources: limits: cpu: 500m memory: 512Mi requests: cpu: 400m memory: 400Mi ......
限定资源类型
LimitRange 资源可以限定如下资源:
| Type | Resource Name | Description |
|---|---|---|
| container | cpu、memory | 限定容器 cpu、memroy |
| Pod | cpu、memory | 限定 Pod 中所有容器cpu、memroy的总和 |
| PVC | storage | 限定PVC申请的存储空间大小 |
LimitRange for PVC 示例:
yaml
apiVersion: v1
kind: LimitRange
metadata:
name: storagelimits
spec:
limits:
- type: PersistentVolumeClaim
max:
storage: 2Gi
min:
storage: 1Gi
环境清理
bash
[root@master30 ~]# kubectl delete ns quota
Health Check
学习参考:配置存活、就绪和启动探针
环境准备
bash
[root@master30 ~]# kubectl create ns health
[root@master30 ~]# kubectl config set-context --current --namespace health
Health Check
应用可能会因为各种问题,变的 unhealthy,例如临时连接断开,配置错误,应用本身错误。
kubelet 使用 probes (探针),周期性地监控容器中应用是否为healthy状态,进一步决定什么时候要重启容器。 例如,当存活探针可以探测到应用死锁(应用在运行,但是无法继续执行后面的步骤)情况,进而重启pod,有助于提高应用的可用性,即使其中存在缺陷。
没有探测的情况,看一个例子:
bash
# 创建一个普通 pod
[root@master30 ~]# kubectl run web --image=docker.io/library/httpd --image-pull-policy=IfNotPresent
[root@laoma20 health]# kubectl describe pod web|grep '^IP:'
IP: 10.224.73.16
[root@master30 ~]# curl 10.224.73.16
<html><body><h1>It works!</h1></body></html>
# 删除主页文件,即使pod中应用数据丢失,pod状态依然为Running
[root@master30 ~]# kubectl exec web -- rm -f htdocs/index.html
# 查看主页内容
[root@master30 ~]# curl 10.224.73.16
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<title>Index of /</title>
</head>
<body>
<h1>Index of /</h1>
<ul></ul>
</body></html>
[root@master30 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
web 1/1 Running 0 51s
# 清理环境
[root@master30 ~]# kubectl delete pod web --force
Probe Type
kubelet 使用启动探针来了解应用容器何时启动。 如果配置了这类探针,存活探针和就绪探针成功之前不会重启,确保这些探针不会影响应用的启动。 启动探针可以用于对慢启动容器进行存活性检测,避免它们在启动运行之前就被杀掉。
-
LivenessProbe :用于确定pod中应用是否处于healthy 状态。如果liveness probe检测的状态为unhealthy ,则控制器将重启创建一个同名的pod。
-
ReadinessProbe:用于确定pod中应用是否可以提供服务。如果返回失败状态,则**服务将从endpoints 中删除容器ip地址。**即使容器处于运行状态,也不接受代理发过来的请求。
-
StartupProbe:用于确定pod是否成功初始化。 如果指定,则在成功完成之前不会执行其他探测。如果此探测失败,Pod 将重新启动,就像 livenessProbe 失败一样。 这可用于在 Pod 生命周期开始时提供不同的探测参数,此时加载数据或预热缓存可能需要比稳态操作期间更长的时间。 这无法更新。
我们这里不深入讨论StartupProbe。
Checking Methods
探针检查容器有四种不同的方法:
- httpGet ,对容器的 IP 地址上指定端口和路径执行 HTTP
GET请求。如果响应的状态码大于等于 200 且小于 400,则诊断被认为是成功的。 - exec,在容器内执行指定命令。如果命令退出时返回码为 0,则认为诊断成功。
- tcpSocket,对容器的 IP 地址上的指定端口执行 TCP 检查。如果端口打开,则诊断被认为是成功的。 如果远程系统(容器)在打开连接后立即将其关闭,这算作是健康的。
- grpc ,使用 gRPC 执行一个远程过程调用。 目标应该实现 gRPC 健康检查。 如果响应的状态是 "SERVING",则认为诊断成功。
我们这里不讨论 grpc 方法。
HTTP Checks-httpGet
当使用HTTP Checks,控制器使用webhoook判定容器健康情况。如果HTTP的响应码在200-399之间,判定check成功。适应范围:可以返回HTTP状态码应用。
livenessProbe
bash
[root@master30 ~]# vim deploy-httpGet-liveness.yaml
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web
name: web
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- image: docker.io/library/httpd
imagePullPolicy: IfNotPresent
name: httpd
# 添加livenessProbe部分
livenessProbe:
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 10
httpGet:
path: /index.html
# port填写时间web端口
port: 80
# scheme指定协议,HTTP或者HTTPS
scheme: HTTP
probe选项说明:
- initialDelaySeconds:必选。容器启动后多长时间,probe开始生效。
- timeoutSeconds:必选。probe需要多长时间完成。如果超过该值,控制器判定probe失败。默认值1s,最小值是1秒。
- periodSeconds:可选。检查频率。默认值10s,最小值是1秒。
- successThreshold:可选,连续成功最少次数后判定probe成功。默认值1,最小值是1。
- failureThreshold:可选。连续失败最少次数后判定probe失败。默认值3,最小值是1。
bash
[root@master30 ~]# kubectl apply -f deploy-httpGet-liveness.yaml
[root@master30 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
web-85c6ff748f-qwszz 1/1 Running 0 12m
[root@master30 ~]# kubectl describe pod web-85c6ff748f-j92jn|grep '^IP:'
IP: 10.98.146.216
# 删除主页文件
[root@master30 ~]# kubectl exec web-85c6ff748f-qwszz -- bash -c 'rm htdocs/index.html'
# 观察pod状态,RESTARTS次数变位1,再次访问
[root@master30 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
web-85c6ff748f-qwszz 1/1 Running 1 13m
# 容器删除需要一些时间,由参数terminationGracePeriodSeconds设定,默认值为30s。
# 只有等容器删除,并创建完成后才会继续检测
[root@master30 ~]# curl 10.98.146.216
<html><body><h1>It works!</h1></body></html>
# 清理环境
[root@master30 ~]# kubectl delete deployments.apps web
readinessProbe
bash
[root@master30 ~]# vim deploy-httpGet-readiness.yaml
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- image: docker.io/library/httpd
imagePullPolicy: IfNotPresent
name: httpd
# 添加readinessProbe部分
readinessProbe:
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 10
httpGet:
path: /index.html
port: 80
scheme: HTTP
bash
# 创建应用
[root@master30 ~]# kubectl apply -f deploy-httpGet-readiness.yaml
[root@master30 ~]# kubectl expose deployment web --port=80 --target-port=80
[root@master30 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
web ClusterIP 10.98.146.216 <none> 80/TCP 4m5s
[root@master30 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
web-9479dc55c-6bpg7 1/1 Running 0 2m34s
web-9479dc55c-d2gbn 1/1 Running 0 2m34s
web-9479dc55c-hqh8q 1/1 Running 0 2m34s
# 准备3个pod主页文件
[root@master30 ~]# for pod in $(kubectl get pods -o name|awk -F / '{print $2}'); do kubectl exec $pod -- bash -c "echo $pod > htdocs/index.html"; done
[root@master30 ~]# for i in {1..90};do curl -s 10.96.180.30;done|sort |uniq -c
24 web-9479dc55c-6bpg7
33 web-9479dc55c-d2gbn
33 web-9479dc55c-hqh8q
[root@master30 ~]# kubectl get endpoints web
NAME ENDPOINTS AGE
web 10.224.73.15:80,10.224.73.34:80,10.224.73.35:80 21m
# 删除 web-9479dc55c-6bpg7主页文件
[root@master30 ~]# kubectl exec -it web-9479dc55c-6bpg7 -- rm -f htdocs/index.html
# web 服务的后端没有pod的ip
[root@master30 ~]# kubectl get endpoints web
NAME ENDPOINTS AGE
web 10.224.73.15:80,10.224.73.34:80 23m
# 访问svc,后端无法看到 web-9479dc55c-6bpg7
[root@master30 ~]# for i in {1..90};do curl -s 10.96.180.30;done|sort |uniq -c
50 web2
40 web3
# 观察web1状态,READY为0,RESTARTS数量为0
[root@master30 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
web-9479dc55c-6bpg7 0/1 Running 0 8m49s
web-9479dc55c-d2gbn 1/1 Running 0 8m49s
web-9479dc55c-hqh8q 1/1 Running 0 8m49s
# 清理环境
[root@master30 ~]# kubectl delete deployments.apps web
Execution Checks-exec
当使用容器执行检测,kubelet代理将在容器内执行命令。返回值是0,代表check成功。
示例1:检测容器自带文件
bash
[root@master30 ~]# vim deploy-exec-liveness.yaml
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web
name: web
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- image: docker.io/library/httpd
imagePullPolicy: IfNotPresent
name: httpd
# 添加livenessProbe部分
livenessProbe:
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 10
exec:
command:
- cat
- /usr/local/apache2/htdocs/index.html
bash
# 创建应用
[root@master30 ~]# kubectl apply -f deploy-exec-liveness.yaml
[root@master30 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-8c9ff9b76-nm6s2 1/1 Running 1 (2s ago) 18s
# 删除主页文件
[root@master30 ~]# kubectl exec web-8c9ff9b76-nm6s2 -- bash -c 'rm htdocs/index.html'
# 观察pod状态,RESTARTS次数变位1
[root@master30 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
web 1/1 Running 1 4m5s
示例2:检测自定义文件
bash
[root@master30 ~]# kubectl run busybox --image=busybox --image-pull-policy=IfNotPresent -o yaml --dry-run=client > busybox.yml
[root@master30 ~]# vim deploy-exec-busybox.yml
yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: busybox
name: busybox
spec:
containers:
- image: busybox
imagePullPolicy: IfNotPresent
name: busybox
# 添加args参数
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 10; rm -rf /tmp/healthy; sleep 100
#添加livenessProbe参数
livenessProbe:
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 10
exec:
command:
- ls
- /tmp/healthy
dnsPolicy: ClusterFirst
restartPolicy: Always
TCP Socket Checks-tcpSocket
当使用TCP socket checks,kubelet代理尝试打开容器socket。如果check可以建立连接,判定check成功。
示例:liveness probe使用TCP Socket check
bash
[root@master30 ~]# vim deploy-tcpSocket-liveness.yaml
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web
name: web
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- image: docker.io/library/httpd
imagePullPolicy: IfNotPresent
name: httpd
# 添加livenessProbe部分
livenessProbe:
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 10
tcpSocket:
port: 80
Health Check Case
Health Check 在 Scale Up 中的应用
对于多副本应用, 当执行Scale Up操作时, 新副本会作为backend被添加到Service的负载均衡中, 与已有副本一起处理客户的请求。考虑到应用启动通常都需要一个准备阶段, 比如加载缓存数据、 连接数据库等, 从容器启动到真正能够提供服务是需要一段时间的。 我们可以通过Readiness探测判断容器是否就绪, 避免将请求发送到还没有准备好的backend。
Health Check 在滚动更新中的应用
Health Check另一个重要的应用场景是Rolling Update。 试想一下, 现有一个正常运行的多副本应用, 接下来对应用进行更新(比如使用更高版本的image) , Kubernetes会启动新副本, 然后发生了如下事件:
- 正常情况下新副本需要10秒钟完成准备工作, 在此之前无法响应业务请求。
- 由于人为配置错误, 副本始终无法完成准备工作(比如无法连接后端数据库)。
如果没有配置Health Check, 会出现怎样的情况?
因为新副本本身没有异常退出, 默认的Health Check机制会认为容器已经就绪, 进而会逐步用新副本替换现有副本, 其结果就是: 当所有旧副本都被替换后, 整个应用将无法处理请求, 无法对外提供服务。 如果这是发生在重要的生产系统上, 后果会非常严重。
如果正确配置了Health Check, 新副本只有通过了探测才会被添加到Service; 如果没有通过探测, 现有副本不会被全部替换, 业务仍然正常进行。
环境清理
bash
[root@master30 ~]# kubectl delete ns health
认证和授权
学习参考:API 访问控制
环境准备
bash
[root@master30 ~]# kubectl create ns auth
[root@master30 ~]# kubectl config set-context --current --namespace auth
Kubernetes API 访问控制
学习参考:Kubernetes API 访问控制
当用户使用User 或 服务账号访问Kubernetes API时,每个请求都会经过多阶段的访问控制之后才会被接受,包括身份认证、鉴权以及准入控制(Admission Control)。
如下图所示:

传输安全
默认情况下,Kubernetes API 服务器在第一个非 localhost 网络接口的 6443 端口上进行监听, 受 TLS 保护。在一个典型的 Kubernetes 生产集群中,API 使用 443 端口。 该端口可以通过 --secure-port 进行变更,监听 IP 地址可以通过 --bind-address 标志进行变更。
客户端向 Kubernetes API 服务器发起请求时,**API 服务器出示证书。**该证书可以使用私有证书颁发机构(CA)签名,也可以基于链接到公认的 CA 的公钥基础架构签名。 该证书和相应的私钥可以通过使用 --tls-cert-file 和 --tls-private-key-file 标志进行设置。
如果你的集群使用私有证书颁发机构,你需要在客户端的 ~/.kube/config 文件中提供该 CA 证书的副本, 以便你可以信任该连接并确认该连接没有被拦截。
身份认证
如上图步骤 ① 所示:Kubernetes 操作前首先进行身份认证(Authentication)。
Kubernetes 使用认证模块进行认证,认证模块包含客户端证书 、密码 、普通令牌、引导令牌和 JSON Web 令牌(JWT,用于服务账号)等。如果 Kubernetes 指定多个认证模块,服务器依次尝试每个验证模块,直到其中一个成功。
- 如果请求认证通过,下一步对该用户名进行鉴权。
- 如果请求认证不通过,服务器将以 HTTP 状态码 401 拒绝该请求。
身份认证组件在认证节中有更详细的描述。
鉴权
如上图的步骤 ② 所示,将请求验证为来自特定的用户后,请求必须被鉴权(Authorization)。请求必须包含请求者的用户名、请求的行为以及受该操作影响的对象。 如果现有策略声明用户有权完成请求的操作,那么该请求被鉴权通过。
示例: 以下策略,Bob 只能在 projectCaribou 名称空间中读取 Pod。
json
{
"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
"kind": "Policy",
"spec": {
"user": "bob",
"namespace": "projectCaribou",
"resource": "pods",
"readonly": true
}
}
- 如果 Bob 执行以下请求:读取
projectCaribou名称空间中的对象清单,其鉴权请求将被允许。
json
{
"apiVersion": "authorization.k8s.io/v1beta1",
"kind": "SubjectAccessReview",
"spec": {
"resourceAttributes": {
"namespace": "projectCaribou",
"verb": "get",
"group": "unicorn.example.org",
"resource": "pods"
}
}
}
- 如果 Bob 在
projectCaribou名字空间中请求写(create或update)对象或在其它名字空间中请求读取(get)对象,其鉴权请求会被拒绝。
**注意:**Kubernetes 鉴权要求使用公共 REST 属性与现有的组织范围或云提供商范围的访问控制系统进行交互。 使用 REST 格式很重要,因为这些控制系统可能会与 Kubernetes API 之外的 API 交互。
Kubernetes 支持多种鉴权模块,例如 ABAC 模式、RBAC 模式和 Webhook 模式等。 管理员创建集群时,他们配置应在 API 服务器中使用的鉴权模块。 如果配置了多个鉴权模块,则 Kubernetes 会检查每个模块,任意一个模块鉴权该请求,请求即可继续; 如果所有模块拒绝了该请求,请求将会被拒绝(HTTP 状态码 403)。
要了解更多有关 Kubernetes 鉴权的更多信息,包括有关使用支持鉴权模块创建策略的详细信息, 请参阅鉴权。
准入控制
这一操作如上图的步骤 ③ 所示。
-
准入控制器对创建、修改、删除或(通过代理)连接对象的请求进行操作。 当有多个准入控制器被配置时,服务器将依次调用它们。准入控制器不会对仅读取对象的请求起作用。准入控制模块是可以修改或拒绝请求的软件模块。 除鉴权模块可用的属性外,准入控制模块还可以访问正在创建或修改的对象的内容。
-
与身份认证和鉴权模块不同,如果任何准入控制器模块拒绝某请求,则该请求将立即被拒绝。除了拒绝对象之外,准入控制器还可以为字段设置复杂的默认值。
-
请求通过所有准入控制器后,将使用检验例程检查对应的 API 对象,然后将其写入对象存储(如步骤 4 所示)。
可用的准入控制模块参考 准入控制器。
审计
Kubernetes 审计提供了一套与安全相关的、按时间顺序排列的记录,其中记录了集群中的操作序列。 集群对用户、使用 Kubernetes API 的应用程序以及控制平面本身产生的活动进行审计。
更多信息请参考 审计。
认证管理
学习参考:认证
Kubernetes 中的用户
Kubernetes 集群有两类用户:
- 普通用户 ,Kubernetes 中普通用户不是由 kubernetes 直接提供,而是身份认证插件提供,Kubernetes 并不包含用来代表普通用户账号的对象 。 普通用户的信息无法通过 API 调用添加到集群中,Kubernetes 认为:能够提供由集群的证书机构签名的合法证书的用户是通过身份认证的用户。 基于这样的机制,Kubernetes 使用证书中的 'subject' 的通用名称(Common Name)字段 (例如,"/CN=bob")来确定用户名。 接下来,基于角色访问控制(RBAC)子系统会确定用户是否有权针对某资源执行特定的操作。
- 服务账号,Kubernetes 中服务账号是 Kubernetes API 所管理的用户。它们被绑定到特定的名字空间, 或者由 API 服务器自动创建,或者通过 API 调用创建。服务账号与一组以 Secret 保存的凭据相关,这些凭据会被挂载到 Pod 中,从而允许集群内的进程访问 Kubernetes API。
每个 API 请求必须包含一个用户:普通用户相关或者服务账号,客户端也可以发起匿名请求。这意味着集群内外的每个进程在向 API 服务器发起请求时都必须通过身份认证,否则会被视作匿名用户。
身份认证策略
Kubernetes 通过身份认证插件认证 API 请求的身份。HTTP 请求发给 API 服务器时,插件会将以下属性关联到请求本身:
- 用户名 :用来辩识最终用户的字符串。常见的值可以是
kube-admin或jane@example.com。 - 用户 ID:用来辩识最终用户的字符串,旨在比用户名有更好的一致性和唯一性。
- 用户组 :取值为一组字符串,其中各个字符串用来标明用户是某个命名的用户逻辑集合的成员。 常见的值可能是
system:masters或者devops-team等。 - 附加字段:一组额外的键-值映射,键是字符串,值是一组字符串; 用来保存一些鉴权组件可能觉得有用的额外信息。
所有(属性)值对于身份认证系统而言都是不透明的, 只有被鉴权组件解释过之后才有意义。
可以同时启用多种身份认证方法,通常至少使用两种方法:
- 针对服务账号使用服务账号令牌。
- 至少另外一种方法对用户的身份进行认证,例如X509客户证书。
Kubernetes 默认使用的是服务账号和X509客户证书。本课程深入探讨以上两种方法。
认证插件
Kubernetes支持同时开启多个认证插件,只要有一个认证通过即可。如果认证成功,则用户的username会被传入鉴权模块做进一步鉴权验证;而对于认证失败的请求则返回HTTP 401。
常用认证插件:
-
X509 客户证书
-
客户端用户与Kubernetes交互时候,使用的认证凭据文件.kube/config就是使用X509证书。
-
API Server启动时配置 --client-ca-file=SOMEFILE 参数。
-
bash
[root@master30 ~]# cat /etc/kubernetes/manifests/kube-apiserver.yaml |\
grep -- --client-ca-file
- --client-ca-file=/etc/kubernetes/pki/ca.crt
-
静态令牌文件
- API Server启动时配置 --token-auth-file=SOMEFILE 参数。
bash
[root@master30 ~]# cat /etc/kubernetes/manifests/kube-apiserver.yaml |\
grep -- --token-auth-file
- 文件为
csv格式,每行至少包括三列 token,username,user id。第四列为可选group 名项。如果有多个group名,列必须用""双引号包含其中,例如:
bash
token,user,uid,"group1,group2,group3"
-
默认未启用。
-
启动引导令牌
-
为了支持平滑地启动引导新的集群,Kubernetes 包含了一种动态管理的持有者令牌类型, 称作 启动引导令牌(Bootstrap Token) 。 这些令牌以 Secret 的形式保存在
kube-system名字空间中,可以被动态管理和创建。 使用kubeadm引导和管理集群时,kubeadm 会自动完成这些设置。 -
你必须在 API 服务器上设置
--enable-bootstrap-token-auth标志来启用基于启动引导令牌的身份认证组件。
-
bash
[root@master30 ~]# cat /etc/kubernetes/manifests/kube-apiserver.yaml |\
grep bootstrap
- --enable-bootstrap-token-auth=true
-
请参阅启动引导令牌, 以了解关于启动引导令牌身份认证组件详细信息。
-
服务账号令牌
-
服务账号(Service Account)是一种自动被启用的用户认证机制,使用经过签名的持有者令牌来验证请求。
-
服务账号通常由 API 服务器自动创建并通过
ServiceAccount准入控制器关联到集群中运行的 Pod 上。 持有者令牌会挂载到 Pod 中可预知的位置,允许集群内进程与 API 服务器通信。 -
服务账号也可以使用 Pod 规约的
serviceAccountName字段显式地关联到 Pod 上。
-
-
Webhook 令牌身份认证
Webhook 身份认证是一种用来验证持有者令牌的回调机制。
-
身份认证代理
API 服务器可以配置成从请求的头部字段值(如
X-Remote-User)中辩识用户。 这一设计是用来与某身份认证代理一起使用 API 服务器,代理负责设置请求的头部字段值。 -
basic-auth-file认证
在kubernetes 1.19及之后的版本中,kubernetes放弃了
basic-auth-file认证方式。
匿名请求
如果请求没有被已配置的身份认证方法拒绝, 则被视作匿名请求(Anonymous Requests)。这类请求获得用户名 system:anonymous 和对应的用户组 system:unauthenticated。
-
在 1.5.1-1.5.x 版本中,匿名访问默认情况下是被禁用的,可以通过为 API 服务器设定
--anonymous-auth=true来启用。 -
在 1.6 及之后版本中,如果所使用的鉴权模式不是
AlwaysAllow,则匿名访问默认是被启用的。 从 1.6 版本开始,ABAC 和 RBAC 鉴权模块要求对system:anonymous用户或者system:unauthenticated用户组执行显式的权限判定,所以之前的为用户*或用户组*赋予访问权限的策略规则都不再包含匿名用户。
**例如,**在一个配置了令牌身份认证且启用了匿名访问的服务器上,如果请求提供了非法的持有者令牌, 则会返回 401 Unauthorized 错误。如果请求没有提供持有者令牌,则被视为匿名请求。
创建账户
以下探讨使用 **X509客户证书 **插件管理用户。
客户端准备
客户端要想访问集群,必须安装与集群版本一致的kubectl工具。
bash
[root@client ~]# apt install -y kubectl=1.30.2-00
准备申请材料
bash
# 创建私钥
[root@client ~]# openssl genrsa -out laoma.key 2048
# 根据私钥,创建请求证书
[root@client ~]# openssl req -new -key laoma.key -out laoma.csr -subj '/CN=laoma/O=kubernets'
# 参数说明:
## C,Country,代表国家
## ST,STate,代表省份
## L,Location,代表城市
## O,Organization,代表组织,公司
## OU,Organization Unit,代表部门
## CN,Common Name,代表服务器域名
## emailAddress,代表联系人邮箱地址。
# 其他示例:
[root@client ~]# openssl req -new -key servera.key -out servera.csr -subj "/C=CHINA/ST=JS/L=NJ/O=LM/OU=DEVOPS/CN=servera.lab.example.com/emailAddress=laoma@lab.example.com"
# 客户端将自己请求证书发给kubernetes管理员
[root@client ~]# scp laoma.csr root@master30:
创建用户凭据
管理员使用以下资源文件创建用户的kubeconfig。
bash
# 使用ca.crt和ca.key签名laoma.csr,得到laoma.crt证书
[root@master30 ~]# openssl x509 -req -in laoma.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out laoma.crt -days 1095
# 导出kubeconfig模版
[root@master30 ~]# kubectl config view > config.tpl
# 将kubeconfig模板、laoma.crt和kubernetes的ca证书发给客户端
[root@master30 ~]# scp config.tpl laoma.crt /etc/kubernetes/pki/ca.crt root@client:~
创建 kubeconfig
kubeconfig创建方法:
**方法一:**使用kubectl config命令创建。
修改模版config.tpl,结果如下:
yaml
apiVersion: v1
clusters:
- cluster:
server: https://10.1.8.30:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
namespace: default
user: laoma
name: laoma@kubernetes
current-context: laoma@kubernetes
kind: Config
users:
- name: laoma
bash
# 设置 cluster
[root@client ~]# mv config.tpl config
[root@client ~]# kubectl config set-cluster kubernetes --kubeconfig=config --certificate-authority=ca.crt --embed-certs
# --kubeconfig指定kubeconfig文件
# --server指定kubernetes服务器认证地址
# --certificate-authority选项指定ca证书
# --embed-certs选项作用是将ca.crt的内容添加到config文件中,
# 如果没有该选项,则添加 --certificate-authority 选项指定的路径,也就是ca.crt
# 设置credentials
[root@client ~]# kubectl config set-credentials laoma --kubeconfig=config --client-key=laoma.key --client-certificate=laoma.crt --embed-certs
# --client-key 指定用户私钥
# --client-certificate 指定服务器为用户生成的证书
# 设置context
[root@client ~]# kubectl config set-context laoma --kubeconfig=config --namespace=default --cluster=kubernetes --user=laoma
# --namespace指定Namespace
# --cluster指定集群
# --user指定用户
# 授权用户laoma集群管理员角色,后续详细讲解角色管理
[root@master30 ~]# kubectl create clusterrolebinding laoma-admin --clusterrole=cluster-admin --user=laoma
# 验证结果
[root@client ~]# kubectl get nodes --kubeconfig=config
NAME STATUS ROLES AGE VERSION
master30.laoma.cloud Ready control-plane 40h v1.30.2
worker31.laoma.cloud Ready <none> 40h v1.30.2
worker32.laoma.cloud Ready <none> 40h v1.30.2
**方法二:**使用文本编辑器创建(不推荐)。
bash
# 获取文件ca.crt base64编码,填充到certificate-authority-data
[root@client ~]# cat ca.crt | base64 | tr -d '\n'
# 获取文件laoma.key base64编码,填充到client-key-data
[root@client ~]# cat laoma.key | base64 | tr -d '\n'
# 获取文件laoma.crt base64编码,填充到client-certificate-data
[root@client ~]# cat laoma.crt | base64 | tr -d '\n'
# 使用上面的base64编码修改配置文件对应值
[root@master30 ~]# kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://10.1.8.30:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-laoma
name: kubernetes-laoma@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-laoma
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
删除账户
bash
# 通过删除证书进行删除账户即可,为了后续操作方便,该账户不删除
# k8s删除用户csr资源后,客户端用户仍可以访问集群。
# 解释:用户认证功能由x509提供,与k8s无关。
# 如果不予许用户登录,应该从x509认证机制方面下手,例如ca.crt将相应客户端csr加入黑名单。
# 删除权限
[root@master30 ~]# kubectl delete clusterrolebindings.rbac.authorization.k8s.io laoma-admin
# 验证权限
[root@client ~]# kubectl get nodes
Error from server (Forbidden): nodes is forbidden: User "laoma" cannot list resource "nodes" in API group "" at the cluster scope
定集群
--user指定用户
授权用户laoma集群管理员角色,后续详细讲解角色管理
root@master30 \~\]# kubectl create clusterrolebinding laoma-admin --clusterrole=cluster-admin --user=laoma ## 验证结果 \[root@client \~\]# kubectl get nodes --kubeconfig=config NAME STATUS ROLES AGE VERSION master30.laoma.cloud Ready control-plane 40h v1.30.2 worker31.laoma.cloud Ready 40h v1.30.2 worker32.laoma.cloud Ready 40h v1.30.2 **方法二:**使用文本编辑器创建(不推荐)。 ```bash # 获取文件ca.crt base64编码,填充到certificate-authority-data [root@client ~]# cat ca.crt | base64 | tr -d '\n' # 获取文件laoma.key base64编码,填充到client-key-data [root@client ~]# cat laoma.key | base64 | tr -d '\n' # 获取文件laoma.crt base64编码,填充到client-certificate-data [root@client ~]# cat laoma.crt | base64 | tr -d '\n' # 使用上面的base64编码修改配置文件对应值 [root@master30 ~]# kubectl config view apiVersion: v1 clusters: - cluster: certificate-authority-data: DATA+OMITTED server: https://10.1.8.30:6443 name: kubernetes contexts: - context: cluster: kubernetes user: kubernetes-laoma name: kubernetes-laoma@kubernetes current-context: kubernetes-admin@kubernetes kind: Config preferences: {} users: - name: kubernetes-laoma user: client-certificate-data: REDACTED client-key-data: REDACTED #### 删除账户 ```bash # 通过删除证书进行删除账户即可,为了后续操作方便,该账户不删除 # k8s删除用户csr资源后,客户端用户仍可以访问集群。 # 解释:用户认证功能由x509提供,与k8s无关。 # 如果不予许用户登录,应该从x509认证机制方面下手,例如ca.crt将相应客户端csr加入黑名单。 # 删除权限 [root@master30 ~]# kubectl delete clusterrolebindings.rbac.authorization.k8s.io laoma-admin # 验证权限 [root@client ~]# kubectl get nodes Error from server (Forbidden): nodes is forbidden: User "laoma" cannot list resource "nodes" in API group "" at the cluster scope ```