標籤:

生產環境中使用Docker Swarm的一些建議

譯者按: 實踐中會發現,生產環境中使用單個Docker節點是遠遠不夠的,搭建Docker集群勢在必行。然而,面對Kubernetes, Mesos以及Swarm等眾多容器集群系統,我們該如何選擇呢?它們之中,Swarm是Docker原生的,同時也是最簡單,最易學,最節省資源的,至少值得我們多了解一下。本文將介紹一些非常實用的建議。

原文: rock-it.pl/tips-for-usi

譯者: Fundebug

為了保證可讀性,本文採用意譯而非直譯。另外,本文版權歸原作者所有,翻譯僅用於學習

如果你在單個生產節點上用過Docker,然後發現單個節點的資源不夠用,那麼你會怎麼做呢?我也遇到過這種情況! 關於在生產環境中使用Docker Swarm,我會為你提供一些建議,也許能夠幫到你。這些都是我一年來積累的一些經驗。

另外,如果你對Docker Swam不熟悉的話,可以參考我之前的博客My experience with Docker Swarm - when you may need it?

1. 閱讀官方文檔

我並不打算重複官方文檔。儘管文檔非常短,但是通過它可以了解Swarm的基本知識。另外,我也不會寫如何搭建Swarm集群,這方面的資料太多了,你可以查看 Digital Ocean或者自己谷歌。PS: 我是使用Ansible搭建Swarm集群的。

2. Docker Swarm要點

Swarm的負載非常低。據我觀察,Swarm進行調度和通信的CPU負載非常低。因此,Swarm的管理節點(Manager)可以同時作為工作節點(Worker)。如果你需要搭建一個非常大的集群(1000+ 節點),管理節點需要更多資源,但是對於中小型集群來說,管理節點需要的資源可以忽略不計。另外,這篇博客介紹了Swarm3k(一個4700節點的Swarm集群的實驗),不妨了解一下。

Swarm集群的網路通信(服務發現,負載均衡以及容器間通信)非常可靠。當你開啟一個服務的埠之後,在Swarm集群中的任何一個節點都可以訪問它。負載均衡也是由Swarm提供的。後文會提到一些之前遇到的問題,但是Docker 1.13之後,這些問題都解決了。

使用Swarm只需要掌握少量命令。下面是我每天需要用到的所有命令:

# 創建服務ndocker service create n --image nginx n --replicas 2 n nginx nn# 更新服務ndocker service update n --image nginx:alpine n nginx nn# 刪除服務ndocker service rm nginxnn# 減少服務實例(這比直接刪除服務要好)ndocker service scale nginx=0nn# 增加服務實例ndocker service scale nginx=5nn# 查看所有服務ndocker service lsnn# 查看服務的容器狀態ndocker service ps nginxnn# 查看服務的詳細信息。ndocker service inspect nginxn

實現零宕機部署也非常簡單。這樣也可以方便地實現持續部署:

# 構建新鏡像ndocker build -t hub.docker.com/image . nn# 將新鏡像上傳到Docker倉庫ndocker push hub.docker.com/imagenn# 更新服務的鏡像ndocker service update --image hub.docker.com/image servicen

Swarm非常容易入門。分散式系統通常是非常複雜的。與其他容器集群系統(Mesos, Kubernetes)相比,Swarm的學習曲線最低。在沒有任何Swarm知識的情況下,我只花了一周時間,就把服務從單個Docker主機遷移到20個節點的Docker集群上。

更新服務要慎重。 你的容器同時運行在多個主機上。更新服務時,只需要更新Docker鏡像。合理的測試和部署流程是保證成功的關鍵。

3. 決定哪些容器部署在Swarm集群

並非所有服務都應該部署在Swarm集群內。資料庫以及其他有狀態服務就不適合部署在Swarm集群內。理論上,你可以通過使用labels將容器部署到特定節點上,但是這樣的話,Swarm集群外的節點就很難訪問它們了(Docker 1.12沒有很好的方法,但是1.13之後可以使用attachable network)。如果你允許集群外的節點訪問資料庫,則所有節點都可以訪問它,這顯然不符合你的需求。另外,Docker Swarm的跨節點數據卷(cross-host mounted volumes)並不可靠,一個簡單的文件上傳都可能引起問題。

無狀態的容器就非常適合部署在Swarm集群中,它們可以由環境變數進行配置(使用ENV指令)。建議為開源工具構建鏡像,例如,可以將Nginx的配置文件放到Docker鏡像中。

下面是我部署在Swarm集群中的服務:

  • Django channels (網頁應用)
  • Nginx(代理)
  • Celery(周期性任務)
  • Sensu(監控)

下面是我部署在Swarm集群之外的容器:

  • Postgres(資料庫)
  • Redis(緩存)

由於一個獲取真正IP的問題,我很可能會將Nginx運行在Swarm集群之外,或者採用host模式。

4. 配置Docker倉庫

Docker倉庫,你值得擁有!你可以自己搭建一個,或者使用Docker倉庫服務,比如DockerHub或者GitLab Container Registry。不要在伺服器上直接構建Docker鏡像,因為你有多個節點(在每個節點上構建鏡像非常麻煩),而且在創建服務的時候你需要指定鏡像(這個鏡像所有節點都應該可以下載)。如果你配置了私有Docker倉庫,則需要指定--with-registry-auth,否則這些節點將無法下載鏡像。

