HECK:haproxy+etcd+confd+kvm 实现高可用自动化发现基础架构

【HECK】

  目的实现自动缩/扩容的高可用web架构。

【软件介绍】

  1、Etcd

    Etcd是一个高可用的 Key/Value 存储系统,主要用于分享配置和服务发现。

     简单:支持 curl 方式的用户 API (HTTP+JSON)
     安全:可选 SSL 客户端证书认证
     快速:单实例可达每秒 1000 次写操作
     可靠:使用 Raft 实现分布式

  2、Confd

    Confd是一个轻量级的配置管理工具。通过查询Etcd,结合配置模板引擎,保持本地配置最新,同时具备定期探测机制,配置变更自动reload。

  3、Haproxy介绍

    HAProxy是提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。

  

【方案介绍】

  首先web解决方案是haproxy+web(nginx)实现。

  KVM+Etcd+Confd实现自动发现上线到haproxy里面。

  

  web方案:haproxy+nginx。haproxy公用配置,http reuest路由到不同的ha如:a.domain.com通过ha1转发,b.domain.com通过ha2转发

  haproxy高可用:haproxy+keepalived实现haproxy高可用

  etcd高可用:haproxy+keepalived实现etcd的高可用(etcd本身只实现写操作被转发到etcd leader上)

  confd:配置管理,配置自动拉去etcd中的配置项

  web服务:kvm+web镜像(linux+nginx+php),通过kvm实现web增删

  举例:添加一台bbs组下的web

  1、创建一个web vm,ip:172.16.1.100

  2、向etcd中添加一条配置类似如下:“group:bbs;name:bbs03;ip:172.16.1.100;”

  3、confd会定期从etcd中拉取配置,从而发现。

  4、图例

  

  PS:kvm的可替代方案docker,etcd+confd的可替代方案puppet

【安装过程】

  搭建概述

  [test01:172.17.59.81] ha+confd
    HA-Proxy version 1.5.2
    Confd version confd 0.9.0
  [test02:172.17.59.82] etcd
    etcd version 2.0.5
  [web01:172.17.59.110] vm
    CentOS release 6.5 (Final)

  

  test01:安装haproxy、confd
    #yum install haproxy

    # wget https://github.com/kelseyhightower/confd/releases/download/v0.9.0/confd-0.9.0-linux-amd64 -O confd //获得git当时最新版本的confd
    # mv confd /usr/local/bin/confd
    # chmod +x /usr/local/bin/confd
    # /usr/local/bin/confd -version

  test02:安装etcd
    # curl -L https://github.com/coreos/etcd/releases/download/v2.0.5/etcd-v2.0.5-linux-amd64.tar.gz -o etcd-v2.0.5-linux-amd64.tar.gz
    # tar xzvf etcd-v2.0.5-linux-amd64.tar.gz
    # cd etcd-v2.0.5-linux-amd64
    # cp etcd* /bin/
    # etcd --version

  test03:安装kvm
    1、安装 KVM 和 virtinst (一个创建 virtual machines 的工具 )
      # yum install kvm kmod-kvm qemu libvirt python-virtinst
      或者
      # yum groupinstall KVM

    2、装完后记的重起,重起后检查模块是否有加载
      # lsmod | grep kvm
      可以使用 virsh 来测试
      # virsh -c qemu:///system list

    3. 安装桥接管理的工具
      # yum install bridge-utils

    4、 virt-install安装虚拟机
      光盘安装:( 在图形界面下)
      # virt-install --name Kcentos_01 --ram 700 --vcpus=2 --disk path=/var/virt_images/Kcentos_01.img,size=10 –bridge=br0 --os-type=linux --os-variant=rhel5.4 --accelerate --cdrom=/dev/cdrom –vnc

      其他安装可以查看:virt-install –help

    5、图形界面安装:
      安装 GUI 的管理软件
      # yum install virt-manager
      # virt-manager安装虚拟机

    ============================================================================================

    3 网络配置(br0)
      # vim /etc/sysconfig/network-scripts/ifcfg-br0

      BOOTPROTO=static
      DEVICE=br0
      TYPE=Bridge
      ONBOOT=yes
      IPADDR=172.16.0.99
      NETMASK=255.255.0.0
      GATEWAY=172.16.0.1

      # vim /etc/sysconfig/network-scripts/ifcfg-eth0

      DEVICE=eth0
      ONBOOT=yes
      BRIDGE=br0    

      # /etc/init.d/network restart

      #没尝试vnc链接,直接在服务器端视窗里面运行了 virt-viewer red-1 安装的。
      #vnc配置
      #修改vnc监听端口,放开使vnc监听所有网段
      # vim /etc/libvirt/qemu.conf

      vnc_listen = "0.0.0.0"
      vnc_password = "123456"

 【配置过程】

  [Etcd配置]

    【启动】没有配置 直接启动
    #/bin/etcd -name etcd01

    -peer-addr 172.17.59.82:7001

    -addr 172.17.59.82:4001

    -data-dir /data/etcd

    -peer-bind-addr 0.0.0.0:7001

    -bind-addr 0.0.0.0:4001

    -initial-cluster etcd01='http://172.17.59.82:4001'

    -initial-cluster-state new &

  

    

    【使用方法】
    # curl -L http://172.17.59.82:4001/v2/keys/mykey -XPUT -d value="my value"
    {"action":"set","node":{"key":"/mykey","value":"my value","modifiedIndex":6,"createdIndex":6},"prevNode":{"key":"/mykey","value":"my value","modifiedIndex":5,"createdIndex":5}}
    # curl -L http://172.17.59.82:4001/v2/keys/mykey
    {"action":"get","node":{"key":"/mykey","value":"my value","modifiedIndex":6,"createdIndex":6}}
    # curl -L http://172.17.59.82:4001/v2/keys/mykey -XDELETE
    {"action":"delete","node":{"key":"/mykey","modifiedIndex":7,"createdIndex":6},"prevNode":{"key":"/mykey","value":"my value","modifiedIndex":6,"createdIndex":6}}
    # curl -L http://172.17.59.82:4001/v2/keys/mykey&?recursive=true ###批量获取

  

  [confd + haproxy 配置] haproxy使用的配置是confd的haproxy模板生成的

    【在etcd中添加配置】
    # curl -XPUT http://172.17.59.82:4001/v2/keys/app/servers/{servername} -d value="{ip}:{port}"

    

    【cond 启动】
    # /usr/local/bin/confd -verbose -interval 10 -node '172.17.59.82:4001' -confdir /etc/confd > /var/log/confd.log &

  

    【haproxy 启动】
    # /etc/init.d/haproxy start

    【confd配置:只有haproxy的配置】

      [配置文件]

      # cat /etc/confd/conf.d/haproxy.toml 

