[toc]
ansible 自动化运维
运维工具
| OS Provisioning: PXE, Cobbler(repository, distritution, profile) |
| PXE: dhcp, tftp,(http,ftp) |
| dnsmsq:dhcp,dns |
| OS Config: |
| puppet, saltstack, func |
| Task Excute: |
| fabric, func,saltstack |
| Deployment: |
| fabric, |
| 运维工具分类: |
| agent: puppet, func 这些工具必需要有agent端; |
| agentless: ansible, fabirc 这些工具必需启用ssh服务; |
| Properties: |
| Minimal learning curve, auditability: 入门曲线非常平缓; |
| No bootstrapping: 无需agent; |
| No DAG ordering, Fails Fast: 没有次序; |
| No agents(other than sshd) -o resource consumption when not in use: 没有代理; |
| No Server: 也没有服务端; |
| No additional PKI : 无需证书等功能; |
| Modules in any language: 模块可以使用任意编程语言来编写; |
| YAML, not code: 使用yaml配置文件; |
| SSH by default: 使用ssh默认接口; |
| Strong multi-tier solution: 支持多级使用方案; |
| Host Inventory: |
| 定义可被 ansible管控的主机; |
| Core Modules: |
| 可被调用的核心模块,可以完成大部作的任务; |
| Custom Modules: |
| 自定义模块,当ansible实现不了时,可以使用任意编程语言来编写模块; |
| Connection Plugins: |
| ansible 可以支持一些插件来实现一些功能,如发送邮件功能; |
| ansible的核心线件: |
| ansible core |
| host iventory |
| core modules |
| custom modules |
| playbook (yaml, jinjia2) |
| connect plugin |
| ansible特性: |
| 基于Python语言实现,由Paramiko模块实现,PyYAML和Jinia2 三个关键的模块构建 |
| python特性:,agentless; |
| 默认使用SSH协议: 会有安全隐患; |
| 基于密钥认证来连接到各节点操作; |
| 主从模式: |
| master: ansible, ssh client; |
| savle: ssh server结点; |
| 支持自定义模块:支持各种编程语言; |
| 支持Playbook |
| 基于"模块"完成各种"任务"; |
ansible 的安装和使用
| # ansible 在于epel源中 |
| # yum list all *ansible* |
| ansible.noarch 2.4.2.0-2.el7 @extras |
| # 安装依赖于epel源 |
| 配置文件 /etc/ansible/ansible.cfg |
| Invertory: /etc/ansible/hosts |
| # vim /etc/ansible |
| [dbserver] |
| 172.16.55.123 |
| |
| [webserver] |
| 172.16.55.124 |
| 172.1655.125 |
| # 在ansible主机生成一组密钥 |
| # ssh-keygen |
| # 实现双机互信 |
| # for i in {3..5} ; do ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.16.55.12$i; done |
| # for i in {3..5} ; do ssh root@172.16.55.12$i "date" && echo "The Messages From 172.16.55.12$i"; done |
| 2018年 04月 09日 星期一 09:47:09 CST |
| The Messages From 172.16.55.123 |
| 2018年 04月 09日 星期一 09:47:10 CST |
| The Messages From 172.16.55.124 |
| 2018年 04月 09日 星期一 09:47:10 CST |
| The Messages From 172.16.55.125 |
| # 此时ansbile所在的服务器可以实现对各结点的控制 |
asnbile-doc 的使用
| # ansible-doc |
| # ansible-doc -l |
| # ansible-doc -s MODULE_NAME; |
| # ansible-doc -s yum |
ansible命令的应用基础
| ansible命令应用基础: |
| 语法: ansible <host-pattern> [-f forks] [-m module_name] [-a args] |
| -f forks: 启动的并发线程数; |
| -m module_name: 要使用的模块; |
| -a args: 模块特有的参数; |
常见的模块:
command: 命令模块,默认模块,用于在远程命令;
| # ansible 172.16.55.124 -m command -a "date" |
| 172.16.55.124 | SUCCESS | rc=0 >> |
| 2018年 04月 09日 星期一 09:57:39 CST |
| |
| # ansible dbserver -m command -a "date" |
| 172.16.55.123 | SUCCESS | rc=0 >> |
| 2018年 04月 09日 星期一 09:58:02 CST |
| |
| # ansible all -m command -a "date" |
| 172.16.55.124 | SUCCESS | rc=0 >> |
| 2018年 04月 09日 星期一 09:58:24 CST |
| |
| 172.16.55.123 | SUCCESS | rc=0 >> |
| 2018年 04月 09日 星期一 09:58:24 CST |
| |
| 172.16.55.125 | SUCCESS | rc=0 >> |
| 2018年 04月 09日 星期一 09:58:32 CST |
| |
| # ansible all -m command -a "tail -2 /var/log/messages" |
| 172.16.55.124 | SUCCESS | rc=0 >> |
| Apr 9 09:58:24 fabric1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=date removes=None creates=None chdir=None stdin=None |
| Apr 9 09:59:22 fabric1 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=tail -2 /var/log/messages removes=None creates=None chdir=None stdin=None |
| |
| 172.16.55.123 | SUCCESS | rc=0 >> |
| Apr 9 09:58:24 hyperledger ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=date removes=None creates=None chdir=None stdin=None |
| Apr 9 09:59:23 hyperledger ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=tail -2 /var/log/messages removes=None creates=None chdir=None stdin=None |
| |
| 172.16.55.125 | SUCCESS | rc=0 >> |
| Apr 9 09:58:31 fabric2 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=date removes=None creates=None chdir=None stdin=None |
| Apr 9 09:59:23 fabric2 ansible-command: Invoked with warn=True executable=None _uses_shell=False _raw_params=tail -2 /var/log/messages removes=None creates=None chdir=None stdin=None |
cron 模块:可以使被管理节点自动生成一生任务计划;
state所有属性:
| */10 * * * * /bin/echo "Test Message" |
| # ansible webserver -m cron -a 'minute="*/10" job="/bin/echo Test Message" name="Test Cron Job"' |
| 172.16.55.124 | SUCCESS => { |
| "changed": true, |
| "envs": [], |
| "jobs": [ |
| "Test Cron Job" |
| ] |
| } |
| 172.16.55.125 | SUCCESS => { |
| "changed": true, |
| "envs": [], |
| "jobs": [ |
| "Test Cron Job" |
| ] |
| } |
| # 执行完之后登录以上的某一台服务器进行验证 |
| # crontab -l |
| #Ansible: Test Cron Job |
| */10 * * * * /bin/echo Test Message |
| # ansible webserver -m cron -a 'minute="*/10" job="/bin/echo Test Message" name="Test Cron Job" state="absent"' |
| # 将以上建立的定时任务计划移除 |
user模块: 用于建立用户;
name=: 指明需要建立用户的用户名;
| |
| 172.16.55.124 | SUCCESS => { |
| "changed": true, |
| "comment": "", |
| "createhome": true, |
| "group": 1001, |
| "home": "/home/user1", |
| "name": "user1", |
| "shell": "/bin/bash", |
| "state": "present", |
| "system": false, |
| "uid": 1001 |
| } |
| 172.16.55.123 | SUCCESS => { |
| "changed": true, |
| "comment": "", |
| "createhome": true, |
| "group": 1001, |
| "home": "/home/user1", |
| "name": "user1", |
| "shell": "/bin/bash", |
| "state": "present", |
| "system": false, |
| "uid": 1001 |
| } |
| 172.16.55.125 | SUCCESS => { |
| "changed": true, |
| "comment": "", |
| "createhome": true, |
| "group": 1001, |
| "home": "/home/user1", |
| "name": "user1", |
| "shell": "/bin/bash", |
| "state": "present", |
| "system": false, |
| "uid": 1001 |
| } |
| |
| |
| |
| |
| |
| |
| |
| 172.16.55.123 | SUCCESS => { |
| "changed": true, |
| "comment": "", |
| "createhome": true, |
| "group": 306, |
| "home": "/home/mysqld", |
| "name": "mysqld", |
| "shell": "/bin/bash", |
| "state": "present", |
| "system": true, |
| "uid": 306 |
| } |
| 172.16.55.125 | SUCCESS => { |
| "changed": true, |
| "comment": "", |
| "createhome": true, |
| "group": 306, |
| "home": "/home/mysqld", |
| "name": "mysqld", |
| "shell": "/bin/bash", |
| "state": "present", |
| "system": true, |
| "uid": 306 |
| } |
| 172.16.55.124 | SUCCESS => { |
| "changed": true, |
| "comment": "", |
| "createhome": true, |
| "group": 306, |
| "home": "/home/mysqld", |
| "name": "mysqld", |
| "shell": "/bin/bash", |
| "state": "present", |
| "system": true, |
| "uid": 306 |
| } |
copy模块: 用于文件的远程传输;
- src=: 定义本地源文件路径;
- dest=: 定义远程目标文件路径,但不支持绝对路径;
- content=: 取代src=,表示直接用此处指定的信息生成目标文件,
但这里要注意的是,会把节点主机的源文件覆盖,类似于 echo > /path/to/file
| |
| 172.16.55.123 | SUCCESS => { |
| "changed": true, |
| "checksum": "3858e5b009a8c0828cb529780a2ad547411d8d94", |
| "dest": "/tmp/fstab.ansible", |
| "gid": 0, |
| "group": "root", |
| "md5sum": "01ea40602497b8cfe5a53743054fa04d", |
| "mode": "0640", |
| "owner": "root", |
| "size": 541, |
| "src": "/root/.ansible/tmp/ansible-tmp-1523241179.42-225211025896206/source", |
| "state": "file", |
| "uid": 0 |
| } |
| 172.16.55.125 | SUCCESS => { |
| "changed": true, |
| "checksum": "3858e5b009a8c0828cb529780a2ad547411d8d94", |
| "dest": "/tmp/fstab.ansible", |
| "gid": 0, |
| "group": "root", |
| "md5sum": "01ea40602497b8cfe5a53743054fa04d", |
| "mode": "0640", |
| "owner": "root", |
| "secontext": "unconfined_u:object_r:admin_home_t:s0", |
| "size": 541, |
| "src": "/root/.ansible/tmp/ansible-tmp-1523241179.42-108291746173038/source", |
| "state": "file", |
| "uid": 0 |
| } |
| 172.16.55.124 | SUCCESS => { |
| "changed": true, |
| "checksum": "3858e5b009a8c0828cb529780a2ad547411d8d94", |
| "dest": "/tmp/fstab.ansible", |
| "gid": 0, |
| "group": "root", |
| "md5sum": "01ea40602497b8cfe5a53743054fa04d", |
| "mode": "0640", |
| "owner": "root", |
| "size": 541, |
| "src": "/root/.ansible/tmp/ansible-tmp-1523241179.35-169240840464627/source", |
| "state": "file", |
| "uid": 0 |
| } |
| |
| 172.16.55.123 | SUCCESS => { |
| "changed": true, |
| "checksum": "06759ebeeffb1ec2ba32b71d0440258a2ec812ca", |
| "dest": "/tmp/ssjinyao", |
| "gid": 0, |
| "group": "root", |
| "md5sum": "7da4c3d419470482101fa8cfa338c882", |
| "mode": "0644", |
| "owner": "root", |
| "size": 35, |
| "src": "/root/.ansible/tmp/ansible-tmp-1523241579.59-247115936338069/source", |
| "state": "file", |
| "uid": 0 |
| } |
| 172.16.55.124 | SUCCESS => { |
| "changed": true, |
| "checksum": "06759ebeeffb1ec2ba32b71d0440258a2ec812ca", |
| "dest": "/tmp/ssjinyao", |
| "gid": 0, |
| "group": "root", |
| "md5sum": "7da4c3d419470482101fa8cfa338c882", |
| "mode": "0644", |
| "owner": "root", |
| "size": 35, |
| "src": "/root/.ansible/tmp/ansible-tmp-1523241579.53-265190945061484/source", |
| "state": "file", |
| "uid": 0 |
| } |
| 172.16.55.125 | SUCCESS => { |
| "changed": true, |
| "checksum": "06759ebeeffb1ec2ba32b71d0440258a2ec812ca", |
| "dest": "/tmp/ssjinyao", |
| "gid": 0, |
| "group": "root", |
| "md5sum": "7da4c3d419470482101fa8cfa338c882", |
| "mode": "0644", |
| "owner": "root", |
| "secontext": "unconfined_u:object_r:admin_home_t:s0", |
| "size": 35, |
| "src": "/root/.ansible/tmp/ansible-tmp-1523241579.58-230356470158720/source", |
| "state": "file", |
| "uid": 0 |
| } |
| |
| Hellow Ansible |
| Welcome to ssjinyao |
file: 用于设定文件属性;
- path=: 指定文件路径, 可以使用name 或dest来替换;
- 创建文件的符号链接;
- src=:指明源文件;
- path=: 指明符号链接文件路径;
| |
| 172.16.55.123 | SUCCESS => { |
| "changed": true, |
| "gid": 306, |
| "group": "mysql", |
| "mode": "0644", |
| "owner": "mysql", |
| "path": "/tmp/ssjinyao", |
| "size": 35, |
| "state": "file", |
| "uid": 27 |
| } |
| 172.16.55.124 | SUCCESS => { |
| "changed": true, |
| "gid": 306, |
| "group": "mysql", |
| "mode": "0644", |
| "owner": "mysql", |
| "path": "/tmp/ssjinyao", |
| "size": 35, |
| "state": "file", |
| "uid": 27 |
| } |
| 172.16.55.125 | SUCCESS => { |
| "changed": true, |
| "gid": 306, |
| "group": "mysql", |
| "mode": "0644", |
| "owner": "mysql", |
| "path": "/tmp/ssjinyao", |
| "secontext": "unconfined_u:object_r:admin_home_t:s0", |
| "size": 35, |
| "state": "file", |
| "uid": 27 |
| } |
| |
| 172.16.55.123 | SUCCESS => { |
| "changed": true, |
| "dest": "/tmp/ssjinyao.link", |
| "gid": 0, |
| "group": "root", |
| "mode": "0777", |
| "owner": "root", |
| "size": 13, |
| "src": "/tmp/172.16", |
| "state": "link", |
| "uid": 0 |
| } |
| 172.16.55.124 | SUCCESS => { |
| "changed": true, |
| "dest": "/tmp/ssjinyao.link", |
| "gid": 0, |
| "group": "root", |
| "mode": "0777", |
| "owner": "root", |
| "size": 13, |
| "src": "/tmp/ssjinyao", |
| "state": "link", |
| "uid": 0 |
| } |
| 172.16.55.125 | SUCCESS => { |
| "changed": true, |
| "dest": "/tmp/ssjinyao.link", |
| "gid": 0, |
| "group": "root", |
| "mode": "0777", |
| "owner": "root", |
| "secontext": "unconfined_u:object_r:user_tmp_t:s0", |
| "size": 13, |
| "src": "/tmp/ssjinyao", |
| "state": "link", |
| "uid": 0 |
| } |
ping: 测试远程主机的连接性;
| |
| 172.16.55.123 | SUCCESS => { |
| "changed": false, |
| "ping": "pong" |
| } |
| 172.16.55.124 | SUCCESS => { |
| "changed": false, |
| "ping": "pong" |
| } |
| 172.16.55.125 | SUCCESS => { |
| "changed": false, |
| "ping": "pong" |
| } |
service: 指定运行状态;
- enabled=: 是否开机自动启动;
- name =: 服务名称;
- state =: 状态,取值有started, stopped, restarted;
| # ansible webserver -m service -a "enabled=true name=httpd state=started" |
shell: 在远程主机运行命令;
尤其是用到管道等复杂命令
| # ansible all -m shell -a 'echo "xxxxxxxx" | passwd --stdin user1 ' |
| 172.16.55.123 | SUCCESS | rc=0 >> |
| 更改用户 user1 的密码 。 |
| passwd:所有的身份验证令牌已经成功更新。 |
| |
| 172.16.55.124 | SUCCESS | rc=0 >> |
| 更改用户 user1 的密码 。 |
| passwd:所有的身份验证令牌已经成功更新。 |
| |
| 172.16.55.125 | SUCCESS | rc=0 >> |
| 更改用户 user1 的密码 。 |
| passwd:所有的身份验证令牌已经成功更新。 |
script: 将本地脚本复制到远程主机上并运行之;
注意: 要使用相对路径指定脚本;
| # cat test.sh |
| #!/bin/bash |
| sum=0 |
| for i in {1..100}; do |
| sum=$[$sum+$i] |
| done |
| echo $sum |
| |
| # chmod +x test.sh |
| # ansible all -m script -a "/tmp/test.sh" |
| 172.16.55.123 | SUCCESS => { |
| "changed": true, |
| "rc": 0, |
| "stderr": "Shared connection to 172.16.55.123 closed.\r\n", |
| "stdout": "5050\r\n", |
| "stdout_lines": [ |
| "5050" |
| ] |
| } |
| 172.16.55.124 | SUCCESS => { |
| "changed": true, |
| "rc": 0, |
| "stderr": "Shared connection to 172.16.55.124 closed.\r\n", |
| "stdout": "5050\r\n", |
| "stdout_lines": [ |
| "5050" |
| ] |
| } |
| 172.16.55.125 | SUCCESS => { |
| "changed": true, |
| "rc": 0, |
| "stderr": "Shared connection to 172.16.55.125 closed.\r\n", |
| "stdout": "5050\r\n", |
| "stdout_lines": [ |
| "5050" |
| ] |
| } |
yum: 安装程序包;
- name=: 指明要安装的程序包,可以带上版本号;
- state=: present, latest表示安装,absent表示卸载;
| # ansible all -m yum -a 'name="zsh" state="present"' |
| # ansible all -m yum -a 'name="zsh" state="absent"' |
setup: 收集远程主机的facts;
- 每个被管理节点在接收并运行管理命令之前,会将自己主机相关信息;
- 如操作系统版本、IP地址等报告给远程的ansible主机;
ansible-playbook(剧本) 的使用
playbook的核心元素;
- taskfs:任务
- variadble: 变量
- templates: 模板
- handlers: 处理器
- roles:角色
YAML 介绍;
| YAML 是一个可读性高的用来表达资料序列的格式,YAML参考了其他多处语言; |
| 包括:XML、C语言、Python、Perl以及电子邮件格式等 |
| Clark Evans在2001年首次发表了这种语言 |
| |
| YAML Ain't Markup Language, 即YAML不是XML。不过,在开发的这种语言时; |
| YAML的意思其实是:"Yet Another Markup Language(仍是一种标记语言)。"其特性: |
| |
| YAML的可读性好 |
| YAML 和脚本语言的交互性好 |
| YAML 使用实现语言的数据类型 |
| YAML 有一个一致的信息模型 |
| YAML 易于实现 |
| YAML 可以基于流来处理 |
| YAML 表达能力强,扩展性好 |
| YAML的语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构; |
| 其结构(Structure)通过空格来展示,序列(Sequence)里的项用"-"来代表,Map里的键值用";"分隔 |
ansible变量:
| 变量命名 |
| 变量名仅能由字母、数字和下划线组成,且只能以字母开头; |
| facts |
| facts是由正在通信的远程目标主机发回的信息,这些信息被保存在ansible变量中; |
| 要获取指定的远程主机所支持的所有facts,可使用如下命令进行; |
| # ansible hostname -m setup |
| register |
| 把任务的输出定义为变量,然后用于其他任务,示例如下: |
| tasks: |
| - shell: /usr/bin/foo |
| register: foo_result |
| ignore_errors: True |
| - hosts: websrvs |
| remote_user: root |
| tasks: |
| - name: copy file |
| copy: content="{{ ansible_all_ipv4_address }}" dest=/tmp/var.dns |
| |
| 通过命令行传递变量 |
| 在运行playbook的时候也可以传递一些变量供playbook使用,示例如下: |
| ansible-playbook test.yml --extra-vars "hosts=www user=ssjinyao" |
| 通过roles传递变量 |
| 当给一个主机应用角色的时候可以传递变量,然后在角色内使用这些变量,示例如下: |
| - hosts: webservers |
| roles: |
| - common |
| - { role: foo_app_instance, dir: '/web/htdocs/a.com', port: 8080 } |
| Inventory |
| ansible的主要功用在于批量主机操作,为了便捷地使用其中的部分主机; |
| 可以在inventory file中将其分组命名,默认的inventory file为/etc/ansible/hosts; |
| inventory file可以有多个,且也可以通过Dynamic Inventory来动态生成; |
| inventory文件格式 |
| inventory文件遵循INI文件风格,中括号中的字符为组名; |
| 可以将同一个主机同时归并到多个不同的组中; |
| 此外,当如若目标主机使用了非默认的SSH端口,还可以在主机名称之后使用冒号加端口号来标明; |
| |
| [webservers] |
| web1.ssjinyao.com:25181 |
| web2.ssjinyao.com |
| [dbservers] |
| db1.ssjinyao |
| db2.ssjinyao.com |
| db3.ssjinyao.com |
| 如果主机名称遵循相似的命名模式,还可以使用列表的方式标识各主机,例如: |
| |
| [webservers] |
| www[01:50].ssjinyao.com |
| [databases] |
| db-[a:f].ssjinyao.com |
| |
| 主机变量 |
| 可以在inventory中定义主机时为其添加主机变量以便于在playbook中使用。例如: |
| [webservers] |
| web1.ssjinyao.com http_port=80 maxRequestsPerChild=808 |
| web2.ssjinyao.com http_port=8080 maxRequestsPerChild=909 |
| |
| 组变量 |
| 组变量是指赋予给指定组内所有主机上的在playbook中可用的变量。例如: |
| [webservers] |
| web1.ssjinyao.com |
| web2.ssjinyao.com |
| |
| [webservers:vars] |
| ntp_server=web1.ssjinyao.com |
| nfs_server=web2.ssjinyao.com |
| |
| 组嵌套 |
| 在inventory中组还可以包含其它的组,并且也可以向组中的主机指定变量; |
| 不过,这些变量只能在ansible-playbook中使用,而ansible不支持; |
| |
| [apache] |
| httpd1.ssjinyao.com |
| httpd2.ssjinyao.com |
| [nginx] |
| nginx1.ssjinyao.com |
| nginx2.ssjinyao.com |
| [webservers:children] |
| apache |
| nginx |
| [webservers:vars] |
| ntp_server=ntp.ssjinyao.com |
| inventory参数 |
| ansible基于ssh连接inventory中指定的远程主机时,还可以通过参数指定其交互方式;这些参数如下所示: |
| ansible_ssh_host |
| The name of the host to connect to, if different from the alias you wish to give to it. |
| ansible_ssh_port |
| The ssh port number, if not 22 |
| ansible_ssh_user |
| The default ssh user name to use. |
| ansible_ssh_pass |
| The ssh password to use (this is insecure, we strongly recommend using --ask-pass or SSH keys) |
| ansible_sudo_pass |
| The sudo password to use (this is insecure, we strongly recommend using --ask-sudo-pass) |
| ansible_connection |
| Connection type of the host. Candidates are local, ssh or paramiko. The default is paramiko before |
| Ansible 1.2, and 'smart' afterwards which detects whether usage of 'ssh' would be feasible based on |
| whether ControlPersist is supported. |
| ansible_ssh_private_key_file |
| Private key file used by ssh. Useful if using multiple keys and you don't want to use SSH agent. |
| ansible_shell_type |
| The shell type of the target system. By default commands are formatted using 'sh'-style syntax by default. |
| Setting this to 'csh' or 'fish' will cause commands executed on target systems to follow those shell's syntax instead. |
| ansible_python_interpreter |
| The target host python path. This is useful for systems with more |
| than one Python or not located at "/usr/bin/python" such as \*BSD, or where /usr/bin/python |
| is not a 2.X series Python. We do not use the "/usr/bin/env" mechanism as that requires the remote user's |
| path to be set right and also assumes the "python" executable is named python, where the executable might |
| be named something like "python26". |
| ansible\_\*\_interpreter |
| Works for anything such as ruby or perl and works just like ansible_python_interpreter. |
| This replaces shebang of modules which will run on that host. |
| |
条件测试
如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试;
when语句
在task后添加when子句即可使用条件测试;when语句支持Jinja2表达式语法
| - name: "shutdown Debian flavored systems" |
| command: /sbin/shutdown -h now |
| when: ansible_os_family == "Debian" |
| |
| |
| 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 |
| - hosts: all |
| remote_user: root |
| vars: |
| - username: user10 |
| tasks: |
| - name: create {{ username }} user |
| user: name={{username}} |
| when: ansible_fqdn == "fabric2" |
| |
迭代
| |
| |
| - name: add several users |
| user: name={{ item }} state=present groups=wheel |
| with_items: |
| - testuser1 |
| - testuser2 |
| |
| - name: add user testuser1 |
| user: name=testuser1 state=present groups=wheel |
| - name: add user testuser2 |
| user: name=testuser2 state=present groups=wheel |
| |
| - name: add several users |
| user: name={{ item.name }} state=present groups={{ item.groups }} |
| with_items: |
| - { name: 'testuser1', groups: 'wheel' } |
| - { name: 'testuser2', groups: 'root' } |
Host和User
| |
| |
| |
| -hosts: webnodes |
| remote_user: root |
| |
| |
| |
| |
| |
| - hosts: webnodes |
| remote_user: ssjinyao |
| tasks: |
| - name: test connection |
| ping: |
| remote_user: ssjinyao |
| sudo: yes |
任务列表与action
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| tasks: |
| - name: make sure apache is running |
| service: name=httpd state=running |
| |
| tasks: |
| - name: disable selinux |
| command: /sbin/setenforce 0 |
| |
| tasks: |
| - name: run this command and ignore the result |
| shell: /usr/bin/somecommand || /bin/true |
| |
| tasks: |
| - name: run this command and ignore the result |
| shell: /usr/bin/somecommand |
| ignore_errors: True |
handlers
| |
| |
| |
| |
| |
| - 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 |
roles
| |
| |
| |
| |
| |
| 一个roles的案例如下所示: |
| site.yml |
| webservers.yml |
| fooservers.yml |
| roles/ |
| common/ |
| files/ |
| templates/ |
| tasks/ |
| handlers/ |
| vars/ |
| meta/ |
| webservers/ |
| files/ |
| templates/ |
| tasks/ |
| handlers/ |
| vars/ |
| meta/ |
| 而在playbook中,可以这样使用roles: |
| --- |
| |
| - hosts: webservers |
| roles: |
| - common |
| - webservers |
| 也可以向roles传递参数,例如: |
| --- |
| |
| - hosts: webservers |
| roles: |
| - common |
| - { role: foo_app_instance, dir: '/opt/a', port: 5000 } |
| - { role: foo_app_instance, dir: '/opt/b', port: 5001 } |
| |
| 甚至也可以条件式地使用roles,例如: |
| --- |
| |
| - hosts: webservers |
| roles: |
| - { role: some_role, when: "ansible_os_family == 'RedHat'" } |
创建role的步骤
- 创建以roles命名的目录;
- 在roles目录中分别创建以各角色名称命名的目录,如webservers等;
- 在每个角色命名的目录中分别创建files、handlers、meta、tasks、templates和vars目录;
- 用不到的目录可以创建为空目录,也可以不创建;
- 在playbook文件中,调用各角色;
role内各目录中可用的文件
- tasks目录:至少应该包含一个名为main.yml的文件,其定义了此角色的任务列表;此文件可以使用include包含其它的位于此目录中的task文件;
- files目录:存放由copy或script等模块调用的文件;
- templates目录:template模块会自动在此目录中寻找Jinja2模板文件;
- handlers目录:此目录中应当包含一个main.yml文件,用于定义此角色用到的各handler;在handler中使用include包含的其它的handler文件也应该位于此目录中;
- vars目录:应当包含一个main.yml文件,用于定义此角色用到的变量;
- meta目录:应当包含一个main.yml文件,用于定义此角色的特殊设定及其依赖关系;
- ansible 1.3及其以后的版本才支持;
- default目录:为当前角色设定默认变量时使用此目录;应当包含一个main.yml文件;
| tags用于让用户选择运行或路过playbook中的部分代码; |
| ansible具有幂等性,因此会自动跳过没有变化的部分; |
| 有些代码为测试其确实没有发生变化的时间依然会非常地长; |
| 此时,如果确信其没有变化,就可以通过tags跳过此些代码片断。 |
- 目录名同角色名;
- 目录结构有固定格式;
- files: 表态文件;
- templates: Jinjia2模板文件;
- tasks:至少有main.yml文件,定义各tasks;
- handlers: 至少有一个main.yml文件,定义各handlers;
- vars:至少有一个mian.yml文件,定义变量;
- meta:定义依赖关系等信息;
- site.yml中定义playbook,额外也可以有其它的yml文件;
ansible-playbook使用示例
在webserver中执行简单管理类命令
| test.yml |
| - hosts: webserver |
| remote_user: root |
| tasks: |
| - name: create nginx 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 db_servers |
| copy: src=/etc/inittab dest=/tmp/inittab.ans## ansible-playbook test.yml |
heartbeat 部署
| heartbeat.yaml |
| - hosts: hbhosts |
| remote_user: root |
| tasks: |
| - name: ensure heartbeat latest version |
| yum: name=heartbeat state=present |
| - name: authkeys configure file |
| copy: src=/root/hb_conf/authkeys dest=/etc/ha.d/authkeys |
| - name: authkeys mode 600 |
| file: path=/etc/ha.d/authkeys mode=600 |
| notify: |
| - restart heartbeat |
| - name: ha.cf configure file |
| copy: src=/root/hb_conf/ha.cf dest=/etc/ha.d/ha.cf |
| notify: |
| - restart heartbeat |
| handlers: |
| - name: restart heartbeat |
| service: name=heartbeat state=restarted |
系统环境初始化
| --- |
| - hosts: all |
| tasks: |
| - name: Add mongodb 3.4 yum repo |
| template: src=./yum/mongo34.repo dest=/etc/yum.repos.d/ |
| - name: Yum remove old mongodb |
| yum: name=mongodb state=removed update_cache=true |
| - name: Yum install mongodb 3.4 |
| yum: name=mongodb-org state=installed update_cache=true |
| - name: Mongo shell edit |
| shell: | |
| killall mongod |
| echo 'never' > /sys/kernel/mm/transparent_hugepage/enabled |
| echo 'never' > /sys/kernel/mm/transparent_hugepage/defrag |
| - name: start mongodb |
| service: name=mongod state=restarted |
| |
| - name: Create mongo user and passwd admin xxxxxx |
| mongodb_user: |
| name: "admin" |
| password: "xxxxxxssjinyao.com" |
| database: "admin" |
| roles: "userAdminAnyDatabase" |
| state: "present" |
| yum: name=mod_ssl state=installed update_cache=true |
| - name: Install git |
| yum: name=git state=installed update_cache=true |
| - name: Install tree |
| yum: name=tree state=installed update_cache=true |
| |
| - name: Install any packages |
| yum: name={{item}} state=installed update_cache=true |
| with_items: |
| - libffi |
| - libffi-devel |
| - openssl |
| - openssl-devel |
| - libxml2 |
| - libxml2-devel |
| - libjpeg-turbo |
| - libjpeg-turbo-devel |
| |
| - name: Install any packages2 |
| yum: name={{item}} state=installed update_cache=true |
| with_items: |
| - zlib |
| - zlib-devel |
| - vim |
| - httpd |
| - mariadb-server |
| - redis |
| - php |
| - php-intl |
| - php-pear |
| - php-devel |
| - libicu |
| - libicu-devel |
| - git |
| - centos-release-scl |
| |
| - name: Install any packages3 |
| yum: name={{item}} state=present update_cache=true |
| with_items: |
| - python-pip |
| - python-devel |
| - gcc |
| - gcc-c++ |
| - kernel-devel |
| - make |
| - MySQL-python |
| - php-mysql |
| - php-gd |
| - mysql-devel |
| - libcurl |
| - libcurl-devel |
| - python-lxml |
| |
| - name: Install any packages4 |
| yum: name={{item}} state=present update_cache=true |
| with_items: |
| - php55 |
| - php-pecl-mongo |
| - php55-php |
| - php55-php-gd |
| - php55-php-mbstring |
| - php55-php-devel |
| - php55-php-mysqlnd |
| - php55-php-ldap |
| - php55-php-intl |
| - php55-php-pear |
| - php55-php-mongo |
| - unzip |
| |
| - name: Install any packages5 other, you can add |
| yum: name={{item}} state=present update_cache=true |
| with_items: |
| - readline-devel |
| - patch |
| |
| - name: Copy php-55 config file to etc |
| copy: remote_src=True src=/opt/rh/httpd24/root/etc/httpd/conf.d/php55-php.conf dest=/etc/httpd/conf.d/ |
| - name: Copy php-55 httpd modules to etc |
| copy: remote_src=True src=/opt/rh/httpd24/root/etc/httpd/conf.modules.d/10-php55-php.conf dest=/etc/httpd/conf.d/ |
| - name: Copy php-55 httpd moduels to etc |
| copy: remote_src=True src=/opt/rh/httpd24/root/etc/httpd/modules/libphp55-php5.so dest=/etc/httpd/modules/ |
| |
| - name: pip install any packages |
| pip: name={{item}} state=present |
| with_items: |
| - supervisor |
| - virtualenv |
| - celery |
| - flower |
| - mongo |
| - redis |
| |
| - name: echo a messages |
| shell: | |
| ifconfig &> /tmp/test.ifconfig |
| netstat -ant &> /tmp/test.netstat |
| exit 0 |
| notify: |
| - start nginx |
| - name: Add redis config file |
| template: src=./redis/redis.conf dest=/etc/ |
| |
| - name: start redis |
| service: name=redis state=started |
| |
| - name: stop apache |
| service: name=httpd state=stopped |
| |
| handlers: |
| - name: start nginx |
| service: name=nginx state=started |
| - name: restart httpd |
| service: name=httpd state=restarted |