Kubernetes 健康检查、认证授权与 Dashboard 小白教程
日期:2026-10-28
面向:零基础小白,每条命令可直接复制执行(命令后 ------ 是注释,别复制进去)
第一部分:Kubernetes Health Check(健康检查)
1. 这是干啥的
应用会突然"病倒":连接断开、配置错误、程序 bug。kubelet 用**探针(probe)**周期性检查容器里的应用是否健康,不行就重启它,保证服务不掉线。
2. 不配健康检查的后果(先看反面教材)
kubectl create ns health
kubectl config set-context --current --namespace health
kubectl run web --image=hub.laoma.cloud/library/httpd --image-pull-policy=IfNotPresent
kubectl describe pod web | grep '^IP:'
curl 10.224.73.16
kubectl exec web -- rm -f htdocs/index.html
kubectl get pod
删掉主页文件后,pod 状态依然是 Running------应用已经废了,K8s 还当你活着。这就是必须上探针的原因。
清理:kubectl delete pod web --force
3. 三种探针(记住三句话)
| 探针 | 问什么 | 不通过会怎样 |
|---|---|---|
| LivenessProbe 存活 | 你还活着吗? | 重启 pod |
| ReadinessProbe 就绪 | 能接客了吗? | 从 Service 的 endpoints 踢出去,不转发流量(但不重启) |
| StartupProbe 启动 | 启动完成了吗? | 启动期间不跑前两个探针,给慢启动应用保命 |
4. 四种检查方式
- httpGet:发 HTTP GET,返回码 200-399 算健康(适合 Web 应用)
- exec:进容器执行命令,退出码 0 算健康
- tcpSocket:端口能连上算健康
- grpc:调 gRPC 健康检查接口(今天不深入)
5. 探针 5 个参数(必背)
- initialDelaySeconds:容器启动后多久开始查(必填)
- timeoutSeconds:一次检查超时多久算失败(默认 1s)
- periodSeconds:隔多久查一次(默认 10s)
- successThreshold:连续成功几次才算健康(默认 1)
- failureThreshold:连续失败几次才算病倒(默认 3)
6. 实验一:livenessProbe + httpGet(活着就重启)
cat > deploy-httpGet-liveness.yaml <<'EOF'
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: hub.laoma.cloud/library/httpd
imagePullPolicy: IfNotPresent
name: httpd
livenessProbe:
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 10
httpGet:
path: /index.html
port: 80
scheme: HTTP
EOF
kubectl apply -f deploy-httpGet-liveness.yaml
kubectl get pod
kubectl exec web-85c6ff748f-qwszz -- bash -c 'rm htdocs/index.html'
kubectl get pod
看 RESTARTS 从 0 变 1------探针发现 index.html 没了,自动把容器重启,主页恢复:
curl 10.98.146.216
清理:kubectl delete deployments.apps web
7. 实验二:readinessProbe(就绪才接客,3 副本演示)
cat > deploy-httpGet-readiness.yaml <<'EOF'
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: hub.laoma.cloud/library/httpd
imagePullPolicy: IfNotPresent
name: httpd
readinessProbe:
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 10
httpGet:
path: /index.html
port: 80
scheme: HTTP
EOF
kubectl apply -f deploy-httpGet-readiness.yaml
kubectl expose deployment web --port=80 --target-port=80
给每个 pod 写上不同的主页,便于观察流量走向:
for pod in (kubectl get pods -o name \| awk -F / '{print 2}'); do kubectl exec pod -- bash -c "echo pod > htdocs/index.html"; done
kubectl get endpoints web
for i in {1...90}; do curl -s 10.96.180.30; done | sort | uniq -c
三个 pod 轮流接客(web-...-6bpg7 / -d2gbn / -hqh8q 都有流量)。
现在删掉一个 pod 的主页文件:
kubectl exec -it web-9479dc55c-6bpg7 -- rm -f htdocs/index.html
kubectl get endpoints web
endpoints 里少了一个 IP!再看 pod 状态:
kubectl get pod
web-9479dc55c-6bpg7 是 0/1(不 Ready)但 RESTARTS 是 0 ------readiness 只踢人不重启。再 curl,流量只剩两个 pod 的。这就是"就绪探针把病号从名单里踢出去"。
清理:kubectl delete deployments.apps web
8. 实验三:exec(命令退出码判健康)
cat > deploy-exec-liveness.yaml <<'EOF'
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: hub.laoma.cloud/library/httpd
imagePullPolicy: IfNotPresent
name: httpd
livenessProbe:
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 10
exec:
command:
-
cat
-
/usr/local/apache2/htdocs/index.html
EOF
kubectl apply -f deploy-exec-liveness.yaml
kubectl exec web-8c9ff9b76-nm6s2 -- bash -c 'rm htdocs/index.html'
kubectl get pods
cat 命令失败 → 探针失败 → RESTARTS 变 1。
busybox 加强版(自定义健康文件,10 秒后消失):
kubectl run busybox --image=busybox --image-pull-policy=IfNotPresent -o yaml --dry-run=client > busybox.yml
yaml 里关键加两段:
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 10; rm -rf /tmp/healthy; sleep 100
livenessProbe:
...
exec:
command:
- ls
- /tmp/healthy
启动 10 秒内健康文件在 → 探针通过;10 秒后被删 → 探针失败 → 重启。
9. 实验四:tcpSocket(端口通不通)
cat > deploy-tcpSocket-liveness.yaml <<'EOF'
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: hub.laoma.cloud/library/httpd
imagePullPolicy: IfNotPresent
name: httpd
livenessProbe:
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 10
tcpSocket:
port: 80
EOF
kubectl apply -f deploy-tcpSocket-liveness.yaml
端口连不上就重启。
10. 健康检查的两大实战场景(面试必考)
场景 1:Scale Up 扩容
应用启动要时间(加载缓存、连数据库),新副本没准备好就放进 Service 会把请求打崩。readiness 探针检查通过才让它接客。
场景 2:滚动更新
- 没配健康检查:新副本还没就绪就被当"好的"替换旧副本,全换完 → 整个服务瘫痪
- 配了健康检查:新副本通过探测才替换;不通过 → 旧副本继续服务,业务不断
11. 环境清理
kubectl delete ns health
第二部分:Kubernetes 认证和授权
1. 访问控制四道关(按顺序过)
一个请求进来,依次过:传输安全(TLS)→ ①身份认证 → ②鉴权 → ③准入控制 ,最后写入存储;全程有审计记录。
- ① 身份认证(Authentication):你是谁?失败返回 401
- ② 鉴权(Authorization):你配做这事吗?失败返回 403
- ③ 准入控制(Admission):请求内容能不能放行(可改可拒),只拦写操作不拦读
- 审计(Audit):按时间记录所有安全相关操作
2. 两类用户
- 普通用户(人):K8s 不管这个,由外部认证插件提供(如 X509 证书),证书 CN 字段就是用户名
- 服务账号 ServiceAccount(程序):K8s 自己管,绑 namespace,给 pod 里的程序用
3. 认证插件速览
- X509 客户证书:默认开启,你的 kubeconfig 就是它
- 静态令牌文件:--token-auth-file,默认不开
- 引导令牌 Bootstrap Token:kubeadm 建集群时用
- 服务账号令牌:自动启用
- Webhook / 认证代理:企业集成用
- basic-auth:1.19 以后弃用
- 匿名请求:没被拦下的就是 system:anonymous 匿名用户
4. 实验:用 X509 证书创建一个用户 laoma(重点,一步步来)
① 客户端准备材料
openssl genrsa -out laoma.key 2048
openssl req -new -key laoma.key -out laoma.csr -subj '/CN=laoma/O=kubernets'
CN(Common Name)就是用户名,O(Organization)是组。把 CSR 发给管理员:
scp laoma.csr root@master30:
② 管理员用集群 CA 签名发证
openssl x509 -req -in laoma.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out laoma.crt -days 1095
kubectl config view > config.tpl
scp config.tpl laoma.crt /etc/kubernetes/pki/ca.crt root@client:~
③ 客户端拼 kubeconfig(方法一:命令生成)
mv config.tpl config
kubectl config set-cluster kubernetes --kubeconfig=config --certificate-authority=ca.crt --embed-certs --server=https://10.1.8.30:6443
kubectl config set-credentials laoma --kubeconfig=config --client-key=laoma.key --client-certificate=laoma.crt --embed-certs
kubectl config set-context laoma --kubeconfig=config --namespace=default --cluster=kubernetes --user=laoma
参数速记:
- --embed-certs:把证书内容直接嵌进 config 文件(不用每次找路径)
- --namespace / --cluster / --user:context 三件套
④ 管理员授权后客户端就能干活了
kubectl create clusterrolebinding laoma-admin --clusterrole=cluster-admin --user=laoma
kubectl get nodes --kubeconfig=config
能列出节点,说明认证 + 授权全通。
⑤ 删除账户:删绑定即可(认证是证书干的,与 K8s 无关,彻底删要吊销证书)
kubectl delete clusterrolebindings.rbac.authorization.k8s.io laoma-admin
删完客户端再执行 kubectl get nodes,报 Forbidden------权限没了。
5. 授权模式有哪些
- Node:专给 kubelet 用的
- ABAC:属性策略,老古董
- RBAC:角色访问控制,主流,K8s 默认
- Webhook:外接企业系统
- AlwaysAllow:全放行(别在生产用)
- AlwaysDeny:全拒绝(admin 除外)
看当前用哪种:
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep mode
输出 --authorization-mode=Node,RBAC
6. role vs clusterrole(区别就一句话)
| 范围 | 怎么绑 | |
|---|---|---|
| Role | 只管一个命名空间 | rolebinding |
| ClusterRole | 管整个集群所有命名空间 | clusterrolebinding |
预定义 clusterrole 四兄弟:view(只读)< edit < admin(大部分权限)< cluster-admin(万能)
verbs 动作:get(查单个)、list(列清单)、watch(监听变化)、create、delete、update、patch、exec
7. 创建 role 三连
kubectl create role pod-role --verb=get,list,watch --resource=pods -n default
kubectl create rolebinding default-pod-laoma -n default --role=pod-role --user=laoma
kubectl get pod -n default
绑定后,laoma 在 default 里就能看 pod 了。回收:
kubectl delete rolebindings default-pod-laoma -n default
8. apiGroups 这个坑(必踩必背)
role 的 rules 里 apiGroups 写错,权限直接失效:
| 资源 | apiGroups |
|---|---|
| pod、service、PV、PVC | ""(空) |
| Deployment、DaemonSet、StatefulSet | apps |
| Job、CronJob | batch |
| Role/RoleBinding/ClusterRole/ClusterRoleBinding | rbac.authorization.k8s.io |
| NetworkPolicy | networking.k8s.io |
查法:kubectl explain deployment | grep VERSION
9. clusterrole 绑定两种模式(重点区别)
kubectl create clusterrole pod-role --verb=get,list,watch --resource=pods
- clusterrolebinding:绑定后全集群所有命名空间生效
- rolebinding 绑 clusterrole:只在当前命名空间生效
kubectl create clusterrolebinding laoma-pod-role --clusterrole=pod-role --user=laoma
绑完 laoma 在 kube-system、default 都能看 pod。
坑:给 clusterrole 指定"限定在 auth 命名空间"没意义,cluster 角色就是全局的。
10. 服务账户 ServiceAccount
每个命名空间默认有一个叫 default 的 SA,pod 不指定就用它跑。
kubectl get sa
kubectl run web --image=hub.laoma.cloud/library/httpd --image-pull-policy=IfNotPresent
kubectl get pod web -o yaml | grep serviceAccount
token 怎么进容器:1.24+ 版本不再自动建永久 Secret,改用短期 token(TokenRequest)。kubelet 把 token、ca.crt、namespace 三个文件自动挂到容器里:
kubectl exec -it web -- bash
ls /var/run/secrets/kubernetes.io/serviceaccount
里面有 ca.crt、namespace、token 三个文件。
pod 内程序访问 apiserver 的完整流程:
- 读 token 文件
- 请求头带 Authorization: Bearer
- 发给 apiserver
- apiserver 验 token,解析出是哪个 SA(ns + 名字)
- 找这个 SA 绑定的 RoleBinding / ClusterRoleBinding
- 按 RBAC 规则判断允不允许
- 返回结果
实验:建一个带权限的 SA
kubectl create sa sa1
kubectl create clusterrolebinding auth-sa1-cluster-admin --clusterrole=cluster-admin --serviceaccount=auth:sa1
格式:--serviceaccount=命名空间:SA名
cat > web.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
labels:
run: web
name: web
spec:
containers:
- image: httpd
imagePullPolicy: IfNotPresent
name: web
restartPolicy: Always
serviceAccount: sa1
serviceAccountName: sa1
EOF
kubectl apply -f web.yaml
提醒:pod 有了 cluster-admin 权限,不代表它会乱动------程序用什么权限是它自己代码说了算。
手动创建 token(两种):
- 临时令牌:kubectl create token sa1(带生命周期,pod 删了自动失效)
- 永久令牌:创建带注解 kubernetes.io/service-account.name: sa1 的 Secret(新版不推荐)
回收:kubectl delete clusterrolebindings auth-sa1-cluster-admin
第三部分:Kubernetes Dashboard
1. kuboard(第三方界面,老师课堂用)
Kuboard 是开源中文 K8s 管理界面,功能比官方 Dashboard 全(多集群、内置监控、终端工具、审计)。
在线体验:https://demo.kuboard.cn(用户 demo / 密码 demo123)
独立容器方式安装(不占集群资源,课堂推荐):
mkdir /kuboard-data
nerdctl run -d --name=kuboard
-p 80:80/tcp
-p 10081:10081/tcp
-e KUBOARD_ENDPOINT="http://10.1.8.30:80"
-e KUBOARD_AGENT_SERVER_TCP_PORT="10081"
-v /kuboard-data:/data
eipwork/kuboard:v3
浏览器访问 http://10.1.8.30,登录 admin / Kuboard123,导入集群时用 .kubeconfig 文件。
卸载:nerdctl container rm kuboard --force,再 rm -fr /kuboard-data
2. Kubernetes Dashboard(官方)
部署:
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.6.1/aio/deploy/recommended.yaml
grep image: recommended.yaml
wget -O recommended.yaml http://192.168.50.200/class/course-materials/software/stage03/kubernetes-dashboard-recommended-v2.6.1.yaml
grep image: recommended.yaml
kubectl apply -f recommended.yaml
镜像换成内网源(hub.laoma.cloud),执行部署。
验证:
kubens kubernetes-dashboard
kubectl get deployments.apps
kubectl get service
- dashboard 以 serviceAccount: kubernetes-dashboard 身份运行
- 它绑的 ClusterRole 默认只有读 metrics 的权限(nodes.metrics.k8s.io、pods.metrics.k8s.io)
- 所以刚装完的 dashboard 只能看监控数据,管理不了一点
改成 NodePort 方便访问:
kubectl edit svc kubernetes-dashboard
把 spec.type 改成 NodePort。再查看:
kubectl get svc kubernetes-dashboard
kubectl -n kubernetes-dashboard create token kubernetes-dashboard
浏览器访问 https://10.1.8.30:30518,选 Token 方式,粘贴上面生成的长 token 登录。
提示:新版本只支持 Bearer Token 登录;token 有效期 24 小时,过期重新生成。想要管理权限,把 cluster-admin 绑给 dashboard 的 SA 即可:
kubectl create clusterrolebinding kubernetes-dashboard-cluster-admin --clusterrole=cluster-admin --serviceaccount kubernetes-dashboard:kubernetes-dashboard
今日小结(一句话版)
- 健康检查:liveness 管死活(不健康就重启),readiness 管接客(不健康就踢出负载均衡),滚动更新和扩容都靠它保命
- 认证授权:认证问"你是谁"(X509 证书),授权问"你能干啥"(RBAC 角色),服务账号是给程序用的身份
- Dashboard:官方默认最小权限(只读监控),想管集群要自己绑 cluster-admin