NO IMAGE

640.gif?wxfrom=5&wx_lazy=1

本文來自作者 大白菜 在 GitChat 上分享「Docker
落地踩過的坑」,「閱讀原文」檢視交流實錄

「文末高能」

編輯 | 嘉仔

前言

接觸 Docker 是在大四畢業設計中,當時選的課題是:基於 Docker 的自動化運維研究。也很幸運,畢業從事的工作也是 Docker 相關的工作。第一份工作是在杭州銅板街,杭州的朋友可能聽過,在那裡工作了近
2 年時間。主要的工作是將 Docker 落地於公司,提高整個交付流程的效率。第二份工作是塗鴉智慧,主要工作是,實現公司的 DevOps 。在整個 Docker 落地過程中,踩過無數的坑,這當中,包括技術的選型,如何將現有的開發習慣都 Docker 化,以及最大的困難和挑戰就是讓大家相信 Docker 能在 DevOps 中帶來更好的幫助較於傳統的自動化運維。本文,主要介紹幾個在Docker 落地過程中的一些建議和常見的幾個坑。
包括:

  • Registry 使用 Harbor 對映象倉庫管理

  • Registry 使用 oss 或者 s3 作為儲存

  • Registry 批量清理映象

  • Docker dubbo 服務註冊

  • Docker 刪除上一次部署的容器的映象

  • RocketMQ broker 註冊 IP 問題

  • ….

正文


Registry
使用 Harbor 對映象倉庫管理

目前主流的 Registry 有
Portus(https://github.com/SUSE/Portus
)、Harbor(https://github.com/vmware/harbor
)、docker-registry-web 等。本文建議使用 VMware 的開源 Harbor 作為 Docker 映象管理倉庫。Harbor 相關文件較全面,社群相對活躍,而且功能強大。

Harbor 主要的功能有:

  • 基於角色的訪問控制

  • 映象同步複製

  • 圖形介面管理映象

  • 漏洞掃描

  • 支援 LDAP/AD

  • 映象刪除和垃圾回收

  • 對所有操作進行審計

  • 提供 RESTful API

詳細介紹請參考官方文件

