实验环境
[laoma@controller ~]$mkdirweb&&cdweb[laoma@controller web]$cat>ansible.cfg<<'EOF' [defaults] remote_user = laoma inventory = ./inventory [privilege_escalation] become = True become_user = root become_method = sudo become_ask_pass = False EOF[laoma@controller web]$cat>inventory<<'EOF' controller node1 node2 node3 node4 EOF修改文件并将其复制到主机
红帽Ansible引擎本身内置附带了大型模块集合(模块库),为了便于整理、记录和管理这些模块,
已根据文档中的功能以及在系统上安装的时间将它们分成多个组。
Files 模块库包含的模块允许您完成与Linux文件管理相关的大多数任务,如创建、复制、编辑和
修改文件的权限和其他属性,下表列出了常用的Files模块库中使用的模块。
file:设置权限、所有权、SELinux上下文以及常规文件、符号链接、硬链接和目录的时间戳等属性。此模块还可以创建或删除常规文件、符号链接、硬链接和目录。
sefcontext,设置持久selinux上下文。
lineinfile:确保特定行位于某个文件中,或使用反向引用正则表达式来替换现有行。
replace:查找文件中行,一次性替换成对应内容。
blockinfile:插入、更新或删除多行文本块。
stat:检索文件的状态信息,类似于Linux stat命令。
copy:将文件从本地或远程计算机复制到受管节点上的某个位置。
synchronize:围绕rsync命令的一个程序,可加快和简化常见任务。
fetch:用于从远程计算机获取文件到控制节点。
file 模块
示例1:创建文件或修改文件属性
--- - hosts: node1 gather_facts: no tasks: - name: Touch afileandsetpermissions file: path: /tmp/testfile owner: laoma group: wheel mode: 0640 state:touchmode选项: 必须使用前导0 (‘0644’ or ‘01777’) 或者引起来 (‘‘644’’ or ‘‘1777’’) 。如果直接写640,则会640当做10进制,并转换成二进制1 010 000 000,最终文件权限是-w- — --T。
示例2:创建目录
--- - hosts: node1 gather_facts: no tasks: - name: create directory file: path: /webdev owner: apache group: apache mode: 0755 state: directory示例3:删除文件
--- - hosts: node1 gather_facts: no tasks: - name: deletefilefile: path: /tmp/testfile state: absentsefcontext 模块
selinux库中添加默认规则。
示例:
--- - hosts: node1 gather_facts: no tasks: - sefcontext: target:'/samba(/.*)?'setype: samba_share_t state: present注意:
- sefcontext模块是修改selinux 库规则,并不会立刻应用于文件,relabel时候才会生效。
- file模块会立刻应用于文件。
lineinfile 模块
示例1:确保文件中存在特定行
--- - hosts: node1 gather_facts: no tasks: - name:addline lineinfile: path: /tmp/testfile line:'Add this line to file'state: present还可以在特定位置插入:
- insertbefore,最后一个匹配到前插入
--- - hosts: node1 gather_facts: no tasks: - name:addline lineinfile: path: /etc/httpd/conf/httpd.conf line:'Listen 82'insertbefore:'Listen 80'state: present- insertafter,最后一个匹配到后插入
--- - hosts: node1 gather_facts: no tasks: - name:addline lineinfile: path: /etc/httpd/conf/httpd.conf line:'Listen 82'insertafter:'Listen 80'state: present示例2:替换文本行
--- - hosts: node1 gather_facts: no tasks: - name: replace line lineinfile: path: /tmp/testfile regexp:'Add'line:'replace'state: present--- - hosts: node1 gather_facts: no tasks: - name:addline lineinfile: path: /etc/httpd/conf/httpd.conf line:'#Listen 80'regexp:'^Listen 80'state: present示例3:替换成多行文本
--- - hosts: node1 gather_facts: no tasks: - name:addline lineinfile: path: /tmp/testfile line:|line1line2regexp:'replace'state: presentreplace 模块
该模块使用正则表达式匹配内容,将匹配的内容替换成指定的内容。匹配的多个地方都会被替换掉。
示例:
--- - hosts: node1 gather_facts: no tasks: - name: replace multi line replace: path: /tmp/testfile regexp:'^Hello World.*'replace:'Hello Laoma'blockinfile 模块
示例:将文本块添加到现有文件
--- - hosts: node1 gather_facts: no tasks: - name:addblock lines tofileblockinfile: path: /tmp/testfile block:|line1infileline2infileaa line3infilesss state: present添加的内容如下,会在第一行和最后一行额外添加注释
# BEGIN ANSIBLE MANAGED BLOCKline1infileline2infileaa line3infilesss# END ANSIBLE MANAGED BLOCKstat 模块
stat 模块检索文件的信息,类似于Linux stat命令。 参数提供检索文件属性、确定文件校验和等
功能。
stat 模块返回一个包含文件状态数据的值的散列字典,允许您使用单独的变量引用各条信息。
示例:
--- - hosts: node1 gather_facts: no tasks: - stat: path: /tmp/testfile checksum_algorithm: md5 register: result - debug: msg:"/tmp/testfile md5 is {{ result.stat.checksum }}"- debug: var: resultcopy 模块
示例1:将控制节点上文件拷贝到受管理节点,类似于Linux中scp命令。
--- - hosts: node1 gather_facts: no tasks: - name: copy /tmp/testfile to remotenodecopy: src: /tmp/testfile dest: /tmp说明:此模块假定设置了force: yes,强制覆盖远程文件,类似scp命令。如果设置force: no, 则
不会出现覆盖。
示例2:写入字符串到文件
--- - hosts: node1 gather_facts: no tasks: - name:writestring into /tmp/testfile copy: content:"hello world\n"dest: /tmp/testfilesynchronize 模块
synchronize 模块是一个围绕 rsync 工具的打包程序,它简化了playbook中的常见文件管理任
务。
rsync工具必须同时安装在本地和远程主机上。默认情况下,在使用synchronize模块时, “本地
主机”是同步任务的源主机, 而 “目标主机”是synchronize连接到的主机。
示例1:同步文件
--- - hosts: node1 gather_facts: no tasks: - name: synchronizefilesynchronize: src: /tmp/testfile dest: /tmp/示例2:同步目录
--- - hosts: node1 gather_facts: no remote_user: root tasks: - name: synchronize directory synchronize: src: /etc/sysconfig dest: /tmp/fetch 模块
从受管节点检索文件,例如将被管理节点文件先取到控制节点,然后用于分发到其他节点。诸如SSH公钥之类的文件。
示例:
--- - hosts: node1 gather_facts: no tasks: - name: fetchfilefrom remotenodefetch: src: /tmp/testfile dest: /tmp文件保存在:/tmp/node1/tmp/testfile。
[laoma@controller web]$ tree /tmp/node1 /tmp/node1 └── tmp └── testfile1directory,1file使用JINJA2模板部署文件
JINJA2 模板介绍
Jinja2 模板是功能强大的工具,可用于自定义要在受管节点上部署的配置文件。 创建Jinja2 模板
后,可以通过template模块部署到受管节点上, 该模块支持将控制节点中的本地文件转移到受管节点。
示例1:部署web服务器,主页内容显示为Welcome to HOSTNAME。HOSTNAME为受管主机完全主机名。
playbook内容如下:
--- - name: Enable intranet services hosts: node1 tasks: - name: ensure latest version of httpd yum: name: httpd state: latest - name:testhtml page is installed# template模块: 复制文件到受管主机时,根据jinja2语法替换template:# 指定 Jinja2 模板来源src: index.html.j2# 指定要在目标主机上创建的文件dest: /var/www/html/index.html - name: httpd enabled and running service: name: httpd enabled:truestate: restarted...index.html.j2 内容如下:
Welcome to{{ansible_fqdn}}剧本执行完成后,index.html内容如下:
Welcome to node1.laoma.cloudtemplate模块,与copy模块类似,允许指定已部署文件的所有者(拥有该文件的用户) 、组、权限和 SELinux上下文 。
示例2:推送 ssh 服务配置文件。 sshd_config.j2内容如下:
AuthorizedKeysFile /etc/.rht_authorized_keys .ssh/authorized_keys# {{ ansible_managed }}# DO NOT MAKE LOCAL MODIFICATIONS TO THIS FILE AS THEY WILL BE LOSTPort{{ssh_port}}ListenAddress{{ansible_facts['default_ipv4']['address']}}HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh/ssh_host_ecdsa_key HostKey /etc/ssh/ssh_host_ed25519_key SyslogFacility AUTHPRIV PermitRootLogin{{root_allowed}}AllowGroups{{groups_allowed}}PasswordAuthentication{{passwords_allowed}}playbook 参考
--- - name: config sshdservicehosts: node1 vars: ssh_port:1022root_allowed:"yes"groups_allowed: wheel passwords_allowed:"yes"ansible_managed:"Ansible managed"tasks: - name: config sshdservicetemplate: src: sshd_config.j2 dest: /root/sshd_configJinja2 模板语法
Jinja2 模板由多个元素组成:数据、变量和表达式。在呈现Jinja2模板时, 这些变量和表达式被替换为对应的值。模板中使用的变量可以在playbook的vars部分中指定,也可以使用受管主机
FACTS。
变量和逻辑表达式置于分隔符之间:
- {{ EXPR }},用于装载表达式,比如变量,运算表达式,比较表达式。
- {% EXPR %},用于装载控制语句,比如if,for等。
- {# #},用于装载注释,模板文件中的注释不会包含在最终生成文件中。
for 语句
Jinja2使用for语句来提供循环功能。
示例1:
--- - name:testtemplate hosts: node1 vars: users: - tom - jack - Snoopy - lucy tasks: - name:testtemplate template: src: testfile.j2 dest: /tmp/testfile...testfile.j2内容如下:
{%foruserinusers%}{{user}}{% endfor %}for用于声明循环,{% endfor %} 表示结束。user变量会遍历users变量中所有值。
生成的/tmp/testfile内容如下:
tom jack Snoopy lucy示例2:testfile.j2内容如下
{#forstatement#}{%foruserinusers%}{{loop.index}}-{{user}}{% endfor %}loop.index代表当前循环的索引号,从1开始到最后循环体的数量。例如循环体有12个,那么
loop.index代表1,2,3,…,12。
生成的/tmp/testfile内容如下:
1- tom2- jack3- Snoopy4- lucy示例3:部署myhosts
创建 playbook:
- 使用模板文件hosts.j2在dev主机组中的主机上生成文件/etc/myhosts。
- hosts.j2内容如下:
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6- 针对每个受管节点包含一行内容:
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain610.1.8.10 controller.laoma.cloud controller10.1.8.11 node1.laoma.cloud node110.1.8.12 node2.laoma.cloud node210.1.8.13 node3.laoma.cloud node310.1.8.14 node4.laoma.cloud node4 注:清单主机名称的显示顺序不重要。
inventory 内容如下:
[controllers]controller[dev]node1[test]node2[prod]node3 node4答案如下:
--- - name: /etc/myhosts is up todatehosts: all tasks: - name: Deploy /etc/myhosts template: src: hosts.j2 dest: /etc/myhosts when: inventory_hostnameingroups.devhosts.j2内容如下:
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6{%forserveringroups.all %}{{hostvars[server].ansible_default_ipv4.address}}{{hostvars[server].ansible_fqdn}}{{hostvars[server].ansible_hostname}}{% endfor %}说明:
hostvars是magic 变量,通过该变量引用其他受管主机facts。
[server]不能使用单引号,因为server作为变量处理,替换为all中主机。
play 必须针对所有主机执行,收集所有主机facts,因为模版需要引用所有主机的facts。
只部署到dev主机组,使用when语句。groups.dev是magic变量,该变量获取dev主机组中
主机清单。
示例4: num 变量引用方括号中列表
{%fornumin[3,1,7,8,2]%}{{num}}{% endfor %}生成的文件内容如下:
31782示例5: range(3)代表 0 1 2,循环三次。
{%fornuminrange(3)%}{{num}}{% endfor %}生成的文件内容如下:
012示例6:range(1,4,2),从1开始,到4结束,步长2。
{%fornuminrange(1,4,2)%}{{num}}{% endfor %}生成的文件内容如下:
13if 语句
Jinja2使用if语句来提供条件控制。如果满足某些条件, 则在部署文件中放置一行。if语句判断条件同ansible中when语句。
示例1: 只要变量finished不是假值,那么输出finished变量值。
{%iffinished %}{{finished}}{% endif %}示例2: 如果PORT定义了端口,那么使用该值,否则使用默认3306。
{%ifPORT is defined %}bind-address=0.0.0.0:{{PORT}}{%else%}bind-address=0.0.0.0:3306{% endif %}示例3:
{%if条件1 %}...{%elif条件2 %}...{%elif条件n %}...{%else%}...{% endif %}{% elif 条件N %}可以多次使用。
示例4: for和if配合使用
{%fornumin[7,1,5,3,9]ifnum>3%}{{num}}{% endfor %}等同于:
{%fornumin[7,1,5,3,9]%}{%ifnum>3%}{{num}}{% endif %}{% endfor %}生成的文件内容如下:
759表达式
示例1:
{{1==1}}{{2!=2}}{{2>1}}{{2>=1}}{{2<1}}{{2<=1}}生成的文件内容如下:
True False True True False False示例2:
jinja2test{{(2>1)or(1>2)}}{{(2>1)and(1>2)}}{{nottrue}}{{not True}}{{notfalse}}{{not False}}生成的文件内容如下:
jinja2testTrue False False False True True示例3:
{{3+2}}{{3-4}}{{3*5}}{{2**3}}{{7/5}}{{7//5}}{{17%5}}生成的文件内容如下:
5-11581.412示例4:
jinja2test{{1in[1,2,3,4]}}{{1notin[1,2,3,4]}}生成的文件内容如下:
jinja2testTrue False模版注释
{# #},用于装载注释,模板文件中的注释不会包含在最终生成文件中。
示例:
{# 此处是注释#}{%fornumin[7,1,5,3,9]%}{%ifnum>3%}{{num}}{% endif %}{% endfor %}生成的文件内容如下:
759ansible_managed 变量
为避免系统管理员修改Ansible部署的文件,最好在模板顶部包含注释,指示不应手动编辑该文
件。
在/etc/ansible/ansible.cfg配置文件[defaults]块中有如下默认配置:
[defaults]ansible_managed=Ansible managed可使用ansible_managed变量来引用“Ansible managed” 字符串。
要想在jinja2 模板内,使用ansible_managed变量代表的字符串,使用下列语法:
{{ansible_managed}}filter 过滤器
Jinja2还提供filter,对输出的结果进行格式化输出。
- “{{ output | to_json }}”,使用JSON格式输出。
- “{{ output | to_yaml }}”,使用YAML格式输出。
- “{{ output | to_nice_json }}”,使用人们更加可读的JSON格式输出。
- “{{ output | to_nice_yaml }}”,使用人们更加可读的YAML格式输出。
- “{{ output | from_json }}”,把output当做JSON格式解析。
- “{{ output | from_yaml }}”,把output当做YAML格式解析。
字符串处理过滤器:
- “{{ testvar | upper }}” ,将字符串转换成纯大写。
- “{{ testvar | lower }}” ,将字符串转换成纯小写。
- “{{ testvar | capitalize }}”,将字符串变成首字母大写,之后所有字母纯小写。
- “{{ testvar | reverse }}”,将字符串反转。
- “{{ testvar | first }}”,返回字符串的第一个字符。
- “{{ testvar | last }}”,返回字符串的最后一个字符。
- “{{ testvar | trim }}”,将字符串开头和结尾的空格去除。
- “{{ testvar | center(width=30) }}”,将字符串放在中间,并且设置字符串的长度为30,字符串两边用空格补齐30位长。
- “{{ testvar | length }}”,返回字符串长度,length与count等效,可以写为count。
- “{{ testvar | list }}”,将字符串转换成列表,每个字符作为一个元素。
列表处理过滤器:
- “{{ testvar | first }}”,返回列表中的第一个值。
- “{{ testvar | last }}”,返回列表中的最后一个值。
- “{{ testvar | min }}”,返回列表中最小的值。
- “{{ testvar | max }}”,返回列表中最大的值。
- “{{ testvar | sort }}”,将列表升序排序输出。
- “{{ testvar | sort(reverse=true) }}”,将列表降序排序输出。
- “{{ testvar | sum }}”,返回纯数字非嵌套列表中所有数字的和。
- “{{ testvar | join }}”,将列表中的元素合并成一个字符串。
- “{{ testvar | join(’ , ') }}”,将列表中的元素使用指定分隔符合并成一个字符串。
- “{{ testvar | random }}”,从列表中随机返回一个元素。
- “{{ testvar | unique }}”,去掉列表中重复的元素,重复的元素只留下一个。
数字处理过滤器:
- {{ ‘a’ | int }}",将对应的值转换成int类型,如果无法转换,默认返回0。使用int(default=6)
- 或者int(6)时,如果无法转换则返回指定值6。
- “{{ ‘a’ | float }}”,将对应的值转换成浮点型,如果无法转换,默认返回’0.0’。使用
- float(default=8.88)或者float(8.88)时,如果无法转换则返回默认值’8.88’。
- “{{ testvar4 | abs }}”,获取对应数值的绝对值。
- “{{ 12.5 | round }}”,四舍五入。
- “{{ 3.1415926 | round(5) }}”,取小数点后五位。
- “{{ 100 | random }}”,从0到100中随机返回一个随机数。
- “{{ 10 | random(start=5) }}”,从5到10中随机返回一个随机数。
- “{{ 15 | random(step=5) }}”,从0到15中随机返回一个随机数,这个随机数是5的倍数。
- “{{ 15 | random(start=5,step=3) }}”,从5到15中随机返回一个随机数,步长为3。