Ansible架构

  • Inventory   主机清单,可以对主机分组
  • ansible-hoc   ansible的命令,适用临时场景
  • ansible-playbook   ansible是一个场景的集合,是YAML语言
  • 被控端: 被管理的主机
  • 连接协议:ansible是用的ssh协议,所以被控端不需要安装额外的agent,这也是

ansible-galaxy

连接https://galaxy.ansible.com 下载对应的Role,相当于仓库。从仓库里拉取相关应用

让我们获取一个nginx的role

1、安装

通过Yum安装RPMs适用于 EPEL 6, 7, 以及仍在支持中的Fedora发行版.这里我们直接安装就行。

sudo yum install ansible

配置文件

  • /etc/ansible/ansible.cfg   主配置文件,配置ansible工作特性
  • /etc/ansible/hosts   主机清单
  • /etc/ansible/roles/  存放角色目录

程序

  • /usr/bin/ansible   主程序,临时命令执行工具
  • /usr/bin/ansible-doc  查看配置文档,模块文档
  • /usr/bin/ansible-galaxy  下载\上传优秀代码或role模块的官方平台
  • /usr/bin/ansible-playbook  定制自动化任务,编排剧本工具
  • /usr/bin/ansible-pull  远程执行命令工具
  • /usr/bin/ansible-vault  文件加密工具
  • /usr/bin/ansible-console  基于Console界面与用户交互的执行工具

ansible配置文件详解

  • inventory      = /etc/ansible/hosts   主机列表配置文件
  • library        = /usr/share/my_modules/   库文件存放目录
  • remote_tmp     = ~/.ansible/tmp  临时py命令文件存放在远程主机上的目录
  • local_tmp      = ~/.ansible/tmp  本机的临时命令执行目录
  • forks          = 5    默认并发数
  • sudo_user      = root   默认sudo用户
  • ask_sudo_pass = True  默认sudo用户是否需要密码
  • ask_pass      = True  每次执行ansible命令询问是否需要密码
  • remote_port    = 22   默认ssh端口
  • host_key_checking = False  检查对应主机的host_key,建议取消注释
  • logpath =/var/log/ansible.log 日志文件存放位置

ansible-doc

  • -a 列出所有模块文档(太多不建议)
  • -l  --list 列出所有模块
  • -s --snippet 显示指定模块的playbook模块

示例

  • ansible-doc -l   列出所有模块
  • ansible-doc ping   查看ping模块文档
  • ansible-doc -s  ping   查看ping模块帮助用法

ansible命令用法

ansible <host-pattern> [-m module_name] [-a args]

  • --version 查看版本
  • -m   指定模块
  • -v  详细过程 -vv -vvv更详细
  • --list-hosts  显示主机列表,可简写--list
  • -k  提示输入ssh连接密码,默认key验证
  • -K 提示输入sudo时候的口令
  • -C --check 检查,但不执行
  • -T 执行超时时间,默认10s
  • -u 指定远程执行的用户
  • -b 代替旧版本的sudo切换

ansible <host-pattern>的格式

配置主机列表

  • all 表现所有的主机: ansible all -m ping
  • * 通配符(要加引号):  ansible "*" -m ping  ansible "10.10.3.*" -m ping
  • 或关系: ansible "monserver:ceph*" -m ping
  • 与关系:ansible "monserver:&ceph*" -m ping
  • 非关系(要用‘’号): ansible 'cephserver:!monserver' -m ping

ansible-galaxy

连接https://galaxy.ansible.com下载对应的Role,相当于仓库,可以找到自己想要的应用的role。

下载一个nginx的role

$ ansible-galaxy install nginxinc.nginx
- downloading role 'nginx', owned by nginxinc
- downloading role from https://github.com/nginxinc/ansible-role-nginx/archive/0.11.0.tar.gz

列出相关的本地的role

$ ansible-galaxy list
- nginxinc.nginx, 0.11.

删除一个role

$ ansible-galaxy remove nginxinc.nginx
- successfully removed nginxinc.nginx

ansible密钥分发

这里我们需要准备两台主机,我们需要在主机A上生成秘钥

 ssh-keygen -t rsa

主机清单分组

普通分组
[monserver]
10.10.3.150
10.10.3.151
10.10.3.152
[osdserver]
10.10.3.153
10.10.3.154
10.10.3.155
嵌套分组
[cephserver]
10.10.3.15[:]

测试cephserver 主机组是否可用

ansible cephserver -m ping -k
SSH password:
10.10.3.150 | SUCCESS => {
"changed": false,
"ping": "pong"
}
10.10.3.152 | SUCCESS => {
"changed": false,
"ping": "pong"
}
10.10.3.151 | SUCCESS => {
"changed": false,
"ping": "pong"
}
10.10.3.153 | SUCCESS => {
"changed": false,
"ping": "pong"
}
10.10.3.154 | SUCCESS => {
"changed": false,
"ping": "pong"
}
10.10.3.155 | SUCCESS => {
"changed": false,
"ping": "pong"
}

分发密钥

我们怕密码不同,我们可以把密码配置到主机清单的变量里。

#方法1
[cephserver:vars]
ansible_ssh_user=root
ansible_ssh_pass=
ansible_ssh_port=
#方法2
[osdserver]
10.10.3.153 ansible_ssh_user=root ansible_ssh_pass= ansible_ssh_port=
10.10.3.154 ansible_ssh_user=root ansible_ssh_pass= ansible_ssh_port=
10.10.3.155 ansible_ssh_user=root ansible_ssh_pass= ansible_ssh_port=

这里我们用方法一,我们使用了authorized_key模块

 ansible cephserver -m  authorized_key -a "user=root key='{{lookup('file','/root/.ssh/id_rsa.pub')}}'"
