1一、基本部署

安装 Ansible

# yum -y install epel-release
# yum list all *ansible*
# yum info ansible
# yum -y install ansible

Ansible 配置文件

/etc/ansible/ansible.cfg 主配置文件
/etc/ansible/hosts Inventory
/usr/bin/ansible-doc 帮助文件
/usr/bin/ansible-playbook 指定运行任务文件

定义库存

# cd /etc/ansible/
# cp hosts{,.bak}
# > hosts
# cat hosts
[webserver]
127.0.0.1
192.168.10.149
[dbserver]
192.168.10.113

使用秘钥连接方式

# ssh-keygen -t rsa
# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.10.149
# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.10.113
# ssh-copy-id -i /root/.ssh/id_rsa.pub root@127.0.0.1

使用帮助

# ansible-doc -l 列出ansible所有的模块
# ansible-doc -s MODULE_NAME 查看指定模块具体适用

Ansible 命令应用基础

语法:ansible
[-f forks] [-m module_name] [-a args]
这次命令对哪些主机生效的
inventory group name
ip
all
-f forks 一次处理多少个主机
-m module_name 要使用的模块
-a args 模块特有的参数
# ansible 192.168.10.113 -m command -a 'date'
# ansible webserver -m command -a 'date'
# ansible all -m command -a 'date'

2二、常见模块

command 命令模块(默认模块)用于在远程主机执行命令;不能使用变量,管道等
# ansible all -a 'date'

cron 计划任务
month 指定月份
minute 指定分钟
job 指定任务
day 表示那一天
hour 指定小时
weekday 表示周几
state 表示是添加还是删除
present:安装
absent:移除
# ansible webserver -m cron -a 'minute="*/10" job="/bin/echo hello" name="test cron job"' #不写默认都是*,每个任务都必须有一个名字
# ansible webserver -a 'crontab -l'
# ansible webserver -m cron -a 'minute="*/10" job="/bin/echo hello" name="test cron job" state=absent' #移除任务

user 用户账号管理
name 用户名
uid uid
state 状态
group 属于哪个组
groups 附加组
home 家目录
createhome 是否创建家目录
comment 注释信息
system 是否是系统用户
# ansible all -m user -a 'name="user1"'
# ansible all -m user -a 'name="user1" state=absent'

group 组管理
gid gid
name 组名
state 状态
system 是否是系统组
# ansible webserver -m group -a 'name=mysql gid=306 system=yes'
# ansible webserver -m user -a 'name=mysql uid=306 system=yes group=mysql'

copy 复制文件(复制本地文件到远程主机的指定位置)
src 定义本地源文件路径
dest 定义远程目录文件路径(绝对路径)
owner 属主
group 属组
mode 权限
content 取代src=,表示直接用此处的信息生成为文件内容
# yum -y install libselinux-python
# ansible all -m copy -a 'src=/etc/fstab dest=/tmp/fstab.ansible owner=root mode=640'
# ansible all -m copy -a 'content="hello ansible
Hi ansible" dest=/tmp/test.ansible'

file 设置文件的属性
path|dest|name 对那个文件做设定
创建文件的符号链接:
src: 指定源文件
path: 指明符号链接文件路径
# ansible all -m file -a 'owner=mysql group=mysql mode=644 path=/tmp/fstab.ansible'
# ansible all -m file -a 'path=/tmp/fstab.link src=/tmp/fstab.ansible state=link'

ping 测试指定主机是否能连接
# ansible all -m ping

service 管理服务运行状态
enabled 是否开机自动启动
name 指定服务名
state 指定服务状态
started 启动服务
stoped 停止服务
restarted 重启服务
arguments 服务的参数
# ansible webserver -m service -a 'enabled=true name=httpd state=started'

shell 在远程主机上运行命令
尤其是用到管道变量等功能的复杂命令
# ansible all -m shell -a 'echo devopsman | passwd --stdin user1'

script 将本地脚本复制到远程主机并运行之
# ansible all -m script -a '/tmp/test.sh'

yum 安装程序包
name 程序包名称(不指定版本就安装最新的版本latest)
state present,latest表示安装,absent表示卸载
# ansible webserver -m yum -a 'name=httpd'
# ansible all -m yum -a 'name=ntpdate' #默认就是安装
# ansible all -m yum -a 'name=ntpdate state=absent'

