猿创征文|云原生|kubernetes实务---部署MySQL--实战(一)

简介: 猿创征文|云原生|kubernetes实务---部署MySQL--实战(一)

导读:

kubernetes集群搭建其实仅仅是第一步,不是为了部署而部署,当然是需要实战使用啦。在实际的生产活动中和测试活动中,kubernetes的使用是不相同的,本文试图从一个贴近实际的生产活动来讲述如何优雅的,正确的使用kubernetes。

部署前的相关知识简介:

由于是单实例的MySQL,因此,本文暂时不使用StatefulSet.。

StatefulSet的简介

在本文中,我们将在Kubernetes中部署数据库,因此我们必须了解什么是StatefulSet。是用于管理有状态应用程序的工作负载。它管理一组Pod的实现和扩展,并保证这些Pod的顺序和唯一性。

像Deployment一样,StatefulSet也管理具有相同容器规范的一组Pod。由StatefulSets维护的Pod具有唯一的,持久的身份和稳定的主机名,而不用管它们位于哪个节点上。如果我们想要一个跨存储的持久性,我们可以创建一个持久性卷并将StatefulSet用作解决方案的一部分。即使StatefulSet中的Pod容易发生故障,存储卷与新Pod进行匹配也很容易。

StatefulSet对于需要以下一项或多项功能的应用程序很有价值:

  • 稳定的唯一网络标识符。
  • 稳定,持久的存储。
  • 有序,顺畅的部署和扩展。
  • 有序的自动滚动更新。

在Kubernetes上部署数据库时,我们需要使用StatefulSet,但是使用StatefulSet有一些局限性:

  • 需要使用持久性存储卷为Pod提供存储。
  • 删除副本或按比例缩小副本将不会删除附加到StatefulSet的存储卷。存储卷确保数据的安全性。
  • StatefulSet当前需要Headless Service 来负责Pod的网络标识。
  • 与Deployment 不同,StatefulSet不保证删除StatefulSet资源时删除所有Pod,而Deployment在被删除时会删除与Deployment关联的所有Pod。在删除StateFul之前,你必须将pod副本数量缩小到0 。

实践正文:

一,

部署一个使用本地存储卷的单机MySQL

MySQL版本是5.7.23----通常用在测试环境,生产是不允许这样做的哦

这个部署示例将使用最为简单的本地存储,MySQL的相关配置文件和相关账号密码等敏感信息将使用明文存储在资源清单文件内,部署方式为deployment。

(1)StorageClass---存储类

这个可以不使用,因为我们下面将使用的是静态存储:

[root@master mysql]# cat mysql-sc.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner   # no-provisioner代表不会自动创建PV,创建PV步骤不可省略
volumeBindingMode: immutable     #立刻绑定

(2)pv---存储卷定义

在node2节点,新建目录,mkdir -p /mnt/mysql-data,因为在此文件内做了亲和度调度,指定是在node2存储数据卷。

  • volumeMode: Filesystem 这个其实是默认的,可以不写,但写了也没错。
  • persistentVolumeReclaimPolicy: Delete 数据卷回收策略,这里是删除,也就是pvc删除了,数据卷跟随删除,是默认策略,但不建议使用这个,建议使用Retain。
  • persistentVolumeReclaimPolicy: Recycle:不保留数据。经测试pvc删除后,在nfs服务端的数据也会随机删除。只有hostPath和NFS支持这种方式
  • Retain:不清理保留数据。即删除pvc或者pv后,在插件上的数据(nfs服务端)不会被删除。这种方式是最常用的,可以避免误删pvc或者pv而造成数据的丢失。
  • 本例使用了节点亲和度,这里比较容易出错的地方是,如果有亲和度策略,该pv无法更新,只能删除重新生成。说人话就是,比如,上面的删除策略想要调整,OK,必须删除pv,不能patch它,然后重新执行清单文件才可以,否则报错报到你怀疑人生。
cat mysql-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv
spec:
  capacity:
    storage: 15Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
