上次我们说到了deployment来管理pod容器的副本数量,如果挂掉之后容器再次启动就可以了,但是如果要是启动的是mysql集群、zookeeper集群、etcd这种集群,里面都有id号,这种有关联的,如果一旦挂掉之后,在启动之后呢,集群id是否会变化呢?答案是肯定会变的。 那有没有另外的一种控制器模式吗?当然k8s会给我吗提供的。【statefulset】 那什么场景需要使用StatefulSet呢?官方给出的建议是,如果你部署的应用满足以下一个或多个部署需求,则建议使用StatefulSet

稳定的、唯一的网络标识。 稳定的、持久的存储。 有序的、优雅的部署和伸缩。 有序的、优雅的删除和停止。 有序的、自动的滚动更新。 接下来看一下statefulset和deployment的区别:

1、接下来我们开始实践一下statefulset这种模式,来部署zookeeper集群

docker pull leolee32/kubernetes-library:kubernetes-zookeeper1.0-3.4.10 安装zk的机器下载这个镜像

2、Zookeeper集群需要用到存储,这里需要准备持久卷(PersistentVolume,简称PV),我这里以yaml文件创建3个PV,供待会儿3个Zookeeper节点创建出来的持久卷声明

3、创建一个pv;{persistent-volume.yaml}

cat persistent-volume.yaml kind: PersistentVolume apiVersion: v1 metadata: name: k8s-pv-zk1 annotations: volume.beta.kubernetes.io/storage-class: "anything" labels: type: local spec: capacity: storage: 3Gi accessModes: - ReadWriteOnce hostPath: path: "/var/lib/zookeeper" persistentVolumeReclaimPolicy: Recycle

kind: PersistentVolume apiVersion: v1 metadata: name: k8s-pv-zk2 annotations: volume.beta.kubernetes.io/storage-class: "anything" labels: type: local spec: capacity: storage: 3Gi accessModes: - ReadWriteOnce hostPath: path: "/var/lib/zookeeper" persistentVolumeReclaimPolicy: Recycle

kind: PersistentVolume apiVersion: v1 metadata: name: k8s-pv-zk3 annotations: volume.beta.kubernetes.io/storage-class: "anything" labels: type: local spec: capacity: storage: 3Gi accessModes: - ReadWriteOnce hostPath: path: "/var/lib/zookeeper" persistentVolumeReclaimPolicy: Recycle 接下来启动一下;这里发现pv和pvc还没有绑定状态是Available

4、部署Zookeeper集群

cat zookeeper.yaml apiVersion: v1 kind: Service metadata: name: zk-hs labels: app: zk spec: ports:

  • port: 2888 name: server
  • port: 3888 name: leader-election clusterIP: None selector: app: zk

apiVersion: v1 kind: Service metadata: name: zk-cs labels: app: zk spec: ports:

  • port: 2181 name: client selector: app: zk

apiVersion: policy/v1beta1 kind: PodDisruptionBudget metadata: name: zk-pdb spec: selector: matchLabels: app: zk maxUnavailable: 1

apiVersion: apps/v1 kind: StatefulSet metadata: name: zk spec: selector: matchLabels: app: zk serviceName: zk-hs replicas: 3 updateStrategy: type: RollingUpdate podManagementPolicy: Parallel template: metadata: labels: app: zk spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: "app" operator: In values: - zk topologyKey: "kubernetes.io/hostname" containers: - name: kubernetes-zookeeper imagePullPolicy: Always image: "leolee32/kubernetes-library:kubernetes-zookeeper1.0-3.4.10" resources: requests: memory: "1Gi" cpu: "0.5" ports: - containerPort: 2181 name: client - containerPort: 2888 name: server - containerPort: 3888 name: leader-election command: - sh - -c - "start-zookeeper
--servers=3
--data_dir=/var/lib/zookeeper/data
--data_log_dir=/var/lib/zookeeper/data/log
--conf_dir=/opt/zookeeper/conf
--client_port=2181
--election_port=3888
--server_port=2888
--tick_time=2000
--init_limit=10
--sync_limit=5
--heap=512M
--max_client_cnxns=60
--snap_retain_count=3
--purge_interval=12
--max_session_timeout=40000
--min_session_timeout=4000
--log_level=INFO" readinessProbe: exec: command: - sh - -c - "zookeeper-ready 2181" initialDelaySeconds: 10 timeoutSeconds: 5 livenessProbe: exec: command: - sh - -c - "zookeeper-ready 2181" initialDelaySeconds: 10 timeoutSeconds: 5 volumeMounts: - name: datadir mountPath: /var/lib/zookeeper securityContext: runAsUser: 1000 fsGroup: 1000 volumeClaimTemplates:

  • metadata: name: datadir annotations: volume.beta.kubernetes.io/storage-class: "anything" spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 3Gi

完成之后开始创建 没起来看一下啥原因 发现没有zookeeper用户 创建一下并给个权限

【注意】{每个安装zk的机器都要执行} 发现有2个已经启动了,有1个pening状态,在master上面没有安装 接下来看一下日志发现报这个错误 使用kubeadm初始化的集群,出于安全考虑Pod不会被调度到Master Node上,也就是说Master Node不参与工作负载 我们这里让master也运行一个,机器有限就三台 允许master节点部署pod,使用命令如下: kubectl taint nodes --all node-role.kubernetes.io/master-

执行完成过一会再看看 启动了

【禁止master部署pod:】 kubectl taint nodes k8s node-role.kubernetes.io/master=true:NoSchedule

好了,接下来我们看一下效果是不是集群模式

说明已经成功了


但是我们3个zk,一般允许宕机一个,另外2个可以对外工作 接下来我们模拟一下宕机一个 模拟k8s-node1节点故障 看一下效果: 说明机器故障了,接下来 机器启动之后看一下 看到了吧,节点恢复之后会自动加入到原来的集群之中 为啥会这样呢 因为StatefulSet的稳定的唯一的网络标识特性,我们能比较轻松的实现Pod的固定IP需求,但是要是deployment就复杂的多了,会随机给你拉起,但是这个不会的 这里有个其他的知识点: PodDisruptionBudget控制器可以设置应用POD集群处于运行状态最低个数,也可以设置应用POD集群处于运行状态的最低百分比,这样可以保证在主动销毁应用POD的时候,不会一次性销毁太多的应用POD,从而保证业务不中断或业务SLA不降级 咱们这里会保留一个对外提供服务 通过两个参数来配置PodDisruptionBudget: 1、 MinAvailable参数:表示最小可用POD数,表示应用POD集群处于运行状态的最小POD数量,或者是运行状态的POD数同总POD数的最小百分比。

2、 MaxUnavailable参数:表示最大不可用PO数,表示应用POD集群处于不可用状态的最大POD数,或者是不可用状态的POD数同总POD数的最大百分比。 !!!!!这里需要注意的是,MinAvailable参数和MaxUnavailable参数是互斥的,也就是说如果使用了其中一个参数,那么就不能使用另外一个参数了 这个在后面专门会讲到,这里只是提一下用到了。

今天演示讲到这里,后面有问题欢迎私信留言给我,一起讨论