在 active/standby 中集群 PODs 的 Kubernetes 服务

Kubernetes service with clustered PODs in active/standby

抱歉没有保持简短,因为任何此类尝试都会让我错过问题的一些重要细节。

我有一个遗留 Java 应用程序,它在集群环境中以 active/standby 模式工作,通过预定义端口公开某些 RESTful Web 服务。

如果我的应用集群中有两个节点,在任何时间点只有一个处于主动模式,另一个处于被动模式,并且请求始终由具有应用程序的节点提供服务运行宁处于活动模式。 'Active' 和 'Passive' 只是角色,这样的应用程序将在两个节点上 运行ning。主动和被动实例通过相同的预定端口相互通信。

假设我有一个双节点集群,每个节点上都有一个我的应用程序实例 运行ning,那么其中一个实例最初是活动的,另一个是被动的。如果由于某种原因活动节点因某种原因进行折腾,则其他节点中的应用程序实例使用某种心跳机制识别此情况,接管控制并成为新的活动节点。当旧的主动角色恢复时,它会检测到另一个人拥有新的主动角色,因此它会进入被动模式。

该应用程序设法在同一端点 IP 上提供 RESTful web 服务,而不管哪个节点正在 运行 使用集群 IP 以 'Active' 模式连接应用程序,这 piggy-返回活动实例,因此集群 IP 切换到 运行在活动模式下运行应用程序的任何节点。

我正在尝试将此应用程序和 运行 容器化到 Kubernetes 集群中以实现规模化和易于部署。我能够将其容器化并能够将其部署为 Kubernetes 集群中的 POD。

为了在这里引入 Active/Passive 角色,我 运行 设置了这个 POD 的两个实例,每个实例都使用节点亲和力固定到一个单独的 K8S 节点(每个节点都被标记为主动或被动,以及 POD 定义固定在这些标签上),并使用我的应用程序的集群机制将它们集群起来,而只有一个是主动的,另一个是被动的。

我通过使用 NodePort 使用 K8S 服务语义在外部公开 REST 服务,并通过主节点上的 NodePort 公开 REST WebService。

这是我的 yaml 文件内容:

apiVersion: v1
kind: Service
metadata:
  name: myapp-service
  labels:
    app: myapp-service
spec:
  type: NodePort
  ports:
    - port: 8443
      nodePort: 30403
  selector:
    app: myapp

---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: active
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: myapp
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: nodetype
                operator: In
                values:
                - active
      volumes:
        - name: task-pv-storage
          persistentVolumeClaim:
           claimName: active-pv-claim
      containers:
      - name: active
        image: myapp:latest
        imagePullPolicy: Never
        securityContext:
           privileged: true
        ports:
         - containerPort: 8443
        volumeMounts:
        - mountPath: "/myapptmp"
          name: task-pv-storage

---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: passive
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: myapp
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: nodetype
                operator: In
                values:
                - passive
      volumes:
        - name: task-pv-storage
          persistentVolumeClaim:
           claimName: active-pv-claim
      containers:
      - name: passive
        image: myapp:latest
        imagePullPolicy: Never
        securityContext:
           privileged: true
        ports:
         - containerPort: 8443
        volumeMounts:
        - mountPath: "/myapptmp"
          name: task-pv-storage

一切似乎都工作正常,除了因为两个 PODs 都通过相同的端口公开 Web 服务,K8S 服务正在以随机方式将传入请求路由到其中一个 PODS。由于我的 REST WebService 端点仅在活动节点上工作,因此服务请求仅在请求路由到具有活动角色的应用程序的 POD 时通过 K8S 服务资源工作。如果在任何时间点,K8S 服务碰巧将传入请求路由到应用程序处于被动角色的 POD,则服务 inaccessible/not 得到服务。

如何使 K8S 服务始终将请求路由到应用程序处于活动角色的 POD?这在 Kubernetes 中可行吗?还是我的目标太高了?

感谢您的宝贵时间!

实现此目的的一种方法是在 pod 中添加 label 标记作为活动和备用。然后 select 您服务中的活动吊舱。这会将流量发送到标记为活动的 pod。

https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#service-and-replicationcontroller

您可以在本文档中找到另一个示例。

https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/

您可以将就绪探测与选举容器结合使用。选举总是会从选举池中选出一个 master,如果您确保只有那个 pod 被标记为就绪……只有那个 pod 会接收流量。