#  storageClassName: local-storage
  local:       # 指定它是一个 Local Persistent Volume
    path: /mnt/mysql-data  # PV对应的本地磁盘路径
  nodeAffinity:     # 亲和性标志
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
            - k8s-node1   # 必须部署在node1上

(3)pvc---存储卷需求清单

没什么好说的了,只需要记住这个name: mysql-pv-claim,一会部署的时候引用这个名字即可。

[root@master mysql]# cat mysql-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
spec:
 # storageClassName: local-storage
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

(4)deployment方式部署

数据库密码是password

 strategy:
   type: Recreate

是一种部署方式,停止旧版本部署新版本,说人话就是,旧的去了,新的就来。当然,本例无所谓了。

strategy:

   type: RollingUpdate

   rollingUpdate:

     maxSurge: 1  -->一次可以添加多少个实例

     maxUnavailable: 0  -->能够容忍多少个实例无法使用,0表示不容忍

rollingupdae是另一种部署方式--见名思意,滚动更新通过逐个替换实例来逐步部署新版本的应用,直到所有实例都被替换完成为止。它通常遵循以下过程:在负载均衡器后面使用版本 A 的实例池,然后部署版本 B 的一个实例,当服务准备好接收流量时(Readiness Probe 正常),将该实例添加到实例池中,然后从实例池中删除一个版本 A 的实例并关闭。

通常生产环境是使用滚动更新或者蓝绿更新策略。

     - image: mysql:5.7.23
       imagePullPolicy: IfNotPresent

镜像拉取策略是本地有就用本地的,如果没有该镜像就去网络上拉取,通常生产环境也是用这个的,毕竟很多项目是在内网中的,获取镜像是有问题的。

     - name: mysql-persistent-storage
       persistentVolumeClaim:
         claimName: mysql-pv-claim

这个name写了两次,保证一致就可以,但可以随便定义, claimName: mysql-pv-claim这个是引用的上面的pvc的名字,不能乱写。

[root@master mysql]# cat deploy-mysql.yaml 
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: mysql:5.7.23
        imagePullPolicy: IfNotPresent
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim

(5)编写服务清单

这个service的作用只是一会测试的时候使用,端口暴露3306,集群内部使用。

[root@master mysql]# cat mysql-svc.yaml 
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  ports:
  - port: 3306
  selector:
    app: mysql
  clusterIP: None

应用这些文件(这个顺序是建立顺序,注意,StorageClass文件不需要执行,因为,我已经将关于它的地方注释掉了):

k apply -f mysql-pv.yaml -f mysql-pvc.yaml  -f deploy-mysql.yaml

单元测试:

客户端连接MySQL,可以看到连接成功,密码测试成功:

[root@master mysql]# kubectl run -it --rm --image=mysql:5.7.23 --restart=Never mysql-client -- mysql -h mysql -ppassword
If you don't see a command prompt, try pressing enter.
mysql> status;
--------------
mysql  Ver 14.14 Distrib 5.7.23, for Linux (x86_64) using  EditLine wrapper
Connection id:    4
Current database: 
Current user:   root@10.244.1.25
SSL:      Cipher in use is DHE-RSA-AES256-SHA
Current pager:    stdout
Using outfile:    ''
Using delimiter:  ;
Server version:   5.7.23 MySQL Community Server (GPL)
Protocol version: 10
Connection:   mysql via TCP/IP
Server characterset:  latin1
Db     characterset:  latin1
Client characterset:  latin1
Conn.  characterset:  latin1
TCP port:   3306
Uptime:     10 min 19 sec
Threads: 1  Questions: 12  Slow queries: 0  Opens: 105  Flush tables: 1  Open tables: 98  Queries per second avg: 0.019
--------------

在node2节点,查看一下此数据库的数据目录是否存在:

[root@slave2 ~]# ll /mnt/mysql-data/
total 188484
-rw-r----- 1 polkitd ssh_keys       56 Sep  7 13:44 auto.cnf
-rw------- 1 polkitd ssh_keys     1679 Sep  7 13:45 ca-key.pem
-rw-r--r-- 1 polkitd ssh_keys     1107 Sep  7 13:45 ca.pem
-rw-r--r-- 1 polkitd ssh_keys     1107 Sep  7 13:45 client-cert.pem
-rw------- 1 polkitd ssh_keys     1679 Sep  7 13:45 client-key.pem
-rw-r----- 1 polkitd ssh_keys      407 Sep  7 15:28 ib_buffer_pool
-rw-r----- 1 polkitd ssh_keys 79691776 Sep  7 15:28 ibdata1
-rw-r----- 1 polkitd ssh_keys 50331648 Sep  7 15:28 ib_logfile0
-rw-r----- 1 polkitd ssh_keys 50331648 Sep  7 13:44 ib_logfile1
-rw-r----- 1 polkitd ssh_keys 12582912 Sep  7 15:28 ibtmp1
drwxr-x--- 2 polkitd ssh_keys     4096 Sep  7 13:44 mysql
drwxr-x--- 2 polkitd ssh_keys     8192 Sep  7 13:44 performance_schema
-rw------- 1 polkitd ssh_keys     1679 Sep  7 13:45 private_key.pem
-rw-r--r-- 1 polkitd ssh_keys      451 Sep  7 13:45 public_key.pem
-rw-r--r-- 1 polkitd ssh_keys     1107 Sep  7 13:45 server-cert.pem
-rw------- 1 polkitd ssh_keys     1679 Sep  7 13:45 server-key.pem
drwxr-x--- 2 polkitd ssh_keys     8192 Sep  7 13:44 sys

看一哈pv和pvc是否正常(其实也是扯淡了,已经看到数据库的数据了,当然没问题啦);

[root@master mysql]# k get pv,pvc,svc
NAME                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                    STORAGECLASS   REASON   AGE
persistentvolume/mysql-pv   15Gi       RWO            Delete           Bound    default/mysql-pv-claim                           14m
NAME                                   STATUS   VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/mysql-pv-claim   Bound    mysql-pv   15Gi       RWO                           14m
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
service/kubernetes   ClusterIP   10.0.0.1     <none>        443/TCP    11d
service/mysql        ClusterIP   None         <none>        3306/TCP   10m

小结:

OK,现在一个最为简单的MySQL就部署好了, 那么,部署的这么一个数据库有什么问题吗?当然有啦,第一,数据库的密码以明文的形式存在pv建立的文件里,毫无秘密可言,第二,此数据库使用的是默认3306端口,也是毫无安全性,所有的配置都是默认,此数据库也可以说是一个没有任何定制的数据库,比如,慢查询,binlog也没有开启等等个性化的设置都没有全部默认,第三,现在仅仅是一个数据库服务,如果有N个服务,比如redis单或者集群实例,nginx实例等等其他服务,那么,持久化存储的管理就会给我们带来一个巨大的挑战(这个例子使用的是静态存储,需要一个动态存储来解放自己啦)。

因此,可以说,这样创建的数据库是完全不能使用在生产环境的,只能是作为一个测试或者学习的环境,是一个快速出环境的手段啦。

二,部署一个生产可用的MySQL

生产环境下的可用的MySQL所要求的东西更多一点,比如,安全性,可定制化性,可扩展性,这些虽然简简单单的就这么几句话,但,实际做起来你就会发现不是那么好搞的哦,下面我就详细讲讲如何实现一个可用于生产环境的MySQL单机版部署:

首先,需要一个动态存储类,也就是StorageClass,还需要一个secret,以保存敏感信息,主要是MySQL的密码,其次,需要一个configmap,此文件保存MySQL的配置文件。

(1)

nfs的StorageClass类创建

就不在此文里说了,以我原来写的博文为主:kubernetes学习之持久化存储StorageClass(4)_zsk_john的博客-CSDN博客

(2)

存放密码的secret文件:

secret文件内的密码是加密了,type: Opaque表示模糊模式,没什么太多意义,需要和pvc一个namespace。

root用户名使用base64加密,密码也是同样的加密方式,这里,我的密码就不演示加密了:

[root@master wordpress]# echo -n root |base64
cm9vdA==
[root@master mysql1]# cat  secret.yaml 
kind: Secret
apiVersion: v1
metadata:
  name: user-and-password
  namespace: database
