第六课 Docker践行DevOps理念-docker-swarm介绍使用

第六课 Docker践行DevOps理念-docker-swarm

tags:

  • Docker
  • 慕课网

categories:

  • docker-swarm

第一节 docker-swarm介绍

1.1 多容器的问题

  1. 怎么去管理这么多容器?
  2. 怎么能方便的横向扩展?
  3. 如果容器down了,怎么能自动恢复?
  4. 如何去更新容器而不影响业务?
  5. 如何去监控追踪这些容器?
  6. 怎么去调度容器的创建?
  7. 保护隐私数据?

1.2 docker-swarm

  1. 它是docker内置的容器编排工具。当然还有其他的编排工具(比如:k8s)
  2. Docker Swarm Mode Architecture
    • 一种角色叫Manager(避免单点故障,需要数据库来同步)
    • 另一种角色叫worker
      在这里插入图片描述
  3. Service和Replicas
    在这里插入图片描述
  4. 服务创建和调度
    在这里插入图片描述

1.3 实验环境-swarm cluster

  1. Vagrant + Virtualbox
  2. Docker Machine + Virtualbox
  3. Paly with docker https://labs.play-with-docker.com/
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.require_version ">= 1.6.0"

boxes = [
    {
        :name => "swarm-manager",
        :eth1 => "192.168.205.10",
        :mem => "1024",
        :cpu => "1"
    },
    {
        :name => "swarm-worker1",
        :eth1 => "192.168.205.11",
        :mem => "1024",
        :cpu => "1"
    },
    {
        :name => "swarm-worker2",
        :eth1 => "192.168.205.12",
        :mem => "1024",
        :cpu => "1"
    }
]

Vagrant.configure(2) do |config|

  config.vm.box = "centos/7"

  boxes.each do |opts|
      config.vm.define opts[:name] do |config|
        config.vm.hostname = opts[:name]
        config.vm.provider "vmware_fusion" do |v|
          v.vmx["memsize"] = opts[:mem]
          v.vmx["numvcpus"] = opts[:cpu]
        end

        config.vm.provider "virtualbox" do |v|
          v.customize ["modifyvm", :id, "--memory", opts[:mem]]
          v.customize ["modifyvm", :id, "--cpus", opts[:cpu]]
        end

        config.vm.network :private_network, ip: opts[:eth1]
      end
  end

  #config.vm.synced_folder "./labs", "/home/vagrant/labs"
  config.vm.provision "shell", privileged: true, path: "./setup.sh"

end
# 配置阿里镜像
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://eyzd1v97.mirror.aliyuncs.com"]
}
EOF
# 更新源
sudo yum-config-manager \
  --add-repo \
  https://download.docker.com/linux/centos/docker-ce.repo
sudo yum clean all  
sudo yum makecache fast
sudo yum update
# 安装依赖包和docker
sudo yum install -y yum-utils device-mapper-persistent-data lvm2 git vim gcc glibc-static telnet bridge-utils net-tools
sudo yum install docker-ce-17.12.0.ce -y
sudo systemctl enable docker
sudo systemctl daemon-reload
sudo systemctl restart docker

# 添加vagrant到docker组中
sudo gpasswd -a vagrant docker # 把当前用户添加到docker组中
sudo systemctl restart docker.service # 重启docker服务

1.4 创建三节点的swarm集群

  1. 进入swarm-manager节点
    • vagrant ssh swarm-manager
    • 初始化管理节点:docker swarm init --advertise-addr=192.168.205.10
  2. 看输出有Token,进入另外两台worker添加子节点节点:docker swarm join --token SWMTKN-1-4efgmfq2ktp7kse85hph2url6hb1lx7z0bpj58zfrq8tuu7k8o-d7oua9xqykog02vicrydepm11 192.168.205.10:2377
  3. 在swarm-manager节点中查看当前swarm集群中的节点:docker node ls

第二节 docker-swarm中的service

