Kubernetes控制器(四)______StatefulSet

控制器介绍

StatefulSet: 是Kubernetes中用于管理有状态应用的控制器。与Deployment不同,StatefulSet用于部署和管理需要持久标识、有序部署和唯一网络标识的 Pod。典型的用例包括数据库、缓存和队列等有状态应用。(有状态服务:单点故障整体崩溃。无状态服务:单点故障不影响整体)

  1. 稳定的网络标识符: StatefulSet中的每个Pod都具有稳定的网络标识符,其名称遵循固定的命名模式。即Pod重新调度后其PodName和HostName不变,基于Headless Service(无头服务)来实现。(无头服务:就是跳过这个4层或者7层代理,直接与pod的真实Ip进行访问。正常我们通过nslookup解析到service的ip,而无头服务,通过解析后得到的是后端pod的ip地址)
  2. 有序部署: StatefulSet确保Pod按照固定顺序部署和更新。在Pod启动和停止时,StatefulSet会按照定义的顺序逐个进行,从而确保有序的启动和停止。即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次进行(即从0到N-1,在下一个Pod运行之前的所有Pod必须都是Running和Ready状态),基于init containers来实现。
  3. 持久标识: StatefulSet中的每个Pod都具有持久标识符,通常用于持久化存储(例如持久卷)。即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现。
  4. 有状态服务: StatefulSet管理的Pod可以用作有状态服务。与Deployment不同,StatefulSet管理的Pod具有固定的网络标识符和持久标识符,因此更适合于有状态应用的需求。
  5. 有序收缩,有序删除(即从N-1到0)

从StatefulSet的特点和应用场景发现,StatefulSet通过Headless Service生成可解析的DNS记录;通过volumeClaimTemplates创建pvc和对应的pv绑定;后定义StatefulSet来创建pod。

和Deployment相比:相同的是StatefulSet和Deployment管理了基于相同容器定义的一组Pod。但和Deployment不同的是,StatefulSet为它们的每个Pod维护了一个固定的ID。这些Pod是基于相同的声明来创建的,但是不能相互替换,无论怎么调度,每个Pod都有一个永久不变的ID。你在StatefulSet对象中定义你期望的状态,然后StatefulSet的控制器就会通过各种更新来达到那种你想要的状态。

基于StatefulSet的Mysql部署

在生产环境中数据的存储尤为重要,不管什么哪一类的Mysql高可用(keepalived+双主,MHA,MMM,Heartbeat+DRBD)基础都是Msql的主从复制。Mysql主从同步的过程第一部分就是master记录二进制日志。在每个事务更新数据完成之前,master在二日志记录这些改变。MySQL将事务写入二进制日志。在事件写入二进制日志完成后,master通知存储引擎提交事务。 下一步就是slave将master的binary log拷贝到它自己的中继日志。首先,slave开始一个工作线程——I/O线程。I/O线程在master上打开一个普通的连接,然后开始binlog dump process。Binlog dump process从master的二进制日志中读取事件,如果已经同步了master,它会睡眠并等待master产生新的事件。I/O线程将这些事件写入中继日志。 SQL slave thread(SQL从线程)处理该过程的最后一步。SQL线程从中继日志读取事件,并重放其中的事件而更新slave的数据,使其与master中的数据一致。只要该线程与I/O线程保持一致,中继日志通常会位于OS的缓存中,所以中继日志的开销很小。

k8s部署mysql集群(一主两从)在K8s官网有示例:https://kubernetes.io/zh-cn/docs/tasks/run-application/run-replicated-stateful-application/可供参考。集群读写分离,读数据库通过Service服务访问。通过headless服务对数据库实现写操作同时使Slave数据库与Master数据库实现同步。

部署持久化存储

可参考:https://blog.csdn.net/qq42004/article/details/137113713?spm=1001.2014.3001.5502

修改StorgaeClass对象中的parameters.pathPattern: “ . P V C . n a m e s p a c e / {.PVC.namespace}/ .PVC.namespace/{.PVC.annotations.nfs.io/storage-path}”
为:parameters.pathPattern: " . P V C . n a m e s p a c e / {.PVC.namespace}/ .PVC.namespace/{.KaTeX parse error: Expected 'EOF', got '}' at position 9: PVC.name}̲{.PVC.annotations.nfs.io/storage-path}"在mysql的Pod获取PVC后在存储后端创建的目录增加一层。否则容器创建的持久化目录都在一个目录内。