type: Opaque
data:
  username: cm9vdA==
  password: c2hpZ3VhbmczMg==

(3)

config文件

MySQL的主要配置文件,根据此配置文件,可定制MySQL:

这里的MySQL配置文件部分就可以实现端口号更改等等各种各样的需求,我写的这个是比较全的所有配置,但,基本都是默认的东西。

cm需要和secret以及pvc是一个namespace。

[root@master mysql1]# cat mysql-cm.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-config
  namespace: database
data:
  mysqld.cnf: |-
    [mysqld]
    pid-file        = /var/run/mysqld/mysqld.pid
    socket          = /var/run/mysqld/mysqld.sock
    datadir         = /var/lib/mysql
    log-error      = /var/log/mysql/error.log #haha
    symbolic-links=0
    sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'
    lock_wait_timeout = 3600
    open_files_limit    = 65535
    back_log = 1024
    max_connections = 512
    max_connect_errors = 1000000
    table_open_cache = 1024
    table_definition_cache = 1024
    thread_stack = 512K
    sort_buffer_size = 4M
    join_buffer_size = 4M
    read_buffer_size = 8M
    read_rnd_buffer_size = 4M
    bulk_insert_buffer_size = 64M
    thread_cache_size = 768
    interactive_timeout = 600
    wait_timeout = 600
    tmp_table_size = 32M
    max_heap_table_size = 32M

(3)

存储清单文件---pvc

[root@master mysql1]# cat mysql-pvc.yaml 
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: mysql
  namespace: database
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1.5Gi
  storageClassName: managed-nfs-storage

(4)

服务文件

端口暴露的作用,为了后面的单元测试环节,和cm,secret,等一样的namespace。

[root@master mysql1]# cat mysql-svc.yaml 
apiVersion: v1
kind: Service
metadata:
  name: mysql
  namespace: database
spec:
  ports:
  - port: 3306
  selector:
    app: mysql
  clusterIP: None

(5)

部署文件

该文件仍然是指定了namespace为database,并且挂载了cm和secret

[root@master mysql1]# cat deploy-mysql.yaml 
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: mysql
  namespace: database
spec:
  selector:
    matchLabels:
      app: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:5.7.23
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef: 
              name: user-and-password
              key: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
        - name: config-volume1                      
          mountPath: "/etc/mysql/mysql.conf.d/"  
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql
      - name: config-volume1                      
        configMap:                                
          name: mysql-config               

(6)

部署命令

[root@master mysql1]# k apply  -f mysql-pvc.yaml -f mysql-svc.yaml -f secret.yaml -f mysql-cm.yaml -f deploy-mysql.yaml 
persistentvolumeclaim/mysql configured
service/mysql unchanged
secret/user-and-password unchanged
configmap/mysql-config unchanged
deployment.apps/mysql unchanged

(7)

单元测试

密码是设定在secret内的,现在密码校验通过,证明secret文件生效了。

[root@master mysql1]# kubectl run -it --rm --image=mysql:5.7.23 --restart=Never -n database mysql-client  -- mysql -h mysql -psecret
If you don't see a command prompt, try pressing enter.
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.23    |
+-----------+
1 row in set (0.00 sec)
mysql> status;
--------------
mysql  Ver 14.14 Distrib 5.7.23, for Linux (x86_64) using  EditLine wrapper

configmap的测试:

配置文件的查看(先进入容器,然后查看文件),和前面定义的配置文件匹配了,证明cm没有问题。

[root@master mysql1]# k exec -it mysql-bd8c75548-pk552 -n database -- /bin/bash
root@mysql-bd8c75548-pk552:/# cat /etc/mysql/mysql.conf.d/mysqld.cnf 
[mysqld]
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
datadir         = /var/lib/mysql
log-error      = /var/log/mysql/error.log #haha
symbolic-links=0
sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'
lock_wait_timeout = 3600
open_files_limit    = 65535
back_log = 1024
max_connections = 512
max_connect_errors = 1000000
table_open_cache = 1024
table_definition_cache = 1024
thread_stack = 512K
sort_buffer_size = 4M
join_buffer_size = 4M
read_buffer_size = 8M
read_rnd_buffer_size = 4M
bulk_insert_buffer_size = 64M
thread_cache_size = 768
interactive_timeout = 600
wait_timeout = 600
tmp_table_size = 32M
max_heap_table_size = 32Mroot