2.1 Service的创建维护和水平扩展

  1. docker service create --help
  2. 在swarm中我们就不要用docker run 啦,docker run只能创建运行在本地节点的容器。docker service 可以随机在swarm集群中创建容器。
  3. 服务水平拓展docker service scale demo=5
    • 分母表示要求的拓展数目 5
    • 分子表示Ready,准备好了5个
  4. 查看服务的具体信息:docker service ps demo
  5. 如果我们到一台机器上强制删除一个容器, swarm会发现容器失效,会自动重新启动一台容器以达到swarm的scale=5的设置修补
    在这里插入图片描述
# 在swarm节点中创建busybox服务
docker service create --name demo busybox sh -c "while true;do sleep 3600;done"
# 查看创建的service服务
docker service ls
# 查看服务的具体信息 比如在那台机器上
docker service ps demo
# demo使我们service的名字 而不是我们创建的容器的名字 服务创建的容器名为:demo.1.3y15hagxrtnsggtdi4lct7mkc
docker ps -a
# 服务水平拓展
 docker service scale demo=5
# 如果我们到一台机器上强制删除一个容器
docker rm -f c96cd4209efc
# 如果手速快 可以看到 4个变成5个的过程
docker service ls 
docker service ls
# 删除服务 默认把所有节点的service产生的容器删除
docker service rm demo

2.2 swarm集群里通过service部署wordpress

  1. 先创建一个overlay的网络,这样不管,这两个容器是否在同一个机器上都可以相互通信。
    • docker network create -d overlay demo
# 创建一个overlay的网络
docker network create -d overlay demo
# 创建mysql 服务
docker service create --name mysql --env MYSQL_ROOT_PASSWORD=root --env MYSQL_DATABASE=wordpress --network demo --mount type=volume,source=mysq1-data,destination=/var/lib/mysql mysql:5.7
# 查看服务在个机器上
docker service ps mysql
# 创建wordpress服务
docker service create --name wordpress -p 80:80 --env WORDPRESS_DB_PASSWORD=root --env WORDPRESS_DB_HOST=mysql --network demo wordpress
# 发现wordpress服务在work2上 在work2上观察网络发现demo
docker network ls 
# 输入下面三个ip的地址 都可以访问 wordpress服务 
192.168.205.10
192.168.205.11
192.168.205.12
  1. swarm内部维护了一个网络机制会同步网络的创建,不需要我们手动使用etcd等key value数据库来同步。

2.3 集群服务间通信之Routing Mesh体现-Internal

  1. swarm有内置的DNS服务发现功能
    • 为连到overlay上的所有的sevice增加一条DNS的记录
    • Service的DNS的名字是sevice名字name
    • 但是DNS对应的ip并不是对应机器上的容器的ip,而是一个vip(虚拟IP)。这其实很好理解,因为它要拓展和自我恢复,容器的ip很不稳定容易改变。(虚拟ip和实际ip有个映射关系)
    • 它技术是通过LVS(Linux Virtual Server)实现的。 www.linuxvirtualserver.org
  2. nslookup命令介绍。查询DNS用的。例子: nslookup www.imooc.com 可以看到域名对应的ip地址
    在这里插入图片描述
# 启动一个whoam服务 网络连到demo上
docker service create --name whoami -p 8000:8000 --network demo -d jwilder/whoami
docker service ps whoami
# 访问它会返回hostname
curl 127.0.0.1:8000
# 启动一个busybox服务 网络连到demo上
docker service create --name client -d --network demo busybox sh -c "while true;do sleep 3600;done"
# 实验开始 进入client的容器中
docker exec -it c925c4dc5eb4 /bin/sh
# ping whoami服务名 可以ping通发现虚拟IP vip 10.0.0.10
ping whoami
# 拓展whoami 看下ping的地址会不会变 肯定不变呀 虚拟ip呀 vip 10.0.0.10
docker service scale whoami=3
ping whoami
# 在client容器中使用 nslookup查询 返回vip 10.0.0.10
nslookup whoami
# 在client容器中使用nslookup查询tasks.whoami可以看到容器ip
nslookup tasks.whoami
# client容器访问whoami服务 发现提供服务的是随机一台虚机 自动负载均衡
wget whoami:8000
more index.html
  1. LVS(Linux Virtual Server)技术介绍。
    • www.linuxvirtualserver.org 用于实现操作系统级别的Node Banlance
    • 这个技术由国人 章文松 实现。从阿里调到滴滴
    • 感兴趣可以实现:Ivs+keepalived配置高可用负载均衡集群。
      在这里插入图片描述
  2. Internal: Container和Container之间的访问通过overlay网络(vxlan技术)通信服务和服务之间通过VIP(LVS技术)虚拟IP通信 ,它会自动帮我们做负载均衡
    在这里插入图片描述

