ansible-playbook基础语法

1:notify语法;

---         ###定义此文件为yaml文件
- hosts: all    ###playbook所针对的主机
  tasks:     ###playbook所定义的tasks集合

    - name: install base server    ##task的名字可自己定义
      yum: name=vim,httpd s
      state=installed   ###所调用的模块

    - name: copy the config.conf    
      copy: src=/root/http.conf dest=/etc/httpd/conf/http.conf
     notify:  ###触发handlers,如果拷贝的文件的md5值发生变化,就会触发 restart the httpd service这个handlers    
         - restart the httpd service

#    - name: start the httpd service
#      service: name=httpd state=started enabled=yes

  handlers:   ###定义一个handlers让 httpd服务重启。
   - name: restart the httpd service
     service: name=httpd state=restarted

2:调用某个yaml文件

使用
- import_playbook : base.yml
- include: base.yml       两种方式都可以

3:ansible roles基本语法结构

roles这个词:一个分类,将mysql、php等分为各自的大组,在各个角色内定义具体的小任务,方便管理,另一方面,类似于php的类的自动加载,roles基于一个已知的文件结构,可以自动去加载某些vars_files、tasks、handlers等。
一个项目的组成如下:
site.yml
webservers.yml
fooservers.yml
roles/
common/ # 一个角色包含了一个playbook的基本参数
files/
templates/ # 模板
tasks/ # 任务
handlers/ # 触发任务
vars/ # 变量
defaults/
meta/
webservers/
files/
templates/
tasks/
handlers/
vars/
defaults/
meta/

roles内各目录含义解释:
files:用来存放由copy模块或script模块调用的文件。
templates:用来存放jinjia2模板,template模块会自动在此目录中寻找jinjia2模板文件。
tasks:此目录应当包含一个main.yml文件,用于定义此角色的任务列表,此文件可以使用include包含其它的位于此目录的task文件。
handlers:此目录应当包含一个main.yml文件,用于定义此角色中触发条件时执行的动作。
vars:此目录应当包含一个main.yml文件,用于定义此角色用到的变量。
defaults:此目录应当包含一个main.yml文件,用于为当前角色设定默认变量。
meta:此目录应当包含一个main.yml文件,用于定义此角色的特殊设定及其依赖关系。

4:基础语法

