Initial commit
This commit is contained in:
parent
cc01d8bf27
commit
054a3711f1
9 changed files with 393 additions and 7 deletions
63
README.md
63
README.md
|
@ -2,18 +2,69 @@
|
||||||
|
|
||||||
Ansible playbook that provisions a group of servers to run HAProxy with a shared hosting IP from kepalived.
|
Ansible playbook that provisions a group of servers to run HAProxy with a shared hosting IP from kepalived.
|
||||||
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
## Variables
|
## Variables
|
||||||
|
|
||||||
| Variable | Required | Default | Choices | Description |
|
| Variable | Required | Default | Choices | Description |
|
||||||
| -------- | -------- | ------- | ------- | ----------- |
|
| --------------------------------- | -------- | -------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| | | | | |
|
| haproxy_bind_adapter | Yes | eth0 | | Interface to use for the Shared IP |
|
||||||
|
| haproxy_keepalived_adapter | Yes | eth0 | | Interface to use for the keepalived communication |
|
||||||
|
| haproxy_keepalived_adapter_vlan | No | | | When specified, this will setup the given vlan and use that for the keepalived communication to keep the traffic out of the primary network |
|
||||||
|
| haproxy_keepalived_ip | Yes | 172.16.10.1/24 | | IP to use for the keepalived communication |
|
||||||
|
| haproxy_keepalived_process_weight | Yes | 10 | | Weight used for tracking the haproxy process on the server |
|
||||||
|
| haproxy_shared_ip | Yes | | | Shared IP that will be used by the group |
|
||||||
|
| haproxy_shared_ip_subnet | Yes | /24 | | Subnet for the shared IP |
|
||||||
|
| haproxy_shared_priority | Yes | 100 | | Keepalived priority for the host - this will |
|
||||||
|
| haproxy_shared_state | Yes | MASTER | MASTER/BACKUP | What state the keepalived configuration will start with for the desired host - After config starts it will determine if other members exist and adjust based on priority |
|
||||||
|
| haproxy_shared_virtual_router_id | Yes | 25 | | Virtual Router ID for the keepalived configuration - This should be the same for the group |
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
|
Execute playbook with needed variables
|
||||||
|
|
||||||
|
`ansible-playbook -i hosts site.yml --ask-pass --ask-become-pass`
|
||||||
|
|
||||||
|
Inventory File:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
# file: hosts
|
||||||
|
|
||||||
|
haproxy:
|
||||||
|
hosts:
|
||||||
|
dev-ha01:
|
||||||
|
ansible_host: 10.1.1.3
|
||||||
|
haproxy_shared_state: MASTER
|
||||||
|
haproxy_shared_priority: 101
|
||||||
|
haproxy_bind_adapter: "eth0"
|
||||||
|
haproxy_keepalived_adapter: "eth0"
|
||||||
|
haproxy_keepalived_adapter_vlan: "100"
|
||||||
|
haproxy_keepalived_ip: 172.16.10.1/24
|
||||||
|
|
||||||
|
dev-ha02:
|
||||||
|
ansible_host: 10.1.1.4
|
||||||
|
haproxy_shared_state: BACKUP
|
||||||
|
haproxy_shared_priority: 100
|
||||||
|
haproxy_bind_adapter: "eth0"
|
||||||
|
haproxy_keepalived_adapter: "eth0"
|
||||||
|
haproxy_keepalived_adapter_vlan: "100"
|
||||||
|
haproxy_keepalived_ip: 172.16.10.2/24
|
||||||
|
|
||||||
|
dev-ha03:
|
||||||
|
ansible_host: 10.1.1.5
|
||||||
|
haproxy_shared_state: BACKUP
|
||||||
|
haproxy_shared_priority: 99
|
||||||
|
haproxy_bind_adapter: "eth0"
|
||||||
|
haproxy_keepalived_adapter: "eth0"
|
||||||
|
haproxy_keepalived_adapter_vlan: "100"
|
||||||
|
haproxy_keepalived_ip: 172.16.10.3/24
|
||||||
|
|
||||||
|
vars:
|
||||||
|
haproxy_shared_ip: "10.10.2.60"
|
||||||
|
haproxy_shared_ip_subnet: "/24"
|
||||||
|
haproxy_shared_virtual_router_id: 25
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
See LICENSE file for full license information.
|
See LICENSE file for full license information.
|
||||||
|
|
||||||
## Screenshots
|
|
||||||
|
|
6
haproxy.yml
Normal file
6
haproxy.yml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
# file: haproxy.yml
|
||||||
|
|
||||||
|
- hosts: haproxy
|
||||||
|
roles:
|
||||||
|
- haproxy
|
37
hosts.yml
Normal file
37
hosts.yml
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
---
|
||||||
|
# file: hosts
|
||||||
|
|
||||||
|
haproxy:
|
||||||
|
hosts:
|
||||||
|
dev-ha01:
|
||||||
|
ansible_host: 10.1.1.3
|
||||||
|
haproxy_shared_state: MASTER
|
||||||
|
haproxy_shared_priority: 101
|
||||||
|
haproxy_bind_adapter: "eth0"
|
||||||
|
haproxy_keepalived_adapter: "eth0"
|
||||||
|
haproxy_keepalived_adapter_vlan: "100"
|
||||||
|
haproxy_keepalived_ip: 172.16.10.1/24
|
||||||
|
|
||||||
|
dev-ha02:
|
||||||
|
ansible_host: 10.1.1.4
|
||||||
|
haproxy_shared_state: BACKUP
|
||||||
|
haproxy_shared_priority: 100
|
||||||
|
haproxy_bind_adapter: "eth0"
|
||||||
|
haproxy_keepalived_adapter: "eth0"
|
||||||
|
haproxy_keepalived_adapter_vlan: "100"
|
||||||
|
haproxy_keepalived_ip: 172.16.10.2/24
|
||||||
|
|
||||||
|
dev-ha03:
|
||||||
|
ansible_host: 10.1.1.5
|
||||||
|
haproxy_shared_state: BACKUP
|
||||||
|
haproxy_shared_priority: 99
|
||||||
|
haproxy_bind_adapter: "eth0"
|
||||||
|
haproxy_keepalived_adapter: "eth0"
|
||||||
|
haproxy_keepalived_adapter_vlan: "100"
|
||||||
|
haproxy_keepalived_ip: 172.16.10.3/24
|
||||||
|
|
||||||
|
vars:
|
||||||
|
haproxy_shared_ip: "10.10.2.60"
|
||||||
|
haproxy_shared_ip_subnet: "/24"
|
||||||
|
haproxy_shared_virtual_router_id: 25
|
||||||
|
|
20
roles/haproxy/defaults/main.yml
Normal file
20
roles/haproxy/defaults/main.yml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
---
|
||||||
|
# file: roles/haproxy/defaults/main.yml
|
||||||
|
|
||||||
|
haproxy_config_file: "example.haproxy.cfg.j2"
|
||||||
|
|
||||||
|
# Set for entire group
|
||||||
|
|
||||||
|
haproxy_shared_ip: ""
|
||||||
|
haproxy_shared_ip_subnet: "/24"
|
||||||
|
haproxy_shared_virtual_router_id: 25
|
||||||
|
haproxy_keepalived_process_weight: 10
|
||||||
|
|
||||||
|
# Set per host
|
||||||
|
|
||||||
|
haproxy_shared_state: MASTER
|
||||||
|
haproxy_shared_priority: 100
|
||||||
|
haproxy_bind_adapter: "eth0"
|
||||||
|
haproxy_keepalived_adapter: "eth0"
|
||||||
|
haproxy_keepalived_adapter_vlan: ""
|
||||||
|
haproxy_keepalived_ip: 172.16.10.1/24
|
26
roles/haproxy/handlers/main.yml
Normal file
26
roles/haproxy/handlers/main.yml
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
---
|
||||||
|
# file: roles/haproxy/handlers/main.yml
|
||||||
|
|
||||||
|
- name: reload haproxy
|
||||||
|
service:
|
||||||
|
name: haproxy
|
||||||
|
state: reloaded
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: reload keepalived
|
||||||
|
service:
|
||||||
|
name: keepalived
|
||||||
|
state: reloaded
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: reload firewalld
|
||||||
|
service:
|
||||||
|
name: firewalld
|
||||||
|
state: reloaded
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Restart SSH
|
||||||
|
service:
|
||||||
|
name: sshd
|
||||||
|
state: restarted
|
||||||
|
become: yes
|
134
roles/haproxy/tasks/main.yml
Normal file
134
roles/haproxy/tasks/main.yml
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
---
|
||||||
|
# file: roles/haproxy/tasks/main.yml
|
||||||
|
|
||||||
|
- name: Install Ansible prereq packages
|
||||||
|
package:
|
||||||
|
name:
|
||||||
|
- policycoreutils-python-utils
|
||||||
|
- NetworkManager
|
||||||
|
state: latest
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Install packages
|
||||||
|
package:
|
||||||
|
name:
|
||||||
|
- keepalived
|
||||||
|
- haproxy
|
||||||
|
- firewalld
|
||||||
|
state: latest
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Add VLAN
|
||||||
|
nmcli:
|
||||||
|
conn_name: "{{ haproxy_keepalived_adapter }}.{{ haproxy_keepalived_adapter_vlan }}"
|
||||||
|
vlanid: "{{ haproxy_keepalived_adapter_vlan }}"
|
||||||
|
ip4: "{{ haproxy_keepalived_ip }}"
|
||||||
|
vlandev: "{{ haproxy_keepalived_adapter }}"
|
||||||
|
autoconnect: yes
|
||||||
|
type: vlan
|
||||||
|
state: present
|
||||||
|
become: yes
|
||||||
|
when: (haproxy_keepalived_adapter_vlan is defined) and (haproxy_keepalived_ip is defined)
|
||||||
|
|
||||||
|
- name: Enable firewall rule for vrrp
|
||||||
|
firewalld:
|
||||||
|
rich_rule: 'rule protocol value="vrrp" accept'
|
||||||
|
permanent: yes
|
||||||
|
state: enabled
|
||||||
|
immediate: yes
|
||||||
|
notify: reload firewalld
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Allow binding non-local IP
|
||||||
|
sysctl:
|
||||||
|
name: net.ipv4.ip_nonlocal_bind
|
||||||
|
value: "1"
|
||||||
|
reload: true
|
||||||
|
state: present
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Allow binding ip forward
|
||||||
|
sysctl:
|
||||||
|
name: net.ipv4.ip_forward
|
||||||
|
value: "1"
|
||||||
|
reload: true
|
||||||
|
state: present
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Update keepalived configuration
|
||||||
|
template:
|
||||||
|
src: keepalived.conf.j2
|
||||||
|
dest: /etc/keepalived/keepalived.conf
|
||||||
|
notify: reload keepalived
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Enable keepalived
|
||||||
|
service:
|
||||||
|
name: keepalived
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Limit SSH to only ansible_host
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/ssh/sshd_config
|
||||||
|
regexp: '^#?ListenAddress '
|
||||||
|
line: "ListenAddress {{ ansible_host }}"
|
||||||
|
notify:
|
||||||
|
- Restart SSH
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Flush handlers
|
||||||
|
meta: flush_handlers
|
||||||
|
|
||||||
|
- name: Set haproxy_connect_any flag and keep it persistent across reboots
|
||||||
|
seboolean:
|
||||||
|
name: haproxy_connect_any
|
||||||
|
state: yes
|
||||||
|
persistent: yes
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Update HAProxy configuration
|
||||||
|
template:
|
||||||
|
src: haproxy.cfg.j2
|
||||||
|
dest: /etc/haproxy/haproxy.cfg
|
||||||
|
mode: 0644
|
||||||
|
validate: haproxy -f %s -c -q
|
||||||
|
notify: reload haproxy
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Ensure HAProxy is started and enabled on boot.
|
||||||
|
service:
|
||||||
|
name: haproxy
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Enable firewall ports for haproxy
|
||||||
|
firewalld:
|
||||||
|
rich_rule: 'rule family=ipv4 destination address={{ haproxy_shared_ip }}{{ haproxy_shared_ip_subnet }} port port={{ item.port }} protocol={{ item.protocol }} accept'
|
||||||
|
permanent: yes
|
||||||
|
immediate: yes
|
||||||
|
state: enabled
|
||||||
|
with_items:
|
||||||
|
- {port: "22", protocol: "tcp"}
|
||||||
|
- {port: "80", protocol: "tcp"}
|
||||||
|
- {port: "443", protocol: "tcp"}
|
||||||
|
notify: reload firewalld
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Enable firewall ports for haproxy stats
|
||||||
|
firewalld:
|
||||||
|
port: "9999/tcp"
|
||||||
|
permanent: yes
|
||||||
|
immediate: yes
|
||||||
|
state: enabled
|
||||||
|
notify: reload firewalld
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Enable firewalld
|
||||||
|
service:
|
||||||
|
name: firewalld
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
become: yes
|
84
roles/haproxy/templates/example.haproxy.cfg.j2
Normal file
84
roles/haproxy/templates/example.haproxy.cfg.j2
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
global
|
||||||
|
log /dev/log local0
|
||||||
|
log /dev/log local1 notice
|
||||||
|
chroot /var/lib/haproxy
|
||||||
|
#stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
|
||||||
|
stats socket /var/lib/haproxy/stats
|
||||||
|
stats timeout 30s
|
||||||
|
user haproxy
|
||||||
|
group haproxy
|
||||||
|
daemon
|
||||||
|
|
||||||
|
# Default SSL material locations
|
||||||
|
ca-base /etc/ssl/certs
|
||||||
|
crt-base /etc/ssl/private
|
||||||
|
|
||||||
|
# See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
|
||||||
|
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
|
||||||
|
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
|
||||||
|
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
|
||||||
|
tune.ssl.default-dh-param 2048
|
||||||
|
tune.h2.initial-window-size 1048576
|
||||||
|
|
||||||
|
defaults
|
||||||
|
log global
|
||||||
|
mode http
|
||||||
|
option httplog
|
||||||
|
option dontlognull
|
||||||
|
timeout connect 5000
|
||||||
|
timeout client 50000
|
||||||
|
timeout server 50000
|
||||||
|
{% if ansible_os_family == 'Debian' %}
|
||||||
|
errorfile 400 /etc/haproxy/errors/400.http
|
||||||
|
errorfile 403 /etc/haproxy/errors/403.http
|
||||||
|
errorfile 408 /etc/haproxy/errors/408.http
|
||||||
|
errorfile 500 /etc/haproxy/errors/500.http
|
||||||
|
errorfile 502 /etc/haproxy/errors/502.http
|
||||||
|
errorfile 503 /etc/haproxy/errors/503.http
|
||||||
|
errorfile 504 /etc/haproxy/errors/504.http
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
frontend ssh-in
|
||||||
|
mode tcp
|
||||||
|
bind {{ haproxy_shared_ip }}:22
|
||||||
|
timeout connect 0ms
|
||||||
|
timeout client 0ms
|
||||||
|
timeout server 0ms
|
||||||
|
use_backend example-ssh-backend
|
||||||
|
|
||||||
|
frontend http-in
|
||||||
|
mode http
|
||||||
|
bind {{ haproxy_shared_ip }}:80
|
||||||
|
|
||||||
|
use_backend example-http-backend
|
||||||
|
|
||||||
|
frontend https-in
|
||||||
|
mode tcp
|
||||||
|
tcp-request inspect-delay 1s
|
||||||
|
bind {{ haproxy_shared_ip }}:443
|
||||||
|
tcp-request content accept if { req.ssl_hello_type 1 }
|
||||||
|
|
||||||
|
use_backend example-https-backend
|
||||||
|
|
||||||
|
backend example-ssh-backend
|
||||||
|
mode tcp
|
||||||
|
timeout connect 0ms
|
||||||
|
timeout client 0ms
|
||||||
|
timeout server 0ms
|
||||||
|
server example 10.1.1.11:22 check
|
||||||
|
|
||||||
|
backend example-http-backend
|
||||||
|
mode http
|
||||||
|
log global
|
||||||
|
timeout connect 30000
|
||||||
|
timeout server 30000
|
||||||
|
retries 3
|
||||||
|
server example 10.10.2.11:80 check
|
||||||
|
|
||||||
|
backend example-https-backend
|
||||||
|
mode tcp
|
||||||
|
log global
|
||||||
|
timeout connect 30000
|
||||||
|
timeout server 30000
|
||||||
|
retries 3
|
||||||
|
server example 10.10.2.11:443 check
|
24
roles/haproxy/templates/keepalived.conf.j2
Normal file
24
roles/haproxy/templates/keepalived.conf.j2
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
vrrp_track_process track_haproxy {
|
||||||
|
process haproxy
|
||||||
|
weight {{ haproxy_keepalived_process_weight }}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vrrp_instance VI_1 {
|
||||||
|
{% if haproxy_keepalived_adapter_vlan != '' %}
|
||||||
|
interface {{ haproxy_keepalived_adapter }}.{{ haproxy_keepalived_adapter_vlan }}
|
||||||
|
{% else %}
|
||||||
|
interface {{ haproxy_keepalived_adapter }}
|
||||||
|
{% endif %}
|
||||||
|
state {{ haproxy_shared_state }}
|
||||||
|
virtual_router_id {{ haproxy_shared_virtual_router_id }}
|
||||||
|
priority {{ haproxy_shared_priority }}
|
||||||
|
|
||||||
|
virtual_ipaddress {
|
||||||
|
{{ haproxy_shared_ip }}{{ haproxy_shared_ip_subnet }} dev {{ haproxy_bind_adapter }}
|
||||||
|
}
|
||||||
|
|
||||||
|
track_process {
|
||||||
|
track_haproxy
|
||||||
|
}
|
||||||
|
}
|
4
site.yml
Normal file
4
site.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
## This playbook deploys the whole application stack in this site.
|
||||||
|
|
||||||
|
- import_playbook: haproxy.yml
|
Loading…
Reference in a new issue