這是最近項(xiàng)目中遇到的一個(gè)問(wèn)題。在已知的部署在 docker 容器云上某個(gè)應(yīng)用中,讀寫(xiě)非常頻繁,對(duì)磁盤(pán)的性能要求極高,但是又不能在同一個(gè)容器內(nèi)進(jìn)行高強(qiáng)度讀寫(xiě)。另外,該主機(jī)內(nèi)存資源有冗余,允許使用特權(quán)模式運(yùn)行容器,不要求該部分?jǐn)?shù)據(jù)持久性存儲(chǔ)。
成都創(chuàng)新互聯(lián)長(zhǎng)期為上千家客戶(hù)提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為尼瑪企業(yè)提供專(zhuān)業(yè)的網(wǎng)站設(shè)計(jì)制作、網(wǎng)站制作,尼瑪網(wǎng)站改版等技術(shù)服務(wù)。擁有10余年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。
通過(guò)對(duì)問(wèn)題的分析,我采取了以下解決方案:
通過(guò)把內(nèi)存掛載成硬盤(pán),可以大幅度提高磁盤(pán)的性能;
由于不能在同一個(gè)容器內(nèi)進(jìn)行讀寫(xiě),可以使用 NFS 來(lái)解決;
允許使用特權(quán)模式,可以在容器內(nèi)部掛載磁盤(pán);
不要求數(shù)據(jù)持久存儲(chǔ),可以把內(nèi)存當(dāng)作告訴磁盤(pán)來(lái)使用;
在本文中已經(jīng)對(duì)涉及到公司利益部分內(nèi)容進(jìn)行處理,例如:文中涉及到的鏡像已經(jīng)移除相關(guān)應(yīng)用,直接以centos7.6.1810為基礎(chǔ)鏡像。
CentOS Linux release 7.6.1810 (Core)
內(nèi)存:256GB
#!/bin/bash
UserName='gysl'
PassWord='drh223'
# Install the Docker engine. This needs to be executed on every machine.
curl http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker-ce.repo>&/dev/null
if [ $? -eq 0 ] ;
then
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine>&/dev/null
yum list docker-ce --showduplicates|grep "^doc"|sort -r
yum -y install docker-ce-18.09.3-3.el7
rm -f /etc/yum.repos.d/docker-ce.repo
systemctl enable docker --now && systemctl status docker
else
echo "Install failed! Please try again! ";
exit 110
fi
# Modify related kernel parameters.
cat>/etc/sysctl.d/docker.conf<&/dev/null
# Turn off and disable the firewalld.
systemctl stop firewalld
systemctl disable firewalld
# Disable the SELinux.
sed -i.bak 's/=enforcing/=disabled/' /etc/selinux/config
# Disable the swap.
sed -i.bak 's/^.*swap/#&/g' /etc/fstab
# Install EPEL/vim/git.
yum -y install epel-release vim git
yum repolist
# Add a docker user.
useradd $UserName
echo $PassWord|passwd $UserName --stdin
usermod $UserName -aG docker
# Reboot the machine.
reboot
執(zhí)行以上腳本重啟服務(wù)器之后,以用戶(hù)名 gysl 登錄系統(tǒng)。
Dockefile內(nèi)容如下:
FROM centos:7.6.1810
ENV SSD='/high-speed-storage' SIZE='10m'
COPY . /
RUN yum -y install nfs-utils && \
mkdir $SSD
CMD [ "/bin/bash","/start.sh" ]
start.sh腳本內(nèi)容如下:
#!/bin/bash
echo "$SSD *(fsid=0,rw,no_root_squash,no_subtree_check)">>/etc/exports
mount -t tmpfs -o size=$SIZE tmpfs $SSD
/usr/sbin/exportfs -r
/usr/sbin/rpcbind
/usr/sbin/rpc.nfsd
/usr/sbin/rpc.mountd
/usr/sbin/rpc.rquotad
while true;
do
sleep 6000;
done
新建一個(gè)目錄,將上文中的 Dokcerfile 與 start.sh 放到該目錄。
[gysl@gysl-dev ~]$ mkdir nfs
[gysl@gysl-dev ~]$ cd nfs
[gysl@gysl-dev nfs]$ docker build -t nfs:v1.0 .
啟動(dòng)容器內(nèi)的 NFS 服務(wù),命令如下:
[gysl@gysl-dev nfs]$ docker run -itd --privileged --rm nfs:v1.0
953dd0cf03e024447ba3a7f1be6dce6217226b25c13ffa2b9967941c96b73f4e
[gysl@gysl-dev nfs]$ docker inspect 953|grep -w 'IPAddress'
"IPAddress": "172.17.0.2",
"IPAddress": "172.17.0.2",
修改 Dockerfile ,內(nèi)容如下:
FROM centos:7.6.1810
ENV SSD='/high-speed-storage' DATA='/data'
COPY . /
RUN yum -y install nfs-utils && \
mkdir $DATA
CMD [ "/bin/bash","/start-client.sh" ]
添加 start-client.sh 腳本,腳本內(nèi)容如下:
#!/bin/bash
mount -t nfs 172.17.0.2:$SSD $DATA
while true; do sleep 6000; done
新建一個(gè)目錄,把修改后的 Dockerfile 和 start-client.sh 放到同一目錄,執(zhí)行命令如下:
[gysl@gysl-dev ~]$ mkdir nfs-client
[gysl@gysl-dev ~]$ cd nfs-client/
[gysl@gysl-dev nfs-client]$ vi Dockerfile
[gysl@gysl-dev nfs-client]$ vi start-client.sh
[gysl@gysl-dev nfs-client]$ docker run --privileged -itd --rm nfs-client:v1.0
7e01276f49815b76dd4dc3ae3ff9a80b8d4f32814f46c4e58f7cfab0d945cebf
進(jìn)入應(yīng)用容器,查看是否掛載成功:
[root@7e01276f4981 /]# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 8.0G 2.6G 5.5G 32% /
tmpfs 64M 0 64M 0% /dev
tmpfs 455M 0 455M 0% /sys/fs/cgroup
/dev/mapper/centos-root 8.0G 2.6G 5.5G 32% /etc/hosts
shm 64M 0 64M 0% /dev/shm
172.17.0.2:/high-speed-storage 10M 0 10M 0% /data
[root@7e01276f4981 /]# touch /data/test
成功!問(wèn)題解決!
不符合一個(gè)容器一個(gè)進(jìn)程的容器運(yùn)用的主流標(biāo)準(zhǔn);
數(shù)據(jù)不能持久化保存,重啟容器數(shù)據(jù)會(huì)被清除;
容器存在依賴(lài)性,必須先啟動(dòng)提供 NFS 服務(wù)的容器;
適用范圍狹窄;
不能通過(guò) systemd 來(lái)管理服務(wù);
linux下的 ramdisk 是由內(nèi)核提供的,mount 命令掛載即可使用。它會(huì)被視為塊設(shè)備,使用時(shí)需要格式化該文件系統(tǒng)。ramdisk 一旦創(chuàng)建就會(huì)占用固定大小的物理內(nèi)存,tmpfs則是動(dòng)態(tài)分配。
在同一臺(tái)主機(jī)的未指定網(wǎng)絡(luò)方案的情況下,Docker 是通過(guò) bridge 的方式進(jìn)行橋接的。如果涉及到跨主機(jī)的互聯(lián),那么可能需要使用其他方案。
nfs-ganesha 也是 NFS 在容器中的一個(gè)比較流行的解決方案。更多資料可參閱: