大家好,我是小碗湯,今天分享一篇搭建一個高可用鏡像倉庫的教程。詳細中夾雜著簡單~。篇幅較長,兄弟們不妨耐心看完~
Harbor 部署架構圖harbor 使用 helm 部署在 k8s 集群中,通過 ingress-nginx 代理。pgsql 採用 Pgpool-II 代理,做主從切換、通過同步流式複製進行數據複製,客戶端請求通過 Pgpool-II 路由。這裡假設示例主機信息如下
版本信息harbor-helm 1.5.0 chart 包自帶的 harbor 版本為 2.1.0
redisRedis 為哨兵模式,架構圖如下:
Redis 實例拓撲分布:
至於 Redis 集群在虛擬機上的部署,我使用的是Cymbal 項目[1]
Cymbal 秉承開箱即用的原則,整個部署過程十分簡單,最小化版本只需要一個 runnable jar 及 mysql 服務的支持即可。
Cymbal 是當當網架構部孵化並開源的 Redis PaaS 平臺,基於 Spring Boot2 開發。目標是幫助技術團隊以簡單,低成本的方式管理大規模 Redis 集群。目前當當網內部使用 Cymbal 管理的 Redis 實例數量達到 1000+。
Cymbal 採用 DevOps 的設計思想,以多租戶的方式,最大程度上賦予開發人員運維權限,從而加快團隊運轉。同時,Cymbal 上面集成了豐富的運維功能:從監控、報警到在線擴縮容等,力求最大程度上消除運維門檻。
假設用 Cymbal 部署之後 redis 哨兵信息如下:172.0.0.1:9381,172.0.0.2:9381,172.0.0.3:9381
哨兵 Master 為: mymaster-EC4Fy7DJ
密碼為: harborpwd
下面會用到這些信息。
Pgsql基於 PGpool 中間件實現 postgresql 一主一從集群部署,架構圖實例如下:
PGPool、Pgsql 實例拓撲分布:
Pgpool 在 k8s 集群中多實例部署,Pgsql 主從實例在虛擬機中用 docker 容器啟動。
docker 部署 pgsql在虛擬機上直接部署 pgsql 集群在時間成本上,還是不太容易的。我們這裡使用 docker 去管理,會輕鬆一點。
創建 volume,由於複製管理器映像的 PostgreSQL 是非 root 用戶,因此您還需要為主機中的掛載目錄設置適當的權限:
# 主實例
# docker volume create pg-0
# chgrp -R root /var/lib/docker/volumes/pg-0
# chmod -R g+rwX /var/lib/docker/volumes/pg-0
# 從實例
# docker volume create pg-1
# chgrp -R root /var/lib/docker/volumes/pg-1
# chmod -R g+rwX /var/lib/docker/volumes/pg-1我們這裡將主從部署在不同的主機上,所以兩組命令應該在兩臺主機上執行。從而保證不同時掛掉。
啟動 pgsql 實例的腳本:
#!/bin/bash
set -o errexit
node=$1
if [[ -z "${node}" ]]; then
echo "Error: need node argument, example: pg-0"
exit -1
fi
existUp=$(docker ps -f name=${node} -q)
if [[ -n "${existUp}" ]]; then
# nothing
echo "node: ${node} is Up"
exit 0
fi
existNotUp=$(docker ps -a -f name=${node} -q)
if [[ -n "${existNotUp}" ]]; then
# start
echo "node: ${node} is not Up, will start it"
docker start ${existNotUp}
exit 0
fi
# create
docker run --detach --name ${node} \
--network host \
--env REPMGR_PARTNER_NODES=pg-0,pg-1 \
--env REPMGR_NODE_NAME=${node} \
--env REPMGR_NODE_NETWORK_NAME=${node} \
--env REPMGR_PRIMARY_HOST=${node} \
--env REPMGR_USERNAME=repmgrharbor \
--env REPMGR_PASSWORD=repmgrpwd \
--env POSTGRESQL_POSTGRES_PASSWORD=pgpwd \
--env POSTGRESQL_USERNAME=pgharbor \
--env POSTGRESQL_PASSWORD=pgpwd \
--env POSTGRESQL_DATABASE=pgharbor \
--env BITNAMI_DEBUG=true \
--env TZ=Asia/Shanghai \
-v ${node}:/bitnami/postgresql \
-v /neworiental/pgsql/custom-conf/:/bitnami/repmgr/conf/ \
bitnami/postgresql-repmgr:9.6.16啟動時,用:
# start-pg.sh {容器名}容器名為 pg-0(主)或者 pg-1(從)。
pgsql 掛掉自啟動docker 容器掛掉後,用 crontab 保證容器可以重新啟動,30s 為間隔去執行 start-pg.sh 腳本。
執行 crontab -e 在最後新增以下內容,然後:wq 保存退出即可:
# Need these to run on 30-sec boundaries, keep commands in sync.
* * * * * /pgsql/start-pg.sh pg-1
* * * * * ( sleep 30 ; /pgsql/start-pg.sh pg-1 )
創建 PgpoolapiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/component: pgpool
app.kubernetes.io/instance: pgsql
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: postgresql-ha-doc
helm.sh/chart: postgresql-ha-8.0.2
name: pgpool-for-docker-dp-pgsql
namespace: harbor
spec:
progressDeadlineSeconds: 600
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
app.kubernetes.io/component: pgpool
app.kubernetes.io/instance: pgsql
app.kubernetes.io/name: postgresql-ha-doc
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app.kubernetes.io/component: pgpool
app.kubernetes.io/instance: pgsql
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: postgresql-ha-doc
helm.sh/chart: postgresql-ha-8.0.2
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
app.kubernetes.io/component: pgpool
app.kubernetes.io/instance: pgsql
containers:
- env:
- name: BITNAMI_DEBUG
value: "false"
- name: PGPOOL_BACKEND_NODES
value: 0:172.0.0.1:5432,1:172.0.0.2:5432,
- name: PGPOOL_SR_CHECK_USER
value: repmgrharbor
- name: PGPOOL_SR_CHECK_PASSWORD
value: repmgrpwd
- name: PGPOOL_SR_CHECK_DATABASE
value: postgres
- name: PGPOOL_ENABLE_LDAP
value: "no"
- name: PGPOOL_POSTGRES_USERNAME
value: pgharbor
- name: PGPOOL_POSTGRES_PASSWORD
value: pgpwd
- name: PGPOOL_ADMIN_USERNAME
value: pgpooladmin
- name: PGPOOL_ADMIN_PASSWORD
value: pgpoolpwd
- name: PGPOOL_ENABLE_LOAD_BALANCING
value: "yes"
- name: PGPOOL_DISABLE_LOAD_BALANCE_ON_WRITE
value: transaction
- name: PGPOOL_ENABLE_LOG_CONNECTIONS
value: "no"
- name: PGPOOL_ENABLE_LOG_HOSTNAME
value: "yes"
- name: PGPOOL_ENABLE_LOG_PER_NODE_STATEMENT
value: "no"
- name: PGPOOL_CHILD_LIFE_TIME
- name: PGPOOL_ENABLE_TLS
value: "no"
image: docker.io/bitnami/pgpool:4.2.6-debian-10-r7
imagePullPolicy: IfNotPresent
livenessProbe:
exec:
command:
- /opt/bitnami/scripts/pgpool/healthcheck.sh
failureThreshold: 5
initialDelaySeconds: 30
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
name: pgpool
ports:
- containerPort: 5432
name: postgresql
protocol: TCP
readinessProbe:
exec:
command:
- bash
- -ec
- PGPASSWORD=${PGPOOL_POSTGRES_PASSWORD} psql -U "pgharbor" -d "pgharbor"
-h /opt/bitnami/pgpool/tmp -tA -c "SELECT 1" >/dev/null
failureThreshold: 5
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 5
resources: {}
securityContext:
runAsUser: 1001
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext:
fsGroup: 1001
terminationGracePeriodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/component: pgpool
app.kubernetes.io/instance: pgsql
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: postgresql-ha-doc
helm.sh/chart: postgresql-ha-8.0.2
name: pgpool-for-docker-dp-pgsql
namespace: harbor
spec:
ports:
- name: postgresql
port: 5432
protocol: TCP
targetPort: postgresql
selector:
app.kubernetes.io/component: pgpool
app.kubernetes.io/instance: pgsql
app.kubernetes.io/name: postgresql-ha-doc
sessionAffinity: None
type: ClusterIP直接kubectl apply以上 yaml 即可。
連接 pgsql 手動創庫harbor 對接外部 pgsql 時,需要提前創建庫,所以手動創建以下四個 database(一般 DBA 來做這件事), 可以直接連接 pgsql 主實例,也可以通過 Pgpool 連接:
# PGPASSWORD=pgpwd psql -h localhost -p 5432 -U pgharbor -d pgharbor
pgharbor=> CREATE DATABASE registry ENCODING 'UTF8';
pgharbor=> CREATE DATABASE notary_signer ENCODING 'UTF8';
pgharbor=> CREATE DATABASE notary_server ENCODING 'UTF8';
pgharbor=> CREATE DATABASE clair ENCODING 'UTF8';
harbor 物料harbor-helm 倉庫[2]
部署 harbor下載 harbor-helm 包:
# wget https://github.com/goharbor/harbor-helm/archive/refs/tags/v1.5.0.tar.gz
# tar -zxf v1.5.0.tar.gz
# cd harbor-helm-1.5.0
# 創建ns
kubectl create ns harbor創建域名證書 Secret,這裡需要用到你的域名證書。
kubectl create secret tls harbor-ingress -n harbor --cert=./product.cn.pem --key=./product.cn.key如果沒有域名證書,也可以使用自動生成證書,下面會講到。
修改 values.yaml 中以下內容:
expose:
type: ingress
tls:
enabled: true
certSource: secret
secret:
# The name of secret which contains keys named:
# "tls.crt" - the certificate
# "tls.key" - the private key
secretName: "harbor-ingress"
ingress:
hosts:
core: harbor-pro.kubeinfo.cn
controller: default
annotations:
ingress.kubernetes.io/ssl-redirect: "true"
ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "0"
# If Harbor is deployed behind the proxy, set it as the URL of proxy
externalURL: https://harbor-pro.kubeinfo.cn
# The initial password of Harbor admin. Change it from portal after launching Harbor
harborAdminPassword: "Harbor678901"
persistence:
enabled: true
resourcePolicy: "keep"
persistentVolumeClaim:
registry:
storageClass: "cephfs"
accessMode: ReadWriteMany
size: 200Gi
notary:
enabled: false
database:
# if external database is used, set "type" to "external"
# and fill the connection informations in "external" section
type: external
external:
host: "pgpool-for-docker-dp-pgsql.harbor.svc.cluster.local"
port: "5432"
username: "pgharbor"
password: "pgpwd"
maxOpenConns: 1000
redis:
# if external Redis is used, set "type" to "external"
# and fill the connection informations in "external" section
type: external
external:
# support redis, redis+sentinel
# addr for redis: <host_redis>:<port_redis>
# addr for redis+sentinel: <host_sentinel1>:<port_sentinel1>,<host_sentinel2>:<port_sentinel2>,<host_sentinel3>:<port_sentinel3>
addr: "172.0.0.1:9381,172.0.0.2:9381,172.0.0.3:9381"
# The name of the set of Redis instances to monitor, it must be set to support redis+sentinel
sentinelMasterSet: "mymaster-EC4Fy7DJ"
password: "harborpwd"
values.yaml 中的域名修改為自己的域名,這裡用到的是 harbor-pro.kubeinfo.cnexpose.tls.certSource 可以為 auto,即 chart 包會自動生成證書,我們這裡用 secret域名對應的證書 secret 名,這裡為 harbor-ingress,即上面創建的外部 pgsql 信息,這裡連接到集群內 pgpool 的域名storageClass 這裡用 Rook 部署的 ceph 集群的文件存儲,修改為 cephfs安裝 harborhelm install pro -n harbor -f values.yaml .正常情況,一段時間後,harbor 會啟動成功,我們訪問harbor 域名[3]即可看到 harbor 的界面。
升級如果修改了 values.yaml 後,執行升級:
helm upgrade pro -n harbor -f values.yaml .
卸載helm uninstall pro -n harbor
原文本文首發於微信公眾號【我的小碗湯】,歡迎掃文末二維碼關注~
參考資料[1]Cymbal 項目: https://github.com/dangdangdotcom/cymbal
[2]harbor-helm 倉庫: https://github.com/goharbor/harbor-helm
[3]harbor 域名: https://harbor-pro.kubeinfo.cn
推薦閱讀
真快!10秒內將k8s集群運行起來
這款工具,幫你輕鬆用手機管理 K8S 集群
6個工具助你在Windows上輕鬆運行Kubernetes
當年加入相互「保」,現在相互「寶」涼了!交的錢都白交了?
5 個必備的命令行工具,效率飛起
極簡工具 | MacOS上運行容器和k8s | 支持M1
目前MacOS上,管理容器和k8s可選擇的產品有哪些?
一款k8s實時錯誤監控工具,值得用起來
Docker容器如何優雅使用NVIDIA GPU
頂級工具 | Popeye幫你發現k8s集群潛在問題
Web自動化神器,批量下載小姐姐美圖,可直接導入使用
點讚👍 星標✨ 在看 👁 讓我看見你們!!
本公眾號主要分享linux、Golang、網絡、雲原生相關技術,實用工具,歡迎掃碼關注!