Saltstack (五) --- Jinja模板 的使用

一、Jinja模板簡介

Jinja是一種基於python的模板引擎,在SLS文件裏可以直接使用jinja模板來做一些操作。

通過jinja模板可以爲不同服務器定義各自的變量。

兩種分隔符: {% ... %}{{ ... }},前者用於執行諸如 for 循環 或賦值的語句,後者把表達式的結果打印到模板上(引用)。

二、Jinja模板使用方式

使用控制結構包裝條件

Jinja最基本的用法是使用控制結構包裝條件:

[root@server1 salt]# vim test.sls
[root@server1 salt]# cat test.sls 
/mnt/testfile:
  file.append:
    {% if grains['fqdn'] == 'server2' %}
    - text: server2
    {% elif grains['fqdn'] == 'server3' %}
    - text: server3
    {% endif %}

以上文件的內容表示在server2和server3創建文件/mnt/testfile,並將不同的內容添加進入文件。

推送:

[root@server1 salt]# salt '*' state.sls test

在server2查看:

[root@server2 ~]# cd /mnt/
[root@server2 mnt]# cat testfile 
server2

在server3查看:

[root@server3 ~]# cd /mnt/
[root@server3 mnt]# cat testfile 
server3

在普通文件的使用

Jinja在普通文件的使用:

[root@server1 salt]# cd apache/
[root@server1 apache]# vim init.sls 
[root@server1 apache]# cat init.sls 
apache:
  pkg.installed:
    - pkgs:
      - {{ pillar['webserver'] }}
  service.running:
    - name: httpd
    - reload: true
    - enable: true
    - watch:
      - file: /etc/httpd/conf/httpd.conf

/etc/httpd/conf/httpd.conf:
  file.managed:
    - source: salt://apache/httpd.conf
    - template: jinja
    - context:
      bind: 172.25.63.3
      port: 80

其中:

- template: jinja		#啓用jinja模板
- context:
  bind: 172.25.63.3		#定義變量
  port: 80

表示啓用jinja模板和定義變量,接下來在配置文件中調用變量:

[root@server1 apache]# vim httpd.conf 
[root@server1 apache]# cat -n httpd.conf | grep 42
    42	Listen {{ bind }}:{{ port }}

推送(由於ip已經設置,故推送給server3):

[root@server1 apache]# salt server3 state.sls apache

在這裏插入圖片描述推送成功,在server3查看:

[root@server3 ~]# netstat -antlpe | grep 80
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      0          34667      3047/nginx: master  

查看配置文件:
[root@server3 ~]# cat -n /etc/httpd/conf/httpd.conf | grep 42
    42	Listen 172.25.63.3:80

從配置文件可以看出變量成功調用。

但是這種方式在主機數量增多後就不太合適,我們可以結合grains和pillar來進行調用:

[root@server1 apache]# vim init.sls
[root@server1 apache]# cat init.sls 
apache:
  pkg.installed:
    - pkgs:
      - {{ pillar['webserver'] }}
  service.running:
    - name: httpd
    - reload: true
    - enable: true
    - watch:
      - file: /etc/httpd/conf/httpd.conf

/etc/httpd/conf/httpd.conf:
  file.managed:
    - source: salt://apache/httpd.conf
    - template: jinja
    - context:
      bind: {{ grains['ipv4'] }}
      port: 80

但是這種方式調用時,grains['ipv4']是個列表:

[root@server1 apache]# salt server3 grains.item ipv4
server3:
    ----------
    ipv4:
        - 127.0.0.1
        - 172.25.63.3

在推送時就會有問題:

[root@server1 apache]# salt server3 state.sls apache

在這裏插入圖片描述可以看出apache並不支持列表的形式,因此我們可以使用切片(與python的切片方法相同):

[root@server1 apache]# vim init.sls
[root@server1 apache]# cat init.sls 
apache:
  pkg.installed:
    - pkgs:
      - {{ pillar['webserver'] }}
  service.running:
    - name: httpd
    - reload: true
    - enable: true
    - watch:
      - file: /etc/httpd/conf/httpd.conf

/etc/httpd/conf/httpd.conf:
  file.managed:
    - source: salt://apache/httpd.conf
    - template: jinja
    - context:
      bind: {{ grains['ipv4'][-1] }}
      port: 80

再次推送:

[root@server1 apache]# salt server3 state.sls apache

在這裏插入圖片描述可以看出推送成功。

我們也可以將port變量調用pillar的值:

[root@server1 apache]# vim init.sls 
[root@server1 apache]# cat init.sls 
apache:
  pkg.installed:
    - pkgs:
      - {{ pillar['webserver'] }}
  service.running:
    - name: httpd
    - reload: true
    - enable: true
    - watch:
      - file: /etc/httpd/conf/httpd.conf

/etc/httpd/conf/httpd.conf:
  file.managed:
    - source: salt://apache/httpd.conf
    - template: jinja
    - context:
      bind: {{ grains['ipv4'][-1] }}
      port: {{ pillar['port'] }}

推送:

[root@server1 apache]# salt server3 state.sls apache

