【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

yaml 复制代码
apiVersion: v1
kind: Namespace
metadata:
  name: mysql

2. 创建本地存储PV和StorageClass

mysql-storage.yaml

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

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

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

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

yaml 复制代码
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. 部署脚本

sh 复制代码
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. 查看部署情况

sh 复制代码
# 查看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. 验证插入数据重启后数据不丢失

  1. 创建表并保存数据
sql 复制代码
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服务
sh 复制代码
# 删除mysql pod
kubectl delete -f mysql-statefulset.yaml

# 重新部署mysql statefulset

kubectl apply -f mysql-statefulset.yaml
  1. 验证数据
sh 复制代码
# 重新进入
kubectl exec -it -n mysql mysql-0 -- mysql -u root -p

use myapp;

select * from users;

重要说明

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

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

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

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

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

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

引用

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

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

部署Spring应用

相关推荐
WilsonPan3 天前
【Kubernetes】入门-部署Spring应用
系统运维
谅望者5 天前
Linux文件查看命令完全指南:cat、less、head、tail、grep使用详解
linux·excel·less·shell·文件操作·命令行·系统运维
IT小哥哥呀17 天前
5 个 Windows 故障排除工具
windows·故障排除·系统运维·windows系统·电脑问题
WilsonPan1 个月前
macOS上优雅运行Docker容器
系统运维
Johny_Zhao2 个月前
达梦数据库高可用集群部署方案
linux·mysql·网络安全·docker·信息安全·kubernetes·云计算·shell·containerd·达梦数据库·yum源·系统运维·centos8
Johny_Zhao2 个月前
Conda、Anaconda、Miniconda对比分析
linux·网络安全·信息安全·kubernetes·云计算·conda·shell·containerd·anaconda·yum源·系统运维·miniconda
Johny_Zhao3 个月前
Linux防止rm误操作防护方案
linux·网络·人工智能·网络安全·信息安全·云计算·yum源·系统运维
Johny_Zhao3 个月前
基于 Docker 的 LLaMA-Factory 全流程部署指南
linux·网络·网络安全·信息安全·kubernetes·云计算·containerd·yum源·系统运维·llama-factory
Johny_Zhao3 个月前
Rsync + Sersync 实时数据同步方案
linux·网络安全·信息安全·云计算·rsync·系统运维·sersync