099-Cloud Native Deployments of Hazelcast using Kubernetes
Kubernetes在Hazelcast平台上的原生云部署
这篇文档主要是描述Kubernetes在Hazelcast平台上的原生云部署。当我们提到原生云的时,意味着我们当前的应用程序是运行在一个集群之上,同时使用这个集群的基础设施实现这个应用程序。值得注意的是,在此情况下,一个定制化的Hazelcast引导程序被用来使Hazelcast可以动态的发现已经加入集群的Hazelcast节点。 当拓扑结构发生变化时,需要Hazelcast节点自身进行交流和处理。 本文档同样也尝试去解释Kubernetes的核心组件:Pods、Service和ReplicationController。
前提
下面的例子假定你已经安装了Kubernetes集群并且可以运行。同时你也已经在你的路径下安装了kubectl命令行工具。可以从“开始”这个小节中得到相应平台的安装指令。
给急性子的备注
下面的介绍会有点长,如果你想跳过直接开始的话,请看结尾处的“拓展部分”。 资源
资源
免费的资源如下:
Hazelcast Discovery - https://github.com/pires/hazelcast-kubernetes-bootstrapper
Dockerfile -https://github.com/pires/hazelcast-kubernetes
Docker Trusted Build - https://quay.io/repository/pires/hazelcast-kubernetes
简单的单调度单元的Hazelcast节点
在Kubernetes中,最小的应用单元就是Pod。一个Pod就是同一个主机调度下的一个或者多个容器。在一个Pod中的所有容器共享同一个网络命名空间,同时可以有选择性的共享同一个数据卷。 在这种情况下,我们不能单独运行一个Hazelcast pod,因为它的发现机制依赖于Service的定义。
添加一个Hazelcast 服务
在Hazelcast 中,一个Service被描述为执行同一任务的Pods集合。比如,一个Hazelcast集群中的节点集合。Service 的一个重要用途就是通过建立一个均衡负载器将流量均匀的分到集合中的每一个成员。此外,Service还可以作为一个标准的查询器,使动态变化的POD集合提供有效通过Kubernetes 的API。实际上,这个就是探索机制的工作原理,就是在service的基础上去发现Hazelcast pods。 下面是对Service的描述:
apiVersion: v1
kind: Service
metadata:
labels:
name: hazelcast
name: hazelcast
spec:
ports:
- port: 5701
selector:
name: hazelcast
这里值得注意的是selector(选择器)。在标签的上层有一个查询器,它标识了被Service所覆盖的Pods集合。在这种情况下,selector就是代码中name: hazelcast
。在接下来的 Replication Controller说明书中,你会看到Pods中有对应的标签,那么它就会被这个Service中对应的成员变量所选中。
创建该Serviced的命令如下:
$ kubectl create -f examples/hazelcast/hazelcast-service.yaml
添加一个拷贝节点
Kubernetes 和 Hazelcast 真正强大的地方在于它们可以轻松的建立一个可拷贝的、大小可调的Hazelcast集群。 在Kubernetes 中,存在一个叫做Replication Controller的管理器,专门用来管理相同Pods的拷贝集合。和Service一样,它也存在一个在集合成员变量中定义的选择查询器。和Service不同的是,它对拷贝的个数有要求,会通过创建或者删除Pods来确保当前Pods的数量符合要求。 Replication Controllers会通过匹配响应的选择查询器来确认要接收的Pods,下面我们将创建一个单拷贝的Replication Controller去接收已经存在的Hazelcast Pod。
apiVersion: v1
kind: ReplicationController
metadata:
labels:
name: hazelcast
name: hazelcast
spec:
replicas: 1
selector:
name: hazelcast
template:
metadata:
labels:
name: hazelcast
spec:
containers:
- resources:
limits:
cpu: 0.1
image: quay.io/pires/hazelcast-kubernetes:0.5
name: hazelcast
env:
- name: "DNS_DOMAIN"
value: "cluster.local"
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- containerPort: 5701
name: hazelcast
在这段代码中,有一些需要注意的东西。首先要注意的是,我们运行的是quay.io/pires/hazelcast-kubernetes image, tag 0.5。这个busybox安装在JRE8上。尽管如此,它还是添加了一个用户端的应用程序,从而可以发现集群中的Hazelcast节点并且引导一个Hazelcast实例。HazelcastDiscoveryController通过内置的搜索服务器来探索Kubernetes API Server ,之后用Kubernetes API来发现新的节点。
你可能已经注意到了,我们会告知Kubernetes,容器会暴露hazelcast端口。最终,我们需要告诉集群的管理器,我们需要一个CPU核。
对于Hazelcast pod而言,replication controller块的配置基本相同,以上就是声明,它只是给管理器提供一种简单的建立新节点的方法。其它的部分就是查询选择器和条件1中,配置下来的要求的POD数量。
最后,我们需要根据你的Kubernetes集群的DNS配置来设置DNS_DOMAIN的环境变量。
创建该控制器的命令:
$ kubectl create -f examples/hazelcast/hazelcast-controller.yaml
当控制器成功的准备好后,你就可以查询服务端点:
$ kubectl get endpoints hazelcast -o json
{
"kind": "Endpoints",
"apiVersion": "v1",
"metadata": {
"name": "hazelcast",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/endpoints/hazelcast",
"uid": "094e507a-2700-11e5-abbc-080027eae546",
"resourceVersion": "4094",
"creationTimestamp": "2015-07-10T12:34:41Z",
"labels": {
"name": "hazelcast"
}
},
"subsets": [
{
"addresses": [
{
"ip": "10.244.37.3",
"targetRef": {
"kind": "Pod",
"namespace": "default",
"name": "hazelcast-nsyzn",
"uid": "f57eb6b0-2706-11e5-abbc-080027eae546",
"resourceVersion": "4093"
}
}
],
"ports": [
{
"port": 5701,
"protocol": "TCP"
}
]
}
]
}
你可以看到Service 发现那些被replication controller建立的Pods。
这下变的更加有趣了。让我们把把集群提高到2个Pod。
$ kubectl scale rc hazelcast --replicas=2
现在,如果你去列出集群中的Pods,你应该会看到2个 hazelcast pods:
'$ kubectl get pods'
NAME READY STATUS RESTARTS AGE
hazelcast-nanfb 1/1 Running 0 40s
hazelcast-nsyzn 1/1 Running 0 2m
kube-dns-xudrp 3/3 Running 0 1h
如果想确保每一个Pods都在工作,你可以通过log命令来进行日志检查,如下:
$ kubectl log hazelcast-nanfb hazelcast
2015-07-10 13:26:34.443 INFO 5 --- [ main] com.github.pires.hazelcast.Application : Starting Application on hazelcast-nanfb with PID 5 (/bootstrapper.jar started by root in /)
2015-07-10 13:26:34.535 INFO 5 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@42cfcf1: startup date [Fri Jul 10 13:26:34 GMT 2015]; root of context hierarchy
2015-07-10 13:26:35.888 INFO 5 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2015-07-10 13:26:35.924 INFO 5 --- [ main] c.g.p.h.HazelcastDiscoveryController : Asking k8s registry at https://kubernetes.default.svc.cluster.local..
2015-07-10 13:26:37.259 INFO 5 --- [ main] c.g.p.h.HazelcastDiscoveryController : Found 2 pods running Hazelcast.
2015-07-10 13:26:37.404 INFO 5 --- [ main] c.h.instance.DefaultAddressPicker : [LOCAL] [someGroup] [3.5] Interfaces is disabled, trying to pick one address from TCP-IP config addresses: [10.244.77.3, 10.244.37.3]
2015-07-10 13:26:37.405 INFO 5 --- [ main] c.h.instance.DefaultAddressPicker : [LOCAL] [someGroup] [3.5] Prefer IPv4 stack is true.
2015-07-10 13:26:37.415 INFO 5 --- [ main] c.h.instance.DefaultAddressPicker : [LOCAL] [someGroup] [3.5] Picked Address[10.244.77.3]:5701, using socket ServerSocket[addr=/0:0:0:0:0:0:0:0,localport=5701], bind any local is true
2015-07-10 13:26:37.852 INFO 5 --- [ main] com.hazelcast.spi.OperationService : [10.244.77.3]:5701 [someGroup] [3.5] Backpressure is disabled
2015-07-10 13:26:37.879 INFO 5 --- [ main] c.h.s.i.o.c.ClassicOperationExecutor : [10.244.77.3]:5701 [someGroup] [3.5] Starting with 2 generic operation threads and 2 partition operation threads.
2015-07-10 13:26:38.531 INFO 5 --- [ main] com.hazelcast.system : [10.244.77.3]:5701 [someGroup] [3.5] Hazelcast 3.5 (20150617 - 4270dc6) starting at Address[10.244.77.3]:5701
2015-07-10 13:26:38.532 INFO 5 --- [ main] com.hazelcast.system : [10.244.77.3]:5701 [someGroup] [3.5] Copyright (c) 2008-2015, Hazelcast, Inc. All Rights Reserved.
2015-07-10 13:26:38.533 INFO 5 --- [ main] com.hazelcast.instance.Node : [10.244.77.3]:5701 [someGroup] [3.5] Creating TcpIpJoiner
2015-07-10 13:26:38.534 INFO 5 --- [ main] com.hazelcast.core.LifecycleService : [10.244.77.3]:5701 [someGroup] [3.5] Address[10.244.77.3]:5701 is STARTING
2015-07-10 13:26:38.672 INFO 5 --- [ cached1] com.hazelcast.nio.tcp.SocketConnector : [10.244.77.3]:5701 [someGroup] [3.5] Connecting to /10.244.37.3:5701, timeout: 0, bind-any: true
2015-07-10 13:26:38.683 INFO 5 --- [ cached1] c.h.nio.tcp.TcpIpConnectionManager : [10.244.77.3]:5701 [someGroup] [3.5] Established socket connection between /10.244.77.3:59951
2015-07-10 13:26:45.699 INFO 5 --- [ration.thread-1] com.hazelcast.cluster.ClusterService : [10.244.77.3]:5701 [someGroup] [3.5]
Members [2] {
Member [10.244.37.3]:5701
Member [10.244.77.3]:5701 this
}
2015-07-10 13:26:47.722 INFO 5 --- [ main] com.hazelcast.core.LifecycleService : [10.244.77.3]:5701 [someGroup] [3.5] Address[10.244.77.3]:5701 is STARTED
2015-07-10 13:26:47.723 INFO 5 --- [ main] com.github.pires.hazelcast.Application : Started Application in 13.792 seconds (JVM running for 14.542)
接着是4个Pods: $ kubectl scale rc hazelcast --replicas=4 然后通过刚才的操作去检查这4个成员是否连接。
拓展部分
对于那些急性子,下面是这一章所用到的所有命令:
# 建立一个service去跟踪所有的hazelcast nodes
kubectl create -f examples/hazelcast/hazelcast-service.yaml
#建立一个 replication controller去拷贝hazelcast nodes
kubectl create -f examples/hazelcast/hazelcast-controller.yaml
#升级成2个节点
kubectl scale rc hazelcast --replicas=2
#升级成4个节点
kubectl scale rc hazelcast --replicas=4
Hazelcast 的搜索源代码
点击这里