RH358优化Web服务器流量–自动化执行 Web 服务优化
本章节介绍如何使用Ansible部署HAProxy和Varnish,并使用HAProxy模块进行滚动更新。
RH358专栏地址:https://blog.csdn.net/qq_41765918/category_11532281.html
1. 使用Ansible部署HAProxy和Varnish
使用Ansible部署HAProxy和Varnish遵循一个标准流程:
-
使用Ansible yum模块安装haproxy和varnish包。
-
使用copy或template模块部署配置文件。
-
使用Ansible service模块启用和启动服务。
-
使用Ansible firewalld模块配置防火墙规则。
-
当您的设置不使用标准网口时,可以选择使用Ansible seboolean模块来启用haproxy_connect_any和varnishd_connect_any SELinux布尔值。
这与本课程中学习的其他服务很相似。因此,本节不讨论如何编写Ansible Playbooks来部署和配置HAProxy和Varnish。相反,它研究了如何使用Ansible更新web服务器或web内容,这些web服务器通过HAProxy实现负载均衡,而不会导致客户停机。
2. 使用HAProxy模块进行滚动更新
可以使用Ansible更新web内容或在web服务器群上运行的web应用程序。在进行更新时,通常需要删除每个web服务器,这样客户就不会访问部分部署的内容或非功能的应用程序。
Ansible haproxy模块可以暂时禁用后端web服务器,然后从haproxy重新启用。有了这个模块,你可以开发一个Ansible Playbook,它首先禁止web服务器使用HAProxy,部署新的内容或更新web应用程序,最后在更新过程完成时在HAProxy中重新启用服务器。
然而,在开发这样一个过程时,必须特别小心。通常,当Ansible运行一个play时,它会对所有托管主机执行第一个任务,并在处理第二个任务之前等待所有这些主机上的任务完成,以此类推。这种行为会导致不良的副作用。例如,如果play一开始从HAProxy禁用web服务器,他们可能都是在同一时间退出服务。
Ansible有几个特性可以支持滚动更新,这是一种将部署堆叠到一批服务器上的策略。有了这个策略,Ansible可以零停机时间部署更新。
为滚动更新准备Ansible剧本
如果要通过剧本批量处理主机,请在剧本中使用serial关键字。serial关键字指定每个批处理中应该有多少台主机。Ansible处理每一批主机,直到开始下一批。
看看下面这剧本的开头部分:
---
- name: Update the back-end web servers
hosts: web_servers
serial: 2
...output omitted...
在本例中,serial关键字指示Ansible分批处理web_servers主机组中的两台主机。如果剧本没有错误地执行,Ansible会用新一批重复剧本。这个过程继续进行,直到Ansible处理完所有的主机。
使用HAProxy模块控制Web服务器
下面的Ansible Playbook将新的内容部署到web_servers主机组中的web服务器上
---
- name: Update the back-end web servers
hosts: web_servers
serial: 2
tasks:
- name: the web server is removed from service during the update
# 第一个任务从HAProxy中删除批处理中的web服务器。HAProxy停止向这些服务器发送客户端请求。
haproxy:
socket: /var/lib/haproxy/stats
# Ansible haproxy模块使用haproxy UNIX套接字进行操作。
state: disabled
backend: my-web-farm
# backend参数提供了HAProxy backend部分的名称。
host: "{{ inventory_hostname }}"
delegate_to: haproxy.example.com
# haproxy模块必须在haproxy服务器上运行才能访问UNIX套接字。
- name: the new content is deployed
# Ansible使用同步模块将新内容批量部署到web服务器上。
synchronize:
src: "new_web_content/v2/"
dest: /var/www/html
delete: true
- name: the web server is re-enabled in HAProxy
# play再次使用haproxy模块重新启用haproxy中的web服务器。
haproxy:
socket: /var/lib/haproxy/stats
state: enabled
backend: my-web-farm
host: "{{ inventory_hostname }}"
delegate_to: haproxy.example.com
如果没有serial关键字,play将同时在所有web服务器上执行。这可能会导致服务中断,因为第一个任务将从HAProxy禁用所有web服务器。
Ansible haproxy模块要求你在管理模式下配置UNIX套接字。在HAProxy主机上,编辑/etc/haproxy/haproxy.cfg配置文件,然后在全局部分的stats socket指令中添加level admin选项。
global
...output omitted...
# turn on stats unix socket
stats socket /var/lib/haproxy/stats level admin
...output omitted...
3. 课本练习
[student@workstation ~]$ lab optimizeweb-automation start
在练习的第一部分,使用一个现有的Ansible Playbook为一对负载均衡的web服务器来部署一个HAProxy和Varnish Cache基础设施,按照下图的架构:
在练习的第二部分中,您将开发一个剧本来执行新web内容的零停机部署。
1. 熟悉项目。
[student@workstation ~]$ cd /home/student/optimizeweb-automation
[student@workstation optimizeweb-automation]$ tree
.
├── ansible.cfg
├── cacert.pem
├── deploy_apache.yml
├── deploy_haproxy.yml
├── deploy_varnish.yml
├── deploy_webcontent.yml
├── files
│ ├── haproxy.cfg
│ ├── port.conf
│ ├── servera.lab.example.com.crt
│ └── servera.lab.example.com.key
├── inventory
├── new_web_content
│ ├── serverc.lab.example.com
│ │ └── index.html
│ └── serverd.lab.example.com
│ └── index.html
├── reset_webcontent.yml
├── run_curl_in_a_loop.sh
├── site.yml
├── solution
│ └── update_webcontent.yml
└── update_webcontent.yml
5 directories, 18 files
[student@workstation optimizeweb-automation]$ cat ansible.cfg
[defaults]
inventory=inventory
remote_user=devops
[student@workstation optimizeweb-automation]$ cat inventory
[lb_servers]
servera.lab.example.com
[web_servers]
serverc.lab.example.com
serverd.lab.example.com
[student@workstation optimizeweb-automation]$ cat site.yml
---
- name: Deploy HAProxy
import_playbook: deploy_haproxy.yml
- name: Deploy Varnish
import_playbook: deploy_varnish.yml
- name: Deploy Web Server
import_playbook: deploy_apache.yml
- name: Deploy Web Content
import_playbook: deploy_webcontent.yml
2. 回顾deploy_haproxy.yml剧本。
[student@workstation optimizeweb-automation]$ cat deploy_haproxy.yml
...output omitted...
- name: the HAProxy configuration file is deployed
copy:
src: files/haproxy.cfg
dest: /etc/haproxy/haproxy.cfg
notify: restart haproxy
- name: SELinux allows HAProxy to connect to remote port 6081
seboolean:
name: haproxy_connect_any
state: true
persistent: true
...output omitted...
[student@workstation optimizeweb-automation]$ cat files/haproxy.cfg
global
...output omitted...
# turn on stats unix socket
stats socket /var/lib/haproxy/stats level admin
# UNIX套接字允许从本地系统监视和控制HAProxy。Ansible haproxy模块使用该套接字来禁用和启用后端服务器。该模块需要级别管理选项来控制HAProxy。
...output omitted...
defaults
...output omitted...
option http-server-close
# option forwardfor except 127.0.0.0/8
# forwardfor选项指示HAProxy将X-Forwarded-For头添加到它发送到后端服务器的每个请求中。这个选项被注释掉了,因为HAProxy通过HTTP PROXY协议与Varnish通信,它负责为您添加报头。
option redispatch
...output omitted...
frontend http-proxy
bind *:443 ssl crt /etc/pki/haproxy/haproxy.pem
http-request add-header X-Forwarded-Proto https
# HAProxy添加了X-Forwarded-Proto标头来指示客户端使用HTTPS协议的后端web服务器。
default_backend classroom-web-farm
backend classroom-web-farm
balance roundrobin
server serverc.lab.example.com 172.25.250.12:6081 send-proxy-v2 check inter 5s
server serverd.lab.example.com 172.25.250.13:6081 send-proxy-v2 check inter 5s
# send-proxy-v2选项激活HAProxy和Varnish之间的HTTP PROXY协议。
第二个任务启用haproxy_connect_any SELinux布尔值,允许HAProxy使用端口6081与Varnish通信。默认情况下,SELinux只允许HAProxy绑定(监听)并连接到http_cache_port_t和http_port_t端口类型,可以用下面的命令检查:
[student@workstation optimizeweb-automation]$ sudo semanage port --list | \
grep -e ^http_cache_port_t -e ^http_port_t
[sudo] password for student: student
http_cache_port_t tcp 8080, 8118, 8123, 10001-10010
http_cache_port_t udp 3130
http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
注意,端口6081不在列表中。
3. 回顾deploy_varnish.yml剧本。
[student@workstation optimizeweb-automation]$ cat deploy_varnish.yml
...output omitted...
- name: the varnish systemd service configuration file is deployed
copy:
src: files/port.conf
dest: /etc/systemd/system/varnish.service.d/port.conf
notify:
- reload systemd
- restart varnish
...output omitted...
[student@workstation optimizeweb-automation]$ cat files/port.conf
[Service]
ExecStart=
ExecStart=/usr/sbin/varnishd -a :80 -a :6081,PROXY -f /etc/varnish/default.vcl -s malloc,256m
-a :80选项指示varnishd守护进程监听端口80。update_webcontent.yml剧本在练习的第二部分中使用该端口来确认新的web内容是可用的。
-a :6081,PROXY选项激活端口6081上的HTTP代理协议,HAProxy使用该端口与Varnish通信。
4. 用Ansible Playbook部署HAProxy, Varnish, Apache HTTP Server。
[student@workstation optimizeweb-automation]$ ansible-playbook site.yml
[student@workstation optimizeweb-automation]$ curl --cacert cacert.pem \
https://servera.lab.example.com/
This is serverc.lab.example.com
[student@workstation optimizeweb-automation]$ curl --cacert cacert.pem \
https://servera.lab.example.com/
This is serverd.lab.example.com
[student@workstation optimizeweb-automation]$ curl --cacert cacert.pem \
https://servera.lab.example.com/
This is serverc.lab.example.com
[student@workstation optimizeweb-automation]$ curl --cacert cacert.pem \
https://servera.lab.example.com/
This is serverd.lab.example.com
在练习的第二部分中,您将检查、完成并运行update_webcontent.yml Ansible剧本。该剧本在serverc和serverd上的Apache HTTP服务器上执行新web内容的滚动更新。
5. 回顾update_webcontent.yml剧本。
[student@workstation optimizeweb-automation]$ cat update_webcontent.yml
---
- name: Ensure new web content is deployed
hosts: web_servers
gather_facts: false
become: true
serial: 1
# serial任务参数指示Ansible在第一个web服务器上运行整个play,如果成功,则在第二个服务器上运行。
tasks:
- name: the web server is removed from service during the update
# 第一个任务使用haproxy模块从haproxy后端部分临时删除web服务器。
haproxy:
socket: ## FIXME ##
state: disabled
backend: ## FIXME ##
host: "{{ inventory_hostname }}"
delegate_to: servera.lab.example.com
- name: the new content is deployed
# synchronize模块部署新的web内容。notify参数指示Ansible重新启动Varnish。这次重启将清除缓存,以便Varnish能够提供新内容。
synchronize:
src: "new_web_content/{{ inventory_hostname }}/"
dest: /var/www/html
delete: true
notify: Varnish Cache is clean
post_tasks:
- name: Smoke Test - Ensure HTTP 200 OK
# 此任务访问内容以验证服务器是否正常运行。
uri:
url: "http://localhost"
status_code: 200
# If the test fails, servers are not re-enabled
# in the load balancers, and the update process halts.
- name: the healthy web server is enabled in HAProxy
# 本任务使用haproxy模块将web服务器添加到haproxy backend部分。
haproxy:
socket: ## FIXME ##
state: enabled
backend: ## FIXME ##
host: "{{ inventory_hostname }}"
delegate_to: servera.lab.example.com
handlers:
- name: Varnish Cache is clean
service:
name: varnish
state: restarted
6. 完成update-webcontent.yml的剧本。
首先需要检索haproxy模块缺少的两个参数:haproxy UNIX套接字的路径和backend部分的名称。
[student@workstation optimizeweb-automation]$ cat files/haproxy.cfg
global
...output omitted...
# turn on stats unix socket
stats socket /var/lib/haproxy/stats level admin
...output omitted...
backend classroom-web-farm
balance roundrobin
server serverc.lab.example.com 172.25.250.12:6081 send-proxy-v2 check inter 5s
server serverd.lab.example.com 172.25.250.13:6081 send-proxy-v2 check inter 5s
[student@workstation optimizeweb-automation]$ vim update_webcontent.yml
tasks:
...output omitted...
- name: the web server is removed from service during the update
haproxy:
socket: /var/lib/haproxy/stats
state: disabled
backend: classroom-web-farm
host: "{{ inventory_hostname }}"
delegate_to: servera.lab.example.com
...output omitted...
- name: the healthy web server is enabled in HAProxy
haproxy:
socket: /var/lib/haproxy/stats
state: enabled
backend: classroom-web-farm
host: "{{ inventory_hostname }}"
delegate_to: servera.lab.example.com
[student@workstation optimizeweb-automation]$ ansible-playbook \
--syntax-check update_webcontent.yml
7. 运行optimizewebautomation/run_curl_in_a_loop.sh脚本以观察。
该脚本循环运行curl命令,通过HAProxy和Varnish访问后端web服务器。通过这种方式,可以监控更新web内容的行为。剧本对web内容滚动更新。
运行剧本并观察脚本输出内容
[student@workstation optimizeweb-automation]$ ansible-playbook update_webcontent.yml
完成实验
[student@workstation ~]$ lab optimizeweb-automation finish
总结
- 介绍使用Ansible部署HAProxy和Varnish。
- 使用HAProxy模块进行滚动更新。
- 若喜欢金鱼哥的文章,顺手点个赞。也可点个关注,因为后续会不断上干货。