Featured image of post K8s Dashboard + Reloader 部署实战

K8s Dashboard + Reloader 部署实战

Dashboard v2.7.0 NodePort 部署 + admin-user Token、Reloader ConfigMap/Secret 自动热加载

Dashboard 与 Reloader

Dashboard 是 K8s 官方 Web UI,可以看 Pod/Service/Deployment 状态,看日志,exec 进容器,编辑资源。生产环境强烈建议部署一个,方便排障。

Reloader(stakater/Reloader)能监听 ConfigMap / Secret 变化,自动滚动升级引用了这些 ConfigMap/Secret 的 Deployment / StatefulSet / DaemonSet。生产环境必备——改一个配置不用手动 rollout。

适用版本:Dashboard v2.7.0 / Reloader v1.0.80 / K8s 1.28.5


1. Dashboard 部署

1.1 快速部署

1
2
3
4
mkdir -p /data/k8scnf/dashboard && cd /data/k8scnf/dashboard

# 默认官方 yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml

1.2 修改为 NodePort

默认 Dashboard Service 是 ClusterIP,外部访问不到。改成 NodePort:

1
kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard
1
2
3
4
5
6
7
8
spec:
  type: NodePort
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 32443
  selector:
    k8s-app: kubernetes-dashboard

或者直接修改 recommended.yaml 后 apply。

1.3 创建 admin user

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
cat << "EOF" > dashboard-user.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kube-system
EOF

kubectl apply -f dashboard-user.yaml

1.4 生成登录 token

1
2
3
4
5
# K8s 1.24+ 用 create token
kubectl -n kube-system create token admin-user

# K8s 1.23 及以下用以下方法
# kubectl -n kube-system get secret $(kubectl -n kube-system get sa/admin-user -o jsonpath="{.secrets[0].name}") -o jsonpath="{.data.token}" | base64 -d

token 默认 1 小时过期,可以延长:

1
kubectl edit -n kubernetes-dashboard deploy/kubernetes-dashboard
1
2
3
4
5
spec:
  containers:
  - args:
    - --auto-generate-certificates
    - --token-ttl=86400  # 单位分钟,1 天

1.5 访问 Dashboard

1
2
3
4
5
6
# 通过 VIP 访问(生产推荐)
https://<vip-internal>:32443/#/login
https://<vip-public>:32443/#/login

# 或通过任意 master 节点
https://<master1-ip>:32443/#/login

输入上一步生成的 token 即可登录。

1.6 修改 dashboard-metrics-scraper

Dashboard 还依赖 dashboard-metrics-scraper(拉取 metrics 数据),要确保镜像能拉到。如果用私有 harbor,需要替换:

1
2
3
4
5
kubectl edit deploy dashboard-metrics-scraper -n kubernetes-dashboard

# image: kubernetesui/metrics-scraper:v1.0.8
# 改为
# image: <private-registry>/base/kubernetesui/metrics-scraper:v1.0.8

2. Reloader 部署

2.1 为什么需要 Reloader

K8s Deployment 不会自动监听 ConfigMap 变化。改了一个 ConfigMap 之后,Pod 内的配置还是旧的——必须手动 kubectl rollout restart deployment

Reloader 通过 watch apiserver 事件解决这个问题:

  • 监听 reload.annotation 标注的 ConfigMap / Secret
  • 一旦内容变化,自动 rollout 引用此 ConfigMap 的所有 Deployment / StatefulSet / DaemonSet

2.2 部署

1
2
3
4
mkdir -p /data/k8scnf/reloader && cd /data/k8scnf/reloader

# 下载官方 yaml
curl -L -o reloader.yaml https://raw.githubusercontent.com/stakater/Reloader/master/deployments/kubernetes/reloader.yaml

修改镜像(用国内源 / 私有 harbor):

1
sed -i "s#stakater/reloader:#<private-registry>/base/stakater/reloader:#g" reloader.yaml

应用:

1
kubectl apply -f reloader.yaml

2.3 验证

1
2
3
4
kubectl get pods -A | grep reloader
# reloader-xxx                            1/1     Running   0          1m

kubectl logs -f <reloader-pod-name>

2.4 使用方法

自动 reload 所有 ConfigMap

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  annotations:
    reloader.stakater.com/auto: "true"  # 任何 ConfigMap/Secret 变化都自动 reload
spec:
  template:
    spec:
      containers:
      - name: my-app
        envFrom:
        - configMapRef:
            name: my-app-config

精确控制 reload 哪些 ConfigMap

1
2
3
4
5
6
7
8
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-app-config
  annotations:
    reloader.stakater.com/match: "true"  # 这个 ConfigMap 变化时,触发 reload 标了 reloader.stakater.com/match 的 Deployment
data:
  key: value
1
2
3
4
5
6
7
8
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  annotations:
    reloader.stakater.com/match: "true"  # 只 reload 标了 match 的 ConfigMap
spec:
  ...

Reload Secret

1
2
3
4
5
6
7
8
9
apiVersion: v1
kind: Secret
metadata:
  name: my-app-secret
  annotations:
    reloader.stakater.com/auto: "true"
type: Opaque
stringData:
  password: "{{SECRET_PASSWORD}}"

2.5 实战场景

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 1. 创建 ConfigMap
kubectl create cm mysql-config -n test --from-literal=db.host=mysql-master

# 2. Deployment 引用
# envFrom: configMapRef: name: mysql-config
# annotations: reloader.stakater.com/auto: "true"

# 3. 改 ConfigMap
kubectl edit cm mysql-config -n test
# 改一个 value 后 :wq 退出

# 4. 自动生效
# kubectl get pods -n test -l app=mysql
# 能看到 Pod 已经被重建

3. 排错

3.1 Dashboard 403 / token 无效

  • 检查 token 是否过期
  • 检查 ClusterRoleBinding 里的 namespace 是否正确

3.2 Dashboard 页面空白

metrics-scraper 没拉起来:

1
2
kubectl logs -n kubernetes-dashboard deploy/dashboard-metrics-scraper
# 通常是镜像拉不到

3.3 Reloader 不触发

  • 检查 Deployment 是否有 reloader.stakater.com/auto: "true" annotation
  • 检查 ConfigMap 是不是真的被 Deployment 引用
  • 看 Reloader Pod 日志:
1
kubectl logs -f -l app=reloader

3.4 Reloader 触发后 Pod 起不来

通常是 ConfigMap 内容错了。先 kubectl describe pod 看 event 排错。


4. 小结

Dashboard + Reloader 是 K8s 集群"运维体验"的关键:

  1. Dashboard 给非 K8s 用户一个 Web 入口,token 方式鉴权
  2. Reloader 让 ConfigMap 改动自动生效,省去手动 rollout
  3. 两者都依赖基础镜像能拉到,私有 harbor 部署要提前 tag + push

下一步:NFS 存储实战:单节点 + Keepalived 双机热备

使用 Hugo 构建
主题 StackJimmy 设计