天天看點

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

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

原文:

Tips for using Docker Swarm mode in production 譯者: 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隻需要掌握少量指令。下面是我每天需要用到的所有指令:

# 建立服務
docker service create \  
  --image nginx \
  --replicas 2 \
  nginx 

# 更新服務
docker service update \  
  --image nginx:alpine \
  nginx 

# 删除服務
docker service rm nginx

# 減少服務執行個體(這比直接删除服務要好)
docker service scale nginx=0

# 增加服務執行個體
docker service scale nginx=5

# 檢視所有服務
docker service ls

# 檢視服務的容器狀态
docker service ps nginx

# 檢視服務的詳細資訊。
docker service inspect nginx  
           

實作零當機部署也非常簡單。這樣也可以友善地實作持續部署:

# 建構新鏡像
docker build -t hub.docker.com/image . 

# 将新鏡像上傳到Docker倉庫
docker push hub.docker.com/image

# 更新服務的鏡像
docker service update --image hub.docker.com/image service  
           

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 \  
  --log-driver gelf \
  --log-opt gelf-address=udp://monitoring.example.com:12201 \
  --log-opt tag=example-tag \
  example-service
           

7. 建立attachable network

attachable network是一個非常重要的特性。你最好使用它,否則

docker run

建立的容器将無法接入Swarm叢集的網絡。這是Docker 1.13之後的版本才有的功能,也許你需要更新。

建立attachable network的指令如下:

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

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

如果你按照

How to write excellent Dockerfiles

建構Docker鏡像,你很可能會使用環境變量去配置很多東西。如果你這樣做的話,則遷移到Swarm叢集時問題會少很多。示例指令如下:

# 建立服務時指定環境變量
docker service create \  
  --env VAR=VALUE \
  --env-file FILENAME \
  ...

# 增加、删除環境變量
docker service update \  
  --env-add VAR=NEW_VALUE \
  --env-rm VAR \
  ..
           

下一步是使用

Secrets API

。簡單地說,你可以将私密資料(比如密碼,SSL證書等)以檔案的形式挂載到容器中。雖然我還沒有用過Secrets API,但是我覺得值得嘗試一下。

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

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

另外,預設的

update-parallelism

值是1,這就意味着更新服務時,每次隻更新1個容器。通常,這個值太小了。我的建議是将它設為

服務容器數 / 2

.。

相關指令

# 将同時更新的容器數設為10
docker service update \  
  --update-parallelism 10 \
  webapp

# 同時增加多個服務的容器數
docker service scale redis=1 nginx=4 webapp=20

# 檢視服務狀态
docker service ls

# 檢視服務的詳情(排除關閉的容器) 
docker service ps webapp | grep -v "Shutdown"  
           

10. 将Swarm配置代碼化

最佳方式是使用

Docker Compose v3

文法,這樣可以将服務的所有配置選項代碼化。我将

docker-compose.yml

用于開發環境,

docker-compose.prod.yml

用于生産環境。使用docker-compose檔案部署服務的話,需要使用

docker stack deploy

指令(參考

docker stack

docker-compose檔案示例

# docker-compose.prod.yml
version: '3'  
services:  
  webapp:
    image: registry.example.com/webapp
    networks:
      - ingress
    deploy:
      replicas: ${WEBAPP_REPLICAS}
      mode: replicated
      restart_policy:
        condition: on-failure

  proxy:
    image: registry.example.com/webapp-nginx-proxy
    networks:
      - ingress
    ports:
      - 80:80
      - 443:443
    deploy:
      replicas: ${NGINX_REPLICAS}
      mode: replicated
      restart_policy:
        condition: on-failure

networks:  
  ingress:
    external: true
           

部署指令

export NGINX_REPLICAS=2 WEBAPP_REPLICAS=5

docker login registry.example.com  
docker stack deploy \  
  -c docker-compose.prod.yml\
  --with-registry-auth \
  frontend
           

另外,docker-compse檔案支援環境變量(${VARIABLE}),這樣你可以動态地調整配置。

11. 設定資源限制

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

reserve-cpu

選項也非常有用。當我希望平均地将所有容器部署到各個主機時,我會使用

reserve-cpu

,它可以保證每個容器都有足夠地資源。示例:

# 限制服務占用的CPU資源
docker service update  
  --limit-cpu 0.25
  --reserve-cpu 0.1
  webapp
           

13. 監控網絡連接配接

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

--endpoint-mode

選項)

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

歡迎加入

我們Fundebug

的****Docker****技術交流群****: 305097057****。

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

nodejs-qq-group.jpg

版權聲明:

轉載時請注明作者

以及本文位址:

https://blog.fundebug.com/2017/05/08/docker-swarm-suggestion/