Ansible 的一些使用笔记

Ansible LINUX

Posted by gomyck on February 17, 2023

ansible 是又红帽开源的一款自动化部署工具, 基于 python, 实现了批量系统配置, 程序部署, 运行命令等功能

安装

使用 pip 安装 ansible 是最快最稳妥的安装方式

1
$ pip install ansible

使用

我们在使用 ansible 时, 通常使用 ansible-playbook 命令来执行多个任务流程, ansible 命令只适用于单个命令的执行, 不在赘述

playbook 使用方法:

1
2
3
# 使用-i 指定 inventory 文件, ansible 默认的 inventory 目录是 /etc/inventory  如果我们自定义文件的话 需要手动指定
# inventory 文件中配置的是主机列表以及主机相关的变量
$ ansible-playbook -i inventory install-helm.yaml

常用的 ansible-playbook 编排脚本模版如下:

这是一个在 docker 中离线安装 minio 集群的 ansible 脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
---
- name: 安装 minio 集群
  remote_user: root
  hosts: minio
  vars:
    store_image_path: /home/docker_images/
  tasks:
    - name: 组装集群信息
      set_fact:
        host_list: ""
        volume_mount: ""
    - name: 查看 docker 服务
      service:
        name: docker
        state: started
    - name: 查看文件夹是否存在
      file:
        path: 'item'
        state: directory
        mode: 0755
      with_items:
        - 'store_image_path'
        - 'dirs.file_path'
    - name: 复制本地镜像到服务器
      copy:
        src: 'image_pathimage_file'
        dest: 'item'
      with_items:
        - 'store_image_path'
    - name: 查看镜像是否存在
      shell: docker images | grep image_origin_name
      register: reg
      ignore_errors: True
      changed_when: 'reg.rc == 1'
    - name: 安装 minio 镜像
      when: reg.changed
      register: reg
      shell: docker load -i 'item'
      with_items:
        - 'store_image_pathimage_file'
    - name: 查看 minio 服务是否存在
      shell: docker ps | grep server_name
      register: reg
      ignore_errors: True
      changed_when: 'reg.rc == 1'
    - name: 删除原有未启动容器
      when: reg.changed
      shell: docker rm server_name
      ignore_errors: True
    - name: 启动 minio 集群
      when: reg.changed
      shell: docker run -d --net=host --name server_name \
             -e TZ=Asia/Shanghai --restart=unless-stopped \
             -e MINIO_SERVER_URL=http://inventory_hostname:9000 \
             volume_mount image_origin_name:image_version \
             server --console-address "inventory_hostname:9001" \
             host_list

下面是 inventory 文件的配置(yaml 形式, 为了更好的定义主机变量):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
minio:
  hosts:
    #需要安装的主机 IP
    192.168.x.x:
      dirs:
        #需要挂载的存储目录
        file_path:
          - /home/minio1/
          - /home/minio2/
    #需要安装的主机 IP
    192.168.x.xx:
      dirs:
        #需要挂载的存储目录
        file_path:
          - /home/minio1/
          - /home/minio2/
  vars:
    #本地存储镜像的路径
    image_path: /root/tmp/
    #本地存储镜像文件名
    image_file: minio.tar
    #镜像名称
    image_origin_name: minio/minio
    #镜像版本
    image_version: RELEASE.2023-01-12T02-06-16Z
    #启动后容器的名称
    server_name: gomyck_minio

playbook 常用的语法和内置变量

循环的一些用法:

名称 作用
with_items 简单的列表循环
with_nested 嵌套循环
with_dict 循环字典
with_fileglob 循环指定目录中的所有文件
with_lines 循环一个文件中的所有行
with_sequence 生成一个自增的整数序列,可以指定起始值和结束值以及步长。参数以key=value的形式指定,format指定输出的格式。数字可以是十进制、十六进制、八进制
with_subelement 遍历子元素
with_together 遍历数据并行集合

with_items:

1
2
3
4
5
tasks:
  - name: "with_items"
    debug:
      msg: " item "
    with_items: " data "

with_nested

1
2
3
4
5
6
7
tasks:
  - name: debug loops
    debug: msg="name is  item[0]   vaule is  item[1]  num is  item[2] "
    with_nested:
      - ['alice','bob']
      - ['a','b','c']
      - ['1','2','3']

with_dict

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 假如有如下变量内容:
users:
  alice:
    name: Alice Appleworth
    telephone: 123-456-7890
  bob:
    name: Bob Bananarama
    telephone: 987-654-3210

# 现在需要输出每个用户的用户名和手机号:
tasks:
  - name: Print phone records
    debug: msg="User  item.key  is  item.value.name  ( item.value.telephone )"
    with_dict: " users "

with_fileglob

