一. 前言
Consul是由HashiCorp基于Go语言开发的支持多数据中心分布式高可用的服务发布和注册服务软件,采用Raft算法保证服务的一致性,且支持健康检查。但是在kubernetes里,当节点发生故障或者资源不足时,会根据策略杀掉节点的一些pod转而生成新的pod,而新生成的pod的ip地址和名称(hash值)都发生了变化。这时候我们如何保证新的pod和原有的pod的唯一标识不变呢?statefulset可以做到,他能保证pod具有唯一的网络标识。
二. Statefulset
deployment来管理pod容器的副本数量,一个应用的所有Pod是完全一样的。所以,它们互相之间没有顺序,也无所谓运行在哪台宿主机上。需要的时候,Deployment就可以通过Pod模板创建新的Pod;不需要的时候,Deployment就可以“杀掉”任意一个Pod。但是,在实际的场景中,并不是所有的应用都可以满足这样的要求。尤其是分布式应用,它的多个实例之间,往往有依赖关系,比如:主从关系、主备关系。还有就是数据存储类应用,它的多个实例,往往都会在本地磁盘上保存一份数据。而这些实例一旦被杀掉,即使重建出来,实例与数据之间的对应关系也已经丢失,从而导致应用失败。所以,这种实例之间有不对等关系,以及实例对外部数据有依赖关系的应用,就被称为“有状态应用”(Stateful Application)。
三. 编排stafulset.yaml
piVersion: apps/v1
kind: StatefulSet
metadata:
name: consul
spec:
serviceName: consul
replicas: 3
selector:
matchLabels:
app: consul
template:
metadata:
labels:
app: consul
spec:
terminationGracePeriodSeconds: 10
containers:
- name: consul
image: consul:latest
args:
- "agent"
- "-server"
- "-bootstrap-expect=3"
- "-ui"
- "-data-dir=/consul/data"
- "-bind=0.0.0.0"
- "-client=0.0.0.0"
- "-advertise=$(PODIP)"
- "-retry-join=consul-0.consul.$(NAMESPACE).svc.cluster.local"
- "-retry-join=consul-1.consul.$(NAMESPACE).svc.cluster.local"
- "-retry-join=consul-2.consul.$(NAMESPACE).svc.cluster.local"
- "-domain=cluster.local"
- "-disable-host-node-id"
env:
- name: PODIP
valueFrom:.
fieldRef:
fieldPath: status.podIP
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- containerPort: 8500
name: ui-port
- containerPort: 8443
name: https-port
通过以上定义文件我们可以看到,里面最核心的部分是–retry-join后面的dns规则,由于我们指定了pod名称为consul,并且有三个实例,因此它们的名称为consul-0,consul-1,consul-2,即便有节点失败,起来以后名称仍然是固定的,这样不管新起的podIp是多少,通过dns都能够正确解析到它.
四. 创建服务
apiVersion: v1
kind: Service
metadata:
name: consul
labels:
name: consul
spec:
type: NodePort
ports:
- name: http
port: 8500
nodePort: 30850
targetPort: 8500
- name: https
port: 8443
nodePort: 30851
targetPort: 8443
selector:
app: consul
五. 页面访问