Note: part of the code of the article case will be misaligned. Please pay attention to the format alignment when using!!
Chapter 3 yaml syntax and playbook writing
Ansible's playbook adopts yaml syntax, so before learning ansible playbook, it is necessary to understand and master the grammar format of yaml. Only by practicing and mastering the writing method of playbook can ansible be used smoothly.
3.1 yaml syntax
Here is an example of playbook to illustrate the syntax of yaml:
--- - name: Install Mysql package yum: name={{ item }} state=present with_items: - mysql-server - MySQL-python - libselinux-python - libsemanage-python #Install mysql service - name: Configure SELinux to start mysql on any port seboolean: name=mysql_connect_any state=true persistent=yes when: ansible_selinux.status == "enabled" - name: Create Mysql configuration file template: src=my.cnf.j2 dest=/etc/my.cnf notify: - restart mysql #Configure my.cnf and restart mysql service - name: Start Mysql Service service: name=mysqld state=started enabled=yes
1. Yaml files start with - -- to indicate that this is a yaml file;
2. In yaml, the character "ා" is used as the comment character. It can comment the whole line or the content after the character "ා" in the line;
3. Strings in yaml usually don't need to be quoted, even if they contain some special characters. However, in some cases, quotation marks must be added to avoid errors in yaml reading. The most common is to use quotation marks when referencing variables;
4. Finally, it is about the writing format of Boolean value, that is, the expression of true/false. The boolean type in playbook is very flexible, which can be divided into the following two situations:
A: Module parameters: the Boolean value is parsed as a string by ansible.
It accepts the following options: yes/on/1/true/no/off/0/false, which is parsed by ansible.
B: Non module parameters: the Boolean value is parsed by the yaml interpreter. Accepts case insensitive true/yes/on/y/false/no/off/n. For example, enabled=yes above.
For the use of Boolean values in playbook, it is recommended to follow the official specification of ansible:
The Boolean parameter of the module is yes/no, and the Boolean parameter of the non module is True/False
playbook basic components
Hosts: the target host to run the task
Remote user: the user who performs tasks on a remote host
tasks: task list
handlers: tasks, unlike tasks, are triggered only when the notification is received
templates: text files using the template language, using jinja2 syntax.
Variables: variables, variable replacement {{variable_name}}}
3.2 list
The use of lists in playbook is very important. It uses "-" (minus sign plus one or more spaces) as list items, that is, arrays in json. For example, the above example:
- mariadb-server
- mariadb
- MySQL-python
- libselinux-python
- libsemanage-python
The above list is equivalent to the following json list:
[
"mariadb-server",
"mariadb",
"MySQL-python",
"libselinux-python",
"libsemanage-python"
]
It is also equivalent to the following inline forms:
[mariadb-server,mariadb,MySQL-python,libselinux-python,libsemanage-python]
Specifically, in ansible playbook, a list describes a local environment. It does not have to have a name or start from the same attribute. As long as you use "-", it means that you define a range, and the items in the range belong to the list.3.3 dictionary
In playbook, virtual content can be written in the form of dictionary, while physical, action and object content should be defined as list
The writing mode of dictionary is as follows: nginx? Port: 80
If it can't be written in key/value format and is an entity file, it should be written as a list, such as: - nginx_port.yml3.4 branch writing
There are three ways to continue lines in playbook:
(1) Use the greater than sign after key:.
(2) Use a vertical bar after "key:". This way you can write many lines like a script.
(3) Multi indent.
For example:
--- #Identification - hosts: localhost tasks: - shell: echo 2 >>/tmp/test.txt creates=/tmp/haha.txt # More indents than module shell - shell: > # Use the greater than sign after "key:" echo 2 >>/tmp/test.txt creates=/tmp/haha.txt - shell: | # Specify multiline commands echo 2 >>/tmp/test.txt echo 3 >>/tmp/test.txt args: creates: /tmp/haha.txt
3.5 transfer parameters to modules
Generally speaking, the parameters of the module are in the format of key=value. There are three ways to pass them:
(1) After writing directly to the module, the format "key=value" is required at this time.
(2) It is written as a dictionary, i.e. "key: value". Writing requires multiple indents.
(3) Use the built-in property args, and then indent multiple levels to define the parameter list.
For example:
--- #Identification - hosts: localhost tasks: - yum: name=unix2dos state=installed # key=value passed directly - yum: name: unxi2dos state: installed # "key: value" dictionary format transfer - yum: args: # Pass using args name: unix2dos state:installed
3.6 relationship between playbook and play
A playbook can contain multiple plays. Each play contains at least two items: tasks and hosts.
It should be noted that in some cases, role is used in play, and the content of playbook does not seem to have tasks. In fact, the role itself has integrated playbook. At this time, no task is not a syntax error. But if you don't use role, the playbook must contain hosts and tasks.
3.7 when to use quotation marks in Playbook
Most of the definitions in playbook are list and dictionary contents. In most cases, you don't need to use quotation marks, but there are two special cases where you need to consider using quotation marks.
(1) When the brace "{}" appears;
(2) ':' when colons and spaces appear.
The reason why curly braces are surrounded by quotation marks is that when they are not used, they will be parsed into an inline dictionary by yaml, resulting in incorrect parsing or not executed according to the actual logic.
--- #Identification - hosts: localhost tasks: - shell: 'echo "{{inventory_hostname}}: haha"' register: hello - debug: 'msg="{{hello.stdout}}: heihei"'
3.8 use of template in Playbook
3.8.1 template
The variables in the module often use the built-in variables of the server itself. We can use the setup module to find the variable names we need:
#To find the remote server host name: [root@centos130 lnmp]# ansible 192.168.8.131 -m setup -a 'filter="ansible_fqdn"' 192.168.8.131 | SUCCESS => { "ansible_facts": { "ansible_fqdn": "centos131" }, "changed": false } #Find the number of cpu cores for the remote server: [root@centos130 lnmp]# ansible 192.168.8.131 -m setup |grep "cpu" "ansible_processor_vcpus": 1, #To view the operating system type of a remote server: [root@centos130 lnmp]# ansible 192.168.8.131 -m setup |grep "ansible_os_family" "ansible_os_family": "RedHat",
Introduction to module templates:
1. Modules are files, files and can be nested with scripts;
2. The module uses Jinja2 language and has the following forms:
(1) String: use single or double quotes
(2) Number: integer, floating point
(3) List: [item1,item2,...]
(4) No group: (item1,item2,...)
(5) Dictionary: {key1:value1,key2:value2,...}
(6) Boolean: true/false
3. Arithmetic operation: +, -, *, /, / / (rounding),% (rounding), * * (power)
4. Comparison operation: = =,! =, < and < =, > and >=
5. Logical operation: and, or, not
6. Expression: for, if, when
Note: the template module can only be used in ANSI ble playbook.
For example, the default worker process of nginx is auto, which is modified to the second power of the cpu core number of the server. At the same time, the port of nginx is obtained from the hosts list:
#Modify nginx.conf module file [root@centos130 ansible]# cat template/nginx.conf.j2 .... user nginx; worker_processes {{ ansible_processor_vcpus**2 }}; error_log /var/log/nginx/error.log; pid /run/nginx.pid; .... server { listen {{ nginx_port }} default_server; listen [::]:{{ nginx_port }} default_server; ..... #Modify the hosts list configuration [root@centos130 ansible]# cat hosts [web] 192.168.8.131 nginx_port #Write ansible Playbook [root@centos130 ansible]# cat testtemp.yml --- #Identification - hosts: web remote_user: root tasks: - name: install package 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 #Test execution: [root@centos130 ansible]# ansible-playbook -i hosts -C testtemp.yml #You can also add variables directly from the - e parameter command line: [root@centos130 ansible]# ansible-playbook -i hosts -e "http_port=99" testtemp.yml
3.8.2 use of when
1. Conditional test: if you need to use conditional test as the precondition of whether a task is executed or not according to variables, facts or the execution results of previous tasks, use the syntax format of jinja2 through when statement and task
2. When statement, add when clause after task to use conditional test
#For example: tasks: - name: shutdown RedHat flavored system command: /sbin/shutdown -h now when: ansible_os_family == "RedHat"
For example, the configuration file of nginx is introduced. According to different operating system versions, different nginx.conf module files are used:
#Modify nginx.conf module file [root@centos130 ansible]# ls template/ nginx.conf6.j2 nginx.conf7.j2 #Write ansible Playbook [root@centos130 ansible]# cat testwhen.yml --- #Identification - hosts: all remote_user: root tasks: - name: install package yum: name=nginx - name:copy template for centos7 template: src=nginx.conf7.j2 dest=/etc/nginx/nginx.conf when: ansible_distribution_major_version == "7" notify: restart service - name:copy template for centos6 template: src=nginx.conf6.j2 dest=/etc/nginx/nginx.conf when: ansible_distribution_major_version == "6" notify: restart service - name: start service service: name=nginx state=started enabled=yes handlers: - name: restart service service: name=nginx state=restarted #Test execution: [root@centos130 ansible]# ansible-playbook -i hosts -C testwhen.yml