容器编排Docker Swarm,是课程第七章的内容

1.容器编排Swarm介绍

Swarm是Docker自带的,不需要额外安装 swarm

swarm_2 Swarm里面有两种节点,一种是Manager节点,还有一种是Worker节点。 一般Container是运行在Worker上的,但是Manager节点上也是可以运行的,只是一般不这么做

swarm_3

2.创建一个三节点的swarm集群

  1. docker swarm init --advertise-addr=192.168.205.10
    这个命令要在准备作为manager节点的机器上来运行,运行这个命令的就是manager节点了,ip就是本机的ip,运行完成之后,会返回命令2
  2. docker swarm join --token SWMTKN-1-1rbdry31gxzz2u0nsbrqa5xkkd31lw83dpj5jife62xhqclbpr-151fu5csqw3ombtkm19jp9vej 192.168.205.10:2377
    这个命令都是命令1里面返回的,我们直接到worker节点的机器上运行就可以了
  3. docker node ls,查看现在的集群情况,这个命令要在manager节点上运行

3.Service的创建维护和水平扩展

相关命令:

  • docker service create --name demo busybox sh -c "while true; do sleep 3600; done",这个就是启动一个service,相当于与docker run
  • docker service ls,查看所有service的情况
  • docker service ps demo,查看某个service的情况,可以看到运行在哪个节点上
  • docker service rm demo,删除service,但是容器被删除会有一点延迟
  • docker service scale demo=3,横向扩展,也就是demo这个service的replicas会变成3,

NOTICE

  1. docker service ls命令返回结果里面的REPLICAS,都是"3/3"这样,分母表示总共有总数,分子表示现在有多少已经ready了
  2. 假设replicas我们设置为了5,那么swarm会自动帮我们去创建5个container,这时候,我们使用docker rm -f强制删除一个容器。我们会看到replicas会变成4/5,但是过一会又会变成5/5,因为swarm会确保我们的replicas个数。4/5的时候,swarm会自动帮我们再创建一个。

4.在swarm集群里通过service部署wordpress

部署过程:

  1. docker network create demo -d overlay,在集群里面创建overlay的网络,name为demo
  2. docker service create –name mysql –network demo –env MYSQL_ROOT_PASSWORD=xphone123 –env MYSQL_DATABASE=wordpress –mount type=volume,source=mysql-data,destination=/var/lib/mysql mysql 这个是创建mysql这个service的命令,–mount就是我们的docker run里面使用的-v命令,source=mysql-data指定的就是volume name,要注意docker run和docker service create里面的有些参数是不一样的
  3. docker service create –name wordpress -p 80:80 –env WORDPRESS_DB_PASSWORD=xphone123 –env WORDPRESS_DB_HOST=mysql –network demo wordpress,这个是创建wordpress的命令,WORDPRESS_DB_HOST的值等于mysql,这个mysql就是service的name,也就是之前ping mysql会得到那个地址的逻辑。

NOTICE

我们在运行了上面命令之后,我们可以通过docker service ps wordpress看到这个service是运行在哪个节点上面的,我们可以访问这个节点的ip,然后就看到了wordpress页面,这个是肯定的。但是这里要注意,我们这时候去访问其他两个节点的ip,也是可以看到wordpress页面的。原理在7-5,7-6里面

5.集群服务间通信之Routing Mesh

命令:

  1. docker network create demo -d overlay
  2. docker service create –name whoami -p 8000:8000 –network demo -d jwilder/whoami
  3. docker service create –name client -d –network demo busybox sh -c “while true; do sleep 3600; done”

上面的命令都运行好之后,我们现在应该是两个容器。我们进入client这个service的容器里面,我们ping whoami,是会通的,会得到一个地址,这里我们假设是10.0.0.9。
然后我们运行一个命令,docker service scale whoami=2,那么现在whoami这个service下面就有两个容器了。
我们还是在client里面ping whoami,这个时候我们发现,ping的通,但是ip还会是10.0.0.9。
那这里就有个问题了,whoami这个service有两个容器,我们到底ping的是哪个?
其实这个10.0.0.9,这个其实不是哪个容器的ip,这个是vip,也就是一个虚拟ip,容器有另外的ip。我们可以使用nslookup查看tasks.whoami,我们就看到了真实的ip。或者我们在client容器里面运行traceroute tasks.whoami,我们可以看到每次的结果可能是不一样的。因为docker会自动为我们在service里面负载均衡。发送给10.0.0.9的这个vip的流量会被分配到每个容器的真实ip上。

routingMesh

loadBalancing

IPVS

NOTICE

  1. nslookup whoami,这个可以看到vip是多少
  2. nslookup tasks.whoami,可以看到vip之后的所有真实ip是多少
  3. 容器里面的nslookup可能会有问题,也就是找不到这个dns记录,这个时候我们可以使用traceroute tasks.servicename来解决
  4. LVS可以就认为是IPVS,因为现在IPVS是LVS的一部分

6.Routing Mesh之Ingress负载均衡

Routing Mesh两种体现里面的另一个,Ingress Network。这个是可以把服务端口暴露到每个swarm节点上,和7-5里面的不一样。 ingress

