Ansible Playbooks高级使用
文件操作
文件创建
- file
用于设置文件/链接/目录的属性,或者删除文件/链接/目录
### state如果是directory当目录不存在时会自动创建;如果是file当文件不存在时不会自动创建
- name: Create log dir
file:
path: "{{ item.src }}"
state: directory
with_items: "{{ log_dirs }}"
when: is_metal | bool
tags:
- common-log
- name: Mask lxc-net systemd service
file:
src: /dev/null
path: /etc/systemd/system/lxc-net.service
state: link
when:
- ansible_service_mgr == 'systemd'
tags:
- lxc-files
- lxc-net
修改文件
- lineinfile
用于检测文件是否存在特殊行或者使用后端正则表达式来替换匹配到的特殊行
- name: Extra lxc config
lineinfile:
dest: "/var/lib/lxc/{{ inventory_hostname }}/config"
line: "{{ item.split('=')[0] }} = {{ item.split('=', 1)[1] }}"
insertafter: "^{{ item.split('=')[0] }}"
backup: "true"
with_items: "{{ extra_container_config | default([]) }}"
delegate_to: "{{ physical_host }}"
register: _ec
when: not is_metal | bool
tags:
- common-lxc
- replace
lineinfile的多行匹配版本,此模块会在文件中插入一段内容,并在内容开始和结束位置设置标签,后续可以使用标签可以对此块内容进行操作
### 在ml2_conf.ini文件的[ml2]和[ml2_type_vlan]字段之间插入一段内容
- name: Enable ovn in neutron-server
replace:
dest: "{{ node_config_directory }}/neutron-server/ml2_conf.ini"
regexp: '\[ml2\][\S\s]*(?=\[ml2_type_vlan\])'
replace: |+
[ml2]
type_drivers = local,flat,vlan,geneve
tenant_network_types = geneve
mechanism_drivers = ovn
extension_drivers = port_security
overlay_ip_version = 4
[ml2_type_geneve]
vni_ranges = 1:65536
max_header_size = 38
[ovn]
ovn_nb_connection = tcp:{{ api_interface_address }}:{{ ovn_northdb_port }}
ovn_sb_connection = tcp:{{ api_interface_address }}:{{ ovn_sourthdb_port }}
ovn_l3_mode = False
ovn_l3_scheduler = chance
ovn_native_dhcp = True
neutron_sync_mode = repair
backup: yes
when:
- action == "deploy"
- inventory_hostname in groups['network']
notify:
- Restart neutron-server container
- ini_file
ini后缀格式文件修改
### 设置l3_agent.ini文件[DEFAULT]字段的external_network_bridge选项值为br-ex
- name: Set the external network bridge
vars:
agent: "{{ 'neutron-vpnaas-agent' if enable_neutron_vpnaas | bool else 'neutron-l3-agent' }}"
ini_file:
dest: "{{ node_config_directory }}/{{ agent }}/l3_agent.ini"
section: "DEFAULT"
option: "external_network_bridge"
value: "{{ neutron_bridge_name | default('br-ex') }}"
backup: yes
when:
- action == "deploy"
- inventory_hostname in ovn_central_address
delegate_to: "{{ item }}"
with_items: "{{ groups['neutron-server'] }}"
notify:
- Restart {{ agent }} container
- assemble
将多个文件聚合成一个文件
### 将/etc/haproxy/conf.d目录下的文件内容聚合成/etc/haproxy/haproxy.cfg文件
- name: Regenerate haproxy configuration
assemble:
src: "/etc/haproxy/conf.d"
dest: "/etc/haproxy/haproxy.cfg"
notify: Restart haproxy
tags:
- haproxy-general-config
循环控制
- with_items
标准循环,用于执行重复任务,{{ item }}类似宏展开
- name: add several users
user:
name: "{{ item.name }}"
state: present
groups: "{{ item.groups }}"
with_items:
- { name: 'testuser1', groups: 'wheel' }
- { name: 'testuser2', groups: 'root' }
- with_nested
嵌套循环
### 修改neutron-server组所有主机的ml2_conf.ini文件的对应字段值
- name: Enable ovn in neutron-server
vars:
params:
- { section: 'ml2', option: 'type_drivers', value: 'local,flat,vlan,geneve' }
- { section: 'ml2', option: 'tenant_network_types', value: 'geneve' }
- { section: 'ml2', option: 'mechanism_drivers', value: 'ovn' }
- { section: 'ml2', option: 'extension_drivers', value: 'port_security' }
- { section: 'ml2', option: 'overlay_ip_version', value: '4' }
- { section: 'securitygroup', option: 'enable_security_group', value: 'True' }
ini_file:
dest: "{{ node_config_directory }}/neutron-server/ml2_conf.ini"
section: "{{ item[0].section }}"
option: "{{ item[0].option }}"
value: "{{ item[0].value }}"
backup: yes
when:
- action == "deploy"
- inventory_hostname in ovn_central_address
delegate_to: "{{ item[1] }}"
with_nested:
- "{{ params }}"
- "{{ groups['neutron-server'] }}"
notify:
- Restart neutron-server container
流程控制
- tags
设置任务标签
tasks:
- yum: name={{ item }} state=installed
with_items:
- httpd
- memcached
tags:
- packages
- template: src=templates/src.j2 dest=/etc/foo.conf
tags:
- configuration
### 执行playbook可以指定只执行标签对应任务或跳过标签对应任务
# ansible-playbook example.yml --tags "configuration,packages"
# ansible-playbook example.yml --skip-tags "notification"
- fail_when
用来控制playbook退出
- name: Check if firewalld is installed
command: rpm -q firewalld
register: firewalld_check
failed_when: firewalld_check.rc > 1
when: ansible_os_family == 'RedHat'
- pre_tasks/post_tasks
用来设置在执行roles模块之前和之后需要执行的任务
- name: Install the aodh components
hosts: aodh_all
gather_facts: "{{ gather_facts | default(True) }}"
max_fail_percentage: 20
user: root
pre_tasks:
- include: common-tasks/os-lxc-container-setup.yml
- include: common-tasks/rabbitmq-vhost-user.yml
static: no
vars:
user: "{{ aodh_rabbitmq_userid }}"
password: "{{ aodh_rabbitmq_password }}"
vhost: "{{ aodh_rabbitmq_vhost }}"
_rabbitmq_host_group: "{{ aodh_rabbitmq_host_group }}"
when:
- inventory_hostname == groups['aodh_api'][0]
- groups[aodh_rabbitmq_host_group] | length > 0
- include: common-tasks/os-log-dir-setup.yml
vars:
log_dirs:
- src: "/openstack/log/{{ inventory_hostname }}-aodh"
dest: "/var/log/aodh"
- include: common-tasks/mysql-db-user.yml
static: no
vars:
user_name: "{{ aodh_galera_user }}"
password: "{{ aodh_container_db_password }}"
login_host: "{{ aodh_galera_address }}"
db_name: "{{ aodh_galera_database }}"
when: inventory_hostname == groups['aodh_all'][0]
- include: common-tasks/package-cache-proxy.yml
roles:
- role: "os_aodh"
aodh_venv_tag: "{{ openstack_release }}"
aodh_venv_download_url: "{{ openstack_repo_url }}/venvs/{{ openstack_release }}/{{ ansible_distribution | lower }}/aodh-{{ openstack_release }}-{{ ansible_architecture | lower }}.tgz"
- role: "openstack_openrc"
tags:
- openrc
- role: "rsyslog_client"
rsyslog_client_log_rotate_file: aodh_log_rotate
rsyslog_client_log_dir: "/var/log/aodh"
rsyslog_client_config_name: "99-aodh-rsyslog-client.conf"
tags:
- rsyslog
vars:
is_metal: "{{ properties.is_metal|default(false) }}"
aodh_rabbitmq_userid: aodh
aodh_rabbitmq_vhost: /aodh
aodh_rabbitmq_servers: "{{ rabbitmq_servers }}"
aodh_rabbitmq_port: "{{ rabbitmq_port }}"
aodh_rabbitmq_use_ssl: "{{ rabbitmq_use_ssl }}"
tags:
- aodh
主机路由
- delegate_to
可以将当前任务放到其他hosts上执行
### 这是一段在容器中执行的playbook的一部分,这时候需要检测容器所在的宿主机上的对应目录是否存在,这时候就需要用到委托来跳出当前容器到宿主机上执行当前任务
- name: Ensure mount directories exists
file:
path: "{{ item['mount_path'] }}"
state: "directory"
with_items:
- "{{ lxc_default_bind_mounts | default([]) }}"
- "{{ list_of_bind_mounts | default([]) }}"
delegate_to: "{{ physical_host }}"
when:
- not is_metal | bool
tags:
- common-lxc
- local_action
将任务放在ansible控制主机(运行ansible-playbook的主机)上执行
- name: Check if the git cache exists on deployment host
local_action:
module: stat
path: "{{ repo_build_git_cache }}"
register: _local_git_cache
when: repo_build_git_cache is defined
用户和用户组控制
- group
创建用户组
### 创建系统管理员组haproxy,present表示不存在创建,absent表示存在删除
- name: Create the haproxy system group
group:
name: "haproxy"
state: "present"
system: "yes"
tags:
- haproxy-group
- user
创建用户
### 创建haproxy:haproxy用户,并创建home目录
- name: Create the haproxy system user
user:
name: "haproxy"
group: "haproxy"
comment: "haproxy user"
shell: "/bin/false"
system: "yes"
createhome: "yes"
home: "/var/lib/haproxy"
tags:
- haproxy-user
其他
- authorized_key
添加用户的SSH认证key
- name: Create authorized keys file from host vars
authorized_key:
user: "{{ repo_service_user_name }}"
key: "{{ hostvars[item]['repo_pubkey'] | b64decode }}"
with_items: "{{ groups['repo_all'] }}"
when: hostvars[item]['repo_pubkey'] is defined
tags:
- repo-key
- repo-key-store
- slurp
用来读取远程主机上文件内容是base64加密的文件
### 读取id_rsa.pub文件的内容,并设置到变量repo_pub中
- name: Get public key contents and store as var
slurp:
src: "{{ repo_service_home_folder }}/.ssh/id_rsa.pub"
register: repo_pub
changed_when: false
tags:
- repo-key
- repo-key-create
- uri
web访问,类似执行curl命令
- name: test proxy URL for connectivity
uri:
url: "{{ repo_pkg_cache_url }}/acng-report.html"
method: "HEAD"
register: proxy_check
failed_when: false
tags:
- common-proxy
- wait_for
等待一个端口变得可用或者等待一个文件变得可用
- name: Wait for container ssh
wait_for:
port: "22"
delay: "{{ ssh_delay }}"
search_regex: "OpenSSH"
host: "{{ ansible_host }}"
delegate_to: "{{ physical_host }}"
register: ssh_wait_check
until: ssh_wait_check | success
retries: 3
when:
- (_mc is defined and _mc | changed) or (_ec is defined and _ec | changed)
- not is_metal | bool
tags:
- common-lxc
- command
执行shell命令
### ignore_errors为true表示命令执行出错也不会退出playbook
- name: Check if clean is needed
command: docker exec openvswitch_vswitchd ovs-vsctl br-exists br-tun
register: result
ignore_errors: True
切换用户
### 使用become会先切换成apache用户,再执行command命令,默认become_user用户为root(如果你ansible配置的就是root用户的免密码登入那就不需要become了)
- name: Run a command as the apache user
command: somecommand
become: true
become_user: apache
检测链表是否为空
### pip_wheel_install为链表变量
- name: Install wheel packages
shell: cd /tmp/wheels && pip install {{ item }}*
with_items:
- "{{ pip_wheel_install | default([]) }}"
when: pip_wheel_install > 0