setup 收集远程主机的facts
每个被管理节点在接受并运行管理命令之前,会将自己主机相关信息,如操作系统版本,IP地址等报告给远程的ansible主机
# ansible all -m setup

3三、Ansible剧本

  • 组成结构:
  • inventory #以下操作应用的主机
    modules #调用哪些模块做什么样的操作
    ad hoc commands #在这些主机上运行哪些命令
    playbooks
    tasks #任务,即调用模块完成的某操作
    variable #变量
    templates #模板
    handlers #处理器,由某事件触发执行的操作
    roles #角色

4四、YAML

4.1 YAML介绍

YAML是一种同等格式的高使用数据表达顺序的。YAML了其他语言,包括:XML、C语言、Perl以及电子邮件RFC2822。ClarkEvans在2001年是第一个这种格式语言,另外 Ingy dot Net 与 Oren Ben-Kiki 也是这语言的共同设计者。

YAML Ain't Markup Language,即YAML不是XML,不过,在开发这种语言的时候,YAML的英文其实是:“Yet Another Markup Language”(仍然是标记语言),其特性:

  • YAML 的性质好
  • YAML和脚本语言的性好
  • YAML 使用语言实现的数据类型
  • YAML有一个一致的信息模型
  • YAML 容易实现
  • YAML 可以基于流来处理
  • YAML 表达能力强,扩展性好
更多内容及规范见[1]

4.2 YAML 语法

YAML的语法和其他高阶语言类似,并且可以简单的量表、散列表、标号等数据结构,其结构(结构)通过空格来展示,序列(序列)里的用“-”来表示,映射里面的键值对用":"分割,下面是一个例子。

name: john smith
age: 41
gender: male
spouse:
name:jane smith
age:37
gender: female
children:
- name:jimmy smith
age:17
gender: male
- name:jenny smith
age: 13
gender: female

YAML文件扩展名通常为.yaml,如example.yaml

4.2.1 清单

列表的所有元素均使用“-”打头,例如:

# A list of testy fruits
- Apple
- Orange
- Strawberry
- Mango

4.2.2 字典

搜索通过key与value进行标识,例如:

---
# An employee record
name: Example Developer
job: Developer
skill: Elite

也可以将key:value置于{}中进行表示,例如:

---
#An exmloyee record
{name: Example Developer, job: Developer, skill: Elite}

5五、Ansible基础元素

5.1 变量

5.1.1 变量命名

变量名能由字符组成、数字和下划线,且仅以字符。

5.1.2 事实

事实是由正在通信的远程目标主机发送回的信息,这些信息被保存在可操作的变量中。要获取指定的远程主机所支持的所有事实,可以使用以下命令进行:

#ansible hostname -m setup

5.1.3 注册

把任务的输出定义为变量,然后其他任务,实例化如下:

tasks:
- shell: /usr/bin/foo
register: foo_result
ignore_errors: True

5.1.4 穿越任务传递

在运行 playbook 的时候也可以传递一些变量供 playbook 使用,示例如下:

#ansible-playbook test.yml --extra-vars "hosts=www user=devopsman"

5.1.5 通过角色传递变量

当给一个主机应用这些角色的时候可以传递变量,然后在角色的内部使用变量,示例如下:

- hosts: webserver
roles:
- common
- {role: foo_app_instance, dir: '/web/htdocs/a.com', port: 8080}

5.2 库存

可用的主要用在列表中的操作,用于使用的部分主机,目录文件中将其分类,定义目录文件为/etc/ansible/host

库存文件可以有多个,并且也可以通过动态库存来动态生成。

5.2.1 库存文件格式

盘点文件遵循INI文件风格,中当用不同的字符为组名。可以将同一个主机同时归到的组中;另外,如果使用目标主机名之后,还非默认的SSH端口,可以在主机上的多个名称使用冒号加端口号来表示。

ntp.devopsman.cn
[webserver]
www1.devopsman.cn:2222
www2.devopsman.cn
[dbserver]
db1.devopsman.cn
db2.devopsman.cn
db3.devopsman.cn
如果主机名遵循相似的命名模式,还可使用列表的方式标识个主机,例如:
[webserver]
www[01:50].example.com
[databases]
db-[a:f].example.com

