[MYSQL/K8s] 基于 Kubenetes 集群安装 MYSQL
0 序
- 本篇的目的不在于安装mysql,而在于安装部署完成K8s后,以MYSQL为例展示如何基于K8s集群完整地部署一个程序服务。
MYSQL 较为典型——service / pod / secret / pv / pvc 均可涉及。
1 部署步骤
step1 配置 mysql.yaml
mkdir -p ~/k8s-deployments/
touch ~/k8s-deployments/mysql.yaml
vim ~/k8s-deployments/mysql.yaml
编辑内容:
# mysql-configmap.yaml | ConfigMap: MySQL 配置
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-config
namespace: mysql
data:
my.cnf: |
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
max_connections=200
innodb_buffer_pool_size=256M
---
# mysql-secret.yaml | Secret: MySQL 密码(生产环境建议使用 Vault 或 External Secrets)
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
namespace: mysql
type: Opaque
stringData:
MYSQL_ROOT_PASSWORD: "YourStrongPassword123!"
MYSQL_USER: "appuser"
MYSQL_PASSWORD: "AppUserPass123!"
---
# mysql-pvc.yaml | PVC: 数据存储(使用 local-path-provisioner )
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
namespace: mysql
spec:
# 指定 local-path-provisioner
storageClassName: local-path
accessModes:
# MySQL 单实例只需 RWO
- ReadWriteOnce
resources:
requests:
# 根据实际需求调整
storage: 20Gi
---
# mysql-statefulset.yaml | StatefulSet: MySQL 有状态的工作负载 (与 无状态的 Deployment 相对)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
namespace: mysql
spec:
serviceName: mysql
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
ports:
- containerPort: 3306
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: MYSQL_ROOT_PASSWORD
- name: MYSQL_DATABASE
value: "app_database"
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql # MySQL 数据目录
- name: mysql-config
mountPath: /etc/mysql/conf.d
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
livenessProbe:
exec:
command: ["mysqladmin", "ping", "-p${MYSQL_ROOT_PASSWORD}"]
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
exec:
command: ["mysqladmin", "ping", "-p${MYSQL_ROOT_PASSWORD}"]
initialDelaySeconds: 5
periodSeconds: 2
volumes:
- name: mysql-data
persistentVolumeClaim:
# 引用上面定义的 PVC
claimName: mysql-pvc
- name: mysql-config
configMap:
name: mysql-config
---
# mysql-service.yaml | Service: 暴露 MySQL 端口
apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: mysql
spec:
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306
type: ClusterIP
当然,也可将本文件分拆为几个文件来进行部署:
mysql-deployment.yaml
mysql-secret.yaml
mysql-configmap.yamlmysql-namespace.yaml
mysql-pv-pvc.yaml
mysql-service.yaml
...
step2 基于 mysql.yaml 部署/启动运行
kubectl create -f mysql.yaml
或 kubectl apply -f mysql.yaml
[补充] kubectl delete -f mysql.yaml
step3 查验 MYSQL 的运行情况
查验 k8s 的 service/pod/statefulset、secret、pv/pvc
//查看 service/pod/statefulset/
# kubectl get all --namespace mysql
NAME READY STATUS RESTARTS AGE
pod/mysql-0 1/1 Running 0 4h14m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/mysql ClusterIP 10.100.xxx.19 <none> 3306/TCP 4h14m
NAME READY AGE
statefulset.apps/mysql 1/1 4h14m
//查看 secret
# kubectl get secret --namespace mysql
NAME TYPE DATA AGE
mysql-secret Opaque 3 4h15m
//查看 pv / pvc
# kubectl get pv --namespace mysql
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-10e35004-c24f-443d-9268-e5603172c382 20Gi RWO Delete Bound mysql/mysql-pvc local-path 4h17m
# kubectl get pvc --namespace mysql
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mysql-pvc Bound pvc-10e35004-c24f-443d-9268-e5603172c382 20Gi RWO local-path 4h18m
获取 Kubernetes 中 MySQL Pod 的连接信息
1. 查看 Pod 的 IP 和端口
# 获取 Pod 的详细信息,包括 IP 地址
kubectl get pod <mysql-pod-name> -o wide
# 查看 Pod 的详细描述(包含端口映射)
kubectl describe pod <mysql-pod-name>
2. 查看 Service 信息(推荐方式)
通常 MySQL 会通过 Service 暴露,这样更稳定:
# 列出所有 Service
kubectl get svc
# 查看 MySQL Service 详情
kubectl describe svc <mysql-service-name>
# 获取 Service 的 ClusterIP 和端口
kubectl get svc <mysql-service-name> -o jsonpath='{.spec.clusterIP}:{.spec.ports[0].port}'
3. 通过环境变量查看(若是通过 Secret 配置的)
# 查看 Pod 的环境变量
kubectl exec <mysql-pod-name> -- env | grep -i mysql
# 查看 Secret 中的连接信息
kubectl get secret <mysql-secret-name> -o yaml
# 解码 base64 密码
echo "<base64-encoded-password>" | base64 -d
4. 查看 ConfigMap 或部署配置
# 查看使用的 ConfigMap
kubectl get configmaps --namespace <mysql-namespace>
kubectl get configmap <mysql-configmap> --namespace <mysql-namespace> -o yaml
# 查看 Deployment/StatefulSet 的配置
kubectl get deployments --namespace <mysql-namespace>
kubectl get deployment <mysql-deployment> --namespace <mysql-namespace> -o yaml
kubectl get statefulsets --namespace <mysql-namespace>
//如: kubectl get statefulsets -n mysql
//NAME READY AGE
//mysql 1/1 4h39m
kubectl get statefulset <mysql-statefulset> --namespace <mysql-namespace> -o yaml
5. 端口转发(本地测试用)
# 将本地端口映射到 Pod 端口
kubectl port-forward <mysql-pod-name> 3306:3306
# 然后本地可以用 localhost:3306 连接
mysql -h localhost -P 3306 -u root -p
典型连接信息示例
| 信息项 | 获取方式 |
|---|---|
| 主机地址 | Service 的 ClusterIP 或 Service 名称 |
| 端口 | 默认 3306,查看 kubectl get svc |
| 用户名 | 通常是 root 或自定义用户,查看 Secret/环境变量 |
| 密码 | 查看 Secret:kubectl get secret |
最佳实践建议
- 使用 Service DNS 连接:在集群内通过
<service-name>.<namespace>.svc.cluster.local连接 - 使用 Secret 管理凭证:不要硬编码密码
- 考虑使用 Helm Chart:如
bitnami/mysql,会自动配置好连接信息
连接验证
-
安装 MYSQL 客户端 (可忽略此步骤,跳过即可)
-
推荐方式: 直接进入Pod内
kubectl exec -it <mysql-pod-name> --namespace mysql -- mysql --port=3306 -u root -p
[root@vm-a k8s-deployments]# kubectl exec -it mysql-0 -n mysql -- mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8568
Server version: 8.0.45 MySQL Community Server - GPL
Copyright (c) 2000, 2026, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> SELECT user, host FROM mysql.user;
+------------------+-----------+
| user | host |
+------------------+-----------+
| root | % |
| mysql.infoschema | localhost |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+------------------+-----------+
5 rows in set (0.00 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| app_database |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
- 推荐方式: 直接进入Pod内
# 找到 mysql 相关的 pod
kubectl get pods -n mysql -l app=mysql
# 进入 pod 内部,然后在 pod 里连接 mysql
kubectl exec -it <mysql-pod-name> -n mysql -- /bin/bash
# 在 pod 内部使用服务名连接
mysql -h mysql.mysql.svc.cluster.local -P 3306 -u root -p
如:
[root@vm-a k8s-deployments]# kubectl exec -it mysql-0 -n mysql -- /bin/bash
bash-5.1# mysql -h mysql.mysql.svc.cluster.local -P 3306 -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 10316
Server version: 8.0.45 MySQL Community Server - GPL
Copyright (c) 2000, 2026, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> exit;
Z FAQ for K8s 安装部署 MYSQL
Q: service 的 type 为 ClsuterIP ,无法基于<serviceName>.<namespace>.svc.cluster.local的【服务域名】在宿主机上访问,如何解决?
问题描述
[root@vm-a k8s-deployments]# ssh mysql.mysql.svc.cluster.local -p 3306 -v
OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 58: Applying options for *
ssh: Could not resolve hostname mysql.mysql.svc.cluster.local: Name or service not known
原因分析
这个错误表明 DNS 解析失败,无法找到 mysql.mysql.svc.cluster.local 这个域名。
mysql.mysql.svc.cluster.local 是 Kubernetes 集群内部的 DNS 名称,只能在 Pod 内部或通过集群 DNS 解析。你的宿主机(vm-a)无法直接解析这个域名。
解决方案
方案 1:进入 Pod 内部执行(推荐)
# 找到 mysql 相关的 pod
kubectl get pods -n mysql -l app=mysql
# 进入 pod 内部,然后在 pod 里连接 mysql
kubectl exec -it <mysql-pod-name> -n mysql -- /bin/bash
# 在 pod 内部使用服务名连接
mysql -h mysql.mysql.svc.cluster.local -P 3306 -u root -p
方案 2:使用 kubectl port-forward 转发端口
# 将本地端口映射到 mysql 服务
kubectl port-forward svc/mysql 3306:3306 -n mysql
# 然后在另一个终端连接本地端口
mysql -h 127.0.0.1 -P 3306 -u root -p
方案 3:直接使用 Pod IP(临时方案)
# 获取 mysql pod 的 IP
kubectl get pods -n mysql -o wide
# 使用 Pod IP 连接(不推荐,IP 会变)
mysql -h <pod-ip> -P 3306 -u root -p
方案 4:使用 NodePort 或 LoadBalancer 暴露服务
如果你确实需要从集群外部访问,可以修改 Service 类型:
# 查看当前 service 类型
kubectl get svc mysql -n mysql
# 修改为 NodePort(示例)
kubectl patch svc mysql -n mysql -p '{"spec":{"type":"NodePort"}}'
# 或者使用 LoadBalancer(如果有云提供商支持)
kubectl patch svc mysql -n mysql -p '{"spec":{"type":"LoadBalancer"}}'
快速排查命令
# 确认 mysql 服务是否存在
kubectl get svc -n mysql
# 确认 DNS 服务是否正常
kubectl get pods -n kube-system -l k8s-app=kube-dns
# 测试集群 DNS 解析(在 pod 内执行)
kubectl run -it --rm debug --image=busybox:1.28 --restart=Never -- nslookup mysql.mysql.svc.cluster.local
总结
| 场景 | 推荐方案 |
|---|---|
| 临时调试 | kubectl exec 进入 Pod |
| 本地开发 | kubectl port-forward |
| 生产环境外部访问 | NodePort / LoadBalancer / Ingress |
Q: 如何将 mysql 的 service type 从 ClusterIP 换为 NodePort?
将 MySQL 的 ClusterIP 改为 NodePort 的方法:
方法1:直接修改现有 Service(保留原配置)
# 1. 修改 Service 类型为 NodePort
kubectl patch svc mysql -n mysql -p '{"spec":{"type":"NodePort"}}'
# 2. 查看分配的 NodePort
kubectl get svc mysql -n mysql
输出示例:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mysql NodePort 10.100.174.19 <none> 3306:30001/TCP 4h49m
30001就是自动分配的 NodePort,范围 30000-32767
方法2:指定固定 NodePort(推荐)
# 指定具体的节点端口(例如 30001)
kubectl patch svc mysql -n mysql -p '{"spec":{"type":"NodePort","ports":[{"port":3306,"targetPort":3306,"nodePort":30001}]}}'
方法3:通过 YAML 编辑(最灵活)
# 导出当前配置备份
kubectl get svc mysql -n mysql -o yaml > mysql-svc-backup.yaml
# 编辑 Service
kubectl edit svc mysql -n mysql
修改内容:
spec:
type: NodePort # 改为 NodePort
ports:
- port: 3306
targetPort: 3306
nodePort: 30001 # 可选:指定端口(30000-32767)
protocol: TCP
保存退出后自动生效。
修改后连接方式
# 获取节点 IP
kubectl get nodes -o wide
# 验证网络联通性
ssh <node-ip> -p 3306 -v
如: ssh 10.100.174.19 -p 3306 -v
# 连接 MySQL(用任意节点的 IP + NodePort,即可在 K8s 集群的宿主机及其所在网络上进行连接)
mysql -h <node-ip> -P 30001 -u root -p
回滚操作(如需恢复 ClusterIP)
kubectl patch svc mysql -n mysql -p '{"spec":{"type":"ClusterIP"}}'
完整检查命令
# 确认修改成功
kubectl get svc mysql -n mysql
# 查看 Endpoints(确认后端 Pod 正常)
kubectl get endpoints mysql -n mysql
# 测试连接(在集群外执行)
mysql -h <node-ip> -P <node-port> -u root -p
Y 推荐文献
- K8s概述 - 博客园/千千寰宇
- [K8s] Kubernetes 安装部署指南(V2) - 博客园/千千寰宇
- [云原生] K8s 核心组件使用指南 - 博客园/千千寰宇
- MYSQL之数据库管理篇 - 博客园/千千寰宇
X 参考文献
本文作者:
千千寰宇
本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!
本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!

浙公网安备 33010602011771号