容器集群 swarm
容器生態包含三個部分
- 容器核心知識 架構、鏡像、容器、網絡、存儲
- 容器平臺技術 容器編排引擎、容器管理平臺、基于容器的paas
- 容器支持技術 多主機管理、跨主機網絡方案、監控、日志管理
docker Swarm
從主機層面上來講,docker swarm 管理的是 docker host 集群
集群化
- 服務器集群由一組網絡上相互連接的服務器組成,他們協同工作。集群能夠像 單個 系統那樣工作,同時提供高可用、負載均衡和并行處理
- 如果部署應用和服務時選擇的是多個獨立的服務器而非集群,資源整體利用率很難到達最優。而且,應用使用資源的趨勢是波動的,喪失了業務的彈性。當某個服務器宕機時,我必須手動將受影響的應用遷移到其他服務器
docker swarm mode
在docker v1.12
中 docker重現實現了容器集群的編排方式。docker swarm 集成到 docker engine 。在此之前,提供集群的功能的 docker swarm 是一個獨立的軟件,而且依賴外部數據庫。
重要概念
swarm
- swarm運行docker engine 的多個主機組成的集群
- 從 v1.12開始,集群管理和編排功能已經集成到 docker engine。當 docker engine 初始化了一個swarm 或者加入到一個已經存在的 swarm 時,他就啟動了 searm mode
- 運行searm mode后,docker 增加了編排service的能力
- docker允許在同一臺主機上運行swarm server,同時運行單獨的容器
node
- swarm中的每個docker engine都是一個node 有兩種類型的node:
manager
和worker
- 在manager node上執行部署命令 manager將任務進行拆分分配給一個或多個worker node完成部署
*manager node 負責執行編排集群管理工作,保持并維護swarm處于期望狀態。swarm 上如果有多個manager node ,他們會自己協商一臺個manager節點為leader執行編排任務。- worker node接受并處理,manager node 派發的任務。默認配置下manager node 同時也是一個worker node,不過可以配置成manager-only node 讓其專門負責編排和集群管理工作
- worker node 會定時向 manager node 報告自己的狀態和正在執行的任務的狀態,這樣manager 就可以維護整個集群的狀態
server
- service 定義了worker node 上要執行的任務。swarm編排任務就是保證service處于期望狀態下
例:
1、在swarm中運行一個httpd服務,使用httpd鏡像,副本數為3;
2、manager node 負責創建這個service ,分析需要啟動3個httpd容器,根據當前各個worker node的狀態,然后將任務分配下去,node1 創建兩個容器,node2 創建1個容器;
3、運行了一段時間后,node2突然宕機了,manager 監控到node2異常,根據各個worker node 狀態,在node3上又啟動了一個httpd容器
保證了service 處于期望的三個副本的狀態
部署集群
1、創建swarm集群manager節點(初始化)
# docker swarm init --advertise-addr 192.168.1.90
--advertise-addr :指定與其他節點通信的地址
命令執行成功后會輸出三部分信息
>swarm創建成功,此node成為manager節點
以worker身份加入此集群需要的命令(可以復制去worker node執行)
以manager身份加入此集群需要的命令
查看此集群內的節點列表
# docker node ls
docker node ls --filter role=manager
--filter 按角色進行過濾
2、在worker節點上運行加入到集群的命令(manager安裝時生成)
# docker swarm join \
--token SWMTKN-1-1daezk9u1u8f1ul7xt5reneubhqkaowdmwt8bgw382517r7vn3-be37t5k6wzd9brjykdc7iaigg \
192.168.1.90:2377
Error response from daemon: rpc error: code = 14 desc = grpc: the connection is unavailable
工作節點加入集群時報錯 關閉防火墻
再次查看集群的節點列表
# docker node ls
查看以worker加入此集群的命令
# docker swarm join-token worker
查看以manager加入此集群的命令
docker swarm join-token manager
運行service
1、創建名為web_service的服務
# docker service create --name web_server httpd
--name 為服務命名 使用指定鏡像
# docker service ls
查看服務列表
列表中的REPLICAS
列為服務的副本信息
# docker service ps
查看服務每個副本的狀態 服務的鏡像名、副本在那個節點上運行、運行狀態、錯誤信息
報錯信息 No such image: ubuntu:lates
記得添加國內加速器配置
實現service的伸縮
1、增加web_server服務的副本數 scale up
(依賴以創建的服務)(增加到
指定數量,并非增加指定數量)
# docker service scale web_server=5
通過docker service ls
docker service ps web_server
查看詳細
讓manager node 不運行容器
# docker node update --availability drain swarm1
更新設置 從有效主機里移除 swarm1
# docker node ls
再次查看 AVAILABILITY
列swarm1節點已經從Active狀態到Drain狀態
# docker service ps web_server
再次查看服務的狀態 swarm1 節點上的副本已經被shutdown了,并且已經在其他節點生成了副本
2、減少副本數 scale down
# docker service scale web_server=3
# docker service ls
# docker service ps web_server
故障切換 failover
failover
失效備援
swarm 內置了failover策略,swarm會盡力保證我們要求的期望狀態
訪問容器
將容器公布出去
# docker service rm web_server
刪除服務
# docker service create --name web_server --replicas=2 httpd
創建服務并擁有兩個副本
# docker service ps web_server
查看服務的信息
# docker ps
在實際運行容器的機器上查看容器
# netstat -antp | grep 80
查看主機監聽的端口
# docker exec web_server.2.rt2nabx6qnon874ypzmf5fuuq ifconfig
查看容器的網絡信息
# curl 172.17.0.2
訪問容器IP地址上的80端口(只能在host上訪問容器運行的應用,并未暴露到外部)
# docker service update --publish-add 8080:80 web_server
修改web服務的端口暴露到外部網絡
# docker service create --name web_server1 --publish 80:80 --replicas=2 httpd
創建服務時聲明服務暴露到外部網絡
這樣在集群的任何一個節點 訪問 publish 映射的端口,都可以訪問到服務內容器副本中的應用。
神奇的 routing mesh
swarm的每個節點上都運行著 load balancer
負載均衡器
上述環境下,當我們訪問swarm集群的任意節點時,swarm內部的 load balancer 就會將請求轉發給web_server其中的一個副本。
這就是 routing mesh 路由網格
,所以訪問swarm集群的那個節點,即使此節點上沒有運行這個服務的副本,最終都可以訪問到service
ingress網絡
當我們應用 --publish-add 時,swarm 會重新配置service
# docker service ps web_server
查看service內容器的變化
之前的所有副本被shutdown,然后啟動了新的副本
# docker exec web_server.2.q9rxkj6q9zk4q6o9uvgx2lu7b ifconfig
再次查看新建容器內部的網絡情況
發現相比之前的容器多出一張網卡 10.255.0.7
# docker network ls
# docker network inspect ingress
查看網絡的詳細信息
觀察發現現在的容器副本有兩張網卡,eth0為ingress提供,eth1為bridge提供
eth0 連接的是overlay類型的ingress網絡,讓在不同host上運行的容器可以互相通信
eth1 連接的是bridge類型的docker_gwbridge網絡,,讓其可以通過host主機訪問外網
ingress網絡是創建swarm集群,或加入集群時自動創建的overlay網絡
通過overlay網絡,主機和容器,容器和容器之間可以相互訪問;同時 routing mesh 將外部請求路由到不同主機的容器,從而實現了外部網絡對service的訪問。
service之間的通信
微服務架構的應用由多個service組成。每個service都運行了若干個容器。service之間必然是要通信的。
服務發現
1、將所有service都publish出去,然后通過routing mesh訪問。但缺點就是把不應該公布出去的服務也全部公布出去,增加了安全隱患。
如果不采用publish方式,swarm集群就要提供一種滿足以下要求的機制
1、讓service之間可以簡單的方式進行訪問
2、當service副本的IP發生改變,不會影響service之間的訪問
3、當service副本數發生改變時,不會影響service之間的訪問
docker swarm 原生支持服務發現,通過服務發現,service使用者不需要知道service運行在哪,ip多少,幾個副本,就能與service通信。
創建overlay網絡
要使用服務發現,相互通信的service就要在同一overlay網絡下
ingress網絡沒有提供服務發現的功能,必須手動創建新的overlay網絡
# docker network create --driver overlay myapp_net
# docker network ls
# docker network inspect myapp_net
創建一個overlay網絡
# docker service create --name my_web --network myapp_net --publish 80:80 --replicas 3 httpd
# docker service create --name util --network myapp_net busybox sleep 10000000
將兩個服務運行在指定網絡中
# docker service ps util
查看服務的副本運行在那臺worker上
# docker exec util.1.r6cur67bppq1us4brhgdpy612 ping -c 4 my_web
嘗試ping web服務
ping服務名解析出了一個ip地址,著就是web服務的vip,swarm會對vip的訪問負載均衡到每一個副本
對于服務的使用者來說,根本不需要知道my_web副本的ip,也不需要知道my_web的vip,只需要使用service的名字就能訪問服務。
Rolling update 滾動更新
滾動更新降低了應用更新的風險,如果某個副本更新失敗,整個更新將暫停,其他副本則可以繼續提供服務。同時在更新的過程中一直有副本在運行的,因此也保證了業務的連續性。
創建一個服務
# docker service create --name my_web --replicas 3 --network myapp_net --publish 80:80 httpd:2.2.31
# docker service ps my_web
創建一個特定版本的web服務
# docker service update --image httpd:2.2.32 my_web
# docker service ps my_web
將服務的容器副本更新為另一個版本
默認配置下每次只更新一個副本,且副本之間沒有等待時間
# docker service update --replicas 6 --update-parallelism 2 --update-delay 1m40s my_web
更新web服務service的設置
將容器拓展為6個副本 每次滾動升級時2個一組,每100秒升級一組
--update-parallelism 設置并行更新的副本數
--update-delay 設置滾動更新的間隔時間
# docker service inspect --pretty my_web
檢查web服務service的設置
# docker service ps my_web
查看服務的狀態,容器副本數量的變化
# docker service update --image httpd:2.4.16 my_web
# docker service ps my_web
將web服務容器副本滾動升級到2.4
# docker service update --rollback my_web
--rollback 回滾升級
--rollback 只能回滾到上次update的狀態,不能無限制的回滾
# docker service ps my_web | grep Run
global mode
searm可以在service創建或運行過程中通過--replicas靈活的增加減少副本數,內部調度器會根據當前集群的資源使用情況在不同的node上啟停容器,這就是service默認的replicas mode
。
service還提供了一個global mode
,其作用是強制在每個worker節點上運行一個且最多一個副本,即使之后有新的node加入,swarm也會在新的節點上啟動一個副本。
docker service create --mode global --name logspout \
--mount type=bind,source=/var/run/docker.sock,destination=/var/run/docker.sock \
gliderlabs/logspout
創建一個service,在每個node節點上運行一個副本
# docker service inspect logspout --pretty
查看service的設置 Service Mode:global
Label
精細控制service的運行的位置
1、為每個node定義label
2、設置service運行在指定的node上
label可以靈活的描述node的屬性,用戶可以任意指定
# docker node update --label-add env=test worker1
給node打標簽
# docker node inspect worker1 --pretty
查看節點配置 查看標簽信息
# docker node update --label-add env=prod swarm1
# docker node update --label-add env=prod worker2
打標簽
# docker service create --constraint node.labels.env==test --replicas 3 --name my_web_test --publish 8080:80 httpd
指定在test標簽上的節點運行服務
# docker service ps my_web_test
查看副本運行的節點
# docker service inspect my_web_test --pretty
查看服務約束的設置 --constraint 的設置
# docker service update --constraint-rm node.labels.env==test my_web_test
# docker service update --constraint-add node.labels.env==prod my_web_test
將服務從test環境遷移到prod環境下
Health Check
健康檢查
docker 只能容器啟動進程的返回代碼判斷其運行狀態,對于容器內部應用的運行狀態沒有了解。
執行run命令時,通常根據dockerfile的CMD或ENTRYPOINT啟動一個進程,這個進程的狀態就是docker ps 顯示的狀態。