[template] 
  src = "haproxy.cfg.tmpl" 
  dest = "/etc/haproxy/haproxy.cfg" 
  keys = [ 
     "/app/servers", 
  ] 
reload_cmd = "/etc/init.d/haproxy reload"

      [模板文件]

      # cat /etc/confd/templates/haproxy.cfg.tmpl
      

global
    log         127.0.0.1 local2

    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon

    stats socket /var/lib/haproxy/stats

defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000

frontend  main *:80
    acl url_static       path_beg       -i /static /images /javascript /stylesheets
    acl url_static       path_end       -i .jpg .gif .png .css .js

    use_backend static          if url_static
    default_backend             app


backend static
    balance     roundrobin
    server      static 172.17.59.83:80 check

backend app
    balance     roundrobin
    {{range gets "/app/servers/*"}}
    server {{base .Key}} {{.Value}} check inter 5000 fall 1 rise 2
    {{end}}


listen status *:8080
    stats enable
    stats uri /stats
    stats auth admin:123456
    stats realm (Haproxy statistic)

    【confd语法】
    1、作为path.Base函数的别名,获取路径最后一段。
    {{ with get "/app/servers/prickly_blackwell"}}
      server {{base .Key}} {{.Value}} check
    {{end}}

    结果:prickly_blackwell 192.168.1.22:49162

    2、返回一对匹配的KV,找不到则返回错误。
    {{with get "/app/servers/prickly_blackwell"}}
      key: {{.Key}}
      value: {{.Value}}
    {{end}}

    结果:/app/servers/prickly_blackwell 192.168.1.22:49162

    3、gets 返回所有匹配的KV,找不到则返回错误。
    {{range gets "/app/servers/*"}}
      {{.Key}} {{.Value}}
    {{end}}

    /app/servers/backstabbing_rosalind 192.168.1.22:49156
    /app/servers/cocky_morse 192.168.1.22:49158
    /app/servers/goofy_goldstine 192.168.1.22:49160
    /app/servers/prickly_blackwell 192.168.1.22:49162

    4、getv
      返回一个匹配key的字符串型Value,找不到则返回错误。
      {{getv "/app/servers/cocky_morse"}}

      结果:192.168.1.22:49158

    5、getvs
      返回所有匹配key的字符串型Value,找不到则返回错误。
      {{range getvs "/app/servers/*"}}
        value: {{.}}
      {{end}}

      结果:

      value: 192.168.1.22:49156
      value: 192.168.1.22:49158
      value: 192.168.1.22:49160
      value: 192.168.1.22:49162

    

    6、split 对输入的字符串做split处理,即将字符串按指定分隔符拆分成数组。
      {{ $url := split (getv "/app/servers/cocky_morse") ":" }}
      host: {{index $url 0}}
      port: {{index $url 1}}

      结果: 

      host: 192.168.1.22 

      port: 49158


    7、ls 返回所有的字符串型子key,找不到则返回错误。
      {{range ls "/app/servers/"}}
        subkey: {{.}}
      {{end}}

      结果:

      subkey: backstabbing_rosalind
      subkey: cocky_morse
      subkey: goofy_goldstine
      subkey: prickly_blackwell

    8、lsdir 返回所有的字符串型子目录,找不到则返回一个空列表。
      {{range lsdir "/app/"}}
        subdir: {{.}}
      {{end}}

      结果:subdir: servers

  

  【kvm clone】
  # virt-clone 是可以指定mac和uuid的,不指定的话会自动生成
  # virt-clone -o rhel5.4_32_2 -n rhel5.4_32_3 -f /dev/libvirt_lvm/rhel5.4-3 -m 52:54:00:31:15:40

  PS:博主镜像创建的时候只安装了nginx,需要将 chkconfig nginx on 

