Initial commit
This commit is contained in:
parent
cc01d8bf27
commit
054a3711f1
9 changed files with 393 additions and 7 deletions
65
README.md
65
README.md
|
@ -2,18 +2,69 @@
|
|||
|
||||
Ansible playbook that provisions a group of servers to run HAProxy with a shared hosting IP from kepalived.
|
||||
|
||||
## Requirements
|
||||
|
||||
## 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
|
||||
|
||||
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
|
||||
|
||||
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