【Kubernetes】部署数据库MySQL应用

Kubernetes部署MySQL

在部署MySQL前,先解释一下DeploymentStatefulSet差异

Deployment vs StatefulSet

Deployment

Deployment 主要用于部署无状态应用(Stateless Application)。它管理 Pod 的副本集,并支持滚动更新、回滚等功能。

特点:

  1. 无状态:Deployment 管理的 Pod 是完全相同的、可替代的。任何一个 Pod 都可以被另一个 Pod 替换,不会影响应用的整体功能。

  2. 随机命名和身份:Pod 的名称是随机的(例如:my-app-5d89b4f6d-xxxxx),没有固定的顺序。

  3. 共享存储:多个 Pod 可以共享同一个持久化存储(例如:同一个 PVC),但通常每个 Pod 不需要独立的存储。

  4. 服务发现和负载均衡:通过 Service 访问时,流量会被随机分配到任意一个 Pod。

  5. 扩缩容:可以轻松地增加或减少副本数,新 Pod 会替代旧 Pod,没有顺序要求。

  6. 使用场景

    • Web 服务器(如 Nginx、Apache)

    • 无状态 API 服务

    • 任何不需要保存状态或状态存储在外部(如数据库、Redis)的应用

StatefulSet

StatefulSet 用于部署有状态应用(Stateful Application),每个 Pod 有唯一的、稳定的身份标识。

特点:

  1. 有状态:每个 Pod 有独立的、稳定的网络标识和存储。

  2. 有序部署和扩展

    • 当部署多个 Pod 时,它们会按顺序创建(从 0 到 N-1),并且会等待前一个 Pod 准备就绪后才会创建下一个。

    • 缩容时,顺序相反(从 N-1 到 0)。

  3. 稳定的网络标识

    • 每个 Pod 都有一个稳定的主机名,格式为:-

    • 例如:一个名为 web 的 StatefulSet 有三个副本,Pod 名称分别为 web-0、web-1、web-2。

    • 每个 Pod 拥有一个稳定的 DNS 名称:...svc.cluster.local。

  4. 独立的存储

    • 每个 Pod 可以拥有独立的持久化存储(通过 VolumeClaimTemplate 为每个 Pod 创建独立的 PVC)。

    • 当 Pod 被重新调度时,会挂载相同的存储,从而保持状态。

  5. 使用场景

    • 数据库(如 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. 部署脚本

kubsucl 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 

【Kubernetes】部署数据库MySQL应用

2. 验证插入数据重启后数据不丢失

  1. 创建表并保存数据
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; 
  1. 重启k8s服务
# 删除mysql pod kubectl delete -f mysql-statefulset.yaml  # 重新部署mysql statefulset  kubectl apply -f mysql-statefulset.yaml 

【Kubernetes】部署数据库MySQL应用

  1. 验证数据
# 重新进入 kubectl exec -it -n mysql mysql-0 -- mysql -u root -p  use myapp;  select * from users; 

【Kubernetes】部署数据库MySQL应用

重要说明

  1. 节点选择:需要根据实际环境修改PV中的节点名称

  2. 目录权限:确保节点上的本地目录有正确的读写权限

  3. 数据持久性:本地存储的数据不会在Pod重新调度时自动迁移

  4. 备份策略:重要数据务必建立定期备份机制

  5. 资源限制:根据实际需求调整CPU和内存限制

这个配置提供了一个生产可用的单机MySQL部署方案,包含了健康检查、资源配置、数据持久化等关键功能。

引用

https://github.com/WilsonPan/java-developer

例子: https://github.com/WilsonPan/java-developer/k8s/mysql

部署Spring应用

发表评论

评论已关闭。

相关文章