至此,一个自己可控的,具有一定安全性的单实例MySQL就部署完了。

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
存储 Kubernetes 开发工具
使用ArgoCD管理Kubernetes部署指南
ArgoCD 是一款基于 Kubernetes 的声明式 GitOps 持续交付工具,通过自动同步 Git 存储库中的配置与 Kubernetes 集群状态,确保一致性与可靠性。它支持实时同步、声明式设置、自动修复和丰富的用户界面,极大简化了复杂应用的部署管理。结合 Helm Charts,ArgoCD 提供模块化、可重用的部署流程,显著减少人工开销和配置错误。对于云原生企业,ArgoCD 能优化部署策略,提升效率与安全性,是实现自动化与一致性的理想选择。
1198 0
|
运维 Dubbo Cloud Native
Dubbo 云原生重构出击:更快部署、更强控制台、更智能运维
Apache Dubbo 最新升级支持云原生,提供一键部署微服务集群与全新可视化控制台,提升全生命周期管理体验,助力企业高效构建云原生应用。
1895 25
|
关系型数据库 MySQL 分布式数据库
阿里云PolarDB云原生数据库收费价格:MySQL和PostgreSQL详细介绍
阿里云PolarDB兼容MySQL、PostgreSQL及Oracle语法,支持集中式与分布式架构。标准版2核4G年费1116元起,企业版最高性能达4核16G,支持HTAP与多级高可用,广泛应用于金融、政务、互联网等领域,TCO成本降低50%。
|
存储 Kubernetes 异构计算
Qwen3 大模型在阿里云容器服务上的极简部署教程
通义千问 Qwen3 是 Qwen 系列最新推出的首个混合推理模型,其在代码、数学、通用能力等基准测试中,与 DeepSeek-R1、o1、o3-mini、Grok-3 和 Gemini-2.5-Pro 等顶级模型相比,表现出极具竞争力的结果。
|
存储 Kubernetes 监控
K8s集群实战:使用kubeadm和kuboard部署Kubernetes集群
总之,使用kubeadm和kuboard部署K8s集群就像回归童年一样,简单又有趣。不要忘记,技术是为人服务的,用K8s集群操控云端资源,我们不过是想在复杂的世界找寻简单。尽管部署过程可能遇到困难,但朝着简化复杂的目标,我们就能找到意义和乐趣。希望你也能利用这些工具,找到你的乐趣,满足你的需求。
1457 33
|
Kubernetes 开发者 Docker
集群部署:使用Rancher部署Kubernetes集群。
以上就是使用 Rancher 部署 Kubernetes 集群的流程。使用 Rancher 和 Kubernetes,开发者可以受益于灵活性和可扩展性,允许他们在多种环境中运行多种应用,同时利用自动化工具使工作负载更加高效。
1023 19
|
存储 测试技术 对象存储
使用容器服务ACK快速部署QwQ-32B模型并实现推理智能路由
阿里云最新发布的QwQ-32B模型,通过强化学习大幅度提升了模型推理能力。QwQ-32B模型拥有320亿参数,其性能可以与DeepSeek-R1 671B媲美。
|
存储 Kubernetes 测试技术
企业级LLM推理部署新范式:基于ACK的DeepSeek蒸馏模型生产环境落地指南
企业级LLM推理部署新范式:基于ACK的DeepSeek蒸馏模型生产环境落地指南
1022 12
|
Cloud Native Serverless 数据中心
阿里云ACK One:注册集群支持ACS算力——云原生时代的计算新引擎
阿里云ACK One:注册集群支持ACS算力——云原生时代的计算新引擎
669 10
|
人工智能 Kubernetes 异构计算
大道至简-基于ACK的Deepseek满血版分布式推理部署实战
大道至简-基于ACK的Deepseek满血版分布式推理部署实战
1041 5

推荐镜像

更多