【本文目标】
将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.pngpom.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<String, String> map = hazelcastInstance.getMap("testMap");
map.put(key, value);
return true;
}
@GetMapping("get")
public String getValue(@RequestParam String key) {
IMap<String, String> map = hazelcastInstance.getMap("testMap");
return map.get(key);
}
@GetMapping("size")
public int getSize() {
IMap<String, String> 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中运行的),运行:
image.pngdocker build -f DockerFile -t hazelcast-k8s .
检查下,运行docker images
,有了:
image.pngdocker images
3. 将hazelcast-k8s镜像推送至docker hub上
docker tag:给我们本地的镜像加一个tag别名:
docker tag hazelcast-k8s <docker username>/hazelcast-k8s
push镜像:
登陆docker hub查看,发现镜像已经有了: image.pngdocker push <docker username>/hazelcast-k8s
4. Kubernetes相关:配置RBAC
RBAC全称叫:Role-based access control,即权限相关的配置。
Hazelcast官网已经为我们准备了一个在线yaml,ServiceAccount=defult,namespace同样为default,如果需要自定义,那么下载rbac.yaml文件自行改之:
image.pngkubectl apply -f https://raw.githubusercontent.com/hazelcast/hazelcast-kubernetes/master/rbac.yaml
查看资源类型为hazelcast-cluster-role
:
查看资源类型为hazelcast-cluster-role-binding
:
我也把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组件:
image.png 查看Pod: image.pngkubectl create deployment hazelcast-k8s --image=<docker username>/hazelcast-k8s
查看具体的Log:
image.pngkubectl logs -f hazelcast-k8s-5779bdf674-zpkmt
5.2 扩大Deployment中的replicaSet,从1个变为2个:
image.png 可以看到新增了一个Pod: image.pngkubectl scale deployment hazelcast-k8s --replicas=2
查看新的Pod的Log:
kubectl logs -f hazelcast-k8s-5779bdf674-cmd8w
【成功!!!】两个Pod组成了一个Hazelcast的集群:
Hazelcast有两种模式,一种是C/S模式,一个是embedded模式(即没有Server,每个节点既是client又是server),本文用的是embedded模式: image.png6. 测试
创建一个类型为ClusterIP的service,自身的端口为8080,targetPort为8090(targetPort的意思是指向的Pod中的containerPort为多少,我们项目定义的为8090):
可以看到创建好了: image.pngkubectl create service clusterip hazelcast-k8s --tcp=8080:8090
因为ClusterIP为内部service,想要被外部访问:
- 要么通过另外创建组件Ingress进行访问
- 要么将上述的service改为type为LoadBalancer的service
- 要么通过下面的命令进行转发,这样才可以从我们本机的localhost进行访问:
kubectl port-forward service/hazelcast-k8s 8080:8080
测试API:
a) /version:
b) 存放cache:/put:
image.pngc) 取出cache:/get:
image.pngd) cache大小:/size:
image.png7. 总结
那么两个Pod间是怎么自动发现的呢?
从官网上来看,主要是通过插件——Hazelcast Kubernetes discovery plugin 。
这个插件会调用Kubernetes API来自动发现成员。所以才需要【第4章】中的Role-based access control的相关配置。
查看2个Pod的IP:
image.png log中可以看到,Hazelcast的通信用的是Pod自己的IP: image.pngkubectl get pod -o wide
【目前的架构】hazelcast通过Pod的IP,端口为5701,进行通信,而创建的Service,只是给String Boot项目本身的8090端口做暴露,跟Hazelcast本身的5701没有关系:
未命名文件 (8).png8. 为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:
image.pngkubectl describe service hazelcast-service
网友评论