文章转载自:https://www.cnblogs.com/ludongguoa/p/15319861.html

一般情况下 Kubernetes 可以通过 ReplicaSet 以一个 Pod 模板创建多个 pod 副本,但是它们都是无状态的,任何时候它们都可以被一个全新的 pod 替换。然而有状态的 pod 需要另外的方案确保当一个有状态的 pod 挂掉后,这个 pod 实例需要在别的节点上重建,但是新的实例必须与被替换的实例拥有相同的名称、网络标识和状态。这就是 Statefulset 管理 pod 的手段。

对于容器集群,有状态服务的挑战在于,通常集群中的任何节点都并非100%可靠的,服务所需的资源也会动态地更新改变。当节点由于故障或服务由于需要更多的资源而无法继续运行在原有节点上时,集群管理系统会为该服务重新分配一个新的运行位置,从而确保从整体上看,集群对外的服务不会中断。若采用本地存储,当服务漂移后数据并不会随着服务转移到新的节点,重启服务就会出现数据丢失的困境。

本文目的是通过一个 mysql 的主从集群搭建,深入了解 kubernetes 的 statfulset 管理。为了降低实验的外部依赖,存储层面上,我采用的是本地存储,当然生产上不建议这样做,生产环境的存储推荐官方介绍到的的 gce、nfs、ceph等存储方案,因为这些方案支持动态供给的特性,允许开发人员通过 pvc 的定义,快速实现数据有效存储,所以你绝不应该把一个宿主机上的目录当作 PV 使用, 只是本文用于实验需要,采用 Local Persistent Volume 的手段,目的只是为了验证 Statefulset 的状态管理功能。

实验环境

  • kubernetes Master
  • kubernetes Node(测试演示,所有的副本都会在其上运行)
  • kubernetes DNS 服务已开启

实验目的

  • 搭建一个主从复制(Master-Slave)的 MySQL 集群
  • 从节点可以水平扩展
  • 所有的写操作只能在主节点上执行
  • 读操作可以在主从节点上执行
  • 从节点能同步主节点的数据

本地存储原理

为了快速搭建测试环境,我们这里使用了本地存储,也就是说,用户希望 Kubernetes 能够直接使用宿主机上的本地磁盘目录,而不依赖于远程存储服务,来提供持久化的容器 Volume。不过这里有个难点:我们把存储固定在一个节点上,但是pod在调度的时候,是飘来飘去的,怎么能让pod通过pvc也能固定在pv上?

给这个 Pod 加上一个 nodeAffinity 行不行?

当然行,但是这变相破坏了开发人员对资源对象的定义规范了,开发人员应该不需要时刻考虑调度的细节。调度的改动应该交给运维就行。所以我们为了实现本地存储,我们采用了 延迟绑定 的方法。方法很简单,我们都知道 storageclass 一般由运维人员设计,我们只需要在storageclass 指定 no-provisioner。这是因为 Local Persistent Volume 目前尚不支持 Dynamic Provisioning,所以它没办法在用户创建 PVC 的时候,就自动创建出对应的 PV。与此同时,这个 StorageClass 还定义了一个 volumeBindingMode=WaitForFirstConsumer 的属性。它是 Local Persistent Volume 里一个非常重要的特性,即:延迟绑定

  1. kind: StorageClass
  2. apiVersion: storage.k8s.io/v1
  3. metadata:
  4. name: local-storage
  5. provisioner: kubernetes.io/no-provisioner
  6. volumeBindingMode: WaitForFirstConsumer

实验步骤

一、先在node (实验用的node节点IP是172.31.170.51 )节点上,预先分配几个pv (不建议在生产上这样操作)

01-persistentVolume-1.yaml

  1. apiVersion: v1
  2. kind: PersistentVolume
  3. metadata:
  4. name: example-mysql-pv
  5. spec:
  6. capacity:
  7. storage: 15Gi
  8. volumeMode: Filesystem
  9. accessModes:
  10. - ReadWriteOnce
  11. persistentVolumeReclaimPolicy: Delete
  12. storageClassName: local-storage
  13. local:
  14. path: /data/svr/projects/mysql
  15. nodeAffinity:
  16. required:
  17. nodeSelectorTerms:
  18. - matchExpressions:
  19. - key: kubernetes.io/hostname
  20. operator: In
  21. values:
  22. - 172.31.170.51

01-persistentVolume-2.yaml

  1. apiVersion: v1
  2. kind: PersistentVolume
  3. metadata:
  4. name: example-mysql-pv-2
  5. spec:
  6. capacity:
  7. storage: 15Gi
  8. volumeMode: Filesystem
  9. accessModes:
  10. - ReadWriteOnce
  11. persistentVolumeReclaimPolicy: Delete
  12. storageClassName: local-storage
  13. local:
  14. path: /data/svr/projects/mysql2
  15. nodeAffinity:
  16. required:
  17. nodeSelectorTerms:
  18. - matchExpressions:
  19. - key: kubernetes.io/hostname
  20. operator: In
  21. values:
  22. - 172.31.170.51

01-persistentVolume-3.yaml

  1. apiVersion: v1
  2. kind: PersistentVolume
  3. metadata:
  4. name: example-mysql-pv-3
  5. spec:
  6. capacity:
  7. storage: 15Gi
  8. volumeMode: Filesystem
  9. accessModes:
  10. - ReadWriteOnce
  11. persistentVolumeReclaimPolicy: Delete
  12. storageClassName: local-storage
  13. local:
  14. path: /data/svr/projects/mysql3
  15. nodeAffinity:
  16. required:
  17. nodeSelectorTerms:
  18. - matchExpressions:
  19. - key: kubernetes.io/hostname
  20. operator: In
  21. values:
  22. - 172.31.170.51

记住,这是在生产上不推荐的做法,我只是实验用途才这样手动预先创建,正规的做法应该通过storageclass采用 Dynamic Provisioning, 而不是 Static Provisioning 机制生产PV。

  1. kubectl apply -f 01-persistentVolume-{1..3}.yaml
  2. persistentvolume/example-mysql-pv1 created
  3. persistentvolume/example-mysql-pv2 created
  4. persistentvolume/example-mysql-pv3 created

二、创建 StorageClass

02-storageclass.yaml

  1. kind: StorageClass
  2. apiVersion: storage.k8s.io/v1
  3. metadata:
  4. name: local-storage
  5. provisioner: kubernetes.io/no-provisioner
  6. volumeBindingMode: WaitForFirstConsumer

执行创建

  1. kubectl apply -f 02-storageclass.yaml
  2. storageclass.storage.k8s.io/local-storage created

三、创建Namespace

03-mysql-namespace.yaml

  1. apiVersion: v1
  2. kind: Namespace
  3. metadata:
  4. name: mysql
  5. labels:
  6. app: mysql

执行创建

  1. kubectl apply -f 03-mysql-namespace.yaml
  2. namespace/mysql created

四、使用 ConfigMap 为 Master/Slave 节点分配不同的配置文件

04-mysql-configmap.yaml

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. name: mysql
  5. namespace: mysql
  6. labels:
  7. app: mysql
  8. data:
  9. master.cnf: |
  10. # Master配置
  11. [mysqld]
  12. log-bin=mysqllog
  13. skip-name-resolve
  14. slave.cnf: |
  15. # Slave配置
  16. [mysqld]
  17. super-read-only
  18. skip-name-resolve
  19. log-bin=mysql-bin
  20. replicate-ignore-db=mysql

创建执行

  1. kubectl apply -f 04-mysql-configmap.yaml
  2. configmap/mysql created

五、创建mysql密码Secret

05-mysql-secret.yaml

  1. apiVersion: v1
  2. kind: Secret
  3. metadata:
  4. name: mysql-secret
  5. namespace: mysql
  6. labels:
  7. app: mysql
  8. type: Opaque
  9. data:
  10. password: MTIzNDU2 # echo -n "123456" | base64

创建执行

  1. kubectl apply -f 05-mysql-secret.yaml
  2. secret/mysql-secret created

六、使用 Service 为 MySQL 提供读写分离

