Kubernetes部署MySQL
在部署MySQL前,先解释一下Deployment和StatefulSet差异
Deployment vs StatefulSet
Deployment
Deployment 主要用于部署无状态应用(Stateless Application)。它管理 Pod 的副本集,并支持滚动更新、回滚等功能。
特点:
- 无状态:Deployment 管理的 Pod 是完全相同的、可替代的。任何一个 Pod 都可以被另一个 Pod 替换,不会影响应用的整体功能。
- 随机命名和身份:Pod 的名称是随机的(例如:my-app-5d89b4f6d-xxxxx),没有固定的顺序。
- 共享存储:多个 Pod 可以共享同一个持久化存储(例如:同一个 PVC),但通常每个 Pod 不需要独立的存储。
- 服务发现和负载均衡:通过 Service 访问时,流量会被随机分配到任意一个 Pod。
- 扩缩容:可以轻松地增加或减少副本数,新 Pod 会替代旧 Pod,没有顺序要求。
- 使用场景:
- Web 服务器(如 Nginx、Apache)
- 无状态 API 服务
- 任何不需要保存状态或状态存储在外部(如数据库、Redis)的应用
StatefulSet
StatefulSet 用于部署有状态应用(Stateful Application),每个 Pod 有唯一的、稳定的身份标识。
特点:
- 有状态:每个 Pod 有独立的、稳定的网络标识和存储。
- 有序部署和扩展:
- 当部署多个 Pod 时,它们会按顺序创建(从 0 到 N-1),并且会等待前一个 Pod 准备就绪后才会创建下一个。
- 缩容时,顺序相反(从 N-1 到 0)。
- 稳定的网络标识:
- 每个 Pod 都有一个稳定的主机名,格式为:-。
- 例如:一个名为 web 的 StatefulSet 有三个副本,Pod 名称分别为 web-0、web-1、web-2。
- 每个 Pod 拥有一个稳定的 DNS 名称:...svc.cluster.local。
- 独立的存储:
- 每个 Pod 可以拥有独立的持久化存储(通过 VolumeClaimTemplate 为每个 Pod 创建独立的 PVC)。
- 当 Pod 被重新调度时,会挂载相同的存储,从而保持状态。
- 使用场景:
- 数据库(如 MySQL、PostgreSQL 集群)
- 分布式系统(如 Zookeeper、Etcd、Kafka)
- 任何需要持久化数据且每个实例有独立状态的应用
核心差异总结
特性 Deployment StatefulSet 适用场景 无状态应用 有状态应用 Pod身份 可互换、匿名 唯一、有序、稳定 网络标识 随机名称,不稳定 固定名称,有序(web-0, 存储 共享存储,Pod间无区别 独立存储,每个Pod专用 部署策略 滚动更新,可并行 顺序部署/删除(0→1→2) 服务发现 通过Service负载均衡 通过Headless 部署MySQL
1. 创建命名空间
mysql-namespace.yaml
- apiVersion: v1
- kind: Namespace
- metadata:
- name: mysql
复制代码 2. 创建本地存储PV和StorageClass
mysql-storage.yaml
- apiVersion: storage.k8s.io/v1
- kind: StorageClass
- metadata:
- name: local-storage
- provisioner: kubernetes.io/no-provisioner
- volumeBindingMode: WaitForFirstConsumer
- ---
- apiVersion: v1
- kind: PersistentVolume
- metadata:
- name: mysql-local-pv
- labels:
- type: local
- spec:
- capacity:
- storage: 10Gi
- accessModes:
- - ReadWriteOnce
- persistentVolumeReclaimPolicy: Retain
- storageClassName: local-storage
- local:
- path: /data/mysql # 节点上的本地目录
- nodeAffinity:
- required:
- nodeSelectorTerms:
- - matchExpressions:
- - key: kubernetes.io/hostname
- operator: In
- values:
- - colima # 替换为实际节点名称
复制代码 3. 创建MySQL配置ConfigMap
mysql-configmap.yaml
- apiVersion: v1
- kind: ConfigMap
- metadata:
- name: mysql-config
- namespace: mysql
- data:
- custom.cnf: |
- [mysqld]
- default_authentication_plugin=mysql_native_password
- skip-name-resolve
- explicit_defaults_for_timestamp
- max_connections=1000
- innodb_buffer_pool_size=256M
- innodb_log_file_size=128M
- character-set-server=utf8mb4
- collation-server=utf8mb4_unicode_ci
复制代码 4. 创建MySQL密码Secret
mysql-secret.yaml
- apiVersion: v1
- kind: Secret
- metadata:
- name: mysql-secret
- namespace: mysql
- type: Opaque
- data:
- root-password: cm9vdDEyMyE= # echo -n 'root123!' | base64
- user-password: YXBwdXNlcjEyMyE= # echo -n 'appuser123!' | base64
复制代码 5. 创建MySQL StatefulSet
mysql-statefulset.yaml
- 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
- env:
- - name: MYSQL_ROOT_PASSWORD
- valueFrom:
- secretKeyRef:
- name: mysql-secret
- key: root-password
- - name: MYSQL_DATABASE
- value: "myapp"
- - name: MYSQL_USER
- value: "appuser"
- - name: MYSQL_PASSWORD
- valueFrom:
- secretKeyRef:
- name: mysql-secret
- key: user-password
- ports:
- - containerPort: 3306
- name: mysql
- volumeMounts:
- - name: mysql-data
- mountPath: /var/lib/mysql
- - name: mysql-config
- mountPath: /etc/mysql/conf.d
- resources:
- requests:
- memory: "512Mi"
- cpu: "250m"
- limits:
- memory: "1Gi"
- cpu: "500m"
- livenessProbe:
- exec:
- command:
- - sh
- - -c
- - "mysqladmin ping -u root -p${MYSQL_ROOT_PASSWORD}"
- initialDelaySeconds: 30
- periodSeconds: 10
- timeoutSeconds: 5
- readinessProbe:
- exec:
- command:
- - sh
- - -c
- - "mysqladmin ping -u root -p${MYSQL_ROOT_PASSWORD}"
- initialDelaySeconds: 5
- periodSeconds: 5
- timeoutSeconds: 1
- volumes:
- - name: mysql-config
- configMap:
- name: mysql-config
- volumeClaimTemplates:
- - metadata:
- name: mysql-data
- spec:
- accessModes: [ "ReadWriteOnce" ]
- storageClassName: "local-storage"
- resources:
- requests:
- storage: 10Gi
复制代码 6. 创建MySQL Service
mysql-service
- apiVersion: v1
- kind: Service
- metadata:
- name: mysql
- namespace: mysql
- labels:
- app: mysql
- spec:
- ports:
- - port: 3306
- targetPort: 3306
- name: mysql
- selector:
- app: mysql
- type: ClusterIP
- ---
- # 可选:创建NodePort Service用于外部访问
- apiVersion: v1
- kind: Service
- metadata:
- name: mysql-external
- namespace: mysql
- spec:
- type: NodePort
- ports:
- - port: 3306
- targetPort: 3306
- nodePort: 30306
- selector:
- app: mysql
复制代码 7. 部署脚本
- kubsuclr apply -f mysql-namespace.yaml
- kubectl apply -f mysql-storage.yaml
- kubectl apply -f mysql-configmap.yaml
- kubectl apply -f mysql-secret.yaml
- kubectl apply -f mysql-statefulset.yaml
- kubectl apply -f mysql-service.yaml
复制代码 8. 测试验证
1. 查看部署情况
- # 查看Pod状态
- kubectl get pods -n mysql -w
- # 检查PV/PVC状态...
- kubectl get pv,pvc -n mysql
- # 检查Service...
- kubectl get svc -n mysql
- # 进入mysql
- kubectl exec -it -n mysql mysql-0 -- mysql -u root -p
复制代码
2. 验证插入数据重启后数据不丢失
- CREATE TABLE IF NOT EXISTS `users` (
- `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '用户ID',
- `username` VARCHAR(50) NOT NULL COMMENT '用户名',
- `password` CHAR(60) NOT NULL COMMENT 'Bcrypt加密密码', -- 固定60字符长度
- `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
- `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
- PRIMARY KEY (`id`))
- ENGINE=InnoDB
- DEFAULT CHARSET=utf8mb4
- COLLATE=utf8mb4_unicode_ci
- COMMENT='用户信息表';
- insert into users(username,`password`, created_at, updated_at) values('wilson', '123456', CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP())
- select * from users;
复制代码- # 删除mysql pod
- kubectl delete -f mysql-statefulset.yaml
- # 重新部署mysql statefulset
- kubectl apply -f mysql-statefulset.yaml
复制代码
- # 重新进入
- kubectl exec -it -n mysql mysql-0 -- mysql -u root -p
- use myapp;
- select * from users;
复制代码
重要说明
- 节点选择:需要根据实际环境修改PV中的节点名称
- 目录权限:确保节点上的本地目录有正确的读写权限
- 数据持久性:本地存储的数据不会在Pod重新调度时自动迁移
- 备份策略:重要数据务必建立定期备份机制
- 资源限制:根据实际需求调整CPU和内存限制
这个配置提供了一个生产可用的单机MySQL部署方案,包含了健康检查、资源配置、数据持久化等关键功能。
引用
https://github.com/WilsonPan/java-developer
例子: https://github.com/WilsonPan/java-developer/k8s/mysql
部署Spring应用
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |