1.安装
2.部署ANSIBLE
   2.1INVENTORY
   2.2ANSIBLE配置文件
   2.3AD HOC命令
3.PLAYBOOK
4.变量
5.ansible vault加密变量
6.ansible_facts
7.loop
8.条件判断
9.handler处理
10.错误处理
11.tags标签
12.管理文件
13.template模板
14.host-pattern
15.动态Inventory
16.role
17.配置并行

 


1.安装

  1.1控制节点:linux 
  1.2 受管主机:windows

yum install ansible
yum install python36

2. 部署ANSIBLE

  目录结构

ansible_facts受用_linux

ansible_facts受用_ansible_facts受用_02

2.1INVENTORY

     mkdir  web

     vim inventory

     格式:INI,YAML格式。

ansible all -i inventory --list-host #当前文件夹
# 系统目录 /etc/ansible/hosts 

#查找是否有 servera这个主机
ansible all -i ./inventory --list-hosts servera

#在文件中查找 abc
grep abc /etc/hosts

#不属于任何组
ansible all -i ./inventory --list-hosts ungrouped

树形查看:ansible-inventory -i inventory --graph

[njwebs]
servera
serverb
[njdbs]
serverc
serverd
[nj:children]
njwebs
njdbs

2.2ANSIBLE配置文件

2.21配置文件及优先级  

    文件位置和优先级:由上到下,优先级越来越高。

  ./相对路径

ansible_facts受用_ansible_03

 查看当前使用的配置文件:

ansible --version|grep 'config file'