10.10.3.150 | CHANGED => {
    "changed": true,
    "comment": null,
    "exclusive": false,
    "follow": false,
    "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCuimpsq0vBZHHR9ypSlQjucyliwNQUppIkimDcTYiYg9ttRf0A3foPd01nXiez8TP52csdrEDUnZsy85fugtvRatu9eWi8BWXzVm0/9m7NuCDzyOqeoBHgiPPqdOwX7Djp4D0BRiu4YqhzTTjC+dkMvxJAxVpx6eyJglfPL7fII3iL0b45F812de869rqgP6CFIkNuiZGPtxCa/ngyP/ILCmhLRSOddflE1QKviV6J7+VHPOtvI1iK0TQMI2HZolf9sj7nzzUE0lH8gH4PLh8OF6Yup8QoBvHv6Y+EN3z7ORLEji1Sv2iUClQHgwcd6CWfAgy1NNURCyl92/t8D54f root@ceph-moni-0",
    "key_options": null,
    "keyfile": "/root/.ssh/authorized_keys",
    "manage_dir": true,
    "path": null,
    "state": "present",
    "unique": false,
    "user": "root",
    "validate_certs": true
}
10.10.3.152 | CHANGED => {
    "changed": true,
    "comment": null,
    "exclusive": false,
    "follow": false,
    "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCuimpsq0vBZHHR9ypSlQjucyliwNQUppIkimDcTYiYg9ttRf0A3foPd01nXiez8TP52csdrEDUnZsy85fugtvRatu9eWi8BWXzVm0/9m7NuCDzyOqeoBHgiPPqdOwX7Djp4D0BRiu4YqhzTTjC+dkMvxJAxVpx6eyJglfPL7fII3iL0b45F812de869rqgP6CFIkNuiZGPtxCa/ngyP/ILCmhLRSOddflE1QKviV6J7+VHPOtvI1iK0TQMI2HZolf9sj7nzzUE0lH8gH4PLh8OF6Yup8QoBvHv6Y+EN3z7ORLEji1Sv2iUClQHgwcd6CWfAgy1NNURCyl92/t8D54f root@ceph-moni-0",
    "key_options": null,
    "keyfile": "/root/.ssh/authorized_keys",
    "manage_dir": true,
    "path": null,
    "state": "present",
    "unique": false,
    "user": "root",
    "validate_certs": true
}
......

authorized_key

  • - exclusive [default: no]: 是否移除 authorized_keys 文件中其它非指定 key
  • - key: SSH public key(s) 可以是字符串或 url,如:https://github.com/username.keys
  • - key_options [Default: None]: 附加到 key 中的字符串,该字符串会加到 key 的开头
  • - path [Default: (homedir)+/.ssh/authorized_keys]: 指定 authorized_keys 文件存放的位置
  • - state (Choices: present, absent) [Default: present]: present 添加指定 key 到 authorized_keys 文件中;absent 从 authorized_keys 文件中移除指定 key
  • - user: 指定修改远端服务器上哪个用户的 authorized_keys
  • - manage_dir (Choices: yes, no) [Default: yes]: 指定模块是否应该管理 authorized key 文件所在的目录。如果设置为 yes,模块会创建目录,以及设置一个已存在目录的拥有者和权限。如果通过 path 选项,重新指定了一个 authorized key 文件所在目录,那么应该将该选项设置为 no

2、远程执行命令

ansible all -m ping
172.16.138.40 | SUCCESS => {
"changed": false,
"ping": "pong"
}
172.16.138.41 | SUCCESS => {
"changed": false,
"ping": "pong"
}

我们也可以通过主机组执行命令

$ ansible webhost -m command -a  "w"
172.16.138.41 | CHANGED | rc= >>
:: up days, :, users, load average: 0.24, 0.33, 0.27
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/ 172.16.40.86 : .00s .00s .00s -bash
root pts/ k8s-master : .00s .06s .00s w 172.16.138.40 | CHANGED | rc= >>
:: up days, :, users, load average: 0.98, 0.88, 0.86
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/ 172.16.40.86 : :08m .29s .29s -bash
root pts/ 172.16.40.86 : .00s .11s .00s ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout= -o ControlPath=/root/.ansible/cp/2c6989e158 -tt 172.16.138.40 /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1553146517.04-153785974352870/AnsiballZ_command.py && sleep 0'
root pts/ k8s-master : .00s .10s .01s w
  • webhost 是指定的主机组
  • -m 是指定模块
  • -a 是执行的命令

这里还有一个shell模块。同样也支持写一个命令。

3、管理文件和目录

ansible 172.16.138.41 -m copy -a "src=/etc/ansible dest=/tmp/ansible_test owner=root group=root mode=755"
172.16.138.41 | CHANGED => {
"changed": true,
"dest": "/tmp/ansible_test/",
"src": "/etc/ansible"
}

我们看一下目标主机下/tmp目录

[root@node02 tmp]# ls
ansible_test
[root@node02 tmp]# ls ansible_test/
ansible
[root@node02 tmp]#
  • src 指定源目录
  • dest 指定目标目录

需要注意的是,如果目标主机没有这个目录会自动创建这个目录,如果拷贝是文件,目标主机指定的名字和源如果不同,并且不是已经存在的目录,相当于copy过去又重命名。但相反,如果目标主机上已经处在的目录,则会直接把文件copy到该目录下。

Fetch模块

抓取远程节点上的文件,只能复制远程单个文件,不能复制目录

$ ansible all -m fetch -a "src=/var/log/messages dest=/root/logs"
10.10.3.150 | CHANGED => {
"changed": true,
"checksum": "1e74d4714c730e75b453868a1a842e05b5e1504a",
"dest": "/root/logs/10.10.3.150/var/log/messages",
"md5sum": "32f20a6108ec6a30e5a81435b329c690",
"remote_checksum": "1e74d4714c730e75b453868a1a842e05b5e1504a",
"remote_md5sum": null
}
.....
我们用tree查看一下目录
$ tree
.
├── 10.10.3.150
│   └── var
│   └── log
│   └── messages
├── 10.10.3.151
│   └── var
│   └── log
│   └── messages
├── 10.10.3.152
│   └── var
│   └── log
│   └── messages
├── 10.10.3.153
│   └── var
│   └── log
│   └── messages
├── 10.10.3.154
│   └── var
│   └── log
│   └── messages
└── 10.10.3.155
└── var
└── log
└── messages

File模块

创建一个文件夹

ansible all -m file -a "path=/data state=directory"
10.10.3.154 | CHANGED => {
"changed": true,
"gid": ,
"group": "root",
"mode": "",
"owner": "root",
"path": "/data",
"size": ,
"state": "directory",
"uid":
}
.........

创建文件

 ansible all -m file -a "path=/data/zzk state=touch"
10.10.3.150 | CHANGED => {
"changed": true,
"dest": "/data/zzk",
"gid": ,
"group": "root",
"mode": "",
"owner": "root",
"size": ,
"state": "file",
"uid":
}
..........

删除文件

ansible all -m file -a "path=/data/zzk state=absent"
10.10.3.153 | CHANGED => {
"changed": true,
"path": "/data/zzk",
"state": "absent"
}

3、脚本管理

我们先随便写一个脚本

#!/bin/bash
date >> /tmp/data.txt

ansible需要先把脚本copy到对应主机上

$ ansible 172.16.138.41 -m copy  -a "src=/tmp/1.sh dest=/tmp/test.sh owner=root group=root mode=755"
172.16.138.41 | CHANGED => {
    "changed": true,
    "checksum": "a0d6b0777539641b9aab412a0297b1273e836bbb",
    "dest": "/tmp/test.sh",
    "gid": 0,
    "group": "root",
    "md5sum": "fc416150a5e218531c550b98e6ea35b6",
    "mode": "0755",
    "owner": "root",
    "size": 36,
    "src": "/root/.ansible/tmp/ansible-tmp-1553151731.05-254487603693246/source",
    "state": "file",
    "uid": 0
}

