本文使用的是本机挂载数据,这样存在一个弊端没有pvc挂载好
重点来了:这种共享宿主机存储的方法似乎可以解决Mysql数据库数据恢复的场景,我们似乎可以万事大吉了!But,有的老铁会问:如果我得宿主机挂了怎么办?或者Pod没有在上一次节点上拉起,而是在新的节点上拉起,那数据都不在一个宿主机上,还恢复个锤子! 听起来有点儿道理啊,确实存在这个问题那怎么解决呢?还是那句话 :总有”好事者”替我们解决了这个问题!
既然Host类型
的持久化存储无法解决节点宕机或者pod在另外的机器上拉起导致数据无法恢复的Bug,那我们就应该思考一个问题:既然我无法在宿主机持久化,那我在集群之外的服务器上存储数据,让我的Pod关联到这个数据存储服务器上,同时我对这个数据存储服务器做高可用,岂不美哉? 此处应该有掌声,三分钟!
想法很好,那我们来介绍一下K8S给我们的解决方案: PersistentVolumes 简称PV
PV 是什么?它是一种插件,它能够支持多种数据存储服务器,通过PV,我们能在K8S集群中,把我们的数据持久化到外部的服务器中。下图是PV能够支持的数据存储服务类型
k8s分为有状态和无状态两种创建pod方式, 有状态保证了数据的持久化适合mysql,不会像无状态那样滚动升级,而是关闭旧的pod在新启动一个pod,保证了数据持久化
背景
K8S 中,由于ReplicaSet、ReplicationController、Deployment等这些控制器都是无状态的,但是想要使用k8s来编排有状态的服务如数据库等,k8s 推出了面向有状态服务的工作负载 StatefulSet。网络持久化、存储持久化,部署持久化有状态服务
定义
无状态服务(stateless service)对单次请求的处理,不依赖其他请求,也就是说,处理一次请求所需的全部信息,要么都包含在这个请求里,要么可以从外部获取到(比如说数据库),服务器本身不存储任何信息。
有状态服务(stateful service)则相反,它会在自身保存一些数据,先后的请求是有关联的。
电商购物为例,在商城里购买一件商品。需要经过放入购物车、确认订单、付款等多个步骤。由于HTTP协议本身是无状态的,所以为了实现有状态服务,就需要通过一些额外的方案。比如最常见的session,将用户挑选的商品(购物车),保存到session中,当付款的时候,再从购物车里取出商品信息。
二、无状态服务 和 有状态服务
无状态服务特点
1、数据方面:无状态服务不会在本地存储持久化数据.多个实例可以共享相同的持久化数据
2、结果方面:多个服务实例对于同一个用户请求的响应结果是完全一致的
3、关系方面:这种多服务实例之间是没有依赖关系
4、影响方面:在k8s控制器 中动态启停无状态服务的pod并不会对其它的pod产生影响
5、示例方面:nginx实例,tomcat实例,web应用
6、资源方面:相关的k8s资源有:ReplicaSet、ReplicationController、Deployment
7、创建方式:Deployment被设计用来管理无状态服务的pod
每个 pod完全一致,原因如下:
无状态服务内的多个 Pod创建的顺序是没有顺序的
无状态服务内的多个Pod的名称是随机的.pod被重新启动调度后,它的名称与IP都会发生变化
无状态服务内的多个Pod背后是共享存储的
8、扩缩容方式:随机缩容
由于是无状态服务,所以这些控制器创建的pod序号都是随机值。并且在缩容也是随机,并不会明确缩容某一个pod。因为所有实例得到的返回值都是一样,所以缩容任何一个pod都可以。
有状态服务介绍
1、数据方面:有状态服务需要在本地存储持久化数据,典型的是分布式数据库的应
2、结果方面:实例之间,请求结果可能存在不一致
3、关系方面:分布式节点实例之间有依赖的拓扑关系.比如,主从关系.
4、影响方面:如果K8S停止分布式集群中任 一实例pod,就可能会导致数据丢失或者集群的crash
5、示例方面:mysql数据库、kafka、zookeeper、Redis主从架构
6、资源方面:statefulSet
7、创建方式:statefulSet管理
Stateful管理有状态的应用,Pod有如下特征:
唯一性:每个Pod会被分配一个唯一序号.
顺序性:Pod启动,更新,销毁是按顺序进行.
稳定的网络标识:Pod主机名,DNS地址不会随着Pod被重新调度而发生变化.
稳定的持久化存储:Pod被重新调度后,仍然能挂载原有的PV,从而保证了数据的完整性和一致性
有状态的 pod是用来运行有状态应用的,所以其在数据卷上存储的数据非常重要,在 Statefulset 缩容时删除这个声明将是灾难性的,特别是对于 Statefulset 来说,缩容就像减少其 replicas 数值一样简单。基于这个原因,当需要释放特定的持久卷时,需要手动删除对应的持久卷声明。
无状态服务(Stateless Service):
是指该服务运行的实例不会在本地存储需要持久化的数据,并且多个实例对于同一个请求响应的结果是完全一致的。这类服务在网易蜂巢云平台创建后,借助k8s内部的负载均衡,当访问该服务的请求到达服务一端后,负载均衡会随机找到一个实例来完成该请求的响应(目前为轮询)。这类服务的实例可能会因为一些原因停止或者重新创建(如扩容时),这时,这些停止的实例里的所有信息(除日志和监控数据外)都将丢失(重启容器即会丢失)。因此如果您的容器实例里需要保留重要的信息,并希望随时可以备份以便于以后可以恢复的话,那么建议您创建有状态服务。
有状态服务(Stateful Service):
是指该服务的实例可以将一部分数据随时进行备份,并且在创建一个新的有状态服务时,可以通过备份恢复这些数据,以达到数据持久化的目的。有状态服务只能有一个实例,因此不支持“自动服务容量调节”。一般来说,数据库服务或者需要在本地文件系统存储配置文件或其它永久数据的应用程序可以创建使用有状态服务。要想创建有状态服务,必须满足几个前提:
待创建的服务镜像(image)的Dockerfile中必须定义了存储卷(Volume),因为只有存储卷所在目录里的数据可以被备份
创建服务时,必须指定给该存储卷分配的磁盘空间大小
如果创建服务的同时需要从之前的一个备份里恢复数据,那么还要指明该存储卷用哪个备份恢复。
无状态服务和有状态服务主要有以下几点区别:
实例数量:无状态服务可以有一个或多个实例,因此支持两种服务容量调节模式;有状态服务只能有一个实例,不允许创建多个实例,因此也不支持服务容量调节模式。
存储卷:无状态服务可以有存储卷,也可以没有,即使有也无法备份存储卷里面的数据;有状态服务必须要有存储卷,并且在创建服务时,必须指定给该存储卷分配的磁盘空间大小。
数据存储:无状态服务运行过程中的所有数据(除日志和监控数据)都存在容器实例里的文件系统中,如果实例停止或者删除,则这些数据都将丢失,无法找回;而对于有状态服务,凡是已经挂载了存储卷的目录下的文件内容都可以随时进行备份,备份的数据可以下载,也可以用于恢复新的服务。但对于没有挂载卷的目录下的数据,仍然是无法备份和保存的,如果实例停止或者删除,这些非挂载卷里的文件内容同样会丢失
https://help.aliyun.com/document_detail/163545.html 在边缘托管集群创建过程中,平台会默认为您创建至少一个ECS实例,并接入到集群管控。该实例主要用来部署云端管控应用,也支持您自定义的云端管控应用部署。通过默认自带node-role.alib
abacloud.com/addon: Effect: NoSchedule污点(Taints),来保证边缘业务不会部署在云端管控节点。截止1.14.8-aliyunedge.1版本,中心管控节点上默认安装的管控应用有:
...
nodeSelector:
alibabacloud.com/is-edge-worker: 'false'
beta.kubernetes.io/arch: amd64
beta.kubernetes.io/os: linux
tolerations:
- effect: NoSchedule
key: node-role.alibabacloud.com/addon
operator: Exists
...
还可以去除污点然后在加上污点,这样期间部署的pod也不会被驱逐
批量添加污点
- 登录容器服务管理控制台,在左侧导航栏中选择集群。
- 在集群列表页面中,单击目标集群名称,然后在左侧导航栏中,选择节点管理 > 节点。
- 在节点页面右上角单击标签与污点管理。
- 单击污点页签,批量选择节点,单击添加污点。
- 在弹出的对话框中设置名称、值和Effect。 Effect参数的说明如下,更多信息,请参见污点和容忍度。
参数名称 参数说明
NoSchedule 如果污点中存在至少一个Effect值为NoSchedule的污点, 则系统不会将Pod分配到该节点。
NoExecute 任何不能忍受这个污点的Pod都会被驱逐,任何可以忍受这个污点的Pod都不会被驱逐。
PreferNoSchedule 系统会尽量避免将Pod调度到存在其不能容忍污点的节点上, 但这不是强制的。
node-role.alibabacloud.com/addon: effect: NoSchedule
例如追加这段话就是说只运行在管控节点,不需要另外指定ip了
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
nodeSelector:
alibabacloud.com/is-edge-worker: 'false'
beta.kubernetes.io/arch: amd64
beta.kubernetes.io/os: linux
tolerations:
- effect: NoSchedule
key: node-role.alibabacloud.com/addon
operator: Exists
在第一个spec后面加入一个serviceName可直接指定service
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis-cm
namespace: database
spec:
serviceName: redisdemo2
replicas: 1
selector:
matchLabels:
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
configMap:
name: myconfigmap
configMap:
name: myconfigmap 名称一定要比上面那个少两格否则只能挂成临时目录
挂载格式
volumeMounts:
# 从configmap获取的配置文件,挂载到指定文件中
- name: conf
mountPath: /conf/redis.conf
subPath: redis.conf
- name: data
mountPath: /data/redis
- name: logs
mountPath: /logs
# 时区设置
- name: timezone
mountPath: /etc/localtime
volumes:
- name: conf
# 配置文件采用configMap
configMap:
name: redis
defaultMode: 0755
# 日志采用hostPath卷
- name: logs
hostPath:
type: DirectoryOrCreate
path: /logs
# 时区定义
- name: timezone
hostPath:
path: /usr/share/zoneinfo/Asia/Shanghai
- name: data
hostPath:
type: DirectoryOrCreate
path: /home
挂载nasPVC
volumeMounts:
- name: pvc-nas
mountPath: /data
volumes:
- name: pvc-nas
persistentVolumeClaim:
claimName: static-nas-pvc
挂载云盘非vpc
volumeMounts:
- mountPath: /cache-test
name: cache-volume
volumes:
- name: cache-volume
csi:
driver: diskplugin.csi.alibabacloud.com
fsType: ext4
volumeAttributes:
volumeSize: "20"
tags: "test:eci"
参考配置1
[root@k8s-master1 ~]# cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: mysql #为该Deployment设置key为app,value为mysql的标签
name: mysql
namespace: test
spec:
replicas: 1 #副本数量
selector: #标签选择器,与上面的标签共同作用
matchLabels: #选择包含标签app:nginx的资源
app: mysql
template: #这是选择或创建的Pod的模板
metadata: #Pod的元数据
labels: #Pod的标签,上面的selector即选择包含标签app:nginx的Pod
app: mysql
spec: #期望Pod实现的功能(即在pod中部署)
containers: #生成container,与docker中的container是同一种
- name: mysql
image: mysql:5.7 #使用镜像mysql: 创建container,该container默认3306端口可访问
ports:
- containerPort: 3306 # 开启本容器的3306端口可访问
env:
- name: MYSQL_ROOT_PASSWORD
value: hjj123456
volumeMounts: #挂载持久存储卷
- name: mysql-data #挂载设备的名字,与volumes[*].name 需要对应
mountPath: /var/lib/mysql #挂载到容器的某个路径下
- name: mysql-dev-conf
mountPath: /etc/mysql
volumes:
- name: mysql-data #和上面保持一致 这是本地的文件路径,上面是容器内部的路径
nfs:
server: 10.0.19.129 #nfs的ip地址
path: /opt/data/mysql/data #此路径需要实现创建
- name: mysql-dev-conf
nfs:
server: 10.0.19.129
name: /opt/data/mysql/cnf #此路径需要实现创建
参考配置2
---
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-config
namespace: plugins
labels:
app: mysql
data:
my.cnf: |-
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
skip-character-set-client-handshake = true
max_connections=2000
secure_file_priv=/var/lib/mysql
lower_case_table_names = 1
log-error=/var/lib/mysql/mysql_error.log
bind-address=0.0.0.0
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'
---
apiVersion: v1
kind: Service
metadata:
labels:
app: mysql
name: mysql-svc
namespace: plugins
spec:
type: NodePort
ports:
- name: http
port: 3306
nodePort: 30021
protocol: TCP
targetPort: 3306
selector:
app: mysql
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
namespace: plugins
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- args:
- --datadir
- /var/lib/mysql/datadir
env:
- name: MYSQL_ROOT_PASSWORD
value: root
- name: MYSQL_USER
value: user
- name: MYSQL_PASSWORD
value: user
image: mysql:5.7
name: mysql-container
ports:
- containerPort: 3306
name: dbapi
volumeMounts:
- mountPath: /var/lib/mysql
name: mysql-storage
- name: config
mountPath: /etc/mysql/conf.d/my.cnf
subPath: my.cnf
volumes:
- name: mysql-storage
persistentVolumeClaim:
claimName: nfs-plugins
- name: config
configMap:
name: mysql-config
- name: localtime
hostPath:
type: File
path: /etc/localtime
自己配置 , nodeName: gem-yxyw-t-c02,分配主机的时候需要查看主机名
需要说明的是strategy部分,用于定义deployment的升级策略。
spec.strategy:用于定义升级的策略
spec.strategy.type:定义使用何种方式升级。一种是RollingUpdate,即滚动升级。另一种方式为Recreate。即先将所有旧的Pod停止,然后再启动新的pod。默认策略即为RollingUpdate
#这个升级策略很重要,之前没有指定用的是默认的滚动升级RollingUpdate,会导致更新的pod无法启动,因为这种模式之前的容器没有停止还占用了挂载的宿主机目录,改成将Recreate模式会将之前的容器停止,在新启动一个宿主机挂载目录就没有被占用会直接成功,这也导致重启的时候会有一段停止时间
但是如果定义为无状态就不需要指定升级策略
kind: StatefulSet #有状态
kind: Deployment #无状态
实际配置1
---
apiVersion: v1
kind: ConfigMap
metadata:
name: mysqldb01-config
labels:
app: gem-sale-t-db01
data:
my.cnf: |-
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
skip-character-set-client-handshake = true
max_connections=2000
secure_file_priv=/var/lib/mysql
lower_case_table_names = 1
bind-address=0.0.0.0
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'
---
apiVersion: v1
kind: Service
metadata:
labels:
app: gem-sale-t-db01
name: gem-sale-t-db01
spec:
type: NodePort
ports:
- name: http
port: 3306
nodePort: 30001
protocol: TCP
targetPort: 3306
selector:
app: gem-sale-t-db01
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: gem-sale-t-db01
name: gem-sale-t-db01
spec:
serviceName: gem-sale-t-db01
replicas: 1
selector:
matchLabels:
app: gem-sale-t-db01
strategy: #更新策略
type: Recreate # 策略类型 .spec.strategy.type 可以是 “Recreate” 或 “RollingUpdate”。“RollingUpdate” 是默认值。
Recreate: #.spec.strategy 策略指定用于用新 Pod 替换旧 Pod 的策略。 .spec.strategy.type 可以是 “Recreate” 或 “RollingUpdate”。“RollingUpdate” 是默认值。
maxSurge: 25% #最大峰值
maxUnavailable: 25% #最大不可用
template:
metadata:
labels:
app: gem-sale-t-db01
spec:
containers:
- name: gem-sale-t-db01
image: mysql:5.7
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: 3!y5cD&%2OWz
livenessProbe:
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
exec:
command: ["mysqladmin", "-uroot", "-p${MYSQL_ROOT_PASSWORD}", "ping"]
readinessProbe:
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
exec:
command: ["mysqladmin", "-uroot", "-p${MYSQL_ROOT_PASSWORD}", "ping"]
volumes:
- name: config
configMap:
name: mysqldb01-config
nodeName: gem-yxyw-t-c02
实际配置2 mysql需要持久化推荐使用这个配置,这个不要加升级测略
---
apiVersion: v1
kind: ConfigMap
metadata:
name: gem-nacos-t-db
labels:
app: gem-nacos-t-db
data:
my.cnf: |-
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
skip-character-set-client-handshake = true
max_connections=2000
secure_file_priv=/var/lib/mysql
log-error=/var/lib/mysql/mysql_error.log
lower_case_table_names = 1
bind-address=0.0.0.0
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'
---
apiVersion: v1
kind: Service
metadata:
labels:
app: gem-nacos-t-db
name: gem-nacos-t-db
spec:
type: NodePort
ports:
- name: http
port: 3306
nodePort: 30005
protocol: TCP
targetPort: 3306
selector:
app: gem-nacos-t-db
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: gem-nacos-t-db
name: gem-nacos-t-db
spec:
serviceName: gem-nacos-t-db
replicas: 1
selector:
matchLabels:
app: gem-nacos-t-db
template:
metadata:
labels:
app: gem-nacos-t-db
spec:
containers:
- name: gem-nacos-t-db
image: mysql:5.7
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: Gd*(53#SALE
livenessProbe:
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
exec:
command: ["mysqladmin", "-uroot", "-p${MYSQL_ROOT_PASSWORD}", "ping"]
readinessProbe:
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
exec:
command: ["mysqladmin", "-uroot", "-p${MYSQL_ROOT_PASSWORD}", "ping"]
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
- name: timezone
mountPath: /etc/localtime
- name: config
mountPath: /etc/mysql/conf.d/my.cnf
subPath: my.cnf
volumes:
- name: config
configMap:
name: gem-nacos-t-db
- name: timezone
hostPath:
path: /usr/share/zoneinfo/Asia/Shanghai
- name: mysql-data
hostPath:
type: DirectoryOrCreate
path: /data/mysql/gem-nacos-t-db/mysql-data
nodeName: gem-yxyw-t-c02
实际配置3,local挂载,在k8s上创建pv和pvc
apiVersion: v1
kind: PersistentVolume
metadata:
name: gem-yx-d-db1
namespace: yx-dev
spec:
capacity:
storage: 50Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: gem-yx-d-db1
local:
path: /data/mysql/gem-yx-d-db1/data
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- gem-yxyw-t-c02
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gem-yx-d-db1
namespace: yx-dev
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 50Gi
storageClassName: gem-yx-d-db1
---
apiVersion: v1
kind: ConfigMap
metadata:
name: gem-yx-d-db1
labels:
app: gem-yx-d-db1
data:
my.cnf: |-
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
skip-character-set-client-handshake = true
max_connections=2000
secure_file_priv=/var/lib/mysql
log-error=/var/lib/mysql/mysql_error.log
lower_case_table_names = 1
bind-address=0.0.0.0
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'
---
apiVersion: v1
kind: Service
metadata:
labels:
app: gem-yx-d-db1
name: gem-yx-d-db1
spec:
type: NodePort
ports:
- name: http
port: 3306
nodePort: 30003
protocol: TCP
targetPort: 3306
selector:
app: gem-yx-d-db1
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: gem-yx-d-db1
name: gem-yx-d-db1
spec:
serviceName: gem-yx-d-db1
replicas: 1
selector:
matchLabels:
app: gem-yx-d-db1
template:
metadata:
labels:
app: gem-yx-d-db1
spec:
containers:
- name: gem-yx-d-db1
image: mysql:5.7
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: Gd*(53#SALE
livenessProbe:
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
exec:
command: ["mysqladmin", "-uroot", "-p${MYSQL_ROOT_PASSWORD}", "ping"]
readinessProbe:
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
exec:
command: ["mysqladmin", "-uroot", "-p${MYSQL_ROOT_PASSWORD}", "ping"]
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
- name: timezone
mountPath: /etc/localtime
- name: config
mountPath: /etc/mysql/conf.d/my.cnf
subPath: my.cnf
volumes:
- name: config
configMap:
name: gem-yx-d-db1
- name: timezone
hostPath:
path: /usr/share/zoneinfo/Asia/Shanghai
- name: mysql-data
persistentVolumeClaim:
claimName: gem-yx-d-db1
mysql8.0部署,亲测试验证可用,跟mysql5.7配置不同
---
apiVersion: v1
kind: ConfigMap
metadata:
name: gem-yx-t-db2
labels:
app: gem-yx-t-db2
data:
# my.cnf代表着mysql8的配置文件名称
my.cnf: |
[mysql]
# mysql客户端默认字符集
default-character-set=utf8
[mysqld]
# 数据库文件位置
datadir=/var/lib/mysql
# 允许最大连接数
max_connections=1000
# innodb的dml操作的行级锁的等待时间
innodb_lock_wait_timeout=500
# 设置mysql服务端默认字符集
character-set-server=utf8mb4
# 默认创建新数据的新建排序规则
collation-server=utf8mb4_general_ci
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB
# 缓存大小
sort_buffer_size=256MB
# 大小写敏感配置项0为敏感,1为不敏感
lower_case_table_names = 1 #不区分大小写
lower_case_table_names=1
# 选择正8区
default-time-zone='+8:00'
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
---
apiVersion: v1
kind: Service
metadata:
labels:
app: gem-yx-t-db2
name: gem-yx-t-db2
spec:
type: NodePort
ports:
- name: http
port: 3306
nodePort: 30002
protocol: TCP
targetPort: 3306
selector:
app: gem-yx-t-db2
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: gem-yx-t-db2
name: gem-yx-t-db2
spec:
serviceName: gem-yx-t-db2
replicas: 1
selector:
matchLabels:
app: gem-yx-t-db2
template:
metadata:
labels:
app: gem-yx-t-db2
spec:
containers:
- name: gem-yx-t-db2
image: mysql:8.0.19
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: 3!y5cD&%2OWz
livenessProbe:
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
exec:
command: ["mysqladmin", "-uroot", "-p${MYSQL_ROOT_PASSWORD}", "ping"]
readinessProbe:
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
exec:
command: ["mysqladmin", "-uroot", "-p${MYSQL_ROOT_PASSWORD}", "ping"]
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
- name: timezone
mountPath: /etc/localtime
- name: config
mountPath: /etc/mysql/conf.d/my.cnf
subPath: my.cnf
volumes:
- name: config
configMap:
name: gem-yx-t-db2
- name: timezone
hostPath:
path: /usr/share/zoneinfo/Asia/Shanghai
- name: mysql-data
hostPath:
type: DirectoryOrCreate
path: /data/mysql/gem-yx-t-db2/mysql-data
nodeName: gem-yxyw-t-c02
mkdir -p /data/mysql/GEM-SALE-T-DB01/mysql-data
mkdir -p /data/mysql/GEM-SALE-T-DB02/mysql-data
参数简介:
show variables like '%max_connections%'; #查数据库最大连接数确定配置是否生效
- ports: 配置镜像映射端口。
- env: 镜像环境变量配置,其中 MYSQL_ROOT_PASSWORD 是 Mysql 镜像用于配置 root 用户默认密码变量。
- resources: 配置 CPU、Memory 资源限制,可以通过配置该值来配置 Pod 的 QoS 级别。
- livenessProbe: 配置存活探针,定时检测 Mysql 应用运行状态,如果检测到 Mysql 挂掉将进行重启操作。
- readinessProbe: 配置就绪探针,定时检测 Mysql 应用启动状态,如果启动成功将允许流量涌入,启动失败将进行重启操作。
- command: 探针执行探测时执行的探测命令。
- volumeMounts: 存储卷挂载配置,用于镜像内存储的挂载配置,与 volumes 中对于的 name 进行绑定。
- volumes: 存储卷配置,可配置使用 pvc、hostPath、emptyDir、nfs 等存储,需要配置 name 值与 VolumeMounts 进行绑定。
- 在镜像内部命令行中输入 mysql 登录命令,测试是否能够正常登录:
$ mysql -h 10.36.21.220 -P 30336 --user=root --password=123456
mysql -h 10.36.21.220 -P 30336 -uroot -p'123456'
导出导入数据库
导出数据库所有库
mysqldump -h 127.0.0.1 -uroot -p"Gd*(53#SALE" -R -E --all-databases >back.sql
导入数据库所有库
mysql -h 10.36.21.220 -P 30004 -uroot -p'3!y5cD&%2OWz' <back.sql
k8s的mysql的pod误删之后数据恢复,
gem-sale-t-db04被删除之后,挂载的数据卷还在/data/mysql/GEM-SALE-T-DB04/mysql-data,我们从新创建一个pod把数据拷贝到新的挂载卷,数据库就自动恢复了
cd /data/mysql/GEM-SALE-T-DB06/mysql-data
\cp -rf /data/mysql/GEM-SALE-T-DB04/mysql-data/* ./
数据恢复
docker容器数据恢复
恢复步骤
1. 查找数据卷位置
数据卷目录在 /var/lib/docker/volumes 下,每个容器都会在该目录下有一个文件夹,如果容器还存在的话,我们可以使用 docker inspect 容器ID 去查看 数据卷位置,这下容器被删除了,可怎么办,只能挨个去找了,一般 MySQL 容器数据卷目录下会有一个 _data 目录,该目录下会显示你每个数据库的文件夹,最终找到了
2. 创建新数据卷
使用 docker volume create 数据卷名字 命令新建一个数据卷,docker volume ls 查看数据卷列表
docker volume create mysqldata
docker volume ls
注意:使用数据卷进行挂载的时候,数据卷必须是一个空的目录,也就是说不能有任何数据。
创建容器
执行创建指令:
docker run -d -p 3306:3306 --name mysql -v mysqldata:/var/lib/mysql -e MYSQL\_ROOT\_PASSWORD=123456 -d mysql:5.7
恢复数据之前需要把刚刚建立的数据卷里面关联的内容删除掉,然后把之前的数据卷内容复制到现在的数据卷进行数据恢复。
cd /var/lib/docker/volumes/mysqldata/_data/
rm -f *
rm -f -R *
复制内容到数据卷
cd /var/lib/docker/volumes/容器id/_data/
cp -R * /var/lib/docker/volumes/mysqldata/_data/
至此数据库数据恢复完成,需要重启下mysql容器,进入恢复的容器查看
docker stop mysql
docker start mysql
因使用Deployment创建的pod无法挂载数据库配置文件,所以采用使用镜像创建先创建一个配置文件后续好挂载,原理是先用YAML方式创建,然后编辑这个pod,新建一个镜像参照这个手动创建一个pod,指定节点后面可以yaml里面加入节点参数,
最后找到原因了,挂载配置哪里不能自己命名只能使用默认的名称
创建mysql配置文件
---
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-t1-config
labels:
app: gem-yx-t-db1
data:
my.cnf: |-
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
skip-character-set-client-handshake = true
max_connections=2000
secure_file_priv=/var/lib/mysql
lower_case_table_names = 1
bind-address=0.0.0.0
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'
创建pod镜像gem-yx-t-db1
mysql:5.7
3306 tcp
MYSQL_ROOT_PASSWORD Gd*(53#SALE
["mysqladmin","-uroot","-p${MYSQL_ROOT_PASSWORD}","ping"]
["mysqladmin","-uroot","-p${MYSQL_ROOT_PASSWORD}","ping"]
mysql-data /data/mysql/gem-yx-t-db1/mysql-data /var/lib/mysql
time /etc/localtime /etc/localtime
默认配置名 mysql-t1-config /etc/mysql/conf.d #自己取名无法启动
service创建
nodeName: gem-yxyw-t-c02 #绑定节点
select now(); #查看数据库时间是否正确
show variables like '%max_connections%'; #查数据库最大连接数确定配置是否生效
在k8s集群中,service和pod都可以通过域名的形式进行相互通信,换句话说,在k8s集群内,通过service和pod的域名,可以直接访问内部应用,不必在通过service ip地址进行通信,一般的,我们创建service的时候不建议指定service的clusterIP,而是让k8s自动为service分配一个clusterIP,这样,service的IP是自动分配,但是service名字总是固定的吧,这样在集群内部就可以直接通过service的域名来连接即可,如前端pod应用直接通过service域名来连接后端pod。
service的域名
<servicename>.<namespace>.svc.<clusterdomain>
其中,servicename为service名称,namespace为service所处的命名空间,clusterdomain是k8s集群设计的域名后缀,默认为cluster.local
mysql -h gem-yx-t-db1.yx-test.svc.cluster.local -uroot -p'Gd*(53#SALE'
mysql -h gem-yx-t-db2.yx-test.svc.cluster.local -uroot -p'3!y5cD&%2OWz'
mysql -h gem-yx-d-db1.yx-dev.svc.cluster.local -uroot -p'Gd*(53#SALE'
mysql -h gem-zs-t-db1.yx-test.svc.cluster.local -uroot -p'zs@JINDI'
mysql -h gem-nacos-t-db.nacos.svc.cluster.local -uroot -p'Gd*(53#SALE'
MySQL数据库之日志管理
[mysqld]
log-error=/home/mysql/mysql_error.log #指定错误日志的保存位置
general_log=ON 通用查询日志,用来记录MySQL的所有连接和语句,默认是关闭的。
general_log_file=/home/mysql/mysql_general.log
log-bin=mysql-bin #也可以log_bin=mysql-bin #二进制日志
#使用相对路径,则文件存储在默认目录/usr/local/mysql/data/中
slow_query_log=ON
slow_query_log_file=/home/mysql/mysql_slow_query.log
long_query_time=5 #慢查询时间,设置超过5秒执行的语句被记录,缺省时为10秒
[mysqld]
##错误日志,用来记录当MySQL启动、停止或运行时发生的错误信息,默认已开启
log-error=/home/mysql/mysql_error.log
##通用查询日志,用来记录MySQL的所有连接和语句,默认是关闭的
general_log=ON
general_log_file=/home/mysql/mysql_general.log
##二进制日志(binlog),用来记录所有更新了数据或者已经潜在更新了数据的语句,记录了数据的更改,可用于数据恢复,默认已开启
log-bin=mysql-bin #也可以log_bin=mysql-bin
#使用相对路径,则文件存储在默认目录/home/mysql/中
##慢查询日志,用来记录所有执行时间超过long_query_time秒的语句,可以找到哪些查询语句执行时间长,以便于优化,默认是关闭的
slow_query_log=ON
slow_query_log_file=/home/mysql/mysql_slow_query.log
long_query_time=5 #慢查询时间,设置超过5秒执行的语句被记录,缺省时为10秒
mysql -u root -p[密码]
#查看错误日志存放位置
show variables like 'log_error';
#查看通用查询日志是否开启
show variables like 'general%';
#查看二进制日志是否开启
show variables like 'log_bin%';
#查看慢查询日功能是否开启
show variables like '%slow%';
#查看慢查询时间设置
show variables like 'long_query_time';
#在数据库中设置开启慢查询的方法,即以修改变量值的方式开启。但重启服务后会失效。
set global slow_query_log=ON;