文章目录
一、 数据链路层的负载均衡
1、环境准备
[root@server1 ansible]# cat hosts
[test]
192.168.0.2
[prod]
192.168.0.3
[webserver:children]
test
prod
[lb]
192.168.0.1
[root@server1 ansible]# cat ansible.cfg
[defaults]
inventory = ./hosts
remote_user = westos
[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False
[root@server1 ansible]# ssh-copy-id westos@server1
[root@server1 ansible]# cat /mnt/ansible/playbook.yml
---
- hosts: webserver
tasks:
- name: install apache
dnf:
name: httpd
state: present
- name: start apache
service:
name: httpd
state: started
enabled: yes
- name: create index.html
copy:
content: "{{ ansible_hostname }}\n"
dest: /var/www/html/index.html
- name: accept http
firewalld:
service: http
permanent: yes
immediate: yes
state: enabled
[root@server1 ansible]# ansible-playbook playbook.yml
2、haproxy负载均衡
[root@server1 ansible]# dnf install haproxy.x86_64 -y
[root@server1 ansible]# cd /etc/haproxy/
[root@server1 haproxy]# ls
haproxy.cfg
[root@server1 ansible]# vim /etc/haproxy/haproxy.cfg
63 stats uri /status
64 stats auth admin:westos
71 bind *:80
90 server app1 192.168.0.2:80 check
91 server app2 192.168.0.3:80 check
[root@server1 haproxy]# systemctl start haproxy.service
[root@server1 haproxy]# netstat -antlp
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 22549/haproxy
[root@server1 ansible]# firewall-cmd --permanent --add-service=http
success
[root@server1 ansible]# firewall-cmd --reload
success
[root@server1 ansible]# firewall-cmd --list-all
负载均衡在两个ip上
当关闭server2的http服务
3、自动化部署haproxy
[root@server1 ansible]# systemctl start firewalld.service
[root@server1 ansible]# vim haproxy.yml
---
- hosts: lb
tasks:
- name: install haproxy
dnf:
name: haproxy
state: present
- name: configure haproxy
copy:
src: haproxy.cfg
dest: /etc/haproxy/haproxy.cfg
- name: start haproxy
service:
name: haproxy
state: started
- name: accept haproxy
firewalld:
service: http
permanent: yes
immediate: yes
state: enabled
[root@server1 ansible]# visudo
101 westos ALL=(ALL) NOPASSWD: ALL
[root@server1 ansible]# cp /etc/haproxy/haproxy.cfg .
[root@server1 ansible]# ansible-playbook haproxy.yml
4、 魔术变量-自动添加负载均衡节点
haproxy自动化添加负载均衡的web节点
[root@server1 ansible]# cp haproxy.cfg haproxy.cfg.j2
[root@server1 ansible]# ansible lb -m setup | less
[root@server1 ansible]# vim haproxy.cfg.j2
backend app
balance roundrobin
{% for host in groups['webserver'] %}
server {{ hostvars[host]['ansible_facts']['hostname'] }} {{ hostvars[host]['ansible_facts'] ['enp1s0']['ipv4']['adderss'] }}:80 check
{% endfor %}
[root@server1 ansible]# vim haproxy.yml
- name: configure haproxy ##更改内容
template:
src: haproxy.cfg.j2
dest: /etc/haproxy/haproxy.cfg
[root@server1 ansible]# vim playbook.yml ##最后行添加
- import_playbook: haproxy.yml
[root@server1 ansible]# ansible-playbook playbook.yml
[root@server1 ansible]# cat /etc/haproxy/haproxy.cfg ##部署完自动写好
backend app
balance roundrobin
server server2 192.168.0.2:80 check
server server3 192.168.0.3:80 check
[root@server4 ~]# visudo
westos ALL=(ALL) NOPASSWD: ALL
[root@server1 ansible]# ssh-copy-id westos@server4
[root@server1 ansible]# vim hosts
[test]
192.168.0.2
[prod]
192.168.0.3
192.168.0.4
[webserver:children]
test
prod
[lb]
192.168.0.1
[root@server1 ansible]# systemctl reload haproxy.service ##手动更新
[root@server1 ansible]# vim haproxy.yml ##最后行添加 ##自动化更新
handlers:
- name: restart haproxy
service:
name: haproxy
state: reloaded
[root@server1 ansible]# ansible-playbook playbook.yml
二、变量文件推荐的管理方式
1. 定义主机组变量
[root@server1 ansible]# mkdir group_vars
[root@server1 ansible]# cd group_vars/
[root@server1 group_vars]# mkdir webserver
[root@server1 group_vars]# cd webserver/
[root@server1 webserver]# vim vars
http_port: 8080
[root@server1 ansible]# vim playbook.yml
---
- hosts: webserver
tasks:
- name: install apache
dnf:
name: httpd
state: present
- name: create index.html
copy:
content: "{{ ansible_hostname }}\n"
dest: /var/www/html/index.html
- name: config httpd
template:
src: httpd.conf.j2
dest: /etc/httpd/conf/httpd.conf
notify: restart httpd
- name: start httpd
service:
name: httpd
state: started
enabled: yes
- name: accept http
firewalld:
service: http
permanent: yes
immediate: yes
state: enabled
- name: accept 8080
firewalld:
port: 8080/tcp
permanent: yes
immediate: yes
state: enabled
handlers:
- name: restart httpd
service:
name: httpd
state: restarted
[root@server1 ansible]# scp server2:/etc/httpd/conf/httpd.conf httpd.conf.j2
[root@server1 ansible]# vim haproxy.cfg.j2
Listen {{ http_port }}
[root@server1 ansible]# ansible-playbook playbook.yml
[root@server2 conf]# cat /etc/httpd/conf/httpd.conf
[root@server1 ansible]# yum install -y tree
[root@server1 ansible]# tree .
触发成功
2. 定义主机变量
[root@server1 ansible]# vim playbook.yml
- hosts: webserver
vars: ##添加行 其他内容不变
http_port: 80
tasks:
- name: install apache
[root@server1 ansible]# ansible-playbook playbook.yml
[root@server1 ansible]# mkdir host_vars
[root@server1 ansible]# cd host_vars/
[root@server1 host_vars]# mkdir 192.168.0.2
[root@server1 host_vars]# cd 192.168.0.2/
[root@server1 192.168.0.2]# vim vars
http_port: 8080
[root@server1 192.168.0.2]# vim vault
passwd: westos
[root@server1 ansible]# vim playbook.yml
---
- hosts: test
# vars:
# http_port: 80
tasks:
- name: install apache
[root@server1 ansible]# ansible-playbook playbook.yml
注意:主机变量中文件名称需要以ip命名,文件名称需要与hosts中的内容一致。ip对应ip,名称对应名称。
[root@server1 ansible]# ansible-vault encrypt /mnt/ansible/host_vars/192.168.0.2/vault
[root@server1 ansible]# ansible-vault view /mnt/ansible/host_vars/192.168.0.2/vault
Vault password:
passwd: westos
[root@server1 ansible]# vim playbook.yml
- name: create user
user:
name: liunx
password: "{{ passwd | password_hash('sha512') }}"
state: present
[root@server1 ansible]# ansible-playbook playbook.yml
[root@server1 ansible]# ansible-playbook playbook.yml --ask-vault-pass
[root@server2 conf]# id linux
uid=1001(linux) gid=1001(linux) groups=1001(linux)
[root@server2 conf]# cat /etc/shadow
linux:$6$Lzflp3z4xZOjim87$HZxOQkJghAlsZjraeoW2MsZ7PDT1qabEsw4fCgAb6PCza6MrGV2/rmp.L6SNn38gE0yiXz8g0IZd/LkdSfSJZ.:18813:0:99999:7:::
主机变量的优先级高于组变量的优先级,组变量一般用来加载公共变量。
[root@server1 ansible]# cat host_vars/192.168.0.2/vars
http_port: 8080
[root@server1 ansible]# cat group_vars/webserver/vars
http_port: 80
[root@server1 ansible]# vim playbook.yml
- hosts: webserver
when: ansible_hostname == "server2"
[root@server1 ansible]# ansible-playbook playbook.yml --ask-vault-pass
[root@server1 ansible]# cat hosts
[test]
192.168.0.2
[prod]
192.168.0.3
192.168.0.4
[webserver:children]
test
prod
[lb]
192.168.0.1
三、 block任务块
它是task的一个分组,对任务进行分解.
[root@server1 ansible]# vim playbook.yml
- import_playbook: haproxy.yml
[root@server1 ansible]# vim host_vars/192.168.0.2/vars
http_port: 8080
[root@server1 ansible]# vim haproxy.cfg.j2
#80 check 换为 {{ hostvars[host]['http_port'] }} check
[root@server1 ansible]# echo westos > web_pass
[root@server1 ansible]# ll web_pass
-rw-r--r--. 1 root root 7 Jan 2 15:08 web_pass
[root@server1 ansible]# chmod 600 web_pass
[root@server1 ansible]# ansible-playbook playbook.yml --vault-password-file web_pass
[root@server1 ansible]# cat /etc/haproxy/haproxy.cfg
[root@server1 ansible]# cat hosts
[test]
192.168.0.2
[prod]
192.168.0.3
192.168.0.4
[webserver:children]
test
prod
[lb]
192.168.0.1
[root@server1 ansible]# vim playbook.yml
---
- hosts: all
tasks:
- name: deploy apache
block:
when: ansible_default_ipv4.address in groups['webserver']
[root@server1 ansible]# ansible-playbook playbook.yml --vault-password-file web_pass
block中部署apache的任务只在webserver中的用户中进行,跳过server1.
[root@server1 ansible]# ansible 192.168.0.3 -m debug -a "msg={{groups}}" ##调内部变量
[root@server1 ansible]# ansible 192.168.0.3 -m debug -a "msg={{ansible_version}}"
[root@server1 ansible]# ansible 192.168.0.3 -m debug -a "msg={{group_names}}"
[root@server1 ansible]# ansible 192.168.0.4 -m debug -a "msg={{inventory_hostname}}"
[root@server1 ansible]# ansible 192.168.0.4 -m debug -a "msg={{inventory_dir}}"
四、 阻止错误处理
忽略错误 强制输出
[root@server1 ansible]# vim block.yml
---
- hosts: localhost
become: no
gather_facts: false
tasks:
- name: Handle the error
block:
- debug:
msg: 'I execute normally'
- name: i force a failure
command: /bin/false
- debug:
msg: 'I never execute, due to the above task failing,;-('
rescue:
- debug:
msg: 'I caught an error, can do stuff here to fix it, ;-)'
[root@server1 ansible]# ansible-playbook block.yml
block内运行报错后,会直接运行rescue里的内容,做对应的错误处理。
[root@server1 ansible]# vim block.yml
ignore_errors: yes
[root@server1 ansible]# ansible-playbook block.yml
[root@server1 ansible]# vim block.yml
# ignore_errors: yes
# changed_when: false #不改变正常逻辑,只是在判断的时候始终以ok作为输出
always:
- debug:
msg: "This alawys executes, :-)"
[root@server1 ansible]# ansible-playbook block.yml
always 无论block和rescue部分中以前发生过或没有发生任何错误,此部分都将运行。
五、 使用魔术变量访问其他主机的信息
数据库服务器希望使用另一个节点的“事实”值或分配给另一个节点的清单变量,则可以在模板甚至行动中轻松使用
{{ hostvars['test.example.com']['ansible_facts']['distribution'] }}
1. 事实变量
一台主机引用另一台主机的事实变量
[root@server1 ansible]# cat test.yml
---
- hosts: 192.168.0.2
tasks:
- debug:
msg: "{{ ansible_hostname}}"
- hosts: 192.168.0.1
tasks:
- debug:
msg: "{{ hostvars['192.168.0.2']['ansible_facts']['hostname'] }}"
[root@server1 ansible]# ansible-playbook test.yml
[root@server1 ansible]# vim test.yml
---
- hosts: 192.168.0.2
vars:
name: redhat
tasks:
- debug:
msg: "{{ ansible_hostname}}"
- debug:
msg: "{{ name }}"
vars:
name: westos
- hosts: 192.168.0.1
tasks:
- debug:
msg: "{{ hostvars['192.168.0.2']['ansible_facts']['hostname'] }}"
- debug:
msg: "{{ hostvars['192.168.0.2']['ansible_facts']['enp1s0']['ipv4']['address'] }}"
[root@server1 ansible]# ansible-playbook test.yml
2. 注册变量
变量的另一主要用途是运行命令并将该命令的结果注册为变量/执行任务并将返回值保存在变量中以供以后的任务使用.
事实变量和自注册的变量,例如command: /bin/date可以传递到下一个剧本中,但是用户自定义的变量,例如name: redhat不可以被下一个剧本调用。
[root@server1 ansible]# /bin/date
Thu Jul 8 18:56:33 CST 2021
[root@server1 ansible]# vim test.yml
- command: /bin/date
register: result
- debug:
msg: "{{ hostvars['192.168.0.2']['result']['stdout'] }}"
[root@server1 ansible]# ansible-playbook test.yml
3. set_fact
[root@server1 ansible]# vim test.yml
---
- hosts: 192.168.0.2
tasks:
- set_fact: name="westos"
- debug:
msg: "{{ ansible_hostname}}"
- command: /bin/date
register: result
- hosts: 192.168.0.1
tasks:
- debug:
msg: "{{ hostvars['192.168.0.2']['ansible_facts']['hostname'] }}"
- debug:
msg: "{{ hostvars['192.168.0.2']['result']['stdout'] }}"
- debug:
msg: "{{ hostvars['192.168.0.2']['name'] }}"
[root@server1 ansible]# ansible-playbook test.yml
六、角色编写
角色中定义的变量>主机变量>组变量>
1. apache
[root@server1 ansible]# cat playbook.yml ##拆分脚本
[root@server1 ansible]# mkdir roles
[root@server1 ansible]# vim ansible.cfg ##添加行
[defaults]
roles_path = ./roles
[root@server1 ansible]# ansible-galaxy list
# /mnt/ansible/roles
[root@server1 roles]# ansible-galaxy init apache
[root@server1 roles]# ls
apache
[root@server1 roles]# tree apache/
[root@server1 apache]# vim tasks/main.yml
- name: install httpd
dnf:
name: httpd
state: present
- name: create index.html
copy:
content: "{{ ansible_hostname }}\n"
dest: /var/www/html/index.html
- name: config httpd
template:
src: httpd.conf.j2
dest: /etc/httpd/conf/httpd.conf
notify: restart httpd
- name: start httpd
service:
name: httpd
state: started
enabled: yes
- name: accept http
firewalld:
service: http
permanent: yes
immediate: yes
state: enabled
- name: accept 8080
firewalld:
port: 8080/tcp
permanent: yes
immediate: yes
state: enabled
[root@server1 apache]# cp /mnt/ansible/httpd.conf.j2 templates/
[root@server1 apache]# vim handlers/main.yml
- name: restart httpd
service:
name: httpd
state: restarted
[root@server1 apache]# vim templates/httpd.conf.j2
Listen {{ http_port }}
[root@server1 apache]# cd ..
[root@server1 roles]# cd ..
[root@server1 ansible]# ansible-galaxy role list
# /mnt/ansible/roles
- apache, (unknown version)
[root@server1 ansible]# vim playbook1.yml
---
- hosts: webserver
roles:
- role: apache
when: ansible_default_ipv4.address in groups['webserver']
[root@server1 ansible]# ansible-playbook playbook1.yml
[root@server1 ansible]# cat host_vars/192.168.0.2/vars
http_port: 8080
[root@server1 ansible]# cat group_vars/webserver/vars
http_port: 80
[root@server1 ansible]# cat hosts
[webserver:children]
test
prod
[root@server2 ~]# netstat -antlp
tcp6 0 0 :::8080 :::* LISTEN 96368/httpd
[root@server3 ~]# netstat -antlp
tcp6 0 0 :::80 :::* LISTEN 30388/httpd
[root@server1 apache]# vim vars/main.yml
http_port: 80
[root@server1 ansible]# ansible-playbook playbook1.yml
[root@server2 ~]# netstat -antlp ##角色中定义的变量优先级更高
tcp6 0 0 :::80 :::* LISTEN 103836/httpd
优先级: 角色中定义的变量>主机变量>组变量>
playbook.yml中的自定义变量会覆盖roles中定义的变量,一般不更改角色中的变量,角色中的变量可能是公共变量。
2. haproxy
[root@server1 ansible]# ansible-galaxy init haproxy
[root@server1 roles]# ls
apache haproxy
[root@server1 haproxy]# ls
defaults files handlers meta README.md tasks templates tests vars
[root@server1 haproxy]# vim tasks/main.yml
- name: install haproxy
dnf:
name: haproxy
state: present
- name: configure haproxy
template:
src: haproxy.cfg.j2
dest: /etc/haproxy/haproxy.cfg
notify: restart haproxy
- name: start haproxy
service:
name: haproxy
state: started
- name: accept haproxy
firewalld:
service: http
permanent: yes
immediate: yes
state: enabled
[root@server1 haproxy]# vim handlers/main.yml
- name: restart haproxy
service:
name: haproxy
state: reloaded
[root@server1 haproxy]# cp /mnt/ansible/haproxy.cfg.j2 templates/
[root@server1 haproxy]# vim templates/haproxy.cfg.j2
[root@server1 ansible]# ansible-galaxy list
# /mnt/ansible/roles
- apache, (unknown version)
- haproxy, (unknown version)
[root@server1 ansible]# vim playbook1.yml
---
- hosts: all
roles:
- role: apache
when: ansible_default_ipv4.address in groups['webserver']
- role: haproxy
http_port: 80
when: ansible_hostname == "server1"
[root@server1 ansible]# vim host_vars/192.168.0.2/vars
http_port: 80
[root@server1 ansible]# cat group_vars/webserver/vars
http_port: 80
[root@server1 ansible]# ansible-playbook playbook1.yml
[root@server1 ansible]# cat /etc/haproxy/haproxy.cfg #80端口触发成功
server server2 192.168.0.2:80 check
server server3 192.168.0.3:80 check
server server4 192.168.0.4:80 check