1
2
3
4
5
6
7
8
9
- name: Upload public keys
  copy:
    src: " item "
    dest: /root/.sshkeys
    mode: 0600
    owner: root
    group: root
  with_fileglob:
    - /root/.ssh/*.pub

with_lines

with_lines循环结构会让你在控制主机上执行任意命令,并对命令的输出进行逐行迭代。假设我们有一个 文件test.txt包含如下行:

1
2
3
4
- name: print all names
  debug: msg=" item "
  with_lines:
    - cat test.txt

判断的一些用法:

when:

使用 when 时,变量名不需要双大括号

1
2
3
4
tasks:
  - name: "shut down Debian flavored systems"
    command: /sbin/shutdown -t now
    when: ansible_facts['os_family'] == "Debian"
1
2
3
4
5
6
7
8
9
10
11
==  :比较两个对象是否相等,相等为真
!=  :比较两个对象是否不等,不等为真
>   :比较两个值的大小,如果左边的值大于右边的值,则为真
<   :比较两个值的大小,如果左边的值小于右边的值,则为真
>=  :比较两个值的大小,如果左边的值大于右边的值或左右相等,则为真
<=  :比较两个值的大小,如果左边的值小于右边的值或左右相等,则为真
and :逻辑与,当左边与右边同时为真,则返回真  and 也可以使用列表表示
    - xxx == 111
    - aaa == 123
or  :逻辑或,当左边与右边有任意一个为真,则返回真
not :取反,对一个操作体取反

判断变量的 tests

1
2
3
defined :判断变量是否已经定义,已经定义则返回真
undefind :判断变量是否已经定义,未定义则返回真
none :判断变量值是否为空,如果变量已经定义,但是变量值为空,则返回真

判断执行结果的 tests

1
2
3
4
success 或 succeeded:通过任务的返回信息判断任务的执行状态,任务执行成功则返回真
failure 或 failed:通过任务的返回信息判断任务的执行状态,任务执行失败则返回真
change 或 changed:通过任务的返回信息判断任务的执行状态,任务执行状态为changed则返回真
skip 或 skipped:通过任务的返回信息判断任务的执行状态,当任务没有满足条件,而被跳过执行时,则返回真

判断路径的 tests

1
2
3
4
5
6
注:如下tests的判断均针对于ansible主机中的路径,与目标主机无关
file : 判断路径是否是一个文件,如果路径是一个文件则返回真
directory :判断路径是否是一个目录,如果路径是一个目录则返回真
link :判断路径是否是一个软链接,如果路径是一个软链接则返回真
mount:判断路径是否是一个挂载点,如果路径是一个挂载点则返回真
exists:判断路径是否存在,如果路径存在则返回真

block 用于分组任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
tasks:
   - name: Install, configure, and start Apache
     block:
     - name: install httpd and memcached
       yum:
         name: " item "
         state: present
       loop:
         - httpd
         - memcached
     - name: apply the foo config template
       template:
         src: templates/src.j2
         dest: /etc/foo.conf
     - name: start service bar and enable it
       service:
         name: bar
         state: started
         enabled: True
     when: ansible_facts['distribution'] == 'CentOS'
     become: true
     become_user: root
     ignore_errors: yes

block 用于错误处理

除了 block 关键字,还有另外一个关键字 rescue,rescue 关键字与 block 关键字同级,rescue 的字面意思为”救援”,表示当 block 中的任务执行失败时,会执行 rescue 中的任务进行补救,这将“恢复”运行任务的失败状态,并且 playbook 将继续,就像它已成功一样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 tasks:
 - name: Handle the error
   block:
     - debug:
         msg: 'I execute normally'
     - name: i force a failure
       command: /bin/false
     - debug:
         msg: 'I never execute, due to the above task failing, :-('
   rescue:
     - debug:
         msg: 'I caught an error, can do stuff here to fix it, :-)'
   always:
     - debug:
         msg: "This always executes, :-)"

内置变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1.gourps和group_names

groups是一个全局变量,它会打印出Inventory文件里面的所有主机以及主机组信息,它返回的是一个JSON字符串,我们可以直接把它当作一个变量,
使用 groups 格式调用。当然也可以使用 groups['all'] 引用其中一个的数据。变量会打印当前主机所在的groups名称,
如果没有定义会返回ungrouped,它返回的组名是一个list列表。

2.hostvars

hostvars是用来调用指定的主机变量,需要传入主机信息,返回结果也是一个JSON字符串,同样,也可以直接引用JSON字符串内的指定信息。

3.inventory_hostname和inventory_hostname_short

inventory_hostname返回的是Inventory文件里面定义的主机名,inventory_hostname_short返回的是Inventory文件里面定义的主机名的第一部分。

4.play_hosts和inventory_dir

play_hosts变量时用来返回当前playbook运行的主机信息,返回格式是主机list结构,inventory_dir变量时返回当前playbook使用的Inventory目录。