5.2.2 主机变量

可以在清单中定义主机时自定义主机以便在剧本中使用,:

[webserver]
www1.devopsman.cn http_port=80 maxRequestsPerChild=808
www2.devopsman.cn http_port=8080 maxRequestsPerChild=909

5.2.3 组变量

例如:

[webserver]
www1.devopsman.cn
www2.devopsman.cn
[webserver:vars]
ntp_server=ntp.devopsman.cn
nfs_server=nfs.devopsman.cn

2.4 丙组 5.

inventory中,组还可以包含其他的组,并且也可以向组中的主机指定。不过,这些只能在ansible-playbook中使用变量,而ansible不支持。

[apache]
httpd1.devopsman.cn
httpd2.devopsman.cn
[nginx]
ngx1.devopsman.cn
ngx2.devopsman.cn
[webserver:children] #固定格式
apache
nginx
[webserver:vars]
ntp_server=ntp.devopsman.cn

5.2.5 库存参数

ansible基于ssh连接库存的远程主机时,还可以通过指定其指定参数的方式,这些参数显示如下:

ansible_ssh_host
ansible_ssh_port
ansible_ssh_user
ansible_ssh_pass
ansible_sudo_pass
ansible_connection
ansible_ssh_private_key_file
ansible_shell_type
ansible_python_interpreter

5.3 条件测试

需要根据变量或任务的执行结果来为某项任务执行与否的操作、执行到条件测试。

5.3.1 当语句

在任务后添加when字句可以使用条件测试;当语句支持jinja2表达式语句时,例如:

tasks:
- name: 'shutdown debian flavored system"
command: /sbin/shutdown -h now
when: ansible_os_family == "Debian"

当语句中还可以使用 jinja2 的大部分“过滤器”时,如果可能出现某种结果的错误并基于后面指定的语句,可以使用 jinja2 的语句;

tasks:
- command:/bin/false
register: result
ignore_errors: True
- command: /bin/something
when: result|failed
- command: /bin/something_else
when: result|success
- command: /bin/still/something_else
when: result|skipped

此外,当语句中还可以使用facts或playbook中定义的变量

# cat cond.yml
- hosts: all
remote_user: root
vars:
- username: user10
tasks:
- name: create {{ username }} user
user: name={{ username }}
when: ansible_fqdn == "node1.exercise.com"

5.4 重复

当有需要重复性的时候,可以使用重复性的时候,可以重复使用。举例来说,需要将其职责的内容,定义为项目的内容,定义为项目语句来引用通过使用的内容可以灵活地执行。

- name: add server user
user: name={{ item }} state=persent groups=wheel
with_items:
- testuser1
- testuser2

这个语句的功能于下面的语句:

- name: add user testuser1
user: name=testuser1 state=present group=wheel
- name: add user testuser2
user: name=testuser2 state=present group=wheel

用_items中可以,例如:

- name: add several users
user: name={{ item.name}} state=present groups={{ item.groups }}
with_items:
- { name: 'testuser1', groups: 'wheel'}
- { name: 'testuser2', groups: 'root'}

6六、模板示例:

# grep '{{' conf/httpd.conf
MaxClients {{ maxClients }}
Listen {{ httpd_port }}
# cat /etc/ansible/hosts
[webserver]
127.0.0.1 httpd_port=80 maxClients=100
192.168.10.149 httpd_port=8080 maxClients=200
# cat apache.yml
- hosts: webserver
remote_user: root
vars:
- package: httpd
- service: httpd
tasks:
- name: install httpd package
yum: name={{ package }} state=latest
- name: install configuration file for httpd
template: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify:
- restart httpd
- name: start httpd service
service: enabled=true name={{ service }} state=started
handlers:
- name: restart httpd
service: name=httpd state=restarted

7七、Ansible剧本

剧本由一个或多个“组成”组成。剧本是由一个或多个“任务列表”组成的。剧本是主要由一个或多个“任务列表”组成的。剧本是由一个或多个任务定义的。 ansible 的一个模块。将播放组织在一个播放簿中,即可以让他们按照某个编排的机制同一个单一的大戏。下面是一个示例。

