ansible笔记(38):jinja2模板(一)

栏目: 数据库 · 发布时间: 7年前

内容简介:所属分类:ansible
  • A+

所属分类:ansible 运维技术

在本博客中,ansible是一个系列文章,我们会尽量以通俗易懂的方式总结ansible的相关知识点。

ansible系列博文直达链接:ansible轻松入门系列

"ansible系列"中的每篇文章都建立在前文的基础之上,所以, 请按照顺序阅读这些文章,否则有可能在阅读中遇到障碍。

当安装完 redis 以后,redis默认配置的监听地址为"127.0.0.1",这样是安全的,但是,如果我需要让redis监听在非"127.0.0.1"的IP地址上,以便让其他主机也能够使用本机上的redis服务,那么我就需要修改默认的配置,没错,修改redis配置文件中的bind设置,即可将redis绑定在指定的IP上,假设,现在需要一次性在10台主机上安装redis,并且让安装后的redis都监听在redis所在主机的非"127.0.0.1"的IP地址上,我们该怎么办呢?通过ansible在10台主机上安装redis很容易,但是安装完成后,10台主机中的redis都是使用默认的监听地址"127.0.0.1"的,难道我们要在安装完成后,挨个的手动修改这10台主机中的redis配置文件吗?显然,应该有更加方便的方法能够解决这个问题,没错,这个方法就是使用"模板"。

此处,先大致的描述一下"模板"的用法,以便先在脑海中形成概念方便理解,我们会在之后进行具体的示例和解释,到时候我们自然会更加清晰的理解"模板"。

如果想要解决上述问题,我们可以先创建一个"模板"文件,ansible会根据"模板"文件,为每一台主机生成对应的配置文件,大致步骤如下:

1、找一个现成的redis配置文件,作为"模板"文件,你可以从之前安装过redis的主机中拷贝一份,也可以从redis的rpm包中提取一份。

2、修改模板文件,将IP设置部分使用变量进行替换。

3、使用ansible调用"template"模块,对"模板文件"进行渲染,根据模板生成每个主机对应的配置文件,并将最终生成的配置文件拷贝到目标主机中。

了解完上述步骤,你可能已经初步的有了一个大致的概念,那么现在,我们来看看具体该怎样实现。

首先,就是准备一个redis配置文件作为模板文件,所有主机的redis配置文件都是根据这个模板文件生成的,此处,我已经从之前安装过redis的主机中拷贝了一个redis.conf文件到ansible控制机中,打开这个配置文件,可以看到,默认监听的地址为"127.0.0.1",如下图所示

ansible笔记(38):jinja2模板(一)

按照要求,每个主机上的redis都应该监听在自己的非本地回环地址上,但是,每个主机的IP地址都不一样,我们怎样才能获取到每个机器的IP地址呢?你肯定已经想到了,我们在使用ansible连接到对应主机时,就已经获取到了对应主机的IP地址,对应的IP就存放在"ansible_host"变量中(在配置ansible清单时也是将远程主机的IP地址写入到ansible_host变量中,如果你忘记了,情回顾前文,但是需要注意,ansible控制机对应的ansible_host变量的值并不是自己的IP,而是在清单中配置的主机别名),所以,我们只要在bind设置中使用"ansible_host"变量进行替换即可,修改redis.conf文件,如下图所示:

ansible笔记(38):jinja2模板(一)

完成上述修改后,模板配置文件就算准备好了,那么,我们就来编写一个playbook,来完成上述工作场景,示例playbook如下:

# cat temptest.yml
---
- hosts: test70
 remote_user: root
 gather_facts: no
 tasks:
 - yum:
     name: redis
     state: present
 - template:
     src: /testdir/ansible/redis.conf
     dest: /etc/redis.conf

如上例所示,先使用yum模块安装了redis,然后调用template模块,上例template模块使用了两个参数,src参数和dest参数,src参数对应的文件就是ansible主机中的模板文件,即我们刚才修改过的redis.conf配置文件模板,dest参数表示将最终生成的配置文件拷贝到目标主机的所在路径,也就是说,上例playbook会调用template模块,使用ansible主机中的/testdir/ansible/redis.conf 文件作为模板文件,根据模板文件,对目标主机test70生成最终的配置文件,最终的配置文件会被拷贝到test70主机的/etc目录中,并且文件名为redis.conf,通过yum安装redis后默认的配置文件路径即为 /etc/redis.conf,我们使用template模块生成了最终的配置文件后,覆盖了yum默认配置文件,如上例所示,template模块不仅能够根据模板文件生成文件,还会自动将生成的文件拷贝到远程主机中的指定位置,那么我们来运行一下上例playbook

