编写和运行Playbook

playbook运行

运行

ansible-playbook playbook.yaml

语法检查

选项–syntax-check,只检查剧本语法,不执行剧本。

空运行,是指模拟运行,并不是真正执行。

ansible-playbook playbook.yaml -C

Playbook提权

在playbook中指定此关键字将覆盖/etc/ansible/ansible.cfg文件中的设置特权升级属性

  • remote_user,指定ssh用户

  • become,启用或禁用特权升级

  • become_method,启用特权升级的方法

  • become_user,特殊升级的帐户

部署文件到受管主机

修改文件并将其复制到主机

file模块

设置vim环境便于编辑Playbooks

[kitty@controller webapp 10:34:07]$ vim ~/.vimrc
set ts=2
set paste

示例1:创建文件或修改文件属性

vim test1.yaml
---
- hosts: node1
  gather_facts: no
  tasks:
    - name: Touch a file and set permissions
      file:
        path: /tmp/testfile
        owner: kitty
        group: wheel
        mode: 0640
        state: touch
...

#执行该文件
ansible-playbook test.yaml

示例2:创建目录

vim test2.yaml
---
- hosts: node1
  gather_facts: no
  tasks:
    - name: create directory
      file:
        path: /webdev
        owner: kitty
        group: kitty
        mode: 0755
        state: directory 
...

示例3:删除文件

vim test3.yaml
---
- hosts: node1
  gather_facts: no
  tasks:
   -  name: delete file 
      file:
        path: /tmp/testfile
        state: absent

lineinfile模块

示例1:确保文件中存在特定行

vim file1.yaml
---
- hosts: node1
gather_facts: no
tasks:
- name: add line
lineinfile:
path: /tmp/testfile
line: 'Add this line to file'
state: present
#执行
ansible-playbook file1.yaml

验证:

[root@node1 ~ 10:48:43]# cat /tmp/testfile
Add this line to file

最后一个匹配到后插入

---
- hosts: node1
gather_facts: no
tasks:
- name: add line
lineinfile:
path: /etc/httpd/conf/httpd.conf
line: 'Listen 82'
insertafter: 'Listen 80'
state: present

验证:

[root@node1 ~ 11:20:49]# cat /etc/httpd/conf/httpd.conf
hello
nihao
[root@node1 ~ 11:20:55]# cat /etc/httpd/conf/httpd.conf
hello
nihao
Listen 82

示例2:替换文本行

---
- hosts: node1
gather_facts: no
tasks:
- name: replace line
lineinfile:
path: /tmp/testfile
regexp: 'Add'
line: 'replace'
state: presen

验证:

[root@node1 ~ 11:23:49]# cat /tmp/testfile
hello
Add this line to file
nihao
[root@node1 ~ 11:23:53]# vim /tmp/testfile
[root@node1 ~ 11:24:46]# cat /tmp/testfile
hello
replace
nihao

示例3:替换成多行文本

---
- hosts: node1
gather_facts: no
tasks:
- name: add line
lineinfile:
path: /tmp/testfile
line: |
line 1
line 2
regexp: 'replace'
state: present

验证

[root@node1 ~ 11:30:02]# cat /tmp/testfile
hello
replace
nihao
[root@node1 ~ 11:34:53]# cat /tmp/testfile
hello
line 1
line 2
nihao

replace模块

该模块使用正则表达式匹配内容,将匹配的内容替换成指定的内容。 匹配的多个地方都会被替换掉

示例 :

---
- hosts: node1
gather_facts: no
tasks:
- name: replace multi line
replace:
path: /tmp/testfile
regexp: '^Hello World.*'
replace: 'Hello Laoma'

验证

[root@node1 ~ 11:41:09]# cat /tmp/testfile
Hello World
line 1
line 2
nihao
[root@node1 ~ 11:41:11]# cat /tmp/testfile
Hello kitty
line 1
line 2
nihao

copy模块

示例1:将控制节点上文件拷贝到受管理节点,类似于Linux中scp命令。

---
- hosts: node1
gather_facts: no
tasks:
- name: copy /tmp/testfile to remote node
copy:
src: /tmp/testfile
dest: /tmp

说明:此模块假定设置了force: yes,强制覆盖远程文件,类似scp命令。如果设置force: no, 则不会出现覆盖

#验证
[kitty@controller webapp 11:45:37]$ cat /tmp/testfile 
hello world
kitty
[root@node1 ~ 11:46:05]# cat /tmp/testfile
hello world
kitty

示例2:写入字符串到文件

---
- hosts: node1
gather_facts: no
tasks:
- name: write string into /tmp/testfile
copy:
content: "hello world\n"
dest: /tmp/testfile

验证

[root@node1 ~ 11:46:05]# cat /tmp/testfile
hello world
kitty
[root@node1 ~ 11:46:14]# cat /tmp/testfile
hello world

管理变量和事实

管理 VARIABLES

变量简介

ansible 利用变量来存储数据,以便在Ansible项目文件中重复引用,有利于简化项目的创建和维护,降低出错率。我们在playbook中可以针对如用户、软件包、服务、文件等进行变量定义。

