【HECK】javascript
目的实现自动缩/扩容的高可用web架构。php
【软件介绍】css
一、Etcdhtml
Etcd是一个高可用的 Key/Value 存储系统,主要用于分享配置和服务发现。java
简单:支持 curl 方式的用户 API (HTTP+JSON)
安全:可选 SSL 客户端证书认证
快速:单实例可达每秒 1000 次写操做
可靠:使用 Raft 实现分布式node
二、Confdpython
Confd是一个轻量级的配置管理工具。经过查询Etcd,结合配置模板引擎,保持本地配置最新,同时具有按期探测机制,配置变动自动reload。linux
三、Haproxy介绍nginx
HAProxy是提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费、快速而且可靠的一种解决方案。git
【方案介绍】
首先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
一、建立一个web vm,ip:172.16.1.100
二、向etcd中添加一条配置相似以下:“group:bbs;name:bbs03;ip:172.16.1.100;”
三、confd会按期从etcd中拉取配置,从而发现。
四、图例
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
一、安装 KVM 和 virtinst (一个建立 virtual machines 的工具 )
# yum install kvm kmod-kvm qemu libvirt python-virtinst
或者
# yum groupinstall KVM
二、装完后记的重起,重起后检查模块是否有加载
# lsmod | grep kvm
可使用 virsh 来测试
# virsh -c qemu:///system list
3. 安装桥接管理的工具
# yum install bridge-utils
四、 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
五、图形界面安装:
安装 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语法】
一、做为path.Base函数的别名,获取路径最后一段。
{{ with get "/app/servers/prickly_blackwell"}}
server {{base .Key}} {{.Value}} check
{{end}}
结果:prickly_blackwell 192.168.1.22:49162
二、返回一对匹配的KV,找不到则返回错误。
{{with get "/app/servers/prickly_blackwell"}}
key: {{.Key}}
value: {{.Value}}
{{end}}
结果:/app/servers/prickly_blackwell 192.168.1.22:49162
三、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
四、getv
返回一个匹配key的字符串型Value,找不到则返回错误。
{{getv "/app/servers/cocky_morse"}}
结果:192.168.1.22:49158
五、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
六、split 对输入的字符串作split处理,即将字符串按指定分隔符拆分红数组。
{{ $url := split (getv "/app/servers/cocky_morse") ":" }}
host: {{index $url 0}}
port: {{index $url 1}}
结果:
host: 192.168.1.22
port: 49158
七、ls 返回全部的字符串型子key,找不到则返回错误。
{{range ls "/app/servers/"}}
subkey: {{.}}
{{end}}
结果:
subkey: backstabbing_rosalind
subkey: cocky_morse
subkey: goofy_goldstine
subkey: prickly_blackwell
八、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"
核心命令:
一、virt-clone -n $vmname -o $image -f $vmfile
二、virt-edit $vmfile /etc/sysconfig/network-scripts/ifcfg-eth0 -e 's/^IPADDR.*/IPADDR='$vmip'/m'
三、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 : 拒绝眼高手低