# ansible-playbook temptest.yml

playbook执行完毕后,我们到目标主机test70上查看/etc/redis.conf文件,redis.conf中的bind配置如下图所示

ansible笔记(38):jinja2模板(一)

可以看到,test70中的redis.conf文件中的bind配置对应的IP地址为10.1.1.70,这个IP正是test70主机的IP地址,这种效果完全符合我们的预期,在test70主机中安装完redis以后,并没有手动的修改配置文件,而是利用"模板",自动生成了对应配置文件,并拷贝到了远程主机中的指定位置,上例中,为了演示方便,目标主机只指定了test70一台主机,你也可以在上例playbook中一次性的指定多台目标主机试试,最终的效果就是每台主机中的redis都监听在自己的IP地址上。

经过上述描述,你一定已经明白了模板的作用和用法,模板功能可以帮助我们灵活的生成配置文件,我们只需要先选择一个文件作为模板文件,然后修改模板文件中需要灵活生成的部分,使用变量进行替换(对应的变量必须提前定义好或者能够在运行时获取),模板文件中不需要灵活生成的部分保持不变即可,当需要为各个目标主机生成配置文件时,只需调用template模块,templdte模块会在ansible控制机中对模板文件进行渲染,最终生成各个主机对应的配置文件,然后拷贝到远程主机的指定位置中。

除了在playbook中能够使用template模块,在ad-hoc命令中也可以直接调用templdate模块,在ad-hoc命令中使用templdate模块比较方便我们测试模板文件的最终生成效果,示例如下:

# ansible test70 -m template -a "src=/testdir/ansible/redis.conf dest=/opt/redis.conf"

直接在ansible主机中执行上述ad-hoc命令,执行完成后,即可在目标主机中的对应位置获取到最终生成的文件。

由于template模块还负责将最终生成的文件拷贝到远程主机上,所以还有一些常用的参数,可以用于设置配置文件的权限,如下:

owner参数: 指定最终生成的文件拷贝到远程主机后的属主。

group参数: 指定最终生成的文件拷贝到远程主机后的属组。

mode参数: 指定最终生成的文件拷贝到远程主机后的权限,如果你想将权限设置为"rw-r--r--",则可以使用mode=0644表示,如果你想要在user对应的权限位上添加执行权限,则可以使用mode=u+x表示。

除了上述参数,还有如下参数也很常用

force参数: 当远程主机的目标路径中已经存在同名文件,并且与最终生成的文件内容不同时,是否强制覆盖,可选值有yes和no,默认值为yes,表示覆盖,如果设置为no,则不会执行覆盖拷贝操作,远程主机中的文件保持不变。

backup参数: 当远程主机的目标路径中已经存在同名文件,并且与最终生成的文件内容不同时,是否对远程主机的文件进行备份,可选值有yes和no,当设置为yes时,会先备份远程主机中的文件,然后再将最终生成的文件拷贝到远程主机。

上述参数的具体示例就不再多写了,有了前文中总结的模块作为基础,搞定上述参数自然不在话下。

前文中我们提到过,ansible使用的是jinja2模板引擎,你肯定早就想到了,当templdate模块对模板文件进行渲染时,使用的就是jinja2模板引擎,所以,如果想要更加灵活的编辑模板文件,最好还要了解一些与jinja2有关的基本知识点,其实,我们一直都在使用jinja2的语法,当我们在playbook中引用变量时,会将变量用双括号"{{  }}"括起,这就是jinja2的语法,在jinja2中,使用"{{  }}"装载变量,除了"{{  }}",还有一些其他的jinja2基本语法,我们一起来了解一下,如下:

{{      }}  :用来装载表达式,比如变量、运算表达式、比较表达式等。

{%   %}   :用来装载控制语句,比如 if 控制结构,for循环控制结构。