- hosts: webserver
vars:
http_port: 80
max_clients: 256
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum: name=httpd state=latest
- name: ensure apache is running
service: name=httpd state=started
handlers:
- name: restart apache
service: name=httpd state=restarted

7.1 剧本基础组件

7.1.1 主机和用户

剧本中的每一个任务都是为了让一个或一个主持人执行。 ;remote_user 用于指定远程主机的执行任务组的用户,如上面的实例中的

- hosts: webserver
remote_user: root

用于,remote_user 可以在各个任务中使用,也可以通过指定其通过 sudo 的方式进行上任务,也可以用户在远程执行其任务;不过,甚至可以在 sudo_user 指定时使用 sudo_user 在主机上切换的使用。

- hosts: webserver
remote_user: devopsman
tasks:
- name: test connection
ping:
remote_user: devopsman
sudo: yes

7.1.2 任务列表和动作

播放的主题部分列表。任务列表每个任务中逐个依次执行。是在指定的每个任务中逐个执行上,即在主机上完成第一个任务在所有任务中自上而下的第二个开始剧本,如果中途发生错误,所有已执行的任务都可能回滚,在更正剧本之后再重新执行一次时即可。

任务的目的是使用指定的参数执行模块,而在模块参数中可以使用。

任务都应该有它的名字,用于剧本的执行结果输出,建议其内容的清晰地描述任务的执行步骤,如果为名字提供,则将输出用于。

定义任务可以使用“:动作选项”或“模块选项”:推荐使用前面的模块选项“或”模块:推荐使用前面以返回格式的首选项。如果动作一行的内容过多,也中使用在行使用空白处进行换行。

tasks:
- name:make sure apache is running
service: name=httpd state=started
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true

在的模块中,只有command和shell模块需要给定一个列表而单独使用“key=value”格式,例如:

tasks:
- name: disable selinux
command: /sbin/setenforce 0

如果命令或脚本的退出代码,可以使用其他替代方式或者使用ignore_errors来加载错误信息:

tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: True

7.1.3 处理程序

用于当关注的资源发生变化时发生一定的变化。

“通知”这个动作可用于每个播放的最后被触发,这样可以避免有变化发生在每次执行执行的操作,取而代之,仅在所有的变化发生完成后执行指定操作,在notify操作中的操作中,也就是调用handlers中定义的notify。

- name: template configuration file
template: src=template.j2 dest=/etc/foo.conf
notify:
- restart memcached
- restart apache

这些处理程序是多种任务与列表任务,并没有重复上的不同任务。

handlers:
- name: restart memcached
service: name=memcached state=restarted
- name: restart apache
service: name=apache state=restarted

简单的例子1:

# cat nginx.yml
- hosts: webserver
remote_user: root
tasks:
- name: create nginxn group
group: name=nginx system=yes gid=208
- name: create nginx user
user: name=nginx uid=208 group=nginx system=yes
- hosts: dbserver
remote_user: root
tasks:
- name: copy file to dbserver
copy: src=/etc/inittab dest=/tmp/inittab.ans
# ansible-playbook nginx.yml

简单的例子2:

# cat apache.yml
- hosts: webserver
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd state=latest
- name: install configuration file for httpd
copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
- name: start httpd service
service: enabled=true name=httpd state=started
# ansible-playbook apache.yml

处理程序示例:

# cat apache.yml
- hosts: webserver
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd state=latest
- name: install configuration file for httpd
copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify:
- restart httpd
- name: start httpd service
service: enabled=true name=httpd state=started
handlers:
- name: restart httpd
service: name=httpd state=restarted
# ansible-playbook apache.yml

变量示例1:

# cat apache.yml
- hosts: webserver
remote_user: root
vars:
- package: httpd
- service: httpd
tasks:
- name: install httpd package
yum: name={{ package }} state=latest
- name: install configuration file for httpd
copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify:
- restart httpd
- name: start httpd service
service: enabled=true name={{ service }} state=started
handlers:
- name: restart httpd
service: name=httpd state=restarted

变量示例 2:(在剧本中可以使用所有的变量)

