【k8s学习】在Kubernetes上部署Hazelcast集群(embedded模式)

【本文目标】
将Hazelcast部署到k8s上,并且两个Pod间能组成Hazelcast集群。

【参考】
官网:Get Started with Embedded Hazelcast on Kubernetes:https://docs.hazelcast.com/tutorials/kubernetes-embedded


【步骤】

  • 准备一个项目,Hazelcast与Spring Boot集成,部署到kubernetes上需要在hazelcast.yaml中开启flag。
    可参考我之前的文章:【Hazelcast学习】入门篇,以及和Spring Boot集成
  • 通过DockerFile build image
    可参考我之前的文章:【Docker学习】布署Spring Boot项目到docker中
  • push到docker hub上
    可参考我之前的文章:【k8s学习】布署Spring Boot项目到minikube上
  • Kubernetes相关:配置RBAC
  • 将项目部署至minikube中
    关于minikube安装,可参考之前的文章:【k8s学习】minikube、kubectl、yaml配置文件的介绍

1. 创建本地项目

首先准备一个Hazelcast项目:
image.png

pom.xml非常简单:
三个artifactId:

  • spring-boot-starter-web(version用的是2.5.7,还需要加上spring-boot parent)
  • hazelcast(version用的是5.1.1)
  • hazelcast-spring(version用的是5.1.1)

另外别忘了加上build plugin:spring-boot-maven-plugin,这个可以将Spring Boot打包成fat jar(即可以使用java -jar运行)

在resources.xml中加上hazelcast.yaml文件:

hazelcast:
  network:
    join:
      multicast:
        enabled: false
      kubernetes:
        enabled: true

写了几个API:

@RestController
public class HazelcastController {

    @Autowired
    private HazelcastInstance hazelcastInstance;

    @GetMapping("version")
    public String version() {
        return "hazelcast k8s test v1";
    }

    @GetMapping("put")
    public boolean put(@RequestParam String key, @RequestParam String value) {
        IMap map = hazelcastInstance.getMap("testMap");
        map.put(key, value);
        return true;
    }

    @GetMapping("get")
    public String getValue(@RequestParam String key) {
        IMap map = hazelcastInstance.getMap("testMap");
        return map.get(key);
    }

    @GetMapping("size")
    public int getSize() {
        IMap map = hazelcastInstance.getMap("testMap");
        return map.size();
    }

}

使用mvn clean package命令,将项目打包下。

2. 添加DockerFile文件

我用的是8090端口,在application.yaml中定义好的,如果不定义,默认是8080端口:

FROM openjdk:8-jdk-alpine
COPY target/SpringBootHazelcastK8s.jar hazelcastK8s.jar
expose 8090
ENTRYPOINT ["java","-jar","hazelcastK8s.jar"]

打开命令行工具,跳到DockerFile所在的目录(我直接在idea terminal中运行的),运行:

docker build -f DockerFile -t hazelcast-k8s .

image.png

检查下,运行docker images,有了:

docker images

image.png

3. 将hazelcast-k8s镜像推送至docker hub上

docker tag:给我们本地的镜像加一个tag别名:

docker tag hazelcast-k8s /hazelcast-k8s

push镜像:

docker push /hazelcast-k8s

登陆docker hub查看,发现镜像已经有了:
image.png

4. Kubernetes相关:配置RBAC

RBAC全称叫:Role-based access control,即权限相关的配置。

Hazelcast官网已经为我们准备了一个在线yaml,ServiceAccount=defult,namespace同样为default,如果需要自定义,那么下载rbac.yaml文件自行改之:

kubectl apply -f https://raw.githubusercontent.com/hazelcast/hazelcast-kubernetes/master/rbac.yaml

image.png

查看资源类型为hazelcast-cluster-role

image.png

查看资源类型为hazelcast-cluster-role-binding

image.png

我也把rbac.yaml文件copy下来贴出来了:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: hazelcast-cluster-role
rules:
  - apiGroups:
      - ""
    resources:
      - endpoints
      - pods
      - nodes
      - services
    verbs:
      - get
      - list

---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: hazelcast-cluster-role-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: hazelcast-cluster-role
subjects:
  - kind: ServiceAccount
    name: default
    namespace: default

5. 将项目部署至Kubernetes中

我的Kubernetes环镜用的是minikube。

5.1 创建Deployment组件:

kubectl create deployment hazelcast-k8s --image=/hazelcast-k8s

image.png

查看Pod:
image.png

查看具体的Log:

kubectl logs -f hazelcast-k8s-5779bdf674-zpkmt

image.png

5.2 扩大Deployment中的replicaSet,从1个变为2个:

kubectl scale deployment hazelcast-k8s --replicas=2

image.png

可以看到新增了一个Pod:
image.png

查看新的Pod的Log:

kubectl logs -f hazelcast-k8s-5779bdf674-cmd8w

【成功!!!】两个Pod组成了一个Hazelcast的集群:

Hazelcast有两种模式,一种是C/S模式,一个是embedded模式(即没有Server,每个节点既是client又是server),本文用的是embedded模式:
image.png

6. 测试

创建一个类型为ClusterIP的service,自身的端口为8080,targetPort为8090(targetPort的意思是指向的Pod中的containerPort为多少,我们项目定义的为8090):

kubectl create service clusterip hazelcast-k8s --tcp=8080:8090

可以看到创建好了:
image.png

因为ClusterIP为内部service,想要被外部访问:

  • 要么通过另外创建组件Ingress进行访问
  • 要么将上述的service改为type为LoadBalancer的service
  • 要么通过下面的命令进行转发,这样才可以从我们本机的localhost进行访问:

kubectl port-forward service/hazelcast-k8s 8080:8080

测试API:
a) /version:

image.png

b) 存放cache:/put:

image.png

c) 取出cache:/get:

image.png

d) cache大小:/size:

image.png

7. 总结

那么两个Pod间是怎么自动发现的呢?

从官网上来看,主要是通过插件——Hazelcast Kubernetes discovery plugin 。

这个插件会调用Kubernetes API来自动发现成员。所以才需要【第4章】中的Role-based access control的相关配置。

查看2个Pod的IP:

kubectl get pod -o wide

image.png

log中可以看到,Hazelcast的通信用的是Pod自己的IP:
image.png

【目前的架构】hazelcast通过Pod的IP,端口为5701,进行通信,而创建的Service,只是给String Boot项目本身的8090端口做暴露,跟Hazelcast本身的5701没有关系:

未命名文件 (8).png

8. 为Hazelcast之间的通信加上Service:

【更好的做法是我们可以为Hazelcast的5701也定义Service,这样在项目中可以写上service name,在Pod间的通信,可以通过Service转发】

在项目中配置:

hazelcast:
  network:
    join:
      multicast:
        enabled: false
      kubernetes:
        enabled: true
        namespace: default
        service-name: hazelcast-service

重新docker push后,再重新创建deployment。

创建新的Service,可以看到port为5701,为hazelcast通信时使用:

apiVersion: v1
kind: Service
metadata:
  name: hazelcast-service
spec:
  type: LoadBalancer
  selector:
    app: hazelcast-k8s
  ports:
  - name: hazelcast
    port: 5701

启动后,查看service:
可以看到Endpoint指向的是两个Pod,端口为5701:

kubectl describe service hazelcast-service

image.png

你可能感兴趣的:(【k8s学习】在Kubernetes上部署Hazelcast集群(embedded模式))