变量命名规则

只能包含字母、数字和下划线(如包含空格、点、 $符号都为非法变量名)
只能以字母开头

变量范围和优先级

ansible项目文件中多个位置支持定义变量,主要包含三个基本范围:

  • Global scope:从命令行或 Ansible 配置设置的变量。
  • Play scope:在play和相关结构中设置的变量。
  • Host scope:由清单、事实(fact)收集或注册的任务,在主机组和个别主机上设置的变量。
    优先级从高到低顺序: Global -> Play -> Host
    在多个级别上定义了相同名称的变量,则采用优先级别最高的变量。

Global scope

最高级别的变量,影响整个 Ansible 运行环境。

通过选项-e传递给ansible或者ansible-playbook命令

ansible node1 -m debug -a "msg={{ package }}" -e "package=httpd"
#输出的结果
node1 | SUCCESS => {
    "msg": "httpd"
}

ansible node1 -m yum -a "name={{ package }} state=present" -e "package=httpd"
# name={{ package }} state=present
# name: 要操作的软件包名称,使用变量 {{ package }}
# state=present: 确保软件包已安装(如果未安装则安装)
#-e "package=httpd" 设置变量 package 的值为 "httpd"(Apache Web 服务器)
# 所以最终 {{ package }} 会被替换为 httpd

Play scope

在单个 play 内部定义的变量,作用于该 play 的所有主机。

vars 声明

格式1:

vim vars1.yaml
# 在node1主机上创建用户joe,并设置其家目录为/home/joe,然后显示用户信息。
---
- name: test vars statement in play
  hosts: node1
  vars:
    #设置变量
    user: joe
    home: /home/joe
  tasks:
    - name: add user {{ user }}
      user:
        #调用变量
        name: "{{ user }}"
        home: "{{ home }}"
        state: present
    #输出用户信息
    - name: debug user
      debug:
        msg: |
          username is {{ user }}
          home is {{ home }}
#执行
ansible-playbook vars1.yaml
...
"msg": "username is joe\nhome is /home/joe\n"
...

格式2

# 列表格式变量
---
- name: test vars statement in play
  hosts: node1
  vars:
    - user: joe
    - home: /home/joe
  tasks:
    - name: add user {{ user }}
      user:
        name: "{{ user }}"
        home: "{{ home }}"
        state: present

    - name: debug user
      debug:
        msg: |
          username is {{ user }}
          home is {{ home }}
vars_files 声明

如果变量比较多,可以使用变量文件进行分类,然后分列别应用到playbook中。

示例:

mkdir vars
vim vars/user1.yaml
# yaml 格式
user: user1
home: /home/user
---
- name: test vars statement in play
  hosts: node1
  # 调用变量文件
  vars_files:
    - vars/user1.yaml
  tasks:
    - name: add user {{ user }}
      user:
        name: "{{ user }}"
        home: "{{ home }}"
        state: present
    - name: debug user
      debug:
        msg: >
          username is {{ user}}
          home is {{ home }}

Host scope

针对特定主机或主机组定义的变量。

主机清单中定义

较旧的做法是直接在清单文件中定义。不建议采用,但仍可能会遇到

示例:

vim inventory 
......
[webs]
# 添加变量
node1 user=laowang
node2 user=laoma
......

验证:

vim playbook.yaml

---
- name: test vars statement in play
  hosts: webs
  tasks:
    - name: add user {{ user }}
      user:
        name: '{{ user }}'
        state: present
    - name: debug user
      debug:
        msg: |
          username is {{user}}
# 输出结果:
ansible-playbook playbook.yaml
......
ok: [node1] => {
    "msg": "username is laowang\n"
}
ok: [node2] => {
    "msg": "username is laoma\n"
}
......

缺点:使得清单文件更复杂,在同一文件中混合提供了主机和变量信息

# 向webs主机组输出问候消息,调用变量
ansible webs -m debug -a 'msg="hello ,{{ user }}"'

修改inventory

[kitty@controller webapp 15:05:57]$ cat inventory 
[controllers]
controller

[webs]
node1 user=laowang
node2 
# 添加
[webs:vars]
user=laoma

[dbs]
node3
node4

