Docker学习——DockerSwarm集群

文章目录

    • 前言
    • Swarm简介
    • Docker swarm环境搭建
    • Service的创建维护和水平扩展
    • 集群服务间通信之Routing Mes
    • Docker stack部署复杂应用至集群
    • Docker Secret管理和使用

前言

环境准备

多台安装了Docker的虚拟机,我使用的是在windows10上安装virtualbox和vagrant来创建多台虚拟机。

关于vagrant和virtualbox的操作以及环境搭建可以看我以前写的这篇文章:使用virtualbox和vagrant搭建Docker环境。

Vagrantfile内容:

# -*- mode: ruby -*-

Vagrant.require_version ">= 1.6.0"

boxes = [
    {
        :name => "vagrant1",
        :eth1 => "192.168.205.10",
        :mem => "1024",
        :cpu => "1"
    },
    {
        :name => "vagran2",
        :eth1 => "192.168.205.11",
        :mem => "1024",
        :cpu => "1"
    },
    {
        :name => "vagran3",
        :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

在vagrantfile中直接引用了安装Docker的setup.sh脚本,setup.sh脚本内容:

#/bin/sh

# install some tools
sudo yum install -y git vim gcc glibc-static telnet bridge-utils

# install docker
curl -fsSL get.docker.com -o get-docker.sh
sh get-docker.sh

# start docker service
sudo groupadd docker
sudo gpasswd -a vagrant docker
sudo systemctl start docker

rm -rf get-docker.sh

Swarm简介

Docker swarm是Docker的集群管理工具。

swarm 集群由管理节点(manager)和工作节点(work node)构成 。

  • swarm mananger:负责整个集群的管理工作包括集群配置、服务管理等所有跟集群有关的工作。

  • work node:即图中的 available node,主要负责运行相应的服务来执行任务(task)。
    Docker学习——DockerSwarm集群_第1张图片

  • service: Swarm用service管理容器,一个service就是一个容器,使用swarm创建容器的时候,该容器可能会运行在任何一个节点上。

Docker swarm环境搭建

  • 选中manager主机执行:

    $ docker swarm init --advertise-addr
    

Docker学习——DockerSwarm集群_第2张图片

  • 在另一台主机上执行上边那句话加入work node:
    在这里插入图片描述

  • 当在以后想要再加入work节点的时候,可以在manager主机上执行docker swarm join-token manager查看token:
    在这里插入图片描述

Service的创建维护和水平扩展

docker service create创建并运行一个service容器:

docker service create --name demo busybox sh -c "while true; do sleep 3600;done"

docker service ls查看运行中的service:

[vagrant@vagrant1 ~]$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
eixl0pvhw572        demo                replicated          1/1                 busybox:latest

  • 当NODE是replicated时表示该容器可以横向扩展:
    在这里插入图片描述

    docker service scale可以横向扩展容器在不同节点的运行数量,在使用docker service ls发现REPLICAS数量变为了5:
    Docker学习——DockerSwarm集群_第3张图片
    Docker学习——DockerSwarm集群_第4张图片

    docker service ps命令可以查看service运行的详情,查看下扩展的demo容器在各个节点的运行详情:
    Docker学习——DockerSwarm集群_第5张图片

    如果删除其中一个节点运行的容器会发生什么呢?

    到vagrant1节点,先docker ps查看下运行中的容器,在使用docker rm -f强制删除demo1:
    在这里插入图片描述

    在使用docker service ls会发现还是有5个运行着的service, 这是因为使用scale命令扩展的service,当其中一个停止以后会在新的节点创建并运行相同的service:
    Docker学习——DockerSwarm集群_第6张图片

docker service rm可以删除运行着的service(包括所有节点上的):
Docker学习——DockerSwarm集群_第7张图片

  • 我们创建service的时候可以指定运行的节点, 比如说我要创建一个nginx指定运行在vagrant3节点上:

    1. 给节点打上标签:docker node update --label-add func=nginx vagrant3 , func=nginx

    2. 在创建service是指定containt参数

      docker service create --name vagrant3_nginx --constraint 'node.labels.func == nginx' nginx
      

不同节点间的网络通信

当使用Swarm创建service集群的时候会分布在不同的节点,那么不同的节点之间如何通信呢?

docker Swarm创建overlay网络会在不同的节点同步该网络

所以可以使用overlay网络来连接不同节点间的service:

  • 首先创建一个overlay网络:

    docker network create -d overlay my_overlay
    
  • 在创建service时指定网络为overlay就可以了,比如通过service部署一个wordpress(需要一个mysql容器和wordpress容器):

    创建mysql指定网络为overlay, 指定两个环境变量以及挂载。

    docker service create --name mysql --network my-overlay --env MYSQL_ROOT_PASSWORD=root --env MYSQL_DATABASE=wordpress --mount type=volume,source=mysql-data,destination=/var/lib/mysql mysql
    

    创建wordpress指定网络为overlay, 指定两个环境变量以及端口映射:

    docker service create --name --network my-overlay wordpress -p 80:80 --env WORDPRESS_DB_PASSWORD=root --env WORDPRESS_DB_HOST=mysql wordpress
    

集群服务间通信之Routing Mes

使用Docker Swarm创建集群的时候默认使用的是overlay网络,在overlay网络上集群上的service之间可以互相通过service name进行通信的,其底层是通过DNS服务实现的。

当我们使用overlay网络创建一个service的时候,docker内置的DNS服务会给该service一个DNS记录,DNS的name是service的name,但是DNS对应的ip是一个虚拟ip并不是该service所在节点的ip(因为节点的ip可以能会改变,如果使用节点ip作为DNS记录会不稳定,使用虚拟ip就不会发生这种情况), 该ip只是为了标记该service所在节点的位置。
Docker学习——DockerSwarm集群_第8张图片

下面通过一个实验来验证:

  • 首先确保有一个overlay网络

  • 创建一个service使用overlay网络:

    docker service create --name whoami -p 8000:8000 --network my-overlay -d jwilder/whoami
    
  • 在创建一个service使用overlay网络:

    docker service create --name client -d --network my-overlay busybox sh -c "while true; do sleep 3600; done"
    
  • 在docker manager主机上使用docker service ps client查看下client service所在的主机,进入client service 的后台,ping whoami service发现ping的ip是10.0.2.2,这个ip就是DNS服务给绑定的虚拟ip:
    Docker学习——DockerSwarm集群_第9张图片

  • 现在将whoami service扩展到两个,在进入client ping whoami service发现ping的ip还是10.0.2.2:
    在这里插入图片描述
    Docker学习——DockerSwarm集群_第10张图片

    Routing Mesh的两种体现

  • Internal——Container和Container之间的访问通过overlay网络(通过VIP虚拟IP)。

  • Ingress——如果服务有绑定接口,则此服务可以通过任意swarm节点相应接口访问。

当web service使用scale扩展至多个节点时,docker内置的DNS服务也会绑定多个虚拟IP,当我们通过client service去访问web service时,DNS服务会动态的让我们访问不同的节点上的web service,达到服务端负载均衡的目的,当然前提是在同一个overlay网络下。
Docker学习——DockerSwarm集群_第11张图片

client service一个具体的请求时通过DNS + VIP + iptable + LVS整个解析路径来达到负载均衡的。

  • 当client容器发起一个对web service name 的请求时,首先DNS会解析这个name为VIP,然后在通过iptables 和 ipvs来动态转换地址至对应的web service达到负载均衡的目的。
    Docker学习——DockerSwarm集群_第12张图片

Docker stack部署复杂应用至集群

  • 准备yum文件,使用Docker stack部署时image只能使用从官方拉取的镜像,不能使用Dockerfile文件:
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:
      	# 使用manager节点
        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:
      	# 使用manager节点
        constraints: [node.role == manager]

# 网络不写驱动默认为overlay网络
networks:
  frontend:
  backend:

volumes:
  db-data:
  • 执行deploy命令:

    [root@vagrant1 example-vote-app]# docker stack deploy example --compose-file=docker-compose.yml
    
  • 使用docker stack ls查看service:
    在这里插入图片描述

    使用docker stack services example查看这6个services:
    Docker学习——DockerSwarm集群_第13张图片

    浏览器输入ip查看投票应用:
    Docker学习——DockerSwarm集群_第14张图片

5001端口查看投票结果(需要):
Docker学习——DockerSwarm集群_第15张图片

Docker Secret管理和使用

Docker Secret 用于保存敏感信息。

创建

docker secret create命令创建,发现可以通过文件或者标准输入创建。

bash-4.2$ docker secret create
"docker secret create" requires at least 1 and at most 2 arguments.
See 'docker secret create --help'.

Usage:  docker secret create [OPTIONS] SECRET [file|-]

Create a secret from a file or STDIN as content

通过文件创建:

  • 首先创建一个叫做password的文件,里边写上密码:admin123:

  • 执行docker secret create my-pw password就可以将password文件下的内容存入Docker节点中:

    bash-4.2$ docker secret create my-pw password
    mxisg7k2xzzot7pcsv1dl1r4e
    

    存入节点后为了防止密码文件泄漏,此时可以将password文件删除:

    bash-4.2$ rm -f password
    
  • 通过docker secret ls可以查看当前存入的内容:

    bash-4.2$ docker secret ls
    ID                          NAME                DRIVER              CREATED              UPDATED
    mxisg7k2xzzot7pcsv1dl1r4e   my-pw                                   About a minute ago   About a minute ago
    

通过标准输入:

bash-4.2$ echo "admin123" | docker secret create my-pw2 -
r3ojwxv0289tb4wt4lukxm2yr

使用docker secret ls此时可以查看到两个:

bash-4.2$ docker secret ls
ID                          NAME                DRIVER              CREATED             UPDATED
mxisg7k2xzzot7pcsv1dl1r4e   my-pw                                   5 minutes ago       5 minutes ago
r3ojwxv0289tb4wt4lukxm2yr   my-pw2                                  38 seconds ago      38 seconds ago

删除

使用命令docker secret rm可以删除。

查看详情

docker secret inspect

bash-4.2$ docker secret inspect mxisg7k2xzzot7pcsv1dl1r4e
[
    {
        "ID": "mxisg7k2xzzot7pcsv1dl1r4e",
        "Version": {
            "Index": 21
        },
        "CreatedAt": "2020-10-18T14:43:45.00358644Z",
        "UpdatedAt": "2020-10-18T14:43:45.00358644Z",
        "Spec": {
            "Name": "my-pw",
            "Labels": {}
        }
    }
]

service中使用secret

指定参数--secret就可以使用:

bash-4.2$ docker service create --name client --secret my-pw busybox sh -c "while true; do sleep 3600; done"
6ublh03hz0806i5l894agfyqh
overall progress: 1 out of 1 tasks 
1/1: running   
verify: Service converged 

进入该service的后台,secret保存在/run/secrets/目录下:

bash-4.2$ docker exec -it 05b sh
/ # 
/ # 
/ # cd /run/secrets/
/run/secrets # ls
my-pw
/run/secrets # cat my-pw
admin123
/run/secrets # 

创建一个Mysql的service, root密码从环境变量中读取,而环境变量信息又是从secret中获取:

bash-4.2$ docker service create --name db --secret my-pw -e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/my-pw mysql
zf5v4dulpxygt6lmlto3nda4d

找到该service的结点进入后台使用secret中的密码登录root用户:
Docker学习——DockerSwarm集群_第16张图片

在stack 中使用secret

在yum文件中指定secrets, 需要注意的是这里的my-pw是需要提前创建好的:

version: '3'

services:
  web:
    image: wordpress
    ports:
      - 8080:80
    secrets:
      - my-pw
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_PASSWORD_FILE: /run/secrets/my-pw
$ docker service create --name db --secret my-pw -e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/my-pw mysql
zf5v4dulpxygt6lmlto3nda4d

找到该service的结点进入后台使用secret中的密码登录root用户:

[外链图片转存中…(img-KcZ0VBvD-1603035582880)]

在stack 中使用secret

在yum文件中指定secrets, 需要注意的是这里的my-pw是需要提前创建好的:

version: '3'

services:
  web:
    image: wordpress
    ports:
      - 8080:80
    secrets:
      - my-pw
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_PASSWORD_FILE: /run/secrets/my-pw

你可能感兴趣的:(Docker,docker,docker,swarm)