tags: docker
, devops
Docker Swarm進階實戰(1)
容器的更新
在不移除及重啟容器的情況下更新,從以下指令選項可以知道,container update
旨在控制和限縮該容器的資源
另外要清楚的是我們透過docker run
執行一個容器,其狀態就只有Running
及Shotdown
兩種,如果出了差錯,此容器不會也不該有任何操作可以重新建立自己
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
$ docker container update --help Options: --blkio-weight uint16 Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0) --cpu-period int Limit CPU CFS (Completely Fair Scheduler) period --cpu-quota int Limit CPU CFS (Completely Fair Scheduler) quota --cpu-rt-period int Limit the CPU real-time period in microseconds --cpu-rt-runtime int Limit the CPU real-time runtime in microseconds -c, --cpu-shares int CPU shares (relative weight) --cpus decimal Number of CPUs --cpuset-cpus string CPUs in which to allow execution (0-3, 0,1) --cpuset-mems string MEMs in which to allow execution (0-3, 0,1) --kernel-memory bytes Kernel memory limit -m, --memory bytes Memory limit --memory-reservation bytes Memory soft limit --memory-swap bytes Swap limit equal to memory plus swap: '-1' to enable unlimited swap --restart string Restart policy to apply when a container exits |
Service的更新
再來看
service update
的選項,很明顯比容器更還多出許多操作,因為swarm service存在的目的就是要能在不影響服務的情況下取代(replace)、重建recreate容器12$ docker service --helpswarm mode也是利用這種方式,逐一取代service底下執行的容器,達到滾動更新
docker service的指令並非直接告訴系統去新增或刪除容器,而是新增了一連串的工作到佇列中,整個處理的流程帶有scale、rollback、failure mitigation等功能
12$ docker service scale web=412$ docker service rollback webservice更新的目標是limit downtime,也就是控制停機時間
stack deploy
會觸發service更新service更新會對nodes做rebalancing
滾動更新
- Swarm service的分配原則
- 預設分散至多個nodes上
- 使用率較低的node優先配置
- 使用者可自行定義此分配模式
- 定義service分配的5種方式:
- Service Constraints
- Service Modes
- Placement Preferences
- Node Availability
- Resource Requirements
- 測試前準備事項
- 準備3+個以上nodes組成的swarm
- 至少要有1個manager跟2個worker
- 清理運行中的docker程序及服務
- 部署一個visualizer服務
1. Service Constraints
- 對nodes加上label來限制(constraints)服務的配置
- label可以是built-in或custom
- built-in:
node.<-- key -->
- built-in:
- 可以在service新增/修改時add/remove label
- 是hard requiremnts,亦即符合條件的node才配置服務
- 一個service可加上多個限制條件
- label可以是單個key,或key=value的篩選方式
- 可以用
==
或!=
來篩選 - label分成兩種:
- node.labels標籤存在raft資料庫,只能由manager node來新增
- engine.labels透過docker engine的設定檔
daemon.json
新增,須重開docker daemon - 通常是使用預設的node.labels,如果不方便對manager做動態設定,才會從engine.lables下手
範例:service只在manager配置
1 2 |
docker service create --constraint node.role==manager nginx |
或
1 2 |
docker service create --constraint node.role!=worker nginx |
範例:新增node標籤
1 2 |
docker node update --label-add=dmz=true node2 |
接著以key, value限制service配置
1 2 |
docker service create --constraint node.labels.dmz==true nginx |
範例:在service更新時重設條件
1 2 |
docker service create --name s1 --constraint node.role==worker nginx |
1 2 |
docker service update --constraint-rm node.role==worker --constraint-add node.role==manager s1 |
範例:stack file
1 2 3 4 5 6 7 8 9 |
version: "3.1" services: db: image: mysql:5.7 deploy: placement: constraints: - node.labels.disk == ssd |
built-in label list
- id
- hostname
- ip(e.g. 172.19.17.0/24)
- role(manager|worker)
- platform.os(linux|windows)
- platform.arch(x86_64|386)
- labels
2. Service mode
- 預設是replicated,例如replica=10,docker swarm會執行10個container並盡可能分散到各個node上,但不能確保每個node都會配置到該task
- Global是replica的相反,能確保one task on node
- Global適用於host agents(monitoring, backup, proxy…)
- 目前僅限於
service create
時設定
1 2 |
docker service create --mode=global nginx |
1 2 3 4 5 6 7 |
version: "3.1" services: web: image: nginx deploy: mode: global |
3. Placement Preferences
- 是soft requirement
- 目前只有spread這個策略
- spread tasks among all values of a Label
- 適用availablility zones, datacenters, racks, subnets > things where you want to spread workload out amongst various type of infrastructure
- 可用於
service create/update
範例: Lable all nodes with availability zone
1 2 3 4 |
docker node update --label-add=azone=1 node1 docker node update --label-add=azone=2 node2 docker node update --label-add=azone=3 node3 |
根據這個Label加以分散
1 2 |
docker service create --placement-pref spread=node.labels.azone --replicas 3 nginx |
範例: Multi-level perferences 官方範例
使用--placement-pref
增加限制
1 2 |
docker service create --placement-pref=spread=node.labels.azone --replicas=8 --name webapp nginx |
現在試著打破限制,使用新的條件增加覆蓋原有限制,測試soft requirement
1 2 |
docker service update --constraint-add node.role==worker webapp |
stack file範例
1 2 3 4 5 6 7 8 9 |
version: "3.1" services: web: image: nginx deploy: placement: preferences: spread: node.labels.azone |
4. Node Availability
每個節點會有一個有機狀態(admin-controlled state):
- active: 執行現有的task,且可以指派新的task至該node(available)
- pause: 常用在trouble shooting,現有的tasks持續執行(不保證如果有執行service update,相同的容器會依舊執行),但不能指派新的task至該node(not available)
- drain: 維護時會用到,重新指派現有的tasks,且不能指派新的task至該node(not available)
有些文章會建議維護時可以把manager node設為drain,但實際上你會需要在manager node做管理的事情,例如有monitoring tools要跑(e.g. Portainer, swarm web GUI),或是需要與swarm溝通的logging engine,這些容器可不能被停掉(drain/pause),尤其這兩個狀態如果容器出了任何問題,沒辦法重新建立
建議不要用在manager node,而是用label的方式來限制(控制)manager tasks
範例指令
pause node2
1 2 |
dock node update --availibility pause node2 |
drain node3,將其tasks指派到其他nodes
1 2 |
docker node update --availibility drain node3 |
5. Resource Requirements
針對節點資源的條件限制,如cpu用量和記憶體大小,使用上要特別注意,例如運行database的service,資料如果持續增長到超過限制,該容器會被關閉重新排程
Reservation是一種promise,例如主機有4 CPU,如果把某個service的CPU資源設為4,其他service將無法取得任何CPU資源
docker run
針對限制容器資源有許多設置選項,但Swarm中的docker service
是另一回事,目前只有cpu和memory的選項可以操作
如果docker找不到足夠的資源來部署service,該service會進入Pending的狀態,然後持續kill、recreate的流程直到找到資源為止
範例指令
1 2 |
docker service create --reserve-memory 800M --reserve-cpu 1 mysql |
或是藉由剝奪資源來關閉service
1 2 |
docker service update --reserve-memory 0 --reserve-cpu 0 mysql |