执行远程脚本

ansible 172.16.138.41 -m shell -a "/tmp/test.sh"
172.16.138.41 | CHANGED | rc= >>

4、管理任务计划

ansible 172.16.138.41 -m cron -a "name='test cron' job='touch /tmp/111.txt' weekday=6"
172.16.138.41 | CHANGED => {
"changed": true,
"envs": [],
"jobs": [
"test cron"
]
}
  • cron 定时任务模块
  • name 指定定时任务的名字
  • job 指定定时任务的内容
  • weekday 指定是时间计划,也可以使用*****表示

我们看一下目录主机的定时任务

$ crontab -l
#Ansible: test cron
* * * * touch /tmp/.txt

我们看到有个Ansible的表示,下面是定时任务的内容。

我们可以通过state=absent 来删除定时任务

$ ansible 172.16.138.41 -m cron -a "name='test cron' state=absent"
172.16.138.41 | CHANGED => {
"changed": true,
"envs": [],
"jobs": []
}

5、Playbook

playbook就是把一些模块的集合搞到一个文件里。play的主要功能在于将事先归为一组的主机装扮成事先通过ansible中的task定义好的角色,从根本来讲,所谓的task无非是调用ansible的一个module。将多个play组织在一个playbook中,既可以让他们连通起来按事先编排的机制同唱一台戏。

核心元素:

  • hosts  执行的主机列表
  • tasks  任务集
  • varniables  内置变量或者自定义变量在playbook中调用
  • templates  模板,可以替换模板中的变量并实现一些简单逻辑文件
  • handlers  和notity结合使用,由特定条件触发的操作,满足条件方可执行,否则不执行。
  • tags  标签  指定某条任务执行,用于选择运行playbook中的部分代码,ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常的长。此时,如果确信没有其他变化, 就可以通过tags跳过这些代码片段。

例如:

---   #表示开始
- hosts: 172.16.138.41 #指定远程主机
remote_user: root #指定远程用户
tasks: #任务
- name: test_playbook #任务名字
shell: touch /tmp/playbook.txt #具体的任务,核心

执行

ansible-playbook /etc/ansible/test.yaml

PLAY [172.16.138.41] ******************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************
ok: [172.16.138.41] TASK [test_playbook] ******************************************************************************************************************
[WARNING]: Consider using the file module with state=touch rather than running 'touch'. If you need to use command because file is
insufficient you can add 'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg to get rid of this message. changed: [172.16.138.41] PLAY RECAP ****************************************************************************************************************************
172.16.138.41 : ok= changed= unreachable= failed=

在palybook中使用file模块和user模块

---
- host: monserver
remote_user: root tasks:
- name: create new file
file: name=/data/newfile state=touch
- name: create net user
user: name=test1

这里我们使用-C参数,-C 是测试一下,不执行真正的结果

ansible-playbook -C test.yaml

PLAY [monserver] ***************************************************************************************

TASK [Gathering Facts] *********************************************************************************
ok: [10.10.3.150]
ok: [10.10.3.152]
ok: [10.10.3.151] TASK [create new file] *********************************************************************************
ok: [10.10.3.150]
ok: [10.10.3.152]
ok: [10.10.3.151] TASK [create net user] *********************************************************************************
changed: [10.10.3.150]
changed: [10.10.3.152]
changed: [10.10.3.151] PLAY RECAP *********************************************************************************************
10.10.3.150 : ok= changed= unreachable= failed=
10.10.3.151 : ok= changed= unreachable= failed=
10.10.3.152 : ok= changed= unreachable= failed=

查看playbook执行文件中有哪些主机

ansible-playbook test.yaml --list-hosts

playbook: test.yaml

  play # (monserver): monserver    TAGS: []
pattern: [u'monserver']
hosts ():
10.10.3.152
10.10.3.150
10.10.3.151

查看playbook执行文件中,有哪些任务

ansible-playbook test.yaml --list-tasks

playbook: test.yaml

  play # (monserver): monserver    TAGS: []
tasks:
create new file TAGS: []
create net user TAGS: []

在指定主机下执行

ansible-playbook test.yaml --limit 10.10.3.152

PLAY [monserver] ***************************************************************************************

TASK [Gathering Facts] *********************************************************************************
ok: [10.10.3.152] TASK [create new file] *********************************************************************************
changed: [10.10.3.152] TASK [create net user] *********************************************************************************
changed: [10.10.3.152] PLAY RECAP *********************************************************************************************
10.10.3.152 : ok= changed= unreachable= failed=

6、Playbook变量

变量的来源:

  • ansible setup facts 来和获取系统变量,举例:ansible monserver  -m  setup  过滤:ansible monserver  -m  setup  -a "filter=ansible_hostname"
  • 在/etc/ansible/hosts中定义
  1. 普通变量:主机组中主机单独定义,优先级高于公共变量
  2. 公共(组)变量:针对主机组中所有主机定义统一变量
  • 通过命令行指定变量,优先级最高。 ansible-playbook -e varname=value
  • 在playbook中定义
  • 在role中定义

我们创建一个用户。通过变量传过去

---
- name: create_user
hosts: 172.16.138.41
remote_user: root
gather_facts: false
vars:
- user: "zzkk"
tasks:
- name: create-user
user: name="{{ user }}"

执行:

ansible-playbook /etc/ansible/user.yaml

PLAY [create_user] ********************************************************************************************************************

TASK [create-user] ********************************************************************************************************************
changed: [172.16.138.41] PLAY RECAP ****************************************************************************************************************************
172.16.138.41 : ok= changed= unreachable= failed=

测试

---
- hosts: monserver
remote_user: root tasks:
- name: install httpd package
yum: name={{ pkname }}
- name: start service
service: name={{ pkname }} state=started enabled=yes

执行

ansible-playbook -e 'pkname=vsftpd' app.yaml

PLAY [monserver] ***************************************************************************************

TASK [Gathering Facts] *********************************************************************************
ok: [10.10.3.152]
ok: [10.10.3.150]
ok: [10.10.3.151] TASK [install httpd package] ***************************************************************************
changed: [10.10.3.152]
changed: [10.10.3.150]
changed: [10.10.3.151] TASK [start service] ***********************************************************************************
changed: [10.10.3.150]
changed: [10.10.3.152]
changed: [10.10.3.151] PLAY RECAP *********************************************************************************************
10.10.3.150 : ok= changed= unreachable= failed=
10.10.3.151 : ok= changed= unreachable= failed=
10.10.3.152 : ok= changed= unreachable= failed=

palybook中定义变量

---
- hosts: monserver
remote_user: root
vars:
- pkname: vsftpd tasks:
- name: install httpd package
yum: name={{ pkname }}
- name: start service
service: name={{ pkname }} state=started enabled=yes

