K3s部署PostgreSQL

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配置实现访问控制等,进一步提升部署的安全性与稳定性。