1.额外的两个小东西
ansible-galaxy:
- 连接https://galaxy.ansible.com下载相应的roles
- 列出所有安装的galaxy:ansible-galaxy list [xxx]
- 删除galaxy:ansible-galaxy remove [xxx]
ansible-vault:
- 对剧本进行加密:ansible-vault encrypt 剧本1
- 对剧本进行解密:ansible-vault decrypt 剧本1
- 查看加密后的剧本:ansible-vault view 剧本1
- 编辑加密后的剧本:ansible-vault edit 剧本1
- 修改加密口令:ansible-vault rekey 剧本1
- 加密后的剧本无法运行,需要先解密
2.playbook
剧本中常用的模块可以看这篇:
2.1.简单了解playbook
playbook是由一个或多个“play”组成
ansible-playbook语法:
ansible-playbook [选项] 剧本1 剧本2
YAML基本语法:
- 使用缩进表示层级关系,不允许使用Tab🗡,缩进的空格数不重要,但是一定要统一
- 剧本后缀为".yml"或".yaml"
- #代表注释
- 布尔值灵活,不区分大小写的true/false;yes/no;on/off;y/n;0/1都被允许
- 一个完整的代码块至少元素包括name:task
下面通过一个简单的例子了解一下playbook:
--- - hosts: web remote_user: root tasks: - name: hello world command: hostname
然后通过以下命令运行剧本:当然这个剧本可能没显示什么内容
ansible-playbook test.yaml
如果只想看运行效果,不实际执行,可以用这条命令:
ansible-playbook -C test.yaml
以上剧本中各行内容含义:
- “—”没有什么特殊含义,表示这是一个剧本文件,省略也没有错误
- hosts代表对哪些主机运行剧本,主机清单存放在
/etc/ansible/hosts
文件
- remote_user表示以什么身份运行
- tasks表示任务,可以有一个或多个
2.2.playbook核心元素
- hosts:执行的远程主机清单
- tasks:任务级,一个或多个
- varniables:内置变量或自定义变量
- templates:模板,可替换模板文件中变量实现一些逻辑的文件
- handlers:与notity结合使用,触发器,满足条件即执行
- tags:标签
2.3.playbook基本使用
2.3.1.忽略错误信息
如果执行剧本时由于一个可能出现的错误导致整个剧本无法继续执行,可以使用以下方法来忽略错误
- 命令或脚本退出码不为0的情况,意思是即使错误也返回为真
tasks: - name: xxx shell: 命令 ||/bin/true
- 或使用ignore_errors忽略错误
tasks: - name: xxx shell: 命令 ignore_errors: True
2.3.2.handlers和notify结合形成触发器
- handlers:是task列表,与其他task并没有什么不同,作用于关注的资源发生改变时,处罚一定的操作。
- notify:此action用于在每个play的最后被触发,可避免有多次发生改变时每次都执行指定操作,仅在所有的变化发生完成后一次性的执行指定操作。
tasks: - name: install httpd yum: name=httpd - name: config file template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf notify: restart service - name: start service service: name=httpd state=started enabled=yes handlers: - name: restart service service: name=httpd state=restarted
以上代码中handlers与notify的含义是,当服务的配置文件发生变化时,将处罚服务的重启动作。
handlers是可以有多个的。
2.3.3.tags的使用
- 相当于给某个action起一个标签,例如下面这个例子。
tasks: - name: install httpd yum: name=httpd tags: inhttpd - name: xxx - name: xxx
标签的效果是执行剧本时不会全部执行,只会执行带有标签的动作。
在剧本中可以多个动作共同使用一个标签。
ansible-playboos -t inhttpd httpd.yml
这个命令就是☞执行这个剧本的标签为inhttpd的一个动作,举例不好,看懂就行。
2.3.4.变量
- 变量名:只能由字母、数字和下划线组成,且只能字母开头
变量来源:
- ansible setup facts远程主机的所有变量可直接使用
ansible web -m setup -a 'filter=xxx' 例: ansible web -m setup -a 'filter=*address*'
- 在主机清单中定义:可针对单独主机定义,也可针对组定义,单独主机优先级更高
下面这个例子说明了针对单台主机的变量与针对组都有效的变量。
例: [web] 192.168.10.3 http_port=80 192.168.10.4 http_port=81 [web:vars] nodename=www
- 通过命令指定变量,优先级最高
ansible-playbook -e varname=value 例: tasks: - name: install pkg yum: name={{ pkgname }} ansible-playbook -e 'pkgname=nginx' nginx.yml
- 在playbook中定义
vars: - var1: value1 - var2: value2 例: vars: - pkgname: nginx tasks: - name: install pkg yum: name={{ pkgname }}
- 还可以创建单独的变量文件,在剧本中引用,比如以下这个例子
#创建变量文件 vim vars.yml var1: httpd var2: vsftpd #在剧本中调用变量 --- - hosts: web remote_user: root vars_files: - vars.yml #接下来就可以在剧本中调用变量了 tasks: - name: install pkg yum: name={{ var1 }}
2.3.5.模板
- 将配置文件中的一些配置信息替换成变量,传递到远端服务器时会根据主机信息生成新的配置信息
- 使用jinja2语言,使用字面量,有字符串,数字,列表,元组,字典和布尔值等类型
#字符串 可使用单引号或双引号 #数字 可使用整数或浮点数 #列表 [item1,item2] #元组 (item1,item2) #字典 {key1:value1,} #布尔值 true/false
- 可进行算数运算:
+、-、*、/、//、%、**
- 比较操作:
==、!=、>、<...
- 逻辑运算:
and、or、not
- 流表达式
for、if、when
- 建议创建一个存放模板的templates的文件夹,与playbook平级
在剧本中的用法可以看下面这个例子:
- name: copy template template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
j2模板样式示例:以nginx为例写下部分内容
vim /etc/nginx/nginx.conf # 这个例子代表nginx启动的进程数根据cpu的核数来决定 user nginx; worker_processes {{ ansible_processes_vcpus }} # 这个例子代表nginx启动的进程数是cpu核数的2倍 user nginx; worker_processes {{ ansible_processes_vcpus*2 }}
2.3.6.when
- 条件测试判断
作为条件可以使用远程主机的变量表示
举一个例子:如果系统是redhat系列,则执行命令
- name: xxx shell: xxx when: ansible_os_family == "redhat"
2.3.7.迭代:with_items
- 当有需要重复性执行的任务时,可使用迭代机制
- 对于迭代项的引用,固定变量名为
item
- 要在task中使用with_items给定要迭代的元素列表
- 列表格式:字符串,字典
例如:我们要在远程主机安装多个服务,可以使用这种方法,下面这个例子是说在远程主机上安装haproxy与keepalived两个服务
tasks: - name: install pkg yum: name={{ item }} with_items: - haproxy - keepalived
还可以再复杂一些,比如我要创建两个用户,这两个用户分别要加入指定的组,这种方式叫迭代嵌套子变量。
tasks: - name: create users user: name={{ item.name }} group={{ item.group }} with_items: - { name: 'user1', group: 'group1' } - { name: 'user2', group: 'group2' }
2.3.8.for循环与if条件判断
for循环:
for循环的格式为:
{% for xxxxxx %} 内容 {% endfor %}
如果是if的话,格式为:
{% if xxxxxx %} 内容 {% endif %}
例如:我要创建几个文件,文件的主体框架不变,只是端口会变动,可以使用for循环方式。比如创建虚拟主机的时候使用。
# 创建下列剧本所需要的模板文件test.conf.j2 {% for port in ports %} server{ listem {{ port }} } {% endfor %} # 首先定义变量ports vars: ports: - 81 - 82 - 83 # 然后编写任务 tasks: - name: cp conf template: src=test.conf.j2 dest=/data/test.conf
例2:还可以使用另外一种方式创建一个复杂一些的例子.
# 模板文件内容 {% for n in ports %} server{ listem {{ n.port }} servername {{ n.name }} documentroot {{ n.rootdir }} } {% endfor %} # 剧本内容 vars: ports: - web1: port: 81 name: web1.yyang.com rootdir: /data/web1 - web2: port: 82 name: web2.yyang.com rootdir: /data/web2 tasks: - name: cp conf template: src=test.conf.j2 dest=/data/test.conf
if判断:
以上面例2为例,不一定每一行的数据都存在,如果某行数据不存在,则不生成
# 将name变量注释 ports: - web1: port: 81 #name: web1.yyang.com rootdir: /data/web1 # 模板文件如下:如果name变量是存在的,则生成servername配置,不存在则不生成 {% for n in ports %} server{ listem {{ n.port }} {% if n.name is defined %} servername {{ n.name }} {% endif %} documentroot {{ n.rootdir }} } {% endfor %}
到了这里,一般简单一些剧本可以尝试着写了。
至于roles还是放在下一篇吧。