执行

$ ansible-playbook app.yaml

PLAY [monserver] **************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************
ok: [10.10.3.152]
ok: [10.10.3.150]
ok: [10.10.3.151] TASK [install httpd package] **************************************************************************************
changed: [10.10.3.150]
changed: [10.10.3.152]
changed: [10.10.3.151] TASK [start service] **********************************************************************************************
changed: [10.10.3.150]
changed: [10.10.3.152]
changed: [10.10.3.151] PLAY RECAP ********************************************************************************************************
10.10.3.150 : ok= changed= unreachable= failed=
10.10.3.151 : ok= changed= unreachable= failed=
10.10.3.152 : ok= changed= unreachable= failed=

主机清单中定义变量

普遍变量,就是定义单个主机的变量

[monserver]
10.10.3.150 http_port=
10.10.3.151 http_port=
10.10.3.152 http_port=
---
- hosts: monserver
remote_user: root tasks:
- name: hostname
hostname: name=user{{ http_port }}

执行

ansible-playbook -C host.yaml

PLAY [monserver] **************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************
ok: [10.10.3.150]
ok: [10.10.3.152]
ok: [10.10.3.151] TASK [hostname] ***************************************************************************************************
changed: [10.10.3.150]
changed: [10.10.3.151]
changed: [10.10.3.152] PLAY RECAP ********************************************************************************************************
10.10.3.150 : ok= changed= unreachable= failed=
10.10.3.151 : ok= changed= unreachable= failed=
10.10.3.152 : ok= changed= unreachable= failed=

公共变量

[cephserver:vars]
ansible_ssh_user=root
ansible_ssh_pass=
ansible_ssh_port=

7、playbook循环

创建三个文件,并修复其权限为600

---
- hosts: 172.16.138.41
user: root
task:
- name: "touch 1 2 3 file and change file mode"
file: path=/tmp/{{ item }} state=touch mode=
with_items:
- .txt
- .txt
- .txt

执行:

ansible-playbook /etc/ansible/while.yaml

PLAY [172.16.138.41] ******************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************
ok: [172.16.138.41] TASK [touch file and change file mode] ******************************************************************************************
changed: [172.16.138.41] => (item=.txt)
changed: [172.16.138.41] => (item=.txt)
changed: [172.16.138.41] => (item=.txt) PLAY RECAP ****************************************************************************************************************************
172.16.138.41 : ok= changed= unreachable= failed=

8、playbook 条件判断

我们查看一下gather_facts收集到的信息,来作为我们判断的条件,这里我们要获取IP地址。

