将下来介绍Ansible playbooks的相关知识,之前你已经在本地安装了ansible,现在就是如何编写脚本让ansible发挥作用。

playbook语言介绍

playbook作为ansible独有的术语,是ansible配置部署的编排语言框架,本身简单易读的语法结构以及丰富的内嵌模块非常易于我们编写远程系统部署策略,playbook基础的文件格式为yaml格式,可以将playbook称之为总的乐谱,每一个yaml文件可以称为一个playbook的乐章,在这个playbook下可以编写一个或多个task作为这个乐章的音符。我们通过ansible相关的命令去play演奏这个乐谱,就可以将我们预先写好的任务,按照特定的编排部署到远程服务器当中,也就是演奏给我们的听众听。

接下来将详细说明及通过demo演示的方式,向大家介绍一个基础playbooks的框架格式与编写规范。这里通过引入一个Test playbooks乐谱作为一个例子,进行逐一介绍它的基础框架和格式。下面是它的总文件结构:

inventory目录、roles目录及deploy.yml文件构成了它的表层目录结构。下面就详细介绍各个目录的作用。

inventory目录下可以存放一个或多个server详细清单目录,用来保存目标部署主机的相关域名或者IP地址,以及该主机的变量参数。通常可以用具体的部署环境例如develpoy开发环境,uat单元测试环境或者production最终产品环境,用来给server清单命名,对应保存在清单的主机地址具体部署到哪个环境当中。

inventory/testenv文件,是具体清单与变量声明文件,这里是保存inventory/testenv文件,意在保存在testenv下的主机部署到testenv环境当中。

roles目录,是任务列表,保存需要部署的详细任务列表,里面可以存放一个或者多个role,通常命名为具体的add或者项目名称。

roles/testbox目录 ,是testbox详细任务,这里是将testbox作为项目名称。

roles/testbox/task目录 ,用来保存testbox任务乐章文件main.yml

roles/testbox/task/main.yml ,是testbox主任务文件。

deploy.yml文件,是一个关键性文件,用作playbook任务入口,调动roles下需要部署的项目,以及该项目下的所有任务,最终将任务部署到environment下定义的目标主机中。下面是各个目录的层级结构:

1
2
3
4
5
6
7
inventory/ 
testenv
roles/
testbox/
task/
main.yml
deploy.yml

playbooks编写规范

接下来开始介绍playbooks的编写规范,学会playbooks的编写规范有助于我们日后开展工作方便和高效。

详细目录testenv

首先介绍inventory目录下的testenv这个详细目录,它由上下两部分组成:[testservers][testservers:vars] [testservers]是一个Server组列表,用来保存一个或多个目标主机、域名或IP地址。我们这里设置了test.example.com这个域名对应目标部署服务器主机名(也就是需要部署的目标主机的域名)。[testservers:vars] 是Server组列表参数,用来定义改组下的远程主机用到的所有key/value参数键值对,作为server组的变量声明,这里设置了server_nametest.example.comuserrootoutput/root/test.txt,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[testservers]
test.example.com

[testservers:vars]
server_name=test.example.com
user=root
output=/root/test.txt
````

