Chemmy's Blog

chengming0916@outlook.com

前言

在使用Podman时,由于默认镜像源位于国外,下载镜像速度较慢甚至无法连接。本文将详细介绍如何在Windows系统上修改Podman的镜像配置源,实现镜像下载加速。

系统环境

  • 操作系统:Windows 10/11
  • Podman版本:适用于Windows的Podman Desktop
  • 依赖组件:WSL 2(Windows Subsystem for Linux)

解决方案

核心思路

将Podman的默认镜像源修改为国内镜像源,实现下载加速。

操作步骤

1. 打开Windows PowerShell

以管理员身份运行PowerShell,输入以下命令进入WSL子系统:

1
wsl

2. 修改registries.conf配置文件

在WSL子系统中,执行以下命令编辑配置文件:

1
sudo vi /etc/containers/registries.conf

如果使用其他编辑器,也可以使用:

1
sudo nano /etc/containers/registries.conf

3. 配置镜像源

在配置文件中添加或修改以下内容:

基本配置示例

1
2
3
4
5
unqualified-search-registries = ["docker.io"]

[[registry]]
prefix = "docker.io"
location = "你的阿里云加速器地址.mirror.aliyuncs.com"

完整配置示例(支持多个镜像源)

1
2
3
4
5
6
7
8
9
10
11
unqualified-search-registries = ["docker.io"]

[[registry]]
prefix = "docker.io"
location = "hub-mirror.c.163.com"

[[registry.mirror]]
location = "docker.mirrors.ustc.edu.cn"

[[registry.mirror]]
location = "registry.docker-cn.com"

4. 保存并退出

  • 在vi编辑器中:按Esc键,输入:wq,按Enter保存退出
  • 在nano编辑器中:按Ctrl+X,输入Y确认保存,按Enter退出

5. 重启Podman服务

退出WSL子系统后,执行以下操作:

方法一:重启WSL

1
2
wsl --shutdown
wsl

方法二:重启Podman机器

1
2
podman machine stop
podman machine start

方法三:重启计算机
如果上述方法无效,可以尝试重启计算机。

6. 验证配置

启动Podman后,可以通过以下命令验证镜像下载速度:

1
podman pull nginx:latest

国内镜像源地址

常用镜像源列表

镜像源名称 地址 备注
Docker中国区官方镜像 https://registry.docker-cn.com 官方镜像,稳定性好
网易镜像 http://hub-mirror.c.163.com 速度较快,推荐使用
中国科技大学镜像 http://docker.mirrors.ustc.edu.cn 教育网镜像
阿里云镜像 http://<你的ID>.mirror.aliyuncs.com 需要阿里云账号

阿里云镜像加速器获取步骤

  1. 登录阿里云控制台

  2. 进入镜像加速器页面

  3. 获取加速器地址

    • 页面会显示你的专属加速器地址
    • 格式如:xxxxxx.mirror.aliyuncs.com
    • 复制该地址用于配置

高级配置

多镜像源配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
unqualified-search-registries = ["docker.io"]

[[registry]]
prefix = "docker.io"
location = "hub-mirror.c.163.com"

[[registry.mirror]]
location = "docker.mirrors.ustc.edu.cn"

[[registry.mirror]]
location = "registry.docker-cn.com"

# 配置私有仓库
[[registry]]
location = "私有仓库地址"
insecure = true # 如果是HTTP而非HTTPS

用户级配置

除了系统级配置,还可以在用户目录下创建配置文件:

1
2
3
4
5
# 创建用户配置目录
mkdir -p ~/.config/containers

# 复制或创建配置文件
cp /etc/containers/registries.conf ~/.config/containers/

故障排除

常见问题及解决方案

1. 配置文件权限问题

1
2
3
4
5
# 检查文件权限
ls -l /etc/containers/registries.conf

# 修改权限(如果需要)
sudo chmod 644 /etc/containers/registries.conf

2. 配置语法错误

1
2
# 检查配置文件语法
podman info --debug

3. 镜像拉取失败

1
2
3
4
5
# 测试镜像拉取
podman pull hello-world

# 查看详细错误信息
podman pull --log-level=debug nginx:latest

4. WSL相关问题

1
2
3
4
5
# 检查WSL状态
wsl --list --verbose

# 重启WSL
wsl --shutdown

配置验证命令

1
2
3
4
5
# 查看当前配置
podman info | grep -A 10 "registries"

# 测试镜像下载速度
time podman pull nginx:latest

性能优化建议

1. 选择最佳镜像源

  • 根据地理位置选择最近的镜像源
  • 定期测试不同镜像源的下载速度
  • 可以配置多个镜像源,Podman会自动选择最快的

2. 缓存配置

1
2
3
4
5
# 查看缓存使用情况
podman system df

# 清理缓存
podman system prune -a

3. 网络优化

  • 确保Windows防火墙允许Podman和WSL的网络访问
  • 检查代理设置(如果有)
  • 使用有线网络而非Wi-Fi(如果可能)

相关资源

官方文档

社区资源

工具推荐

  • Podman Desktop:图形化管理工具
  • Lazydocker:终端UI工具
  • Dive:镜像分析工具

总结

通过修改Podman的镜像配置源,可以显著提高镜像下载速度,提升开发效率。关键步骤包括:

  1. 进入WSL子系统:使用wsl命令
  2. 编辑配置文件:修改/etc/containers/registries.conf
  3. 配置镜像源:添加国内镜像源地址
  4. 重启服务:重启WSL或Podman机器
  5. 验证配置:测试镜像下载速度

建议根据实际网络情况选择合适的镜像源,并定期更新配置以获得最佳性能。对于企业环境,可以考虑搭建私有镜像仓库,进一步提高安全性和稳定性。

一、核心定位

