Linux Ansible自动化运维 template模块 jinja2模板引擎

一、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",如下所示

# vim /etc/redis/6379.conf
  70 bind 127.0.0.1

 
 
 
  • 1
  • 2
  • 3

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

[root@server4 ~]# vim 6379.conf 
bind {
   {
   ansible_host}} 127.0.0.1

 
 
 
  • 1
  • 2
  • 3

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

[root@server4 ~]# vim template.yml
[root@server4 ~]# cat template.yml 
---
- hosts: testB
  remote_user: root
  gather_facts: no
  tasks:
  - template:
      src: /root/6379.conf
      dest: /etc/redis/6379.conf
  - name: restart redis
    shell: /etc/init.d/redis_6379 restart

 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

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

[root@server4 ~]# ansible-playbook template.yml 

 
 
 
  • 1

在这里插入图片描述

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

[root@server3 ~]# vim /etc/redis/6379.conf
bind 172.25.63.3 127.0.0.1

 
 
 
  • 1
  • 2
  • 3

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

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

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

[root@server4 ~]# ansible testB -m template -a "src=/root/6379.conf dest=/etc/redis/6379.conf"

 
 
 
  • 1

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

二、template模块

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

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

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

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

三、jinja2模板引擎

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

  • { { }} :用来装载表达式,比如变量、运算表达式、比较表达式等。
  • {% %} :用来装载控制语句,比如 if 控制结构,for循环控制结构。
  • {# #} :用来装载注释,模板文件被渲染后,注释不会包含在最终生成的文件中。

我们可以用几个示例来熟悉上述基础语法吧,在ansible主机中准备测试文件

变量操作示例

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

[root@server4 jinja2]# vim test1.j2
[root@server4 jinja2]# cat test1.j2 
test jinja2 variable
test {
   {
    testvar1 }} test

 
 
 
  • 1
  • 2
  • 3
  • 4

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

[root@server4 jinja2]# ansible testB -m template -e "testvar1=redhat" -a "src=test1.j2 dest=/opt/test1"

 
 
 
  • 1

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

[root@server3 redis]# cd /opt/
[root@server3 opt]# cat test1 
test jinja2 variable
test redhat test

 
 
 
  • 1
  • 2
  • 3
  • 4

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

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

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

比较表达式示例

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

模板文件内容如下:

[root@server4 jinja2]# vim test2.j2 
[root@server4 jinja2]# cat test2.j2 
{
   {
    1 == 1 }}
{
   {
    2 != 2 }}
{
   {
    2 > 1 }}
{
   {
    2 >= 1 }}
{
   {
    2 < 1 }}
{
   {
    2 <= 1 }}
[root@server4 jinja2]# ansible testB -m template -a "src=test2.j2 dest=/opt/test"

 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

生成文件内容如下:

[root@server3 opt]# cat test
True
False
True
True
False
False

 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

逻辑运算示例

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

模板文件内容:

[root@server4 jinja2]# vim test3.j2 
[root@server4 jinja2]# cat test3.j2 
{
   {
    (2 > 1) or (1 > 2) }}
{
   {
    (2 > 1) and (1 > 2) }}
{
   {
    not true }}
{
   {
    not True }}
{
   {
    not false }}
{
   {
    not False }}
[root@server4 jinja2]# ansible testB -m template -a "src=test3.j2 dest=/opt/test"

 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

生成文件内容:

[root@server3 opt]# cat test
True
False
False
False
True
True

 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

算数运算示例

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

模板文件内容

[root@server4 jinja2]# vim test4.j2 
[root@server4 jinja2]# cat test4.j2 
{
   {
    3 + 2 }}
{
   {
    3 - 4 }}
{
   {
    3 * 5 }}
{
   {
    2 ** 3 }}
{
   {
    7 / 5 }}
{
   {
    7 // 5 }}
{
   {
    17 % 5 }}
[root@server4 jinja2]# ansible testB -m template -a "src=test4.j2 dest=/opt/test"

 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

生成文件内容

[root@server3 opt]# cat test
5
-1
15
8
1.4
1
2

 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

成员运算示例

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

模板文件内容

[root@server4 jinja2]# vim test5.j2 
[root@server4 jinja2]# cat test5.j2 
{
   {
    1 in [1,2,3,4] }}
{
   {
    1 not in [1,2,3,4] }}
[root@server4 jinja2]# ansible testB -m template -a "src=test5.j2 dest=/opt/test"

 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5

生成文件内容

[root@server3 opt]# cat test
True
False

 
 
 
  • 1
  • 2
  • 3

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

python的基础数据类型

模板文件内容如下:

[root@server4 jinja2]# vim test6.j2 
[root@server4 jinja2]# cat test6.j2 
### str
{
   {
    'testString' }}
{
   {
    "testString" }}
### num
{
   {
    15 }}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值