使用StategulSet1Raft集群在Kubernetes中的部署问题架构云计算ContentsApache Ratis中集群中Raft节点的创建 ............................................................ 1使用StategulSet ....................................................................................... 1什么是节点间解析实现部署程序中按名称创建获取名称部署一个集群在程序启动的时候,其实就必须知道集群中所有其他节点的信息(,端口等),如果集群部署在中,怎么进行扩容呢?这是个矛盾的问题:一旦扩容,则集群中节点的信息会发生变化。在中,使用可以解决这一问题。Apache Ratis中集群中Raft节点的创建以为例,在集群中创建节点时,需要初始化一个对象:RaftGroup raftGroup = RaftGroup.valueOf(RaftGroupId.valueOf(UUID.fromString("02511d47-d67c-49a3-9011-abb3109a44c1")), raftPeers)RaftServer server = RaftServer.newBuilder() .setGroup(raftGroup) .setProperties(properties) .setServerId(id) .setStateMachine(stateMachine) .build()其中,即所有节点的信息,这个是提前就知晓的,包括其地址和端口号。比如,。使用StategulSet什么是StategulSet通常在中部署节点使用部署时,每次重新部署都会为其分配新的资源,包括名称、所依赖的等。也就是说,它是无状态的,每次创建的都与之前的没什么关系。而则未解决这一问题而设计,使用它能够创建出一组稳定的。以一个集群为例:apiVersion: apps/v1kind: StatefulSetmetadata: name: webspec: serviceName: "nginx" 使用StategulSet2 replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: k8s.gcr.io/nginx-slim:0.8 ports: - containerPort: 80 name: web volumeMounts: - name: www mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: www spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 1Gi创建完成后,则可以看到部署的节点: ﮫ17ms⠀ kubectl get statefulset powershell 80 18:02:55 NAME READY AGEweb 3/3 5d18h ﮫ1.511s⠀ kubectl get podsNAME READY STATUS RESTARTS AGEweb-0 1/1 Running 0 3d6hweb-1 1/1 Running 0 3d6hweb-2 1/1 Running 0 5d18h可以看到,为其创建了三个实例,无论修改还是重新部署,这个名称是不会变化的,并且其分配的持久化卷也是相对固定的。因此,我们通过可以:保持的状态预知所有的地址(名称)这可以帮助实现集群的创建。节点间解析还需要解决一个问题,就是在每个中都需要能够访问其他节点。根据前面的规则可以知道其他节点的名称,如,但是并不支持在在节点中解析其他节点,如果我们在中肯定是不通的。 使用StategulSet3要实现互相解析,需要使用apiVersion: v1kind: Servicemetadata: name: nginx labels: app: nginxspec: ports: - port: 80 name: web clusterIP: None selector: app: nginx创建之后,将可以使用{podName}.{headlessSvcName}的方式来解析,例如: ﮫ224ms⠀ kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEkubernetes ClusterIP 10.232.0.1 <none> 443/TCP 181dnginx ClusterIP None <none> 80/TCP 5d18h ﮫ0ms⠀ kubectl exec -it web-0 -- /bin/bashowershell 99 14:28:24 root@web-0:/# curl web-1.nginx<html><head><title>403 Forbidden</title></head><body bgcolor="white"><center><h1>403 Forbidden</h1></center><hr><center>nginx/1.11.1</center></body></html>root@web-0:/#实现部署程序中按名称创建RaftGroup通过以上的方式,在知道集群副本数目、、名称的情况下可以得到所有机器的地址。因此,可以将这些信息传入到程序中,根据这些构建:raft: group: "02511d47-d67c-49a3-9011-abb3109a44c1" dataStoragePath: /data/ratis-data id: dw-dynamic-service-0 peers: size: 3 pattern: dw-dynamic-service-%d port: 6000 使用StategulSet4Map<String, RaftConfig.PeerConfig> peers = new HashMap<>();for (int i = 0; i < clusterSize; i++) { String host = String.format(properties.getPeers().getPattern(), i); String address = String.format("%s:%d", host, properties.getPeers().getPort()); peers.put(host, new RaftConfig.PeerConfig(address));}获取pod名称可以通过获取的名称,并作为环境变量传入到中。env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: RAFT_ID value: {{ printf "$(POD_NAME).%s" (include "my-service.headless-svcname" .) }}helm部署其他信息通过可以很容易生成出来,例如上面的应用的配置raft: group: {{ .Values.raft.group }} dataStoragePath: /data/ratis-data peers: size: {{ .Values.replicaCount }} pattern: {{ printf "%s-%%d.%s" (include "my-service.fullname" .) (include "my-service.headless-svcname" .) }} port: 6000