Kubernetes(k8s)中文文件 使用Kubernetes在雲上原生部署cassandra_Kubernetes中文社群
譯者:盧文泉
下面的文件描述了在Kubernetes上部署cloud native Cassandra的開發過程。當我們講cloudnative時,我們是指這樣一款應用,它執行在叢集管理器中,並利用叢集管理器的基礎設施來實現應用的功能。特別的是,在本章介紹的例項中,一個定製好的Cassandra SeedProvider*可以確保Cassandra能夠動態發現新的Cassandra節點並把它新增到叢集中。
這篇文件也在努力描述Kubernetes中的核心概念:Pods,Services和Replication Controllers。
預備知識
下面的例子假設你已經安裝和執行一個Kubernetes叢集,並且你也下載好kubectl命令列工具以及配置在你的path中。請先閱讀入門指南獲取在你平臺上安裝Kubernetes的指令。
本文中的例子還需要一些程式碼和配置檔案。為了避免重複輸入(程式碼和配置檔案),你可以使用git clone命令從Kubernetes倉庫中克隆檔案到本地計算機。
簡單的單個Pod Cassandra節點
在Kubernetes中,應用的原子單元(【譯者注】原子單元指不可再分的最小單元)是Pod。一個Pod指必須被部署在同一個主機的一個或者多個容器。同一個pod中的所有容器共享一個網路名稱空間,以及可選地共享掛載卷。在這個簡單的例子中,我們在pod中定義一個執行Cassandra的容器:
apiVersion: v1
kind: Pod
metadata:
labels:
name: cassandra
name: cassandra
spec:
containers:
- args:
- /run.sh
resources:
limits:
cpu: "0.5"
image: gcr.io/google_containers/cassandra:v5
name: cassandra
ports:
- name: cql
containerPort: 9042
- name: thrift
containerPort: 9160
volumeMounts:
- name: data
mountPath: /cassandra_data
env:
- name: MAX_HEAP_SIZE
value: 512M
- name: HEAP_NEWSIZE
value: 100 M
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
volumes:
- name: data
上面的描述中有幾點需要注意。首先我們執行的映象是kubernetes/cassandra。這是一個標準的安裝在Debian上的Cassandra映象。但是它還給Cassandra新增一個定製的SeedProvider,
在Cassandra中, SeedProvider設定一個gossip協議用來發現其它Cassandra節點。KubernetesSeedProvider使用內建的Kubernetes發現服務找到KubernetesAPI伺服器,然後利用Kubernetes API發現新的節點。
也許你注意到(在上面的指令碼中)我們設定了一些Cassandra引數(MAX_HEAP_SIZE 和HEAP_NEWSIZE)以及添加了關於名稱空間的資訊。我們還告訴Kubernetes容器暴露了CQL和Thrift的API埠。最後,我們告訴叢集管理器我們需要0.5個CPU(0.5個核心core)
理論上會立刻建立一個Cassandra pod,但是在Cassandra部署過程中,KubernetesSeedProvider需要知道現在哪個節點上建立服務(【譯者注】這會消耗一些時間)
Cassandra服務
在Kubernetes中一個服務是指執行相同任務的一系列pods集合(【譯者注】一個任務可能由多個pod協同完成)。例如,Cassandra叢集中的pods集合可以是Kubernetes服務,甚至僅僅是一個pod也可以。服務的一個重要用途是在pods成員間分發流量實現負載均衡。服務另外一個用途也可以用作長期查詢,查詢呼叫Kubernetes API使得動態改變pod(或者是上面建立的一個pod)成為可能。這就是我們最初使用Cassandra服務的兩種方式。
下面是服務的描述:
apiVersion: v1
kind: Service
metadata:
labels:
name: cassandra
name: cassandra
spec:
ports:
- port: 9042
selector:
name: cassandra
這裡對於節點最重要的是選擇器,(選擇器)是建立在標籤上的查詢,標籤則標記了服務中包含的pods集合。在這個例子中選擇器是name=cassandra。如果你現在回頭看Pod的描述,你會發現pod有和它對應的標籤。所以這個pod會被選中成為服務中的成員。
通過下面命令建立服務:
$ kubectl create -f examples/cassandra/cassandra-service.yaml
現在服務執行起來了,我們可以使用前面提到的說明來建立第一個Cassandra。
$ kubectl create -f examples/cassandra/cassandra.yaml
不久,你會看到pod也運行了,以及pod中執行的單個容器:
$ kubectl get pods cassandra NAME READY STATUS RESTARTS AGE cassandra 1/1 Running 0 55s
你也可以查詢服務的端點來檢查pod是否被正確選中:
$ kubectl get endpoints cassandra -o yaml
apiVersion: v1
kind: Endpoints
metadata:
creationTimestamp: 2015-06-21T22:34:12Z
labels:
name: cassandra
name: cassandra
namespace: default
resourceVersion: "944373"
selfLink: /api/v1/namespaces/default/endpoints/cassandra
uid: a3d6c25f-1865-11e5-a34e-42010af01bcc
subsets:
- addresses:
- ip: 10.244.3.15
targetRef:
kind: Pod
name: cassandra
namespace: default
resourceVersion: "944372"
uid: 9ef9895d-1865-11e5-a34e-42010af01bcc
ports:
- port: 9042
protocol: TCP
新增複製節點
當然,單節點叢集並不特別有趣。Kubernetes和Cassandra的真正能量在於可以很方便建立一個副本,使得Cassandra叢集可擴充套件。(如果你想了解更多關於 副本控制器基礎內容,請檢視:Replication Controller)
在Kubernetes中一個複製控制器負責複製相同的pods。複製控制器的作用和服務的相同點在於複製控制器有選擇器能查詢集合中的指定成員。與服務不同的是複製控制器有預期數量的副本,所以它能建立或刪除Pods確保pod數量達到預期狀態。
複製控制器會”接受”已經存在並且符合查詢條件的pods,現在我們會建立一個只有一個副本的複製控制器,用它來接收已經存在的Cassandra pod:
apiVersion: v1
kind: ReplicationController
metadata:
labels:
name: cassandra
name: cassandra
spec:
replicas: 1
selector:
name: cassandra
template:
metadata:
labels:
name: cassandra
spec:
containers:
- command:
- /run.sh
resources:
limits:
cpu: 0.5
env:
- name: MAX_HEAP_SIZE
value: 512M
- name: HEAP_NEWSIZE
value: 100M
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: gcr.io/google_containers/cassandra:v5
name: cassandra
ports:
- containerPort: 9042
name: cql
- containerPort: 9160
name: thrift
volumeMounts:
- mountPath: /cassandra_data
name: data
volumes:
- name: data
emptyDir: {}
大部分複製控制器的定義和上面的Cassandra pod的定義類似,定義簡單地為複製控制器提供一個模板,建立新的Cassandra pod時可以很方便拿來使用。不同的部分是選擇器屬性 包含控制器的選擇器查詢以及副本屬性中的副本的預期數量,在這個例子中是1。
建立控制器的指令:
$ kubectl create -f examples/cassandra/cassandra-controller.yaml
現在事實上已經不那麼無趣了,因為之前沒做新的事情。現在它會變得有趣。
現在我們把叢集數量擴充套件到2:
$ kubectl scale rc cassandra --replicas=2
現在如果你列出叢集中的pods,查詢符合標籤name=cassandra的pods,你會看到兩個cassandra pod:
$ kubectl get pods -l="name=cassandra" NAME READY STATUS RESTARTS AGE cassandra 1/1 Running 0 3m cassandra-af6h5 1/1 Running 0 28s
注意其中一個pod的名字是人們可讀的cassandra,它是我們在配置檔案中指定的。另一個是複製控制器隨機生成的字串。
為了證明所有的pods都正常工作,你可以使用nodetool命令檢查叢集的狀態。使用kubectlexec命令在Cassandra Pod中執行nodetool。
$ kubectl exec -ti cassandra -- nodetool status Datacenter: datacenter1 ======================= Status=Up/Down |/ State=Normal/Leaving/Joining/Moving -- Address Load Tokens Owns (effective) Host ID Rack UN 10.244.0.5 74.09 KB 256 100.0% 86feda0f-f070-4a5b-bda1-2eeb0ad08b77 rack1 UN 10.244.3.3 51.28 KB 256 100.0% dafe3154-1d67-42e1-ac1d-78e7e80dce2b rack1
現在擴充套件叢集到4個節點:
kubectl scale rc cassandra --replicas=4
一會後再次檢查狀態:
$ kubectl exec -ti cassandra -- nodetool status Datacenter: datacenter1 ======================= Status=Up/Down |/ State=Normal/Leaving/Joining/Moving -- Address Load Tokens Owns (effective) Host ID Rack UN 10.244.2.3 57.61 KB 256 49.1% 9d560d8e-dafb-4a88-8e2f-f554379c21c3 rack1 UN 10.244.1.7 41.1 KB 256 50.2% 68b8cc9c-2b76-44a4-b033-31402a77b839 rack1 UN 10.244.0.5 74.09 KB 256 49.7% 86feda0f-f070-4a5b-bda1-2eeb0ad08b77 rack1 UN 10.244.3.3 51.28 KB 256 51.0% dafe3154-1d67-42e1-ac1d-78e7e80dce2b rack1
tl; dr;
下面是給那些不耐心的小夥伴的,下面是以上命令的總結:
# create a service to track all cassandra nodes kubectl create -f examples/cassandra/cassandra-service.yaml # create a single cassandra node kubectl create -f examples/cassandra/cassandra.yaml # create a replication controller to replicate cassandra nodes kubectl create -f examples/cassandra/cassandra-controller.yaml # scale up to 2 nodes kubectl scale rc cassandra --replicas=2 # validate the cluster kubectl exec -ti cassandra -- nodetool status # scale up to 4 nodes kubectl scale rc cassandra --replicas=4