本教程描述拉如何在 Kubernetes 上運(yùn)行 Apache Cassandra佛嬉。 數(shù)據(jù)庫 Cassandra 需要永久性存儲提供數(shù)據(jù)持久性(應(yīng)用 狀態(tài))组题。 在此示例中蟆肆,自定義 Cassandra seed provider 使數(shù)據(jù)庫在加入 Cassandra 集群時發(fā)現(xiàn)新的 Cassandra 實(shí)例墩剖。
使用 StatefulSets 可以更輕松地將有狀態(tài)的應(yīng)用程序部署到你的 Kubernetes 集群中塘淑。 有關(guān)本教程中使用的功能的更多信息盐须, 參閱 StatefulSet画饥。
說明:
Cassandra 和 Kubernetes 都使用術(shù)語 node 來表示集群的成員衔瓮。 在本教程中,屬于 StatefulSet 的 Pod 是 Cassandra 節(jié)點(diǎn)抖甘,并且是 Cassandra 集群的成員(稱為 ring)热鞍。 當(dāng)這些 Pod 在你的 Kubernetes 集群中運(yùn)行時,Kubernetes 控制平面會將這些 Pod 調(diào)度到 Kubernetes 的 節(jié)點(diǎn)上。
當(dāng) Cassandra 節(jié)點(diǎn)啟動時薇宠,使用 seed列表 來引導(dǎo)發(fā)現(xiàn) ring 中其他節(jié)點(diǎn)偷办。 本教程部署了一個自定義的 Cassandra seed provider,使數(shù)據(jù)庫可以發(fā)現(xiàn)新的 Cassandra Pod 出現(xiàn)在 Kubernetes 集群中澄港。
一椒涯、教程目標(biāo)
- 創(chuàng)建并驗(yàn)證 Cassandra 無頭(headless)Service..
- 使用 StatefulSet 創(chuàng)建一個 Cassandra ring。
- 驗(yàn)證 StatefulSet回梧。
- 修改 StatefulSet废岂。
- 刪除 StatefulSet 及其 Pod.
二、準(zhǔn)備開始
你必須擁有一個 Kubernetes 的集群漂辐,同時你的 Kubernetes 集群必須帶有 kubectl 命令行工具。
如果你還沒有集群棕硫,參考 用 kubeadm 在 Debian 或 Ubuntu 中創(chuàng)建 k8s 集群髓涯。
要完成本教程,你應(yīng)該已經(jīng)熟悉 Pod哈扮, Service和 StatefulSet纬纪。
三、教程
1 為 Cassandra 創(chuàng)建無頭(headless) Services
在 Kubernetes 中滑肉,一個 Service 描述了一組執(zhí)行相同任務(wù)的 Pod包各。
以下 Service 用于在 Cassandra Pod 和集群中的客戶端之間進(jìn)行 DNS 查找:
cassandra-service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: cassandra
name: cassandra
spec:
clusterIP: None
ports:
- port: 9042
selector:
app: cassandra
創(chuàng)建一個 Service 來跟蹤 cassandra-service.yaml
文件中的所有 Cassandra StatefulSet:
kubectl apply -f ./cassandra-service.yaml
1.1 驗(yàn)證(可選)
獲取 Cassandra Service劈愚。
kubectl get svc cassandra
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cassandra ClusterIP None <none> 9042/TCP 3s
如果沒有看到名為 cassandra
的服務(wù)扭仁,則表示創(chuàng)建失敗有缆。 請閱讀Debug Services略号,以解決常見問題肚菠。
2 使用 StatefulSet 創(chuàng)建 Cassandra Ring
下面包含的 StatefulSet 清單創(chuàng)建了一個由三個 Pod 組成的 Cassandra ring揩环。
cassandra-statefulset.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: cassandra-pv-1
labels:
type: local
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/tmp"
apiVersion: v1
kind: PersistentVolume
metadata:
name: cassandra-pv-3
labels:
type: local
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/tmp"
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: cassandra
labels:
app: cassandra
spec:
serviceName: cassandra
replicas: 3
selector:
matchLabels:
app: cassandra
template:
metadata:
labels:
app: cassandra
spec:
terminationGracePeriodSeconds: 1800
containers:
- name: cassandra
image: registry.cn-hangzhou.aliyuncs.com/google_samples_thepoy/cassandra:v13
imagePullPolicy: Always
ports:
- containerPort: 7000
name: intra-node
- containerPort: 7001
name: tls-intra-node
- containerPort: 7199
name: jmx
- containerPort: 9042
name: cql
resources:
limits:
cpu: "500m"
memory: 1Gi
requests:
cpu: "500m"
memory: 1Gi
securityContext:
capabilities:
add:
- IPC_LOCK
lifecycle:
preStop:
exec:
command:
- /bin/sh
- -c
- nodetool drain
env:
- name: MAX_HEAP_SIZE
value: 512M
- name: HEAP_NEWSIZE
value: 100M
- name: CASSANDRA_SEEDS
value: "cassandra-0.cassandra.default.svc.cluster.local"
- name: CASSANDRA_CLUSTER_NAME
value: "K8Demo"
- name: CASSANDRA_DC
value: "DC1-K8Demo"
- name: CASSANDRA_RACK
value: "Rack1-K8Demo"
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
readinessProbe:
exec:
command:
- /bin/bash
- -c
- /ready-probe.sh
initialDelaySeconds: 15
timeoutSeconds: 5
# These volume mounts are persistent. They are like inline claims,
# but not exactly because the names need to match exactly one of
# the stateful pod volumes.
volumeMounts:
- name: cassandra-data
mountPath: /cassandra_data
# These are converted to volume claims by the controller
# and mounted at the paths mentioned above.
# do not use these in production until ssd GCEPersistentDisk or other ssd pd
volumeClaimTemplates:
- metadata:
name: cassandra-data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
3 驗(yàn)證 Cassandra StatefulSet
- 獲取 Cassandra StatefulSet:
kubectl get statefulset cassandra
結(jié)果:
NAME READY AGE
cassandra 3/3 14m
StatefulSet
資源會按順序部署 Pod诉探。
-
獲取 Pod 查看已排序的創(chuàng)建狀態(tài):
kubectl get pods -l app=cassandra
三個 Pod 要花幾分鐘的時間才能部署先较。部署之后掏击,相同的命令將返回類似于以下的輸出:
NAME READY STATUS RESTARTS AGE cassandra-0 1/1 Running 0 15m cassandra-1 1/1 Running 0 14m cassandra-2 1/1 Running 0 13m
-
運(yùn)行第一個 Pod 中的 Cassandra nodetool卵皂,以顯示 ring 的狀態(tài)。
kubectl exec -it cassandra-0 -- nodetool status
結(jié)果:
Datacenter: DC1-K8Demo ====================== Status=Up/Down |/ State=Normal/Leaving/Joining/Moving -- Address Load Tokens Owns (effective) Host ID Rack UN 10.244.1.20 70.88 KiB 32 65.9% 2c20de58-2680-4edd-b651-d83e73219a05 Rack1-K8Demo UN 10.244.2.16 108.87 KiB 32 69.6% 7fb488d6-5fce-4e82-bfb7-0ac34ddea61d Rack1-K8Demo UN 10.244.3.17 104.55 KiB 32 64.5% fc9be49a-5fbc-454e-b244-cc7e8b736ca2 Rack1-K8Demo
4 修改 Cassandra StatefulSet
使用 kubectl edit
修改 Cassandra StatefulSet 的大小砚亭。
-
運(yùn)行以下命令:
kubectl edit statefulset cassandra
此命令你的終端中打開一個編輯器灯变,修改的就是你之前 apply 的那個配置文件。如果你沒有修改過捅膘,那么需要更改的是第 51 行的
replicas
字段添祸,將其值修改為 4,:x
保存退出寻仗。集群會自動應(yīng)用以此方法修改的配置文件膝捞,StatefulSet 將會擴(kuò)展為 4 個 Pod。
但之前只創(chuàng)建了 3 個 PersistentVolume,每個 Pod 都需要綁定一個 PersistentVolume蔬咬,所以還需要再手動創(chuàng)建一個 PersistentVolume:
apiVersion: v1 kind: PersistentVolume metadata: name: cassandra-pv-4 labels: type: local spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce hostPath: path: "/tmp"
-
獲取 Cassandra StatefulSet 驗(yàn)證更改:
kubectl get statefulset cassandra
結(jié)果:
NAME DESIRED CURRENT AGE cassandra 4 4 36m
5 刪除本示例
出于安全考慮鲤遥,在刪除或縮小 StatefulSet 時不會刪除與 StatefulSet 關(guān)聯(lián)的卷,因?yàn)槟愕臄?shù)據(jù)更有價值林艘。
:warning:警告: 根據(jù)存儲類和回收策略盖奈,刪除 PersistentVolumeClaims 可能導(dǎo)致關(guān)聯(lián)的卷也被刪除。 千萬不要認(rèn)為其容量聲明被刪除狐援,你就能訪問數(shù)據(jù)钢坦。
運(yùn)行以下命令(連在一起成為一個單獨(dú)的命令)刪除 Cassandra StatefulSet 中的所有內(nèi)容:
grace=$(kubectl get pod cassandra-0 -o=jsonpath='{.spec.terminationGracePeriodSeconds}') \
&& kubectl delete statefulset -l app=cassandra \
&& echo "Sleeping ${grace} seconds" 1>&2 \
&& sleep $grace \
&& kubectl delete persistentvolumeclaim -l app=cassandra
運(yùn)行以下命令,刪除你為 Cassandra 設(shè)置的 Service:
kubectl delete service -l app=cassandra
6 Cassandra 容器環(huán)境變量
本教程中的 Pod 使用來自 Google container registry 的 gcr.io/google-samples/cassandra:v13
鏡像(我把這個鏡像 Push 到了阿里云容器鏡像)啥酱。 上面的 Docker 鏡像基于 debian-base爹凹,并且包含 OpenJDK 8。
該鏡像包括來自 Apache Debian 存儲庫的標(biāo)準(zhǔn) Cassandra 安裝镶殷。 通過使用環(huán)境變量禾酱,您可以更改插入到 cassandra.yaml
中的值。
Environment variable | Default value |
---|---|
CASSANDRA_CLUSTER_NAME | 'Test Cluster' |
CASSANDRA_NUM_TOKENS | 32 |
CASSANDRA_RPC_ADDRESS | 0.0.0.0 |