在這裏插入圖片描述成功推送。

此時更改pillar的信息:

[root@server1 pillar]# vim web.sls 
[root@server1 pillar]# cat web.sls 
{% if grains['fqdn'] == 'server3' %}
webserver: httpd
port: 8080
{% elif grains['fqdn'] == 'server2' %}
webserver: nginx
port: 80
{% endif %}

將server3的端口改爲8080,推送:

[root@server1 apache]# salt server3 state.sls apache

在server3查看端口:

[root@server3 ~]# netstat -antlpe | grep 8080
tcp        0      0 172.25.63.3:8080        0.0.0.0:*               LISTEN      0          45425      3749/httpd  

可以看出已經更改爲8080.

當然也可以直接在配置文件中調用grains或者pillar:

[root@server1 apache]# vim init.sls 
[root@server1 apache]# cat init.sls 
apache:
  pkg.installed:
    - pkgs:
      - {{ pillar['webserver'] }}
  service.running:
    - name: httpd
    - reload: true
    - enable: true
    - watch:
      - file: /etc/httpd/conf/httpd.conf

/etc/httpd/conf/httpd.conf:
  file.managed:
    - source: salt://apache/httpd.conf
    - template: jinja				#注意需要啓用jinja模板
[root@server1 apache]# vim httpd.conf 
[root@server1 apache]# cat -n httpd.conf | grep 42
    42	Listen {{ grains['ipv4'][-1] }}:{{ pillar['port'] }}

然後推送:

[root@server1 apache]# salt server3 state.sls apache

在這裏插入圖片描述
可以看出推送成功。

import方式

第三種方式爲import方式,可在state文件之間共享:

定義變量文件:

[root@server1 salt]# vim lib.sls
[root@server1 salt]# cat lib.sls 
{% set port = 80 %}

導入模板文件:

[root@server1 salt]# cd apache/
[root@server1 apache]# vim httpd.conf 
[root@server1 apache]# head -1 httpd.conf 
{% from 'lib.sls' import port %}

調用變量:

 [root@server1 apache]# cat -n httpd.conf | grep 43
    43	Listen {{ grains['ipv4'][-1] }}:{{ port }}

推送:

[root@server1 apache]# salt server3 state.sls apache

在server3查看可以看出配置已經生效:

[root@server3 ~]# netstat -antlpe | grep httpd
tcp        0      0 172.25.63.3:80          0.0.0.0:*               LISTEN      0          45983      3749/httpd    

但是我們先在考慮一個問題,如果我們不僅在init文件中定義了變量port,還用import方式定義了變量,當調用的時候哪個優先級高呢,通過實驗看下結果:

在init文件中定義變量port爲8080(這裏調用的pillar,server3的pillar port爲8080):

[root@server1 apache]# vim init.sls 
[root@server1 apache]# cat init.sls 
apache:
  pkg.installed:
    - pkgs:
      - {{ pillar['webserver'] }}
  service.running:
    - name: httpd
    - reload: true
    - enable: true
    - watch:
      - file: /etc/httpd/conf/httpd.conf

/etc/httpd/conf/httpd.conf:
  file.managed:
    - source: salt://apache/httpd.conf
    - template: jinja
    - context:
#      bind: {{ grains['ipv4'][-1] }}
      port: {{ pillar['port'] }}

import的方式我們上面已經設置過了,因此我們直接推送查看結果:

[root@server1 apache]# salt server3 state.sls apache

server3查看:

[root@server3 ~]# netstat -antlpe | grep httpd
tcp        0      0 172.25.63.3:80          0.0.0.0:*               LISTEN      0          45983      3749/httpd         

可以看出通過import的方式導入的變量優先級高於在init文件中定義的變量,原因是在運行的時候最後讀取的是import方式導入的變量。

注意:一般習慣將變量都定義在init文件中,然後在其他文件中引用即可。

三、Jinja模板應用之部署keepalived高可用集羣

我們這裏準備將server2設置爲master節點,server3爲backup節點,vip爲172.25.63.100

首先編輯init文件在節點安裝keepalived:

[root@server1 salt]# mkdir keepalived
[root@server1 salt]# cd keepalived/
[root@server1 keepalived]# vim init.sls
[root@server1 keepalived]# cat init.sls 
install-kp:
  pkg.installed:
    - name: keepalived

推送測試:

[root@server1 keepalived]# salt '*' state.sls keepalived

在這裏插入圖片描述安裝成功。

繼續編輯init文件,設置配置文件以及服務:

[root@server1 keepalived]# vim init.sls 
[root@server1 keepalived]# cat init.sls 
install-kp:
  pkg.installed:
    - name: keepalived
  
  file.managed:
    - name: /etc/keepalived/keepalived.conf
    - source: salt://keepalived/keepalived.conf

  service.running:
    - name: keepalived
    - reload: true
    - watch:
      - file: install-kp

複製配置文件:

[root@server1 keepalived]# scp server2:/etc/keepalived/keepalived.conf .

[root@server1 keepalived]# ls
init.sls  keepalived.conf

編輯配置文件:

[root@server1 keepalived]# vim keepalived.conf 
[root@server1 keepalived]# cat keepalived.conf 
! Configuration File for keepalived

global_defs {
   notification_email {
     root@localhost
   }
   notification_email_from keepalived@localhost
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id LVS_DEVEL
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        172.25.63.100
    }
}

可以看出配置文件中的角色爲master,優先級爲100,vip爲172.25.63.100。

推送給server2測試:

[root@server1 keepalived]# salt server2 state.sls keepalived

在這裏插入圖片描述推送成功。

在server2查看日誌:

[root@server2 mnt]# tail -20 /var/log/messages 

在這裏插入圖片描述可以看出是master的身份,查看ip:
在這裏插入圖片描述可以看出已經獲得了虛擬ip。

server2部署成功,但是現在有一個問題,server3(backup節點)的配置文件和server2不同,不能直接推送,我們可以結合jinja模板與pillar實現不同主機的配置文件不同。

更改配置文件:

[root@server1 keepalived]# vim keepalived.conf 
[root@server1 keepalived]# cat keepalived.conf 
! Configuration File for keepalived

global_defs {
   notification_email {
     root@localhost
   }
   notification_email_from keepalived@localhost
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id LVS_DEVEL
}

vrrp_instance VI_1 {
    state {{ STATE }}
    interface eth0
    virtual_router_id 51
    priority {{ PRI }}
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        {{ VIP }}
    }
}

其中STATE、PRI、VIP爲變量,接下來我們就需要定義pillar變量:

[root@server1 keepalived]# cd /srv/pillar/
[root@server1 pillar]# vim web.sls 
[root@server1 pillar]# cat web.sls 
{% if grains['fqdn'] == 'server2' %}
kpstate: MASTER
kppri: 100
{% elif grains['fqdn'] == 'server3' %}
kpstate: BACKUP
kppri: 50
{% endif %}

在init文件中將pillar變量賦值給配置文件中的三個變量:

[root@server1 pillar]# cd -
/srv/salt/keepalived
[root@server1 keepalived]# vim init.sls 
[root@server1 keepalived]# cat init.sls 
install-kp:
  pkg.installed:
    - name: keepalived
  
  file.managed:
    - name: /etc/keepalived/keepalived.conf
    - source: salt://keepalived/keepalived.conf
    - template: jinja
    - context:
      STATE: {{ pillar['kpstate'] }}			#將pillar變量賦值給配置文件中的三個變量
      PRI: {{ pillar['kppri'] }}
      VIP: {{ pillar['vip'] }}

  service.running:
    - name: keepalived
    - reload: true
    - watch:
      - file: install-kp

現在可以直接推送給兩個節點:

[root@server1 keepalived]# salt '*' state.sls keepalived

在這裏插入圖片描述配置成功。

在server2查看:

[root@server2 mnt]# tail -20 /var/log/messages 
.......
May 18 23:34:05 server2 Keepalived_vrrp[3688]: VRRP_Instance(VI_1) Transition to MASTER STATE

可以看出已經獲得vip:
[root@server2 mnt]# ip addr
......
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:be:bf:d2 brd ff:ff:ff:ff:ff:ff
    inet 172.25.63.2/24 brd 172.25.63.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet 172.25.63.100/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:febe:bfd2/64 scope link 
       valid_lft forever preferred_lft forever

在server3查看:

[root@server3 ~]# tail -20 /var/log/messages
......
May 18 23:34:04 server3 Keepalived_vrrp[4100]: VRRP_Instance(VI_1) Entering BACKUP STATE
May 18 23:34:04 server3 Keepalived_vrrp[4100]: VRRP_Instance(VI_1) removing protocol VIPs.

可以看出已經部署完成。

接下來進行測試:

關閉server2的keepalived:

[root@server2 mnt]# systemctl stop keepalived

查看server3已經自動切換成了master節點並且得到了vip:

在這裏插入圖片描述
在這裏插入圖片描述此時在server1再次進行推送:

[root@server1 keepalived]# salt '*' state.sls keepalived

推送後由於server2的服務會被啓動,且優先級(100)高於serve3(50),因此server2又會變成master節點:

在這裏插入圖片描述在這裏插入圖片描述

高可用集羣成功部署。

也可以不使用pillar,直接將變量定義在init文件中,比如下面這種寫法和上面的效果是相同的:

[root@server1 keepalived]# vim init.sls 
[root@server1 keepalived]# 
[root@server1 keepalived]# cat init.sls 
install-kp:
  pkg.installed:
    - name: keepalived
  
  file.managed:
    - name: /etc/keepalived/keepalived.conf
    - source: salt://keepalived/keepalived.conf
    - template: jinja
    - context:
        {% if grains['fqdn'] == 'server2' %}
        STATE: MASTER
        PRI: 100
        VIP: 172.25.63.100
        {% elif grains['fqdn'] == 'server3' %}
        STATE: BACKUP
        PRI: 50
        VIP: 172.25.63.100
        {% endif %}


  service.running:
    - name: keepalived
    - reload: true
    - watch:
      - file: install-kp

當節點數量多時還是推薦結合pillar的方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章