在k8s部署akka集群

背景:在 Spring Boot 中整合akka集群。现在需要将其部署在k8s中。

以下仅是一个节点的配置过程。若存在多个节点,则需要配置多次。
假设当前项目为3个akka节点。则在kubernetes中结构为:
在这里插入图片描述

代码层面:

  1. 嵌入 启动 managementbootstrap 自动发现代码
    • 可在配置类中(@configurationActorSystem.create 创建 actorSystem
    • 再使用 @Resource 注入;
        public void init(){
            AkkaManagement.get(actorSystem).start();
            ClusterBootstrap.get(actorSystem).start();
        }
  1. 健康检查类:
    • 注意: 在后续的 conf配置时,需要配置该全限定类名
public class MyhealthCheck implements Supplier<CompletionStage<Boolean>> {

    private final Cluster cluster;

    public ClusterCheck(ActorSystem system) {
        cluster = Cluster.get(system);
    }

    @Override
    public CompletionStage<Boolean> get() {
        return CompletableFuture.completedFuture(cluster.selfMember().status() == MemberStatus.up());
    }
}

kubernetes.yaml 配置

apiVersion: apps/v1  #必选,版本号,例如v1
kind: Deployment  #必选,Pod
metadata:  #必选,元数据
  labels: #自定义标签
    app: appka-test
  name: appka-test
  namespace: appka-1
spec: #必选,Pod中容器的详细定义
  replicas: 1
  selector:
    matchLabels:
      app: appka-test
  template:
    metadata: # 资源的元数据/属性
      labels: # 设定资源的标签
        app: appka-test
        actorSystemName: appka-test
    spec:
      containers: #必选,Pod中容器列表
        - name: appka-test # 容器的名字
          image: appka-test-k8s:latest # 容器使用的镜像地址
          readinessProbe:  # Pod 准备服务健康检查设置
            httpGet: # 通过httpget检查健康,返回200-399之间,则认为容器正常
              path: "/ready"
              port: management
            periodSeconds: 10 # 检查间隔时间
            failureThreshold: 3 # 失败门槛,连接失败5次,pod杀掉,重启一个新的pod
            initialDelaySeconds: 10 # 表明第一次检测在容器启动后多长时间后开始
          livenessProbe: # pod 内部健康检查的设置
            httpGet:
              path: "/alive"
              port: management
            periodSeconds: 10
            failureThreshold: 5
            initialDelaySeconds: 20
          ports:  #需要暴露的端口库号列表
            # akka remoting
            - name: remoting
              containerPort: 2552 #容器需要监听的端口号
              protocol: TCP  #端口协议,支持TCP和UDP,默认TCP
            # akka-management and bootstrap
            - name: management
              containerPort: 8558
              protocol: TCP
            - name: http
              containerPort: 8080
              protocol: TCP
          env: #容器运行前需设置的环境变量列表
            - name: NAMESPACE #环境变量名称
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: REQUIRED_CONTACT_POINT_NR
              value: "2"

---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: pod-reader
  namespace: appka-1
rules:
  - apiGroups: [""] # "" indicates the core API group
    resources: ["pods"]
    verbs: ["get", "watch", "list"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: read-pods
  namespace: appka-1
subjects:
  # serviceAccount是用于控制对Kubernetes API的访问的一种身份验证机制。
  # 每个命名空间默认有一个名为default的服务账号,当你不指定服务账号时,Kubernetes会默认使用这个账号。
  # 这种指定方式有助于明确哪些资源可以访问,从而提高系统的安全性。
  # 在某些情况下,可能需要创建和使用自定义的服务账号,以便更好地控制资源的访问。
  - kind: User
    name: system:serviceaccount:appka-1:default
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

tips:

  1. appka-test 需要适配自己的项目名
  2. appka-1 命名空间 namespace 需要自己适配
  3. containers.image 容器镜像:需要项目自定义部署
  4. subjects.name: 服务账号;其中 appka-1 是命名空间。若需自定义,需要注意!
  5. kind: Role 角色配置次数选择官网默认。
    1. kubernetes 快速入门:K8S系列一:概念入门 - 知乎
    2. K8S系列二:实战入门 - 知乎
    3. K8S系列三:单服务部署 - 知乎
    4. K8S系列四:服务管理 - 知乎

akka conf 文件配置

  1. coordinated-shutdown.exit-jvm = on
    • 当集群节点看到自己处于 Exit 状态时,CoordinatedShutdown 自动运行,将所有组件和资源关闭,包括终止JVM进程。
  2. allow-java-serialization : 设置 允许使用Java序列化来序列化和反序列化Akka的消息
  3. cluster集群配置:
    1. akka.actor.provider = "cluster" 设置akka集群模式
    2. shutdown-after-unsuccessful-join-seed-nodes
      1. 种子节点无法成功加入的最大 时间
    3. 脑裂配置
    4. contact-point-discovery 节点 发现配置
      1. k8s服务发现的名称:需要自定义
      2. k8s发现方式:本项目采用 kubernetes-api
      3. Akka组成集群最少节点数
    5. health-checks 健康就绪检查
    akka {
      loglevel = "DEBUG"
      coordinated-shutdown.exit-jvm = on
      actor {
        allow-java-serialization = on
        provider = "cluster"
      }
    
      cluster {
        shutdown-after-unsuccessful-join-seed-nodes = 60s
        downing-provider-class = "akka.cluster.sbr.SplitBrainResolverProvider"
      }
    }
    
    akka.management {
      cluster.bootstrap {
        contact-point-discovery {
          // ; k8s 服务发现的名称, 自定义
          service-name = "%s"
          discovery-method = kubernetes-api
          required-contact-point-nr = 2
          // ; akka组成集群最少节点数
          required-contact-point-nr = ${?REQUIRED_CONTACT_POINT_NR}
        }
      }
    }
     akka.management {
       health-checks {
         readiness-checks {
         // ; 健康探测的类
           example-ready = "com.src.akka.check.MyhealthCheck"
         }
       }
     }

Akka Management HTTP

	Akka Management HTTP 的默认配置适合在 Kubernetes 中使用,它将绑定到 Pod 外部 IP 地址上的默认端口 8558。

配置完成后,需要对不同的节点打jar包,创建对应的docker镜像,进而部署至不同的pod中。

下面是后续需要考虑的问题。(皆来自官网) 

其他存在的问题

配置后 akka-cluster在k8s还可能存在其他问题:

  1. 集群节点发现方式若两者其中有一个挂掉(如:a挂掉),a重新加入集群后,是否产生新的集群?

    1. Akka Cluster Bootstrap

    2. image

  2. 【脑裂】akka cluster split-brain-resolver(SBR)_lease-majority-CSDN博客

    1. k8s 不同的pod ip不一样。若其中一个节点挂掉,重启pod会改变ip,但akka 集群会继续连接该ip

    2. 解决方式:配置相关策略

      1. Akka集群脑裂_akka脑裂-CSDN博客

主要参考官网的部署步骤:
Deploying Akka Cluster to Kubernetes
学习文章:
Akka 集群如何部署到 k8s 中,实现自动发现管理节点 – 墨烟客 – 不只是代码,更是文学

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