---
- hosts: all
  gather_facts: no/false   ###设置为no或者false,否者会出现Gathering Facts卡住的问题
  remote_user; root   ###远程认证用户
  sudo: yes          ###设置sudo操作
  sudo_user: yaadmin   ###执行sudo操作的用户
  vars:               ####设置playbook变量
    nginx_port: 80
  vars_file:       ####设置playbook的变量调用文件
   - "var.yaml" 
   - [ "one.yaml" , "two.yaml" ]
 vars_prompt:  ###通过交互式输出变量
   - name: "password  vaes"  
     prompt: "Ether password"  ###使用prompt模块加密输出变量
     default: "secret"
     private: yes
     encrypt: "md5_crypt"
     confirm: yes
     salt: 1234
     salt_size: 8
   pre_tasks:  ###运行playbook之前的‘tasks’
     - name: pre-tasks
       shell; hostname
   roles:      ####设置引入role
     - docker 
     - { role: docker, version; '1.5.0', when: "ansible_system == 'Linux'", tags: [docker,install] } 
     - { role: docker, version; '1.5.0', when: "ansible_all_ipv4_addresses == '192.168.124.129' }
   tasks:    ####设置运行tasks
     - include: tasks.yaml
     - include: tasks.yaml ansible_distribution='Centos7'   ansible_distribution_version='6.6'
     - { include: tasks.yaml. version: '1.1', package: [nginx,httpd]}
     - include: tasks_192.168.124.129.yaml
       when: ansible_all_ipv4_addresses == '192.168.124.129'
   post_tasks:  ###设置playbook运行之后的tasks
     - name: post_tasks
       shell: hostname
   handlers:  ##设置playbook的handlers
     - include: handlers.yaml    
      

5:变量的调用
变量优先级:
1、extra vars(命令中-e)最优先
2、inventory 主机清单中连接变量(ansible_ssh_user 等)
3、play 中 vars、vars_files 等
4、剩余的在 inventory 中定义的变量
5、系统的 facts 变量
6、角色定义的默认变量(roles/rolesname/defaults/main.yml)
注:子组会覆盖父组,主机总是覆盖组定义的变量

命令行指定-e
ansible-playbook -i hosts site-1.yml -e "key=123456"

命令行-e指定yaml文件,yaml文件中定义变量
ansible-playbook -i hosts site-1.yml -e @value.yml

yaml文件中使用vars_files参数指定文件,如下:
---
- hosts: all
  gather_facts: no
  vars_files:      #####
  - value.yml      #####
  roles:
  - value
  - httpd

6:tag的使用方法

---
- hosts: all
  roles:
  - value   ###输出的role。
  - httpd
  - install-package
  tags:    ##使用tag模块定义
    - os   ###定义的tag名称
  - ansible
  tags:
    - ansible


使用方法:
ansible-playbook -i hosts site-1.yml -t ansible

7:抓取ip地址配置hosts文件

---
- hosts: all
  vars:
    IP: "{{ ansible_ens34['ipv4']['address'] }}"
  tasks:
    - name: backup the hosts
      shell: mv /etc/hosts /etc/hosts_bak 
      ignore_errors: yes  ###当前任务失败时,可以继续跑下面的playbook,不会造成中断

    - name: copy hosts file to other servers
      copy: src=/root/hosts dest=/etc/ owner=root group=root mode=0644

    - name: config ip hostname
      lineinfile: dest=/etc/hosts line="{{ IP }}  {{ ansible_hostname }}"

以上变量调用的是facts搜集的主机信息
需要在ansible.cfg添加如下配置:
[defaults]
inventory = /etc/ansible/hosts    ###主机清单文件
host_key_checking = False   ##不检查秘钥

gathering = smart      ###缓存方式
fact_caching = yaml     ###缓存方式
fact_caching_connection = /tmp/ansible_fact_cache  ###facts缓存路径
fact_caching_timeout = 300

forks=50

retry_files_enabled = False
callback_whitelist = profile_tasks

[ssh_connection]
pipelining = True

8:批量修改主机名

---
- hosts: all
  tasks:
    - name: show hostname
      shell: hostname
    - name: show ip
      command: ip a
    - hostname: name=web{{ ansible_default_ipv4.address.split('.')[-1] }}

9:网络地址查询

ipaddr使用方法:(需要先安装pip install netaddr)
定义变量:
net_mask: "{{ ansible_default_ipv4.address }}/{{ ansible_default_ipv4.netmask }}"
             192.168.124.129/255.255.255
 编辑filter.yml文件
 ---
- hosts: all
  vars:
    list: "{{ ansible_all_ipv6_addresses }}"
    net_mask: "{{ ansible_default_ipv4.address }}/{{ ansible_default_ipv4.netmask }}"
  tasks:
    - name: debug the min or max
#      debug: msg="{{ info | ipaddr('address') | ipwrap }}"
      debug: msg="{{ net_mask | ipaddr('prefix') }}"
输出结果为:“24”
ipaddr则直接输出192.168.124.129/24
ipaddr('network')输出结果为:192.168.124.0
ipaddr('network/prefix')输出结果为:192.168.124.0/24
ipaddr('host')输出结果为:192.168.124.129/24   
ipwrap:如果调用的是v4地址正常显示,v6地址则以[]显示
ipaddr('10')输出结果为:192.168.124.10/24,显示第十个地址
ipmath(19)输出结果为:192.168.124.29,当前地址+19
其他参数查询:https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters_ipaddr.html 

10:主机路由

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 }}"  ##如果在本地可以使用localhost
  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

11:playbook启动容器

- name: install os-net-config container
  docker_container:  ###调用docker_container模块
    name: os-net-config
    privileged: true  ###容器的执行权限
    network_mode: host   ##网路模式
    image: "{{ os_net_config_image_full }}"  ##镜像
    volumes:   ###映射的目录
      - "/etc/passwd:/etc/passwd:ro"
      - "/etc/os-net-config/:/etc/os-net-config/"
      - "/etc/driverctl.d:/etc/driverctl.d"
      - "/etc/sysconfig/:/etc/sysconfig/:rw"
      - "/lib/modules:/lib/modules:ro"
      - "/run/:/run/"
      - "/sys:/sys"
      - "/var/lib/os-net-config:/var/lib/os-net-config"
    command: os-net-config  ##执行的命令
    state: started  ##动作
  become: true

12:多个tasks合并一起,block

- block:
    - shell: rabbitmqctl stop_app
    - shell: rabbitmqctl join_cluster rabbit@{{ groups['web'].0 }}
    - shell: rabbitmqctl start_app
  when: ansible_default_ipv4.address != "{{ groups['web'].0 }}"

注:  groups['web'].0表示web主机组中的第一个主机

13:when条件使用

- name: start the mariadb service
  service:
    name: mariadb
    state: started
  delegate_to: localhost
  when:
    - ansible_default_ipv4.address == "{{ groups['all'].0 }}"
    - not  check_mariadb_file_exists.stat.exists
此处定义check_mariadb_file_exists.stat.exists结果为true,前面加not表示false。    
###满足上面两个条件tasks任务才可执行。

14:merge_configs用法

- name: Copying over ceph.conf
  vars:
    service_name: "{{ item }}"
  merge_configs:
    sources:
      - "{{ role_path }}/templates/ceph.conf.j2"
      - "{{ node_custom_config }}/ceph.conf"
      - "{{ node_custom_config }}/ceph/{{ inventory_hostname }}/ceph.conf"
    dest: "{{ node_config_directory }}/{{ item }}/ceph.conf"
    mode: "0660"
  become: true
  with_items:
    - "ceph-mon"
    - "ceph-osd"
    - "ceph-rgw"
    - "ceph-mgr"
    - "ceph-mds"
    - "ceph-nfs"
 merge_configs:将多个文件合并为1个文件,如果文件存在则匹配文件,不存在则忽略。

