zoukankan      html  css  js  c++  java
  • 使用docker快速部署一个consul集群

      作为一个开发者,有时候需要一个集群环境,之前的做法要么就是使用多个虚拟机,要么就是采用不同的端口来模拟,但是虚拟机比较占内存,而且启动慢,采用不同的端口来模拟,管理起来比较麻烦一些,程序隔离性差一些。

      docker的出现让我们可以在一台虚拟机上模拟构建出来一个几乎完全隔离的集群,本文提供一种快速构建consul集群的方法。

      首先我们需要consul的镜像,这个可以从dockerhub上获取:

      

      上面第一个就是consul官方的镜像  

        # 搜索镜像
        sudo docker search consul
        # 拉取镜像
        sudo docker pull consul

      获取到镜像之后,可以使用docker run运行,consul镜像运行的相关参数可以参考官方的文档

      consul镜像官方说明:https://registry.hub.docker.com/_/consul

      consul的官方文档:https://www.consul.io/docs

      直接使用docker run来启动一个consul节点的集群,如:

        # 不启用acl时,可直接执行下面的命令,创建一个只有一个节点的consul集群
        sudo docker run -id -expose=[8300,8301,8302,8500,8600] --restart always -p 18300:8300 -p 18301:8301 -p 18302:8302 -p 18500:8500 -p 18600:8600 --name server1 -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt": true}' consul agent -server -bootstrap-expect=1 -node=server1 -bind=0.0.0.0 -client=0.0.0.0 -ui -datacenter dc1
        # 启用acl是,只需要修改上面-e参数,如下面的命令,其中token_value可自行设置
        sudo docker run -id -expose=[8300,8301,8302,8500,8600] --restart always -p 18300:8300 -p 18301:8301 -p 18302:8302 -p 18500:8500 -p 18600:8600 --name server1 -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt": true,"acl": {"enabled": true,"default_policy": "deny","down_policy": "extend-cache","tokens": {"master": "token_value"}}}' consul agent -server -bootstrap-expect=1 -node=server1 -bind=0.0.0.0 -client=0.0.0.0 -ui -datacenter dc1
    
        各参数说明:
        -expose:暴露出出来的端口,即consul启动所需的端口:8300,8301,8302,8500,8600
        --restart:always表示容器挂了就自动重启
        -p:建立宿主机与容器的端口映射
        --name:容器名称
        -e:环境变量,这里用于对consul进行配置
        consul:这是consul镜像名,不是consul命令
        agent:容器中执行的命令,各参数含义:
                -server:表示节点是server类型
                -bootstrap-expect:表示集群中有几个server节点后开始选举leader,既然是单节点集群,那自然就是1了
                -node:节点名称
                -bind:集群内部通信地址,默认是0.0.0.0
                -client:客户端地址,默认是127.0.0.1
                -ui:启用consul的web页面管理
                -datacenter:数据中心
                更多配置参考:https://www.consul.io/docs/agent/options

      命令执行后,可以在浏览器上访问宿主机上的18500端口(映射到容器的8500),就可以访问到consul的web管理页面了,如果启动了acl,那么需要点击右上角的登录进行授权,授权值即上面自己设置的token_value,之后页面大概是这样子的:

      

      如果是启动一个多节点的consul集群,docker run管理起来就会非常繁琐,所以分享两种简单的管理方式:

      使用shell命令来管理

      自己可以写一个shell文件来时间集群的管理,比如:  

      
    #!/bin/bash
    
    servers=3                     #server节点数
    prefix_server="server"        #server节点名称前缀
    clients=3                     #client节点数
    prefix_client="client"        #client节点名称前缀
    datacenter="dc1"              #数据中心
    port_rpc=18100                #rpc端口(起始)(不包含)
    port_lan=18200                #lan端口(起始)(不包含)
    port_wan=18300                #wan端口(起始)(不包含)
    port_http=18400               #http端口(起始)(不包含)
    port_dns=18500                #dns端口(起始)(不包含)
    network_name="net-consul"     #docker网络名称
    token=                        #认证token,可以使用guid,之后连接需要携带token
    
    # 检查网络是否存在
    network_create(){
      if [ -z "$network_name" ];then
        echo network not exists
        exit 1
      fi
      
      if [ $(sudo docker network ls | grep -c "$network_name") -gt 0 ];then
        echo network [$network_name] exists
        return
      fi
    
      echo create network [$network_name]
      sudo docker network create --driver bridge $network_name > /dev/null
    }
    
    # 停止并删除docker容器
    node_down(){
      for i in $(seq 1 $2); do
        node_name="$1$i"
        sudo docker stop $node_name > /dev/null && sudo docker rm $node_name > /dev/null
        echo node [$node_name] removed
      done
    }
    
    # 停止运行docker容器
    node_stop(){
      for i in $(seq 1 $2); do
        node_name="$1$i"
        sudo docker stop $node_name > /dev/null
        echo node [$node_name] stoped
      done
    }
    
    # 生成一组可用的端口
    generate_ports(){
      port_rpc=`expr 1 + $port_rpc`
      port_lan=`expr 1 + $port_lan`
      port_wan=`expr 1 + $port_wan`
      port_http=`expr 1 + $port_http`
      port_dns=`expr 1 + $port_dns`
      
      p_rpc="$port_rpc:8300"
      p_lan="$port_lan:8301"
      p_wan="$port_wan:8302"
      p_http="$port_http:8500"
      p_dns="$port_dns:8600"
      
      bind_ports="-p $p_rpc -p $p_lan -p $p_wan -p $p_http -p $p_dns"
    }
    
    # 创建并运行集群
    consul_run(){  
      network_create
     
      if [ $servers -eq 0 ];then
        echo no servers
        exit 0
      fi
       
      common_agent="-bind=0.0.0.0 -client=0.0.0.0"
      common_docker="--network $network_name -expose=[8300,8301,8302,8500,8600] --restart always"
      
      #设置通用的环境变量
      if [ -z "$token" ];then
        e_server='CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt": true}'     # 不使用token 
      else 
        e_server='CONSUL_LOCAL_CONFIG=
        {
          "skip_leave_on_interrupt": true,
          "acl": {
            "enabled": true,
            "default_policy": "deny",
            "down_policy": "extend-cache",
            "tokens": {
              "master": "'$token'"
            }
          }
        }'
        echo server token:$token
      fi
      e_client='CONSUL_LOCAL_CONFIG={"leave_on_terminate": true}'
      
      # 创建并启动server节点  
      for i in $(seq 1 $servers); do
        node_name="$prefix_server$i"  #节点名称    
    
        generate_ports
        
        if [ $(sudo docker ps -a | grep -c "$node_name") -gt 0 ];then
          echo node [$node_name] exists
          continue
        fi
    
        node_join= 
        if [ $i -ne 1 ];then
          node_join="-join ${prefix_server}1"
        fi    
          
        sudo docker run -d $common_docker -e "$e_server" $bind_ports --name $node_name consul 
        agent -server -bootstrap-expect=$servers -node=$node_name $common_agent -ui -datacenter $datacenter $node_join > /dev/null
          
        echo "server node:[$node_name] is running => $p_rpc  $p_lan  $p_wan  $p_http  $p_dns"    
      done
      
      if [ $clients -gt 0 ];then
        sleep 3
      fi
      
      # 创建并启动client节点
      for i in $(seq 0 `expr $clients - 1`); do
        node_name="$prefix_client`expr $i + 1`"
        
        if [ $(sudo docker ps -a | grep -c "$node_name") -gt 0 ];then
          echo node [$node_name] exists
          continue
        fi
        
        generate_ports    
        server_node="$prefix_server`expr $i % $servers + 1`"
        
        sudo docker run -d $common_docker -e "$e_client" $bind_ports --name $node_name consul 
        agent -node=$node_name $common_agent -retry-join=$server_node > /dev/null
        
        echo "client node:[$node_name] is running => $p_rpc  $p_lan  $p_wan  $p_http  $p_dns"
      done
    }
    
    consul_down(){
      node_down $prefix_client $clients   
      node_down $prefix_server $servers   
    }
    
    consul_start(){
      if [ $servers -le 0 ];then
        echo invalid servers
        exit 2
      fi
    
      for i in $(seq 1 $servers); do
        node_name="$prefix_server$i"
        sudo docker start $node_name > /dev/null 
        echo node [$node_name] started
      done
      
      if [ $clients -gt 0 ];then
        sleep 3
      fi
    
      for i in $(seq 1 $clients); do
        node_name="$prefix_client$i"
        server_node_name="$prefix_server`expr $i % $servers + 1`"
        sudo docker start $node_name > /dev/null
        echo node [$node_name] started
      done
    }
    
    consul_stop(){
      node_stop $prefix_client $clients   
      node_stop $prefix_server $servers   
    }
    
    consul_up(){
      consul_run
      sleep 3
      consul_status
    }
    
    consul_restart(){
      consul_stop
      sleep 3
      consul_start
    }
    
    consul_logs(){
      sudo docker logs $1
    }
    
    consul_status(){
      para_token=
      if [ -n "$token" ];then
        para_token="-token $token"
      fi
      # 检测并等待leader选举
      consul_exec consul operator raft list-peers $para_token > /dev/null
      consul_exec consul members $para_token
    }
    
    consul_exec(){
        sudo docker exec -i ${prefix_server}1 $@
    }
    
    
    if [ ! -z "$1" ];then
      _args=$@
      _index=`expr index "$_args" " "`
      _args=`echo ${_args:$_index}`
      consul_$1 $_args
      exit 0
    fi
    
    echo "
    Usage:    $0 COMMAND
    
    可用命令:
    start    启动集群
    stop     停止集群服务
    up       创建并启动集群
    run      创建并启动集群
    down     停止并删除集群
    status   查看集群容器节点信息
    logs     输出指定节点的日志
    exec     在集群中的首个节点执行指定的命令
    restart  重新启动集群"
    consul.sh

      赋值上面的代码到一个sh文件,比如叫consul.sh,其中,文件开头是几个配置,可以修改:  

        servers=3                     #server节点数
        prefix_server="server"        #server节点名称前缀
        clients=3                     #client节点数
        prefix_client="client"        #client节点名称前缀
        datacenter="dc1"              #数据中心
        port_rpc=18100                #rpc端口(起始)(不包含)
        port_lan=18200                #lan端口(起始)(不包含)
        port_wan=18300                #wan端口(起始)(不包含)
        port_http=18400               #http端口(起始)(不包含)
        port_dns=18500                #dns端口(起始)(不包含)
        network_name="net-consul"     #docker网络名称
        token=                        #认证token,可以使用guid,之后连接需要携带token

      然后进行下面的操作:  

        # 赋予可执行的权限,脚本需要使用/bin/bash来执行,如果使用sh执行可能会报错,sh默认使用/bin/dash执行
        sudo chmod +x consul.sh 
        # 启动
        ./consul.sh up
        # 查看状态
        ./consul.sh status
        # 停止并删除
        ./consul.sh down

      如,启动后:

      

      然后可以在浏览器上访问数组机上对应server节点的8500端口的端口,比如这里的18401,18402,18403,就是打开consul的web管理页面了,如果需要token,就是文件中配置的token参数

      使用docker-compose来管理

      使用shell命令来管理可以很灵活的拓展,以及实现自己的需求,但是需要自行编码比较繁琐,如果需要拓展自己的一些功能,可以使用docker-compose来管理,如下面的内容复制到一个docker-compose.yml文件中:  

      
    # yaml 配置
    version: '2'
    services:
        server1:
            image: consul
            restart: always
            container_name: server1
            ports:
                - 18101:8300
                - 18201:8301
                - 18301:8302
                - 18401:8500
                - 18501:8600
            expose:
                - 8300
                - 8301
                - 8302
                - 8500
                - 8600
            command: agent -server -bootstrap-expect=3 -node=server1 -bind=0.0.0.0 -client=0.0.0.0 -ui -datacenter dc1 
            environment:
                # 不启用acl
                #CONSUL_LOCAL_CONFIG: '{"skip_leave_on_interrupt": true}'
                # 启用acl,下面的token_value是token值,可自行设置
                CONSUL_LOCAL_CONFIG: '{"skip_leave_on_interrupt": true,"acl": {"enabled": true,"default_policy": "deny","down_policy": "extend-cache","tokens": {"master": "token_value"}}}'        
        server2:
            image: consul
            restart: always
            container_name: server2
            ports:
                - 18102:8300
                - 18202:8301
                - 18302:8302
                - 18402:8500
                - 18502:8600
            expose:
                - 8300
                - 8301
                - 8302
                - 8500
                - 8600
            depends_on:
                - server1
            command: agent -server -bootstrap-expect=3 -node=server2 -bind=0.0.0.0 -client=0.0.0.0 -ui -datacenter dc1 -join server1
            environment:
                # 不启用acl
                #CONSUL_LOCAL_CONFIG: '{"skip_leave_on_interrupt": true}'
                # 启用acl,下面的token_value是token值,可自行设置
                CONSUL_LOCAL_CONFIG: '{"skip_leave_on_interrupt": true,"acl": {"enabled": true,"default_policy": "deny","down_policy": "extend-cache","tokens": {"master": "token_value"}}}'    
        server3:
            image: consul
            restart: always
            container_name: server3
            ports:
                - 18103:8300
                - 18203:8301
                - 18303:8302
                - 18403:8500
                - 18503:8600
            expose:
                - 8300
                - 8301
                - 8302
                - 8500
                - 8600
            depends_on:
                - server1
            command: agent -server -bootstrap-expect=3 -node=server3 -bind=0.0.0.0 -client=0.0.0.0 -ui -datacenter dc1 -join server1
            environment:
                # 不启用acl
                #CONSUL_LOCAL_CONFIG: '{"skip_leave_on_interrupt": true}'
                # 启用acl,下面的token_value是token值,可自行设置
                CONSUL_LOCAL_CONFIG: '{"skip_leave_on_interrupt": true,"acl": {"enabled": true,"default_policy": "deny","down_policy": "extend-cache","tokens": {"master": "token_value"}}}' 
        client1:
            image: consul
            restart: always
            container_name: client1
            ports:
                - 18104:8300
                - 18204:8301
                - 18304:8302
                - 18404:8500
                - 18504:8600
            expose:
                - 8300
                - 8301
                - 8302
                - 8500
                - 8600
            depends_on:
                - server1
            command: agent -node=client1 -bind=0.0.0.0 -client=0.0.0.0 -retry-join=server1
            environment:
                CONSUL_LOCAL_CONFIG: '{"leave_on_terminate": true}'
        client2:
            image: consul
            restart: always
            container_name: client2
            ports:
                - 18105:8300
                - 18205:8301
                - 18305:8302
                - 18405:8500
                - 18505:8600
            expose:
                - 8300
                - 8301
                - 8302
                - 8500
                - 8600
            depends_on:
                - server2
            command: agent -node=client2 -bind=0.0.0.0 -client=0.0.0.0 -retry-join=server2
            environment:
                CONSUL_LOCAL_CONFIG: '{"leave_on_terminate": true}'
        client3:
            image: consul
            restart: always
            container_name: client3
            ports:
                - 18106:8300
                - 18206:8301
                - 18306:8302
                - 18406:8500
                - 18506:8600
            expose:
                - 8300
                - 8301
                - 8302
                - 8500
                - 8600
            depends_on:
                - server3
            command: agent -node=client3 -bind=0.0.0.0 -client=0.0.0.0 -retry-join=server3
            environment:
                CONSUL_LOCAL_CONFIG: '{"leave_on_terminate": true}'      
    docker-compose.yml

      然后可以使用docker-compose来启动和停止

        # 启动
        sudo docker-compose up -d
        # 停止
        sudo docker-compose down

      启动后,如:

      

       同样的,这时可以在浏览器上访问数组机上对应server节点的8500端口的端口,比如这里的18401,18402,18403,就是打开consul的web管理页面了,如果需要token,就是文件中配置的token参数

    一个专注于.NetCore的技术小白
  • 相关阅读:
    LINUX系统运行查看
    MySQL数据库中tinyint类型字段读取数据为true和false (MySQL的boolean和tinyint(1))
    mysql DATE_FORMAT 年月日时分秒格式化
    fastJson泛型如何转换
    查找java程序进程快速指令jps
    vim快捷键
    mysql全库搜索指定字符串
    mysql一次性删除所有表而不删除数据库
    一键安装Docker图形化管理界面-Shipyard
    hadoop性能测试
  • 原文地址:https://www.cnblogs.com/shanfeng1000/p/15136682.html
Copyright © 2011-2022 走看看