如何在Kubernetes中運行數據庫?
譯文譯者 | 布加迪
審校 | 重樓
關于Kubernetes中數據庫應該在哪里運行的爭論一直是技術界的熱門話題。流行的觀點是“構建無狀態應用程序”,這表明數據庫最適合使用云提供商的托管服務。然而,在Kubernetes中成功地運行數據庫有一些實用的設計模式。
在大多數云提供商中,卷被限制在單個可用區,這意味著數據庫在設計上也被限制在這個可用區。大多數生產集群可能是區域性或多可用區,對于無狀態應用程序而言更是如此。使用節點選擇器確保數據庫pod位于可用區(它們的卷可以掛載)很重要。
例子:
nodeSelector:
topology.kubernetes.io/zone: europe-west6-b
該配置指定數據庫pod應該在' europe-west6-b ' 可用區中運行。
規劃資源使用情況
由于我們的數據庫被限制在一個可用區中,我們必須仔細規劃節點到可用區的設計,以避免調度錯誤和不可用問題。一種有效的策略是針對數據庫工作負載運行單獨的節點組或節點池。這可以確保所需的可用區始終有足夠的資源可用。
例子:
- 為數據庫工作負載創建專用節點池。
- 使用污點和容差來確保在這些節點上只調度數據庫pod。
# Taint nodes to be dedicated to databases
spec:
taints:
- key: "dedicated"
value: "database"
effect: "NoSchedule"
# Toleration in the DB pod spec
spec:
tolerations:
- key: "dedicated"
operator: "Equal"
value: "database"
effect: "NoSchedule"
高可用性
托管數據庫服務通常提供內置的高可用性和故障切換功能。為了在Kubernetes中實現類似的彈性,對恢復和可用性策略進行細致的規劃必不可少。這里有兩種方法:
1.使用Kubernetes操作符
Zalando Postgres Operator這樣的Kubernetes操作符提供了高級功能,比如讀取副本和自動故障切換,類似托管數據庫服務。這些操作符可以顯著簡化數據庫高可用性的設置和管理。
Zalando Postgres Operator允許你指定讀取副本的數量,并自動管理故障切換。該操作符提供了一個UI,你可以在其中配置這些設置,使其成為Kubernetes中管理數據庫高可用性的一種直觀而強大的工具。下面列出了其他一些操作符,其中一些由各自的社區管理:https://operatorhub.io/?category=Database。
2.自助服務方法
對于那些喜歡動手操作的人而言,特別是針對NoSQL數據庫,這里有一個循序漸進的方法:
- 兩個pod上掛載數據卷:確保數據卷被主pod和從pod都可以訪問。
- pod親緣性:使用pod親緣性規則來確保主pod和從pod放在一起,同時尊重卷約束。
- Init容器:在啟動時,使用從pod中的Init容器從主pod拷貝所有數據。
- 卷掛載約束:將從pod上的卷掛載設置為只讀,以防止數據損壞。
- 使用計劃任務(cronjob)進行重啟:創建一個簡單的計劃任務,每六個小時刪除舊的pod,允許init容器運行并拷貝新數據。
示例配置
下面的例子展示了如何使用pod親緣性關聯設置Neo4j讀取副本、用于數據拷貝的init容器以及掛載存在只讀約束的卷以確保數據完整性。
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- primary-db
topologyKey: "kubernetes.io/hostname"
initContainers:
- name: copy-data
image: busybox
command: ["sh", "-c", "cp -r /data/* /backup/"]
volumeMounts:
- name: data-volume
mountPath: /data
- name: backup-volume
mountPath: /backup
volumes:
- name: data-volume
persistentVolumeClaim:
claimName: primary-db-pvc
- name: backup-volume
persistentVolumeClaim:
claimName: secondary-db-pvc
containers:
- name: secondary-db
image: neo4j:latest
volumeMounts:
- name: backup-volume
mountPath: /data
readOnly: true
備份和恢復
許多服務提供商提供了在基于磁盤的卷上調度重復快照的方法。這通常是首選的方法,因為它更容易設置,并且恢復過程更快。在這種情況下,我們可以定期備份托管數據庫數據的卷。
另一種方法是結合數據庫的專有工具,比如PostgreSQL的pg_dump。
下面是一個使用Kubernetes計劃任務將PostgreSQL配置備份到s3的示例:
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: postgres-backup
spec:
schedule: "0 0 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: postgres
command: ["sh", "-c", "pg_dumpall -c -U $PGUSER | gzip > /backup/db_backup.gz && aws s3 cp /backup/db_backup.gz s3://your-bucket/db-backup-$(date +\%F).gz"]
volumeMounts:
- name: backup-volume
mountPath: /backup
restartPolicy: OnFailure
volumes:
- name: backup-volume
emptyDir: {}
結語
盡管初始設置或學習曲線可能很陡峭,但在Kubernetes中運行數據庫具有很多優勢。一個不太被提及的好處是成本。在RDS中運行db.m4.2xlarge(4vCPU和32GB內存)實例的成本大約是1200美元/月,而運行一個類似大小的EC2實例的成本大約是150美元/月。Kubernetes中的節點還可能運行多個pod,從而進一步優化資源使用。
與廠商無關是促使許多人在Kubernetes中運行數據庫的另一個主要動機。以最小的調整在任何平臺上移動工作負載極具吸引力。
總之,在決定在何處運行生產數據庫之前,請考慮利弊。許多人成功地在Kubernetes中運行數據庫,這類部署的數量在與日俱增。
原文標題:How To Run Databases in Kubernetes,作者:Kolawole Olowoporoku