ansible 172.16.138.41 -m setup
....
"ansible_ens160": {
"active": true,
"device": "ens160",
....
"ipv4": {
"address": "172.16.138.41",
"broadcast": "172.16.138.255",
"netmask": "255.255.255.0",
"network": "172.16.138.0"
},
....

我们写一个判断条件 当ansible_ens160.ipv4.address = 172.16.138.41 执行创建文件

---
- hosts: webhost
user: root
gather_facts: True
tasks:
- name: stady when
shell: touch /tmp/when.txt
when: ansible_ens160.ipv4.address == "172.16.138.41"

执行结果:

ansible-playbook /etc/ansible/when.yaml

PLAY [webhost] ************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************
ok: [172.16.138.41]
ok: [172.16.138.40] TASK [stady when] *********************************************************************************************************************
skipping: [172.16.138.40]
[WARNING]: Consider using the file module with state=touch rather than running 'touch'. If you need to use command because file is
insufficient you can add 'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg to get rid of this message. changed: [172.16.138.41] PLAY RECAP ****************************************************************************************************************************
172.16.138.40 : ok= changed= unreachable= failed=
172.16.138.41 : ok= changed= unreachable= failed=

这里我们看到跳过172.16.138.40,在172.16.138.41中执行。

8、playbook Handlers

module 具有”幂等”性,所以当远端系统被人改动时,可以重放 playbooks 达到恢复的目的. playbooks 本身可以识别这种改动,并且有一个基本的 event system(事件系统),可以响应这种改动.

(当发生改动时)’notify’ actions 会在 playbook 的每一个 task 结束时被触发,而且即使有多个不同的 task 通知改动的发生, ‘notify’ actions 只会被触发一次.

举例来说,比如多个 resources 指出因为一个配置文件被改动,所以 apache 需要重新启动,但是重新启动的操作只会被执行一次.

样例:

安装http服务,并将配置文件copy到远程服务里

---
- hosts: monserver
  remote_user: root   tasks:
    - name: install httpd package
      yum: name=httpd
    - name: copy conf file
      copy: src=files/httpd.conf dest=/etc/httpd/ backup=yes
    - name: start service
      service: name=httpd state=started enabled=yes

执行:

$ ansible-playbook httpd.yaml

PLAY [monserver] ***************************************************************************************

TASK [Gathering Facts] *********************************************************************************
ok: [10.10.3.152]
ok: [10.10.3.151]
ok: [10.10.3.150] TASK [install httpd package] ***************************************************************************
changed: [10.10.3.150]
changed: [10.10.3.152]
changed: [10.10.3.151] TASK [start service] ***********************************************************************************
changed: [10.10.3.150]
changed: [10.10.3.152]
changed: [10.10.3.151] PLAY RECAP *********************************************************************************************
10.10.3.150                : ok=3    changed=2    unreachable=0    failed=0
10.10.3.151                : ok=3    changed=2    unreachable=0    failed=0
10.10.3.152                : ok=3    changed=2    unreachable=0    failed=0

确认是否安装成功

ansible monserver -m shell -a "ss -ntlp | grep :80"
10.10.3.152 | CHANGED | rc= >>
LISTEN ::: :::* users:(("httpd",pid=,fd=),("httpd",pid=,fd=),("httpd",pid=,fd=),("httpd",pid=,fd=),("httpd",pid=,fd=),("httpd",pid=,fd=)) 10.10.3.151 | CHANGED | rc= >>
LISTEN ::: :::* users:(("httpd",pid=,fd=),("httpd",pid=,fd=),("httpd",pid=,fd=),("httpd",pid=,fd=),("httpd",pid=,fd=),("httpd",pid=,fd=)) 10.10.3.150 | CHANGED | rc= >>
LISTEN ::: :::* users:(("httpd",pid=,fd=),("httpd",pid=,fd=),("httpd",pid=,fd=),("httpd",pid=,fd=),("httpd",pid=,fd=),("httpd",pid=,fd=))

这里我们将配置文件的http端口改成81

.....
# directive.
#
# Change this to Listen on specific IP addresses as shown below to
# prevent Apache from glomming onto all bound IP addresses.
#
#Listen 12.34.56.78:
Listen .....

让我们重新执行palybook,看看会发生什么

$ ansible-playbook httpd.yaml

PLAY [monserver] ***************************************************************************************

TASK [Gathering Facts] *********************************************************************************
ok: [10.10.3.150]
ok: [10.10.3.152]
ok: [10.10.3.151] TASK [install httpd package] ***************************************************************************
ok: [10.10.3.150]
ok: [10.10.3.152]
ok: [10.10.3.151] TASK [copy conf file] **********************************************************************************
changed: [10.10.3.152]
changed: [10.10.3.150]
changed: [10.10.3.151] TASK [start service] ***********************************************************************************
ok: [10.10.3.152]
ok: [10.10.3.150]
ok: [10.10.3.151] PLAY RECAP *********************************************************************************************
10.10.3.150 : ok= changed= unreachable= failed=
10.10.3.151 : ok= changed= unreachable= failed=
10.10.3.152 : ok= changed= unreachable= failed=

其实这里我们发现,任务只执行了“copy conf file”这个task,我们再坚持一下远程端口看看有没有启动81

$ ansible monserver -m shell -a "ss -ntlp | grep :81"
10.10.3.150 | FAILED | rc= >>
non-zero return code 10.10.3.152 | FAILED | rc= >>
non-zero return code 10.10.3.151 | FAILED | rc= >>
non-zero return code

我们可以看到这里报错, 没有返回对应的端口,说明就没有启动81端口,我们需要的发现配置文件发送变化,就自动重启。这里我们使用handler来实现

---
- hosts: monserver
remote_user: root tasks:
- name: install httpd package
yum: name=httpd
- name: copy conf file
copy: src=files/httpd.conf dest=/etc/httpd/ backup=yes
notify: restart service
- name: start service
service: name=httpd state=started enabled=yes handlers:
- name: restart service
service: name=httpd state=restarted

执行验证:

$ ansible-playbook httpd.yaml

PLAY [monserver] ***************************************************************************************

TASK [Gathering Facts] *********************************************************************************
ok: [10.10.3.150]
ok: [10.10.3.151] ▽
ok: [10.10.3.152] TASK [install httpd package] ***************************************************************************
ok: [10.10.3.150]
ok: [10.10.3.152]
ok: [10.10.3.151] TASK [copy conf file] **********************************************************************************
changed: [10.10.3.152]
changed: [10.10.3.150]
changed: [10.10.3.151] TASK [start service] ***********************************************************************************
ok: [10.10.3.152]
ok: [10.10.3.150]
ok: [10.10.3.151] RUNNING HANDLER [restart service] **********************************************************************
changed: [10.10.3.152]
changed: [10.10.3.150]
changed: [10.10.3.151] PLAY RECAP *********************************************************************************************
10.10.3.150 : ok= changed= unreachable= failed=
10.10.3.151 : ok= changed= unreachable= failed=
10.10.3.152 : ok= changed= unreachable= failed=0 $ ansible monserver -m shell -a "ss -ntlp | grep :81"
10.10.3.150 | CHANGED | rc=0 >>
LISTEN     0      128         :::81                      :::*                   users:(("httpd",pid=6255,fd=4),("httpd",pid=6254,fd=4),("httpd",pid=6253,fd=4),("httpd",pid=6252,fd=4),("httpd",pid=6251,fd=4),("httpd",pid=6250,fd=4)) 10.10.3.151 | CHANGED | rc=0 >>
LISTEN     0      128         :::81                      :::*                   users:(("httpd",pid=21469,fd=4),("httpd",pid=21468,fd=4),("httpd",pid=21467,fd=4),("httpd",pid=21466,fd=4),("httpd",pid=21465,fd=4),("httpd",pid=21464,fd=4)) 10.10.3.152 | CHANGED | rc=0 >>
LISTEN     0      128         :::81                      :::*                   users:(("httpd",pid=9087,fd=4),("httpd",pid=9086,fd=4),("httpd",pid=9085,fd=4),("httpd",pid=9084,fd=4),("httpd",pid=9083,fd=4),("httpd",pid=9082,fd=4))

9、template模板

  • 文本文件
  • Jinjia2语言,有下面形式:
  1. 字符串:使用单引号或者双引号
  2. 数字:整数,浮点数
  3. 列表:[item1,item2....]
  4. 元组:(item1,item2...)
  5. 字典:{key1:value1,key2:value2....}
  6. 布尔型:true/false
  • 算术运算:“+”,“-”,“*”,“/”,“//”,“%”,“**”
  • 比较操作:==,!=,>,>=,<,<=
  • 逻辑运算:and,or,not
  • 流表达式:For If When

简单使用方法:

在当前目录下创建templates目录,下负责nginx的配置文件

创建一个playbook

---
- hosts: monserver
remote_user: root tasks:
- name: install nginx
yum: name=nginx
- name: copy template
template: src=templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
- name: start nginx
service: name=nginx state=started enabled=yes

执行:

ansible-playbook  temp.yaml

PLAY [monserver] **************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************
ok: [10.10.3.150]
ok: [10.10.3.151]
ok: [10.10.3.152] TASK [install nginx] **********************************************************************************************
changed: [10.10.3.150]
changed: [10.10.3.152]
changed: [10.10.3.151] TASK [copy template] **********************************************************************************************
ok: [10.10.3.150]
ok: [10.10.3.152]
ok: [10.10.3.151] TASK [start nginx] ************************************************************************************************
changed: [10.10.3.152]
changed: [10.10.3.151]
changed: [10.10.3.150] PLAY RECAP ********************************************************************************************************
10.10.3.150 : ok= changed= unreachable= failed=
10.10.3.151 : ok= changed= unreachable= failed=
10.10.3.152 : ok= changed= unreachable= failed=

我们使用系统变量修改nginx work进程数:

获取变量的方法,我们可以使用 ansible monserver -m setup | grep "processor" 获取CPU个数

修改nginx模板文件

$ vim templates/nginx.conf.j2
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/ user nginx;
worker_processes {{ ansible_processor_vcpus** }};
error_log /var/log/nginx/error.log;
.....

修改playbook使用handlers

---
- hosts: monserver
remote_user: root tasks:
- name: install nginx
yum: name=nginx
- name: copy template
template: src=templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart nginx
- name: start nginx
service: name=nginx state=started enabled=yes handlers:
- name: restart nginx
service: name=nginx state=restarted

执行:

ansible-playbook temp.yaml

PLAY [monserver] **************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************
ok: [10.10.3.150]
ok: [10.10.3.151]
ok: [10.10.3.152] ▽ TASK [install nginx] **********************************************************************************************
ok: [10.10.3.150]
ok: [10.10.3.151]
ok: [10.10.3.152] TASK [copy template] **********************************************************************************************
changed: [10.10.3.150]
changed: [10.10.3.152]
changed: [10.10.3.151] TASK [start nginx] ************************************************************************************************
ok: [10.10.3.150]
ok: [10.10.3.152]
ok: [10.10.3.151] RUNNING HANDLER [restart nginx] ***********************************************************************************
changed: [10.10.3.150]
changed: [10.10.3.152]
changed: [10.10.3.151] PLAY RECAP ********************************************************************************************************
10.10.3.150 : ok= changed= unreachable= failed=
10.10.3.151 : ok= changed= unreachable= failed=
10.10.3.152 : ok= changed= unreachable= failed=

验证:

$ ansible monserver -m shell -a "ps -ef  | grep nginx "
10.10.3.151 | CHANGED | rc= >>
root : ? :: nginx: master process /usr/sbin/nginx
nginx : ? :: nginx: worker process
nginx : ? :: nginx: worker process
nginx : ? :: nginx: worker process
nginx : ? :: nginx: worker process
nginx : ? :: nginx: worker process
nginx : ? :: nginx: worker process
nginx : ? :: nginx: worker process
nginx : ? :: nginx: worker process
nginx : ? :: nginx: worker process
nginx : ? :: nginx: worker process
nginx : ? :: nginx: worker process
nginx : ? :: nginx: worker process
nginx : ? :: nginx: worker process
nginx : ? :: nginx: worker process
nginx : ? :: nginx: worker process
nginx : ? :: nginx: worker process
root : pts/ :: /bin/sh -c ps -ef | grep nginx
root : pts/ :: grep nginx ....

同样也可以引用主机清单、playbook等里面的变量。

when用法

when 既中文含义是“当”,当怎么怎么就怎么怎么

当hostname=ceph-osd-1的时候安装服务

---
- hosts: cephserver
remote_user: root
tasks:
- name: install nginx
when: ansible_hostname == "ceph-osd-1"
yum: name=nginx
- name: copy template
when: ansible_hostname == "ceph-osd-1"
template: src=templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart nginx
- name: start nginx
when: ansible_hostname == "ceph-osd-1"
service: name=nginx state=started enabled=yes
handlers:
- name: restart nginx
service: name=nginx state=restarted

迭代机制, with_items

---
- hosts: monserver
remote_user: root tasks:
- name: create some file
file: name=/data/{{ item }} state=touch
with_items:
- file1
- file2
- file3
- name: install spme packages
yum: name= {{ item }}
with_items:
- htop
- sl
- hping3

执行:

ansible-playbook -C testitem.yaml

PLAY [monserver] **********************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************
ok: [10.10.3.150]
ok: [10.10.3.151]
ok: [10.10.3.152] TASK [create some file] ***************************************************************************************************
ok: [10.10.3.150] => (item=file1)
ok: [10.10.3.152] => (item=file1)
ok: [10.10.3.151] => (item=file1)
ok: [10.10.3.150] => (item=file2)
ok: [10.10.3.152] => (item=file2)
ok: [10.10.3.151] => (item=file2)
ok: [10.10.3.150] => (item=file3)
ok: [10.10.3.152] => (item=file3)
ok: [10.10.3.151] => (item=file3) TASK [install spme packages] **********************************************************************************************
ok: [10.10.3.152] => (item=htop)
ok: [10.10.3.150] => (item=htop)
ok: [10.10.3.151] => (item=htop)
ok: [10.10.3.152] => (item=sl)
ok: [10.10.3.150] => (item=sl)
ok: [10.10.3.151] => (item=sl)
ok: [10.10.3.152] => (item=hping3)
ok: [10.10.3.150] => (item=hping3)
ok: [10.10.3.151] => (item=hping3) PLAY RECAP ****************************************************************************************************************
10.10.3.150 : ok= changed= unreachable= failed=
10.10.3.151 : ok= changed= unreachable= failed=
10.10.3.152 : ok= changed= unreachable= failed= [root@ceph-moni- ansible]# ansible-playbook testitem.yaml PLAY [monserver] ********************************************************************************************************** TASK [Gathering Facts] ****************************************************************************************************
ok: [10.10.3.150]
ok: [10.10.3.152]
ok: [10.10.3.151] TASK [create some file] ***************************************************************************************************
changed: [10.10.3.152] => (item=file1)
changed: [10.10.3.151] => (item=file1) ▽
changed: [10.10.3.150] => (item=file1)
changed: [10.10.3.150] => (item=file2)
changed: [10.10.3.152] => (item=file2)
changed: [10.10.3.151] => (item=file2)
changed: [10.10.3.150] => (item=file3)
changed: [10.10.3.152] => (item=file3)
changed: [10.10.3.151] => (item=file3) TASK [install spme packages] **********************************************************************************************
ok: [10.10.3.152] => (item=htop)
ok: [10.10.3.151] => (item=htop)
ok: [10.10.3.150] => (item=htop)
ok: [10.10.3.151] => (item=sl)
ok: [10.10.3.152] => (item=sl)
ok: [10.10.3.150] => (item=sl)
ok: [10.10.3.151] => (item=hping3)
ok: [10.10.3.152] => (item=hping3)
ok: [10.10.3.150] => (item=hping3) PLAY RECAP ****************************************************************************************************************
10.10.3.150 : ok= changed= unreachable= failed=
10.10.3.151 : ok= changed= unreachable= failed=
10.10.3.152 : ok= changed= unreachable= failed=

验证:

ansible  monserver  -m shell -a "ls /data"
10.10.3.150 | CHANGED | rc= >>
file1
file2
file3 10.10.3.152 | CHANGED | rc= >>
file1
file2
file3
newfile 10.10.3.151 | CHANGED | rc= >>
file1
file2
file3

迭代嵌套子变量,使用字典

---
- hosts: monserver
remote_user: root tasks:
- name: create some group
group: name={{ item }}
with_items:
- g1
- g2
- g3
- name: create some users
user: name={{ item.name }} group={{ item.group }}
with_items:
- {name: 'user1',group: 'g1'}
- {name: 'user2',group: 'g2'}
- {name: 'user3',group: 'g3'}

执行:

$ ansible-playbook testitem2.yaml

PLAY [monserver] **********************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************
ok: [10.10.3.152]
ok: [10.10.3.150]
ok: [10.10.3.151] TASK [create some group] ************************************************************************************************** ▽
changed: [10.10.3.150] => (item=g1)
changed: [10.10.3.152] => (item=g1)
changed: [10.10.3.151] => (item=g1)
changed: [10.10.3.152] => (item=g2)
changed: [10.10.3.150] => (item=g2)
changed: [10.10.3.151] => (item=g2)
changed: [10.10.3.152] => (item=g3)
changed: [10.10.3.150] => (item=g3)
changed: [10.10.3.151] => (item=g3) TASK [create some users] **************************************************************************************************
changed: [10.10.3.152] => (item={u'group': u'g1', u'name': u'user1'})
changed: [10.10.3.151] => (item={u'group': u'g1', u'name': u'user1'})
changed: [10.10.3.150] => (item={u'group': u'g1', u'name': u'user1'})
changed: [10.10.3.152] => (item={u'group': u'g2', u'name': u'user2'})
changed: [10.10.3.150] => (item={u'group': u'g2', u'name': u'user2'})
changed: [10.10.3.151] => (item={u'group': u'g2', u'name': u'user2'})
changed: [10.10.3.152] => (item={u'group': u'g3', u'name': u'user3'})
changed: [10.10.3.150] => (item={u'group': u'g3', u'name': u'user3'})
changed: [10.10.3.151] => (item={u'group': u'g3', u'name': u'user3'}) PLAY RECAP ****************************************************************************************************************
10.10.3.150 : ok= changed= unreachable= failed=
10.10.3.151 : ok= changed= unreachable= failed=
10.10.3.152 : ok= changed= unreachable= failed=

for 循环在template模板中:

我们创建一个变量字段

---
- hosts: monserver
  remote_user: root
  vars:
    ports:
      - web1:
        name: webhs1
        port: 81
        rootdir: /data/web1
      - web2:
        name: webhs2
        port: 82
        rootdir: /data/web2
      - web3:
        name: webhs3
        port: 83
        rootdir: /data/web3
  tasks:
    - name: copy conf
      template: src=for3.conf.j2 dest=/data/for1.conf

创建template模板配置文件

{% for p in ports %}
server{
listen {{ p.port }}
servername {{ p.name }}
documentroot: {{ p.rootdir }}
}
{% endfor %}

执行:

ansible-playbook  for.yaml

PLAY [monserver] **********************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************
ok: [10.10.3.152]
ok: [10.10.3.150]
ok: [10.10.3.151] TASK [copy conf] **********************************************************************************************************
changed: [10.10.3.152]
changed: [10.10.3.151]
changed: [10.10.3.150] PLAY RECAP ****************************************************************************************************************
10.10.3.150 : ok= changed= unreachable= failed=
10.10.3.151 : ok= changed= unreachable= failed=
10.10.3.152 : ok= changed= unreachable= failed=

循环嵌套if判断

需求是,如果name有定义就添加这个配置,如果没有就不添加,这里我们在前面定义的变量里注释两个name

---
- hosts: monserver
remote_user: root
vars:
ports:
- web1:
# name: webhs1
port:
rootdir: /data/web1
- web2:
# name: webhs2
port:
rootdir: /data/web2
- web3:
name: webhs3
port:
rootdir: /data/web3
tasks:
- name: copy conf
template: src=for1.conf.j2 dest=/data/for3.conf

在template中增加判断

{% for p in ports %}
server{
listen {{ p.port }}
{% if p.name is defined %}
servername {{ p.name }}
{% endif %}
documentroot: {{ p.rootdir }}
}
{% endfor %}

执行:

ansible-playbook  for1.yaml

PLAY [monserver] **********************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************
ok: [10.10.3.150]
ok: [10.10.3.152]
ok: [10.10.3.151] TASK [copy conf] **********************************************************************************************************
changed: [10.10.3.152]
changed: [10.10.3.151]
changed: [10.10.3.150] PLAY RECAP ****************************************************************************************************************
10.10.3.150 : ok= changed= unreachable= failed=
10.10.3.151 : ok= changed= unreachable= failed=
10.10.3.152 : ok= changed= unreachable= failed=

查看结果:

ansible monserver -m shell -a "cat /data/for3.conf  "
10.10.3.150 | CHANGED | rc= >>
server{
listen
documentroot: /data/web1
}
server{
listen
documentroot: /data/web2
}
server{
listen
servername webhs3
documentroot: /data/web3
}
.......

Role

用于层次性,结构化地组织playbook,roles能够根据层次型结构自动装载变量文件,tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单讲,roles就是通过将变量、文件、任务、模板及处理器放置于单独的目录里。并可以便捷的include他们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。

Role各目录作用:

  • files/ 存放由copy和script模块等调用文件
  • templates/ template模块查找所需要的模板目录
  • tasks/ 定义task,role的基本元素,至少应该包含一个名为main.yaml的文件,其他文件需要在此文件中通过include进行包含
  • handlers/ 至少包含一个名为main.yaml的文件,其他文件需要在此文件中通过include进行包含
  • vars/ 至少包含一个名为main.yaml的文件,其他文件需要在此文件中通过include进行包含
  • mete/ 定义当前角色的特殊设定及其依赖关系,至少包含一个名为main.yaml的文件,其他文件需要在此文件中通过include进行包含
  • default/ 设定默认变量时使用此目录中的main.yaml文件

需求:

通过role安装nginx,安装nginx的步骤:

  1. 创建nginx用户组,group:nginx
  2. 创建nginx用户,user:nginx
  3. yum安装nginx  yum:nginx
  4. 拷贝模板:template:nginx.conf.j2
  5. 启动服务,service:nginx

我们根据需求和上面的解释,场景对应的目录:

mkdir -p testroles/roles/nginx/{tasks,templates}

上面的1、2、3是tasks任务,所以我们会再tasks目录下一一创建

$ vim group.yaml
- name: create group
group: name=nginx
$ vim user.yaml
- name: create user
user: name=nginx group=nginx system=yes shell=/sbin/nologin
$ vim yum.yaml
- name: install package
yum: name=nginx
$ vim start.yaml
- name: start nginx
service: name=nginx state=started
$ vim restart.yaml
- name: restart nginx
service: name=nginx state=restarted
$ vim temp.yaml
- name: copy config
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf

创建配置文件模板

$ vim ../templates/nginx.conf.j2

 For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/ user nginx;
worker_processes {{ ansible_processor_vcpus** }};
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
........

这里我们的配置文件准备完成了。接下来是关键是怎么调用,这时候我们需要一个总的tasks文件(main.yaml)。

$ vim roles/nginx/tasks/main.yaml
- include: group.yaml
- include: user.yaml
- include: yum.yaml
- include: temp.yaml
- include: start.yaml

这里我们在role目录平级的目录创建一个剧本,写具体怎么调用:

$ vim nginx-role.yaml

- hosts: monserver
remote_user: root
roles:
- role: nginx

执行:

ansible-playbook -C  nginx-role.yaml

PLAY [monserver] *******************************************************************************

TASK [Gathering Facts] *************************************************************************
ok: [10.10.3.150]
ok: [10.10.3.152]
ok: [10.10.3.151] TASK [nginx : create group] ********************************************************************
changed: [10.10.3.152]
changed: [10.10.3.151]
changed: [10.10.3.150] TASK [nginx : create user] *********************************************************************
changed: [10.10.3.150]
changed: [10.10.3.152]
changed: [10.10.3.151] TASK [nginx : install package] *****************************************************************
changed: [10.10.3.151]
changed: [10.10.3.152]
changed: [10.10.3.150] TASK [nginx : copy config] *********************************************************************
changed: [10.10.3.152]
changed: [10.10.3.151]
changed: [10.10.3.150] TASK [nginx : start nginx] *********************************************************************
changed: [10.10.3.152]
changed: [10.10.3.151]
changed: [10.10.3.150] PLAY RECAP *************************************************************************************
10.10.3.150 : ok= changed= unreachable= failed=
10.10.3.151 : ok= changed= unreachable= failed=
10.10.3.152 : ok= changed= unreachable= failed= [root@ceph-moni- testroles]# ansible-playbook nginx-role.yaml PLAY [monserver] ******************************************************************************* TASK [Gathering Facts] *************************************************************************
ok: [10.10.3.150]
ok: [10.10.3.151]
ok: [10.10.3.152] TASK [nginx : create group] ********************************************************************
changed: [10.10.3.152]
changed: [10.10.3.150]
changed: [10.10.3.151] TASK [nginx : create user] *********************************************************************
changed: [10.10.3.152]
changed: [10.10.3.150]
changed: [10.10.3.151] TASK [nginx : install package] *****************************************************************
changed: [10.10.3.152]
changed: [10.10.3.150]
changed: [10.10.3.151] TASK [nginx : copy config] *********************************************************************
changed: [10.10.3.150]
changed: [10.10.3.152]
changed: [10.10.3.151] TASK [nginx : start nginx] *********************************************************************
changed: [10.10.3.152]
changed: [10.10.3.150]
changed: [10.10.3.151] PLAY RECAP *************************************************************************************
10.10.3.150 : ok= changed= unreachable= failed=
10.10.3.151 : ok= changed= unreachable= failed=
10.10.3.152 : ok= changed= unreachable= failed=

Ansible-基础的更多相关文章

  1. ansible基础-安装与配置

    一 安装 1.1 ansible架构 ansible是一个非常简单的自动化部署项目,由python编写并且开源.用于提供自动化云配置.配置文件管理.应用部署.服务编排和很多其他的IT自动化需求. an ...

  2. ansible基础-优化

    简介 当管理集群达到一定规模时,ansible达到性能瓶颈是难以避免的,此时我们可以通过一定手段提高ansible的执行效率和性能. 笔者虽未管理过超大规模服务器,但也通过查找资料和咨询大神了解了一些 ...

  3. ansible基础-Jinja2模版 | 过滤器

    Jinja2模版介绍 注:本文demo使用ansible2.7稳定版 在ansible基础-变量的「8.2 模版使用变量」章节中关于模版与变量也有所提及,有兴趣的同学可以去回顾一下. ansible通 ...

  4. ansible基础-理解篇

    1. 介绍 要说现在的部署工具,ansible可以说家喻户晓了. ansible是一个开源软件,用于软件供应.配置管理.应用部署.ansible可以通过SSH.remote PowerShell.其他 ...

  5. ansible基础-roles

    一 简介 注:本文demo使用ansible2.7稳定版 在我看来,role是task文件.变量文件.handlers文件的集合体,这个集合体的显著特点是:可移植性和可重复执行性. 实践中,通常我们以 ...

  6. ansible基础-playbooks

    1. playbooks介绍 如果说ansible的modules是工具,inventory配置文件是原材料,那么playbook就是一封说明书,这里会记录任务是如何如何执行的,当然如果你愿意,这里也 ...

  7. ansible基础-ansible角色的使用

    ansible基础-ansible角色的使用 作者:尹正杰  版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们建议把多个节点都会用到的功能将其定义模块,然后谁要用到该模块就直接调用即可!而在a ...

  8. ansible基础-playbook剧本的使用

    ansible基础-playbook剧本的使用 作者:尹正杰  版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.YAML概述 1>.YAML的诞生 YAML是一个可读性高,用来表达数据序 ...

  9. 003.Ansible基础使用

    一 Ansible命令用法 Ansible命令行执行方式有:Ad-Hoc.Ansible-playbook两种,Web方式其官方提供付费产品Tower.Ad-Hoc主要用于临时命令的执行,Ansibl ...

  10. 自动化运维工具-Ansible基础

    目录 自动化运维工具-Ansible基础 什么是Ansible 同类型软件对比 Ansible的功能及优点 Ansible的架构 Ansible的执行流程 安装Ansible ansible配置文件 ...

随机推荐

  1. 测者的测试技术手册:自动化的自动化EvoSuite:Maven项目集成EvoSuite实战

    EvoSuite是由Sheffield等大学联合开发的一种开源工具,用于自动生成测试用例集,生成的测试用例均符合Junit的标准,可直接在Junit中运行.得到了Google和Yourkit的支持. ...

  2. Python 经典面试题汇总之数据库篇

    数据库和缓存 1.列举常见的关系型数据库和非关系型都有那些? 关系型数据库(需要有表结构) mysql.oracle.splserver.postgresql.db2.sybase 非关系型数据库(是 ...

  3. linux_FTP连接失败

    service vsftpd status vim /etc/vstpd/vsfptd.conf service vsftpd restart service iptables status serv ...

  4. Python3 isdigit()方法

    描述 Python isdigit() 方法检测字符串是否只由数字组成. 语法 isdigit()方法语法: str.isdigit() 参数 无. 返回值 如果字符串只包含数字则返回 True 否则 ...

  5. 【原】Java学习笔记033 - IO

    package cn.temptation; public class Sample01 { public static void main(String[] args) { // 需求:继承关系中爷 ...

  6. mysql No query specified

    MySQL SHOW CREATE TABLE tablename \G; 会出现 ERROR: No query specified 原因 去掉分号 ; \g \G三者选其一即可.

  7. Ajax异步交互基础

    1. ajax是什么? * asynchronous javascript and xml:异步的js和xml * 它能使用js访问服务器,而且是异步访问! * 服务器给客户端的响应一般是整个页面,一 ...

  8. git stash解决代码merge出错

    最近在使用git提交代码时,遇到一个问题,就是我修改了几个文件的代码,然后又想把自己代码库里面的代码更新到最新版本,然后不出所料,代码冲突了!作为一个喜欢解决问题的程序员,怎么会被这样的问题所困住呢? ...

  9. 周一02.4变量&垃圾回收机制

    一.变量 1. 什么是变量 量:记录事物的某种状态,即事物典型的特征 变:事物的状态是可以发生变化的 2. 为何要用变量 是为了让计算机能够像人一样记录事物的状态 3. 如何用变量 (先定义后引用) ...

  10. Exception in thread "main" org.I0Itec.zkclient.exception.ZkAuthFailedException: Authentication failure is thrown while creating kafka topic

    Exception in thread "main" org.I0Itec.zkclient.exception.ZkAuthFailedException: Authentica ...