本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

使用 StatefulSets 部署 PostgreSQL 叢集

編者按:今天的客座文章由 Crunchy Data 的開發者 Jeff McCormick 撰寫,展示瞭如何使用新的 Kubernetes StatefulSet 功能構建 PostgreSQL 叢集。

在早先的一篇文章中,我介紹瞭如何使用 Kubernetes 包管理器 Helm 部署 PostgreSQL 叢集。以下示例提供了使用新的 Kubernetes StatefulSets 功能構建 PostgreSQL 叢集的步驟。

StatefulSets 示例

步驟 1 - 建立 Kubernetes 環境

StatefulSets 是 Kubernetes 1.5 中實現的新功能(早期版本中被稱為 PetSets)。因此,執行此示例需要基於 Kubernetes 1.5.0 或更高版本的環境。

本部落格中的示例使用 kubeadm 部署在 Centos7 上。有關 kubeadm 提供什麼以及如何部署 Kubernetes 叢集的一些說明位於此處

步驟 2 - 安裝 NFS

本部落格中的示例使用 NFS 作為持久卷,但任何共享檔案系統(例如:ceph、gluster)也都可以。

示例指令碼假設您的 NFS 伺服器在本地執行,並且您的主機名解析為已知 IP 地址。

總而言之,在 Centos 7 主機上使 NFS 正常工作的步驟如下:

sudo setsebool -P virt\_use\_nfs 1

sudo yum -y install nfs-utils libnfsidmap

sudo systemctl enable rpcbind nfs-server

sudo systemctl start rpcbind nfs-server rpc-statd nfs-idmapd

sudo mkdir /nfsfileshare

sudo chmod 777 /nfsfileshare/

sudo vi /etc/exports

sudo exportfs -r

/etc/exports 檔案應包含類似於以下內容的行,但需要指定適用的 IP 地址:

/nfsfileshare 192.168.122.9(rw,sync)

完成這些步驟後,NFS 應該在測試環境中執行。

步驟 3 - 克隆 Crunchy PostgreSQL 容器套件

本部落格中使用的示例可以在 Crunchy Containers GitHub 倉庫此處找到。將 Crunchy Containers 倉庫克隆到您的測試 Kubernetes 主機,然後轉到示例:

cd $HOME

git clone https://github.com/CrunchyData/crunchy-containers.git

cd crunchy-containers/examples/kube/statefulset

接下來,拉取 Crunchy PostgreSQL 容器映象:

docker pull crunchydata/crunchy-postgres:centos7-9.5-1.2.6

步驟 4 - 執行示例

首先,需要設定示例中使用的幾個環境變數:

export BUILDBASE=$HOME/crunchy-containers

export CCP\_IMAGE\_TAG=centos7-9.5-1.2.6

BUILDBASE 是您克隆倉庫的位置,CCP_IMAGE_TAG 是我們想要使用的容器映象版本。

接下來,執行示例:

./run.sh

該指令碼將建立幾個 Kubernetes 物件,包括:

  • 持久卷 (pv1, pv2, pv3)
  • 持久卷宣告 (pgset-pvc)
  • 服務賬戶 (pgset-sa)
  • 服務 (pgset, pgset-master, pgset-replica)
  • StatefulSet (pgset)
  • Pod (pgset-0, pgset-1)

此時,Kubernetes 環境中將執行兩個 Pod。

$ kubectl get pod

NAME      READY     STATUS    RESTARTS   AGE

pgset-0   1/1       Running   0          2m

pgset-1   1/1       Running   1          2m

建立 Pod 後,部署將如下所示:

步驟 5 - 發生了什麼?

此示例將部署一個 StatefulSet,它將建立兩個 Pod。

這兩個 Pod 中的容器執行 PostgreSQL 資料庫。對於 PostgreSQL 叢集,我們需要一個容器充當主資料庫,其他容器充當副本資料庫。

那麼,容器如何確定哪個是主資料庫,哪個是副本資料庫呢?

這就是新的 StatefulSet 機制發揮作用的地方。StatefulSet 機制為集合中的每個 Pod 分配一個唯一的序號值。

StatefulSet 提供的唯一序號值始終從 0 開始。在容器初始化期間,每個容器檢查其分配的序號值。序號值為 0 會導致容器在 PostgreSQL 叢集中充當主角色。對於所有其他序號值,容器充當副本角色。這是一種非常簡單的發現形式,由 StatefulSet 機制實現。

PostgreSQL 副本配置為透過專用於主資料庫的服務連線到主資料庫。為了支援這種複製,示例為主角色和副本角色分別建立了一個單獨的服務。一旦副本連線成功,副本將開始從主資料庫複製狀態。

在容器初始化期間,主容器將使用 服務帳戶 (pgset-sa) 更改其容器標籤值,使其與主服務選擇器匹配。更改標籤對於使流向主資料庫的流量能夠到達 Stateful Set 中正確的容器非常重要。集合中的所有其他 Pod 預設假定為副本服務標籤。

步驟 6 - 部署圖

該示例的部署結果如下所示:

在此部署中,有一個用於主資料庫的服務和一個單獨用於副本資料庫的服務。副本已連線到主資料庫,並且狀態複製已開始。

Crunchy PostgreSQL 容器支援其他形式的叢集部署,部署樣式由設定容器的 PG_MODE 環境變數決定。在 StatefulSet 部署的情況下,該值設定為:PG_MODE=set

這個環境變數是容器初始化邏輯關於我們預期部署風格的提示。

步驟 7 - 測試示例

以下測試假設測試系統上已安裝 psql 客戶端。如果之前未安裝 psql 客戶端,則可以按如下方式安裝:

sudo yum -y install postgresql

此外,以下測試假設測試環境的 DNS 解析為 Kube DNS,並且測試環境的 DNS 搜尋路徑已指定為與適用的 Kube 名稱空間和域匹配。主服務名為 pgset-master,副本服務名為 pgset-replica。

按如下方式測試主節點(密碼為 password):

psql -h pgset-master -U postgres postgres -c 'table pg\_stat\_replication'

如果一切正常,上述命令將返回輸出,指示單個副本正在連線到主節點。

接下來,按如下方式測試副本:

psql -h pgset-replica -U postgres postgres  -c 'create table foo (id int)'

上述命令應該會失敗,因為副本在 PostgreSQL 叢集中是**只讀**的。

接下來,按如下方式擴充套件集合:

kubectl scale statefulset pgset --replicas=3

上述命令應該成功建立一個名為 **pgset-2** 的新副本 Pod,如下圖所示:

步驟 8 - 永續性解釋

檢視生成的 NFS 掛載路徑上的持久化 PostgreSQL 資料檔案:

$ ls -l /nfsfileshare/

total 12

drwx------ 20   26   26 4096 Jan 17 16:35 pgset-0

drwx------ 20   26   26 4096 Jan 17 16:35 pgset-1

drwx------ 20   26   26 4096 Jan 17 16:48 pgset-2

StatefulSet 中的每個容器都繫結到示例指令碼中建立的單個 NFS 持久卷宣告 (pgset-pvc)。

由於 NFS 和 PVC 可以共享,因此每個 Pod 都可以寫入此 NFS 路徑。

容器被設計為在該路徑上使用 Pod 主機名建立子目錄以實現唯一性。

結論

StatefulSets 是 Kubernetes 為正在實現叢集的容器構建者新增的一個激動人心的功能。為集合分配的序號值提供了一種非常簡單的機制,用於在部署 PostgreSQL 叢集時做出叢集決策。