Kubernetes特色應用: 實作PostgreSQL High Availability (HA) 架構

閱讀時間約 20 分鐘

不管是在什麼時代,對於資訊系統來說,”高可用性”一直都是在建構各種服務時會優先考量的其中一個關鍵要素,特別是現代服務愈來愈複雜、又必須得無時無刻提供客戶使用,所以從前端的應用服務一直到相關的資料庫一般會以高可用的前提之下進行部署設計。

raw-image

本篇將說明如何利用Kubernetes特色,將PostgreSQL DB以HA的架構來提供服務,當然,也說明了相關的實作流程與相關說明。

  1. 基本架構圖
  2. 前置作業
  3. Deployment vs StatefulSet
  4. HA components
  5. Load balancing
  6. 驗證
  7. 結論

1.基本架構圖

raw-image

2. 前置作業

Git repo: https://github.com/scriptcamp/kubernetes-postgresql.git
#------------------------------------------------
# S2-1. create namespace
#------------------------------------------------
[master]# kubectl create namespace database
#------------------------------------------------
# S2-2. 建立configmap,可以在容器內直接掛載檔案
#------------------------------------------------
[master]# vim postgres-configmap.yaml
[master]# kubectl create -f postgres-configmap.yaml -n database
[master]# kubectl get cm

NAME DATA AGE
kube-root-ca.crt 1 29s
postgres-configmap 1 7s

以下是本檔案所執行的內容說明:
* 檔案內的"pre-stop.sh"負責在postgresqldb服務停止前所需要執行的動作
(1) 先檢查目前正在停止中的元件類型(例如master/follower)
(2) 如果master狀態是停止中,則等待到follower被提升至master之後才繼續
(3) 確保HA架構成立(至少有一個master可進行寫入)
#------------------------------------------------
# S2-3. 建立PostgreSQL SVC
# 建立svc提供pod之間的溝通,此處會有2個類型(headless serivce/Service)
#------------------------------------------------
說明:基本上service會以LB(round-robin)的方式做流量負載平衡,而headless則不會,也不會被指派clusterip
為了要建立postgresql server,此處使用headless service的方式,為了之後的PostgreSQL statefulset.

[master]# vim postgres-headless-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: postgres-headless-svc
spec:
type: ClusterIP
clusterIP: None
ports:
- name: postgresql
port: 5432
targetPort: postgresql
protocol: TCP
selector:
app: postgres

[master]# kubectl create -f postgres-headless-svc.yaml
[master]# kubectl get all -n database

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/postgres-headless-svc ClusterIP None <none> 5432/TCP 4s
#------------------------------------------------
# S2-4. 建立PostgreSQL server secret
# 用來存放密碼,如果是正式環境,建議使用其他secret解決方案來進行管理
#------------------------------------------------
[master]# vim postgres-secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: postgres-secrets
spec:
postgresql-password: "root123"
repmgr-password: "root123"

[master]# kubectl create -f postgres-secrets.yaml
[master]# kubectl describe secret postgres-secrets
raw-image

3.Deployment vs StatefulSet

一般來說,部署應用服務時,通常會使用deployment type來實現,但部署資料庫時,因為資料庫會將所有的table , user等資料都存放在volume內,所以會搭配一個持久性儲存,並且為了要讓Pod可以跟據負載擴與Pod重啟後可以取回原本的資料,還要能保持資料的一致性,以下針對二種資源類型的比較:

  • Deployment: 每次Pod在刪除或重建之後名稱都會改變,不適合拿來做Pod識別使用。
  • StatefulSet: 只要Pod取得名稱之後,不管刪除或重建都不會被更改名稱,適合用來做識別Pod使用。並且因為具備順序的特性,也能確保volume可以掛回原本的volume,大部分的Stateful類型的應用都是這種方式

本篇的Pod資料寫入邏輯是先寫到postgres-0 資料會往其他副本同步。

