zoukankan      html  css  js  c++  java
  • Statefulset详细解析

    StatefulSet实现Pod的拓扑状态

         Stateful状态集在创建和扩展的时候有特殊的限制,如果一个有状态集期望的Pod数量是N,那么有StatefulSet会从0开始依次创建这些Pod在第一个Pod正常运行之前是不会创建第二个Pod.在删除Pod的时候,则是从第N个Pod开始反向依次删除

         StatefulSet的核心功能就是通过某种方式记录这些状态,然后在Pod被重新创建时能够为新Pod恢复这些状态

         只要知道一个Pod的名字以及它对应的Service的名字,就可以通过这条DNS记录访问到Pod的IP地址(pod的名称.service名称) -> Pod的IP

         定义Stateful的对象中有一个serviceName字段来告诉Stateful控制器使用具体的service来解析它所管理的Pod的IP地址

         Pod的名称由StatfulSet对象的名称+Pod创时所在的索引组成 StatefulSet使用这个DNS记录解析规则来维持Pod的拓扑状态

         StatefulSet给它所管理的所有Pod的名字进行了编号,编号规则是: - .而且这些编号都是从0开始累加与StatefulSet的每个Pod实例一一对应 绝不重复

         这些Pod的创建也是严格按照编号顺序进行的.比如,在web-0进入到Running 状态、并且细分状态(Conditions)成为Ready之前,web-1会一直处于Pending状态
         把这两个Pod删除之后Kubernetes会按照原先编号的顺序,创建出了两个新的 Pod.并且Kubernetes依然为它们分配了与原来相同的“网络身份”:web-0.nginx和 web-1.nginx

         通过永远不改变Pod名称的方式StatefulSet保证了Pod网络标识的稳定性.不管Pod是被删除重启还是被调度到其他节点上都不会改变Pod的名称

         StatefulSet管理的pod使用的镜像是一样的,但是每个pod的命令和初始化流程可以完全不一样来实现主从Pod的拓扑部署

        尽管web-0.nginx这条DNS记录本身不会变但它解析到的Pod的IP地址并不是固定的.这就意味着,对于“有状态应用”实例的访问必须使用DNS记录或者hostname的方式而绝不应该直接访问这些Pod的IP地址

    StatefulSet实现Pod的存储状态

          通过PVC机制来实现存储状态管理

          在StatefulSet对象中除了定义PodTemplate还会定义一个volumeClaimTemplates凡是被这个StatefulSet管理的Pod都会声明一个对应的PVC,这个PVC的定义就来自于 volumeClaimTemplates这个模板字段

    这个PVC的名字,会被分配一个与这个Pod完全一致的编号

     把一个Pod比如web-0删除之后,这个Pod对应的PVC和PV并不会被删除,而这个Volume 里已经写入的数据,也依然会保存在远程存储服务里

     StatefulSet在重新创建web-0这个pod的时候.它声明使用的PVC的名字还是叫作:www-web-0 这个PVC的定义,还是来自于PVC模板(volumeClaimTemplates)这是StatefulSet创建 Pod的标准流程

     Kubernetes为它查找名叫www-web-0的PVC时,就会直接找到旧Pod遗留下来的同名的 PVC进而找到跟这个PVC绑定在一起的PV.这样新的Pod就可以挂载到旧Pod对应的那个Volume并且获取到保存在Volume里的数据.通过这种方式Kubernetes的StatefulSet就实现了对应用存储状态的管理

    StatefulSet其实就是一种特殊的Deployment,而其独特之处在于,它的每个Pod都被编号了.而且,这个编号会体现在Pod的名字和hostname等标识信息上,这不仅代表了Pod的创建顺序,也是Pod的重要网络标识(即:在整个集群里唯一的、可被的访问身份).有了这个编号后StatefulSet就使用Kubernetes里的两个标准功能:Headless Service 和 PV/PVC,实现了对 Pod 的拓扑状态和存储状态的维护

    StatefulSet搭建Mysql有状态集群

         1.Master节点和Slave节点需要有不同的配置文件(即:不同的 my.cnf)

           只需要给主从节点分别准备两份不同的 MySQL 配置文件  然后根据Pod的序号(Index)挂载进去即可

         2.Master节点和Slave节点需要能够传输备份信息文件

         3.在Slave节点第一次启动之前需要执行一些初始化SQL操作

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: mysql
      labels:
        app: mysql
    data:
      master.cnf: |
         [mysqld]
         log-bin
      slave.cnf: |
         [mysqld]
         super-read-only
    configmap.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: mysql
      labels:
        app: mysql
    spec:
      ports:
      - name: mysql
        port: 3306
      clusterIP: None
      selector:
        app: mysql
    
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: mysql-read
      labels:
        app: mysql
    spec:
      ports:
      - name: mysql
        port: 3306
      selector:
        app: mysql
    service.yaml
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv001
      labels:
        name: pv001
    spec:
      nfs:
       path: /data/volumes/v1
       server: 192.168.164.141
      accessModes: ["ReadWriteMany","ReadWriteOnce"]
      capacity:
        storage: 20Gi
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv002
      labels:
        name: pv002
    spec:
      nfs:
       path: /data/volumes/v2
       server: 192.168.164.141
      accessModes: ["ReadWriteMany","ReadWriteOnce"]
      capacity:
        storage: 20Gi
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv003
      labels:
        name: pv003
    spec:
      nfs:
       path: /data/volumes/v3
       server: 192.168.164.141
      accessModes: ["ReadWriteMany","ReadWriteOnce"]
      capacity:
        storage: 20Gi
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv004
      labels:
        name: pv004
    spec:
      nfs:
       path: /data/volumes/v4
       server: 192.168.164.141
      accessModes: ["ReadWriteMany","ReadWriteOnce"]
      capacity:
        storage: 20Gi
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv005
      labels:
        name: pv005
    spec:
      nfs:
       path: /data/volumes/v5
       server: 192.168.164.141
      accessModes: ["ReadWriteMany","ReadWriteOnce"]
      capacity:
        storage: 20Gi
    pv.yaml
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: mysql
    spec:
      selector:
        matchLabels:
          app: mysql
      serviceName: mysql
      replicas: 3
      template:
        metadata:
          labels:
            app: mysql
        spec:
          initContainers:
          - name: init-mysql
            image: mysql:5.7
            command:
            - bash
            - "-c"
            - |
              set -ex
              [[ `hostname`  =~ -([0-9]+)$ ]] || exit 1
              ordinal=${BASH_REMATCH[1]}
              echo [mysqld] > /mnt/conf.d/server-id.cnf
              echo server-id=$((100 + $ordinal )) >> /mnt/conf.d/server-id.cnf
              if [[ $ordinal -eq 0 ]]; then
                cp /mnt/config-map/master.cnf /mnt/conf.d/
              else
                cp /mnt/config-map/slave.cnf /mnt/conf.d/
              fi
            volumeMounts:
            - name: conf
              mountPath: /mnt/conf.d
            - name: config-map
              mountPath: /mnt/config-map
          - name: clone-mysql
            image: gcr.io/google-samples/xtrabackup:1.0
            command:
            - bash
            - "-c"
            - |
              set -ex
              [[ -d /var/lib/mysql/mysql ]] && exit 0
              [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
              ordinal=${BASH_REMATCH[1]}
              [[ $ordinal -eq 0 ]] && exit 0
              ncat --recv-only mysql-$((ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
              xtrabackup --prepare  --target-dir=/var/lib/mysql
            volumeMounts:
            - name: data
              mountPath: /var/lib/mysql
              subPath: mysql
            - name: conf
              mountPath: /etc/mysql/conf.d
          containers:
          - name: mysql
            image: mysql:5.7
            env:
            - name: MYSQL_ALLOW_EMPTY_PASSWORD
              value: "1"
            ports:
            - name: mysql
              containerPort: 3306
            volumeMounts:
            - name: data
              mountPath: /var/lib/mysql
              subPath: mysql
            - name: conf
              mountPath: /etc/mysql/conf.d
            resources:
              requests:
                cpu: 500m
                memory: 500Mi
            livenessProbe:
              exec:
                command: ["mysqladmin","ping"]
              initialDelaySeconds: 30
              periodSeconds: 10
              timeoutSeconds: 5
            readinessProbe:
              exec:
                command: ["mysql","-h","127.0.0.1","-e","SELECT 1"]
              initialDelaySeconds: 5
              periodSeconds: 2
              timeoutSeconds: 1
          - name: xtrabackup
            image: gcr.io/google-samples/xtrabackup:1.0
            ports:
            - name: xtrabackup
              containerPort: 3307
            command:
            - bash
            - "-c"
            - |
              set -ex
              cd /var/lib/mysql
              if [[ -f xtrabackup_slave_info ]]; then
                 mv xtrabackup_slave_info change_master_to.sql.in
                 rm -f xtrabackup_binlog_info
              elif [[ -f xtrabackup_binlog_info ]]; then
                 [[ `cat xtrabackup_binlog_info` =~ ^(.*)[[:space:]]+(.*?)$ ]] || exit 1
                 rm xtrabackup_binlog_info
                 echo "change master to master_log_file='${BASH_REMATCH[1]}',
                      MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
              fi
              if [[ -f change_master_to.sql.in ]]; then
                 echo "waiting for mysqld to be ready"
                 until mysql -h 127.0.0.1 -e "SELECT 1";do sleep 1;done
                 echo "Initializing replication from clone position"
                 mv change_master_to.sql.in change_master_to.sql.orig
                 mysql -h 127.0.0.1 <<EOF
                 $(<change_master_to.sql.orig),
                  MASTER_HOST='mysql-0.mysql',
                  MASTER_USER='root',
                  MASTER_PASSWORD='',
                  MASTER_CONNECT_RETRY=10;
              START SLAVE;
              EOF
              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"
            volumeMounts:
            - name: data
              mountPath: /var/lib/mysql
              subPath: mysql
            - name: conf
              mountPath: /etc/mysql/conf.d
          volumes:
          - name: conf
            emptyDir: {}
          - name: config-map
            configMap:
              name: mysql
      volumeClaimTemplates:
      - metadata:
          name: data
        spec:
          accessModes: ["ReadWriteOnce"]
          resources:
            requests:
              storage: 10Gi
    StatefulSet.yaml

    问题调试

        volumes字段属于Pod对象的
        volumesMount字段属于容器对象的
        volumeClaimTemplates字段属于StatefulSet对象的

       - name: MYSQL_ALLOW_EMPTY_PASSWORD
       value: "1" 不能写成value: 1 必须加上双引号 否则会出现异常

       CrashLoopBackOff状态   查看Pod中指定容器的日志信息
         kubectl   logs   mysql-0  init-mysql
         kubectl   logs   mysql-0  clone-mysql
         kubectl   logs   mysql-0  mysql
         kubectl   logs   mysql-0  xtrabackup

      Pending状态
         kubectl describe pod mysql-2   一般是pod调度失败

    流程分析2

       1.安装好MySQL的Master节点之后需要做的第一步工作就是通过XtraBackup将Master 节点的数据备份到指定目录.这一步会自动在目标目录里生成一个备份信息文件名叫:xtrabackup_binlog_info.这两个信息会在接下来配置Slave节点的时候用到
       2.配置第一个Slave节点.Slave节点在第一次启动前需要先把Master节点的备份数据,连同备份信息文件一起拷贝到自己的数据目录(/var/lib/mysql)
       3.启动第一个Slave节点它会使用备份信息文件中的二进制日志文件和偏移量,与主节点进行数据同步
       4.在这个集群中添加更多的Slave节点新添加的Slave节点的备份数据来自于已经存在的Slave节点我们需要将Slave节点的数据备份在指定目录.而这个备份操作会自动生成另一种备份信息文件,名叫:xtrabackup_slave_info.我们就可以执行跟前面一样的“CHANGE MASTER TO”和“START SLAVE”指令,来初始化并启动这个新的Slave节点

       5.当master发生异常Pod在重启的时候保证数据的安全性

           mysql主节点在重启的时候当有写请求提交过来时可以抛出异常提示用户服务暂时不可用(提示下单失败) 过一段时间后再进行访问

     

      根据提示错误的行数信息 发现volumeMounts这个字段定义的时候缩进没有和容器定义进行对齐 导致json解析异常.把yaml中的缩进对齐即可

  • 相关阅读:
    批处理集锦——(2)自定义函数
    批处理集锦——(1)怎么输出空行
    批处理实例——批量修改电视剧文件名称
    error C3861: “LOG4CPLUS_DEBUG”: 找不到标识
    vc个版本对应的vs版本
    Yii2中系统定义的常用路径别名,如果获取web的url
    asp提取声母源码
    Windows Error Code(windows错误代码详解)
    VS2013编译经常卡在正在从以下位置加载xxx.dll的符号
    Python3字符串截取值
  • 原文地址:https://www.cnblogs.com/yxh168/p/12327404.html
Copyright © 2011-2022 走看看