Ansible Playbook的用法(变量与template) 电脑版发表于:2021/4/3 18:52  ># Ansible Playbook的用法(变量与template) [TOC] 使用变量 ------------ <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 变量名:仅能由字母、数字和下划线组成,且只能以字母开头。 我们可以通过setup模块查看远程系统中的变量,都可以直接调用。 </p> ### setup模块示例 ```bash # 获取远程主机的所有环境变量 ansible all -m setup # 如果只需要看部分的,如只查看有address的我们可以用filter参数进行模糊匹配查询 ansible all -m setup -a 'filter=*address*' # 关于该模块更多参数请参考 ansible-doc -s setup ``` <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 通过过滤查看`ipaddress4` </p>  ### 在playbook中定义变量(外部赋值) <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 这里我们创建`file3.yaml`文件并以安装`httpd`与`vsftpd`两个包举例 </p> ```yaml --- - hosts: webserver remote_user: root tasks: - name: install {{ pkname1 }} package yum: name={{ pkname1 }} - name: install {{ pkname2 }} package yum: name={{ pkname2 }} ``` tn>注意在定义变量名时,要以两个大括号包着,并且变量前后要有一个空格。 <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 然后我们通过`-e`参数进行赋值,执行测试一下 </p> ```bash # 这里传入变量参数级别最高 ansible-playbook -e pkname1=httpd -e pkname2=vsftpd file3.yaml # 也可以这样 ansible-playbook -e 'pkname1=httpd pkname2=vsftpd' file3.yaml ```  ### 在playbook中定义变量(内部赋值) <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 根据上面的示例,我们可以直接在内部进行赋值。(这里我就不尝试了) </p> ```yaml --- - hosts: webserver remote_user: root vars: - pkname1: httpd - pkname2: vsftpd tasks: - name: install {{ pkname1 }} package yum: name={{ pkname1 }} - name: install {{ pkname2 }} package yum: name={{ pkname2 }} ``` ### 配置文件中定义变量与运用 <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 我们知道配置文件的位置在`/etc/ansible/hosts`,我们可以针对不同的ip地址定义不同的值比如,我这里定义一个`my_host_last_number`变量,修改`/etc/ansible/hosts`: </p> ```bash [webserver] 10.211.55.5 my_host_last_number=5 10.211.55.6 my_host_last_number=6 [dbserver] 10.211.55.5 ``` <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 然后我们创建一个`file4.yaml`文件的一个脚本,里面将变量值复制到`my_number`文件里面 </p> ```yaml --- - hosts: webserver remote_user: root tasks: - name: Create Number File shell: echo '{{ my_host_last_number }}' > my_number ``` <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 然后我们执行`file4.yaml`脚本,先测试在执行。 </p> ```bash # 测试 ansible-playbook -C file4.yaml # 执行 ansible-playbook file4.yaml # 获取执行结果 ansible all -a 'cat my_number' ```  <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 我们也可以通过指定组进行设置变量,格式为`[组名:vars]`,然后在下面定义变量。然后我们修改一下`file4.yaml`进行执行 </p> ```bash [webserver] 10.211.55.5 my_host_last_number=5 10.211.55.6 my_host_last_number=6 [webserver:vars] mygroup=webserver [dbserver] 10.211.55.5 ``` ```bash --- - hosts: webserver remote_user: root tasks: - name: Create Number File shell: echo '{{ my_host_last_number }}' > my_number - name: Create Group name shell: echo '{{ mygroup }}' > my_number ``` ```bash ansible-playbook file4.yaml ansible all -a 'cat my_number' ```  tn>普通变量:主机组中主机单独定义,优先级高于公共变量 公共(组)变量:针对主机组中所有主机定义统一变量 命令优先级最高 ### 添加自定义变量文件 <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 创建自定义`vars.yml`环境变量的文件。 </p> ```bash # cat vars.yml xx: hello hi: io ``` <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 创建`var.yml`文件,并通过`vars_files`属性指定环境变量配置文件的路径 </p> ```bash --- - hosts: webserver remote_user: root vars_files: - vars.yml tasks: - name: XX Write shell: echo '{{ xx }}' > my_number ``` <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 然后我们执行一下,查看是否将`xx`配置变量的`hello`值覆盖到`my_number`文件中 </p> ```bash ansible-playbook -C var.yml ansible-playbook var.yml # 检查一下 ansible all -m shell -a 'cat my_number' ```  tn>注意:这里的`vars_files`属性最好还是指定为绝对路径。 jinja2语法 ------------ ### jinja2介绍 <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> jinja2模板中使用 `{{ }}` 语法表示一个变量,它是一种特殊的占位符。当利用jinja2进行渲染的时候,它会把这些特殊的占位符进行填充/替换,jinja2支持python中所有的Python数据类型比如列表、字段、对象等。 </p> ### Jinja2算术运算 <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> Jinja 允许你用计算值。这在模板中很少用到,但为了完整性允许其存在 支持下面的运算符 `+`:把两个对象加到一起。 通常对象是素质,但是如果两者是字符串或列表,你可以用这 种方式来衔接它们。 无论如何这不是首选的连接字符串的方式!连接字符串见 ~ 运算符。 {{ 1 + 1 }} 等于 2 `-`:用第一个数减去第二个数。 {{ 3 - 2 }} 等于 1 `/`:对两个数做除法。返回值会是一个浮点数。 {{ 1 / 2 }} 等于 {{ 0.5 }} `//`:对两个数做除法,返回整数商。 {{ 20 // 7 }} 等于 2 `%`:计算整数除法的余数。 {{ 11 % 7 }} 等于 4 `*`:用右边的数乘左边的操作数。 {{ 2 * 2 }} 会返回 4 。 也可以用于重 复一个字符串多次。{{ ‘=’ * 80 }} 会打印 80 个等号的横条 `**`:取左操作数的右操作数次幂。 {{ 2**3 }} 会返回 8 </p> ### 比较操作符 <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> `==` 比较两个对象是否相等 `!=` 比较两个对象是否不等 `>` 如果左边大于右边,返回 true `>=` 如果左边大于等于右边,返回 true `<` 如果左边小于右边,返回 true `<=` 如果左边小于等于右边,返回 true </p> ### 逻辑运算符 <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 对于 if 语句,在 for 过滤或 if 表达式中,它可以用于联合多个表达式 `and`如果左操作数和右操作数同为真,返回 true `or`如果左操作数和右操作数有一个为真,返回 true `not`对一个表达式取反(见下) `(expr)`表达式组 `['list', 'of', 'objects']`: </p> tn>更多请参考:https://www.jianshu.com/p/f04dae701361 Template 模块 ------------ ### Template模块的介绍 <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 当对不同的机器有不同的配置设置时我们可以通过Template的方式设置配置模块。 也可以理解为根据模块文件动态生成对应的配置文件。 </p> ### Template的注意事项 <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> template文件必须存放于templates目录下,且命名为 .j2 结尾。 </p> ```bash # yaml/yml 文件需和templates目录平级,目录结构如下: ./ ├── temnginx.yml └── templates └── nginx.conf.j2 ``` ### 示例同步nginx配置 <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 我们首先在本地安装nginx,并复制相应的配置文件到`templates`目录下。 (一般都是需要先添加nginx源,如果未添加请参考:https://www.tnblog.net/hb/article/details/5843) </p> ```bash yum install nginx # 查看配置 cat /etc/nginx/nginx.conf ``` <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 然后我们想通过不同的主机上cpu的个数去创建nginx的进程数乘2进行创建,将配置文件复制到templates目录下 </p> ```bash ansible all -m setup -a 'filter=*cpu*' ansible all -m setup -a 'filter=ansible_processor_vcpus' # 创建templates mkdir templates # 将配置文件复制到templates目录下 cp /etc/nginx/nginx.conf templates/nginx.conf.j2 # 修改nginx.conf.j2文件 vim templates/nginx.conf.j2 ``` ```bash user nginx; worker_processes {{ ansible_processor_vcpus*2 }}; error_log /var/log/nginx/error.log warn; 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; } ``` <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 先结束Apache服务器防止端口冲突,接下来我们来编辑`nginx.yaml`文件,接着检查并执行。最后访问一下nginx的页面。 </p> ```bash ansible all -m shell -a 'systemctl stop httpd' ``` ```yaml --- - hosts: all remote_user: root tasks: - name: install nginx package yum: name=nginx - name: nginx conf template template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf notify: restart nginx service - name: start service service: name=nginx state=started enabled=yes handlers: - name: restart nginx service service: name=nginx state=restarted ```  ```bash ansible all -m shell -a 'curl 127.0.0.1' ```  <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 如果我们想不受Apache默认启动的80端口影响的话,我们可以通过8拼接`my_host_last_number`属性形成新的端口,这里就是:85与86端口。然后我们通过`cp /etc/nginx/conf.d/default.conf templates/default.conf.j2`命令将默认配置移动至`templates`目录下。 </p> ```bash # cat /etc/ansible/hosts [webserver] 10.211.55.5 my_host_last_number=5 10.211.55.6 my_host_last_number=6 [webserver:vars] mygroup=webserver [dbserver] 10.211.55.5 ``` ```bash # 编辑模版 # cat templates/default.conf.j2 server { listen 8{{ my_host_last_number }}; server_name localhost; #charset koi8-r; #access_log /var/log/nginx/host.access.lo ``` <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 接着我们修改`nginx.yaml`Play文件,最后执行一下。 </p> ```bash --- - hosts: all remote_user: root tasks: - name: install nginx package yum: name=nginx - name: stop service service: name=nginx state=stopped ignore_errors: True - name: nginx default conf template template: src=default.conf.j2 dest=/etc/nginx/conf.d/default.conf notify: restart nginx service - name: nginx conf template template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf notify: restart nginx service - name: start service service: name=nginx state=started enabled=yes handlers: - name: restart nginx service service: name=nginx state=restarted ``` ```bash ansible-playbook nginx.yaml # 检查一下 ansible all -m shell -a 'curl 127.0.0.1:8{{ my_host_last_number }}' ``` When的运用 ------------ <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 当我们对不同操作系统的时候或对相同操作系统不同版本的时候,会做出不同的修改。所以`when`正是因为此操作而诞生的。 </p> ### when的介绍 <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 条件测试:如果需要根据变量、facts或此前任务的执行结果来作为某task执行与否的前提时要用到条件测试,通过when的语句实现,在task中使用,jinja2的语法格式。 when语句 在task后添加when子句即可使用条件测试;when语句支持Jinja2表达式语法 </p> ### 示例 <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 获取不同主机的系统环境版本变量,可以通过如下命令进行查询。 </p> ```bash ansible all -m setup -a 'filter=*distribution*' # 最后查看不同的系统版本时我们发现它是ansible_distribution_major_version ansible all -m setup -a 'filter=*distribution*' ``` <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 接着我们可以只判断系统环境为Centos7的才执行。 </p> ```bash --- - hosts: all remote_user: root tasks: - name: install nginx package yum: name=nginx - name: stop service service: name=nginx state=stopped ignore_errors: True - name: nginx default conf template template: src=default.conf.j2 dest=/etc/nginx/conf.d/default.conf when: ansible_distribution_major_version == "7" notify: restart nginx service - name: nginx conf template template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf when: ansible_distribution_major_version == "7" notify: restart nginx service - name: start service service: name=nginx state=started enabled=yes handlers: - name: restart nginx service service: name=nginx state=restarted ``` Jinja2配合Template的语法的运用 ------------ ### with_items介绍 <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 迭代:当有需要重复性执行的任务时,可以使用迭代机制。 - 对迭代项的引用,固体变量名为 "item" - 要在task中使用with_items给定要迭代的元素列表 - 列表格式: 字符串 字典 </p> > 示例 <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 先创建3个group组,再创建3个group组的用户。 </p> ```bash --- - hosts: all remote_user: root tasks: - name: add some groups group: name={{item}} when: ansible_distribution_major_version == "7" with_items: - g1 - g2 - g3 - name: add some users user: name={{item.name}} group={{item.group}} with_items: - { name: 'user1', group: 'g1' } - { name: 'user2', group: 'g1' } - { name: 'user3', group: 'g3' } ```  ### 循环语句 <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 在`j2`文件中使用`for`循环遍历Ansible的变量。首先我们定义`testfor.yaml`文件。再在`for3.conf.j2`文件中定义循环。 </p> ```yaml --- - hosts: all remote_user: root vars: ports: - web1: port: 81 name: web1 rootdir: /data/web1 - web2: port: 82 name: web2 rootdir: /data/web2 - web3: port: 83 name: web3 rootdir: /data/web3 tasks: - name: copy conf template: src=for3.conf.j2 dest=/data/for3.conf ``` <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 然后在相对路径中,创建`for3.conf.j2`文件,并添加相关内容。最后执行命令。 </p> ```bash {% for p in ports %} server{ listen {{ p.port }} servername {{ p.name }} documentroot {{ p.rootdir }} } {% endfor %} ``` ```bash ansible-playbook -C testfor.yaml ansible-playbook testfor.yaml ```  <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 验证一下 </p> ```bash ansible all -m shell -a 'cat /data/for3.conf' ```  ### 判断语句 <p style="font-weight: 400;line-height: 1.5;color: #212529;-webkit-tap-highlight-color: transparent;box-sizing: border-box;padding: 0px 20px 20px 20px;border: 1px solid #e9ecef;border-left-width: .25rem;border-radius: .25rem;display: block;border-left-color: #5bc0de;"> 通过`if`条件语句判断值有没有被定义。 </p> ```yaml --- - hosts: all remote_user: root vars: ports: - web1: port: 81 #name: web1 rootdir: /data/web1 - web2: port: 82 name: web2 rootdir: /data/web2 - web3: port: 83 #name: web3 rootdir: /data/web3 tasks: - name: copy conf template: src=for3.conf.j2 dest=/data/for3.conf ``` ```bash {% for p in ports %} server{ listen {{ p.port }} {% if p.name is defined %} servername {{ p.name }} {% endif %} documentroot {{ p.rootdir }} } {% endfor %} ``` 