15:retries/delay

- name: configuring client.admin caps
  become: true
  kolla_ceph_keyring:
    name: client.admin
    caps: "{{ ceph_client_admin_keyring_caps }}"
  run_once: True
  delegate_to: "{{ groups['ceph-mon'][0] }}"
  register: result
  until: result is success
  retries: 3
  delay: 15
until:表示判断条件    retries: 重试次数    delay: 每次重试的中间间隔时间

16:判断条件

当判断某个字符是否在一组列表中时,可以通过in or not in来判断
举例如下:
---
- name: get the vms status
  os_server_info:
    auth:
      auth_url: "{{ auth_url }}"
      username: "{{ username }}"
      password: "{{ password }}"
      project_name: "{{ project_name }}"
      os_user_domain_name: "{{ os_user_domain_name }}"
      os_project_domain_name: "{{ os_project_domain_name }}"
    filters:
      vm_state: active
  register: result
   
- name: debug result
  debug: var=result.openstack_servers
   
- name: ensure the vms on the host
  debug: msg="have the vms on host yet"
  with_items:
    - "{{ result.openstack_servers}}"
  failed_when: '"{{ remove_node }}" in item.host'  ###通过in来判断remove_node是否在item.host中

注:判断要删除的节点remove_node是否在列表item.host中。
with_it

17:if else判断语句

类似于shell中的用法,如下:
enable_external: false
networks:
  state: "present"
  name: "v4"
  mtu: "1310"
  shared: "yes"
  external: "{{ 'yes' if enable_external | bool else 'no' }}"
  provider_network_type: "vlan"
  provider_physical_network: "physnet1"
  provider_segmentation_id: "155"
创建网络时是否启为external网络,通过enable_external:来判断。


- name: create networks for vms
  os_network:
    auth:
      auth_url: "{{ auth_url }}"
      username: "{{ username }}"
      password: "{{ password }}"
      project_name: "{{ project_name }}"
      os_user_domain_name: "{{ os_user_domain_name }}"
      os_project_domain_name: "{{ os_project_domain_name }}"
    name: "{{ item.name }}"
    state: "{{ item.state }}"
    mtu: "{{ item.mtu }}"
    shared: "{{ item.shared }}"
    external: "{{ item.external }}"
    provider_network_type: "{{ item.provider_network_type }}"
    provider_physical_network: "{{ item.provider_physical_network }}"
    provider_segmentation_id: "{{ item.provider_segmentation_id }}"
  with_items:
    - "{{ networks }}"
  when: not check_networks_exist.openstack_networks | bool
check_networks_exist.openstack_networks结果为false,前面加not表示为true。

18:忽略不存在的变量

当在多个字典中调用变量时,而字典中的内容不一定完全一致,有的变量不存在,调用变量时
可能会失败,可使用如下方法进行解决:
{{ item.oldVersionId |default('null') }}
当不存在时,可定义为null

19:url过滤器

过滤器「urlsplit」,用于分解一个url链接,取出我们需要的字段:
打印出url中所有可用的值,如下:
debug: msg="{{ "http://172.16.35.15:10080/autoops/spring-data-jpa-audit-extension.git" | urlsplit}}"
ok: [192.168.77.73] => {
    "msg": {
        "fragment": "", 
        "hostname": "172.16.35.15", 
        "netloc": "172.16.35.15:10080", 
        "password": null, 
        "path": "/autoops/spring-data-jpa-audit-extension.git", 
        "port": 10080, 
        "query": "", 
        "scheme": "http", 
        "username": null
    }
}

取出hostname的值,如下:
debug: msg={{ "http://172.16.35.15:10080/autoops/spring-data-jpa-audit-extension.git"|urlsplit('hostname') }}
ok: [192.168.77.73] => {
    "msg": "172.16.35.15"
}

20:字符串过滤

过滤字符串中的字符,选取需要的内容
- name: debug the file 
    debug: msg={{ "http://172.16.35.15:10080/autoops/spring-data-jpa-audit-extension.git".split('://')[1] }}
打印内容如下:
ok: [192.168.77.73] => {
    "msg": "172.16.35.15:10080/autoops/spring-data-jpa-audit-extension.git"
}

split('://')[1]:将上面链接分成两部分,取右面的值   

21:合并两个字典

- name: combine the dirct
    set_fact:
      var={{ {'a':1, 'b':2}| combine({'c':3}) }}
   
  - name: debug the var
    debug: msg="{{ var}}"
##################################################
Friday 14 August 2020  22:46:42 +0800 (0:00:00.068) ******* 
ok: [192.168.77.73] => {
    "msg": {
        "a": 1, 
        "b": 2, 
        "c": 3
    }
}

你可能感兴趣的:(ansible,自动化)