Harbor(https://github.com/vmware/harbor)。

需要注意的一點是,儘量使用 https,安裝文件:https
訪問安裝文件(https://github.com/vmware/harbor/blob/master/docs/configure_https.md)

使用
oss
或者
s3
作為儲存

Docker 提供了豐富的映象倉庫儲存方式,預設我們是使用本地的檔案系統。這種方式有很多弊端,一個就是本地磁碟有限,因為映象倉庫是很耗儲存的。如果咱們用的是 aws 或者 aliyun 機器,那麼使用 s3 或
oss 作為映象倉庫的儲存是超級便利的,也就再也不用擔心磁碟不夠,磁碟損壞等問題。這裡介紹一下使用 aliyun 的 oss 最為映象倉庫的儲存。

先看看使用 oss 最為儲存的配置項:

storage:
oss:
 accesskeyid: accesskeyid
 accesskeysecret: accesskeysecret
 region: OSS region name
 endpoint: optional endpoints
 internal: optional internal endpoint
 bucket: OSS bucket
 encrypt: optional data encryption setting
 secure: optional ssl setting
 chunksize: optional size valye
 rootdirectory: optional root directory

注:這裡是 registry 的配置檔案 config.yml 中 storage 配置

具體  配置項((https://docs.docker.com/registry/storage-drivers/oss/)
 含義:

0?wx_fmt=jpeg
下面是一個具體例子:

storage:
 cache:
   layerinfo: inmemory
 oss:
  accesskeyid: xxxx
  accesskeysecret: xxxx
  region: oss-cn-hongkong
  endpoint: xxx.oss-cn-hongkong.aliyuncs.com
  bucket: xxx
 maintenance:
   uploadpurging:
     enabled: false
 delete:
   enabled: true

這裡有點比較有用的提示:

internal 這個配置預設是 false 的,意味著 endpoint 則是外網 endpoint 。從阿里雲的 OSS中:

0?wx_fmt=jpeg

我們可以看到,外網流出的費用是需要收費的,所以如果 oss 和 開的 ECS 都是在同一個 Region ,建議配置 endpoint : true ,然後 endpoint 配置內網的地址。可以節省成本。

如果公司使用的是 aliyun ECS ,而且機器涉及到跨 Region 。那麼建議搭建多個映象倉庫。比如開發環境或者日常環境搭使用一個倉庫,線上使用一個倉庫。線上的倉庫只儲存預發環境或者是線上環境的映象。具體倉庫部署可以後面一起討論。

Registry 批量清理映象

在長期頻繁使用映象倉庫後,由於倉庫清理映象比較費勁,業內也沒有一個比較好的清理方案,官方提供的倉庫清理也比較費勁,導致 Docker 映象倉庫越積越大,嚴重消耗磁碟空間。基於該現狀,並結合上面提到的使用 Harbor 作為倉庫管理,完美解決 Registry 清理映象的問題。

映象命名規則

如果想方便快捷的清理映象,映象的名字和 tag 的命名都極為重要。儘量做到分層,分類。這樣有助於批量刪除清理映象。比如下面的命名規則:

0?wx_fmt=jpeg

這樣做的好處是能夠方便的做到批量刪除映象。比如想刪除日常環境下的映象,只需要匹配 xxx/deploy/app/daily 就行。

藉助
Harbor Restful API 刪除映象或 Tag


主要有下面幾個步驟:


  • 如果想刪除 xxx/deploy/app/daily 下的所有映象。

1. 使用 GET /api/repositories ,該 API 有個 filter 引數,設定 filter=xxx/deploy/app/daily ,則可以匹配查詢出xxx/deploy/app/daily 下的所有 repositories。 

2. 遍歷上一步拿到的 repositories, 使用 DELETE /api/repositories/${repoName}

  • 如果想刪除某個 repo 的 tag,同理,也可以呼叫 API 刪除

  • 上述刪除動作 ,實際上並沒有刪除,只是刪除了 Registry 的索引。實際檔案並沒有刪除。 
    最後還需要執行映象的垃圾回收:

docker run -it –name gc –rm –volumes-from registry vmware/registry:2.6.2-photon garbage-collect /etc/registry/config.yml

⚠️ 注意:最好停止 registry 服務,防止在回收的時候有 push 操作,從而造成映象分層的混亂和誤刪。

通過使用 Harbor API ,可以方便快捷的操作 Registry,開源社群還提供了 Harbor 的 Java API,本質上我們自己也可以封裝。Github 地址:Harbor
Java API(https://github.com/johnnywong233/harbor-java-client)。

Docker dubbo 服務註冊

背景


在容器部署應用和常規部署應用混合使用一套 zk 或者是在 Docker 叢集下容器部署應用,將出現 dubbo 服務呼叫失敗的問題。

原因

在容器中部署應用時,應用中的 dubbo 服務,獲取容器 hostname 的 IP 地址和配置檔案中的埠號向註冊中心中註冊。由於不同網段不能互相通訊訪問,這就導致了,容器部署應用和常規部署應用混合共用一套註冊中心或是在 Docker 叢集下容器部署應用時,將出現 dubbo 消費者不能訪問服務提供者。

分析

由於 dubbo 服務註冊,是去拿 hostname 的 IP 向,通過這點,hostname 必須為宿主機的 IP 地址。為了解決上述問題,首要解決的問題是網路通訊問題。

解決方法

方法一:啟用容器時,指定容器的網路模式為
host 模式,因為 host 模式容器共享主機的網路。

docker run –net=host

優點:簡單,容易配置。

缺點:一個機器相同應用只能起一份。

方法二:想辦法讓主機 hostname
的 IP 為宿主機的 IP,這樣通過宿主機的 IP 和對映的 dubbo 埠號,就能避免這個問題。這裡推薦一個比較挫的方法。

啟動容器時,指定 hostname ,並且將宿主機的 /etc/hosts 掛載至容器中,如:/tmp/hosts,容器啟動的時候,讀取/tmp/hosts 中宿主機的 IP,寫入到容器的 /etc/hosts 中。

  • 具體步驟如下: 

  • 宿主機的 /etc/hosts,追加宿主機的 IP,如下:

127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 
192.168.1.216 hostname

  • 啟動容器時將宿主機的 /etc/hosts 掛載至容器中的/tmp 中,並指定 hostname 為 dubbo-service-provider

docker run -v /etc/hosts:/tmp/hosts –hostname dubbo-service-provider

  • 容器啟動時執行指令碼,步驟如下:

1.首先從 /tmp/hosts 中獲取宿主機的 IP

hostIP=grep -F hostname /home/tomcat/hosts |awk '{print $1}'

2.註釋掉容器自身的host 配置(由於容器中的 /etc/hosts 許可權問題,需採用如下曲折方法)

cp /etc/hosts /etc/hosts.temp 
sed -i ‘s/^[^#].*dubbo-service-provider/#&/’ /etc/hosts.temp 
cat /etc/hosts.temp >/etc/hosts

3.將宿主機IP追加到容器/etc/hosts

echo “${hostIP} dubbo-service-provider” >> /etc/hosts

以上兩種方法可以解決 dubbo docker 化中網路通訊問題。如果是線上上,建議使用第一種。不僅僅是 dubbo 服務註冊會遇到這種網路通訊問題,很多中介軟體都有同樣的問題,比如 rocketMq、kafka
等。下面介紹一下 RocketMQ broker 註冊 IP 問題。


RocketMQ broker 註冊 IP 問題


問題描述

RocketMQ 裝入容器中時,Broker 註冊地址將使用容器自身的 IP ,導致 consumer 端不能從 broker 中拿到消費訊息。


分析

RocketMQ broker 啟動時,使用了預設的配置檔案,其中 brokerip1 的值預設是本機IP地址,預設系統自動識別,但是某些多網絡卡機器會存在識別錯誤的情況,在 Docker 環境中,都是多網絡卡。所以該值需要手動配置。

解決辦法

  • 生成broker預設配置模版:sh mqbroker -m > broker.p

  • 修改配置檔案broker.p

brokerIp1=192.168.1.23

載入修改過的配置檔案:nohup sh mqbroker -c broker.p

總結


由於篇幅和時間有限,以上整理的幾個建議和踩過的坑,分享給在 Docker 化落地的朋友,希望能夠在這條路上少踩點坑。未來不久,我們會計劃開源我們的 DevOps 平臺,和大家一起探索和進步。

近期熱文

Java
多執行緒程式設計核心技術有哪些

Python
的 C 擴充套件開發慣例

如何成為一名程式設計師麵霸

輕鬆入門
| 用 WordPress 和主題模板做網站

Java
8 Stream API 實用指南


福利

640?wx_fmt=png

「閱讀原文」看交流實錄,你想知道的都在這裡