在文件 ansible.cfg中查找 ‘^\[’

egrep  ‘^\[’ ansible.cfg

ansible_facts受用_ansible_facts受用_04

2.22常见配置 

ansible_facts受用_ansible_facts受用_05

2.23 验证配置
ansible all -m command -a id

2.3AD HOC命令

目的:

1.快速执行单个任务

2.快速测试和更改

3.执行简单任务

ansible_facts受用_服务器_06

返回值:

ansible_facts受用_linux_07


 

3.PLAYBOOK

vim ~/.vimrc    在家目录下 用vim时执行命令
bash ~/.bashrc 在家目录下 用bash时执行命令 
vim /etc/vimrc  全局的vimrc

set ai ts=2
# ai 自动缩进 ts=2 tab键用2个空格实现

3.1一文件一个列表:

---                         #开始
- name: create user         # - 代表列表
  hosts: servera
  tasks:
    - name: create user laoma
      user:
        name: tang
        uid:
        state: present
  shuiguo:                
    - pingguo
    - juzi
    - taozi
  

...                         #结束 一般不写

 3.2 一文件中多个列表

ansible_facts受用_ansible_facts受用_08


3个层次:是列表类型 - 

1.play :name,hosts,tasks

2.tasks:name,模块

3.模块

冒号后有一个空格 字典类型(多个键值对)

key: value  字典类型

 4.变量

   4.1变量定义

ansible_facts受用_ansible_facts受用_09

ansible_facts受用_vim_10

 4.2 变量作用域

ansible_facts受用_ansible_11


4.3 引用变量时要用引号

1.变量声明


ansible_facts受用_服务器_12

 2.变量文件声明

ansible_facts受用_ansible_facts受用_13


注意:

:后面一定要加“”或者‘’

ansible_facts受用_linux_14

 4.4.主机变量和主机组变量

 1.主机变量:

ansible_facts受用_linux_15

---
- name: test vars
  hosts: servers
  remote_user: root
  vars_files:
    - vars/user1.yml
  #vars:
  #  user: joe
  #  home: /home/joe
  tasks:
    - name: add user {{ user }}
      user:
        name: "{{ user }}"
        home: "{{ home }}"
    - name: debug user
      debug:
        msg: >
          username is  {{ user }}
          home is {{ home }}

inventory

[servers]
servera user=usera home=/opt/usera
serverb user=userb home=/opt/userb

此时 vars_files需要注释掉。

2.主机组变量
   优先级低于主机变量的。
inventory

[servers]
servera user=usera home=/opt/usera
serverb
[servers:vars]
user=tom
home=/opt/tom

3.如果有非常多的主机:

ansible_facts受用_服务器_16


3.1主机目录:host_vars:

3.2主机组目录:group_vars:

#1.创建目录mkdir host_vars

#2.创建servera.yml.   serverb.yml

vim host_vars/servera.yml

user: user1
home: /opt/user1
user: user2
home: /opt/user2

grep . host_vars/* #  当前目录/host_vars/

3.2主机组目录:group_vars:
vim  group_vars/servers.yml

users: user-servers
home: /opt/user-servers

tree group_vars/  host_vars/  

ansible_facts受用_ansible_17

4.4数组变量

ansible_facts受用_服务器_18


 

4.41数组列表树形结构
      users_vars.yml

user: user1
home: /opt/user1
ansible_host: servera.lab.example.com
ansible_user: root
users:
  bjones:
    frist_name: Bob
    last_name: Jones
    home_dir: /users/bjones
  acook:
    frist_name: Anne
    last_name: Cook
    home_dir: /users/acook

users-play.yml

---
- name: test vars
  hosts: servera
  remote_user: root
  tasks:
    - name: add user {{ user }}
      user:
        name: "{{ users.bjones.first_name }}_{{ users.bjones.last_name }}"
        home: "{{ users.bjones.home_dir }}"
        state: present
    - name: add user {{ user }}
      debug:
        msg: >
          username is {{ user }}
          home is {{ home }}

4.42变量是两个列表,引用时使用下标的方式:

users_vars.yml

user: user1
home: /opt/user1
ansible_host: all
ansible_user: root
users:
  - first_name: bob
    last_name: jones
    home_dir: /users/bjones
  - first_name: Anne
    last_name: Cook
    home_dir: /users/acook

users_play1.yml

---
- name: test
  hosts: servera
  remote_user: root
  tasks:
    - name: create
      file:
        path: /users
        state: directory
    - name: add user
      user:
        name: "{{ users[0].first_name }}_{{ users[0].last_name }}"
        home: "{{ users[0].home_dir }}"
        state: present
    - name: debug
      debug:
        msg: >
          username is {{ user }}
          home is {{ home }}

users_play2.yml

---
- name: test
  hosts: servera
  remote_user: root
  tasks:
    - name: create
      file:
        path: /users
        state: directory
    - name: add user
      user:
        name: "{{ users[0]['first_name'] }}_{{ users[0]['last_name'] }}"
        home: "{{ users[0]['home_dir'] }}"
        state: present
    - name: debug
      debug:
        msg: >
          username is {{ user }}
          home is {{ home }}

以上两种都可以。vim
1.块复制
    编辑可视块提示字样 :ESC+   ctrl+V 
    复制:选取 +y
    黏贴:p
     回到编辑态
2.删除所有行内容
    ESC:退出编辑模式
    g g:光标移到文本的首行
    d+G:
    ESC:1,$d 
3.替换  把users 替换成 user-type1
  :%s/users/users-type1/g
   

4.43用于捕获任务输出

ansible_facts受用_ansible_19

users_vars.yml

user: user1
home: /opt/user1
ansible_host: all
ansible_user: root
users_type2:
  - first_name: bob
    last_name: jones
    home_dir: /users/bjones
  - first_name: Anne
    last_name: Cook
    home_dir: /users/acook
users_type1:
  - first_name: bob
    last_name: jones
    home_dir: /users/bjones
  - first_name: Anne
    last_name: Cook
    home_dir: /users/acook

users_play.yml

---
- name: test vars
  hosts: servera
  remote_user: root
  tasks:
    - name: add user
      user:
        name: "{{ users_type1[0].frist_name }}_{{ users_type1[0].last_name }}"
        home: "{{ users_type1[0].home_dir }}"
        state: present
      register: result  #定义了一个变量用于存储返回值
    - name: show result
      debug:
        var: result

4.5 4个MAGIC变量

ansible_facts受用_linux_20


 

hostvars[host].ansible_default_ipv4.address
hostvars[host].ansible_fqdn
hostvars[host].ansible_hostname

when inventory_hostname in groups.dev

5.ansible vault加密变量
 

ansible-vault --help

# 加密
ansible-valut encrypt host_vars/servera.yml
# 查看
ansible-valut view host_vars/servera.yml
# 编辑
ansible-valut edit host_vars/servera.yml
# 解密
ansible-valut decrypt host_vars/servera.yml

#创建
ansible-valut create securite.yml

6.ansible_facts

 通过setup模块查看: ansible servera -m setup|less

  ansible servera -m setup | less

  ansible servera -m setup > fact.yml

ansible_facts受用_服务器_21

 ansible servera -m debug -a 'var=ansible_facts'
#看不到值的
show_facts.yml

---
- name: show var ansible_facts
  hosts: servera
  tasks:
    - name: show var ansibe_facts
      debug:
        var: ansible_facts

deploy_web.yml
不收集事实 gather_facts: false

---
-  name:
   hosts: servera
   gather_facts: false
   remote_user: root
   become: true
   become_method: sudo
   become_user: root
   tasks:
    - name:
      yum:
        name: httpd
        state: present
    - name:

ansible_facts受用_ansible_22

 引用 两种写法
 ansible_default_ipv4.address
 ansible_facts.default_ipv4.address

 1.判断是否存在
ansible_lvm.vgs.research is defined
ansible_lvm.vgs.research is not defined
ansible_devices.vdb is defined
ansible_devices.vdb is not defined
2.取值
 {{ hostvars[host].ansible_default_ipv4.address }} 
{{ hostvars[host].ansible_fqdn }}
{{ hostvars[host].ansible_hostname }}
‘memory={{ ansible_memtotal_mb }}’
'vdasize={{ ansible_devices.vda.size | default("NONE")}}'

7.loop

#删除 host_vars里的文件
rm -fr host_vars/*
vim host_vars/servera/users_vars.yml

ssh root@servera "egrep 'jack|tom' /etc/passwd"

users_vars.yml

#写法1
user1: jack
user2: tom

#写法2
users:
  - jack
  - tom

#写法3
users:
  bjones:
    frist_name:
    last_name:
    home_dir:
  acook:
    frist_name:
    last_name:
    home_dir:

users_play_loop1.yml

---
- name: create users
  hosts: servera
  gather_facts: no
  vars:
    users:
      - jack
      - tom
  tasks:
    - name: add user jane
      user:
        name: "{{ item }}"
        state: present
      loop:
        - jack
        - tom

users_play_loop2.yml

---
- name: create users
  hosts: servera
  gather_facts: no
  vars:
    users:
      - jack
      - tom
  tasks:
    - name: add user jane
      user:
        name: "{{ item }}"
        state: present  #删除 absent
      loop: "{{ users }}"

7.1简单的循环

    声明变量和不声明变量2种。

ansible_facts受用_ansible_facts受用_23

 7.2循环列表值  列表中带有字典

ansible_facts受用_ansible_24

 7.3with_list with_item

ansible_facts受用_服务器_25


7.4with_random_choice

8.条件判断

8.1判断:== 》等
是否定义:is defined 

---
- name: test when
  hosts: servera
  gather_facts: no
  vars:
    run_mytasks: true
  tasks:
    - name:
      debug:
        msg: "hello my task"
      when: run_mytasks

ansible_facts受用_服务器_26



8.2  判断执行结果

ansible_facts受用_vim_27


 

9.handler处理:

ansible_facts受用_ansible_facts受用_28

与一般的任务区别在于什么?
handlers:
1.多个任务都会执行同一个函数,最后一个任务时才执行
2.任务发生改变时才通知handlers
3.如果状态未发生改变是不执行的,比如相同的playbook,运行两次。

一步步执行
ansible-playbook handlers.yml --step
notify:
    - hello
    - restart apache
handlers:
    - name: restart apache
       service:
           name:
           state:
    - name: hello
      debug:

先执行 restart apache,再执行hello 
执行顺序取决于 handlers 而非 notify

10.错误处理

1.返回值变量关键字:register
2.返回的值: successded,failed,changed
3.忽略执行错误:ignore_errors: true  #yes

---
- name: test error
  hosts: servera
  gather_facts: no
  vars:
    doshell: "yes"
  tasks:
    - shell : cat /etc/host
      register: result
      ignore_errors: true
      when: deoshell == "yes"
    - name: success
      debug:
        msg: success
      when: result is succeeded
    - name: failed
      debug:
        msg: failed
      when: result is failed
    - name: changed
      debug:
        msg: changed
      when: result is changed

1.一般任务,忽略错误

 2.notify-handler模式的play,执行失败后仍然运行handlers

3.failed模块, 任务必定failed,停在这一步。

ansible_facts受用_服务器_29


4.failed_when 指明什么条件下,判定任务执行失败。

ansible_facts受用_ansible_facts受用_30

5.ansible block和错误处理
  5.1当两个语句都需要when 语句判断时,用了block。

---
- name: block example
  hosts:
  gather_facts: no
  tasks:
    - block:
        - name:
          debug:
            msg: task1
        - name:
          debug:
            msg: task2
       when: ansible_distribution == "redhat"

5.2 三个层次

    block 是主任务,执行失败时运行rescue,无论成功与否都执行always.


ansible_facts受用_ansible_facts受用_31

---  
- name: test block  
  hosts: mytest
  gather_facts: no
  vars:
    - run: no
  tasks:
    - block:
        - name:
          debug:
            msg: task1 in block
        - name:
          debug:
            msg: task2 in block
      rescue:
         - name:
           debug:
             msg: task1 in rescue
         - name:
           debug:
             msg: task2 in rescue
      always:
        - name:
          debug:
            msg: task1 in always
        - name:
          debug:
            msg: task2 in always

 查看 ansible facts值:ansible servera -m setup|less
 

11.tags标签

---
- name:
  hosts:
  tasks:
    - name: httpd
      yum:
        name: httpd
        state: latest
      tags: webserver
    - name:
      yum:
        name: postfix
        state: latest
      tags: mailserver
    - name: always debug
      debug:
        msg: debug

ansible_facts受用_linux_32

12.管理文件
 

查找本地的用户和组: /etc/shadow   /etc/passwd
 

12.1 file 创建目录、文件、软硬链接
 

---
- name:
  hosts:
  tasks:
    - name: create file
      file: 
        path: ~/mytest/testfile
        owner:
        group:
        mode: '0640'
        setype: httpd_sys_content_t
        state: touch                             # state 参数file ,directory,link,touch
    - name: create directory
      file: 
        path: ~/mytest/testdir
        owner:
        group:
        mode: '0640'
        setype: httpd_sys_content_t
        state: directory                        # state 参数file ,directory,link,touch
    

   - name: install package
      yum: 
        name: httpd
        state: present                      #state 参数 present absent
    - name: install package
      service: 
        name: "{{ item }}""
        state: present
      loop:
        - httpd
        - firewalld
    - name: create user
      user: 
        name:  harry
        state: present
    - name: create groups
      group: 
        name:  sysm
        state: present

 

ansible_facts受用_ansible_facts受用_33

 file :touch:创建 ;absent:删掉;directory:目录。

12.2修改上下文  selinux context:sefcontext

ansible_facts受用_vim_34

12.3 lineinfile 修改文件内容

ansible_facts受用_ansible_facts受用_35

12.4 replace 多行替换

ansible_facts受用_linux_36

12.5 copy

ansible_facts受用_vim_37

13.template模板
 

13.1 基本功能

变量替换。被传输的文件内容是变量,每台机器各异。

ansible_facts受用_vim_38


1.模板调用:  mytesttemplate.yml

2.模板文件:my.cnf

 

---
- name: test jinja2
  hosts: servera
  tasks:
    - name:
      template:
        src: my.cnf
        dest: /root/my.cnf

my.cnf

bind {{ ansible_default_ipv4.address }}

13.2 jinja2模板

   模板中 光#不是注释。

语法:哪些内容被替换,哪些不被替换?

ansible_facts受用_vim_39

如果指示不用手动编辑:

1.ansible.cfg文件中添加

   ansible_managed= Ansible managed

2.jinja2 模板中添加

# {{ ansible_managed }}

13.21  条件语句+替换的变量是ansible_facts的值

{% for host in groups['all'] %}
{{ hostvars[host]['ansible_facts']['default_ipv4']['address'] }} {{ hostvars[host]['ansible_facts']['fqdn'] }} {{ hostvars[host]['ansible_facts']['hostname'] }}
{% endfor %}
{% for host in groups.all %}
{{ hostvars[host].ansible_default_ipv4.address }} {{ hostvars[host].ansible_facts_fqdn }} {{ hostvars[host].ansible_hostname }}
{% endfor %}

13.22 替换的变量来自文件
  变量文件:~/ansible/host_vars/servera.yml
 变量文件名为主机名,不可任意命名。

ssh_port: 1022
root_allowed: yes
groups_allowed: root
passwords_allowed: yes

模板文件:myvars.cnf

Port {{ ssh_port }}
ListenAddress {{ ansible_defalut_ipv4.address }}
PermitRootLogin {{ root_allowed }}
Allow Groups {{ groups_allowed }}
PasswordAuthentication {{ passwords_allowed }}

13.23 for循环的是自定义变量

模板文件:fro.j2

{% for user in users %}
user:{{ user }}
{% endfor  %}

变量文件:vim /host_vars/servera.yml

users:
  - user01
  - user02
  - user03

13.24

ansible_facts受用_ansible_40

ansible_facts受用_ansible_facts受用_41

13.25 变量过滤器

ansible_facts受用_vim_42

13.26 字符操作过滤器

14.host-pattern

ansible_facts受用_ansible_facts受用_43

 

ansible_facts受用_ansible_facts受用_44

# 1.查找主机 servera
ansible --list-hosts servera
# 2. 查找主机组   出2个
ansible --list-hosts datacenter1
# 并集
ansible --list-hosts datacenter1 ,new
ansible --list-hosts datacenter1 :new
#3.  查找父组     出4个 就是他们底下的 datacenter1 ,datacenter2
ansible --list-hosts datacenter

#4.模糊匹配  一定要加单引号
ansible --list-hosts all
ansible --list-hosts '*'
ansible --list-hosts 'server*'
ansible --list-hosts '172*'


#5.取两个主机组的交集
ansible --list-hosts ' datacenter1,&lab'
ansible --list-hosts ' datacenter1,&serverc'


#6.取数组第1个值, 0-1, -1最后
ansible --list-hosts 'new[0]'
ansible --list-hosts 'new[0-1]'
ansible --list-hosts 'new[-1]'

15.动态Inventory

ansible_facts受用_服务器_45

wget  http://       -O  inventory/inventorya.py
mv inventorya.py inventory

#添加执行权限
chmod +x inventory/*

inventory/inventorya.py --list | json_reformat

ansible_facts受用_ansible_facts受用_46

脚本如何写?

16.role

   16.1 role 结构 

  role 定义了:tasks,操作的主机,模板。

ansible_facts受用_ansible_47

3个示例:

16.11 timesync
 1.安装包
 2.复制角色所有文件
 3.查看帮助文件: 得到示例  README.md
 4.编写调用的:playbook

sudo yum list|grep roles*
sudo yum install -y rhel-system-roles
cp -r /usr/share/ansible/roles/rhel-systemroles.timesync roles/timesync
ansible-galaxy list
vim roles/timesync/README.md
---
- name: Use RHEL system role
  hosts: all
  vars:
    timesync_ntp_servers:
      - hostname: 172.25.254.254
        iburst: yes
  roles:
      - timesync

16.12 seliunx
 1.安装包。
 2.复制角色所有文件。
 3.查看帮助文件: 得到示例  
/usr/share/doc/rhel-system-roles/selinux/example-selinux-playbook.yml
 4.编写调用的:playbook 

sudo yum list|grep roles*
sudo yum install -y rhel-system-roles
cp -r /usr/share/ansible/roles/rhel-systemroles.selinux roles/selinux
ansible-galaxy list
cp /usr/share/doc/rhel-system-roles/selinux/example-selinux-playbook.yml ~/ansible/myselinux.yml
---
- name: Use RHEL system role
  hosts: all
  vars:
    selinux_policy: targeted
    selinux_state: enforcing
    selinux_reboot_required: true
  tasks:
    - block:
        - name: Apply SELinux role
          include_role:
            name: selinux
      rescue:
        - name: Check for failure for other reasons than required reboot
          fail:
          when: not selinux_reboot_required
        - name:
          reboot:
        - name: Reapply SELinux role
          include_role:
            name: selinux

16.13 apache

1.主任务:tasks: main.yml
2.主任务中的变量:defaults:main.yml 
3.主任务中的motd文件: vim files/motd
4.主任务中的
        4.1 模板文件:templates/laoma.conf.j2
        4.2 handlers文件:handlers/main.yml
5.
6.模板文件: templates/index.html.j2
7. 使用

1.主任务 tasks: main.yml

---
- name: install web
  tasks:
    - name: 1.install package  defaults/main.yml
      yum:
        name: "{{ web_package }}"
        state: present
    - name: 2.start service
      service:
        name: "{{ web_service }} "
        state: started
        enabled: yes
    - name: 3.prepare motd  files/motd
      copy:
        src: motd
        dest: /etc/motd
    - name: 4. prepare conf templates/laoma.conf.j2 handlers/main.yml
      template:
        src: laoma.conf.j2
        dest: /etc/httpd/conf.d/laoma.conf
      notify:
        - restart_web
    - name: 5.prepare docRoot
      file:
        path: "/var/www/html/{{ ansible_hostname }}"
        state: directory
    - name: 6.prepare index.html
      template:
        src: index.html.j2
        dest: "/var/www/html/{{ ansible_hostname }}/index.html"

2.主任务中的变量文件:defaults:main.yml 

---
web_package: httpd
web_service: httpd

3.主任务中的motd文件 vim files/motd

# /etc/issue和/etc/motd
#区别在于 /etc/issue 是在 登录之前显示, /etc/motd 是在登录之后显示
hello guys
welcome to servera!

4.主任务中的

    4.1模板文件: templates/laoma.conf.j2


ansible_facts受用_vim_48

    4.2  handlers文件:handlers/main.yml

---
- name: restart_web
  service:
    name: httpd
    state: restarted

5.
6.模板文件:templates/index.html.j2

hello guys
welcome to {{ ansible_fqdn }}!

meta/main.yml

   

ansible_facts受用_ansible_49

7.使用:ansible-galaxy list

---
- name:
  hosts: mytest
  roles:
    - apache

curl http://localhost

16.2 使用 rhel-system-role

   deploy apache
   vim mytestDeployApache.yml
16.21 :关键字
    roles:
        - apache

---
- name: deploy apache
  hosts: serverc
  roles:
    - apache

16.22 : tasks:
include_role:

16.3 使用 Galaxy 角色

查看:
ansible-galaxy info haproxy --offline
ansible-galaxy role info -h
ansible-galaxy search haproxy
ansible-galaxy install docker

安装:

单个安装和多个安装:

ansible-galaxy install -r  requires.yml

vim requires.yml

ansible_facts受用_vim_50


a) ansible init tang cd tang
b) cat  tasks/main.yml

17.配置并行
 

 17.1设置forks

ansible_facts受用_linux_51

1.修改主机清单:inventory:

[servers]
server[a:d]
# 1.查看默认配置
ansible-config  dump|grep -i fork
#2.修改配置文件
vim ansible.cfg
ansible all -m ping

2.修改配置文件: ansible.cfg

[defaults]
inventory=inventory
remote_user=root
forks=2

3.编写 playbook:

---
- name:
  hosts: all
  gather_facts: no
  tasks:
    - name: task1
      shell: sleep 3

4.设置并发台数:

4.1.修改配置文件 ansible.cfg 可以控制每次的台数
4.2.使用命令行控制:ansible-playbook playbook.yml -f 3 命令行高于配置文件。

 

17.2滚动更新
 

ansible_facts受用_vim_52

a)串行:一次完成整个playbook
  滚动更新用的就是串行。
b)并行:多台先完成一个task

关键词
serial: 2
serial: 20%

---
- name: test
  hosts: all
  serial: 2
  gather_facts: no
  tasks:
    - name: task 1
      shell: sleep 3

滚动更新示例:

ansible_facts受用_ansible_53

异步并行模式:

ansible_facts受用_ansible_54

 示例:

ansible_facts受用_ansible_55

---
- name:
  hosts:
  tasks:
    - name: connection
      shell:
      async: 5
      poll: 2

17.3wait_for模块

ansible_facts受用_ansible_facts受用_56

文件是否存在?
与file区别: 每隔30S测一次。
端口号是否打开?


17.4 async_status模块

  检测线程是否存在。2s测一次,最多30次,直到结束。