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

使用 StatefulSets 部署 PostgreSQL 叢集

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

在先前的文章中,我描述了如何使用 Helm(Kubernetes 套件管理器)部署 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 儲存庫克隆到您的測試 Kubernertes 主機,然後轉到範例

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)

此時,兩個 Pod 將在 Kubernetes 環境中運行

$ 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 叢集,我們需要其中一個容器擔任主節點角色,而另一個容器擔任複本節點角色。

那麼,容器如何確定誰將成為主節點,誰將成為複本節點呢?

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

StatefulSets 提供的唯一序號值始終從 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

stateful set 中的每個容器都綁定到範例腳本中建立的單個 NFS 持久卷聲明 (pgset-pvc)。

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

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

結論

對於正在實作叢集化的容器建構者來說,StatefulSets 是 Kubernetes 中新增的令人興奮的功能。分配給集合的序號值提供了一種非常簡單的機制,可在部署 PostgreSQL 叢集時做出叢集決策。