2.4 集群服务间通信之Routing Mesh体现-Ingress

  1. Ingress Network如果服务有绑定接口,则此服务可以通过任意swarm节点的相应接口访问。
    • 就是说任意节点都可以通过8080端口访问到我们的wordpress服务的技术就是Ingress Network
    • 外部访问的负载均衡
    • 服务端口被暴露到各个swarm节点
    • 内部通过IPVS进行负载均衡
      在这里插入图片描述
# 继续上面的实验环境
# 拓展whoami 3个变2个
docker service scale whoami=2
# 它会在两个节点上负载均衡
curl 127.0.0.1:8000
curl 127.0.0.1:8000
curl 127.0.0.1:8000
# 我们到没有容器的 work1上执行 发现可以访问 这就是Ingress Network的作用
curl 127.0.0.1:8000
# 通过命令查看网络转发的过程
sudo iptables -nL -t nat
# 查看work1网络 发现docker_gwbridge的地址和DOCKER-INGRESS网络在同一个网段上(那肯定有关系呀)
ip a 
# 继续 发现 DOCKER-INGRESS 就连在docker_gwbridge上
# 那就是说我们访问本地8000 这个请求转发到172.18.0.2:8000上
# 172.18.0.2:8000就是我们的ingress-sbox 它是一个network namespace
brctl show
docker network inspect docker_gwbridge

在这里插入图片描述
2. 我们访问本地8000 这个请求转发到172.18.0.2:8000上,172.18.0.2:8000就是我们的ingress-sbox 它是一个network namespace。
在这里插入图片描述
3. 继续试验。观察数据包走向

# 安装ipvsadm ipvs管理工具
sudo yum install ipvsadm
# 进入ingress sbox中 它是一个network namespace
sudo nsenter --net=/var/run/docker/netns/ingress_sbox
iptables -nL -t mangle
# 查看负载均衡
ipvsadm -l

在这里插入图片描述

第三节 Docker Stack部署Wordpress

3.1 swarm中docker-compose定义

  1. 我们知道本地开发工具docker-compose可以在本机上(单节点)部署应用。那么在docker swarm的集群中如何构建我们定义的应用呢。
    • 通过docker-compose定义应用,部署不用docker-compose而直接使用docker命令docker stack。
  2. docker-compose定义(version 3.3), 主要增加depoy命令:https://docs.docker.com/compose/compose-file/#replicas
    • 字段endpoint_mode :
      • vip(默认使用): 虚拟ip,service互相访问时,底层通过vip负载均衡成具体ip。
      • dnssr: 通过dns访问不通过vip,robin是负载均衡的策略,循环访问服务。
    • 字段labels : 帮助描述的信息。
    • 字段mode:
      • global: service不能通过scale做拓展。
      • replicated(默认): 可以进行横向拓展
    • 字段placement:主要设置限制条件。
      • 字段placemen下字段preferences 优先喜欢的设置。
      • constraints: node.role == manager 限制只运行在manager节点
    • 字段replicas: 一开始部署时就部署6个service.
    • 字段resources: 设置资源的限制。如:内存、cpu
    • 字段restart_policy: 重启的策略。如:尝试重启的次数
    • 字段update_config:
      • 字段update_config下parallelism字段: 同时更新的replicas个数
      • 字段update_config下delay字段: 更新间隔时间。

