Hello everyone, I am from 9 in the morning to 12 in the evening, and I am currently doing operation and maintenance related work. Blogging is for accumulation, I hope everyone will make progress together!
My homepage: 9 am to 12 pm
Column name: Ansible from entry to proficiency and determined to become an ansible boss
ansible templates
Understanding of templates
How to use the template
- A text file with nested scripts (written in a templating programming language)
- The jinja2 language, using literals, has the following form
string: use single quotes or double quotes
numbers: integers,
lists of floating point numbers: [item1, item2,…]
tuples; (item1, item2,…)
dictionaries: {key1:value1 ,key2:value2,...}
Boolean: true/false - Arithmetic operations: +, -, *, /, //, %, **
- Comparison operations: ==, !=, >, >=, <, <=
- Logical operations: and, or, not
- Flow Expressions: For If When
directory of templates
It is generally recommended to create a templates directory under the ansible directory, parallel to the playbook script
help document
[root@zhaoyj ansible]# ansible-doc -s template
- name: Template a file out to a remote server
template:
attributes: # The attributes the resulting file or directory should have. To get supported flags look at the man page for `chattr' on the target
system. This string should contain the attributes in the same order as the one displayed by `lsattr'. The
`=' operator is assumed as default, otherwise `+' or `-' operators need to be included in the string.
backup: # Create a backup file including the timestamp information so you can get the original file back if you somehow clobbered it incorrectly.
block_end_string: # The string marking the end of a block.
block_start_string: # The string marking the beginning of a block.
dest: # (required) Location to render the template to on the remote machine.
follow: # Determine whether symbolic links should be followed. When set to `yes' symbolic links will be followed, if they exist. When set to `no'
symbolic links will not be followed. Previous to Ansible 2.4, this was hardcoded as `yes'.
force: # Determine when the file is being transferred if the destination already exists. When set to `yes', replace the remote file when contents
are different than the source. When set to `no', the file will only be transferred if the destination does
not exist.
group: # Name of the group that should own the file/directory, as would be fed to `chown'.
lstrip_blocks: # Determine when leading spaces and tabs should be stripped. When set to `yes' leading spaces and tabs are stripped from the start of a
line to a block. This functionality requires Jinja 2.7 or newer.
mode: # The permissions the resulting file or directory should have. For those used to `/usr/bin/chmod' remember that modes are actually octal
numbers. You must either add a leading zero so that Ansible's YAML parser knows it is an octal number
(like `0644' or `01777') or quote it (like `'644'' or `'1777'') so Ansible receives a string and can do
its own conversion from string into number. Giving Ansible a number without following one of these rules
will end up with a decimal number which will have unexpected results. As of Ansible 1.8, the mode may be
specified as a symbolic mode (for example, `u+rwx' or `u=rw,g=r,o=r').
newline_sequence: # Specify the newline sequence to use for templating files.
output_encoding: # Overrides the encoding used to write the template file defined by `dest'. It defaults to `utf-8', but any encoding supported by python
can be used. The source template file must always be encoded using `utf-8', for homogeneity.
owner: # Name of the user that should own the file/directory, as would be fed to `chown'.
selevel: # The level part of the SELinux file context. This is the MLS/MCS attribute, sometimes known as the `range'. When set to `_default', it
will use the `level' portion of the policy if available.
serole: # The role part of the SELinux file context. When set to `_default', it will use the `role' portion of the policy if available.
Manage nginx with templates
Simulate an nginx template file
cp /etc/nginx/nginx.conf /root/ansible/templates/nginx.conf.j2
Write yml script
[root@zhaoyj ansible]# cat templates.yml
---
- hosts: test
remote_user: root
tasks:
- name: install pkg
yum: name=nginx
- name: copy template
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
- name: start service
service: name=nginx state=started enabled=yes
...
test-yml
[root@zhaoyj ansible]# ansible-playbook -C templates.yml
Execute (an error is reported here, because the host computer has a certificate)
[root@zhaoyj ansible]# ansible-playbook templates.yml
PLAY [test] ***********************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************************************************
ok: [192.168.6.249]
TASK [install pkg] ****************************************************************************************************************************************************************************************************
changed: [192.168.6.249]
TASK [copy template] **************************************************************************************************************************************************************************************************
changed: [192.168.6.249]
TASK [start service] **************************************************************************************************************************************************************************************************
fatal: [192.168.6.249]: FAILED! => {
"changed": false, "msg": "Unable to start service nginx: Job for nginx.service failed because the control process exited with error code. See \"systemctl status nginx.service\" and \"journalctl -xe\" for details.\n"}
PLAY RECAP ************************************************************************************************************************************************************************************************************
192.168.6.249 : ok=3 changed=2 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
Modify the number of work of nginx
Modify the number of work of nginx and generate according to the actual cpu
Ansible cpu variable view
[root@zhaoyj ansible]# ansible test -m setup |grep "cpu"
"ansible_processor_vcpus": 8,
edit template file
[root@zhaoyj templates]# vim nginx.conf.j2
user nginx;
worker_processes {
{
ansible_processor_vcpus*2 }};
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
Modify the template script
[root@zhaoyj ansible]# cat templates.yml
---
- hosts: test
remote_user: root
tasks:
- name: install pkg
yum: name=nginx
- name: copy template
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart service
- name: start service
service: name=nginx state=started enabled=yes
handlers:
- name: restart service
service: name=nginx state=restarted
...
execute again
[root@zhaoyj ansible]# ansible-playbook templates.yml
PLAY [test] ***********************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************************************************
ok: [192.168.6.249]
TASK [install pkg] ****************************************************************************************************************************************************************************************************
ok: [192.168.6.249]
TASK [copy template] **************************************************************************************************************************************************************************************************
changed: [192.168.6.249]
TASK [start service] **************************************************************************************************************************************************************************************************
changed: [192.168.6.249]
RUNNING HANDLER [restart service] *************************************************************************************************************************************************************************************
changed: [192.168.6.249]
PLAY RECAP ************************************************************************************************************************************************************************************************************
192.168.6.249 : ok=5 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Check whether the configuration file reads variables
192.168.6.249 | CHANGED | rc=0 >>
worker_processes 16;
[root@zhaoyj ansible]# ansible test -m shell -a "ps aux|grep nginx"
192.168.6.249 | CHANGED | rc=0 >>
root 16342 0.0 0.0 49072 1168 ? Ss 17:16 0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx 16343 0.0 0.0 49460 1900 ? S 17:16 0:00 nginx: worker process
nginx 16344 0.0 0.0 49460 1900 ? S 17:16 0:00 nginx: worker process
nginx 16345 0.0 0.0 49460 1900 ? S 17:16 0:00 nginx: worker process
nginx 16346 0.0 0.0 49460 1900 ? S 17:16 0:00 nginx: worker process
nginx 16347 0.0 0.0 49460 1900 ? S 17:16 0:00 nginx: worker process
nginx 16348 0.0 0.0 49460 1900 ? S 17:16 0:00 nginx: worker process
nginx 16349 0.0 0.0 49460 1900 ? S 17:16 0:00 nginx: worker process
nginx 16350 0.0 0.0 49460 1900 ? S 17:16 0:00 nginx: worker process
nginx 16351 0.0 0.0 49460 1900 ? S 17:16 0:00 nginx: worker process
nginx 16352 0.0 0.0 49460 1900 ? S 17:16 0:00 nginx: worker process
nginx 16353 0.0 0.0 49460 1900 ? S 17:16 0:00 nginx: worker process
nginx 16354 0.0 0.0 49460 1900 ? S 17:16 0:00 nginx: worker process
nginx 16355 0.0 0.0 49460 1900 ? S 17:16 0:00 nginx: worker process
nginx 16356 0.0 0.0 49460 1900 ? S 17:16 0:00 nginx: worker process
nginx 16357 0.0 0.0 49460 1900 ? S 17:16 0:00 nginx: worker process
nginx 16358 0.0 0.0 49460 1636 ? S 17:16 0:00 nginx: worker process
root 17699 0.0 0.0 113284 1204 pts/1 S+ 17:20 0:00 /bin/sh -c ps aux|grep nginx
root 17701 0.0 0.0 112816 960 pts/1 S+ 17:20 0:00 grep nginx
use of when
Conditional test:
If you need to use variables, facts or the execution results of previous tasks as the prerequisite for the execution of a certain task, you need to use conditional tests, which are implemented through the when statement and used in tasks. The grammatical format of jinja2 when statement
:
in Add a when clause after the task to use the conditional test. The when statement supports Jinja2 syntax.
For example:
View version number
[root@zhaoyj ansible]# ansible test -m setup -a "filter="*distribution*""
192.168.6.249 | SUCCESS => {
"ansible_facts": {
"ansible_distribution": "CentOS",
"ansible_distribution_file_parsed": true,
"ansible_distribution_file_path": "/etc/redhat-release",
"ansible_distribution_file_variety": "RedHat",
"ansible_distribution_major_version": "7",
"ansible_distribution_release": "Core",
"ansible_distribution_version": "7.9",
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}
Record "ansible_distribution_major_version": "7", set when the system is equal to 7, copy the configuration file
and modify the template file
[root@zhaoyj ansible]# cat templates.yml
---
- hosts: test
remote_user: root
tasks:
- name: install pkg
yum: name=nginx
- name: copy template
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
when: ansible_distribution_major_version == "7"
notify: restart service
- name: start service
service: name=nginx state=started enabled=yes
handlers:
- name: restart service
service: name=nginx state=restarted
...
Execute the script
[root@zhaoyj ansible]# ansible-playbook templates.yml
PLAY [test] ***********************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************************************************
ok: [192.168.6.249]
TASK [install pkg] ****************************************************************************************************************************************************************************************************
ok: [192.168.6.249]
TASK [copy template] **************************************************************************************************************************************************************************************************
changed: [192.168.6.249]
TASK [start service] **************************************************************************************************************************************************************************************************
changed: [192.168.6.249]
RUNNING HANDLER [restart service] *************************************************************************************************************************************************************************************
changed: [192.168.6.249]
PLAY RECAP ************************************************************************************************************************************************************************************************************
192.168.6.249 : ok=5 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@zhaoyj ansible]# ansible test -m shell -a "cat /etc/nginx/nginx.conf|grep centos"
192.168.6.249 | CHANGED | rc=0 >>
#centos 7
Nested variable passing
We support passing variables when making templates, and can pass a single variable, or pass it in a list, for example:
---
- hosts: test
remote_user: root
tasks:
- name: create some groups
group: name={
{
item }}
with_items:
- group1
- group2
- group3
- name: create some user
user: name={
{
item.name }} group={
{
item.group }}
with_items:
- {
name: 'name1', group: 'group1' }
- {
name: 'name2', group: 'group2' }
- {
name: 'name3', group: 'group3' }
...
implement
```bash
[root@192-168-6-228 ansible]# ansible-playbook test.yml
PLAY [test] ****************************************************************************************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************************************************************************
ok: [192.168.6.223]
TASK [create some groups] **************************************************************************************************************************************************************
changed: [192.168.6.223] => (item=group1)
changed: [192.168.6.223] => (item=group2)
changed: [192.168.6.223] => (item=group3)
TASK [create some user] ****************************************************************************************************************************************************************
changed: [192.168.6.223] => (item={
u'group': u'group1', u'name': u'name1'})
changed: [192.168.6.223] => (item={
u'group': u'group2', u'name': u'name2'})
changed: [192.168.6.223] => (item={
u'group': u'group3', u'name': u'name3'})
PLAY RECAP *****************************************************************************************************************************************************************************
192.168.6.223 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Validation results
[root@192-168-6-228 ansible]# ansible test -m shell -a "getent passwd"|grep name
name1:x:1003:1003::/home/name1:/bin/bash
name2:x:1004:1004::/home/name2:/bin/bash
name3:x:1005:1005::/home/name3:/bin/bash
[root@192-168-6-228 ansible]# ansible test -m shell -a "getent group|grep 100[3-5]"
192.168.6.223 | CHANGED | rc=0 >>
group1:x:1003:
group2:x:1004:
group3:x:1005:
FOR Loop and Conditional Judgment
for loop
Example of format **(% for vhost in nginx_vhosts %)**
:
[root@192-168-6-228 ansible]# cat test1.yml
---
- hosts: test
remote_user: root
vars:
ports:
- 81
- 82
- 83
tasks:
- name: copy file
template: src=port.j2 dest=/tmp/port
...
write a template file
[root@192-168-6-228 ansible]# cat templates/port.j2
{
% for port in ports %}
server{
listen {
{
port }}
}
{
% endfor %}
Note: the in ports in the for loop, the ports need to be executed as defined in the script
[root@192-168-6-228 ansible]# ansible-playbook test1.yml
PLAY [test] ****************************************************************************************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************************************************************************
ok: [192.168.6.223]
TASK [copy file] ***********************************************************************************************************************************************************************
changed: [192.168.6.223]
PLAY RECAP *****************************************************************************************************************************************************************************
192.168.6.223 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Results view
[root@192-168-6-228 ansible]# ansible test -m shell -a "cat /tmp/port"
192.168.6.223 | CHANGED | rc=0 >>
server{
listen 81
}
server{
listen 82
}
server{
listen 83
}
It can also be changed to a dictionary to loop, for example:
[root@192-168-6-228 ansible]# cat test1.yml
---
- hosts: test
remote_user: root
vars:
ports:
- listen_port: 81
- listen_port: 82
- listen_port: 83
tasks:
- name: copy file
template: src=port.j2 dest=/tmp/port
...
template modification
[root@192-168-6-228 ansible]# cat templates/port.j2
{
% for port in ports %}
server{
listen {
{
port.listen_port }}
}
{
% endfor %}
Delete the previous file first to see the effect
[root@192-168-6-228 ansible]# ansible test -m shell -a "rm -f /tmp/port"
[WARNING]: Consider using the file module with state=absent rather than running 'rm'. If you need to use command because file is insufficient you can add 'warn: false' to this
command task or set 'command_warnings=False' in ansible.cfg to get rid of this message.
192.168.6.223 | CHANGED | rc=0 >>
[root@192-168-6-228 ansible]# ansible test -m shell -a "cat /tmp/port"
192.168.6.223 | FAILED | rc=1 >>
cat: /tmp/port: No such file or directorynon-zero return code
[root@192-168-6-228 ansible]# ansible-playbook test1.yml
PLAY [test] ****************************************************************************************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************************************************************************
ok: [192.168.6.223]
TASK [copy file] ***********************************************************************************************************************************************************************
changed: [192.168.6.223]
PLAY RECAP *****************************************************************************************************************************************************************************
192.168.6.223 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@192-168-6-228 ansible]# ansible test -m shell -a "cat /tmp/port"
192.168.6.223 | CHANGED | rc=0 >>
server{
listen 81
}
server{
listen 82
}
server{
listen 83
}
is consistent with the first method
if judgment
The if judgment is also supported in the template. For example, to modify the above template, when the listen_port variable is empty, it will not be executed
---
- hosts: test
remote_user: root
vars:
ports:
- listen_port: 81
- listen_port: 82
- listen_port:
tasks:
- name: copy file
template: src=port.j2 dest=/tmp/port
...
template modification
[root@192-168-6-228 ansible]# cat templates/port.j2
{
% for port in ports %}
server{
{
% if port.listen_port is none %}
listen {
{
port.listen_port }}
{
% endif %}
}
{
% endfor %}
If if is none, it means that the parameter is defined but the value is empty, and it is true.
If it is defined, it means that the parameter is defined as true.
If it is undefined, it means that the parameter is not defined as true.
View the results
[root@192-168-6-228 ansible]# ansible-playbook test3.yml
PLAY [test] ****************************************************************************************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************************************************************************
ok: [192.168.6.223]
TASK [copy file] ***********************************************************************************************************************************************************************
changed: [192.168.6.223]
PLAY RECAP *****************************************************************************************************************************************************************************
192.168.6.223 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@192-168-6-228 ansible]# ansible test -m shell -a "cat /tmp/port"
192.168.6.223 | CHANGED | rc=0 >>
server{
listen
}