[root@localhost k8s]# tree -d /mnt/k8s/my
/mnt/k8s/my #命名空间名称:PVC.namespace
├── data-mysql-pass-0 #Pvc名称:$PVC.name
│   └── mysql #StatufulSet中Mountvolume中的subPaht
│       ├── mysql
│       ├── performance_schema
│       ├── sys
│       ├── test
│       └── xtrabackup_backupfiles

部署Service

apiVersion: v1
kind: Service
metadata:name: mysql-pass-svclabels: ser: mysql-ser namespace: my
spec:ports:- name: mysql port: 3306clusterIP: Noneselector:tai: mysql---apiVersion: v1
kind: Service
metadata:name: mysql-read-passlabels:app: mysql-ser-nodenamespace: my
spec:ports:- name: mysqlport: 3306protocol: TCPnodePort: 32302targetPort: 3306selector:tai: mysql type: NodePort

部署Secret、ConfigMap

apiVersion: v1
kind: Secret
metadata:name: mysql-secret
type: Opaque
data:bwk: cGFzc3dvcmQxMjM0NTY=  # 这里的值是密码的base64编码表示,echo -n '12345678' | base64
---
apiVersion: v1
kind: ConfigMap
metadata:name: mysql-cnf-maplabels:app: mysqlnamespace: my 
data:primary.cnf: |[mysqld]log-bin=mysql-bin bind-address = 0.0.0.0binlog_format=mixed log-bin-index=mysql-bin.index lower_case_table_names=1relay-log-index = slave-relay-bin.indexreplica.cnf: |[mysqld]bind-address = 0.0.0.0super-read-onlylog-bin=mysql-bin relay-log=relay-bin relay-log-index=slave-relay-bin.index lower_case_table_names=1

部署StatefulSet