3.2 Wordpress部署案例

  1. 设置mysql不能拓展,只能在主节点上。
  2. wordpress可拓展, 设置拓展数为3。配置重启策略。。。
  3. 通过docker stack --help 命令部署。deploy、ls、ps、rm、services
  4. docker stack deploy wordpress --compose-file=docker-compose. yml
    • 执行发现服务上会加上 wordpress的 前缀名
# 通过docker stack在docker swarm cluster上部署应用
docker stack deploy wordpress --compose-file=docker-compose.yml
# 查看应用的信息
docker stack ps wordpress
# 删除应用 包括网络
docker stack rm wordpress
version: '3'

services:

  web:
    image: wordpress
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_PASSWORD: root
    networks:
      - my-network
    depends_on:
      - mysql
    deploy:
      mode: replicated
      replicas: 3
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
      update_config:
        parallelism: 1
        delay: 10s

  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: wordpress
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - my-network
    deploy:
      mode: global
      placement:
        constraints:
          - node.role == manager

volumes:
  mysql-data:

networks:
  my-network:
    driver: overlay

3.3 部署投票应用案例

  1. swarm模式下,docker-compose.yml网络类型默认是overlay类型。
  2. 这个例子和上面例子不同的是,镜像需要拉取,而不是构建。
  3. visualizer可视化工具: image: dockersamples/visualizer:stable
docker stack deploy example --compose-file=docker-compose.yml
docker stack services example
# 拓展vote service为三个 前面要加stack名字example
docker service scale example_vote=3
version: "3"
services:

  redis:
    image: redis:alpine
    ports:
      - "6379"
    networks:
      - frontend
    deploy:
      replicas: 2
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure

  db:
    image: postgres:9.4
    volumes:
      - db-data:/var/lib/postgresql/data
    networks:
      - backend
    deploy:
      placement:
        constraints: [node.role == manager]

  vote:
    image: dockersamples/examplevotingapp_vote:before
    ports:
      - 5000:80
    networks:
      - frontend
    depends_on:
      - redis
    deploy:
      replicas: 2
      update_config:
        parallelism: 2
      restart_policy:
        condition: on-failure

  result:
    image: dockersamples/examplevotingapp_result:before
    ports:
      - 5001:80
    networks:
      - backend
    depends_on:
      - db
    deploy:
      replicas: 1
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure

  worker:
    image: dockersamples/examplevotingapp_worker
    networks:
      - frontend
      - backend
    deploy:
      mode: replicated
      replicas: 1
      labels: [APP=VOTING]
      restart_policy:
        condition: on-failure
        delay: 10s
        max_attempts: 3
        window: 120s
      placement:
        constraints: [node.role == manager]

  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]

networks:
  frontend:
  backend:

volumes:
  db-data:

第四节 Docker Secret管理和使用

4.1 Docker Secret介绍和创建

  1. 什么是Secret
    • 用户名密码
    • SSH Key
    • TLS认证
    • 任何不想让别人看到的数据
  2. 密码管理,比如上面的wordpress,密码明文写在docker-compose.yml文件中。这肯定不安全呀
  3. 那怎么安全储存密码同时让service安全访问密码呢。
  4. Docker Swarm Mode Architecture(docker swarm架构图如下)
    在这里插入图片描述
  5. Secret Management
    • 存在Swarm Manager节点Raft database里。(加密的)
    • Secret可以assign给一个service ,这个service就能看到这个secret
    • 在container内部Secret看起来像文件,但是实际是在内存中
  6. docker secret create 创建密码
    • 方式一:从文件中创建密码 docker secret create my-pw password
    • 方式二:从标准输入创建密码: echo “adminadmin” | docker secret create my-pw2 -
  7. 如何使用创建的密码呢? 指定关键字 --secret my-pw。 这里可以传入多个。。。
  8. 上边的是传入一个 如果需要传入多个的话,就需要加入 --secret 名称1 --secret 名称2
