在kubernetes中部署MySQL。
目录
使用Deployment部署MySQL
创建pvc
创建msyql-pod
创建service
登录mysql
讨论一下为什么要用StatefulSet部署MySQL
使用StatefulSet部署MySQL
在kubernetes中部署mysql除了需要部署mysql-pod,还要给mysql-pod创建一个pvc来持久化存储数据库的数据,以及一个service来暴露mysql服务的端口。因此本次部署共分以下三个步骤:
1、创建一个PVC,用于持久化mysql数据,即存储mysql数据
2、创建一个pod,pod中运行mysql容器
3、创建一个service用来暴露mysql的3306端口
创建一个PVC,用于持久化mysql数据,即存储mysql数据 。
#这里采用动态pv/pvc,已创建名为rook-ceph-block的ceph块存储StorageClasses
vim pvc-mysql-01.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-mysql-01
spec:
storageClassName: rook-ceph-block
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
#命令解释:
apiVersion: v1
#定义资源类型为pvc
kind: PersistentVolumeClaim
metadata:
name: pvc-mysql-01
spec:
#指定存储类的名称,即由那个存储类来自动创建和绑定对应的pv
storageClassName: rook-ceph-block
#设置用户对存储资源的访问权限,块存储仅支持ReadWriteOnce
accessModes:
- ReadWriteOnce
#描述对存储资源的请求,这里申请10G大小的存储空间
resources:
requests:
storage: 10Gi
#访问模式(accessModes)
用于描述用户应用对存储资源的访问权限,访问权限包括下面几种方式:
ReadWriteOnce(RWO):读写权限,但是只能被单个节点挂载(块存储不能共享只能被单个节点挂载)
ReadOnlyMany(ROX): 只读权限,可以被多个节点挂载
ReadWriteMany(RWX):读写权限,可以被多个节点挂载
生产环境中通常采用StatefulSet pod控制器来部署mysql数据库,达到一主多从的效果,本次测试部署单节点数据库,不需要主从,故采用deployment的方式创建mysql pod 。
vim mysql-01.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-01
spec:
replicas: 1
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: 1qaz@wsx
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-volume
mountPath: /var/lib/mysql
volumes:
- name: mysql-volume
persistentVolumeClaim:
claimName: pvc-mysql-01
命令解释:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-01
spec:
selector:
matchLabels:
app: mysql
#设置pod更新策略为recreate
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:5.6
name: mysql
#设置容器的环境变量,这里是指定mysql的root密码为1qaz@wsx
env:
- name: MYSQL_ROOT_PASSWORD
value: 1qaz@wsx
ports:
- containerPort: 3306
name: mysql
#自定义一个volume,并挂载到/var/lib/mysql目录下
volumeMounts:
- name: mysql-volume
mountPath: /var/lib/mysql
#设置volume的参数,这里使用名为mysql-pvc-01的pvc去请求pv来填充mysql-volume
volumes:
- name: mysql-volume
persistentVolumeClaim:
claimName: pvc-mysql-01
创建一个service用来向集群外暴露mysql的3306端口。
vim svc-mysql-01.yaml
apiVersion: v1
kind: Service
metadata:
name: svc-mysql-01
spec:
selector:
app: mysql
type: NodePort
ports:
- port: 3306
targetPort: 3306
nodePort: 30001
部署完成后如何登录mysql?
[root@master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mysql-01-6c49f78548-z6hkl 1/1 Running 0 17h 10.122.104.61 node2
[root@master ~]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
svc-mysql-01 NodePort 10.10.3.110 3306:30001/TCP 17h app=mysql
pod内:
#推荐:mysql -uroot -p1qaz@wsx
# mysql -h 10.122.104.61 -uroot -p1qaz@wsx
# mysql -h 172.31.246.31 -P 30001 -uroot -p1qaz@wsx
集群内:
#推荐:mysql -h 10.10.3.110 -uroot -p1qaz@wsx
# mysql -h 10.122.104.61 -uroot -p1qaz@wsx
# mysql -h 172.31.246.31 -P 30001 -uroot -p1qaz@wsx
集群外:
# mysql -h 172.31.246.31 -P 30001 -uroot -p1qaz@wsx
总结:
在pod内:直接使用账号密码即可;即:mysql -uroot -p1qaz@wsx
在集群内:可以指定主机IP为service-IP,pod-ip,以及node-ip,这里推荐在集群内部使用service-ip来登录mysql。因为service本身的作用就是为pods提供一个稳定的IP,不会因为pod调度而变化。
在集群外:只能通过node-ip加nodeport来登录mysql。
以上就是使用deployment控制器部署MySQL的全部内容,但是mysql作为一个有状态应用,显然使用statefulset控制器部署更合适。
Deployment适合无状态应用程序的部署,它的优点是可以自动创建和管理Pod,并支持快速水平扩展。但是,MySQL是有状态的应用程序,它需要稳定的网络标识符(hostname),以便跨Pod保持持久的连接和数据一致性。Deployment不是为有状态应用程序设计的,因此不是最佳选择。
相反,StatefulSet提供了有状态应用程序的部署和管理,它会给每个Pod分配稳定的网络标识符,支持Pod的有序部署和有序回收,保证了Pod之间的数据稳定性。在数据处理应用程序中,StatefulSet通常是更好的选择。
当副本数为1时,使用Deployment和StatefulSet部署mysql有什么区别呢?
资源命名:StatefulSet允许为每个副本指定唯一的名称,即Pod的名称,而在Deployment中使用的Pod名称是随机生成的。这意味着,在StatefulSet中,每个Pod可以直接通过应用名称来访问数据库实例,而在Deployment中,需要通过Service名称来访问实例。(这一点在上述实验过程可以验证,当我们在集群内访问mysql时,-h需要指定service的IP,如果使用StatefulSet可以-h mysql pod 的名称。)
稳定的网络标识:StatefulSet提供了每个Pod的稳定网络标识,即DNS名称,而在Deployment中,Pod名称是不稳定的,这意味着在StatefulSet中,可以方便地进行Pod的扩容、缩容等操作,而不会影响其他组件的网络标识。
将使用Deployment部署的yaml改为使用StatefulSet,如下所示:
使用这两种方式在yaml文件上有哪些区别呢?
首先,pvc和service部分是一样的,没有变化,只需修改pod部分。
1、将 Deployment 中的 kind 改为 StatefulSet。
2、在 StatefulSet 的 spec 中,添加了使用 serviceName 指定对应的 Service 名称,deployment中是不需要的。
使用StatefulSet部署应用需要在spec中使用serviceName指定对应的Service名称,是因为StatefulSet控制器创建的Pod具有稳定的网络标识符(Stable Network Identifiers)。每个Pod都有一个唯一的索引,例如pod-0,pod-1,pod-2等。这些索引用于在网络中区分和定位每个Pod。
通过指定serviceName,StatefulSet可以确保其Pod的网络标识符与关联的Service进行匹配。这样,每个Pod都可以通过Service名称而不是Pod名称进行访问,从而实现透明的服务发现和负载均衡。
此外,如果StatefulSet的规模发生变化(例如扩展或缩减Pod数量),服务名称将保持不变。这意味着重新创建或删除Pod时,将保留与之关联的Service,并且不会中断对其的访问。这种稳定的网络标识符对于有状态应用特别重要,它们需要保持持久化数据和网络连接的一致性。
3、StatefulSet和deployment在定义pod更新策略上的区别:
在deployment中使用strategy来定义pod的更新策略:
strategy.type: Recreate
表示使用重建策略,在更新期间删除所有旧的Pod,然后再创建新的Pod。strategy.type: RollingUpdate
表示使用滚动更新策略,逐个更新Pod。在StatefulSet中使用
updateStrategy
来定义pod的更新策略:
updateStrategy.type: RollingUpdate
表示使用滚动更新策略,逐个更新Pod,保证至少有指定数量的Pod在更新期间保持运行。updateStrategy.type: OnDelete
表示在Pod运行时不更新它们,只有在Pod被删除时才会更新。
4、在 StatefulSet 中使用 volumeClaimTemplates 来定义 PVC 模板,可以为每个 Pod 分别创建对应的 PVC。
在
Deployment
中,当创建多个副本(replicas)的Pod
时,它们会共享一个PVC,但是在StatefulSet会根据volumeClaimTemplates为每个pod有序的创建单独的pvc。
如下所示使用Deployment创建三副本的msyql,存储使用ceph rbd,提供rwo的读写方式:
如上所示,三副本的msyql只创建了一个pvc、一个pv,第一个pod使用后,另外两个将无法使用。可以使用cephfs提供rwm的读写方式来解决此问题。
如下图所示使用statefulset创建三副本MySQL,存储使用ceph rbd,提供rwo的读写方式:
如上图所示statefulset会自动创建三个pv、pvc,同时可以发现由于statefulset具有 volumeClaimTemplates字段,无需提前创建pvc,创建了它也不会用你的(pvc-mysql-01)。
以下是完整的使用statefulset部署MySQL的yaml文件:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: svc-mysql-01
replicas: 3
selector:
matchLabels:
app: mysql
updateStrategy:
type: RollingUpdate
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: 1qaz@wsx
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-volume
mountPath: /var/lib/mysql
volumes:
- name: mysql-volume
persistentVolumeClaim:
claimName: pvc-mysql-01
volumeClaimTemplates:
- metadata:
name: mysql-volume
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: rook-ceph-block
---
apiVersion: v1
kind: Service
metadata:
name: svc-mysql-01
spec:
selector:
app: mysql
type: NodePort
ports:
- port: 3306
targetPort: 3306
nodePort: 30002