试验步骤:
试验用swarm集群情况,还是上面的集群,两个whoami,一个client,whoami开放了一个8000端口,并且映射到了本地

  1. curl 127.0.0.1:8000,本机运行这个命令,发现背后有负载均衡。因为每次的返回会不一样,是从不一样的容器返回的,因为现在有两个whoami容器
  2. sudo iptables -nL -t nat,查看端口的情况,查看本地的转发规则 可以看到有一行,tcp dpt:8000 to:172.18.0.2:8000,也就是8000端口的流量,会转发到172.18.0.2:8000
  3. 我们可以在本机ip a,可以看到一个172.18.0.1,docker_gwbridge这个network,和2里面的转发的ip是一个网段里面的
  4. brctl show
  5. docker network inspect docker_gwbridge,查看这个network的情况,会看到172.18.0.2这个ip,属于一个ingress-sbox,它其实是一个network的namespace。我们可以用命令6来查看
  6. sudo ls /var/run/docker/netns,查看namespace
  7. sudo nsenter –net=/var/run/docker/netns/ingress_sbox,进入这个namespace,然后我们会发现,我们进入了ingress_sbox这个namespace,我们运行ip a,就是172.18.0.2
  8. iptables -nL -t mangle,查看这个namespace的iptables,会发现有一行 tcp dpt:8000 MARK set 0x102,MARK set 0x102就是表示IPVS会进行负载均衡
  9. 查看IPVS的具体情况,我们先退出这个namespace,在本机环境里面安装ipvsadm,sudo yum install -y ipvsadm,然后再进入namespace
  10. 再次进入ingress_box这个netns,运行ipvsadm -l,就可以看到负载均衡的真实地址了。这里面的地址就是两个whoami的容器真实ip

数据包走向: ingress_2

7.Docker Stack部署Wordpress

简单的说,stack就是通过文件来启动一系列service,而不是我们用命令一个个的去生成。
具体是用docker-compose file里面的deploy可以实现,具体的yml规则可以看下面的连接。 https://docs.docker.com/engine/reference/commandline/stack_deploy/

命令:

  1. docker stack deploy wordpress –compose-file=docker-compose.yml,创建一个stack,stack的name是wordpress,–compose-file用来指定yml配置文件,也可以是-c
  2. docker stack ls,查看现在的stack
  3. docker stack ps wordpress,查看stack的具体情况
  4. docker stack services wordpress,查看stack里面的service,可以看到绑定的端口
  5. docker stack rm wordpress,删除stack

docker-compose.yml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
version : '3'

services:
  web:
    image: wordpress
    ports:
     - 8080:80
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_PASSWORD: xphone123
    networks:
      - my-network
    depends_on:
      - mysql
    deploy:
      mode: replicated
      replicas: 3 #replicas个数为3
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
      update_config:
        parallelism: 1
        delay: 10s
  
  mysql:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: xphone123
      MYSQL_DATABASE: wordpress
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - my-network
    deploy:
      mode: global
      placement:
        constraints:
          - node.role == manager # 这个service的容器要运行在manager节点上

# 指定volume
volumes:
  mysql-data:

# 指定network
networks:
  my-network:
    driver: overlay #type是overlay

8.作业解答之部署投票应用

具体docker-compose.yml可以查看docker-labs

8.1stack可视化

dockersamples/visualizer:stable,使用这个镜像,可以可视化整个stack

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#这个service的配置
visualizer:
    image: dockersamples/visualizer:stable
    ports:
      - "8080:8080"
    stop_grace_period: 1m30s
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      placement:
        constraints: [node.role == manager]

9.Docker Secret管理和使用

9.1什么是Secret

secret 这些我们都可以存到docker secret里面

9.2Secret存在哪里

secret_2

secret_3

9.3使用方法

相关命令:

  • 从文件创建
    docker secret create my-pw password,这个password是一个文件,注意,我们创建好了docker secret之后,要把这个文件删掉
  • 从输入流创建
    echo “adminadmin” | docker secret create my-pw2 -,注意最后的-
  • docker secret ls,查看所有的secert
  • docker secret rm secret_name,删除secret
  • docker service create –name client –secret my-pw busybox sh -c “while true; do sleep 3600; done”,启动一个service,–secret指定这个service可以读取的secret,可以指定多个
  • cat /run/secrets/my-pw,我们在容器内部的这个路径,就可以读取到对应的secret了
  • 比如我们启动的mysql容器的时候,需要指定数据库密码,我们使用-e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/my-pw,这样就可以读取到我们写在docker secret里面的密码了

10.Docker Secret在Stack中的使用

docker-compose.yml配置文件里面虽然可以写上secret的配置,可以去读取一个文件然后自动生成一个docker secret。但是毕竟这样的方式会存在文件,会不安全。所以开始推荐要用的时候先在命令行里面手动创建docker secret

1
2
3
4
5
6
7
8
9
# 使用文件创建secret,不推荐这种方式
secrets:
  my-pw:
    file: ./password

# 在启动之前先手动创建secret,推荐这种方式
secrets:
  mysql-pw:
    external: true

11.Service更新

对service可以更新很多内容,比如更新镜像(镜像里面的代码逻辑需要更新比如),容器端口的更新

11.1更新镜像:

  1. 更新之前,为了使得我们现在的服务不会因为更新而不能访问(因为swarm集群里面的节点,一般都是生产环境,所以最好是不要有服务中断的情况),所以我们应该先对service进行scale,比如web的service,可以scale=2,那样就会有两个容器在服务
  2. 开始更新镜像,镜像的更新会一个一个来进行,因为我们已经做了scale了,所以服务不会中断,docker service update –image new_image_new web,这里的web是service的name。因为会一个一个更新,所以会出现一个容器是老的镜像,还有一个容器是新的镜像的时刻。

11.2更新端口:

更新端口可以通过先删去老的端口,然后加上新的端口来实现。 docker service update –publish-rm 8080:5000 –publish-add 8088:5000 这样就把原来的8080端口换到了8088端口,更新端口的时候,服务是会中断的,不会像更新镜像的时候一样,因为service都用一个VIP,然后VIP会负载均衡。那么更新端口的时候,VIP的端口会改变,所以服务会中断