[nodes]
node[1:4]
[kitty@controller webapp 15:04:59]$ ansible webs -m debug -a 'msg="hello ,{{ user }}"'
node1 | SUCCESS => {
    "msg": "hello ,laowang"
}
node2 | SUCCESS => {
    "msg": "hello ,laoma"
# 主机大于主机组
目录分层结构定义

在项目目录中创建如下目录:

  • group_vars,定义主机组变量。目录中文件名可以直接使用 主机组名 或者 主机组
    名.yaml 。
  • host_vars,定义主机变量。目录中文件名可以直接使用 主机名 或者 主机名.yam

示例1:

# 创建两个目录
mkdir host_vars group_vars
# 将变量写入上面两个目录中的文件
echo "user: laoma" > host_vars/node1.yml
echo "user: laowang" > group_vars/webs.yml
# 验证
ansible nodes -m debug -a 'msg="hello ,{{ user }}"'
node1 | SUCCESS => {
    "msg": "hello ,laoma"
}
node4 | FAILED! => {
    "msg": "The task includes an option with an undefined variable. The error was: 'user' is undefined"
}
node3 | FAILED! => {
    "msg": "The task includes an option with an undefined variable. The error was: 'user' is undefined"
}
node2 | SUCCESS => {
    "msg": "hello ,laowang"
主机连接特殊变量

ansible_connection,与主机的连接类型,可以是 smart、 ssh 或 paramiko。默认为
smart。
ansible_host,要连接的主机的名称,默认值就是主机清单名称。
ansible_port, ssh 端口号,如果不是 22。
ansible_user, ssh 用户名。
ansible_ssh_pass,要使用的 ssh 密码。切勿以纯文本形式存储此变量,始终使用保管库。
ansible_ssh_private_key_file, ssh 使用的私钥文件。如果使用多个密钥并且您不想使用
SSH 代理,这很有用。
ansible_ssh_common_args,此设置始终附加到 sftp、 scp 和 ssh 的默认命令行。
ansible_sftp_extra_args,此设置始终附加到默认的 sftp 命令行。
ansible_scp_extra_args,此设置始终附加到默认的 scp 命令行。
ansible_ssh_extra_args,此设置始终附加到默认的 ssh 命令行。
ansible_become,等效于 ansible_sudo 或 ansible_su,允许强制提权。
ansible_become_method,允许设置权限提升方法。
ansible_become_user,等效于 ansible_sudo_user 或 ansible_su_user,允许设置您通过
权限升级成为的用户。
ansible_become_pass,等效于 ansible_sudo_pass 或 ansible_su_pass,允许您设置权限
提升密码(切勿以纯文本形式存储此变量;始终使用保管库。请参阅变量和保管库)

数组变量

将多个值存储在同一变量中。

示例:

users:
  bjones:
    first_name: Bob
    last_name: Jones
    home_dir: /users/bjones
  acook:
    first_name: Anne
    last_name: Cook
    home_dir: /users/acook

数组变量引用方式 一:

# Returns 'Bob'
users.bjones.first_name
# Returns '/users/acook'
users.acook.home_dir

数组变量引用方式二 :

# Returns 'Bob'
users['bjones']['first_name']
# Returns '/users/acook'
users['acook']['home_dir']

引用方式总结:

  • 如果使用方法一.分隔符引用的关键字与python的功能函数同名,例如discard、 copy、add,那么就会出现问题。方法二[‘’]引用方式可以避免这种错误.
  • 尽管两种方法都可以使用,为了减少排故难度, Ansible中统一使用其中一种方法

示例1:

---
- name: test vars statement in play
  hosts: node1
  # 数组变量定义
  vars:
    users:
      laoma:
        user_name: laoma
        home_path: /home/laoma
      laowang:
        user_name: laowang
        home_path: /home/laowang
  tasks:
    - name: add user {{ users.laoma.user_name }}
      user:
        # 第一种方法引用变量
        name: '{{ users.laoma.user_name }}'
        home: "{{ users.laoma.home_path }}"
    - name: debug laowang
      debug:
        msg: >
       # 第二方法引用变量
          username is {{ users['laowang']['user_name'] }}
          home_path is {{ users['laowang']['home_path'] }}

MAGIC变量

magic 变量由 Ansible 自动设置,可用于获取与特定受管主机相关的信息

最常用四个 Magic 变量:

  • inventory_hostname,包含清单中配置的当前受管主机的主机名称。这可能因为各种原因而与FACTS报告的主机名称不同。

    [kitty@controller webapp 16:43:54]$ ansible node1 -m debug -a 'var=inventory_hostname'
    node1 | SUCCESS => {
        "inventory_hostname": "node1"
    }
    
  • group_names,列出当前受管主机所属的所有主机组。

    [kitty@controller webapp 16:44:24]$ ansible node1 -m debug -a 'var=group_names'
    node1 | SUCCESS => {
        "group_names": [
            "nodes", 
            "webs"
        ]
    }
    
  • groups,列出清单中的所有组,以及组中含有的主机。

    [kitty@controller webapp 16:45:14]$ ansible node1 -m debug -a 'var=groups'
    node1 | SUCCESS => {
        "groups": {
            "all": [
                "controller", 
                "node1", 
                "node2", 
                "node3", 
                "node4"
            ], 
            "controllers": [
                "controller"
            ], 
            "dbs": [
                "node3", 
                "node4"
            ], 
            "nodes": [
                "node1", 
                "node2", 
                "node3", 
                "node4"
            ], 
            "ungrouped": [], 
            "webs": [
                "node1", 
                "node2"
            ]
        }
    }
    
  • hostvars,包含所有受管主机的变量,可用于获取另一台受管主机的变量的值。如果还没有为受管主机收集FACTS,则它不会包含该主机的 FACTS。

当前主机清单

[kitty@controller webapp 15:56:31]$ cat inventory 
[controllers]
controller

[webs]
node1 
node2 

[dbs]
node3
node4

[nodes]
node[1:4]
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