swarm on ubuntu

因爲在centos7系統上使用docker-machine安裝的swarm實現服務的負載均衡一直失敗,存在問題,故將環境改到ubuntu16.04.2 LTS上進行操做html

兩個節點manager1:192.168.101.17(安裝docker、docker-machine),work1節點192.168.101.18(只進行安裝docker)node

一、在ubuntu系統上安裝docker,這裏採用dpkg包安裝deblinux

下載對應系統架構的deb:https://download.docker.com/linux/ubuntu/dists/xenial/pool/stable/amd64/docker-ce_17.09.0~ce-0~ubuntu_amd64.debnginx

$ sudo dpkg -i docker-ce_17.09.0_ce-0_ubuntu_amd64.deb
$ sudo systemctl start docker
$ sudo systemctl status docker

給兩個節點配置鏡像加速器:web

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組進行docker

wadeson@wadeson:~$ groupadd docker
groupadd:「docker」組已存在
wadeson@wadeson:~$ sudo usermod -aG docker wadeson

配置完成後,須要exit退出一下控制端,從新開啓就行json

二、爲manager1節點單獨安裝docker-machine:一下操做我這裏使用的都是rootubuntu

# 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:vim

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:centos

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  

 

三、建立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的使用查看官網

 

四、上面經過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

而訪問兩個節點卻都是成功的:

相關文章
相關標籤/搜索