apiVersion: apps/v1
kind: StatefulSet
metadata:name: mysql-passlabels:da: mysqlnamespace: my
spec:minReadySeconds: 20replicas: 3revisionHistoryLimit: 20selector:matchLabels:tai: mysqlserviceName: mysql-pass-svc#定义StatefulSet和Service的headless服务关联template:metadata:annotations: description: "Mysql containers for Master-slave replication"name: mysql-containerslabels:tai: mysqlnamespace: mysqlspec:initContainers:- name: init-mysqlimage: mysql:5.7imagePullPolicy: IfNotPresentenv:- name: MYSQL_ROOT_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretkey: bwkcommand:- bash- "-c"- |set -ex# 基于 Pod 序号生成 MySQL 服务器的 ID。[[ $HOSTNAME =~ -([0-9]+)$ ]] || exit 1ordinal=${BASH_REMATCH[1]}echo [mysqld] > /mnt/conf.d/server-id.cnf# 添加偏移量以避免使用 server-id=0 这一保留值。echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf# 将合适的 conf.d 文件从 config-map 复制到 emptyDir。if [[ $ordinal -eq 0 ]]; thencp /mnt/config-map/primary.cnf /mnt/conf.d/elsecp /mnt/config-map/replica.cnf /mnt/conf.d/fi          volumeMounts:- name: confmountPath: /mnt/conf.d- name: confg-mapmountPath: /mnt/config-map- name: clone-mysqlimage: docker.io/yizhiyong/xtrabackup:latestimagePullPolicy: IfNotPresent    command:- bash- "-c"- |set -ex# 如果已有数据,则跳过克隆。[[ -d /var/lib/mysql/mysql ]] && exit 0# 跳过主实例(序号索引 0)的克隆。[[ `hostname` =~ -([0-9]+)$ ]] || exit 1ordinal=${BASH_REMATCH[1]}#获取自动定义Pod名称的最后一个字段。即生成名称的mysql-pass-0的最后一个数字。[[ $ordinal -eq 0 ]] && exit 0# 当等于0的时候推出不等于0的时候执行下面操作,即从原来的对等节点克隆数据。ncat --recv-only  mysql-pass-$(($ordinal-1)).mysql-pass-svc  3307 | xbstream -x -C /var/lib/mysql# 准备备份。ncat --recv-only 通过headless服务访问访问方式是pod-name.namespace.svc.cluster.localxtrabackup --prepare --target-dir=/var/lib/mysqlvolumeMounts:- name: datamountPath: /var/lib/mysqlsubPath: mysql- name: confmountPath: /etc/mysql/conf.dcontainers:- name: mysqlimage: mysql:5.7imagePullPolicy: IfNotPresentenv:- name: MYSQL_ROOT_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretkey: bwk- name: LANGvalue: "C.UTF-8"#此处定义语言环境开发会在服务获取字符编码写Dockerfile的时候可以直接变更。ports:- name: mysqlcontainerPort: 3306volumeMounts:- name: datamountPath: /var/lib/mysqlsubPath: mysql - name: confmountPath: /etc/mysql/conf.d - name: timemountPath: /etc/localtimeresources:requests:cpu: 500mmemory: 1GilivenessProbe:exec:command: - /bin/sh - -ec- >-mysqladmin -uroot -p${MYSQL_ROOT_PASSWORD} PINGinitialDelaySeconds: 30periodSeconds: 10timeoutSeconds: 5readinessProbe:exec:# 检查我们是否可以通过 TCP 执行查询(skip-networking 是关闭的)。command:- /bin/sh- -ec - >-mysql -h127.0.0.1 -uroot -p$MYSQL_ROOT_PASSWORD -e'SELECT 1' initialDelaySeconds: 5periodSeconds: 2timeoutSeconds: 1- name: xtrabackupimage: docker.io/yizhiyong/xtrabackup:latestimagePullPolicy: IfNotPresentenv:- name: MYSQL_ROOT_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretkey: bwkports:- name: xtrabackupcontainerPort: 3307command:- bash- "-c"- |set -excd /var/lib/mysql# 确定克隆数据的 binlog 位置(如果有的话)。if [[ -f xtrabackup_slave_info && "x$(<xtrabackup_slave_info)" != "x" ]]; then# XtraBackup 已经生成了部分的 “CHANGE MASTER TO” 查询# 因为我们从一个现有副本进行克隆。(需要删除末尾的分号!)cat xtrabackup_slave_info | sed -E 's/;$//g' > change_master_to.sql.in# 在这里要忽略 xtrabackup_binlog_info (它是没用的)。rm -f xtrabackup_slave_info xtrabackup_binlog_infoelif [[ -f xtrabackup_binlog_info ]]; then# 我们直接从主实例进行克隆。解析 binlog 位置。[[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1rm -f xtrabackup_binlog_info xtrabackup_slave_infoecho "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.infi# 检查我们是否需要通过启动复制来完成克隆。if [[ -f change_master_to.sql.in ]]; thenecho "Waiting for mysqld to be ready (accepting connections)"until mysql -h 127.0.0.1 -uroot -p${MYSQL_ROOT_PASSWORD} -e "SELECT 1"; do sleep 1; doneecho "Initializing replication from clone position"mysql -h 127.0.0.1 -uroot -p${MYSQL_ROOT_PASSWORD} \-e "$(<change_master_to.sql.in), \MASTER_HOST='mysql-pass-0.mysql-pass-svc', \#访问的mysql master的Pod,此时master容器已经启动名称以及确定。MASTER_USER='root', \MASTER_PASSWORD='${MYSQL_ROOT_PASSWORD}', \MASTER_CONNECT_RETRY=10; \START SLAVE;" || exit 1# 如果容器重新启动,最多尝试一次。mv change_master_to.sql.in change_master_to.sql.orig#修改change_master_to.sql.in防止重启后再次找到文件重克隆fi# 当对等点请求时,启动服务器发送备份。exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \"xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root --password=${MYSQL_ROOT_PASSWORD}"  volumeMounts:- name: datamountPath: /var/lib/mysqlsubPath: mysql- name: confmountPath: /etc/mysql/conf.dresources:requests:cpu: 100mmemory: 100Mivolumes:- name: timehostPath: path: /etc/localtimetype: File- name: confemptyDir: {}- name: confg-mapconfigMap:name: mysql-cnf-mapvolumeClaimTemplates:- metadata:name: dataspec:storageClassName: "nfs-stgc-delete"accessModes: ["ReadWriteOnce"]resources:requests:storage: 1Gi

容器挂载路径图:
在这里插入图片描述

  • StatefulSet.spec.serviceName配置headless服务名称。
  • 在容器init-mysql、mysql、xtrabackup添加环境变量配置mysql密码。clone-mysql和xtrabackup需要密码的进行修改
  • 在clone-mysql、xtrabackup访问Master的位置修改访问的主机名。
  • 挂载服务时间。

部署测试

查看Pod状态

[root@master my]# kubectl get pod -n my 
NAME           READY   STATUS    RESTARTS   AGE
mysql-pass-0   2/2     Running   0          3h6m
mysql-pass-1   2/2     Running   0          3h5m
mysql-pass-2   2/2     Running   0          3h5m

查看Service信息

kubectl describe svc mysql-pass-svc/mysql-read-pass -n my

查看时间同步:

kubectl exec mysql-pass-0 -c mysql -it -n my -- /bin/bash进入容器bash-4.2# date
Sun Mar 31 15:29:12 CST 2024
bash-4.2# exit
[root@master my]# date
2024年 03月 31日 星期日 15:29:15 CSTmysql> select now();+---------------------+| now()               |+---------------------+| 2024-03-31 15:31:10 |+---------------------+1 row in set (0.00 sec)

测试mysql集群

[root@master my]#  kubectl run mysql-client --image=mysql:5.7 -i --rm --restart=Never --\
>   mysql -h mysql-pass-0.mysql-pass-svc.my -uroot -p12345678 <<EOF
> CREATE DATABASE test;
> CREATE TABLE test.messages (message VARCHAR(250));
> INSERT INTO test.messages VALUES ('hello');
> EOF
If you don't see a command prompt, try pressing enter.
pod "mysql-client" deleted
[root@master my]# kubectl run mysql-client --image=mysql:5.7 -i -t --rm --restart=Never --\
>   mysql -h mysql-read-pass.my -uroot -p12345678 -e "SELECT * FROM test.messages"
mysql: [Warning] Using a password on the command line interface can be insecure.+---------+| message |+---------+| hello   |+---------+pod "mysql-client" deleted

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/789661.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分享几个好用的电商API接口(可测试)

以下是一些好用的电商API接口&#xff0c;这些接口都可以用于获取电商平台的商品、订单、物流等相关信息&#xff0c;并提供了测试功能以确保接口的稳定性和可用性&#xff1a; 请求示例&#xff0c;API接口接入Anzexi58 淘宝开放平台API&#xff1a;淘宝开放平台提供了丰富的…

Keil 警告解决 : warning: #870-D: invalid multibyte character sequence

说明&#xff1a;在Keil项目编译时出现了几个 warning: #870-D: 的警告&#xff0c;接下来分析解决这个警告。 注意&#xff1a;在尝试解决问题前一定要将整个工程打包成压缩文件备份&#xff0c;以防更改失败变文件成乱码。 1.警告内容 warning: #870-D: warning: #870-…

Android Monkey自动化测试

monkey一般用于压力测试&#xff0c;用户模拟用户事件 monkey 基本用法 adb shell monkey [参数] [随机事件数]monkey常用命令 -v&#xff1a;用于指定反馈信息级别&#xff0c;总共分三个等级-v -v -vadb shell mokey -v -v -v 100-s&#xff1a;用于指定伪随机数生成器的种…

CentOS7安装flink1.17完全分布式

前提条件 准备三台CenOS7机器&#xff0c;主机名称&#xff0c;例如&#xff1a;node2&#xff0c;node3&#xff0c;node4 三台机器安装好jdk8&#xff0c;通常情况下&#xff0c;flink需要结合hadoop处理大数据问题&#xff0c;建议先安装hadoop&#xff0c;可参考 hadoop安…

impnt只读,燕用,必填,提示词(占位符)属性分别是什么

readonly 属性规定输入字段为只读&#xff08;不能修改&#xff09; <input type"text" placeholder"点我啊" readonly/> disabled 属性规定输入字段是禁用的 <input type"text" placeholder"点我啊" disabled/> re…

XXLJob中GLUE模式实现在线编写java/shell/python/php/nodejs/powerShell---SpringCloud工作笔记202

1.起因: 之前就一直想实现类似的功能,今天总于找到有可以参考的东西了,这个思路可以帮助实现这种功能. 2.获得灵感 就是:我想实现通过在线编写代码,来扩展我们平台的能力,这样随着业务的扩展,不用我们每次都修改了代码,再去部署,这样就比较麻烦,今天偶尔发现,对于xxljob来说.有…

OSCP靶场--ProStore

OSCP靶场–ProStore 考点(node.js代码注入gdb-list源文件c语言命令执行) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap 192.168.200.250 -sV -sC -Pn --min-rate 2500 -p- Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-01 09:18 EDT Nmap scan report…

Stream2Graph论文翻译

Stream2Graph: Dynamic Knowledge Graph for Online Learning Applied in Large-scale Network Abstract 知识图谱(KG)是用于存储某个领域(医疗保健、金融、电子商务、ITOps等)中的知识的有价值的信息来源。大多数工业KG本质上是动态的&#xff0c;因为它们定期更新流数据(客…

Scala第十八章节(Iterable集合、Seq集合、Set集合、Map集合以及统计字符个数案例)

Scala第十八章节 章节目标 掌握Iterable集合相关内容.掌握Seq集合相关内容.掌握Set集合相关内容.掌握Map集合相关内容.掌握统计字符个数案例. 1. Iterable 1.1 概述 Iterable代表一个可以迭代的集合, 它继承了Traversable特质, 同时也是其他集合的父特质. 最重要的是, 它定…

windows无法使用hadoop报错:系统找不到路径

在windows下安装hadoop-3.1.4,进行环境变量配置后&#xff0c;打开window命令行窗口测试hadoop命令&#xff0c;报错&#xff0c;如图所示&#xff1a; 方案&#xff1a;由于JAVA_HOME路径有空格导致&#xff0c;可修改hadoop下\etc\hadoop\hadoop_env.cmd文档中set JAVA_HOME以…

Kubernetes(k8s):如何进行 Kubernetes 集群健康检查?

Kubernetes&#xff08;k8s&#xff09;&#xff1a;如何进行 Kubernetes 集群健康检查&#xff1f; 一、节点健康检查1、使用 kubectl 查看节点状态2、查看节点详细信息3、检查节点资源使用情况 2、Pod 健康检查2.1、 使用 kubectl 查看 Pod 状态2.2、 查看特定 Pod 的详细信息…

Oracle数据库常见 问题 或 报错 集合

【报错】字段长度不足 一般字段长度不够时报错&#xff1a; Cause: java.sql.SQLException: ORA-12899: value too large for colum “列名” 【报错】修改字段长度&#xff0c;提示资源正忙 以pl/sql为例&#xff1a; ctrl选中表&#xff0c;在列选项卡下修改字段长度&#x…

基于 java + Springboot + vue +mysql 大学生实习管理系统(含源码)

目录 &#x1f4da; 前言 &#x1f4d1;摘要 &#x1f4d1;实习管理系统的特点 &#x1f4d1;使用架构 &#x1f4da; 总体设计 &#x1f4da; 数据库设计 &#x1f4ac; 系统公告实体属性 &#x1f4ac; 单位成绩实体属性 &#x1f4ac; 学生实体属性 &#x1f4da; 系…

[已解决]Vue3+Element-plus使用el-dialog对话框无法显示

文章目录 问题发现原因分析解决方法 问题发现 点击按钮&#xff0c;没有想要的弹框 代码如下 修改 el-dialog到body中&#xff0c;还是不能显示 原因分析 使用devtool中vue工具进行查看组件结构 原因在于&#xff0c;在一个局部组件(Detail->ElTabPane->…)中使用…

Qt实现Kermit协议(三)

3 实现 3.2 KermitSendFile 该模块实现了Kermit发送文件功能。 序列图如下&#xff1a; 3.2.1 KermitSendFile定义 class QSerialPort; class KermitSendFile : public QObject, public Kermit {Q_OBJECT public:explicit KermitSendFile(QSerialPort *serial, QObject *…

计算机网络针对交换机的配置

实验 目的 交换机的基本配置&#xff0c;交换机VLAN配置 实验条件 Windows&#xff0c;Cisco packet tracer 实验 内容 交换机的基本配置&#xff0c;交换机VLAN配置 实验 过程 一、交换机的基本配置 进入特权模式 Switch>enable 进入配置模式 Switch#configure ter…

2024年阿里云新用户便宜购买云服务器攻略:5大细节助你降低购买成本

随着互联网的蓬勃发展&#xff0c;无论是个人还是企业&#xff0c;拥有一个稳定且高效的网站或APP已成为提升竞争力的关键。为了将这些项目部署并运行起来&#xff0c;购买一台实用又便宜的云服务器是必不可少的。阿里云作为国内首屈一指的云服务提供商&#xff0c;自然成为了众…

openGauss学习笔记-254 openGauss性能调优-使用Plan Hint进行调优-子链接块名的hint

文章目录 openGauss学习笔记-254 openGauss性能调优-使用Plan Hint进行调优-子链接块名的hint254.1 功能描述254.2 语法格式254.3 参数说明254.4 示例 openGauss学习笔记-254 openGauss性能调优-使用Plan Hint进行调优-子链接块名的hint 254.1 功能描述 指明子链接块的名称。…

CRMEB 标准版 v5.3公测版发布,快来体验

演示站 后台&#xff1a;http://v5.crmeb.net/admin 账号&#xff1a;demo 密码&#xff1a;crmeb.com H5端&#xff1a;http://v5.crmeb.net 新增功能 后台支持所有功能设置搜索 事业部&#xff1a;想在事业部添加代理商&#xff0c;可以在后台选择添加员工&#xff0c;设…

静态图片如何生成gif动画?一个网站在线实现

在当下这个媒体时代&#xff0c;各种各样的图片充斥着我们的生活。尤其是gif动图能够快速有效的传递信息&#xff0c;让用户更加直观的了解某个时间或是场景。非常的生动便捷&#xff0c;那么怎么弄制作gif动画图片呢&#xff1f;其实&#xff0c;只是gif动画的方法非常的简单&…