另外,你應該為Docker鏡像設置版本,這樣更加易於回滾。

5. 將半無狀態的服務變得完全無狀態

所謂半無狀態服務,就是容器需要依賴一些不太重要的外部文件。你可以使用數據卷(volume),但是更好的選擇是使用S3或者其他雲存儲服務。記住,想要獲得擴展性,雲是最好的選擇。

例如,我不得不構建Nginx鏡像,將配置文件放到鏡像中。使用數據卷掛載Nginx配置文件不是很方便。

6. 配置日誌收集服務

使用分散式系統時,集中管理日誌是非常必要的。我們有很多方案,包括開源工具或者SaaS服務,比如ELK,Grafana, Graylog…自己搭建完整的系統是非常複雜的,所以我建議搭建先使用SaaS服務(比如Loggly, Logentries ),當費用太高時,則自己搭建一個系統。ELK可以這樣配置:

docker service update n --log-driver gelf n --log-opt gelf-address=udp://monitoring.example.com:12201 n --log-opt tag=example-tag n example-servicen

7. 創建attachable network

attachable network是一個非常重要的特性。你最好使用它,否則docker run創建的容器將無法接入Swarm集群的網路。這是Docker 1.13之後的版本才有的功能,也許你需要升級。

創建attachable network的命令如下:

docker network create --driver=overlay --attachable coren

8. 先使用環境變數,再考慮Secrets API

如果你按照How to write excellent Dockerfiles構建Docker鏡像,你很可能會使用環境變數去配置很多東西。如果你這樣做的話,則遷移到Swarm集群時問題會少很多。示例命令如下:

# 創建服務時指定環境變數ndocker service create n --env VAR=VALUE n --env-file FILENAME n ...nn# 增加、刪除環境變數ndocker service update n --env-add VAR=NEW_VALUE n --env-rm VAR n ..n

下一步是使用Secrets API 。簡單地說,你可以將私密數據(比如密碼,SSL證書等)以文件的形式掛載到容器中。雖然我還沒有用過Secrets API,但是我覺得值得嘗試一下。

9. 設置合理的服務容器個數以及並行更新的容器個數

一方面,你需要保證足夠多的容器數來處理負載以及作為災備,另一方面,太多的容器會導致CPU和內存資源不足。因此,你需要配置合理的服務容器個數,也就是說,某個服務,需要運行合理個數的容器。

另外,默認的update-parallelism 值是1,這就意味著更新服務時,每次只更新1個容器。通常,這個值太小了。我的建議是將它設為 服務容器數 / 2.。

相關命令

# 將同時更新的容器數設為10ndocker service update n --update-parallelism 10 n webappnn# 同時增加多個服務的容器數ndocker service scale redis=1 nginx=4 webapp=20nn# 查看服務狀態ndocker service lsnn# 查看服務的詳情(排除關閉的容器) ndocker service ps webapp | grep -v "Shutdown"n

10. 將Swarm配置代碼化

最佳方式是使用Docker Compose v3 語法,這樣可以將服務的所有配置選項代碼化。我將 docker-compose.yml用於開發環境, docker-compose.prod.yml用於生產環境。使用docker-compose文件部署服務的話,需要使用 docker stack deploy 命令(參考docker stack

docker-compose文件示例

# docker-compose.prod.ymlnversion: 3 nservices: n webapp:n image: registry.example.com/webappn networks:n - ingressn deploy:n replicas: ${WEBAPP_REPLICAS}n mode: replicatedn restart_policy:n condition: on-failurenn proxy:n image: registry.example.com/webapp-nginx-proxyn networks:n - ingressn ports:n - 80:80n - 443:443n deploy:n replicas: ${NGINX_REPLICAS}n mode: replicatedn restart_policy:n condition: on-failurennnetworks: n ingress:n external: truen

部署命令:

export NGINX_REPLICAS=2 WEBAPP_REPLICAS=5nndocker login registry.example.com ndocker stack deploy n -c docker-compose.prod.ymln --with-registry-auth n frontendn

另外,docker-compse文件支持環境變數(${VARIABLE}),這樣你可以動態地調整配置。

11. 設置資源限制

根據我的經驗,你需要限制所有服務的CPU使用。這樣可以防止單個容器佔用主機的所有的CPU資源。

reserve-cpu 選項也非常有用。當我希望平均地將所有容器部署到各個主機時,我會使用reserve-cpu ,它可以保證每個容器都有足夠地資源。示例:

# 限制服務佔用的CPU資源ndocker service update n --limit-cpu 0.25n --reserve-cpu 0.1n webappn

12. 監控網路連接

我遇到過Swarm網路方面的問題。有時候所有的請求都被轉發到某一個容器,然而還有9個其他容器正在運行。這時,可以嘗試減少/增加實例個數,或者改變路由類型(使用--endpoint-mode選項)

如果沒有監控日誌的話,這樣的問題很難被發現。因此,搭建監控系統是非常必要的。

歡迎加入我們Fundebug的Docker技術交流群: 305097057

版權聲明:n轉載時請註明作者Fundebug以及本文地址:n生產環境中使用Docker Swarm的一些建議n

推薦閱讀:

Docker的作用的主要作用是什麼?
各位前輩請問docker怎麼樣呀,有什麼學習資料(博客呀、網站呀等)給推薦一下,謝謝?
學習Docker哪本書最好?

TAG:Docker |