{#    #}   :用来装载注释,模板文件被渲染后,注释不会包含在最终生成的文件中。

单单靠嘴描述,不够清晰,不如我们一起来动手熟悉一下上述基础语法吧,在ansible主机中准备一个测试文件,我的测试文件名为test.j2

仍然从我们最熟悉的变量操作开始测试,test.j2中写入如下内容:

# cat test.j2
test jinja2 variable
test {{ testvar1 }} test

然后在ansible主机中执行如下测试命令:

# ansible test70 -m template -e "testvar1=teststr" -a "src=test.j2 dest=/opt/test"

如上例所示,我们在渲染模板时传入了变量testvar1,其变量值为teststr,上述命令执行完成后,登录目标主机,即test70主机,查看渲染后的文件内容,如下:

# cat test
test jinja2 variable
test teststr test

上述示例中,"{{  }}"中包含的就是一个变量,当模板被渲染后,变量的值被替换到了最终的配置文件中,当然,既然在模板中定义了变量,那么就要保证在渲染模板时,可以调用到对应的变量,否则就会报错,"{{  }}"中除了能够包含变量,还能够包含哪些东西呢?如后文所示。

注:为了方便示例,之后的示例会直接给出模板文件内容与最终生成文件的内容,省略对应渲染模板的过程,渲染模板过程参考上述示例即可。

上文中提到过,除了变量,"{{  }}"中还可以包含一些表达式,那么我们一起来看看那些常用的表达式在"{{  }}"中的示例。

比较表达式的相关示例如下:

模板文件内容如下:
# cat test.j2
jinja2 test
{{ 1 == 1 }}
{{ 2 != 2 }}
{{ 2 > 1 }}
{{ 2 >= 1 }}
{{ 2 < 1 }}
{{ 2 <= 1 }}
 
生成文件内容如下:
# cat test
jinja2 test
True
False
True
True
False
False

逻辑运算的相关示例如下:

模板文件内容
# cat test.j2
jinja2 test
{{ (2 > 1) or (1 > 2) }}
{{ (2 > 1) and (1 > 2) }}
 
{{ not true }}
{{ not True }}
{{ not false }}
{{ not False }}
 
 
生成文件内容
# cat test
jinja2 test
True
False
 
False
False
True
True

算数运算的相关示例如下:

模板文件内容
# cat test.j2
jinja2 test
{{ 3 + 2 }}
{{ 3 - 4 }}
{{ 3 * 5 }}
{{ 7 / 5 }}
{{ 7 // 5 }}
{{ 17 % 5 }}
 
生成文件内容
# cat test
jinja2 test
5
-1
15
1.4
1
2

成员运算的相关示例如下:

模板文件内容
# cat test.j2
jinja2 test
{{ 1 in [1,2,3,4] }}
{{ 1 not in [1,2,3,4] }}
 
生成文件内容
# cat test
jinja2 test
True
False

在上述成员运算的示例中,in运算符后面对应的是一个"列表",所以你一定已经想到了,一些基础的数据类型,都可以包含在"{{  }}"中,jinja2本身就是基于 python 的模板引擎,所以,python的基础数据类型都可以包含在"{{  }}"中,这也是再自然不过的了,相关示例如下:

模板文件内容如下:
# cat test.j2
jinja2 test
{{ 'testString' }}
{{ "testString" }}
{{ 15 }}
{{ 18.8 }}
{{ ['Aa','Bb','Cc','Dd'] }}
{{ ['Aa','Bb','Cc','Dd'].1 }}
{{ ['Aa','Bb','Cc','Dd'][1] }}
{{ ('Aa','Bb','Cc','Dd') }}
{{ ('Aa','Bb','Cc','Dd').0 }}
{{ ('Aa','Bb','Cc','Dd')[0] }}
{{ {'name':'bob','age':18} }}
{{ {'name':'bob','age':18}.name }}
{{ {'name':'bob','age':18}['name'] }}
{{ True }}
{{ true }}
{{ False }}
{{ false }}
 
 
生成文件内容如下:
# cat test
jinja2 test
### str
testString
testString
### num
15
18.8
### list
['Aa', 'Bb', 'Cc', 'Dd']
Bb
Bb
### tuple
('Aa', 'Bb', 'Cc', 'Dd')
Aa
Aa
### dic
{'age': 18, 'name': 'bob'}
bob
bob
### Boolean
True
True
False
False

从上述示例模板文件可以看出,字符串、数值、列表、元组、字典、布尔值等数据类型均可在"{{  }}"使用,但是,通常我们不会像上述示例那样使用它们,因为通常我们会通过变量将对应的数据传入,而不是将数据直接写在"{{  }}"中,即使直接将数据写在"{{  }}"中,也会配合其他表达式或者函数进行处理,所以,我们可以把上述模板文件的内容改为如下内容进行测试:

jinja2 test
{{ teststr }}
{{ testnum }}
{{ testlist[1] }}
{{ testlist1[1] }}
{{ testdic['name'] }}

此处我们使用如下playbook对上述模板文件进行测试,而不是使用ad-hoc命令,原因稍后解释,测试playbook如下:

# cat temptest.yml
---
- hosts: test70
 remote_user: root
 gather_facts: no
 vars:
   teststr: 'tstr'
   testnum: 18
   testlist: ['aA','bB','cC']
   testlist1:
   - AA
   - BB
   - CC
   testdic:
     name: bob
     age: 18
 tasks:
 - template:
     src: /testdir/ansible/test.j2
     dest: /opt/test

运行上例playbook以后,最终生成的文件如下

# cat test
jinja2 test
tstr
18
bB
BB
bob

刚才之所以用playbook进行测试,是因为如果通过命令把列表当做参数传入后,列表会被当做字符串处理,所以没有通过ad-hoc直接进行测试,而是通过playbook的方式渲染模板。

除了变量和各种常用的运算符,过滤器也可以直接在"{{  }}"中使用,与前文示例中的用法没有任何区别,示例如下:

模板文件内容
# cat test.j2
jinja2 test
{{ 'abc' | upper }}
 
 
生成文件内容
# cat test
jinja2 test
ABC

当然,jinja2的tests自然也能够在"{{  }}"中使用,与前文中的用法也是一样的,如下:

模板文件内容
# cat test.j2
jinja2 test
{{ testvar1 is defined }}
{{ testvar1 is undefined }}
{{ '/opt' is exists }}
{{ '/opt' is file }}
{{ '/opt' is directory }}
 
执行命令时传入变量
# ansible test70 -m template -e "testvar1=1 testvar2=2" -a "src=test.j2 dest=/opt/test"
 
生成文件内容
# cat test
jinja2 test
True
False
True
False
True

说了"过滤器"和"tests",怎么能缺了"lookup",示例如下:

模板文件内容如下
# cat /testdir/ansible/test.j2
jinja2 test
 
{{ lookup('file','/testdir/testfile') }}
 
{{ lookup('env','PATH') }}
 
test jinja2
 
 
ansible主机中的testfile内容如下
# cat /testdir/testfile
testfile in ansible
These are for testing purposes only
 
 
生成文件内容如下
# cat test
jinja2 test
 
testfile in ansible
These are for testing purposes only
 
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
 
test jinja2

经过上述描述,你肯定已经发现了,前文中总结的很多知识点都能用上,而且经过上述描述,"{{  }}"的用法你肯定也已经掌握了,说完"{{  }}",顺势来聊聊"{#   #}",上文中提到过,在jinja2中,使用"{#   #}"包含注释信息,所以,如果我们需要在模板文件中对某些配置进行注释,则可以将注释信息写入到"{#   #}"中

,示例如下:

模板文件内容如下:
# cat test.j2
jinja2 test
{#这是一行注释信息#}
jinja2 test
{#
这是多行注释信息,
模板被渲染以后,
最终的文件中不会包含这些信息
#}
jinja2 test
 
 
生成文件内容如下:
# cat test
jinja2 test
jinja2 test
jinja2 test

"{{  }}"和"{#   #}"的用法就先总结到这里,下一篇文章中,我们再来总结一下"{%  %}"的用法,希望这篇文章能够对你有所帮助~~

ansible笔记(38):jinja2模板(一)

我的微信公众号

关注"实用运维笔记"微信公众号,当博客中有新文章时,可第一时间得知哦~


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Host Your Web Site In The Cloud

Host Your Web Site In The Cloud

Jeff Barr / SitePoint / 2010-9-28 / USD 39.95

Host Your Web Site On The Cloud is the OFFICIAL step-by-step guide to this revolutionary approach to hosting and managing your websites and applications, authored by Amazon's very own Jeffrey Barr. "H......一起来看看 《Host Your Web Site In The Cloud》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具