• 使用Ansible实现nginx+keepalived高可用负载均衡自动化部署


    本篇文章记录通过Ansible自动化部署nginx的负载均衡高可用,前端代理使用nginx+keepalived,端web server使用3台nginx用于负载效果的体现,结构图如下:

    部署前准备工作

    主机规划

    • Ansible : 192.168.214.144
    • Keepalived-node-1 : 192.168.214.148
    • Keepalived-node-2 : 192.168.214.143
    • web1 : 192.168.214.133
    • web2 : 192.168.214.135
    • web3 : 192.168.214.139

    Ansible主机与远程主机秘钥认证

    #!/bin/bash
    
    keypath=/root/.ssh
    [ -d ${keypath} ] || mkdir -p ${keypath}
    rpm -q expect &> /dev/null || yum install expect -y
    ssh-keygen -t rsa -f /root/.ssh/id_rsa  -P ""
    password=fsz...
    while read ip;do
    expect <<EOF
    set timeout 5
    spawn ssh-copy-id $ip
    expect {
    "yes/no" { send "yes
    ";exp_continue }
    "password" { send "$password
    "  }
    }
    expect eof
    EOF
    done < /home/iplist.txt
    
    

    iplist.txt

    192.168.214.148
    192.168.214.143
    192.168.214.133
    192.168.214.135
    192.168.214.139
    192.168.214.134
    

    执行脚本

    [root@Ansible script]# ./autokey.sh

    测试验证

    [root@Ansible script]# ssh 192.168.214.148 'date'
    Address 192.168.214.148 maps to localhost, but this does not map back to the address - POSSIBLE BREAK-IN ATTEMPT!
    Sat Jul 14 11:35:21 CST 2018
    

    配置Ansible基于主机名认证,方便单独管理远程主机

    vim  /etc/hosts
    #
    127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
    192.168.214.148 node-1
    192.168.214.143 node-2
    192.168.214.133 web-1
    192.168.214.135 web-2
    192.168.214.139 web-3
    
    

    安装配置Ansible

    #安装ansible
    [root@Ansible ~]# yum install ansible -y
    
    #配置ansible主机清单
    [root@Ansible ~]# vim /etc/ansible/hosts 
    [all]
    
    192.168.214.148
    192.168.214.143
    192.168.214.133
    192.168.214.135
    192.168.214.139
    
    [node]
    
    192.168.214.148
    192.168.214.143
    
    [web]
    192.168.214.133 
    192.168.214.135
    192.168.214.139
    
    #Ansible执行ping测试 
     [root@Ansible ~]# ansible all -m ping
    

    编写roles,实现web的部署

    先看一下web的目录结构

    [root@Ansible ~]# tree /opt/roles/web
    /opt/roles/web
    .
    ├── tasks
    │   ├── install_nginx.yml
    │   ├── main.yml
    │   ├── start.yml
    │   ├── temps.yml
    │   └── user.yml
    └── templates
        ├── index.html.j2
        └── nginx.conf.j2
    
    2 directories, 7 files
    
    

    按照角色执行的顺序编写

    编写user.yml

    - name: create group nginx
      group: name=nginx
    - name: create user nginx
      user: name=nginx group=nginx system=yes shell=/sbin/nologin
    
    

    编写install_nginx.yml

    - name: install nginx webserver
      yum: name=nginx
    

    创建nginx配置文件的template模板
    由于是测试,后端web服务的nginx.conf配置文件基本保持默认,只只更具后端主机情况设置worker进程数,使用ansible的setup模块中的变量获取远程主机的cpu的数量值

    
    #将配置文件转换成template文件
    [root@Ansible conf]# cp nginx.conf /opt/roles/web/templates/nginx.conf.j2
    #做出修改的内容如下
    worker_processes {{ansible_proccessor_vcpus}};
    
    #在templates目录写一个测试页内如下
    vim index.html.j2
    {{ ansible_hostname }} test page.
    

    编写temps.yml

    - name: cp nginx.conf.j2 to nginx web server rename nginx.conf
      template: src=/opt/roles/web/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
    - name: cp index test page to nginx server
      template: src=/opt/roles/web/templates/index.html.j2 dest=/usr/share/nginx/html/index.html
    
    

    编写start.yml

    - name: restart nginx
      service: name=nginx state=started
    

    编写main.yml

    - import_tasks: user.yml
    - import_tasks: install_nginx.yml
    - import_tasks: temps.yml
    - import_tasks: start.yml
    

    编写执行主文件web_install.yml,执行文件不能与web角色放在同一目录,通常放在roles目录

    [root@Ansible ~]# vim /opt/roles/web_install.yml 
    
    
    ---
    - hosts: web
      remote_user: root
      roles:
        - web
    

    安装前测试: -C选项为测试

    [root@Ansible ~]# ansible-playbook -C /opt/roles/web_install.yml 
    

    如没有问题则执行安装

    [root@Ansible ~]# ansible-playbook /opt/roles/web_install.yml 
    

    测试访问

    [root@Ansible ~]# ansible web -m shell -a 'iptables -F'
    192.168.214.139 | SUCCESS | rc=0 >>
    
    
    192.168.214.135 | SUCCESS | rc=0 >>
    
    
    192.168.214.133 | SUCCESS | rc=0 >>
    
    
    [root@Ansible ~]# curl 192.168.214.133
    web-1 test page.
    
    

    编写roles角色部署nginx+keepalived

    部署高可用集群需要注意各节点包括后端主机的时间问题,保证各主机时间一致。

    [root@Ansible ~]# ansible all -m shell -a 'yum install ntpdate -y'
    
    [root@Ansible ~]# ansible all -m shell -a 'ntpdate gudaoyufu.com'
    
    

    编写roles角色

    编写user.yml

    - name: create nginx group
      group: name=nginx
    - name: create nginx user
      user: name=nginx group=nginx system=yes shell=/sbin/nologin
    
    

    编写install_server.yml

    - name: install nginx and keepalived
      yum: name={{ item }} state=latest
      with_items:
        - nginx
        - keepalived
    

    编写temps.yml

    - name: copy nginx proxy conf and rename
      template: src=/opt/roles/ha_proxy/templates/nginx.conf.j2  dest=/etc/nginx/nginx.conf
      
    - name: copy master_keepalived.conf.j2 to MASTER node
      when: ansible_hostname == "node-1"
      template: src=/opt/roles/ha_proxy/templates/master_keepalived.conf.j2 dest=/etc/keepalived/keepalived.conf
      
    - name: copy backup_keepalived.conf.j2 to BACKUP node
      when: ansible_hostname == "node-2"
      template: src=/opt/roles/ha_proxy/templates/backup_keepalived.conf.j2 dest=/etc/keepalived/keepalived.conf
    

    配置nginx proxy配置文件模板

    [root@Ansible ~]# cp /opt/conf/nginx.conf /opt/roles/ngx_proxy/templates/nginx.conf.j2
    
    [root@Ansible ~]# vim /opt/roles/ngx_proxy/templates/nginx.conf.j2
    
    user nginx;
    worker_processes {{ ansible_processor_vcpus }};
    error_log /var/log/nginx/error.log;
    pid /var/run/nginx.pid;
    
    # Load dynamic modules. See /usr/share/nginx/README.dynamic.
    
    events {
        worker_connections  1024;
    }
    
    
    http {
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  /var/log/nginx/access.log  main;
    
        sendfile            on;
        tcp_nopush          on;
        tcp_nodelay         on;
        keepalive_timeout   65;
        types_hash_max_size 2048;
    
        include             /etc/nginx/mime.types;
        default_type        application/octet-stream;
    
    
        include /etc/nginx/conf.d/*.conf;
    
        upstream web {
    
            server 192.168.214.133:80 max_fails=3 fail_timeout=30s;
            server 192.168.214.135:80 max_fails=3 fail_timeout=30s;
            server 192.168.214.139:80 max_fails=3 fail_timeout=30s;
    
    
        }
    
    
    
        server {
    
        listen       80 default_server;
        server_name  {{ ansible_hostname }};
        root         /usr/share/nginx/html;
        index index.html index.php;
    
             location / {
                    proxy_pass http://web;
                 }
    
             error_page 404 /404.html;
    
              }
    
    
    }
    
    
    

    配置keepalived配置文件模板

    [root@Ansible ~]# cp /opt/conf/keepalived.conf /opt/roles/ha_proxy/templates/master_keepalived.conf.j2
    
    
    [root@Ansible templates]# vim master_keepalived.conf.j2
    
    #
    
    ! Configuration File for keepalived
    
    global_defs {
       notification_email {
         acassen@firewall.loc
         failover@firewall.loc
         sysadmin@firewall.loc
       }
       notification_email_from Alexandre.Cassen@firewall.loc
       smtp_server 192.168.214.1
       smtp_connect_timeout 30
       router_id LVS_DEVEL
       vrrp_skip_check_adv_addr
       vrrp_strict
       vrrp_garp_interval 0
       vrrp_gna_interval 0
       vrrp_iptables
       vrrp_mcast_group4 224.17.17.17
    }
    
    
    vrrp_script chk_nginx {
                    script "killall -0 nginx"
                    interval 1
                    weight -20
                    fall 2
                    rise 1
                }
    
    vrrp_instance VI_1 {
        state MASTER
        interface ens33
        virtual_router_id 55
        priority 100
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass 12345678
        }
        virtual_ipaddress {
            192.168.214.100
        }
    
        track_script {
            chk_nginx
          }
    
       }
    
    

    同样,在master_keepalived.conf.j2基础修改另存为backup_keepalived.conf.j2,只修改角色与优先级即可。注意:master_keepalived.conf.j2文件中的检测故障降低优先级的值要确保降低后MASTER优先级小于BACKUP的优先级

    编写start.yml

    - name: start nginx proxy server
      service: name=nginx state=started
    

    编写main.yml

    - import_tasks: user.yml
    - import_tasks: install_server.yml
    - import_tasks: temps.yml
    - import_tasks: start.yml
    

    编写执行主文件

    [root@Ansible ~]# vim /opt/roles/ha_proxy_install.yml
    
    
    ---
    - hosts: node
      remote_user: root
      roles:
        - ha_proxy
    
    

    执行检测roles

    [root@Ansible ~]# ansible-playbook -C /opt/roles/ha_proxy_install.yml 
     
    

    执行测试没问题即可执行自动部署

    执行过程如下:

    [root@Ansible ~]# ansible-playbook  /opt/roles/ha_proxy_install.yml 
    
    
    
    PLAY [node] **********************************************************************************************************************
    
    TASK [Gathering Facts] ***********************************************************************************************************
    ok: [192.168.214.148]
    ok: [192.168.214.143]
    
    TASK [ha_proxy : create nginx group] *********************************************************************************************
    changed: [192.168.214.148]
    ok: [192.168.214.143]
    
    TASK [ha_proxy : create nginx user] **********************************************************************************************
    changed: [192.168.214.148]
    ok: [192.168.214.143]
    
    TASK [ha_proxy : install nginx and keepalived] ***********************************************************************************
    changed: [192.168.214.143] => (item=[u'nginx', u'keepalived'])
    changed: [192.168.214.148] => (item=[u'nginx', u'keepalived'])
    
    TASK [ha_proxy : copy nginx proxy conf and rename] *******************************************************************************
    changed: [192.168.214.148]
    changed: [192.168.214.143]
    
    TASK [ha_proxy : copy master_keepalived.conf.j2 to MASTER node] ******************************************************************
    skipping: [192.168.214.143]
    changed: [192.168.214.148]
    
    TASK [ha_proxy : copy backup_keepalived.conf.j2 to BACKUP node] ******************************************************************
    skipping: [192.168.214.148]
    changed: [192.168.214.143]
    
    TASK [ha_proxy : start nginx proxy server] ***************************************************************************************
    changed: [192.168.214.143]
    changed: [192.168.214.148]
    
    PLAY RECAP ***********************************************************************************************************************
    192.168.214.143            : ok=7    changed=4    unreachable=0    failed=0   
    192.168.214.148            : ok=7    changed=6    unreachable=0    failed=0   
    

    至此,自动部署nginx+keepalived高可用负载均衡完成了

    最后看一下roles目录的结构

    [root@Ansible ~]# tree /opt/roles/
    /opt/roles/
    ├── ha_proxy
    │   ├── tasks
    │   │   ├── install_server.yml
    │   │   ├── main.yml
    │   │   ├── start.yml
    │   │   ├── temps.yml
    │   │   └── user.yml
    │   └── templates
    │       ├── backup_keepalived.conf.j2
    │       ├── master_keepalived.conf.j2
    │       └── nginx.conf.j2
    ├── ha_proxy_install.retry
    ├── ha_proxy_install.yml
    ├── web
    │   ├── tasks
    │   │   ├── install_nginx.yml
    │   │   ├── main.yml
    │   │   ├── start.yml
    │   │   ├── temps.yml
    │   │   └── user.yml
    │   └── templates
    │       ├── index.html.j2
    │       └── nginx.conf.j2
    ├── web_install.retry
    └── web_install.yml
    
    6 directories, 19 files
    
    

    下面测试服务:keepalived的服务没有在ansible中设置自动启动,到keepalived节点启动即可。

    测试node节点

    [root@Ansible ~]# for i in {1..10};do curl 192.168.214.148;done
    web-3 test page.
    web-1 test page.
    web-2 test page.
    web-3 test page.
    web-1 test page.
    web-2 test page.
    web-3 test page.
    web-1 test page.
    web-2 test page.
    web-3 test page.
    

    将node-1 的MASTER服务停掉测试故障转移,同时查看node-2状态变化

    执行: nginx -s stop

    查看vrrp通知,可以看到主备切换正常:

    [root@node-2 ~]# tcpdump -i ens33 -nn host 224.17.17.17
    
    listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
    
    16:55:20.804327 IP 192.168.214.148 > 224.17.17.17: VRRPv2, Advertisement, vrid 55, prio 100, authtype simple, intvl 1s, length 20
    16:55:25.476397 IP 192.168.214.148 > 224.17.17.17: VRRPv2, Advertisement, vrid 55, prio 0, authtype simple, intvl 1s, length 20
    16:55:26.128474 IP 192.168.214.143 > 224.17.17.17: VRRPv2, Advertisement, vrid 55, prio 90, authtype simple, intvl 1s, length 20
    16:55:27.133349 IP 192.168.214.143 > 224.17.17.17: VRRPv2, Advertisement, vrid 55, prio 90, authtype simple, intvl 1s, length 20
    
    

    再测试访问:

    [root@Ansible ~]# for i in {1..10};do curl 192.168.214.148;done
    web-1 test page.
    web-2 test page.
    web-3 test page.
    web-1 test page.
    web-2 test page.
    web-3 test page.
    web-1 test page.
    web-2 test page.
    web-3 test page.
    web-1 test page.
    

    node-1恢复主节点,抢回MASTER角色

    node-1节点执行nginx指令,可以看到VIP漂移回到node-1节点,测试访问

    [root@Ansible ~]# for i in {1..10};do curl 192.168.214.148;done
    web-1 test page.
    web-2 test page.
    web-3 test page.
    web-1 test page.
    web-2 test page.
    web-3 test page.
    web-1 test page.
    web-2 test page.
    web-3 test page.
    web-1 test page.
    

    其他问题

    上面的自动部署方式还有可以改进的地方,比如,可以将配置keepalived的配置文件中的许多参数在roles中以统一变量的方式定义,然后在template模板文件中引用参数就可以了

    此外还有一个需要注意的地方是:keepalived的配置文件中使用了killall指令检测本地的nginx服务状态,如果检测结果状态为非0就会执行vrrp_script中定义的降级操作,要确保系统这个指令可以执行,有时该指令没有被安装,如果该指令没有存在,即使MASTER节点发生故障也不会发生变化

  • 相关阅读:
    第八周上机作业
    第七次作业
    第七周上机
    第六周作业
    4.9上机作业
    第五周作业
    第四周作业
    第二次上机作业
    第三周作业
    第九周上机练习
  • 原文地址:https://www.cnblogs.com/anay/p/9310430.html
Copyright © 2020-2023  润新知