但問題來了:

  • postgres-1要怎麼知道去那邊找到postgres-0?
  • postgres-2要怎麼知道去那邊找到postgres-1?

如果使用StatefulSet類型,因為具備Pod順序關係且Pod名稱不會改變,所以每個Pod都可以依照命名原則找到所需要發現的Pod:

#------------------------------------------------
# S3-1. 建立postgres statefulset
#------------------------------------------------
[master]# vim postgres-statefulset.yaml
[master]# kubectl create -f postgres-statefulset.yaml
[master]# kubectl get all

[說明]
(1) 將metadata以變數的方式注入: 將pod name, pod namespace以環境變數的方式指派給Pod
(2) 將敏感資料以變數的方式注入:例如db password以變數的方式注入到postgres container
(3) Probes: 確保流程不會卡住,如果卡住也會自動進行重啟(此處使用postgres指令來實現)
(4) VolumeClaimTemplate: 讓Statefulset可以正確的建立volume給replica使用
(5) 本lab使用nfs storageclass做data volume
(6) 以下是幾個重要參數:
POSTGRESQL_VOLUME_DIR: Postgres存放設定與資料的目錄,此目錄需要掛載到pvc
PGDATA: 主要的Pg資料目錄
POSTGRES_USER: 安裝過程中自動建立使用者家目錄
POSTGRES_PASSWORD: 預設建立的使用者密碼
POSTGRES_DB: 當主程式啟動後應該自動產生的DB
raw-image

4.HA components

本篇使用RegMgr來負責以下二個任務:

  • Replication: 將資料從Primary server抄寫到其他複本,可以有效降低Server loading並且將讀寫請求分散
  • Failover: 負責處理Cluster內部的容錯切換,例如將其他節點提升到主節點

所有的設定都已在postgres-statefulset.yaml,以下說明幾個重要部分:

  • REPMGR_PARTNER_NODES: 用,做分隔,列出所有主機名稱
  • REPMGR_PRIMARY_HOST: 主Server的名稱
  • REPMGR_USERNAME: 用來執行RegMgr的使用者
  • REPMGR_PASSWORD: 使用者密碼
  • REPMGR_DATABASE: RegMgr所使用的DB

以下取得每個Pod的IP:

#------------------------------------------------
# S4-1. 確認透過headless svc取得的pod ip
#------------------------------------------------
[master]# kubectl get pod -o wide
raw-image

5.Load balancing

此處使用Pgpool以middleware的型式在Postgres server之前,並且作為整個cluster的gatekeeper使用。

主要目的是:Load Balancing & Limiting the requests

  • Load Balancing : pg pool會取得請求與查詢的連線,透過分析這些查詢來決定那些查詢要再繼續傳送
  • 讀的請求傳送給read-only的節點,寫入的請求就只能給primary node,實現load balancing的能力
  • 限制concurrent連線數量
#------------------------------------------------
# S5-1. 建立pgpool secret
#------------------------------------------------
[master]# vim pgpool-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: pgpool-secrets
data:
admin-password: "SFRzaVZxYjdSZQ=="

[master]# kubectl create -f pgpool-secret.yaml
[master]# kubectl get secrets
raw-image
#------------------------------------------------
# S5-2. 建立pgpool svc (只有內部可以存取, 如果外部可以存取就用nodeport)
#------------------------------------------------
[master]# vim pgpool-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: pgpool-svc
spec:
type: ClusterIP
sessionAffinity: None
ports:
- name: postgresql
port: 5432
targetPort: postgresql
protocol: TCP
nodePort: null
selector:
app: pgpool

[master]# kubectl create -f pgpool-svc.yaml

---------

[master]# vim pgpool-svc-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: pgpool-svc-external
spec:
type: NodePort
ports:
- name: postgresql
port: 5432
targetPort: postgresql
protocol: TCP
nodePort: 32000
selector:
app: pgpool