![](https://upload-images.jianshu.io/upload_images/8964398-2f2abb6b7cae166d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

这两部分组合到一起就构成了我们testenv环境下的server清单。

### 主任务文件main.yml

主任务文件`main.yml`存在于`roles/testbox/task`目录下,它用来保存特定role下的需要执行的具体任务乐章,乐章会保存一个或多个task作为我们的音符,task一般由两部分组成:`任务名称`和`具体执行的任务`。其中`任务名称`用来定义task名称便于我们编写好task后,知道它是干什么用的。`具体执行的任务`通常是使用shell模块执行命令。任务执行调用ansible内嵌模块编排任务逻辑。

我们这里是让shell语句执行一句话并保存到目标目录文件下(打印主机名和用户名到远程testbox主机),`{{user}} 和{{server_name}}`引用了ansible的变量调用,将`inventory/testenv`文件里给我们目标主机定义的参数引入到当前文件中,这里user的值为root,server_name为test.example.com,output值为/root/test.txt,最终的完整语句为:

  • name: print server name and user to #任务名称
    remote testbox
    shell: “echo ‘Currently is logining ‘>“
    1
    2
    3
    4
    5
    6
    7

    ![](https://upload-images.jianshu.io/upload_images/8964398-a1a22f288b578e01.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    ### 任务入口文件deploy.yml

    `deploy.yml`作为我们的核心文件用来与`ansible-playbook`命令直接对话,将playbook下的所有编排内容展示给我们的ansible命令进行最终的play演奏,最后部署到对应的目标主机当中。

  • hosts:”testservers” # 对应于inventory/testenv文件下的[testservers]组列表,用来调用这个组列表下的目标主机,也就是需要部署的目标主机tes.texample.com
    gather_facts:true #server基本信息,用来获取目标主机下的一些基本信息
    remote_user:root #目标服务器系统用户指定,告诉ansible我们在目标主机下使用的是root用户权限进行所有的系统文件操作
    roles:
    • testbox #告诉进入roles/testbox任务目录,进行接下来的任务执行
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11

      ![](https://upload-images.jianshu.io/upload_images/8964398-5c52ece495f628e3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

      这样就介绍完了ansible playbooks的编写规范。

      ### SSH免密码秘钥认证

      由于ansible是以SSH作为通信协议,为了保证正常的通信连接,我们需要配置ansible主机与目标主机进行秘钥认证,保证ansible无需密码即可访问目标主机并进行相应的部署操作。

      第一步,使用下面的命令在ansible服务器端创建ssh本地秘钥(ssh rsa秘钥格式的本地公钥与私钥的秘钥对):

      ssh-keygen -t rsa #创建秘钥
      1
      2
      3

      第二步,使用下面的命令在ansible服务器端建立与目标部署机器的秘钥认证(将ansible服务器端的公钥传送到目标部署机器上,实现ansible服务器端可以免密码访问目标部署机器的资源,从而进行ansible playbooks的部署工作):

      ssh-copy-id -i /home/deploy/.ssh/id_rsa.pub root@test.example.com #远程推送公钥
      1
      2
      3
      4
      5

      ### 执行playbooks

      在完成SSH免密码秘钥认证之后,就可以使用ansible内建的`ansible-playbook`命令去play执行我们的test playbooks例子。可以执行下面的命令来启动playbooks:

      ansible-playbook -i inventory/testenv ./deploy.yml
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13

      其中的`inventory/testenv`这个相对路径对应testenv服务器清单下的`testservers`的值,也就是`test.example.com`服务器主机,`./deploy.yml`用来引入我们当前目录下的`deploy.yml任务入口文件`。这里已经引入了这个入口文件,就可以开启部署工作。

      ![](https://upload-images.jianshu.io/upload_images/8964398-5418c388c05c9bd3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

      至此已经介绍完了playbooks框架及其各个子文件的编写规范,接下来就开始通过demo来演示如何在我们的ansible主机下利用playbooks框架去部署我们的远程目标主机。

      ### 通过demo演示test playbook框架实例

      准备好两台虚拟机,系统均为CentOS7,一台是之前安装过ansible的虚拟机,一台是测试用的机器,我们用它来作为目标机器。

      第一步,登录ansible虚拟机主机,且换换为deploy用户,并加载之前创建的python3.6虚拟环境`.py3-a2.5-env`,并在该环境下加载我们之前安装的ansible2.5版本,使用的命令为:

      [root@localhost ~]# su - deploy #进入deploy虚拟环境
      [deploy@localhost ~]$ source /home/deploy/.py3-a2.5-env/bin/activate #加载虚拟环境
      (.py3-a2.5-env) [deploy@localhost ~]$ source /home/deploy/.py3-a2.5-env/ansible/hacking/env-setup -q #在虚拟环境下加载ansible2.5版本
      1
      2
      3

      第二步,使用`ansible-playbook --version`命令来验证ansible的加载效果:

      (.py3-a2.5-env) [deploy@localhost ~]$ ansible-playbook –version #验证ansible加载效果
      1
      2
      3

      第三步,开始演示如何编写playbooks框架。在当前目录`/home/deploy`下使用`mkdir test_playbooks`命令新建一个`test_playbooks`目录,并进入该目录,然后在该目录下创建若干个子目录,从而搭建我们当前的playbooks框架:

      (.py3-a2.5-env) [deploy@localhost test_playbooks]$ mkdir inventory
      (.py3-a2.5-env) [deploy@localhost test_playbooks]$ mkdir roles
      (.py3-a2.5-env) [deploy@localhost test_playbooks]$ cd inventory
      (.py3-a2.5-env) [deploy@localhost inventory]$ vi testenv
      1
      2
      3

      进入到testenv这个文件后,使用编辑模式往里面添加以下信息:

      [testservers]
      test.example.com

[testservers:vars]
server_name=test.example.com
user=root
output=/root/test.txt

1
2
3

保存退出后,继续执行以下命令:

(.py3-a2.5-env) [deploy@localhost inventory]$ cd ..
(.py3-a2.5-env) [deploy@localhost test_playbooks]$ ls #查看当前的文件信息 inventory roles
(.py3-a2.5-env) [deploy@localhost test_playbooks]$ cd roles
(.py3-a2.5-env) [deploy@localhost roles]$ mkdir testbox
(.py3-a2.5-env) [deploy@localhost roles]$ cd testbox/
(.py3-a2.5-env) [deploy@localhost testbox]$ mkdir tasks
(.py3-a2.5-env) [deploy@localhost testbox]$ cd tasks/
(.py3-a2.5-env) [deploy@localhost tasks]$ vi main.yml

1
2
3

进入到`main.yml`这个文件后,使用编辑模式往里面添加以下信息(注意冒号后面都有空格,且name和shell需要对齐,即距离最左边两个字符):

  • name: Print server name and user to remote testbox
    shell: “echo ‘Currently is logining ‘>“
    1
    2
    3

    保存退出后,继续执行以下命令:

    (.py3-a2.5-env) [deploy@localhost tasks]$ pwd # 查看当前的路径,/home/deploy/test_playbooks/roles/testbox/tasks
    (.py3-a2.5-env) [deploy@localhost tasks]$ cd ../../../ # 返回到test_playbooks目录下
    (.py3-a2.5-env) [deploy@localhost test_playbooks]$ pwd # 确认当前路径,/home/deploy/test_playbooks
    (.py3-a2.5-env) [deploy@localhost test_playbooks]$ vi deploy.yml
    1
    2
    3

    进入到`deploy.yml`这个文件后,使用编辑模式往里面添加以下信息(注意冒号后面都有空格,且name和shell需要对齐,即距离最左边两个字符):

  • hosts: “testservers” # -号是最左边,冒号后有个空格,定义目标主机
    gather_facts: true # 距离左端两个空格,获取目标主机的信息
    remote_user: root # 距离左端两个空格,使用root账户权限
    roles: # 距离左端两个空格
    • testbox # -号距离最左边四个空格,用于进入roles目录下的testbox任务目录进行接下来的任务执行
      1
      2
      3

      保存退出后,继续执行以下命令:

      (.py3-a2.5-env) [deploy@localhost test_playbooks]$ tree . # 查看当前目录的目录树结构
      .
      ├── deploy.yml
      ├── inventory
      │   └── testenv
      └── roles
      └── testbox
      └── tasks
        └── main.yml
      

4 directories, 3 files

1
2
3
4
5
6
7
8
9

别看命令复杂,其实就是为了创建下图所示的目录结构及文件而已:

![](https://upload-images.jianshu.io/upload_images/8964398-b15d517fdf77dc3c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

这样我们就成功创建了一个test playbooks的框架例子,但是在我们使用ansible执行这个playbook之前需要去配置ansible主机与目标主机的秘钥认证,保证ansible无需密码即可访问我们的目标主机进行相应的部署操作。

第四步,在进行SSH免密码秘钥认证之前,我们需要在ansible主机下去创建一个我们目标主机的DNS记录。这里面我们需要输入`su - root`去返回root用户,接着使用`vim /etc/hosts`命令打开hosts配置文件,在里面添加以下信息(注意前面的IP是你待部署目标机器对应的IP,不是ansible虚拟机对应的IP):

192.168.2.132 test.example.com

1
2
3

保存退出后,以deploy用户登录,并返回到该deploy目录:

(.py3-a2.5-env) [deploy@localhost ~]$

1
2
3

第五步,给depoly用户创建一个本地的SSH秘钥认证对,使用的命令为:

(.py3-a2.5-env) [deploy@localhost ~]$ ssh-keygen -t rsa # 之后一路回车即可

1
2
3
4
5
6
7

![](https://upload-images.jianshu.io/upload_images/8964398-fc9110342eb858a3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

可以看到我们的公钥(`id_rsa.pub`)和私钥(`id_rsa`)都保存在`/home/deploy/.ssh/`目录下面。

第六步,使用下面的命令去指定deploy用户的公钥和目标主机的用户名及IP:

(.py3-a2.5-env) [deploy@localhost ~]$ ssh-copy-id -i /home/deploy/.ssh/id_rsa.pub root@test.example.com

1
2
3
4
5
6
7

然后选择yes,并输入目标主机root用户的密码,当出现下面的信息,则表示你已经成功的将ansible虚拟机deploy用户的公钥已经传输给了我们目标主机root用户的ssh目录下,这样我们就成功的建立了ansible主机与目标主机之间的ssh秘钥认证。

![](https://upload-images.jianshu.io/upload_images/8964398-b9462261a6bcd1c0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

第七步,使用下面的命令来测试是否可以免密登录:

(.py3-a2.5-env) [deploy@localhost ~]$ ssh root@test.example.com # 测试免密登录
[root@localhost ~]# exit # 测试成功,退出测试主机,返回ansible主机
(.py3-a2.5-env) [deploy@localhost ~]$

1
2
3

第八步,开始执行任务。进入到`/home/deploy/test_playbooks`目录下,使用下面的命令去执行ansible playbooks 入口文件 ,从而完成我们部署到testenv环境的测试操作:

(.py3-a2.5-env) [deploy@localhost test_playbooks]$ ansible-playbook -i inventory/testenv ./deploy.yml

1
2
3
4
5

出现下面的信息,则表明任务执行完成:

![](https://upload-images.jianshu.io/upload_images/8964398-9986377eba5f4f3e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

(.py3-a2.5-env) [deploy@localhost test_playbooks]$ ansible-playbook -i inventory/testenv ./deploy.yml

PLAY [testservers]
TASK [Gathering Facts]
ok: [test.example.com]

TASK [testbox : Print server name and user to remote testbox]
changed: [test.example.com]

PLAY RECAP ***
test.example.com : ok=2 changed=1 unreachable=0 failed=0

1
2
3
4
5

可以看到一共有2个任务,执行状态都为ok,其中一个任务的状态发送了改变,`unreachable=0`表示无法达到的值为0,也就是可以直接访问到目标主机;`failed=0`表示语法结构没有任何错误。

当然你还可以使用`ssh root@test.example.com`登录到目标主机,然后使用下面的命令查看是否生成了test.txt文件,并输出test.txt文件的信息:

[root@localhost ~]# cat test.txt
Currently root is logining test.example.com

1
2
3
4
5
6
7
8
9
10
11

这样我们就在这台ansible主机下编写的test playbooks成功的将我们的测试任务部署到我们的目标主机当中,实现了将我们的乐谱通过ansible play演奏给我们的听众。

# ansible playbook常用模块

在前面介绍了ansible playbook的编写规范,以及通过一个test palybooks例子演示了如何将测试任务部署到我们的目标主机中。接下来介绍ansible playbook几个日常生活中常用的模块,并通过demo演示如何将这些模块如何运用在playbooks当中。

ansible模块是由ansible对特定部署脚本打包封装后的成品,可以利用该模块成品直接编写playbooks,这样就大大简化了日常工作中对部署脚本的编写逻辑,便于后期维护管理。模块都是由上半部分的任务命名和下半部分的任务语句构成。

**1、File模块**:用于在目标主机创建文件或目录,并赋予其系统权限。

  • name: create a file #定义任务名称
    file: ‘path=/root/foot.txt state=touch mode=0755 owner=foo group=foo’
    1
    2
    3
    4
    5
    6
    7

    `- name`用于定义任务名称为`create a file`,而后面的`file`用于声明任务语句调用的是file模块。`path=/root/foot.txt `表示我们需要在目标主机上创建`/root/foot.txt`文件的路径;`state=touch`定义我们需要创建一个文件;`mode=0755`表示我们需要给这个文件赋予0755权限;`owner=foo`表示该文件属主为foo用户,`group=foo`表示该文件文件属组为foo用户所在的foo组,这样就构成了一个file模块的ansible任务。

    ****

    **2、Copy模块**:用于实现ansible服务端到目标主机的文件传送,同样可以对目的地传送文件进行系统权限配置。

  • name: copy a file #定义任务名称
    copy: ‘remote_src=no src=roles/testbox/files/foo.sh dest=/root/foo.sh mode=0644 force=yes’
    1
    2
    3
    4
    5
    6
    7

    `- name`用于定义任务名称为`copy a file`,而后面的`copy`用于声明任务语句调用的是copy模块。`remote_src=no`用于声明将源ansible主机中的文件传输到目标主机当中;`src=roles/testbox/files/foo.sh`用于声明源文件为这个路径的文件;`dest=/root/foo.sh`用于声明源文件上传至目标主机的位置为`/root/foo.sh`;`mode=0644`表示我们需要给当前文件赋予0644权限;`force=yes`用于定义copy任务强制执行,这样就构成了一个copy模块的ansible任务。

    ***

    **3、Stat模块**:用于获取远程主机中某文件的状态信息,并将信息保存在一个环境变量下供随后使用。

  • name: check if foo.sh exists #检查这个文件是否存在在
    stat: ‘path=/root/foo.sh’ #获取远程主机/root/foo.sh文件状态信息
    register: script_stat
    1
    2
    3
    4
    5
    6
    7

    `- name`用于定义任务名称为`check if foo.sh exists`,检查这个文件是否存在在,而后面的`stat`用于声明任务语句调用的是stat模块。`path=/root/foo.sh`用于定义当前需要获取的文件路径为`/root/foo.sh`,`register: script_stat`表示将stat获取的文件信息传送给`script_stat`这个变量,从而实现从获取文件信息到给变量赋值这样一个任务操作,这样就构成了一个stat模块的ansible任务。

    ***

    **4、Debug模块**:用于打印语句到ansible执行输出,通常与stat模块和where语句配合使用,确认文件状态,也可以调用参数进行语句输出。

  • debug: msg=foo.sh exits # 定义输出内容
    when: script_stat.exists # 调用条件语句when去调用之前的script_stat变量从而判断foo.sh是否存在
    1
    2
    3
    4
    5
    6
    7

    `- debug:msg`用于定义输出内容,而后面的`when:script_stat.exists`用于调用条件语句when去调用之前的`script_stat`变量从而判断foo.sh是否存在。两个部分合在一起用来判断如果foo.sh文件存在,就在ansible执行信息里打印一条`foo.sh exits`存在的语句,不存在则不打印,这样就构成了一个debug模块的ansible任务。

    ***

    **5、command/shell模块**:用来执行Linux目标主机命令行,不过shell模块会调用Linux系统下的/bin/bash,因此可以使用系统环境变量、重定向变量符、及管道符等,但是command模块就不能使用这些shell的特定符号用法。

    command模块

  • name: run the script
    command: “sh /root/foo.sh”

shell模块

  • name: run the script
    shell: “echo ‘test’ >/root/test.txt” #可以使用重定向符(推荐)
    1
    2
    3
    4
    5
    6
    7

    shell模块可以使用重定向符,因此推荐大家使用shell模块,这样就构成了一个`command/shell`模块的ansible任务。

    ***

    **6、template模块**:用于实现ansible服务端到目标主机的jinja2模板传送。

  • name: write the nginx config file #编写一个nginx配置文件
    template: src=roles/testbox/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
    1
    2
    3
    4
    5
    6
    7

    `- name`用于定义任务名称为`write the nginx config file`(编写一个nginx配置文件),而后面的`template`用于声明任务语句调用的是template模块。`src=roles/testbox/templates/nginx.conf.j2`表示源ansible主机模板文件路径为`roles/testbox/templates/nginx.conf.j2`;`dest=/etc/nginx/nginx.conf `表示传送至目标主机路径且重命名为`/etc/nginx/nginx.conf`,注意这个nginx.conf定义的变量参数会调用playbooks server清单里的参数,生成最终的nginx.conf文件,这样就构成了一个`template`模块的ansible任务。

    ***

    **7、packaging模块**:`packaging模块`是一个广义的模块集,用于调用目标主机系统下的包管理工具(yum/apt)进行软件安装。

    CentOSs/RedHat系统

  • name: ensure nginx is at the latest version #确保nginx为最新版本
    yum: pkg=nginx state=latest # yum声明调用的语句是yum模块

Debian/Ubuntu系统

  • name: ensure nginx is at the latest version
    apt: pkg=nginx state=latest # apt声明调用的语句是apt模块
    1
    2
    3
    4
    5
    6
    7
    8
    9

    也就是说可以调用Linux发行版的包管理工具,并根据定义的安装包名称进行配置安装,常用这个模块去安装不同Linux下的http安装包。常用在centos系统下安装`nginx.rpm`格式安装包,以及在Ubuntu系统下通过apt模块下安装`nginx.deb`格式的安装包。

    `- name`用于定义任务名称为`ensure nginx is at the latest version`(确保nginx为最新版本),而后面的`yum`用于声明任务语句调用的是yum模块;`apt`用于声明任务语句调用的是apt模块。`pkg=nginx`表示要安装的为nginx安装包;`state=latest`表示设定安装的nginx为最新版本,这样就构成了一个`packaging`模块的ansible任务。

    ***

    **8、service模块**:用于管理目标主机的INIT系统服务。通常会调用主机的`service `或者`systemctl`用于管理系统服务资源的停止、启动和状态检查。

  • name: start nginx service # 启动nginx服务
    service: name=nginx state=started
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    `- name`用于定义任务名称为`start nginx service`(启动nginx服务),而后面的`service`用于声明任务语句调用的是service模块。`name=nginx`表示定义调用的服务为nginx;`state=started`表示将nginx服务做一个启动操作,这样就构成了一个`service`模块的ansible任务。注意它必须在安装完nginx以后才能进行该模块操作。

    ***

    接下来会通过前面介绍的8个常用模块,来编写一个完整的ansible playbook脚本文件,实现ansible playbook常用模块的应用。下面就是即将编写的脚本文件中的全部信息:

    ![](https://upload-images.jianshu.io/upload_images/8964398-cd6ee7ed293c476e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    ### 通过demo演示ansible playbook常用模块

    首先需要打开ansible主机和模板主机,然后在ansible主机上依次执行下面的命令:

    [root@localhost ~]# su - deploy #进入deploy虚拟环境
    [deploy@localhost ~]$ source /home/deploy/.py3-a2.5-env/bin/activate #加载虚拟环境
    (.py3-a2.5-env) [deploy@localhost ~]$ source /home/deploy/.py3-a2.5-env/ansible/hacking/env-setup -q # 在虚拟环境下加载ansible2.5版本
    (.py3-a2.5-env) [deploy@localhost ~]$ ansible-playbook –version # 验证ansible-playbook命令是否有效
    1
    2
    3

    接着登上待部署的目标机器上,进行一些模块任务需要的预配置工作,保证后面在test playbook上添加的任务能够正常推送到我们的目标主机上。

    ssh root@test.example.com # 此为待部署的目标主机

[root@localhost ~]# useradd foo #添加foo用户
[root@localhost ~]# useradd deploy #添加deploy用户
[root@localhost ~]# mkdir /etc/nginx # 创建nginx配置目录
[root@localhost ~]# rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm #安装nginx的yum源,保证后续可以使用ansible相应的模块在模板主机上安装nginx安装包
[root@localhost ~]# exit #退出待部署的目标主机

1
2
3

继续回到ansible所在的主机,依次执行下面的命令:

(.py3-a2.5-env) [deploy@localhost test_playbooks]$ pwd #确保当前目录为/home/deploy/test_playbooks
(.py3-a2.5-env) [deploy@localhost test_playbooks]$ vi roles/testbox/tasks/main.yml #打开之前的main.yml主任务,我们在其后面新增一些模块任务

1
2
3
4
5
6
7

然后可以使用shift+G按键移动到文件的最后一行的最左边,接着使用shift+数字4按键移动到最后一行的最右边,然后在底下新起一行,新建对应的任务。

****

**一个创建文件的任务。**你需要往main.yml主任务中添加以下代码:

  • name: create a file
    file: ‘path=/root/foo.txt state=touch mode=0755 owner=foo group=foo’

    1
    2
    3

    然后在`/home/deploy/test_playbooks`目录下,执行下面的命令,从而部署执行我们的create a file任务:

    (.py3-a2.5-env) [deploy@localhost test_playbooks]$ ansible-playbook -i inventory/testenv ./deploy.yml

    1
    2
    3
    4
    5
    6
    7

    当结果显示为下面的情况时,表示任务已经执行完成:

    ![](https://upload-images.jianshu.io/upload_images/8964398-85dbbb9d2bd75f47.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    其实你可以使用下面的命令进行验证(如出现下面的信息,则表示执行成功):

    (.py3-a2.5-env) [deploy@localhost test_playbooks]$ ssh root@test.example.com ls -al /root/foo.txt # 验证任务是否执行成功

  • rwxr-xr-x. 1 foo foo 0 4月 26 21:11 /root/foo.txt

    1
    2
    3
    4
    5

    ****

    **一个复制文件的任务。**接下来演示复制文件,但是前提是你ansible主机上有文件才行,因此需要新建`/home/deploy/test_playbooks/roles/testbox/files/foo.sh`文件和目录,然后`foo.sh`文件中的代码为:

    echo “this is a test script”

    1
    2
    3

    然后保存退出即可。接着使用下面的命令来打开之前的main.yml主任务:

    (.py3-a2.5-env) [deploy@localhost test_playbooks]$ vi roles/testbox/tasks/main.yml

    1
    2
    3

    我们在其后面新增copy模块任务:

  • name: copy a file
    copy: ‘remote_src=no src=roles/testbox/files/foo.sh dest=/root/foo.sh mode=0644 force=yes’

    1
    2
    3

    保存退出即可,接着在`/home/deploy/test_playbooks`目录下,执行下面的命令,从而部署执行我们的copya file任务:

    (.py3-a2.5-env) [deploy@localhost test_playbooks]$ ansible-playbook -i inventory/testenv ./deploy.yml

    1
    2
    3
    4
    5
    6
    7
    8
    9

    当结果显示为下面的情况时,表示任务已经执行完成:

    ![](https://upload-images.jianshu.io/upload_images/8964398-47e961586baf41bb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    ****

    **stat和debug模块演示。**接下来演示stat和debug模块的使用,在`roles/testbox/tasks/main.yml`主任务文件中添加以下代码:

  • name: check if foo.sh exists
    stat: ‘path=/root/foo.sh’
    register: script_stat

  • debug: msg=”foo.sh exists”
    when: script_stat.stat.exists

    1
    2
    3

    保存退出即可,接着在`/home/deploy/test_playbooks`目录下,执行下面的命令,从而部署执行我们的stat和debug模块任务:

    (.py3-a2.5-env) [deploy@localhost test_playbooks]$ ansible-playbook -i inventory/testenv ./deploy.yml

    1
    2
    3
    4
    5
    6
    7
    8
    9

    当结果显示为下面的情况时,表示任务已经执行完成:

    ![](https://upload-images.jianshu.io/upload_images/8964398-2392ea8cee8596fc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    ****

    **command/shell模块演示。**接下来演示command/shell模块的使用,在`roles/testbox/tasks/main.yml`主任务文件中添加以下代码(二选一即可):

  • name: run the script
    command: “sh /root/foo.sh”

  • name: run the script
    shell: “echo ‘test’ >/root/test.txt”

    1
    2
    3

    保存退出即可,接着在`/home/deploy/test_playbooks`目录下,执行下面的命令,从而部署执行我们的command/shell模块任务:

    (.py3-a2.5-env) [deploy@localhost test_playbooks]$ ansible-playbook -i inventory/testenv ./deploy.yml

    1
    2
    3
    4
    5
    6
    7
    8
    9

    当结果显示为下面的情况时,表示任务已经执行完成:

    ![](https://upload-images.jianshu.io/upload_images/8964398-e5ca5ebe42ea095b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    ****

    **template模块演示。**接下来演示template模块的使用。首先需要在`inventory/testenv`文件内添加一些参数,便于后续使用:

    [testservers]
    test.example.com

[testservers:vars]
server_name=test.example.com
user=root
output=/root/test.txt
port=80 # 端口号
user=deploy # 用户
worker_processes=4 # 进程数
max_open_file=65505 # 最大文件打开数量
root=/www # 设置根目录

1
2
3

接着新建`/home/deploy/test_playbooks/roles/testbox/templates/nginx.conf.j2`文件和目录,然后`nginx.conf.j2`文件中的代码为:

user ;
worker_processes ;

error_log /var/log/nginx/error.log;

pid /var/run/nginx.pid;

events {
worker_connections ;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '  
                  '$status $body_bytes_sent "$http_referer" '  
                  '"$http_user_agent" "$http_x_forwarded_for"';  

access_log  /var/log/nginx/access.log  main;  

sendfile        on;  
#tcp_nopush     on;  

#keepalive_timeout  0;  
keepalive_timeout  65;  

#gzip  on;  
  
# Load config files from the /etc/nginx/conf.d directory  
# The default server is in conf.d/default.conf  
#include /etc/nginx/conf.d/*.conf;  
server {  
    listen       {{ port }} default_server;  
    server_name  {{ server_name }};  

    #charset koi8-r;  

    #access_log  logs/host.access.log  main;  

    location / {  
        root   {{ root }};  
        index  index.html index.htm;  
    }  

    error_page  404              /404.html;  
    location = /404.html {  
        root   /usr/share/nginx/html;  
    }  

    # redirect server error pages to the static page /50x.html  
    #  
    error_page   500 502 503 504  /50x.html;  
    location = /50x.html {  
        root   /usr/share/nginx/html;  
    }  
}  

}

1
2
3

然后在`roles/testbox/tasks/main.yml`主任务文件中添加以下代码(CentOS系统下使用yum安装软件):

  • name: write the nginx config file
    template: src=roles/testbox/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
  • name: ensure nginx is at the latest version
    yum: pkg=nginx state=latest
  • name: start nginx service
    service: name=nginx state=started
    1
    2
    3

    保存退出即可,接着在`/home/deploy/test_playbooks`目录下,执行下面的命令,从而部署执行我们的command/shell模块任务:

    (.py3-a2.5-env) [deploy@localhost test_playbooks]$ ansible-playbook -i inventory/testenv ./deploy.yml
    1
    2
    3
    4
    5
    6
    7

    当结果显示为下面的情况时,表示任务已经执行完成:

    ![](https://upload-images.jianshu.io/upload_images/8964398-1591b0b2fdbb072c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    其实你可以使用下面的命令进行验证:

    (.py3-a2.5-env) [deploy@localhost test_playbooks]$ ssh root@test.example.com cat /etc/nginx/nginx.conf # 验证任务是否执行成功
    1
    2
    3

    以及查看是否启动了nginx服务:

    (.py3-a2.5-env) [deploy@localhost test_playbooks]$ ssh root@test.example.com ps -ef|grep nginx # 验证nginx是否启动成功
    1
    2
    3
    4
    5

    ### 8个常用模块的任务模板

    为了更好的查阅代码,这里附上待测试的常用模块任务,即前面你往`roles/testbox/tasks/main.yml`文件中添加的代码:

  • name: create a file
    file: ‘path=/root/foo.txt state=touch mode=0755 owner=foo group=foo’
  • name: copy a file
    copy: ‘remote_src=no src=roles/testbox/files/foo.sh dest=/root/foo.sh mode=0644 force=yes’
  • name: check if foo.sh exists
    stat: ‘path=/root/foo.sh’
    register: script_stat
  • debug: msg=”foo.sh exists”
    when: script_stat.stat.exists
  • name: run the script
    command: “sh /root/foo.sh”
  • name: run the script
    shell: “echo ‘test’ >/root/test.txt”
  • name: write the nginx config file
    template: src=roles/testbox/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
  • name: ensure nginx is at the latest version
    yum: pkg=nginx state=latest
  • name: ensure nginx is at the latest version
    apt: pkg=nginx state=latest
  • name: start nginx service
    service: name=nginx state=started
    ```