##管理变量和事实:练习:使用基本身份认证的httpd
[root@workstation~]#mkdir westos
[root@workstationwestos]#cat ansible.cfg
[defaults]
inventory=./inventory
[root@workstationwestos]#cat inventory
[webservers]
serverb.lab.example.com
#写playbook
---
- name: Webserver vars
hosts: webservers
vars:
firewall_pkg: firewalld
firewall_srv: firewalld
web_pkg: httpd
web_srv: httpd
ssl_pkg: mod_ssl
httpdconf_src: files/httpd.conf
httpdconf_dest: /etc/httpd/conf/httpd.conf
secrets_dir: /etc/httpd/secrets
secrets_src: files/htpasswd
secrets_dest: "{{ secrets_dir }}/htpasswd"
web_root: /var/www/html
tasks:
- name: Install packages
yum:
name:
- "{{ firewall_pkg }}"
- "{{ web_pkg }}"
- "{{ ssl_pkg }}"
state:latest
- name: Configure service
copy:
src: "{{ httpdconf_src }}"
dest: "{{ httpdconf_dest }}"
owner: root
group: root
mode: 0644
- name: Create secrets directory
file:
path: "{{ secrets_dir }}"
state: directory
owner: apache
group: apache
mode: 0500
- name: Create htpasswd
copy:
src: "{{ secrets_src }}"
dest: "{{ secrets_dest }}"
owner: apache
group: apache
mode: 0400
- name: Create index.html
copy:
content: "{{ ansible_facts['fqdn'] }} ({{ ansible_facts['all_ipv4_addresses'] }})\n"
dest: "{{ web_root}}/index.html"
- name: Configure firewalld service
service:
name: "{{ firewall_srv }}"
state: started
enabled: true
- name: Firewalld permit https
firewalld:
service: https
state: enabled
immediate: true
permanent: true
- name: Configure apache service
service:
name: "{{ web_srv }}"
state: started
enabled: true
- name: Test apache
hosts: localhost
become: no
vars:
- web_user: admin
vars_files:
- vars/secret.yml
tasks:
- name: Connect to apache with auth
uri:
url: https://serverb.lab.example.com
validate_certs: no
force_basic_auth: yes
user: "{{ web_user }}"
password: "{{ web_pass }}" #定义了访问apache的用户密码
return_content: yes
status_code: 200
register: auth_test
- debug:
var: auth_test.content
#创建加密文件
[root@workstationwestos]#mkdir vars
[root@workstationwestos]#ansible-vault create vars/secret.yml
New Vault password: 'redhat'
Confirm New Vault password: 'redhat'
在文件中写入:
web_pass:redhat
#创建files目录
[root@workstationwestos]#mkdir files
[root@workstationfiles]#ls
htpasswd httpd.conf
[root@serverb~]#htpasswd -cm htpasswd admin
[root@workstationfiles]#vim httpd.conf
134 <Directory "/var/www/html">
135 AuthUserFile /etc/httpd/secrets/htpasswd
136 AuthType basic
137 AuthName "Please input your name and password!!"
138 Require user admin
139
140 Require valid-user
#交互式输入密码,进行语法检测
[root@workstationwestos]#ansible-playbook --syntax-check --vault-id @prompt playbook.yml
Vaultpassword(default):
playbook:playbook.yml
#执行
[root@workstationwestos]#ansible-playbook --vault-id @prompt playbook.yml
#总结
1.变量能够让playbook复用
2.可以给清单中的主机和主机组定义变量
3.可以使用事实和外部文件定义变量,也可以在命令行中
4.register关键字何以用于捕获命令输出
5.ansiblevault
6.ansible事实是从受管主机自动检测到的变量
##########实施任务控制##########
#####编写循环和条件任务######
##简单循环
1.不用循环
---
- name: test
hosts: webservers
tasks:
- name: apache is running
service:
name: httpd
state: started
- name: vsftpd is running
service:
name: vsftpd
state:started
2.使用循环
---
- name: test
hosts: webservers
tasks:
- name: apache and vsftpd are running
service:
name: "{{ item }}" #循环变量item
state:started
loop:
- httpd
- vsftpd
3.将变量放入列表
---
- name: test
hosts: webservers
vars:
web_service:
- httpd
- vsftpd
tasks:
- name: apache and vsftpd are running
service:
name: "{{ item }}"
state: started
loop: "{{ web_service }}"
##循环散列或字典列表
---
- name: User Test
user:
name: "{{ item.name }}"
state: present
groups: "{{ item.groups }}"
loop:
- name: westos
groups: westos
- name: redhat
groups: root
##早些版本的循环,使用with_
vars:
data:
- user1
- user2
- user3
tasks:
- name: "with_items"
debug:
msg: "{{ item }}"
with_items: "{{ data }}"
##register和loop一起使用
[root@workstationloop]#cat loop_register.yml
---
- name: loop register test
gather_facts: no
hosts: localhost
tasks:
- name: loop echo task
shell: "echo This is my item: {{ item }}"
loop:
- one
- two
register: echo_results #注册变量
- name: Show echo results variable
debug:
var: echo_results #显示变量结果
##迭代上面playbook的结果(即使用上面item的结果)
---
- name: loop register test
gather_facts: no
hosts: localhost
tasks:
- name: loop echo task
shell: "echo This is my item: {{ item }}"
loop:
- one
- two
register: echo_results
- name: Show echo results variable
debug:
msg: "STDOUT from previous task: {{ item.stdout }}"
loop: "{{ echo_results['results'] }}"
##条件任务语法
关键字:when
使用布尔值测试
---
- name: Bool ean test
hosts: all
vars:
run_my_task: true #只有当变量为true时,才会执行
tasks:
- name: httpd is installed
yum:
name: httpd
when: run_my_task
测试my_service变量是否有值,有值则安装
---
- name: Bool ean test
hosts: all
vars:
my_service: httpd
tasks:
- name: "{{ my_service }} is installed"
yum:
name: "{{ my_service }}"
when: my_service is defined
##条件
等于(字符串) A == "B"
等于(数字) A == 100
小于 <
大于 >
小于等于 <=
大于等于 >=
不等于 !=
变量存在 xxx is defined
变量不存在 xxx is not defined
布尔值true 1、true、yes
布尔值false 0、false、no
第一个变量的值存在,且在第二个变量的列表中 A in B
##测试多个条件
or两个条件一个为真即可
and两个条件必须都为真
#when支持使用列表描述条件
when:
-ansible_distribution_version=="8.0"
-ansible_kernel=="4.18.0-80.1.2.el8_0.x86_64"
再如:
when:
(ansible_distribution=="RedHat"and
ansible_distribution_major_version=="8")
or
(ansible_distribution=="CentOS"and
ansible_distribution_major_version=="7")
这样写清晰
##组合循环和有条件任务
示例1:
---
- name: keyword
hosts: all
tasks:
- name: install db if enough space
yum:
name: mariadb-server
state: latest
loop: "{{ ansible_mounts }}" #这个变量是事实,已知的
when: item.mount == "/" and item.size_available > 300000000
示例2:
---
- name: Restart httpd if vsftpd is running
hosts: all
tasks:
- name: Get vsftpd status
command: /usr/bin/systemctl is-active vsftpd #判断状态
ignore_errors: yes #如果vsftpd没运行或失败,则忽略
register: result #定义变量保存结果
- name: Restart httpd
service:
name: httpd
state: restarted
when: result.rc == 0 #退出码为0,则重启httpd
##编写循环和条件任务:练习:
[root@workstation~]#mkdir control-flow
[root@workstationcontrol-flow]#cat ansible.cfg
[defaults]
inventory=./inventory
[root@workstationcontrol-flow]#cat inventory
[westos1]
servera.lab.example.com
[westos2]
serverb.lab.example.com
#写playbook
[root@workstationcontrol-flow]#catplaybook.yml
---
- name: Mariadb is running
hosts: westos1
vars:
mariadb_pkgs:
- mariadb-server
- python3-PyMySQL
tasks:
- name: Mariadb is installed
yum:
name: "{{ item }}"
state: present
loop: "{{ mariadb_pkgs }}"
- name: Start Mariadb
service:
name: mariadb
state: started
enabled: true
#修改playbook,条件变为受管主机使用rehdat操作系统时才执行
[root@workstationcontrol-flow]#cat playbook.yml
---
- name: Mariadb is running
hosts: westos2
vars:
mariadb_pkgs:
- mariadb-server
- python3-PyMySQL
tasks:
- name: Mariadb is installed
yum:
name: "{{ item }}"
state: present
loop: "{{ mariadb_pkgs }}"
when: ansible_distribution == "RedHat"
#检测westos2组的主机系统
[root@workstationcontrol-flow]#ansible westos2 -m command -a 'cat /etc/redhat-release' -u student --become
serverb.lab.example.com | CHANGED | rc=0 >>
Red Hat Enterprise Linux release 8.0 (Ootpa)
#运行
[root@workstationcontrol-flow]#ansible-playbook playbook.yml·
PLAY[Mariadbisrunning]******************************************************
TASK[GatheringFacts]*********************************************************
ok:[serverb.lab.example.com]
TASK[Mariadbisinstalled]****************************************************
changed:[serverb.lab.example.com]=>(item=mariadb-server)
changed:[serverb.lab.example.com]=>(item=python3-PyMySQL)
PLAYRECAP*********************************************************************
serverb.lab.example.com:ok=2changed=1unreachable=0
failed=0skipped=0rescued=0ignored=0
######实施处理程序######
处理程序是响应由其他任务触发的通知的任务
#只有在template任务通知已发生更改时才会触发
---
- name: Test
hosts: webservers
tasks:
- name: Copy File
template:
src: files/example.conf
dest: /etc/httpd/conf.d/example.conf
notify: #notify语句指出该任务需要触发一个处理程序
- restart apache #程序名
handlers: #表示处理程序任务列表的开头
- name: restart apache #被任务调用的处理程序名称
service: #处理该程序的模块
name: httpd
state: restarted
#ansible把notify语句当作数组
[root@workstationcode]#mkdir files
[root@workstationcode]#cat files/example.conf
<VirtualHost *:80>
DocumentRoot /www
ServerName www.westos.org
</VirtualHost>
<VirtualHost *:80>
DocumentRoot /bbs
ServerName bbs.westos.org
</VirtualHost>
#写playbook
[root@workstationcode]#cat notify.yml
---
- name: Test
hosts: webservers
tasks:
- name: Copy File
template:
src: files/example.conf
dest: /etc/httpd/conf.d/example.conf
notify:
- restart apache
- restart mysql
handlers:
- name: restart apache
service:
name: httpd
state: restarted
- name: restart mysql
service:
name: mariadb
state: restarted
#使用处理程序注意:
1.处理程序始终按照play的handlers部分指定的顺序运行,不按notify里的
2.处理程序通常在相关play中所有其他任务运行完后运行
3.处理程序名称存在于个play命名空间中(如果两个处理程序同名,只会运行一个)
4.如果多个任务通知处理程序,处理程序也只会运行一次
5.如果包含notify的语句任务没有报告changed结果,则处理程序不会获得通知