zoukankan      html  css  js  c++  java
  • 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 : 拒绝眼高手低

  • 相关阅读:
    Scars To Your Beautiful
    【BZOJ1833】【ZJOI2010】数字计数(数位DP)
    滑块拼图
    神经元(prufer序列+dp)
    sequence(dp+hash+二分搜索+前缀和优化)
    循环移位(后缀自动机)
    MST(最小生成树+倍增)
    nyoj 845【水】
    分割问题【知识点】
    扩展欧几里得【知识点】
  • 原文地址:https://www.cnblogs.com/iamdoufu/p/4533063.html
Copyright © 2011-2022 走看看