# 写入密码admin123
vi password 
# 从文件中创建密码
docker secret create my-pw password
# 创建完密码 可以删除文件啦 防止别人看到密码
rm -rf password
# 通过下面命令 查看存储在Swarm Manager节点数据库中的密码数据
docker secret ls
# 从标准输入创建密码 最后有一个 - 符号别忘了
echo "adminadmin" | docker secret create my-pw2 -
docker secret ls
# 删除一个密码
docker secret rm my-pw2
docker secret ls
# 创建一个 可以访问到 my-pwd 的服务
docker service create --name client --secret my-pw busybox sh -c "while true; do sleep 3600; done"
# 进入到创建好的容器中
docker ps
docker exec -it ccee sh
# 进入容器文件夹 查看内容 发现自己创建的密码原文
cd /run/secrets/
cat my-pw
# 把密码传进来 当作mysql的root密码使用
docker service create --name db --secret my-pw -e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/my-pw mysql
# 进入容器验证root密码
docker exec -it 6dc34 sh
mysql -uroot -p

4.2 Docker Secret在docker-compose.yml中使用

  1. docker stack deploy wordpress -c=docker-compose.yml
  2. 在这个docker-compose最下面有个有三行注释,如果放开的话这是引用了外部密码文件的形式创建docker secret,这种方式虽然省事了,但是有安全隐患,里面多了个passwd文件,最好的方式还是通过docker secret create的方式。
  3. 如果报错: secrets Additional property secrets is not allowed 可能两个原因
    • Docker Engine<1.13.1
    • docker-compose.yml文件的版本号<“3.1”.
  4. 修改docker版本号,以及docker-compose.yml的版本号为3.4
version: '3.4'

services:

  web:
    image: wordpress
    ports:
      - 8080:80
    secrets:
      - my-pw
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_PASSWORD_FILE: /run/secrets/my-pw
    networks:
      - my-network
    depends_on:
      - mysql
    deploy:
      mode: replicated
      replicas: 3
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
      update_config:
        parallelism: 1
        delay: 10s

  mysql:
    image: mysql
    secrets:
      - my-pw
    environment:
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/my-pw
      MYSQL_DATABASE: wordpress
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - my-network
    deploy:
      mode: global
      placement:
        constraints:
          - node.role == manager

volumes:
  mysql-data:

networks:
  my-network:
    driver: overlay

secrets:
   my-pw:
     file: ./password

第五节 service更新

  1. 对运行中的service进行更新。
  2. swarm一般用于生产环境,我们不希望中断业务(不宕机)进行service更新。实际要比我们现在的演示要复杂的多。
  3. 更新命令:docker service update --help
    • 可以更新密码、发布端口、image等。
  4. docker stack没有–update。docker-compose.yml中有一些更新的配置
    • 如果是docker-compose.yml文件通过docker stack部署的service,对它更新时。直接修改docker-compose.yum文件, 然后docker stack deploy执行。它会自动分辨和上次的差别进行更新。
docker network ls
docker network create -d overlay demo
# 创建一个服务 tag是1.0版本
docker service create --name web --publish 8080:5000 --network demo xiaopeng163/python-flask-demo:1.0
# 更新过程 
# 第一步 拓展成两个以上节点 这样一个更新 另外一个仍可以跑业务。等跟新完在更新另一个
docker service scale web=2 
curl 127.0.0.1:8080 # hello docker, version 1
# 在swarm-worker1上一直访问 业务 模拟真实环境
sh -c "while true; do curl 192.168.205.10:8080&&sleep 1; done"
# 第二步 更新容器到2.0
docker service update --image xiaopeng163/python-flask-demo:2.0 web
# 发现有一段时间 是1.0和2.0版本共存的时刻。这个在实际业务中也是不允许的,可以思考一下怎么解决。

# 再做一次端口的更新 端口的中断一定业务会中断的(因为访问是通过vip+端口实现的)
docker service update --publish-rm 8080:5000 --publish-add 8088:5000 web
docker service ls
# 如果是docker-compose.yum文件通过docker stack部署的service,对它更新时。直接修改docker-compose.yum文件, 然后docker stack deploy执行。它会自动分辨和上次的差别进行更新。
发布了61 篇原创文章 · 获赞 8 · 访问量 2794

猜你喜欢

转载自blog.csdn.net/aa18855953229/article/details/105462981