[master]# kubectl create -f pgpool-svc-nodeport.yaml
[master]# kubectl get svc

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/pgpool-svc-external NodePort 10.100.50.5 <none> 5432:32000/TCP 3s
service/postgres-headless-svc ClusterIP None <none> 5432/TCP 23h
#------------------------------------------------
# S5-3. 部署pgpool
#------------------------------------------------
[master]# kubectl create -f pgpool-deployment.yaml
[master]# kubectl get all
raw-image

6.驗證

#------------------------------------------------
# S6-1. 建立client pod
#------------------------------------------------
[master]# vim psql-client.yaml
apiVersion: v1
kind: Pod
metadata:
name: pg-client
spec:
containers:
- image: bitnami/postgresql:11.12.0-debian-10-r13
name: postgresql
env:
- name: ALLOW_EMPTY_PASSWORD
value: "yes"

[master]# kubectl create -f psql-client.yaml
#------------------------------------------------
# S6-2. 取得密碼
#------------------------------------------------
[master]# kubectl get secret postgres-secrets -n database -o jsonpath="{.data.postgresql-password}" | base64 --decode
WbrTpN3g7q
#------------------------------------------------
# S6-3. 執行連線
#------------------------------------------------
[master]# kubectl exec -it pg-client -n database -- /bin/bash
1001@pg-client:/$ PGPASSWORD=WbrTpN3g7q psql -h pgpool-svc -p 5432 -U postgres (inside)
1001@pg-client:/$ PGPASSWORD=WbrTpN3g7q psql -h 10.107.88.16 -p 32000 -U postgres (outside)
psql (11.12)
Type "help" for help.
postgres=#
postgres=# create database db1;
postgres=# \c db1; //to connect to new database
postgres=# create table test (id int primary key not null, value text not null);
postgres=# insert into test values (1, 'value1');
postgres=# select * from test;
raw-image
#------------------------------------------------
# S6-4. 確認資料抄寫
#------------------------------------------------
postgres=# select * from pg_stat_replication;
raw-image
#--------------------------------------------------
# S6-5. 若將Primary刪除後,確認其他follower的狀態
#--------------------------------------------------
[master]# kubectl logs -f postgres-sts-2

[note]
因為statefulset內將primary host訂死在sts-0,如果將sts-0刪除,
RegMgr的同步功能會有問題(會卡在sts-0),可以去編輯statefulset修改REPMGR_PRIMARY_HOST
參數,並刪除sts-0重新建立即可
raw-image
raw-image
raw-image

7.結論

在現代化的架構下,許多應用服務都開始往容器化架構進行移動,如同當初的虛擬化的世界一樣,但因為資料庫非常著重在效能,所以往往都是最後才從獨立的實體機移進新的架構。

本篇實作並說明了資料庫也可以很好的利用容器平台的優勢,實作出傳統實體機上需要另外設定才能實現的功能,未來一定會有愈來愈多的相關應用會移轉至新的平台,但別忘了,資料庫除了可用性很重要之外,對於使用者體驗影響最大的是效能的問題,如果面對大量的查詢,在本篇這種架構之下,可以透過自動生成更多的Pod來回應這些需求,就可以很好的解決這個問題。


References:







15會員
40內容數
記錄IT社畜的自我學習筆記,如同專題名稱,主要是怕自已忘記自已做過什麼、學到什麼。索性就分享我自已在學習Kubernetes這條路上的各種測試、學習心得。
留言0
查看全部
發表第一個留言支持創作者!
超健忘閒人的沙龍 的其他內容
當您在K8S Cluster中使用Harbor作為容器鏡像的儲存庫時,隨著應用服務鏡像的增加,如何透過內建機制將一臺Harbor的內容同步到另一個Harbor就變得愈來愈重要。本文將介紹如何透過內建機制同步Harbor的內容以及支援Harbor同步到其他相容的Image Registry的方式。
本篇將分享關於nginx ingress controller的基本操作,包括預先準備、流程、實際操作、將domain name 映射到Ingress LB IP、部署Demo App 驗證以及結論。
本文將演示在安裝完 Kubernetes Cluster 後的基本元件安裝,包括 Calico/Calicoctl、Metric Server 和 Dashboard UI 的安裝方法以及相關問題與解決方式。
這篇文章教你如何搭建Kubernetes Cluster,包括節點安裝前設定、軟體套件安裝、Control-Plane部署和加入運算節點等步驟。在建置之後,作者會分享一些基礎服務的安裝。希望這篇文章對你有所幫助。
本文章將說明如果您想要從頭建置一組具有Loadbalancer HA架構的Kubernetes Cluster時,你可能會需要做的事前準備工作。
本文將說明在安裝完Kubernetes Cluster之後,接下來必須要進行的CNI Plugin安裝建置方式,同時也透過這篇文章進行基本的CNI說明與比較。 1. Container Network Interface (CNI)
當您在K8S Cluster中使用Harbor作為容器鏡像的儲存庫時,隨著應用服務鏡像的增加,如何透過內建機制將一臺Harbor的內容同步到另一個Harbor就變得愈來愈重要。本文將介紹如何透過內建機制同步Harbor的內容以及支援Harbor同步到其他相容的Image Registry的方式。
本篇將分享關於nginx ingress controller的基本操作,包括預先準備、流程、實際操作、將domain name 映射到Ingress LB IP、部署Demo App 驗證以及結論。
本文將演示在安裝完 Kubernetes Cluster 後的基本元件安裝,包括 Calico/Calicoctl、Metric Server 和 Dashboard UI 的安裝方法以及相關問題與解決方式。
這篇文章教你如何搭建Kubernetes Cluster,包括節點安裝前設定、軟體套件安裝、Control-Plane部署和加入運算節點等步驟。在建置之後,作者會分享一些基礎服務的安裝。希望這篇文章對你有所幫助。
本文章將說明如果您想要從頭建置一組具有Loadbalancer HA架構的Kubernetes Cluster時,你可能會需要做的事前準備工作。
本文將說明在安裝完Kubernetes Cluster之後,接下來必須要進行的CNI Plugin安裝建置方式,同時也透過這篇文章進行基本的CNI說明與比較。 1. Container Network Interface (CNI)
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Thumbnail
引言 在當今的技術世界中,Kubernetes 已成為容器化應用的領導平台。作為一個高效的容器編排系統,它不僅管理著容器的部署和擴展,還提供了必要的自動化支持,以保證應用的高可用性和性能。在這個框架中,自動擴展功能起著至關重要的作用,特別是在面對不斷變化的負載和需求時。
Thumbnail
👨‍💻簡介 在當今的雲計算時代,容器化和微服務架構成為了重要趨勢。Kubernetes,作為領先的容器編排平台,提供了強大的功能來管理和部署應用程式。然而,隨著應用程式和用戶的增加,有效管理誰可以對 Kubernetes 集群執行何種操作變得至關重要。
Thumbnail
在雲端建立AKS後,運行後有許多Container會被外部服務呼叫使用。但我們知道當我們佈署到AKS,如果要被外面服務呼叫,就要在YAML將Type設定成Loadbalance,一旦這樣設定,就會變成每個Container就會多出一個對外的IP,Container變多了,對外IP就會擴增很快,也不好
Thumbnail
宣告式管理是一種管理方法,其中您描述系統或資源的期望狀態,而不必關心實際如何達到該狀態。kubectl apply 命令在 Kubernetes 中實現了這種宣告式管理方式,以下是執行指令時的運作流程...
Thumbnail
Kubernetes 是一個開源的容器管理平台,它可以幫助您自動化容器應用程式的部署、擴展和管理。在 Kubernetes 中,有兩種主要的管理方式:命令式和宣告式。
Thumbnail
在 Kubernetes 裡,Secret 就像是一個保險箱,可以放你任何不想公開的東西。比如說密碼、API 金鑰、憑證等,這樣的資料可能會被放在 Pod 裡,但你可以用 Secret 來避免直接在應用程式的程式碼中暴露這些機密資料。
Thumbnail
什麼是 Kubernetes Deployment? 一樣先來個官網解說 A Deployment provides declarative updates for Pods and ReplicaSets. You describe a desired state in a Deployment,
Thumbnail
什麼是Kubernetes Service? 先來個官網的解說 A Kubernetes Service is an abstraction which defines a logical set of Pods and a policy by which to access them. 白話文就是
Thumbnail
Kubernetes是現代應用程序開發和部署的重要技術,而Pod是Kubernetes中最小的部署單位。Pod是一個或多個container的集合,它們共享一個網路命名空間和一個網路接口。Pod不僅提供了一個簡單而強大的container環境,還可以用於實現多種container編排方案,例如負載平
Autoscaling 的目的是當有大量請求時,系統可以自動的增加運算資源,處理當下的大量請求;也可以根據當下資源使用率低時,自動降低運算資源,達到省錢的目的。
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Thumbnail
引言 在當今的技術世界中,Kubernetes 已成為容器化應用的領導平台。作為一個高效的容器編排系統,它不僅管理著容器的部署和擴展,還提供了必要的自動化支持,以保證應用的高可用性和性能。在這個框架中,自動擴展功能起著至關重要的作用,特別是在面對不斷變化的負載和需求時。
Thumbnail
👨‍💻簡介 在當今的雲計算時代,容器化和微服務架構成為了重要趨勢。Kubernetes,作為領先的容器編排平台,提供了強大的功能來管理和部署應用程式。然而,隨著應用程式和用戶的增加,有效管理誰可以對 Kubernetes 集群執行何種操作變得至關重要。
Thumbnail
在雲端建立AKS後,運行後有許多Container會被外部服務呼叫使用。但我們知道當我們佈署到AKS,如果要被外面服務呼叫,就要在YAML將Type設定成Loadbalance,一旦這樣設定,就會變成每個Container就會多出一個對外的IP,Container變多了,對外IP就會擴增很快,也不好
Thumbnail
宣告式管理是一種管理方法,其中您描述系統或資源的期望狀態,而不必關心實際如何達到該狀態。kubectl apply 命令在 Kubernetes 中實現了這種宣告式管理方式,以下是執行指令時的運作流程...
Thumbnail
Kubernetes 是一個開源的容器管理平台,它可以幫助您自動化容器應用程式的部署、擴展和管理。在 Kubernetes 中,有兩種主要的管理方式:命令式和宣告式。
Thumbnail
在 Kubernetes 裡,Secret 就像是一個保險箱,可以放你任何不想公開的東西。比如說密碼、API 金鑰、憑證等,這樣的資料可能會被放在 Pod 裡,但你可以用 Secret 來避免直接在應用程式的程式碼中暴露這些機密資料。
Thumbnail
什麼是 Kubernetes Deployment? 一樣先來個官網解說 A Deployment provides declarative updates for Pods and ReplicaSets. You describe a desired state in a Deployment,
Thumbnail
什麼是Kubernetes Service? 先來個官網的解說 A Kubernetes Service is an abstraction which defines a logical set of Pods and a policy by which to access them. 白話文就是
Thumbnail
Kubernetes是現代應用程序開發和部署的重要技術,而Pod是Kubernetes中最小的部署單位。Pod是一個或多個container的集合,它們共享一個網路命名空間和一個網路接口。Pod不僅提供了一個簡單而強大的container環境,還可以用於實現多種container編排方案,例如負載平
Autoscaling 的目的是當有大量請求時,系統可以自動的增加運算資源,處理當下的大量請求;也可以根據當下資源使用率低時,自動降低運算資源,達到省錢的目的。