由於在centos7系統上使用docker-machine安裝的swarm實現服務的負載均衡一直失敗,存在問題,故將環境改到ubuntu16.04.2 LTS上進行操作
兩個節點manager1:192.168.101.17(安裝docker、docker-machine),work1節點192.168.101.18(只進行安裝docker)
1、在ubuntu系統上安裝docker,這裡採用dpkg包安裝deb
下載對應系統架構的deb:https://download.docker.com/linux/ubuntu/dists/xenial/pool/stable/amd64/docker-ce_17.09.0~ce-0~ubuntu_amd64.deb
$ sudo dpkg -i docker-ce_17.09.0_ce-0_ubuntu_amd64.deb $ sudo systemctl start docker $ sudo systemctl status docker
給兩個節點配置映象加速器:
root@manager1:~# cat /etc/docker/daemon.json { "dns": ["192.168.101.2","8.8.8.8"], "registry-mirrors": ["https://cbd49ltj.mirror.aliyuncs.com"] }
如果使用普通使用者操作docker:將使用者新增到docker組進行
wadeson@wadeson:~$ groupadd docker groupadd:“docker”組已存在 wadeson@wadeson:~$ sudo usermod -aG docker wadeson
配置完成後,需要exit退出一下控制端,重新開啟就行
2、為manager1節點單獨安裝docker-machine:一下操作我這裡使用的都是root
# cp docker-machine /usr/local/bin/ # cd /usr/local/bin/ # chmod +x docker-machine # docker-machine version docker-machine version 0.13.0, build 9ba6da9
兩個節點的基礎環境配置好後,現在開始建立machine:
root@wadeson:~# ssh-keygen root@wadeson:~# ssh-copy-id root@192.168.101.17 root@wadeson:~# docker-machine create -d generic --generic-ip-address=192.168.101.17 --generic-ssh-key ~/.ssh/id_rsa --generic-ssh-user=root manager1
上面為管理節點自己建立一個machine,下面給遠端主機work1節點建立machine:
root@wadeson:~# ssh-copy-id root@192.168.101.18 root@wadeson:~# docker-machine create -d generic --generic-ip-address=192.168.101.18 --generic-ssh-key ~/.ssh/id_rsa --generic-ssh-user=root work1
root@manager1:~# docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS manager1 - generic Running tcp://192.168.101.17:2376 v17.09.0-ce work1 - generic Running tcp://192.168.101.18:2376 v17.09.0-ce
將machine建立好了之後,接下來搭建swarm叢集,在管理節點manager1節點搭建:
root@wadeson:~# docker-machine ssh manager1 "docker swarm init --advertise-addr 192.168.101.17"
然後將work1節點加進到swarm叢集中:
root@wadeson:~# docker-machine ssh work1 "docker swarm join --token SWMTKN-1-3pb7f9xynb3m8kiejf63w6klcwcbfg0r4dcalnxzeuennfwccc-7ubvqutczmn1ag2qpev2u31wd 192.168.101.17:2377" This node joined a swarm as a worker.
執行完成後,swarm叢集就搭建完成了,檢視節點資訊:
root@wadeson:~# docker-machine ssh manager1 "docker node ls" ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS izidcyk70x8jbhm20emeblymz * manager1 Ready Active Leader gt0onqyz71f2fnzmwqqgtv83z work1 Ready Active
3、建立service
建立一個將埠對映到host主機上的web服務:
root@wadeson:~# docker-machine ssh manager1 "docker service create --name web --replicas 2 --publish 8080:80 nginx" o6hlfsxiw8hjrh0uigmsg46cm
root@wadeson:~# docker-machine ssh manager1 "docker service ls" ID NAME MODE REPLICAS IMAGE PORTS o6hlfsxiw8hj web replicated 0/2 nginx:latest *:8080->80/tcp root@wadeson:~# docker-machine ssh manager1 "docker service ps web" ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS u5q5r94qbq8p web.1 nginx:latest work1 Running Preparing 13 seconds ago 7f71e1ycyrlp web.2 nginx:latest manager1 Running Preparing 13 seconds ago 正在下載映象,所以不是馬上就是running
當分配到節點的狀態都是running時,表示服務建立成功沒有問題,由於在使用centos建立這樣型別的服務時,只有manager管理節點能夠訪問,現在使用ubuntu系統建立的服務:
可以看見在ubuntu建立相同的服務,能夠實現負載均衡的效果的,分配在兩個節點的任務都能夠進行訪問成功
當建立的是一個web服務提供網站訪問,那麼資料目錄是需要進行掛載出來的,而service在建立過程中也是可以指定的,但是引數變成了--mount
root@wadeson:~/docker_project# docker-machine ssh manager1 "docker service create --name web --replicas 2 --publish 8080:80 --mount source=,destination=/usr/share/nginx/html nginx" 0kuxwkaoophassmzhzt7yuk6p
上面建立了一個源掛載點為預設的,將它掛載到了nginx的根目錄,檢視對映到host的詳細路徑:
root@manager1:/www# docker inspect web.2.rpva7n1100w8tbh55lfi8l9w2 使用容器名進行檢視 "Mounts": [ { "Type": "volume", "Name": "1e2bcfdf684f1e8ee6bc9f110cbf455b2efe4d4551b940a80991948cbeaca589", "Source": "/var/lib/docker/volumes/1e2bcfdf684f1e8ee6bc9f110cbf455b2efe4d4551b940a80991948cbeaca589/_data", "Destination": "/usr/share/nginx/html", "Driver": "local", "Mode": "z", "RW": true, "Propagation": "" }
可以詳細的知道host主機上的哪一個目錄與nginx根目錄對應:
檢視volume的一些資訊:
root@manager1:/www# docker volume ls DRIVER VOLUME NAME local 1e2bcfdf684f1e8ee6bc9f110cbf455b2efe4d4551b940a80991948cbeaca589
可以看見在上面建立的service web之後也建立了一個隨機命名的volume(預設為本地)
現在在管理節點manager1上的掛載目錄建立一個html:
然後進行訪問:
但是檢視並訪問work1節點時:
在work1節點上建立的隨機名是和manager1節點不一樣的,所以相應的在manager1節點上增加一個html,而在work1節點上並沒有該html的建立
現在在manager1節點上建立一個本地volume:
root@wadeson:~/docker_project# docker volume create test test root@wadeson:~/docker_project# docker volume ls DRIVER VOLUME NAME local test
然後使用該建立的test volume進行建立一個service:
root@wadeson:~/docker_project# docker-machine ssh manager1 "docker service create --name web --replicas 2 --publish 8080:80 --mount source=test,destination=/usr/share/nginx/html nginx" 39bphuu4248u8cvwv57q5880s 使用test來掛載nginx的網站目錄
建立完成service之後,現在檢視manager1節點將絕對路徑分配到了哪裡?
root@manager1:/www# docker inspect web.1.znwxgy5k5133xbt4gmys5iho4 "Mounts": [ { "Type": "volume", "Name": "test", "Source": "/var/lib/docker/volumes/test/_data", "Destination": "/usr/share/nginx/html", "Driver": "local", "Mode": "z", "RW": true, "Propagation": "" }
root@manager1:~# docker volume inspect test [ { "CreatedAt": "2017-11-18T00:01:43+08:00", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/test/_data", "Name": "test", "Options": {}, "Scope": "local" } ]
現在在manager1節點的掛載點上建立一個新的html
root@manager1:/var/lib/docker/volumes/test/_data# ll 總用量 20 drwxr-xr-x 2 root root 4096 11月 18 00:01 ./ drwxr-xr-x 3 root root 4096 11月 17 23:57 ../ -rw-r--r-- 1 root root 537 9月 15 00:35 50x.html -rw-r--r-- 1 root root 612 9月 15 00:35 index.html -rw-r--r-- 1 root root 26 11月 18 00:01 test.html
然後在節點work1上檢視掛載的點目錄:
root@work1:/var/lib/docker/volumes/test/_data# ll 總用量 16 drwxr-xr-x 2 root root 4096 11月 17 23:58 ./ drwxr-xr-x 3 root root 4096 11月 17 23:58 ../ -rw-r--r-- 1 root root 537 9月 15 00:35 50x.html -rw-r--r-- 1 root root 612 9月 15 00:35 index.html
可以看見work1和manager1上並不一致,然後我們訪問兩個ip:
可以發現即使使用相同的掛載點,如果僅僅在其中一個節點上建立了html,另一個節點依然不能夠進行訪問到,這種模式就需要進行共享儲存或者分散式儲存解決了
docker針對volume的方式有很多種:
建立一個tmpfs: root@wadeson:~/docker_project# docker volume create -o type=tmpfs -o device=tmpfs -o o=size=100m,uid=1000 html html
然後檢視volume資訊:
root@manager1:~# docker volume inspect html [ { "CreatedAt": "2017-11-18T00:33:18+08:00", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/html/_data", "Name": "html", "Options": { "device": "tmpfs", "o": "size=100m,uid=1000", "type": "tmpfs" }, "Scope": "local" } ]
root@manager1:~# docker volume ls DRIVER VOLUME NAME local html local test
僅僅是在manager1節點上進行建立了,而work1節點是沒有的:
root@work1:~# docker volume ls DRIVER VOLUME NAME local test
現在使用這個html volume進行掛載,那麼work1將會建立volume為html的掛載點,但是屬性是和manager1完全不一樣的
root@manager1:~# docker service create --name web --replicas 2 --publish 8080:80 --mount source=html,destination=/usr/share/nginx/html nginx a410dj6ob3v7dc7dge2os3h28
root@work1:~# docker volume inspect html [ { "CreatedAt": "2017-11-19T21:08:10+08:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/html/_data", "Name": "html", "Options": {}, "Scope": "local" } ]
對於manager1這個節點來說html volume的資訊:
root@manager1:~# docker volume inspect html [ { "CreatedAt": "2017-11-19T21:08:10+08:00", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/html/_data", "Name": "html", "Options": { "device": "tmpfs", "o": "size=100m,uid=1000", "type": "tmpfs" }, "Scope": "local" } ]
在manager1節點的掛載目錄下面看不見nginx的原始html:
關於volume的使用檢視官網
4、上面通過docker service建立了服務,現在這裡通過stack命令通過compose檔案進行建立stack來管理服務:
root@manager1:~/docker_project# cat docker-compose.yml version: "3" services: web: image: nginx deploy: replicas: 2 restart_policy: condition: on-failure ports: - "8080:80" networks: - "net" networks: net:
編寫玩compose檔案後,使用stack進行建立:
root@manager1:~/docker_project# docker stack deploy -c docker-compose.yml web
Creating network web_net
Creating service web_web
可以看見建立了服務web_web,建立了網路web_net,而這裡建立的網路與之前單獨使用compose建立的服務中的網路driver是不一樣的:
root@manager1:~/docker_project# docker network ls NETWORK ID NAME DRIVER SCOPE 535f88afa37e bridge bridge local de07db93a69a docker_gwbridge bridge local c496484033f7 host host local q8u4pz1f00sq ingress overlay swarm 4e36c8cfed74 none null local rny61337fv5k web_net overlay swarm
使用swarm叢集建立下的網路預設的driver是overlay模式,而不是bridge
檢視建立的stack:
root@manager1:~/docker_project# docker stack ls NAME SERVICES web 1 root@manager1:~/docker_project# docker stack ps web ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS j8eljggx5u0g web_web.1 nginx:latest work1 Running Running about a minute ago 1ogxqm87cmsu web_web.2 nginx:latest manager1 Running Running about a minute ago
由於stack可以用來管理service,所以也可以用service來檢視服務:
root@manager1:~/docker_project# docker service ls ID NAME MODE REPLICAS IMAGE PORTS ds0z266ttqrf web_web replicated 2/2 nginx:latest *:8080->80/tcp root@manager1:~/docker_project# docker service ps web_web ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS j8eljggx5u0g web_web.1 nginx:latest work1 Running Running 2 minutes ago 1ogxqm87cmsu web_web.2 nginx:latest manager1 Running Running 2 minutes ago
可以看見service的名稱和stack的名稱是不一致的
列出在stack中的服務:
root@manager1:~/docker_project# docker stack services web ID NAME MODE REPLICAS IMAGE PORTS ds0z266ttqrf web_web replicated 2/2 nginx:latest *:8080->80/tcp
然後進行訪問分配的兩個節點:
docker stack的一些命令:
Commands: deploy Deploy a new stack or update an existing stack ls List stacks ps List the tasks in the stack rm Remove one or more stacks services List the services in the stack
這些命令都是比較好操作的,這裡不做介紹了
向compose檔案中加入volume:
root@manager1:~/docker_project# cat docker-compose.yml version: "3" services: web: image: nginx deploy: replicas: 2 restart_policy: condition: on-failure ports: - "8080:80" networks: - "net" volumes: - "/www:/usr/share/nginx/html" networks: net:
volumes指令這裡,只是在manager1節點上建立了/www目錄,而work1節點並沒有:
root@manager1:~/docker_project# docker stack ps web ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS yeoo33w9gtyg web_web.1 nginx:latest manager1 Running Running 26 seconds ago h42wivwjeyyg web_web.2 nginx:latest manager1 Running Running 1 second ago k9cwzgiwqfkw \_ web_web.2 nginx:latest work1 Shutdown Rejected 16 seconds ago "invalid mount config for type…" k1z0euovj5ot \_ web_web.2 nginx:latest work1 Shutdown Rejected 21 seconds ago "invalid mount config for type…" xqchylah6ovp \_ web_web.2 nginx:latest work1 Shutdown Rejected 26 seconds ago "invalid mount config for type…" h7cc0rl07vz7 \_ web_web.2 nginx:latest work1 Shutdown Rejected 26 seconds ago "invalid mount config for type…"
於是swarm試圖在work1上分配任務失敗,節點掛載失敗,於是全部分配到了manager1節點上,如果需要在work1節點上掛載成功,需要建立www目錄,但是後面的資料一致還是需要共享儲存
將上面的volumes掛載改為volume下的某一個沒有建立的(兩個節點之前都沒建立)
root@manager1:~/docker_project# cat docker-compose.yml version: "3" services: web: image: nginx deploy: replicas: 2 restart_policy: condition: on-failure ports: - "8080:80" networks: - "net" volumes: - "mydata:/usr/share/nginx/html" networks: net: volumes: mydata:
利用上面的compose進行建立stack:
root@manager1:~/docker_project# vim docker-compose.yml root@manager1:~/docker_project# docker stack deploy -c docker-compose.yml web Creating network web_net Creating service web_web
root@manager1:~/docker_project# docker stack ps web ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS qgph48g6devs web_web.1 nginx:latest manager1 Running Running 4 seconds ago ukualp6c6rwn web_web.2 nginx:latest work1 Running Running 3 seconds ago
可以看見節點都能成功執行任務,現在檢視各節點的volume情況:
root@manager1:~/docker_project# docker volume ls DRIVER VOLUME NAME local html local test local web_mydata
root@work1:~# docker volume ls DRIVER VOLUME NAME local html local test local web_mydata
然後檢視具體volume web_mydata的掛載目錄:
root@manager1:~/docker_project# docker volume inspect web_mydata [ { "CreatedAt": "2017-11-19T21:39:16+08:00", "Driver": "local", "Labels": { "com.docker.stack.namespace": "web" }, "Mountpoint": "/var/lib/docker/volumes/web_mydata/_data", "Name": "web_mydata", "Options": {}, "Scope": "local" } ]
root@manager1:~/docker_project# cd /var/lib/docker/volumes/web_mydata/_data root@manager1:/var/lib/docker/volumes/web_mydata/_data# ll 總用量 16 drwxr-xr-x 2 root root 4096 11月 19 21:39 ./ drwxr-xr-x 3 root root 4096 11月 19 21:39 ../ -rw-r--r-- 1 root root 537 9月 15 00:35 50x.html -rw-r--r-- 1 root root 612 9月 15 00:35 index.html
root@work1:/var/lib/docker/volumes/web_mydata/_data# ll 總用量 16 drwxr-xr-x 2 root root 4096 11月 19 21:39 ./ drwxr-xr-x 3 root root 4096 11月 19 21:39 ../ -rw-r--r-- 1 root root 537 9月 15 00:35 50x.html -rw-r--r-- 1 root root 612 9月 15 00:35 index.html
可以看見掛載相同的內容了,然後向manager1建立一個html:
root@manager1:/var/lib/docker/volumes/web_mydata/_data# echo "<h1>hello swarm</h1>" >> test.html
訪問兩個節點:
由此可見,同樣需要共享儲存,或者分散式儲存
如果需要將建立的任務進行約束constraints,比如將建立的replicas都建立在節點work1上面:
root@manager1:~/docker_project# cat docker-compose.yml version: "3" services: web: image: nginx deploy: replicas: 2 restart_policy: condition: on-failure placement: constraints: [ node.hostname == work1 ] ports: - "8080:80" networks: - "net" volumes: - "mydata:/usr/share/nginx/html" networks: net: volumes: mydata:
root@manager1:~/docker_project# docker stack ps web ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS waqycm6yzq7n web_web.1 nginx:latest work1 Running Running 5 seconds ago c95s2ts8nnn9 web_web.2 nginx:latest work1 Running Running 5 seconds ago
從上面可以看見了,建立的任務都分配到了節點work1上面,這就是在deploy中新增了constraints條件
而在deploy中也有mode一說,分別有global和replicated,下面舉例說明(預設為replicated)
root@manager1:~/docker_project# cat docker-compose.yml version: "3" services: web: image: nginx deploy: mode: replicated replicas: 2 restart_policy: condition: on-failure placement: constraints: [ node.hostname == work1 ] ports: - "8080:80" networks: - "net" volumes: - "mydata:/usr/share/nginx/html" networks: net: volumes: mydata:
mode為replicated的時候時,與replicas搭配使用,代表建立的任務的副本數,而global不與replicas連用,表示在每個節點上都建立有任務:
root@manager1:~/docker_project# cat docker-compose.yml version: "3" services: web: image: nginx deploy: mode: global restart_policy: condition: on-failure ports: - "8080:80" networks: - "net" volumes: - "mydata:/usr/share/nginx/html" networks: net: volumes: mydata:
然後檢視建立任務對於的節點狀態:
root@manager1:~/docker_project# docker stack ps web ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS rc1t2hv5amhy web_web.izidcyk70x8jbhm20emeblymz nginx:latest manager1 Running Running 1 second ago qbianufy60p4 web_web.gt0onqyz71f2fnzmwqqgtv83z nginx:latest work1 Running Running 1 second ago
當然也可以對全部的節點進行約束,也可以僅僅只是在某一個節點上建立任務:
root@manager1:~/docker_project# cat docker-compose.yml version: "3" services: web: image: nginx deploy: mode: global restart_policy: condition: on-failure placement: constraints: - node.hostname == work1 ports: - "8080:80" networks: - "net" volumes: - "mydata:/usr/share/nginx/html" networks: net: volumes: mydata:
root@manager1:~/docker_project# docker stack ps web ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS oof47jartobw web_web.gt0onqyz71f2fnzmwqqgtv83z nginx:latest work1 Running Running 3 seconds ago
而訪問兩個節點卻都是成功的: