template模板 
模板是一个文本文件,可以做为生成文件的模版,并且模板文件中还可嵌套jinja语法。
 
 
jinja2语言 
官方网站:
http://jinja.pocoo.org/ 
https://jinja.palletsprojects.com/en/2.11.x/ 
 
数据类型 jinja2 语言支持多种数据类型和操作: 
字符串:使用单引号或双引号, 
数字:整数,浮点数 
列表:[item1, item2, …] 
元组:(item1, item2, …) 
字典:{key1:value1, key2:value2, …} 
布尔型:true/false 
算术运算:+, -, *, /, //, %, ** 
比较操作:==, !=, >, >=, <, <= 
逻辑运算:and,or,not 
流表达式:For,If,When 
 
template template功能:可以根据和参考模块文件,动态生成相类似的配置文件,template文件必须存放于templates目录下,且命名为 .j2 结尾,yaml/yml 文件需和templates目录平级,目录结构如下示例:
1 2 3 4  ./ ├── temnginx.yml └── templates     └── nginx.conf.j2Copy to clipboardErrorCopied 
 
范例:利用template 同步nginx配置文件
1 2 3 4 5 6 7 8 9 [root@ansible ~] --- - hosts: web   remote_user: root   tasks:     - name: template config to remote hosts      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf  [root@ansible ~] 
 
template变更替换 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [root@ansible ~] [root@ansible ~] ...... worker_processes {{ ansible_processor_vcpus }}; ...... [root@ansible ~] --- - hosts: web   remote_user: root      tasks:     - name: install nginx       yum: name=nginx     - name: template config to remote hosts       template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf      - name: start service       service: name=nginx state=started enabled=yes         [root@ansible ~] 
 
常用的系统参数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ansible_all_ipv4_addresses:仅显示ipv4的信息 ansible_devices:仅显示磁盘设备信息 ansible_distribution:显示是什么系统,例:centos,suse等 ansible_distribution_version:仅显示系统版本 ansible_distribution_major_version:显示系统版本号(7) ansible_machine:显示系统类型,例:32位,还是64位 ansible_eth0:仅显示eth0的信息 ansible_hostname:仅显示主机名 ansible_kernel:仅显示内核版本 ansible_lvm:显示lvm相关信息 ansible_memtotal_mb:显示系统总内存 ansible_memfree_mb:显示可用系统内存 ansible_memory_mb:详细显示内存情况 ansible_swaptotal_mb:显示总的swap内存 ansible_swapfree_mb:显示swap内存的可用内存 ansible_mounts:显示系统磁盘挂载情况 ansible_processor:显示cpu个数(具体显示每个cpu的型号) ansible_processor_vcpus:显示cpu个数(只显示总的个数) ansible_python_version:显示python版本 
 
template算术运算 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [root@ansible ansible] worker_processes {{ ansible_processor_vcpus**3 }}; [root@ansible ansible] --- - hosts: websrvs   remote_user: root   tasks:     - name: install nginx       yum: name=nginx     - name: template config to remote hosts       template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf       notify: restart nginx     - name: start service       service: name=nginx state=started enabled=yes  handlers:     - name: restart nginx       service: name=nginx state=restarted [root@ansible ~] 
 
template中使用流程控制for和if 
template中也可以使用流程控制 for 循环和 if 条件判断,实现动态生成文件功能
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 --- - hosts: websrvs  remote_user: root  vars:    nginx_vhosts:      - 81      - 82      - 83  tasks:    - name: template config      template: src=nginx.conf2.j2 dest=/data/nginx.conf {% for  vhost in  nginx_vhosts %} server {    listen {{ vhost }} } {% endfor %} ansible-playbook -C templnginx2.yml --limit  192.168.15.8 server {    listen 81    } server {    listen 82    } server {    listen 83    } - hosts: websrvs  remote_user: root  vars:    nginx_vhosts:      - listen: 8080        server_name: "web1.oldboy.com"         root: "/var/www/nginx/web1/"       - listen: 8081        server_name: "web2.oldboy.com"         root: "/var/www/nginx/web2/"       - {listen: 8082, server_name: "web3.oldboy.com" , root:  "/var/www/nginx/web3/" } tasks:    - name: template config       template: src=nginx.conf4.j2 dest=/data/nginx4.conf            {% for  vhost in  nginx_vhosts %} server {    listen {{ vhost.listen }}    server_name {{ vhost.server_name }}    root {{ vhost.root }}   }{% endfor %}  [root@ansible ~] server {    listen 8080    server_name web1.oldboy.com    root /var/www/nginx/web1/   } server {    listen 8081    server_name web2.oldboy.com    root /var/www/nginx/web2/   } server {    listen 8082    server_name web3.oldboy.com    root /var/www/nginx/web3/   }Copy to clipboardErrorCopied 
 
playbook使用when when语句,可以实现条件测试。如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,通过在task后添加when子句即可使用条件测试,jinja2的语法格式。
1 2 3 4 tasks:   - name: "shut down CentOS 6 and Debian 7 systems"     command : /sbin/shutdown -t now    when: (ansible_facts['distribution' ] == "CentOS"  and ansible_facts['distribution_major_version' ] == "6" ) or (ansible_facts['distribution' ] == "Debian"  and ansible_facts['distribution_major_version' ] == "7" )Copy to clipboardErrorCopied 
 
playbook使用迭代with_items(loop) 迭代:当有需要重复性执行的任务时,可以使用迭代机制对迭代项的引用,固定内置变量名为”item”,要在task中使用with_items给定要迭代的元素列表
注意: ansible2.5版本后,可以用loop代替with_items
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 --- - hosts: websrvs  remote_user: root     tasks:     - name: add several users      user: name={{ item }} state=present groups=wheel      with_items:         - testuser1         - testuser2         - testuser3              - name: add several users       user: name=testuser1 state=present groups=wheel     - name: add several users       user: name=testuser2 state=present groups=wheel     - name: add several users       user: name=testuser3 state=present groups=wheel --- - hosts: 172.16.1.7   remote_user: root   tasks:     - name: stop service       shell: /etc/init.d/mysqld stop     - name: delete files and dir       file: path={{item}} state=absent       with_items:         - /usr/local /mysql         - /usr/local /mariadb-10.2.27-linux-x86_64         - /etc/init.d/mysqld         - /etc/profile.d/mysql.sh         - /etc/my.cnf         - /data/mysql     - name: delete user       user: name=mysql state=absent remove=yesCopy to clipboardErrorCopied 
 
迭代嵌套子变量: 在迭代中,还可以嵌套子变量,关联多个变量在一起使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 --- - hosts: websrvs   remote_user: root      tasks:     - name: add some groups       group: name={{ item }} state=present       with_items:         - nginx         - mysql         - apache     - name: add some users       user: name={{ item.name }} group={{ item.group }} state=present       with_items:         - { name: 'nginx' , group: 'nginx'  }         - { name: 'mysql' , group: 'mysql'  }         - { name: 'apache' , group: 'apache'  }Copy to clipboardErrorCopied 
 
管理节点过多导致的超时问题解决方法 
默认情况下,Ansible将尝试并行管理playbook中所有的机器。对于滚动更新用例,可以使用serial关键字定义Ansible一次应管理多少主机,还可以将serial关键字指定为百分比,表示每次并行执行的主机数占总数的比例
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 --- - hosts: all   serial: 2     gather_facts: False   tasks:     - name: task one   comand: hostname     - name: task two       command : hostname - name: test  serail   hosts: all   serial: "20%"     
 
角色是ansible自1.2版本引入的新特性,用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中
运维复杂的场景:建议使用 roles,代码复用度高
roles:多个角色的集合目录, 可以将多个的role,分别放至roles目录下的独立子目录中,如下示例
1 2 3 4 5 roles/  mysql/  nginx/  tomcat/  redis/Copy to clipboardErrorCopied 
 
默认roles存放路径
1 2 3 /root/.ansible/roles /usr/share/ansible/roles /etc/ansible/rolesCopy to clipboardErrorCopied 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ├── nginx -------------role1名称 │   ├── defaults  ---------必须存在的目录,存放默认的变量,模板文件中的变量就是引用自这里。defaults中的变量优先级最低,通常我们可以临时指定变量来进行覆盖 │   │   └── main.yml │   ├── files -------------ansible中unarchive、copy等模块会自动来这里找文件,从而我们不必写绝对路径,只需写文件名 │   │   ├── mysql.tar.gz │   │   └── nginx.tar.gz │   ├── handlers -----------存放tasks中的notify指定的内容 │   │   └── main.yml │   ├── meta │   ├── tasks --------------存放playbook的目录,其中main.yml是主入口文件,在main.yml中导入其他yml文件,要采用import_tasks关键字,include要弃用了 │   │   ├── install.yml │   │   └── main.yml -------主入口文件 │   ├── templates ----------存放模板文件。template模块会将模板文件中的变量替换为实际值,然后覆盖到客户机指定路径上 │   │   └── nginx.conf.j2 │   └── varsCopy to clipboardErrorCopied 
 
files/ :存放由copy或script模块等调用的文件
 
templates/:template模块查找所需要模板文件的目录
 
tasks/:定义task,role的基本元素,至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
 
handlers/:至少应该包含一个名为main.yml的文件;此目录下的其它的文件需要在此文件中通过
 
include进行包含
 
vars/:定义变量,至少应该包含一个名为main.yml的文件;此目录下的其它的变量文件需要在此文件中通过include进行包含
 
meta/:定义当前角色的特殊设定及其依赖关系,至少应该包含一个名为main.yml的文件,其它文件需在此文件中通过include进行包含
 
default/:设定默认变量时使用此目录中的main.yml文件,比vars的优先级低
 
 
创建role的步骤
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1 创建以roles命名的目录 2 在roles目录中分别创建以各角色名称命名的目录,如mysql等 3 在每个角色命名的目录中分别创建files、handlers、tasks、templates和vars等目录;用不到的目录可以创建为空目录,也可以不创建 4 在每个角色相关的子目录中创建相应的文件,如 tasks/main.yml,templates/nginx.conf.j2 5 在playbook文件中,调用需要的角色 [root@m01 package] [root@m01 package] . └── roles     └── nginx         ├── files         ├── handlers         ├── meta         ├── tasks         ├── templates         └── vars Copy to clipboardErrorCopied 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 nginx-role.yml  roles/ └── nginx       ├── files      │   └── main.yml       ├── tasks      │   ├── groupadd.yml       │   ├── install.yml       │   ├── main.yml       │   ├── restart.yml       │   └── useradd.yml       └── vars           └── main.ymlCopy to clipboardErrorCopied 
 
1 2 3 4 5 6 7 --- - hosts: web   remote_user: root   roles:     - mysql     - memcached     - nginx  Copy to clipboardErrorCopied 
 
1 2 3 4 5 6 --- - hosts: all   remote_user: root   roles:     - mysql     - { role: nginx, username: nginx }Copy to clipboardErrorCopied 
 
1 2 3 4 5 --- - hosts: all   remote_user: root   roles:     - { role: nginx, username: nginx, when: ansible_distribution_major_version == '7'  }Copy to clipboardErrorCopied 
 
1 2 3 4 5 6 7 8 --- - hosts: appsrvs   remote_user: root   roles:     - { role: nginx ,tags: [ 'nginx' , 'web'  ] ,when: ansible_distribution_major_version == "6"  }     - { role: httpd ,tags: [ 'httpd' , 'web'  ] }     - { role: mysql ,tags: [ 'mysql' , 'db'  ] }     - { role: mariadb ,tags: [ 'mariadb' , 'db'  ] }Copy to clipboardErrorCopied 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 [root@ansible ~]    [root@ansible ~] [root@ansible ~] - include: group.yml - include: user.yml - include: install.yml - include: config.yml - include: index.yml - include: service.yml [root@ansible ~] - name: create apache group   group: name=apache system=yes gid=80    [root@ansible ~] - name: create apache user   user: name=apache system=yes shell=/sbin/nologin home=/var/www/ uid=80 group=apache    [root@ansible ~] - name: install httpd package   yum: name=httpd [root@ansible ~] - name: config file   copy: src=httpd.conf dest=/etc/httpd/conf/ backup=yes   notify: restart [root@ansible ~] - name: index.html   copy: src=index.html dest=/var/www/html/ [root@ansible ~] - name: start service   service: name=httpd state=started enabled=yes [root@ansible ~] - name: restart   service: name=httpd state=restarted    [root@ansible ~] httpd.conf index.html [root@ansible ~] /data/ansible/roles/httpd/ ├── files │   ├── httpd.conf │   └── index.html ├── handlers │   └── main.yml └── tasks    ├── config.yml    ├── group.yml    ├── index.yml    ├── install.yml    ├── main.yml    ├── service.yml    └── user.yml 3 directories, 10 files [root@ansible ~] --- - hosts: websrvs   remote_user: root   roles:     - httpd      [root@ansible ~] 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 [root@ansible ~] [root@ansible ~] [root@ansible nginx] - include: install.yml - include: config.yml - include: index.yml - include: service.yml [root@ansible nginx] - name: install   yum: name=nginx    [root@ansible nginx] - name: config file for  centos7   template: src=nginx7.conf.j2 dest=/etc/nginx/nginx.conf   when: ansible_distribution_major_version=="7"    notify: restart - name: config file for  centos8   template: src=nginx8.conf.j2 dest=/etc/nginx/nginx.conf   when: ansible_distribution_major_version=="8"    notify: restart    [root@ansible nginx] - name: index.html   copy: src=roles/httpd/files/index.html dest=/usr/share/nginx/html/ [root@ansible nginx] - name: start service   service: name=nginx state=started enabled=yes [root@ansible nginx] - name: restart   service: name=nginx state=restarted [root@ansible nginx] ...省略... user {{user}}; worker_processes {{ansible_processor_vcpus+3}};    error_log /var/log /nginx/error.log; pid /run/nginx.pid; ...省略... [root@ansible nginx] ...省略... user nginx; worker_processes {{ansible_processor_vcpus**3}};   error_log /var/log /nginx/error.log; pid /run/nginx.pid; ...省略... [root@ansible nginx] user: daemon [root@ansible ~] /data/ansible/roles/nginx/ ├── handlers │   └── main.yml ├── tasks │   ├── config.yml │   ├── file.yml │   ├── install.yml │   ├── main.yml │   └── service.yml ├── templates │   ├── nginx7.conf.j2 │   └── nginx8.conf.j2 └── vars    └── main.yml 4 directories, 9 files [root@ansible ~] --- - hosts: web  roles:     - role: nginx      [root@ansible ~] 
 
创建Nginx的roles 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 [root@m01 roles] - Role nginx was created successfully baim0/ └── roles     └── nginx         ├── defaults         │   └── main.yml         ├── files         ├── handlers         │   └── main.yml         ├── meta         │   └── main.yml         ├── README.md         ├── tasks         │   └── main.yml         ├── templates         ├── tests         │   ├── inventory         │   └── test.yml         └── vars             └── main.yml