在 Kubernetes 集群上部署一个高可用的 Consul 集群,确保一个节点挂了之后不会影响已注册到 Consul 的服务。利用 StatefulSet 和无头服务 HeadLess 的选举机制来实现 Consul 集群的高可用性,数据持久化方式选择HostPath,通过 nodeSelector 节点选择器将 Pod 调度到指定的三台机器(10.10.100.44,10.10.50.71,10.10.50.72)上运行,这样可以避免集群整体故障导致的数据丢失。
1. 准备工作
1.确定要创建的目录:
在我们的配置文件中,我们指定了
/data/consul
作为hostPath
的挂载目录,因此我们需要在三个节点(10.10.100.44,10.10.50.71,10.10.50.72)上创建此目录。2.创建目录的命令:
mkdir -p /data/consul chmod -R 755 /data/consul 登陆节点 10.10.100.44 ssh root@10.10.100.44 mkdir -p /data/consul chmod -R 755 /data/consul 登陆节点 10.10.50.71 ssh root@10.10.50.71 mkdir -p /data/consul chmod -R 755 /data/consul 登陆节点 10.10.50.72 ssh root@110.10.50.72 mkdir -p /data/consul chmod -R 755 /data/consul
3.为要固定consul_pod的node节点打标签:
➜ ~ kubectl label nodes 10.10.100.44 nodeType=consul node/10.10.100.44 labeled ➜ ~ kubectl label nodes 10.10.50.71 nodeType=consul node/10.10.50.71 labeled ➜ ~ kubectl label nodes 10.10.50.72 nodeType=consul node/10.10.50.72 labeled
4.创建 Consul Namespace
为 Consul 创建一个命名空间:
kubectl create namespace consul
2.consul yaml文件编排
1.创建无头服务Service(Headless Service) :
无头服务将帮助我们识别集群中的所有Consul server节点:
# 新建consul-server-service.yaml touch consul-server-service.yaml
apiVersion: v1 kind: Service metadata: name: consul namespace: consul labels: name: consul spec: selector: name: consul ports: - name: http port: 8500 targetPort: 8500 - name: https port: 8443 targetPort: 8443 - name: rpc port: 8400 targetPort: 8400 - name: serf-lan-tcp protocol: "TCP" port: 8301 targetPort: 8301 - name: serf-lan-udp protocol: "UDP" port: 8301 targetPort: 8301 - name: serf-wan-tcp protocol: "TCP" port: 8302 targetPort: 8302 - name: serf-wan-udp protocol: "UDP" port: 8302 targetPort: 8302 - name: server port: 8300 targetPort: 8300 - name: consul-dns port: 8600 targetPort: 8600
保存为consul-server-service.yaml,并运行:
kubectl create -f consul-server-service.yaml
2.创建pod控制器StatefulSet:
# 新建consul-server-statefulset.yaml touch consul-server-statefulset.yaml
apiVersion: apps/v1 kind: StatefulSet metadata: name: consul namespace: consul labels: name: consul spec: serviceName: consul selector: matchLabels: name: consul replicas: 3 template: metadata: labels: name: consul spec: terminationGracePeriodSeconds: 10 nodeSelector: nodeType: consul containers: - name: consul image: hashicorp/consul:1.17.3 imagePullPolicy: IfNotPresent args: - "agent" - "-server" - "-bootstrap-expect=3" - "-ui" - "-data-dir=/consul/data" - "-bind=0.0.0.0" - "-client=0.0.0.0" - "-advertise=$(POD_IP)" - "-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: POD_IP valueFrom: fieldRef: fieldPath: status.podIP - name: NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace ports: - containerPort: 8500 name: http - containerPort: 8400 name: rpc - containerPort: 8443 name: https-port - containerPort: 8301 name: serf-lan - containerPort: 8302 name: serf-wan - containerPort: 8600 name: consul-dns - containerPort: 8300 name: server volumeMounts: - name: data-volume mountPath: /consul/data volumes: - name: data-volume hostPath: path: /data/consul
如何是单点部署的话,只需要修改consul-statefulset.yaml内容为:
apiVersion: apps/v1 kind: StatefulSet metadata: name: consul namespace: consul labels: name: consul spec: serviceName: consul selector: matchLabels: name: consul replicas: 1 template: metadata: labels: name: consul spec: terminationGracePeriodSeconds: 10 nodeSelector: nodeType: consul containers: - name: consul image: hashicorp/consul:1.17.3 imagePullPolicy: IfNotPresent args: - "agent" - "-server" - "-dev" # 启用开发模式,取消选举机制 - "-ui" - "-data-dir=/consul/data" - "-bind=0.0.0.0" - "-client=0.0.0.0" - "-advertise=$(POD_IP)" - "-domain=cluster.local" - "-disable-host-node-id" env: - name: POD_IP valueFrom: fieldRef: fieldPath: status.podIP - name: NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace ports: - containerPort: 8500 name: http - containerPort: 8400 name: rpc - containerPort: 8443 name: https-port - containerPort: 8301 name: serf-lan - containerPort: 8302 name: serf-wan - containerPort: 8600 name: consul-dns - containerPort: 8300 name: server volumeMounts: - name: data-volume mountPath: /consul/data volumes: - name: data-volume hostPath: path: /data/consul
保存为
consul-server-statefulset.yaml
,并运行:kubectl create -f consul-statefulset.yaml
3.创建DNS Service:
Consul Dns Service将负责consul_web的访问入口,服务的注册地址:
# 新建consul-server-http.yaml touch consul-server-http.yaml
apiVersion: v1 kind: Service metadata: name: consul-server-http namespace: consul # 添加 namespace 字段并设置为 consul spec: selector: name: consul type: NodePort ports: - protocol: TCP port: 8500 targetPort: 8500 nodePort: 30018 name: consul-server-tcp
保存为
consul-server-http.yaml
,并运行:kubectl create -f consul-server-http.yaml
4.验证部署:
你可以通过检查 Pod 是否在预期的节点上运行来验证部署:
kubectl get pods -o wide -n consul
可以看到3个consul server pod已正常启动并绑定到10.10.100.44 10.10.50.72 10.10.50.71 指定节点上:
随便找三台中的一个nodeip+30018端口打开consul_webui确定节点选举机制是否正常,在UI界面的Nodes栏可以看到,选举机制生效
在浏览器中访问 http://10.10.100.44:30018
5.服务注册:
k8s集群内部服务需要注册conusl服务只需要在启动参数中添加consul的注册地址端口和具体要注册的服务的key,即可实现服务的配置注册引用:
Args: --consul-addr consul-server.consul:8500 --consul-key /app/dev/account_module