# cat facts.yml
- hosts: webserver
remote_user: root
tasks:
- name: copy file
copy: content="{{ ansible_all_ipv4_addresses }} " dest=/tmp/vars.ans

8八、角色

ansible自1.2.2引入角色的能力,功能性、角色的新地组织playbook。根据层次结构自动复制角色文件只需要版本、任务和handlers等。要使用角色在playbook中使用指令包括辅助功能。角色就是通过将变量、文件、用于、模板以及设置在单独的目录中,并且可以简单地任务,并且可以将他们的一种机制包括在内。也可以使用于制造过程中的场景中

一个角色的案例如下所示:

site.yml
webserver.yml
fooserver.yml
roles/
common/
files/
templates/
tasks/
handlers/
vars/
meta/
webserver/
files/
templates/
tasks/
handlers/
vars/
meta/

而在剧本中,可以这样使用角色:

- hosts: webserver
roles:
- common
- webserver

也可以向角色传递参数,例如:

- hosts: webserver
roles:
- common
- { role: foo_app_instance, dir:'/opt/a',port:5000}
- { role: foo_app_instance, dir:'/opt/b',port:5001}

甚至也可以在条件式地使用角色,例如:

- hosts:webserver
roles:
- { role: some_role, when: "ansible_so_family == 'RedHat" }

8.1 创建角色的步骤

  1. 创建以角色命名的目录:
  2. 在角色目录中分别创建以各个角色命名的目录,如webserver等
  3. 在每个角色命名的中分别创建files、handlers、meta、tasks、templates和vars目录;用不到的目录可以创建为空目录,也可以不创建
  4. 在playbook文件中,调用各个角色

8.2 角色内各目录中可应用的文件

  • task目录:应该包含一个其他为main.yml的文件,其定义了这个角色的任务列表;这个文件可以使用包含至少包含在这个目录中的任务文件;
  • 文件目录:由复制文件或脚本等模板块引用的;
  • 模板目录:模板模块会自动在此目录中寻找jinja2模板文件;
  • handlers目录:这个目录应该包含一个main.文件,用于定义这个目录中包含的所有handlers中使用的handlers文件,也应该包含在这个handlers文件中;
  • var 目录包含一个 main.yml 文件,用于定义这个角色的内容:
  • 元目录:应该包含一个main.yml文件,定义用于此角色的特殊设置和依赖关系;ansible1.3以后的才支持;
  • 默认目录:应该包含一个main.yml文件,用于当前角色设置默认变量时使用此目录;
# mkdir -pv ansible_playbooks/roles/{webserver,dbserver}/{tasks,files,templates,meta,handlers,vars}
# cp /etc/httpd/conf/httpd.conf files/
# pwd
/root/ansible_playbooks/roles/webserver
# cat tasks/main.yml
- name: install httpd package
yum: name=httpd state=present
- name: install configuretion file
copy: src=httpd.conf dest=/etc/httpd/conf/httpd.conf
tags:
- conf
notify:
- restart httpd
- name: start httpd
service: name=httpd state=started
# cat handlers/main.yml
- name: restart httpd
service: name=httpd state=restarted
# pwd;ls
/root/ansible_playbooks
roles site.yml
# cat site.yml
- hosts: webserver
remote_user: root
roles:
- webserver
# ansible-playbook site.yml

9九、标签

标签让用户选择运行或跳过playbook中的部分。ansible具有等性的代码,会自动跳过没有代码变化的部分,因此,有些为测试其确实发生变化的时间仍然会非常的长。这时,如果你没有变化,就可以通过标签跳过这些代码片段。

标签:在playbook可以为某个任务或任务定义为一个“标签”,在执行这个playbook时,通过仅使用ansible-playbook--tags选项可以实现运行指定的任务而不是所有的;

# cat apache.yml
- hosts: webserver
remote_user: root
vars:
- package: httpd
- service: httpd
tasks:
- name: install httpd package
yum: name={{ package }} state=latest
- name: install configuration file for httpd
template: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
tags:
- conf
notify:
- restart httpd
- name: start httpd service
service: enabled=true name={{ service }} state=started
handlers:
- name: restart httpd
service: name=httpd state=restarted
# ansible-playbook apache.yml --tags='conf'

来源:https://my.oschina.net/kangvcar/blog/1830155