【自动创建vm的shell脚本】

    #!/bin/bash
    vmname=$1
    image=$2
    vmip=$3
    vmfile="/datadir/kvm/$vmname.qcow2"
    etcdurl='http://172.17.59.82:4001'

    if [ ! $1 ]; then
        echo "vmname must specify"
        echo "USAGE : sh addweb.sh {vmname} {image} {vmip}"
        exit
    fi
    if [ ! $3 ]; then
        echo "vmip must specify"
        echo "USAGE : sh addweb.sh {vmname} {image} {vmip}"
        exit
    fi

    ####### mk vm
    #kvm clone
    virt-clone -n $vmname -o $image -f $vmfile
    if [ $? -ne 0 ]; then
        echo "Clone vm $vmname faild"
        exit
    fi

    #specify vm IP
    virt-edit $vmfile /etc/sysconfig/network-scripts/ifcfg-eth0 -e 's/^IPADDR.*/IPADDR='$vmip'/m'
    if [ $? -ne 0 ]; then
        echo "Specify ip faild"
        exit
    fi

    #edit vm vnc port

    #start vm
    virsh start $vmname
    virsh autostart $vmname
    if [ $? -ne 0 ]; then
        echo "start vm:$vmname faild"
        exit
    fi

    ####### virsh start $vmname

    # set etcd
    curl -XPUT $etcdurl/v2/keys/app/servers/$vmname -d value="$vmip:80"

  核心命令:

    1、virt-clone -n $vmname -o $image -f $vmfile
    2、virt-edit $vmfile /etc/sysconfig/network-scripts/ifcfg-eth0 -e 's/^IPADDR.*/IPADDR='$vmip'/m'
    3、curl -XPUT $etcdurl/v2/keys/app/servers/$vmname -d value="$vmip:80"

【踩过的坑】  

  1 : etcd启动失败
    屏显报错:etcd: couldn't find local name "etcdserver01" in the initial cluster configuration
    解决方式:添加-initial-cluster参数,见启动etcd命令

  2 :启动vm后无法立即使用

    #在源镜像上删除
    # /etc/udev/rules.d/70-persistent-net.rules

  3 :kvm设置ip
    # virt-edit $vmfile /etc/sysconfig/network-scripts/ifcfg-eth0 -e 's/^IPADDR.*/IPADDR='$vmip'/m'

  4 : vnc端口设置

    virsh edit test03  # vnc端口设置成-1,以后通过virsh vncdisplay {domain}查看vnc端口

  5 : nginx 输出当前服务器IP

    楼主使用的sub_filter,替换nginx默认index.html里面的一段文字,如下图所示

    location / {
      root   /usr/share/nginx/html;
      index  index.html index.htm;

      sub_filter  'search string' $server_addr;
      sub_filter_once off;
    }

  

【参考文档】

  * HECD 一个高可用及自动发现的Docker基础架构(博主主要参考的文章)
  http://blog.liuts.com/post/242/ 

  Docker中文文档
  http://yeasy.gitbooks.io/docker_practice/content/ 

  etcd官网
  https://coreos.com/etcd/ 

  etcd@git
  https://github.com/coreos/etcd 

  etcd集群
  https://github.com/coreos/etcd/blob/master/Documentation/clustering.md#etcd-discovery 

  confd@git
  https://github.com/kelseyhightower/confd/ 

PS : 拒绝眼高手低

原文地址:https://www.cnblogs.com/iamdoufu/p/4533063.html