本文作为GitOps环境搭建系列的第二篇,聚焦Traefik反向代理的配置与优化。Traefik是K3s集群默认集成的云原生反向代理与负载均衡工具,具备动态配置、服务自动发现等核心特性,无需重启即可实时更新路由规则。

在GitOps环境中,Traefik扮演”流量入口网关”角色,为所有组件(Gitea、ArgoCD、Tekton、Harbor等)提供统一的HTTPS访问入口,实现域名路由、负载均衡、TLS终结等核心功能。通过Traefik的IngressRoute资源,可以灵活配置HTTP/HTTPS/TCP/UDP等多种协议的路由规则。

二、部署前置检查

部署前需验证K3s集群状态及Traefik基础运行情况:

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
# 1. 验证K3s集群状态
kubectl get nodes

# 2. 验证Traefik是否已运行(K3s默认集成)
kubectl get pods -n kube-system -l app=traefik

# 3. 查看Traefik Service
kubectl get svc -n kube-system traefik

# 4. 验证Helm可用性
helm version --short

# 5. 验证域名解析(替换为实际域名)
nslookup traefik.example.io
````

**前置条件检查清单:**

- [ ] K3s集群运行正常
- [ ] Traefik Pod处于Running状态
- [ ] 域名`traefik.example.io`已解析至K3s节点IP
- [ ] Helm工具可用
- [ ] 具备kube-system命名空间操作权限

## 三、启用Traefik Dashboard

K3s集群(版本≥1.21)默认集成Traefik,但未启用其Dashboard功能。需注意的是,直接修改`/var/lib/rancher/k3s/server/manifests/traefik.yaml`配置文件,会在K3s重启后被系统自动覆盖,因此推荐通过`HelmChartConfig`自定义配置的方式,安全稳定地启用Dashboard。

### 3.1 创建HelmChartConfig配置文件

在Master节点创建持久化配置:

```bash
# 创建HelmChartConfig配置文件
sudo cat > /var/lib/rancher/k3s/server/manifests/traefik-config.yaml << EOF
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: traefik
namespace: kube-system
spec:
valuesContent: |-
dashboard:
enabled: true
domain: traefik.example.io # 统一使用example.io域名
ports:
traefik:
expose: true
logs:
access:
enabled: true
EOF

# 重启K3s使配置生效
sudo systemctl restart k3s

3.2 配置Service与IngressRoute

创建traefik-dashboard.yaml配置文件:

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
# traefik-dashboard.yaml
apiVersion: v1
kind: Service
metadata:
name: traefik
namespace: kube-system
spec:
allocateLoadBalancerNodePorts: true
ports:
- name: web
nodePort: 80
port: 80
protocol: TCP
targetPort: web
- name: websecure
nodePort: 443
port: 443
protocol: TCP
targetPort: websecure
selector:
app.kubernetes.io/instance: traefik-kube-system
app.kubernetes.io/name: traefik
type: LoadBalancer

---

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dashboard-web
namespace: kube-system
spec:
entryPoints:
- web
routes:
- kind: Rule
match: Host(`traefik.example.io`) && PathPrefix(`/dashboard`) || PathPrefix(`/api`)
services:
- name: api@internal
kind: TraefikService

---

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dashboard-websecure
namespace: kube-system
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: Host(`traefik.example.io`) && PathPrefix(`/dashboard`) || PathPrefix(`/api`)
services:
- name: api@internal
kind: TraefikService
tls:
secretName: traefik-dashboard-tls

应用配置:

1
kubectl apply -f traefik-dashboard.yaml

注意:访问Dashboard时URL末尾必须添加/,正确格式为https://traefik.example.io/dashboard/

四、配置IngressRoute实现服务代理

4.1 创建测试环境

1
2
3
# 创建测试应用
kubectl create deploy whoami --image=traefik/whoami --replicas=2
kubectl expose deploy whoami --port=80

4.2 HTTP路由配置

创建HTTP路由规则,通过指定路径访问服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# whoami-http-ingress-route.yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: whoami-ingress-web
namespace: default
spec:
entryPoints:
- web
routes:
- match: Host(`traefik.example.io`) && PathPrefix(`/whoami`)
kind: Rule
services:
- name: whoami
port: 80

4.3 HTTPS路由配置

生成自签名证书(测试环境):

1
2
3
4
5
6
7
8
# 生成自签名证书
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key -out tls.crt \
-subj "/CN=traefik.example.io" \
-addext "subjectAltName=DNS:traefik.example.io"

# 创建TLS Secret
kubectl create secret tls whoami-tls --cert=tls.crt --key=tls.key

配置HTTPS路由:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# whoami-https-ingress-route.yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: whoami-ingress-websecure
namespace: default
spec:
entryPoints:
- websecure
routes:
- match: Host(`traefik.example.io`) && PathPrefix(`/secure/whoami`)
kind: Rule
services:
- name: whoami
port: 80
tls:
secretName: whoami-tls

生产环境建议:使用cert-manager自动管理证书,详见基于K3s搭建GitOps4-证书管理

4.4 TCP/UDP路由配置

Traefik支持代理MySQL、Redis等TCP/UDP服务,需通过IngressRouteTCPIngressRouteUDP配置。

以Redis服务为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# redis-tcp-ingress-route.yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
name: redis
namespace: devops
spec:
entryPoints:
- redis # 需在Traefik配置中启用redis入口点
routes:
- match: HostSNI(`*`)
services:
- name: redis
port: 6379

TCP与HTTP路由差异:

  1. TCP路由使用HostSNI('*')匹配,HTTP路由使用Host()匹配
  2. TCP路由仅代理TCP协议,无法处理HTTP请求
  3. 同一入口点上,TCP路由优先级高于HTTP路由

五、验证部署结果

5.1 验证Traefik组件状态

1
2
3
4
5
6
7
8
9
10
11
# 查看Traefik Pod状态
kubectl get pods -n kube-system -l app=traefik

# 查看Traefik Service
kubectl get svc -n kube-system traefik

# 查看IngressRoute资源
kubectl get ingressroute -A

# 查看Traefik日志
kubectl logs -n kube-system -l app=traefik --tail=50

5.2 验证路由功能

1
2
3
4
5
6
7
8
9
10
# 测试HTTP访问
curl -v http://traefik.example.io/dashboard/
curl -v http://traefik.example.io/whoami

# 测试HTTPS访问(跳过证书验证)
curl -k -v https://traefik.example.io/dashboard/
curl -k -v https://traefik.example.io/secure/whoami

# 查看路由配置
kubectl describe ingressroute traefik-dashboard-websecure -n kube-system

5.3 清理测试资源

1
2
3
4
5
6
7
# 清理测试应用
kubectl delete deploy whoami
kubectl delete svc whoami

# 清理路由配置
kubectl delete ingressroute whoami-ingress-web whoami-ingress-websecure
kubectl delete secret whoami-tls

六、生产环境配置建议

6.1 启用访问日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 在HelmChartConfig中添加日志配置
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: traefik
namespace: kube-system
spec:
valuesContent: |-
logs:
access:
enabled: true
format: json # 使用JSON格式便于日志分析
fields:
general:
defaultMode: keep
headers:
defaultMode: keep

6.2 配置中间件

Traefik中间件可用于实现路径重写、请求限流、认证等高级功能:

1
2
3
4
5
6
7
8
9
10
# 路径重写中间件示例
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: strip-prefix
namespace: default
spec:
stripPrefix:
prefixes:
- /api/v1

6.3 启用指标监控

1
2
3
4
5
6
7
8
9
10
11
12
13
# 启用Prometheus指标
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: traefik
namespace: kube-system
spec:
valuesContent: |-
metrics:
prometheus:
enabled: true
addEntryPointsLabels: true
addServicesLabels: true

七、常见问题修复

问题现象 排查方向 修复方案
Dashboard访问404 路由配置/路径格式 确认访问URL以/结尾,检查IngressRoute配置
HTTPS证书警告 证书配置/TLS Secret 检查证书Secret是否存在,确认域名匹配
服务无法访问 服务发现/端口映射 检查Service selector是否匹配Pod标签
TCP路由不生效 入口点配置 确认Traefik已启用对应TCP入口点
配置被覆盖 HelmChartConfig位置 确认配置文件在/var/lib/rancher/k3s/server/manifests/目录

八、配置参考

所有Traefik配置文件和部署脚本请参考:
https://gitee.com/Chemmy/kube-template/tree/master/devops/traefik

该目录包含:

  • Traefik Dashboard配置
  • IngressRoute示例
  • 中间件配置
  • 生产环境优化配置
  • 监控和日志配置

总结

本文完成了Traefik在K3s集群中的完整配置,包括Dashboard启用、HTTP/HTTPS路由配置、TCP/UDP服务代理等核心功能。Traefik作为GitOps环境的流量入口网关,为后续组件(Gitea、ArgoCD、Tekton、Harbor)提供了统一的访问入口和安全的路由能力。

配置完成后,建议通过测试应用验证各项功能正常。下一篇文章将配置CoreDNS内网域名解析,实现通过域名访问所有GitOps组件。

LibVLCSharp版本

1
2
3
<PackageReference Include="LibVLCSharp" version="3.6.6" />
<PackageReference Include="LibVLCSharp.WPF" version="3.6.6" />
<PackageReference Include="VideoLAN.LibVLC.Windows" version="3.0.16" />

现象播放RTSP视频流时在VideoView播放正常,但会弹出一个窗体同时播放,窗体名VLC (Direct3D11 output)

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public partial class MainWindow : Window
{
private LibVLC m_libVLC;

public MainWindow()
{
InitializeComponent();

this.Loaded += MainWindow_Loaded;

m_libVLC = new LibVLC();
}

private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
VideoView.MediaPlayer = new LibVLCSharp.Shared.MediaPlayer(m_libVLC);
VideoView.MediaPlayer.Play(new Media(m_libVLC, new Uri(uri)));
}
}

故障原因

打断点调试发现,Loaded时间执行两次,第一次执行在VideoView播放正常,第二次执行弹出VLC (Direct3D11 output)

解决方法: 控制只初始化和播放一次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public partial class MainWindow : Window
{
private LibVLC m_libVLC;

public MainWindow()
{
InitializeComponent();

this.Loaded += MainWindow_Loaded;

m_libVLC = new LibVLC();
}

private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
VideoView.MediaPlayer ??= new LibVLCSharp.Shared.MediaPlayer(m_libVLC)
{
Media = new Media(m_libVLC, new Uri(uri))
};

if (!VideoView.MediaPlayer.IsPlaying)
VideoView.MediaPlayer.Play();
}
}

PostgreSQL作为一款高性能、开源的关系型数据库,在云原生场景中,常需与轻量级Kubernetes发行版K3s结合部署,以实现资源高效利用与灵活运维。本文将详细拆解基于K3s部署PostgreSQL的完整流程,涵盖存储配置、配置管理、服务暴露及部署编排等核心环节,助力开发者快速完成部署落地。

一、环境准备

部署前需确保K3s集群已正常运行,且kubectl工具已完成集群连接配置(可通过kubectl get nodes命令验证集群状态)。本文所有资源配置均部署在独立的postgres命名空间下,避免与其他应用资源冲突,需先执行以下命令创建该命名空间:

1
kubectl create namespace postgres

二、存储配置:PersistentVolume与PersistentVolumeClaim

PostgreSQL作为有状态应用,数据持久化是核心需求。本文提供两种存储配置方案,可根据集群规模(单节点/多节点)及实际存储需求灵活选择。

方案1:基于local-path存储类(单节点场景)

local-path是K3s默认集成的存储类,适用于单节点K3s集群,无需手动创建PersistentVolume(PV),仅需定义PersistentVolumeClaim(PVC),系统会自动创建PV并完成绑定。创建postgres-pvc-local-path.yaml配置文件,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
namespace: postgres
labels:
app: postgres
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 10Gi

该配置声明了10Gi的存储资源请求,访问模式为ReadWriteOnce(仅允许单个节点读写),完全适配单节点K3s的部署场景,配置简洁且无需额外运维。

方案2:基于hostPath的自定义存储类(多节点/自定义路径场景)

若需自定义存储路径,或集群为多节点架构,可手动创建PV并绑定PVC,实现更灵活的存储管理。创建postgres-pvc-host-path.yaml文件,包含PV与PVC的完整定义(修正原文中storge的拼写错误为storage):

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
apiVersion: v1
kind: PersistentVolume
metadata:
name: postgres-pv
namespace: postgres
labels:
app: postgres
spec:
storageClassName: postgres-persistent-storage
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
hostPath:
path: /mnt/postgres/data
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
labels:
app: postgres
spec:
storageClassName: postgres-persistent-storage
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi

需提前在集群节点上创建/mnt/postgres/data目录,并确保目录权限正确(建议设置为777或匹配Pod运行用户权限);访问模式ReadWriteMany支持多节点读写,可满足多节点K3s集群的部署需求。

执行以下命令创建对应存储资源:

1
2
3
4
# 方案1(单节点)
kubectl apply -f postgres-pvc-local-path.yaml
# 方案2(多节点/自定义路径)
kubectl apply -f postgres-pvc-host-path.yaml

三、配置管理:ConfigMap定义环境变量

PostgreSQL的核心初始化配置(如默认数据库名、管理员用户名、密码)可通过ConfigMap统一管理,便于后续配置修改与维护,无需重新构建镜像或重启Pod。创建postgres-config.yaml配置文件:

1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: ConfigMap
metadata:
name: postgres-config
namespace: postgres
labels:
app: postgres
data:
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres

本文为简化部署流程,使用ConfigMap存储密码;实际生产环境中,建议使用Secret存储敏感信息(如数据库密码),提升配置安全性。

执行以下命令创建ConfigMap资源:

1
kubectl apply -f postgres-config.yaml

四、服务暴露:Service与IngressRouteTCP

为实现PostgreSQL的可访问性,需根据访问场景(集群内/集群外)配置对应的服务暴露方式。K3s默认集成Traefik作为Ingress控制器,可通过Service实现集群内访问,通过IngressRouteTCP实现集群外访问。

1. ClusterIP类型Service(集群内访问)

创建postgres-service.yaml文件,定义ClusterIP类型的Service,监听PostgreSQL默认端口5432,实现集群内Pod间的访问:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: v1
kind: Service
metadata:
name: postgres
namespace: postgres
labels:
app: postgres
spec:
ports:
- port: 5432
targetPort: 5432
protocol: TCP
selector:
app: postgres
type: ClusterIP

ClusterIP类型Service仅允许集群内Pod访问,集群内其他应用可通过服务域名postgres.postgres.svc.cluster.local:5432连接PostgreSQL数据库。

2. IngressRouteTCP(集群外访问)

若需从集群外访问PostgreSQL,可通过Traefik的IngressRouteTCP暴露TCP端口。创建postgres-ingress.yaml文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
name: postgres-tcp
namespace: postgres
labels:
app: postgres
spec:
entryPoints:
- postgres
routes:
- match: HostSNI(`*`)
services:
- name: postgres
port: 5432

需先在Traefik控制器中配置postgres入口点(entryPoints),指定监听的主机端口(建议与PostgreSQL默认端口5432保持一致),否则IngressRouteTCP配置无法生效。

执行以下命令创建服务相关资源:

1
2
kubectl apply -f postgres-service.yaml
kubectl apply -f postgres-ingress.yaml

五、部署编排:StatefulSet部署PostgreSQL

PostgreSQL作为有状态应用,推荐使用StatefulSet而非Deployment部署,可确保Pod拥有稳定的网络标识和持久化存储,避免因Pod重启导致数据丢失或网络地址变更。创建postgres-statefulset.yaml文件(修正原文“deployment.yaml”命名偏差,贴合StatefulSet资源类型):

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
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
namespace: postgres
labels:
app: postgres
spec:
selector:
matchLabels:
app: postgres
replicas: 1
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16.3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5432
envFrom:
- configMapRef:
name: postgres-config
volumeMounts:
- name: postgredb
mountPath: /var/lib/postgresql/data
volumes:
- name: postgredb
persistentVolumeClaim:
claimName: postgres-pvc

使用postgres:16.3稳定版本镜像,通过envFrom批量加载ConfigMap中的环境变量,将PVC挂载到PostgreSQL的数据存储目录/var/lib/postgresql/data,确保数据持久化;镜像拉取策略设为IfNotPresent,避免重复拉取镜像,提升部署效率。

执行以下命令部署PostgreSQL:

1
kubectl apply -f postgres-statefulset.yaml

六、验证部署结果

部署完成后,需通过一系列命令验证各资源状态,确保PostgreSQL正常运行。

  1. 检查PVC绑定状态:
1
kubectl get pvc -n postgres

正常情况下,PVC的STATUS列显示为Bound,表示存储绑定成功。

  1. 检查StatefulSet与Pod运行状态:
1
2
kubectl get statefulset -n postgres
kubectl get pods -n postgres

确保StatefulSet的READY列显示为1/1(副本数为1时),Pod的STATUS列显示为Running,无异常重启记录。

  1. 测试数据库连接:
1
2
3
4
# 进入PostgreSQL Pod内部
kubectl exec -it postgres-0 -n postgres -- bash
# 连接PostgreSQL数据库(使用ConfigMap中定义的用户名和数据库名)
psql -U postgres -d postgres

若能成功进入PostgreSQL命令行界面(显示postgres=#提示符),说明PostgreSQL部署成功且可正常使用。

总结

本文基于K3s原生资源(PVC/PV、ConfigMap、Service、StatefulSet),完成了PostgreSQL的全流程部署,覆盖了存储配置、配置管理、服务暴露、部署编排及结果验证等核心环节,流程清晰、可操作性强。在实际生产环境中,可根据业务需求灵活调整:如增加副本数实现高可用、使用Secret管理敏感信息、优化Ingress配置实现访问控制等,进一步提升部署的安全性与稳定性。

在K3s集群中部署MySQL,需结合Kubernetes资源编排特性,合理配置存储、网络、配置项等核心组件,确保数据库服务稳定、可访问且数据安全。本文将详细拆解基于K3s部署MySQL的完整流程,涵盖资源配置文件编写、部署操作及关键注意要点,助力开发者快速完成部署落地。

一、环境说明

本文基于K3s集群环境,通过Kubernetes各类核心资源对象(StatefulSet、Service、PVC/PV、ConfigMap、IngressRouteTCP),实现MySQL 5.7版本的规范化部署,重点保障数据持久化、集群内外网络可访问及配置灵活自定义。所有资源均部署在mysql命名空间下,需提前执行命令创建该命名空间:kubectl create namespace mysql

二、核心资源配置与部署

1. 配置自定义参数:ConfigMap

MySQL的核心运行参数通过ConfigMap进行统一管理,便于后续参数调整、维护及复用。创建mysql-config.yaml配置文件,明确定义字符集、最大连接数、绑定地址等关键参数,具体内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-config
namespace: mysql
labels:
app: mysql-config
data:
mysqld.cnf: |
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
skip-character-set-client-handshake = true
max_connections=2000
secure_file_priv=/var/lib/mysql
datadir=/var/lib/mysql
bind-address=0.0.0.0
symbolic-links=0

该配置已做针对性优化:将字符集统一设置为utf8mb4,彻底解决中文乱码及特殊字符存储问题;绑定地址设为0.0.0.0,确保MySQL可被K3s集群内所有节点访问;调整最大连接数至2000,满足中高并发业务场景需求。配置文件编写完成后,执行以下命令部署ConfigMap:

1
kubectl apply -f mysql-config.yaml

2. 数据持久化:PVC/PV配置

MySQL作为关系型数据库,数据持久化是核心需求,需通过PVC(持久化卷声明)和PV(持久化卷)配置,避免Pod重建、重启后数据丢失。本文提供两种存储方案,可根据实际部署场景灵活选择。

方案1:基于local-path存储类(推荐)

K3s集群默认内置local-path存储类,无需手动创建PV,仅需创建PVC即可自动完成PV绑定,部署高效便捷。创建mysql-pvc-local-path.yaml文件,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
namespace: mysql
labels:
app: mysql
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 10Gi

执行部署命令,完成PVC创建:

1
kubectl apply -f mysql-pvc-local-path.yaml

方案2:基于hostPath的PV/PVC(自定义存储路径)

若需指定K3s节点本地具体路径作为MySQL数据存储位置,可手动创建PV和PVC。需注意,原始配置文件mysql-pvc-host-path.yaml中存在笔误(storge应为storage),修正后完整配置如下:

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
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv
namespace: mysql
labels:
app: mysql
spec:
storageClassName: mysql-persistent-storage
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
hostPath:
path: /var/lib/mysql/data

---

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
namespace: mysql
labels:
app: mysql
spec:
storageClassName: mysql-persistent-storage
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi

执行部署命令,完成PV和PVC创建:

1
kubectl apply -f mysql-pvc-host-path.yaml

注意:hostPath存储方案仅适用于单节点K3s集群;多节点集群需使用NFS等共享存储方案,确保数据一致性和可访问性。

3. 部署MySQL实例:StatefulSet

采用StatefulSet部署MySQL实例,可保证Pod名称固定、存储挂载稳定,更适配数据库这类有状态应用的部署需求。创建mysql-deployment.yaml文件(实际为StatefulSet资源类型,命名仅为便于识别),具体配置如下:

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
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
namespace: mysql
labels:
app: mysql
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:5.7
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: root
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
- name: mysql-config
mountPath: /etc/mysql/mysql.conf.d
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pvc
- name: mysql-config
configMap:
name: mysql-config

该配置核心说明:

  • 镜像选用mysql:5.7稳定版本,通过环境变量MYSQL_ROOT_PASSWORD直接设置root用户密码为root(注:生产环境需使用Secret存储密码,避免明文暴露);

  • 将PVC挂载至MySQL默认数据目录/var/lib/mysql,确保数据持久化;将ConfigMap挂载至MySQL配置文件目录,覆盖默认配置,应用自定义参数;

  • 暴露3306端口,为集群内访问提供基础。

执行部署命令,启动MySQL实例:

1
kubectl apply -f mysql-deployment.yaml

4. 集群内访问:Service配置

创建ClusterIP类型的Service,为MySQL实例提供稳定的集群内访问地址,避免因Pod IP变化导致访问失败。创建mysql-service.yaml文件,配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: mysql
labels:
app: mysql
spec:
ports:
- name: tcp
port: 3306
protocol: TCP
targetPort: mysql
selector:
app: mysql
type: ClusterIP

部署完成后,K3s集群内其他Pod可通过固定域名mysql.mysql.svc.cluster.local:3306访问MySQL服务,无需关注具体Pod IP。执行部署命令:

1
kubectl apply -f mysql-service.yaml

5. 外部访问:IngressRouteTCP配置

若需从K3s集群外部访问MySQL服务,可结合K3s默认Ingress控制器(Traefik),配置IngressRouteTCP实现TCP流量转发。创建mysql-ingress.yaml文件,配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
name: mysql-tcp
namespace: mysql
spec:
entryPoints:
- mysql
routes:
- match: HostSNI(`*`)
services:
- name: mysql
port: 3306

注意:需提前在Traefik中配置mysql入口点(entryPoints),并监听指定端口(如3306),确保外部流量可正常转发至MySQL Service,否则外部访问会失败。

执行部署命令,完成IngressRouteTCP配置:

1
kubectl apply -f mysql-ingress.yaml

三、部署验证

部署完成后,需通过一系列操作验证MySQL服务是否正常运行、配置是否生效,具体步骤如下:

  1. 检查所有相关资源状态,确认部署无异常: kubectl get all -n mysql kubectl get pvc,pv -n mysql kubectl get configmap -n mysql 若所有资源均处于Running、Bound等正常状态,说明部署基础无问题。

  2. 验证MySQL内部连接及配置生效情况: # 进入MySQL Pod内部 kubectl exec -it mysql-0 -n mysql -- mysql -uroot -proot # 执行SQL命令,验证字符集等配置是否生效 mysql> show variables like '%character%'; 若查询结果中字符集相关参数均为utf8mb4,说明配置已成功应用。

  3. 外部访问验证(若已配置IngressRouteTCP): mysql -h <K3s节点IP> -P <Traefik监听端口> -uroot -proot 若能成功登录MySQL,说明外部访问配置生效。

四、注意事项

  1. 生产环境安全规范:MYSQL_ROOT_PASSWORD严禁明文写在配置文件中,需通过Kubernetes的Secret资源存储,提升密码安全性。

  2. 多节点集群存储建议:多节点K3s集群中,应使用Longhorn等分布式存储替代hostPath,避免单节点故障导致数据丢失,保障数据库高可用。

  3. 架构扩展说明:本文部署的为MySQL单实例,若需实现主从复制、读写分离架构,需在ConfigMap中额外配置主从复制相关参数,并调整StatefulSet配置。

  4. 数据备份要求:需定期备份PVC挂载目录中的数据,可通过定时任务脚本或专业备份工具实现,防止存储故障、误操作导致数据丢失。

  5. 配置更新生效:修改ConfigMap中的MySQL参数后,需重启MySQL StatefulSet使配置生效,执行命令:kubectl rollout restart statefulset mysql -n mysql

通过以上步骤,可在K3s集群中快速、规范地部署一个配置可定制、数据可持久化、网络可访问的MySQL实例,满足开发测试或生产环境的基础数据库使用需求,同时为后续架构优化、性能调优提供基础。

服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 # 安装nfs服务
sudo apt install nfs-common nfs-kernel-server portman -y

# 创建共享目录
sudo mkdir -p /mnt/share/
sudo chmod 777 /mnt/share

# 编辑映射文件
sudo vim /etc/exports

# 共享目录
/mnt/share *(rw,sync)

# 设置ACL赋予nfsnobody权限
sudo setfacl -m u:nfsbody:rw /mnt/share

# 启动NFS服务
sudo /etc/init.d/nfs-kernel-server start
sudo /etc/init.d/nfs-common start

# 检查服务启动
sudo showmount -e

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 安装nfs
sudo apt install nfs-common

# 新建本地文件夹
sudo mkdir /mnt/nfs

# sudo mount [nfs_server]:[server_dir] [local_mount_point]
# [nfs_server] nfs服务器ip
# [server_dir] 服务器共享路径
# [local_mount_point] 本地挂载路径
sudo mount [nfs_server]:[server_dir] [local_mount_point]
# 示例
sudo mount 192.168.1.100:/mnt/share /mnt/nfs

# 查看挂载是否成功
df -Th

编辑fstab 配置自动挂载

1
2
3
sudo vim /etc/fstab
# 在最后一行添加
[nfs_server]:/mnt/share /mnt/nfs nfs defaults 0 0

卸载

1
2
3
sudo umount [local_mount_point] 
#示例
sudo umount /mnt/nfs

需要认证参考为 Linux 客户端设置具有基于 Kerberos 的身份验证的 NFS 服务器 (linux-console.net)

安全相关参考如何确保NFS服务安全-腾讯云开发者社区-腾讯云 (tencent.com)

用户身份映射参考NFS服务的用户身份映射 - wangmo - 博客园 (cnblogs.com)

本地路径映射(HostPath)

HostPath 卷存在许多安全风险,最佳做法是尽可能避免使用 HostPath。 当必须使用 HostPath 卷时,它的范围应仅限于所需的文件或目录,并以只读方式挂载。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: registry.k8s.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
# 宿主机上目录位置
path: /data
# 此字段为可选
type: Directory

支持的 type 值如下:

取值 行为
空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。
DirectoryOrCreate 如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息。
Directory 在给定路径上必须存在的目录。
FileOrCreate 如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet 相同的组和所有权。
File 在给定路径上必须存在的文件。
Socket 在给定路径上必须存在的 UNIX 套接字。
CharDevice 在给定路径上必须存在的字符设备。
BlockDevice 在给定路径上必须存在的块设备。
1
2
3
4
5
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: example-vol-default
provisioner: vendor-name.example

local

local 卷只能用作静态创建的持久卷。不支持动态配置。

hostPath 卷相比,local 卷能够以持久和可移植的方式使用,而无需手动将 Pod 调度到节点。系统通过查看 PersistentVolume 的节点亲和性配置,就能了解卷的节点约束。

使用 local 卷时,你需要设置 PersistentVolume 对象的 nodeAffinity 字段。 Kubernetes 调度器使用 PersistentVolume 的 nodeAffinity 信息来将使用 local 卷的 Pod 调度到正确的节点。

PersistentVolume 对象的 volumeMode 字段可被设置为 “Block” (而不是默认值 “Filesystem”),以将 local 卷作为原始块设备暴露出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: v1
kind: PersistentVolume
metadata:
name: example-pv
spec:
capacity:
storage: 100Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /mnt/disks/ssd1
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- example-node

NFS映射

1

Minio

1

Ceph

1

准备环境

证书

[[../杂项/OpenSSL生成自签名证书|OpenSSL生成自签名证书]]

[[GitOps/基于K3s搭建GitOps环境4-证书管理|基于K3s搭建GitOps环境4-证书管理]]

默认配置文件

1
helm show values harbor/harbor > harbor-values.yaml

安装

配置清单

harbor-value.yaml

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
expose:
type: ingress
tls:
enabled: true
certSource: secret
secret:
secretName: "example.io"
notarySecretName: "example.io"
ingress:
hosts:
core: harbor.example.io
notary: notary.example.io
controller: default
annotations:
ingress.kubernetes.io/ssl-redirect: "true"
ingress.kubernetes.io/proxy-body-size: "0"
kubernetes.io/ingress.class: "traefik"
traefik.ingress.kubernetes.io/router.tls: "true"
traefik.ingress.kubernetes.io/router.entrypoints: websecure

externalURL: https://harbor.example.io

harborAdminPassword: "Harbor123456"

logLevel: info

chartmuseum:
enabled: true

database:
type: external
external:
host: "postgres.devops.svc.cluster.local"
port: "5432"
username: "harbor"
password: "harbor"
redis:
type: external
external:
addr: "redis.devops.svc.cluster.local:6379"
password: "passwd"

harbor-ingress.yaml

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
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
namespace: kube-ops
name: harbor-http
spec:
entryPoints:
- websecure
tls:
secretName: all-xxxx-com
routes:
- match: Host(`harbor.example.com`) && PathPrefix(`/`)
kind: Rule
services:
- name: harbor-portal
port: 80
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
namespace: kube-ops
name: harbor-api
spec:
entryPoints:
- websecure
tls:
secretName: all-xxxx-com
routes:
- match: Host(`harbor.example.com`) && PathPrefix(`/api/`)
kind: Rule
services:
- name: harbor-core
port: 80
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
namespace: kube-ops
name: harbor-service
spec:
entryPoints:
- websecure
tls:
secretName: all-xxxx-com
routes:
- match: Host(`harbor.example.com`) && PathPrefix(`/service/`)
kind: Rule
services:
- name: harbor-core
port: 80
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
namespace: kube-ops
name: harbor-v2
spec:
entryPoints:
- websecure
tls:
secretName: all-xxxx-com
routes:
- match: Host(`harbor.example.com`) && PathPrefix(`/v2`)
kind: Rule
services:
- name: harbor-core
port: 80
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
namespace: kube-ops
name: harbor-chartrepo
spec:
entryPoints:
- websecure
tls:
secretName: all-xxxx-com
routes:
- match: Host(`harbor.example.com`) && PathPrefix(`/chartrepo/`)
kind: Rule
services:
- name: harbor-core
port: 80
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
namespace: kube-ops
name: harbor-c
spec:
entryPoints:
- websecure
tls:
secretName: all-xxxx-com
routes:
- match: Host(`harbor.example.com`) && PathPrefix(`/c/`)
kind: Rule
services:
- name: harbor-core
port: 80

安装Harbor

1
2
3
4
5
6
7
# 添加Harbor仓库
helm repo add harbor https://helm.goharbor.io

# 使用部署或升级Harbor
helm upgrade harbor harbor/harbor --namespace harbor \
--install --create-namespace \
-f harbor-values.yaml

配置

配置library仓库源

1
2
3
4
5
6
7
kubectl edit configmap harobr-registry -n harbor

# 在auth: 后边添加新节点
proxy:
remoteurl: "https://registry-1.docker.io"


使用Harbor

配置镜像缓存

参考

Harbor 搭建镜像代理 | Northes

Kubernetes ≥ 1.25 Containerd配置Harbor私有镜像仓库_containerd登录镜像仓库-CSDN博客

结合Cert-Manager完成Harbor的Https证书自动签发 | 风格 | 风起于青萍之末 (lusyoe.github.io)

Containerd容器镜像管理-腾讯云开发者社区-腾讯云 (tencent.com)

通过helm在k8s上搭建Harbor - 简书 (jianshu.com)

Kubernetes 集群仓库 harbor Helm3 部署-腾讯云开发者社区-腾讯云 (tencent.com)

containerd基本使用命令 - 杨梅冲 - 博客园 (cnblogs.com)

Kubernetes1.21搭建harbor-腾讯云开发者社区-腾讯云 (tencent.com)

Helm部署

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
helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/

#helm会使用kubectl默认的KUBECONFIG配置,这里我们需要将KUBECONFIG换成k3s的否则会链接失败。
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml

#注意要指定端口号等信息,方便访问
# service.type=NodePort 默认是ClusterIP只能本机访问
# service.nodePort=30080 指定访问端口号
# replicaCount=2 2个节点

# helm v2
helm upgrade --install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard \
--create-namespace \
--namespace kubernetes-dashboard \
# --set service.type=NodePort \
# --set service.nodePort=30080 \
# --set replicaCount=2

# helm v3+
helm install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard \
--create-namespace \
--namespace kubernetes-dashboard \
# --set service.type=NodePort \
# --set service.nodePort=30080 \
# --set replicaCount=2

配置远程访问

NodePort暴露端口

1
kubectl -n kubernetes-dashboard edit service kubernetes-dashboard-web
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
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
...
name: kubernetes-dashboard
namespace: kubernetes-dashboard
resourceVersion: "343478"
selfLink: /api/v1/namespaces/kubernetes-dashboard/services/kubernetes-dashboard
uid: 8e48f478-993d-11e7-87e0-901b0e532516
spec:
clusterIP: 10.100.124.90
externalTrafficPolicy: Cluster
ports:
- port: 443
protocol: TCP
targetPort: 8443
selector:
k8s-app: kubernetes-dashboard
sessionAffinity: None
# 修改开放端口方式
#type: ClusterIP
type: NodePort
status:
loadBalancer: {}

Traefik Ingress反向代理

创建证书请求文件dashboard-cert-manager.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: k3s-chemmy-io
namespace: default
spec:
secretName: k3s-chemmy-io-tls
issuerRef:
name: letsencrypt-staging
kind: ClusterIssuer
commonName: k3s.chemmy.io
dnsNames:
- k3s.sample.net

此配置文件是测试版,正式版参考K3s部署cert-manager

1
2
3
4
5
6
7
8
9
10
11
kubectl apply -f dashboard-cert-manager.yaml

# 查看
kubectl get certificates

# 如果状态不是READY,检查
kubectl describe certificates k3s-chemmy-io

# 清理证书
kubectl delete certificates k3s-chemmy-io
kubectl delete secrets k3s-chemmy-io-tls

配置账户

新建dashboard-admin.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 创建ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
#创建clusterRoleBinding
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: kubernetes-dashboard

新建用户

1
2
# 部署用户资源
kubectl apply -f dashboard-admin.yaml

获取token

1
2
3
4
5
# v1.24+
sudo k3s kubectl -n kubernetes-dashboard create token admin-user

# v1.23 及之前的版本
sudo k3s kubectl -n kubernetes-dashboard describe secret admin-user-token | grep '^token'

Kubectl部署

最新版本只支持Helm,旧版本v2.7支持Kubectl部署

下载 recommended.yaml

1
kubectl apply -f recommended.yaml

修改recommended.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
---
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
# 直接暴露端口使用NodePort,Traefik使用ClusterIP
#type: ClusterIP
type: NodePort
ports:
- port: 443
targetPort: 8443
selector:
k8s-app: kubernetes-dashboard
---
...

dashboard的默认webui证书是自动生成的,由于时间和名称存在问题,导致谷歌和ie浏览器无法打开登录界面,经过测试Firefox可以正常打开。解决证书问题参考Kubernetes Dashboard的安装与坑 - 简书 (jianshu.com)

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
---

# 注释内置自动生成的证书
#apiVersion: v1
#kind: Secret
#metadata:
# labels:
# k8s-app: kubernetes-dashboard
# name: kubernetes-dashboard-certs
# namespace: kubernetes-dashboard
#type: Opaque

---
...
---

kind: Deployment
apiVersion: apps/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: kubernetes-dashboard
template:
metadata:
labels:
k8s-app: kubernetes-dashboard
spec:
containers:
- name: kubernetes-dashboard
image: kubernetesui/dashboard:v2.1.0
imagePullPolicy: Always
ports:
- containerPort: 8443
protocol: TCP
args:
# 注释自动生成证书
# - --auto-generate-certificates
- --namespace=kubernetes-dashboard
# 添加证书配置及证书文件映射
- --token-ttl=3600
- --bind-address=0.0.0.0
- --tls-cert-file=tls.crt
- --tls-key-file=tls.key
# Uncomment the following line to manually specify Kubernetes API server Host
# If not specified, Dashboard will attempt to auto discover the API server and connect
# to it. Uncomment only if the default does not work.
# - --apiserver-host=http://my-address:port
volumeMounts:
- name: kubernetes-dashboard-certs
mountPath: /certs
# Create on-disk volume to store exec logs
- mountPath: /tmp
name: tmp-volume
livenessProbe:
httpGet:
scheme: HTTPS
path: /
port: 8443
initialDelaySeconds: 30
timeoutSeconds: 30
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsUser: 1001
runAsGroup: 2001
volumes:
- name: kubernetes-dashboard-certs
secret:
secretName: kubernetes-dashboard-certs
- name: tmp-volume
emptyDir: {}
serviceAccountName: kubernetes-dashboard
nodeSelector:
"kubernetes.io/os": linux
# Comment the following tolerations if Dashboard must not be deployed on master
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule

---
...

生成证书文件 tls.crt,tls.csr,tls.key

1
2
3
4
5
6
7
8
9
# 生成key
openssl genrsa -out tls.key 2048
# 生成csr
openssl req -new -out tls.csr -key tls.key -subj '/CN=0.0.0.0'
# 生成
openssl x509 -req -in tls.csr -signkey tls.key -out tls.crt

#创建secret
kubectl create secret generic kubernetes-dashboard-certs --from-file=tls.crt --from-file=tls.key -n kubernetes-dashboard

subj子参数解释

缩写 翻译 英文对照
C 国家名称缩写 Country Name (2 letter code)
ST 州或省名称 State or Province Name (full name)
L 城市或区域称 Locality Name (eg, city)
O 组织名(或公司名) Organization Name (eg, company)
OU 组织单位名称(或部门名) Organizational Unit Name (eg, section)
CN 服务器域名/证书拥有者名称 Common Name (e.g. server FQDN or YOUR name)
emailAddress 邮件地址 Email

参考

k3s集群单节点部署与集群内DashBoard部署 - 知乎 (zhihu.com)

k3s集群搭建并安装kubernetes-dashboard - 东峰叵,com - 博客园 (cnblogs.com)

[K8S 快速入门(十九)通过Helm 安装 Kubernetes Dashboard_helm安装dashboard ingress-CSDN博客](https://blog.csdn.net/weixin_41947378/article/details/111661539#:~:text=通过Helm 安装 Kubernetes Dashboard 1 1. 下载 %23,外网访问 %23 将svc的ClusterIP改为NotePort,外网访问 … 5 5. 令牌方式登录仪表盘)

使用 traefik ingress暴露kubernetes-dashbord - HTTPS版本_svclb-traefik-CSDN博客

Kubernetes dashboardv2.7.0安装指南:从零开始搭建可视化界面 - 知乎

0%