ansible不完全指南

2年前 (2018-05-22) 运维之路 自动化 846℃

ansible架构

host inventory 主机清单
playbooks 剧本
core modules 自带的核心模块
custom modules 自定义模块
plugins 插件
connection plugins 连接客户端插件

 

ansible架构
host inventory 主机清单
playbooks 剧本
core modules 自带的核心模块
custom modules 自定义模块
plugins 插件
connection plugins 连接客户端插件

 

ansible常用命令

ansible-doc -l 查看所有模块

ansible-doc -s MODULE 查看模块使用

Ad-Hoc Commands
在命令行中执行任务,不需要写脚本,也不用保存任务
ansible <host-pattern> [options]

排除选项
ansible qr-mapping-server -m ping --limit delicloud005

执行剧本

ansible-playbook

ansible常用简单模块

command 默认模块,有些命令不支持,无法识别管道符号
-a "commad"
user 用户管理模块
-a "name= state{present|absent}"    注:present创建,absent删除
group 组管理模块
-a " name= state gid= system="
cron 定时任务管理模块
-a "name= minute= hour= day= month= weekday= job= user= state="
copy 复制模块
-a "dest= src= mode= owner= group="  注:不需要源文件也可使用conten来定义内容
file 文件属性管理模块,可以创建、删除文件
-a "path= mode= owner= group= state={directory|link|touch|absent} src="  注:如果要定义文件为link类型的话,需要制定源文件
shell模块 支持管道符
-a "command"
yum yum模块
-a "name= state={present|latest|absent}"
service 服务管理模块
-a "name= state={started|stopped|restarted} enabled="
ping模块 无参数查看主机连通性
setup 无参数,搜集客户端信息,如主机核数,值可以用变量获取到

playbook

task 任务,即调用多个模块完成的操作
variables 变量
tag 标签
handlers 处理器,由某事件触发执行的操作
roles 角色

playbook基础组件
1、hosts和users
playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机,可以是一个或多个由冒号分割的主机组,remote_user则用于指定远程主机上的执行任务的用户。如
- hosts: webnodes
remote_user:root
不过,remote_user也可以用于各task中。

2、任务列表和action
play的主体部分是task list,task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后在开始第二个。在运行自上而下的的某playbook时,如果中途发生错误,所有已执行任务都将回滚,因此在更正playbook后重新执行一次即可。
task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这以为着多次执行是安全的,因为其结果均一致。
每个task都应该有其name,用于playbook的执行结果输出,建议其内容尽可能的清晰的描述任务步骤,如果未提供name,则action的结果将用于输出。
定义task可以使用“module: options”格式如
tasks:
  - name: test
    service: name=httpd state=running
在众多模块中,只有command和shell模块仅需要给定一个列表而无需使用“key=value”格式,例如
tasks:
  - name: disable selinux
    command: /sbin/setenforce 0
如果命令或脚本的退出码不为0,可以使用如下方式替代:
tasks:
  - name: run and ignore result
     shell: /usr/bin/somecommand || /bin/true
或者使用ignore_errors来忽略错误信息:
tasks:
   - name: run and ignore result
      shell: /usr/bin/somecommand
      ignore errors: True

3、handlers

cat apache.yml
- hosts: webservers
  remote_user: root
  tasks:
    - name: install apache
      yum: name=httpd state=latest
    - name: install configure 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

上面这个YAML文件存在三个task任务:
1、安装httpd
2、复制配置文件到远端主机
3、启动httpd服务
但是如果任务2中的源配置文件发生了改变,再次执行playbook的话会发现新的配置文件虽然会正确的复制到远端主机去,但是却没有重启httpd服务。因为ansible在执行playbook时发现第三个任务与现在状态是一致的,就不会再次执行任务。要解决这个问题的话需要使用ansible的handlers功能。handlers是用于监控一个任务的执行状态,如果一个tasks任务最后是changed状态则会触发handlers指定的操作
Ansible中通过notify这个模块来实现handlers,将示例1修改后:

cat apache.yml
- hosts: webservers
  remote_user: root
  tasks:
    - name: install apache
      yum: name=httpd state=latest
    - name: install configure file for httpd
      copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
      notify:
        - restart httpd #通知给一个名为restart httpd的handlers
    - name: start httpd service
      service: enabled=true name=httpd state=started  
  handlers: #handlers和tasks同级
    - name: restart httpd #handlers的名字,被notify引用,两边要一致
      service: name=httpd state=restart

当httpd.conf的源文件发生修改后,只需重新执行playbook就会自动重启httpd服务,因为配置文件状态是changed而非

4、tags

用ansible写playbook的朋友可能会发现,当配置工作很多时,如果在中间过程出错了,修改后想重新执行,前面的一大堆步骤让人感觉很烦躁。虽然提供了“retry”文件,但是却只是根据host来判断重新执行,仍然不够方便;又或者,中间的某些步骤特别耗时,比如下载一个很大的数据包,每次执行特别浪费时间,想要特别的跳过。怎么办?我猜你就是把不需要的部分给注释掉了。有没有更好的办法呢?

ansible的playbool中有一个关键字,叫做tags。tags是什么?就是打标签。tags可以和一个play(就是很多个task)或者一个task进行捆绑。然后,ansible-playbook提供了“--skip-tags”和“--tags” 来指明是跳过特定的tags还是执行特定的tags。

下面请看例子。

cat test1.yml
- hosts: test-agent 
  tasks: 
    - command: echo test1 
      tags: 
        - test1 
    - command: echo test2 
      tags: 
        - test2 

当执行 ansible-playbook test1.yml --tags="test1" ,则只会执行 test1的echo命令。
当执行 ansible-playbook test1.yml --skip-tags="test2" ,同样只会执行 test1的echo命令。
同理可以适用于play,请看例子

cat test2.yml
- hosts: test-agent1 
  tags: 
    - play1 
  tasks: 
    - command: echo This is 
    - command: echo agent1 
- hosts: test-agent2 
  tags: 
    - play2 
  tasks: 
    - command: echo This is 
    - command: echo agent2 
- hosts: test-agent3 
  tags: 
    - play3 
  tasks: 
    - command: echo This is 
    - command: echo agent3

当执行 ansible-playbook test2.yml --tags="play1,play3" ,则只会执行 play1和play3的tasks。
当执行 ansible-playbook test2.yml --skip-tags="play2" ,同样只会执行 test1和test3的tasks。

模块

模块templates

如果每个客户端上的配置有所不同,这个时候后就可以使用到templates模块了

- hosts: "{{ SERVICE }}"
  tasks:
   - name: update config
      template: src=/root/ansible/startup.sh dest=/opt/{{ SERVICE }}/startup.sh

模板文件startup.sh配置如下,其中变量全部配置在host inventory中

cd /opt/{{ SERVICE }}/
java -Xms{{ XMS }} \
     -Xmx{{ XMX }} \
     -Xmn{{ XMN }} \
     -Xss256k \
     -XX:MetaspaceSize=512m \
     -XX:MaxMetaspaceSize=512m \
     -XX:SurvivorRatio=4 \
     -XX:+UseParallelGC \
     -XX:ParallelGCThreads=2 \
     -XX:+HeapDumpOnOutOfMemoryError \
     -Dcom.sun.management.jmxremote \
     -Dcom.sun.management.jmxremote.port={{ JMXPORT }} \
     -Dcom.sun.management.jmxremote.authenticate=false \
     -Dcom.sun.management.jmxremote.ssl=false \
     -server \
     -jar {{ SERVICE }}*.jar --spring.profiles.active=product --server.workerId={{ WORKER_ID }}

 

roles

http://www.ansible.com.cn/docs/playbooks_roles.html

ansible中yaml基础元素

变量
1、inventory中定义变量
192.168.0.1 XMS=2048M XMX=2048M XMN=1370M JMXPORT=12328 WORKER_ID=0
2、通过vars关键字定义:
- name: websrvs
remote_user:root
vars:
- package: httpd
- service: httpd
tasks:
- name: install {{ package }}
yum: name={{ package }} state=latest
3、命令行变量
ansible-playbook release.yml --extra-vars "hosts=vipers user=starbuck"
4、setup变量
ansible每一次play执行时都会默认首先执行setup模块取回客户端信息,这里面的键可以直接当做变量使用如下
delicloud000 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"172.20.1.203"
],
"ansible_all_ipv6_addresses": [],
"ansible_apparmor": {
"status": "disabled"
},
"ansible_architecture": "x86_64",
"ansible_bios_date": "04/01/2014",
........

- hosts: " {{ host }} "
  tasks:
- name: test
  copy: content={{ ansible_cmdline.console }} dest=/tmp/vars.ans

变量总结
在ansible中调用变量统一使用 {{ VARS }}
调用字典内的字典key可以使用key.key的方式
定义的变量可以用在模板中

 

条件测试
如果需要根据变量、facts或此前任务的执行结果来作为某task执行与否的前提时需要用到条件测试。
1、when语句
在task后添加when 子句即可使用条件测试如
tasks:
- name: shutdown system
command: /sbin/shutdown -h now
when: ansible_os_family == "Debian"
when语句中还可以使用junja2的大多“filter”,例如要忽略此前某语句的错误并基于其结果(failed或者success)运行后面指定语句,可使用如下形式
task:
- command: /bin/false
register: result
ignore_errors: True
- command: /bin/something
when: result|success
此外,when语句中还可以使用facts或playbook中定义的变量

 

迭代
当有需要重复执行的任务时,可以使用迭代机制,其实用格式为将需要迭代的内容定义为item变量引用,并通过with_items语句来指明迭代的元素列表即可
例如
- name: add users
user: name={{ item }} state=present groups=wheel
with_items:
- testuser1
- testuser2
实际上,with_items中可以使用元素还可以为hashes例如
- name: add users
user: name={{ item.name }} state=present groups={{ item.groups }}
with_items:
- { name:'testuser1',groups:'wheel' }
- { name:'testuser2',groups:'root' }

迭代经常跟register用在一起如下例

将客户机上以.ini后缀名的文件进行修改

- hosts : "{{ host }}"
tasks:
- name: find file
find: paths=/etc/supervisor.d patterns="*.ini" file_type=file
register: find_result
- name: add line
lineinfile: dest={{ item.path }} line="stopasgroup=true\nkillasgroup=true"
with_items: 
- "{{ find_result.files }}"

上例中直接将另一个task的结果置为元素,find_result.files也是一个字典格式如下

{"nlink": 1, "path": "/etc/supervisor.d/base.ini",}

博主

这货来去如风,什么鬼都没留下!!!

相关推荐

嗨、骚年、快来消灭0回复。