06-mysql-services.yaml

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: mysql
  5. namespace: mysql
  6. labels:
  7. app: mysql
  8. spec:
  9. ports:
  10. - name: mysql
  11. port: 3306
  12. clusterIP: None
  13. selector:
  14. app: mysql
  15. ---
  16. apiVersion: v1
  17. kind: Service
  18. metadata:
  19. name: mysql-read
  20. namespace: mysql
  21. labels:
  22. app: mysql
  23. spec:
  24. ports:
  25. - name: mysql
  26. port: 3306
  27. selector:
  28. app: mysql

用户所有写请求,必须以 DNS 记录的方式直接访问到 Master 节点,也就是 mysql-0.mysql 这条 DNS 记录。

用户所有读请求,必须访问自动分配的 DNS 记录可以被转发到任意一个 Master 或 Slave 节点上,也就是 mysql-read 这条 DNS 记录

  1. kubectl apply -f 06-mysql-services.yaml
  2. $ kubectl get svc -n mysql
  3. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  4. mysql ClusterIP None <none> 3306/TCP 20s
  5. mysql-read ClusterIP 10.0.0.63 <none> 3306/TCP 20s

七、使用 StatefulSet 搭建 MySQL 主从集群

mysql-statefulset.yaml

  1. apiVersion: apps/v1
  2. kind: StatefulSet
  3. metadata:
  4. name: mysql
  5. namespace: mysql
  6. labels:
  7. app: mysql
  8. spec:
  9. selector:
  10. matchLabels:
  11. app: mysql
  12. serviceName: mysql
  13. replicas: 2
  14. template:
  15. metadata:
  16. labels:
  17. app: mysql
  18. spec:
  19. initContainers:
  20. - name: init-mysql
  21. image: mysql:5.7
  22. env:
  23. - name: MYSQL_ROOT_PASSWORD
  24. valueFrom:
  25. secretKeyRef:
  26. name: mysql-secret
  27. key: password
  28. command:
  29. - bash
  30. - "-c"
  31. - |
  32. set -ex
  33. # 从 Pod 的序号,生成 server-id
  34. [[ $(hostname) =~ -([-9]+)$ ]] || exit 1
  35. ordinal=${BASH_REMATCH[1]}
  36. echo [mysqld] > /mnt/conf.d/server-id.cnf
  37. # 由于 server-id 不能为 ,因此给 ID 加 100 来避开它
  38. echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
  39. # 如果 Pod 的序号为 ,说明它是 Master 节点,从 ConfigMap 里把 Master 的配置文件拷贝到 /mnt/conf.d 目录下
  40. # 否则,拷贝 ConfigMap 里的 Slave 的配置文件
  41. if [[ ${ordinal} -eq ]]; then
  42. cp /mnt/config-map/master.cnf /mnt/conf.d
  43. else
  44. cp /mnt/config-map/slave.cnf /mnt/conf.d
  45. fi
  46. volumeMounts:
  47. - name: conf
  48. mountPath: /mnt/conf.d
  49. - name: config-map
  50. mountPath: /mnt/config-map
  51. - name: clone-mysql
  52. image: gcr.io/google-samples/xtrabackup:1.0
  53. env:
  54. - name: MYSQL_ROOT_PASSWORD
  55. valueFrom:
  56. secretKeyRef:
  57. name: mysql-secret
  58. key: password
  59. command:
  60. - bash
  61. - "-c"
  62. - |
  63. set -ex
  64. # 拷贝操作只需要在第一次启动时进行,所以数据已经存在则跳过
  65. [[ -d /var/lib/mysql/mysql ]] && exit
  66. # Master 节点(序号为 )不需要这个操作
  67. [[ $(hostname) =~ -([-9]+)$ ]] || exit 1
  68. ordinal=${BASH_REMATCH[1]}
  69. [[ $ordinal == ]] && exit
  70. # 使用 ncat 指令,远程地从前一个节点拷贝数据到本地
  71. ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
  72. # 执行 --prepare,这样拷贝来的数据就可以用作恢复了
  73. xtrabackup --prepare --target-dir=/var/lib/mysql
  74. volumeMounts:
  75. - name: data
  76. mountPath: /var/lib/mysql
  77. subPath: mysql
  78. - name: conf
  79. mountPath: /etc/mysql/conf.d
  80. containers:
  81. - name: mysql
  82. image: mysql:5.7
  83. env:
  84. # - name: MYSQL_ALLOW_EMPTY_PASSWORD
  85. # value: "1"
  86. - name: MYSQL_ROOT_PASSWORD
  87. valueFrom:
  88. secretKeyRef:
  89. name: mysql-secret
  90. key: password
  91. ports:
  92. - name: mysql
  93. containerPort: 3306
  94. volumeMounts:
  95. - name: data
  96. mountPath: /var/lib/mysql
  97. subPath: mysql
  98. - name: conf
  99. mountPath: /etc/mysql/conf.d
  100. resources:
  101. requests:
  102. cpu: 500m
  103. memory: 1Gi
  104. livenessProbe:
  105. exec:
  106. command: ["mysqladmin", "ping", "-uroot", "-p${MYSQL_ROOT_PASSWORD}"]
  107. initialDelaySeconds: 30
  108. periodSeconds: 10
  109. timeoutSeconds: 5
  110. readinessProbe:
  111. exec:
  112. command: ["mysqladmin", "ping", "-uroot", "-p${MYSQL_ROOT_PASSWORD}"]
  113. initialDelaySeconds: 5
  114. periodSeconds: 2
  115. timeoutSeconds: 1
  116. - name: xtrabackup
  117. image: gcr.io/google-samples/xtrabackup:1.0
  118. ports:
  119. - name: xtrabackup
  120. containerPort: 3307
  121. env:
  122. - name: MYSQL_ROOT_PASSWORD
  123. valueFrom:
  124. secretKeyRef:
  125. name: mysql-secret
  126. key: password
  127. command:
  128. - bash
  129. - "-c"
  130. - |
  131. set -ex
  132. cd /var/lib/mysql
  133. # 从备份信息文件里读取 MASTER_LOG_FILE 和 MASTER_LOG_POS 这 2 个字段的值,用来拼装集群初始化 SQL
  134. if [[ -f xtrabackup_slave_info ]]; then
  135. # 如果 xtrabackup_slave_info 文件存在,说明这个备份数据来自于另一个 Slave 节点
  136. # 这种情况下,XtraBackup 工具在备份的时候,就已经在这个文件里自动生成了 "CHANGE MASTER TO" SQL 语句
  137. # 所以,只需要把这个文件重命名为 change_master_to.sql.in,后面直接使用即可
  138. mv xtrabackup_slave_info change_master_to.sql.in
  139. # 所以,也就用不着 xtrabackup_binlog_info 了
  140. rm -f xtrabackup_binlog_info
  141. elif [[ -f xtrabackup_binlog_info ]]; then
  142. # 如果只是存在 xtrabackup_binlog_info 文件,说明备份来自于 Master 节点,就需要解析这个备份信息文件,读取所需的两个字段的值
  143. [[ $(cat xtrabackup_binlog_info) =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
  144. rm xtrabackup_binlog_info
  145. # 把两个字段的值拼装成 SQL,写入 change_master_to.sql.in 文件
  146. echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
  147. MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
  148. fi
  149. # 如果存在 change_master_to.sql.in,就意味着需要做集群初始化工作
  150. if [[ -f change_master_to.sql.in ]]; then
  151. # 但一定要先等 MySQL 容器启动之后才能进行下一步连接 MySQL 的操作
  152. echo "Waiting for mysqld to be ready(accepting connections)"
  153. until mysql -h 127.0.0.1 -uroot -p${MYSQL_ROOT_PASSWORD} -e "SELECT 1"; do sleep 1; done
  154. echo "Initializing replication from clone position"
  155. # 将文件 change_master_to.sql.in 改个名字
  156. # 防止这个 Container 重启的时候,因为又找到了 change_master_to.sql.in,从而重复执行一遍初始化流程
  157. mv change_master_to.sql.in change_master_to.sql.orig
  158. # 使用 change_master_to.sql.orig 的内容,也就是前面拼装的 SQL,组成一个完整的初始化和启动 Slave 的 SQL 语句
  159. mysql -h 127.0.0.1 -uroot -p${MYSQL_ROOT_PASSWORD} << EOF
  160. $(< change_master_to.sql.orig),
  161. MASTER_HOST='mysql-0.mysql.mysql',
  162. MASTER_USER='root',
  163. MASTER_PASSWORD='${MYSQL_ROOT_PASSWORD}',
  164. MASTER_CONNECT_RETRY=10;
  165. START SLAVE;
  166. EOF
  167. fi
  168. # 使用 ncat 监听 3307 端口。
  169. # 它的作用是,在收到传输请求的时候,直接执行 xtrabackup --backup 命令,备份 MySQL 的数据并发送给请求者
  170. exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
  171. "xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root --password=${MYSQL_ROOT_PASSWORD}"
  172. volumeMounts:
  173. - name: data
  174. mountPath: /var/lib/mysql
  175. subPath: mysql
  176. - name: conf
  177. mountPath: /etc/mysql/conf.d
  178. volumes:
  179. - name: conf
  180. emptyDir: {}
  181. - name: config-map
  182. configMap:
  183. name: mysql
  184. volumeClaimTemplates:
  185. - metadata:
  186. name: data
  187. spec:
  188. accessModes:
  189. - "ReadWriteOnce"
  190. storageClassName: local-storage
  191. resources:
  192. requests:
  193. storage: 3Gi

整体的statefulset有两个replicas,一个Master, 一个Slave,然后使用 init-mysql 这个 initContainers 进行配置文件的初始化。接着使用 clone-mysql 这个 initContainers 进行数据的传输;同时使用 xtrabackup 这个 sidecar 容器进行SQL初始化和数据传输功能

创建 StatefulSet

  1. kubectl apply -f 07-mysql-statefulset.yaml
  2. $ kubectl get po -n mysql
  3. NAME READY STATUS RESTARTS AGE
  4. mysql-0 2/2 Running 70s
  5. mysql-1 /2 Pending 5s

可以看到,StatefulSet 启动成功后,会有两个Pod运行。

接下来,我们可以尝试向这个MySQL集群发起请求,执行一些SQL操作来验证它是否正常

服务验证

验证主从状态

  1. kubectl -n mysql exec mysql-1 -c mysql -- bash -c "mysql -uroot -p123456 -e 'show slave status \G'"
  2. mysql: [Warning] Using a password on the command line interface can be insecure.
  3. *************************** 1. row ***************************
  4. Slave_IO_State: Waiting for master to send event
  5. Master_Host: mysql-0.mysql.mysql
  6. Master_User: root
  7. Master_Port: 3306
  8. Connect_Retry: 10
  9. Master_Log_File: mysqllog.000003
  10. Read_Master_Log_Pos: 154
  11. Relay_Log_File: mysql-1-relay-bin.000002
  12. Relay_Log_Pos: 319
  13. Relay_Master_Log_File: mysqllog.000003
  14. Slave_IO_Running: Yes
  15. Slave_SQL_Running: Yes
  16. Replicate_Do_DB:
  17. Replicate_Ignore_DB: mysql
  18. Replicate_Do_Table:
  19. Replicate_Ignore_Table:
  20. Replicate_Wild_Do_Table:
  21. Replicate_Wild_Ignore_Table:
  22. Last_Errno: 0
  23. Last_Error:
  24. Skip_Counter: 0
  25. Exec_Master_Log_Pos: 154
  26. Relay_Log_Space: 528
  27. Until_Condition: None
  28. Until_Log_File:
  29. Until_Log_Pos: 0
  30. Master_SSL_Allowed: No
  31. Master_SSL_CA_File:
  32. Master_SSL_CA_Path:
  33. Master_SSL_Cert:
  34. Master_SSL_Cipher:
  35. Master_SSL_Key:
  36. Seconds_Behind_Master: 0
  37. Master_SSL_Verify_Server_Cert: No
  38. Last_IO_Errno: 0
  39. Last_IO_Error:
  40. Last_SQL_Errno: 0
  41. Last_SQL_Error:
  42. Replicate_Ignore_Server_Ids:
  43. Master_Server_Id: 100
  44. Master_UUID: 1bad4d64-6290-11ea-8376-0242ac113802
  45. Master_Info_File: /var/lib/mysql/master.info
  46. SQL_Delay: 0
  47. SQL_Remaining_Delay: NULL
  48. Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
  49. Master_Retry_Count: 86400
  50. Master_Bind:
  51. Last_IO_Error_Timestamp:
  52. Last_SQL_Error_Timestamp:
  53. Master_SSL_Crl:
  54. Master_SSL_Crlpath:
  55. Retrieved_Gtid_Set:
  56. Executed_Gtid_Set:
  57. Auto_Position: 0
  58. Replicate_Rewrite_DB:
  59. Channel_Name:
  60. Master_TLS_Version:

接下来,我们通过Master容器创建数据库和表、插入数据库

  1. kubectl -n mysql exec mysql- -c mysql -- bash -c "mysql -uroot -p123456 -e 'create database test’"
  2. kubectl -n mysql exec mysql- -c mysql -- bash -c "mysql -uroot -p123456 -e 'use test;create table counter(c int);’"
  3. kubectl -n mysql exec mysql- -c mysql -- bash -c "mysql -uroot -p123456 -e 'use test;insert into counter values(123)’"

然后,我们观察Slave节点是否都同步到数据了

  1. kubectl -n mysql exec mysql-1 -c mysql -- bash -c "mysql -uroot -p123456 -e 'use test;select * from counter’"
  2. c
  3. 123

当看到输出结果,主从同步正常了

扩展从节点

在有了 StatefulSet 以后,你就可以像 Deployment 那样,非常方便地扩展这个 MySQL 集群,比如

  1. kubectl -n mysql scale statefulset mysql -—replicas=3
  2. $ kubectl get po -n mysql
  3. NAME READY STATUS RESTARTS AGE
  4. mysql- 2/2 Running 22m
  5. mysql-1 2/2 Running 22m
  6. mysql-2 2/2 Running 20s

这时候,一个新的mysql-2就创建出来了,我们继续验证新扩容的节点是否都同步到主节点的数据

  1. kubectl -n mysql exec mysql-2 -c mysql -- bash -c "mysql -uroot -p123456 -e 'use test;select * from counter’"
  2. c
  3. 123

当看到输出结果,主从同步正常了。也就是说从 StatefulSet 为我们新创建的 mysql-2 上,同样可以读取到之前插入的记录。也就是说,我们的数据备份和恢复,都是有效的。

Kubernetes 中部署 MySQL 集群的更多相关文章

  1. 在 Kubernetes 中部署 Redis 集群

    在 Kubernetes 中部署 Redis 集群 在Kubernetes中部署Redis集群面临挑战,因为每个 Redis 实例都依赖于一个配置文件,该文件可以跟踪其他集群实例及其角色.为此,我们需 ...

  2. 容器化 | 在 KubeSphere 中部署 MySQL 集群

    程润科 数据库研发工程师,目前从事 RadonDB MySQL Kubernetes 研发,热衷于研究数据库内核.K8s 相关技术. 张莉梅 高级文档工程师,目前负责数据库产品文档开发.维护和管理工作 ...

  3. Docker部署Mysql集群

    单节点数据库的弊病 大型互联网程序用户群体庞大,所以架构必须要特殊设计 单节点的数据库无法满足性能上的要求 单节点的数据库没有冗余设计,无法满足高可用 单节点MySQL的性能瓶领颈 2016年春节微信 ...

  4. Redis笔记 -- 在 Centos7.4单机中部署Redis集群(二)

    0x00--背景和目的 在单台PC服务器上部署Redis集群,通过不同的TCP端口启动多实例,模拟多台独立PC组成集群. 0x01--环境描述: Centos版本:CentOS Linux relea ...

  5. Kubernetes+Flannel 环境中部署HBase集群

    2015-12-14注:加入新节点不更改运行节点参数需求已满足,将在后续文章中陆续总结. 注:目前方案不满足加入新节点(master节点或regionserver节点)而不更改已运行节点的参数的需求, ...

  6. kubernetes二进制部署k8s-master集群controller-manager服务unhealthy问题

    一.问题现象 我们使用二进制部署k8s的高可用集群时,在部署多master时,kube-controller-manager服务提示Unhealthy [root@ceph-01 system]# k ...

  7. (二)Kubernetes kubeadm部署k8s集群

    kubeadm介绍 kubeadm是Kubernetes项目自带的及集群构建工具,负责执行构建一个最小化的可用集群以及将其启动等的必要基本步骤,kubeadm是Kubernetes集群全生命周期的管理 ...

  8. keepalived-1.3.5+MHA部署mysql集群

    MHA: MHA工作原理总结为以下几条: 从宕机崩溃的master保存二进制日志事件(binlog events): 识别含有最新更新的slave: 应用差异的中继日志(relay log)到其他sl ...

  9. Kubernetes(k8s)部署redis-cluster集群

    Redis Cluster 提供了一种运行 Redis 安装的方法,其中数据 在多个 Redis 节点之间自动分片. Redis Cluster 还在分区期间提供了一定程度的可用性,这实际上是在某些节 ...

随机推荐

  1. Drone-比Jenkins更轻量化的持续集成部署工具

    Drone 简介 Drone 是一个基于Docker容器技术的可扩展的持续集成引擎,由GO语言编写,可用于自动化测试与构建,甚至发布.每个构建都在一个临时的Docker容器中执行,使开发人员能够完全控 ...

  2. springboot中实现权限认证的两个框架

    web开发安全框架 提供认证和授权功能! 一.SpringSecurity 1.导入依赖 <dependency> <groupId>org.springframework.b ...

  3. Identity Server 4资源拥有者密码认证控制访问API

    基于上一篇文章中的代码进行继续延伸,只需要小小的改动即可,不明白的地方可以先看看本人上一篇文章及源码: Identity Server 4客户端认证控制访问API 一.QuickStartIdenti ...

  4. WCF全局捕获日志

    /// <summary> /// WCF服务端异常处理器 /// </summary> public class WCF_ExceptionHandler : IErrorH ...

  5. ooday04 Java_面向对象_重写_static

    方法的重写(override/overriding):重新写.覆盖 发生在父子类中,方法名相同,参数列表相同 重写方法被调用时,看对象的类型------------这是规定,记住就OK 当派生类觉得超 ...

  6. Mysql 系列 | 日志模块

    了解了 SQL 执行的流程,知道每一条语句都经过连接器.查询存储.分析器.优化器.执行器最后到存储引擎的过程.查询语句是如此,更新语句也不例外. 不同的是,更新语句会修改表数据,这里就涉及到两个重要的 ...

  7. Collection集合和Collection的常用功能

    boolean add(E e); 向集合里添加元素 boolean remove(E e); 删除集合中的某个元素 void clear(); 清空集合的所有元素 boolean contains( ...

  8. 【Azure Developer】在Azure VM (Windows) 中搭建 kafka服务,并且通过本地以及远程验证 发送+消费 消息

    问题描述 查看了 "How to Install and Run Apache Kafka on Windows? " 一文后,成功安装了Kafka服务,但是如何使用呢?如何在其他 ...

  9. python 可变、不可变类型、深拷贝、浅拷贝理解

    简介 python中数据分为可变类型,不可变类型.不同的数据类型影响着不同情况下的深浅拷贝. 下面则将简要介绍一下 可变类型 当某个数据的值发生改变时,它对应的内存地址不发生改变,常见的有列表.字典. ...

  10. Windows高效开发环境配置(一)

    更多精彩内容,欢迎关注公众号:逻魔代码 前言 用了多年的 MacOS 做开发,一系列诸如 Alfred.Item2.Oh-my-zsh 之类的工具,大大地提升了工作的效率和使用舒适度.新工作不给配 M ...