在一個四節點的Docker Swarm集羣上,嘗試使用Ceph做爲Docker集羣的共享存儲,解決有狀態服務在分佈式環境下的數據存儲問題。html
通過嘗試,成功使用CephFS實現了多個Docker節點之間的存儲共享。但同時注意到,對於小規模Docker集羣而且運維成本有限的場景,Ceph這樣的分佈式對象存儲系統仍然顯得有點重了,本文的4節點docker swarm集羣上,在Ceph集羣與Portainer-Agent(docker運維工具)部署以後,容器數量達到了30個。所以最終決定採用其餘方案實現小規模docker集羣的共享存儲,好比NFS。node
但Ceph做爲一個高可用高性能的分佈式對象/塊/文件存儲系統,在其餘場景仍是有使用價值的。python
本文主要記述Ceph的搭建過程以及如何用cephfs實現docker swarm集羣的共享存儲。其餘諸如原理機制,運維資料等請參考社區文檔。linux
Ceph對外提供了三種存儲接口,分別是對象存儲 RGW(rados gateway)、塊存儲 RBD(rados block device) 和文件存儲 CephFS。RGW是RestAPI,docker的數據卷沒法直接使用。從性能角度考慮,應該是RBD最快,但本文使用的Ceph版本與使用RBD作共享存儲所須要的中間件RexRay貌似存在版本不兼容問題,最終沒能成功。。。git
最終本文使用了CephFS來實現docker swarm集羣的共享存儲。github
本文搭建Ceph使用了目前社區文檔推薦的安裝工具cephadm
,安裝的版本爲octopus
。四個節點的操做系統均爲CentOS7
。docker
https://docs.ceph.com/docs/master/
http://docs.ceph.org.cn/
注意,編寫本文時,中文社區文檔並不是最新版本,好比社區文檔中目前建議使用的安裝工具
cephadm
在中文社區文檔中就沒有相關資料。
No | ip | hostname | OSD盤 | Ceph角色 |
---|---|---|---|---|
1 | 172.17.13.1 | manager01.xxx.com | /dev/sdb | mon,osd,ceph-mds,mgr |
2 | 172.17.13.2 | manager02.xxx.com | /dev/sdb | mon,osd,ceph-mds |
3 | 172.17.13.3 | worker01.xxx.com | /dev/sdb | mon,osd,ceph-mds |
4 | 172.17.13.4 | worker02.xxx.com | /dev/sdb | mon,osd,ceph-mds,mgr,cephadm,NTP服務器 |
Ceph用於存儲數據的服務OSD須要使用乾淨的磁盤,要求以下:shell
- 設備沒有分區
- 設備不得具備任何LVM狀態
- 設備沒有掛載
- 設備不包含任何文件系統
- 設備不包含ceph bluestore osd
- 設備必須大於5G
也就是給節點增長一塊新磁盤以後,只要linux能識別到便可,不要作分區/格式化/mount等操做。json
提早將Ceph相關防火牆規則設置好。或直接關閉防火牆。bootstrap
firewall-cmd --permanent --zone=public --add-service=http firewall-cmd --permanent --zone=public --add-service=https firewall-cmd --permanent --zone=public --add-service=ceph firewall-cmd --permanent --zone=public --add-service=ceph-mon firewall-cmd --reload firewall-cmd --zone=public --list-services firewall-cmd --zone=public --add-port=3300/tcp --permanent firewall-cmd --zone=public --add-port=3300/udp --permanent firewall-cmd --zone=public --add-port=6789/tcp --permanent firewall-cmd --zone=public --add-port=6800-7300/tcp --permanent firewall-cmd --zone=public --add-port=8443/tcp --permanent firewall-cmd --reload firewall-cmd --zone=public --list-ports
Ceph集羣在使用中最好禁用Selinux。在各個節點上以root用戶vi /etc/selinux/config
,修改:
#SELINUX=enforcing SELINUX=disabled
而後執行setenforce 0
從阿里雲鏡像獲取/etc/yum.repos.d/epel.repo
,以下:
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
填坑的過程當中嘗試過不一樣的搭建方案,這裏有些依賴庫可能不是必須的。。。
yum -y install python3 yum-utils yum install yum-plugin-priorities -y yum install gcc python-setuptools python-devel -y easy_install pip
本文的環境已經提早安裝了docker ce,docker compose,並建立了docker swarm集羣。
每一個節點都須要先安裝好Docker,具體方法參考官方文檔:https://docs.docker.com/engine/install/centos/
。
注意最好使用國內的dokcer安裝yum鏡像。
yum-config-manager \ --add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
安裝完成以後,添加docker鏡像倉庫地址,vi /etc/docker/daemon.json
,添加:
"registry-mirrors": [ "https://docker.mirrors.ustc.edu.cn", "https://dockerhub.azk8s.cn", "https://reg-mirror.qiniu.com", "https://hub-mirror.c.163.com", "https://mirror.ccs.tencentyun.com", "https://registry.docker-cn.com" ],
而後重啓docker服務:
systemctl daemon-reload systemctl restart docker
而後提早爲每一個節點拉取Ceph相關鏡像:
docker pull ceph/ceph:v15 docker pull ceph/ceph-grafana docker pull prom/prometheus:v2.18.1 docker pull prom/alertmanager:v0.20.0 docker pull prom/node-exporter:v0.18.1
各節點安裝ntp服務
yum install ntp ntpdate ntp-doc -y
在管理節點worker02.xxx.com
上安裝ntp服務,vi /etc/ntp.conf
:
... restrict 127.0.0.1 restrict ::1 restrict 172.17.13.0 mask 255.255.255.0 # Hosts on local network are less restricted. #restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap # Use public servers from the pool.ntp.org project. # Please consider joining the pool (http://www.pool.ntp.org/join.html). #server 0.centos.pool.ntp.org iburst #server 1.centos.pool.ntp.org iburst #server 2.centos.pool.ntp.org iburst #server 3.centos.pool.ntp.org iburst server 127.127.1.0 ...
配置了NTP服務的管理節點須要防火牆配置端口:
firewall-cmd --zone=public --add-port=123/udp --permanent firewall-cmd --reload firewall-cmd --zone=public --list-ports
在其餘節點設置ntp服務器爲剛剛設定的ntp服務器,vi /etc/ntp.conf
:
… # Use public servers from the pool.ntp.org project. # Please consider joining the pool (http://www.pool.ntp.org/join.html). server worker02.xxx.com #server 0.centos.pool.ntp.org iburst #server 1.centos.pool.ntp.org iburst #server 2.centos.pool.ntp.org iburst #server 3.centos.pool.ntp.org iburst …
重啓各個節點的ntp服務,並設置開機啓動:
systemctl enable ntpd systemctl restart ntpd systemctl status ntpd # Centos7默認安裝了chronyd而且默認enable,這裏須要關閉,不然重啓之後會致使ntpd不能啓動 systemctl disable chronyd
管理節點從外網同步時間,其餘節點從管理節點同步時間:
# 管理節點 ntpdate -u ntp1.aliyun.com # 其餘節點 ntpdate -u worker02.xxx.com
各節點默認已安裝,能夠更新最新版本,並確認服務狀態
yum install openssh-server -y service sshd status
在每一個節點以root身份vi /etc/hosts
,添加:
172.17.13.1 manager01 172.17.13.2 manager02 172.17.13.3 worker01 172.17.13.4 worker02
Ceph默認使用短域名,社區文檔在環境檢查中要求能以短域名ping通,但本文環境都是用的FQDN,這裏即便設置短域名到hosts文件,後續依然有些許小問題。
如下操做均在cephadm節點上執行。(本文規劃將worker02.xxx.com
做爲cephadm節點)
cd ~ mkdir cephadmin cd cephadmin curl --silent --remote-name --location https://hub.fastgit.org/ceph/ceph/raw/octopus/src/cephadm/cephadm chmod +x cephadm ll -h
官方地址
https://github.com/ceph/ceph/raw/octopus/src/cephadm/cephadm
老是下載失敗,所以使用了國內某鏡像地址。
如下操做均在cephadm節點上執行。
生成ceph的yum源文件並將其替換爲使用阿里雲yum源:
./cephadm add-repo --release octopus cat /etc/yum.repos.d/ceph.repo sed -i 's#download.ceph.com#mirrors.aliyun.com/ceph#' /etc/yum.repos.d/ceph.repo cat /etc/yum.repos.d/ceph.repo yum list | grep ceph
注意版本是
octopus
安裝cephadm:
./cephadm install which cephadm
引導ceph集羣:
mkdir -p /etc/ceph cephadm bootstrap --mon-ip 172.17.13.4 --allow-fqdn-hostname
成功後會出現以下信息:
... INFO:cephadm:Ceph Dashboard is now available at: URL: https://worker02.xxx.com:8443/ User: admin Password: 3y44vf60ms INFO:cephadm:You can access the Ceph CLI with: sudo /usr/sbin/cephadm shell --fsid fbd10774-c8cf-11ea-8bcc-00505683571d -c /etc/ceph/ceph.conf -k /etc/ceph/ceph.client.admin.keyring INFO:cephadm:Please consider enabling telemetry to help improve Ceph: ceph telemetry on For more information see: https://docs.ceph.com/docs/master/mgr/telemetry/ INFO:cephadm:Bootstrap complete.
嘗試登陸Ceph CLI:
[root@worker02 ~]# cephadm shell --fsid fbd10774-c8cf-11ea-8bcc-00505683571d -c /etc/ceph/ceph.conf -k /etc/ceph/ceph.client.admin.keyring INFO:cephadm:Using recent ceph image ceph/ceph:v15 [ceph: root@worker02 /]# exit exit
在瀏覽器中訪問https://worker02.xxx.com:8443/
,打開 ceph ui, 第一次登錄要求更改默認密碼
域名訪問前先配置瀏覽器所在節點的hosts文件
如下操做均在cephadm節點上執行。
安裝 ceph 工具包, 其中包括 ceph, rbd, mount.ceph 等命令:
cephadm install ceph-common
驗證集羣狀態:
# 查看 ceph 集羣全部組件運行狀態 ceph orch ps # 查看指定組件運行狀態 ceph orch ps --daemon-type mon # 查看集羣當前狀態 ceph status ceph -s
將以前cephadm bootstrap初始化集羣命令所生成的ceph密鑰拷貝到其餘節點root用戶的"~/.ssh"目錄。注意要輸入其餘節點root用戶密碼。
ssh-copy-id -f -i /etc/ceph/ceph.pub root@manager01.xxx.com ssh-copy-id -f -i /etc/ceph/ceph.pub root@manager02.xxx.com ssh-copy-id -f -i /etc/ceph/ceph.pub root@worker01.xxx.com
將其餘節點加入集羣
ceph orch host add manager01.xxx.com ceph orch host add manager02.xxx.com ceph orch host add worker01.xxx.com ceph orch host ls
查看集羣當前服務分佈(此時應該有4個crash,4個mon,兩個mgr)
ceph orch ps
檢查每一個節點是否有一塊還沒有分區的新磁盤,例如這裏的sdb
:
[root@worker01 ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT fd0 2:0 1 4K 0 disk sda 8:0 0 300G 0 disk ├─sda1 8:1 0 500M 0 part /boot └─sda2 8:2 0 299.5G 0 part ├─centos-root 253:0 0 295.5G 0 lvm / └─centos-swap 253:1 0 4G 0 lvm [SWAP] sdb 8:16 0 300G 0 disk sr0 11:0 1 1024M 0 rom
對於虛擬機,在虛擬機控制檯直接給運行中的虛擬機添加新磁盤以後,每一個節點執行如下命令就能夠刷出磁盤信息,不用重啓:
echo "- - -" > /sys/class/scsi_host/host0/scan echo "- - -" > /sys/class/scsi_host/host1/scan echo "- - -" > /sys/class/scsi_host/host2/scan
將新磁盤設備加入集羣
ceph orch daemon add osd manager01.xxx.com:/dev/sdb ceph orch daemon add osd manager02.xxx.com:/dev/sdb ceph orch daemon add osd worker01.xxx.com:/dev/sdb ceph orch daemon add osd worker02.xxx.com:/dev/sdb # 查看設備信息 ceph orch device ls # 查看掛載好的osd信息 ceph osd df
爲了在其餘節點也可以直接訪問Ceph集羣,咱們須要在其餘節點上也安裝ceph-common。
cephadm之外的其餘節點執行:
mkdir ~/cephadmin mkdir /etc/ceph
從cephadm節點以拷貝ceph.repo,cephadm,ceph集羣配置文件,ceph客戶端管理員密鑰到其餘節點:
scp /etc/yum.repos.d/ceph.repo root@manager01.xxx.com:/etc/yum.repos.d scp /etc/yum.repos.d/ceph.repo root@manager02.xxx.com:/etc/yum.repos.d scp /etc/yum.repos.d/ceph.repo root@worker01.xxx.com:/etc/yum.repos.d scp ~/cephadmin/cephadm root@manager01.xxx.com:~/cephadmin/ scp ~/cephadmin/cephadm root@manager02.xxx.com:~/cephadmin/ scp ~/cephadmin/cephadm root@worker01.xxx.com:~/cephadmin/ scp /etc/ceph/ceph.conf root@manager01.xxx.com:/etc/ceph/ scp /etc/ceph/ceph.conf root@manager02.xxx.com:/etc/ceph/ scp /etc/ceph/ceph.conf root@worker01.xxx.com:/etc/ceph/ scp /etc/ceph/ceph.client.admin.keyring root@manager01.xxx.com:/etc/ceph/ scp /etc/ceph/ceph.client.admin.keyring root@manager02.xxx.com:/etc/ceph/ scp /etc/ceph/ceph.client.admin.keyring root@worker01.xxx.com:/etc/ceph/
其餘節點執行:
cd ~/cephadmin ./cephadm install ceph-common ceph -s
在執行ceph -s
或者ceph health
時,可能會發現以下的錯誤:
Module 'cephadm' has failed: auth get failed: failed to find client.crash.worker02 in keyring retval: -2
推測是Ceph對長域名支持不足的緣由。經過ceph auth ls
命令能夠查看ceph集羣全部的用戶的密鑰,能查到對應的長域名client.crash.worker02.xxx.com
用戶但沒有短域名用戶。經過如下命令建立對應的短域名用戶:
# 手動添加用戶client.crash.xxx,任意節點執行 ceph auth add client.crash.worker02 mgr 'profile crash' mon 'profile crash' ceph auth add client.crash.manager01 mgr 'profile crash' mon 'profile crash' ceph auth add client.crash.manager02 mgr 'profile crash' mon 'profile crash' ceph auth add client.crash.worker01 mgr 'profile crash' mon 'profile crash' # 查看新增用戶是否成功 ceph auth ls # 重啓ceph集羣,各個節點上都須要執行 systemctl restart ceph.target # 也能夠用下面的命令中止再重啓ceph集羣,各個節點上都須要執行 systemctl stop ceph.target systemctl stop ceph\*.service ceph\*.target ps -ef | grep ceph docker ps -a systemctl restart ceph.target # 重啓後從新檢查狀態 ceph -s
任意節點上執行:
# 建立一個用於cephfs數據存儲的池,相關參數自行參閱社區文檔,一言難盡。。。 ceph osd pool create cephfs_data 64 64 # 建立一個用於cephfs元數據存儲的池 ceph osd pool create cephfs_metadata 32 32 # 建立一個新的fs服務,名爲cephfs ceph fs new cephfs cephfs_metadata cephfs_data # 查看集羣當前的fs服務 ceph fs ls # 設置cephfs最大mds服務數量 ceph fs set cephfs max_mds 4 # 部署4個mds服務 ceph orch apply mds cephfs --placement="4 manager01.xxx.com manager02.xxx.com worker01.xxx.com worker02.xxx.com" # 查看mds服務是否部署成功 ceph orch ps --daemon-type mds
本文在這裏遇到一個問題,mds服務一直不能啓動,查看ceph health
發現一個1 filesystem is online with fewer MDS than max_mds
的警告,應該是ceph fs set cephfs max_mds 4
沒有生效。後來重啓了整個集羣就行了。
# 在全部節點上執行 systemctl restart ceph.target # 重啓以後檢查相關服務 ceph orch ps --daemon-type mds ceph osd lspools ceph fs ls
建立用戶,用於客戶端訪問CephFs
ceph auth get-or-create client.cephfs mon 'allow r' mds 'allow r, allow rw path=/' osd 'allow rw pool=cephfs_data' -o ceph.client.cephfs.keyring
查看輸出的ceph.client.cephfs.keyring
密鑰文件,或使用下面的命令查看密鑰:
ceph auth get-key client.cephfs
在各個節點執行:
mkdir /mnt/cephfs/ mount -t ceph manager01.xxx.com:6789,manager02.xxx.com:6789,worker01.xxx.com:6789,worker02.xxx.com:6789:/ /mnt/cephfs/ -o name=cephfs,secret=<cephfs訪問用戶的密鑰>
manager01.xxx.com:6789,manager02.xxx.com:6789,worker01.xxx.com:6789,worker02.xxx.com:6789 是全部mon服務
編輯各個節點的/etc/fstab
文件,實現開機自動掛載,添加如下內容:
manager01.xxx.com:6789,manager02.xxx.com:6789,worker01.xxx.com:6789,worker02.xxx.com:6789:/ /mnt/cephfs ceph name=cephfs,secretfile=<cephfs訪問用戶的密鑰>,noatime,_netdev 0 2
相關參數請自行查閱linux下fstab的配置資料。
將掛載到本地的cephfs做爲本地磁盤使用便可。例如本文中,能夠在docker run命令中,或者docker compose編排文件中,使用volume本地掛載到/mnt/cephfs
下。
示例,注意volumes:
... portainer: image: portainer/portainer ... volumes: - /mnt/cephfs/docker/portainer:/data ... deploy: mode: replicated replicas: 1 placement: constraints: [node.role == manager] ...
至此,使用cephfs實現docker共享存儲的嘗試已經OK。
Ceph的RBD對外提供的是塊存儲,但塊存儲直接做爲磁盤掛載到各節點的話,並不能實現不一樣節點之間的數據共享。所以須要配合中間件Rexray
,以及docker插件rexray/rbd
來實現共享存儲。
但本文並未成功,緣由後敘。
在任意節點上執行:
ceph osd pool create rbd01 32 rbd pool init rbd01 # 在rbd01上建立一個300G的image rbd create img01 --size 307200 --pool rbd01 rbd ls rbd01 rbd info --image img01 -p rbd01
此時能夠在各個節點上掛載RBD的img01,可是並不能實現存儲共享。
# 向linux系統內核載入rbd模塊 modprobe rbd # 將img01映射到系統內核 rbd map img01 --pool rbd01 --id admin # 失敗,須要禁用當前系統內核不支持的feature rbd feature disable img01 --pool rbd01 exclusive-lock, object-map, fast-diff, deep-flatten # 從新映射 rbd map img01 --pool rbd01 --id admin # 映射成功後,會返回映射目錄"/dev/rbd0",對該目錄進行格式化: [root@worker01 ~]# mkfs.xfs /dev/rbd0 meta-data=/dev/rbd0 isize=512 agcount=17, agsize=4914176 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=0, sparse=0 data = bsize=4096 blocks=78643200, imaxpct=25 = sunit=1024 swidth=1024 blks naming =version 2 bsize=4096 ascii-ci=0 ftype=1 log =internal log bsize=4096 blocks=38400, version=2 = sectsz=512 sunit=8 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 # mount到本地 mkdir /mnt/data01 mount /dev/rbd0 /mnt/data01 # 查看本地磁盤信息 df -hT # 卸除掛載並刪除image umount /mnt/data01 rbd unmap img01 --pool rbd01 --id admin rbd rm --image img01 -p rbd01
任意某個節點下載rexray:
curl -sSL https://rexray.io/install | sh
編輯配置文件vi /etc/rexray/config.yml
,內容以下:
rexray: logLevel: debug libstorage: logging: level: debug httpRequests: true httpResponses: true libstorage: service: rbd rbd: defaultPool: rbd01
嘗試啓動Rexray服務,這裏一直失敗:
[root@manager01 rexray]# rexray start ... error: service startup failed: agent: mod init failed: error initializing instance ID cache
日誌中除了最後的錯誤,並沒有其餘有用的信息。在github對應項目的issue中有相似問題,解決方法是ceph配置文件/etc/ceph/ceph.conf
中添加mon_host
配置。但本文使用的ceph版本octopus
的配置文件中已經明確配置了mon_host
,且格式與issue所述不一樣。最終也沒有找到緣由,懷疑是Ceph版本太新,與rexray不兼容所致。因此這裏的嘗試到此爲止,後續安裝docker插件與建立rbd數據卷並未進行。
若是Rexray服務能成功啓動,那麼後續還須要在每一個節點安裝docker插件rexray/rbd
:
docker plugin install rexray/rbd RBD_DEFAULTPOOL=rbd01 LINUX_VOLUME_FILEMODE=0777
最後在docker swarm上建立rbd驅動的數據卷:
docker volume create -d <rexrayHost>:5011/rexray/rbd <數據卷名稱>
若是成功,docker run或編排文件中的volume使用事先建立好的數據卷便可實現存儲共享。