lyd2004888 发表于 2018-7-29 07:11:40

ansible基础三

setup模块常用自带变量:  
匹配完整主机名变量
  
ansible_hostname<主机名变量>
  
ansible_distribution_major_version <版本号变量>
  
ansible_all_ipv4_addresses <IP地址变量>
  

  
变量名:仅能由字母、数字和下划线组成,且只能以字母开头
  
变量来源:
  1 ansible setup facts 远程主机的所有变量都可直接调用
  2 在/etc/ansible/hosts中定义
  普通变量:主机组中主机单独定义,优先级高于公共变量
  公共(组)变量:针对主机组中所有主机定义统一变量
  3 通过命令行指定变量,优先级最高
  ansible-playbook –e varname=value
  4 在playbook中定义
  vars:
  - var1: value1
  - var2: value2
  5 在role中定义
  

  
变量命名:
  变量名仅能由字母、数字和下划线组成,且只能以字母开头
  变量定义:key=value
  示例:http_port=80
  变量调用方式:
  1)通过{{ variable_name }} 调用变量,且变量名前后必须有 空格,有时用“{{ variable_name }}”才生效
  2)ansible-playbook –e 选项指定
  示例:
  ansible-playbook test.yml -e "hosts=www user=mageedu"
  

  在palybook里面使用变量能让playboot更加灵活
  (一):在playbook里定义变量
  看下面的例子:
  

---  
- hosts: web
  remote_user: root
  

  tasks:
  - name: remove package
  yum: name={{ pkname }} state=absent
  - name: initall package
  yum: name={{ pkname }}
  - name: start service
  service: name={{ pkname }} state=started
  
#ansible-playbook -e "pkname=httpd " install.ym
  

  上面这个playbook分为三步,
  第一步:卸包,
  第二步:装包,
  第三步:重启服务
  &quot;但是注意到没有,而这三步我用的是一个变量,也就是我只要在命令行定义一个变量就可以完成这三个动作&quot;
  但是这个还是需要自己手工制定变量,
  (二):将变量名与变量名内容直接定义到playboot里
  看下面的例子:
  

    ---  - hosts: web
  remote_user: root
  "#vars是专门用于在playboot定义变量的关键词"
  vars:
  "#username,gropname就是变量名冒号":"后面的就是变量内容"
  - username: user1
  - groupname: root
  

  tasks:
  #任务一创建组
  - name: create group
  group: name={{ groupname }}
  "#创建用户并把该用户加入上面创建的组里面,再创键家目录到/app下"
  - name: create user
  user: name={{ username }} group={{   groupname }} home=/app/{{ username }}
  
执行playbook的方法:"而这时候调用playboot就不需要用-e指定变量内容了"
  

  #"ansible-playbook useradd.yml"
  PLAY *************************************************************************************************************************************
  

  TASK *************************************************************************************************************************
  ok:
  ok:
  

  TASK ****************************************************************************************************************************
  ok:
  ok:
  

  TASK *****************************************************************************************************************************
  ok:
  changed:
  

  PLAY RECAP *************************************************************************************************************************************
  192.168.136.5            : ok=3    changed=1    unreachable=0    failed=0
  192.168.136.6            : ok=3    changed=0    unreachable=0    failed=0
  

  (三):使用setup中自带的变量
  看下面的例子:
  

---  
- hosts: web
  remote_user: root
  

  tasks:
  - name: create file
  file: name=/app/{{ ansible_hostname }}.txt state=touch
  #ansible web -a 'ls -l /app/'
  192.168.136.5 | SUCCESS | rc=0 >>
  total 0
  -rw-r--r-- 1 rootroot0 Jan 18 16:26 "localhost.txt" #利用变量创建的变量
  drwxr-xr-x 2 user1 root 62 Jan 18 07:05 user1
  

  192.168.136.6 | SUCCESS | rc=0 >>
  total 4
  -rw-r--r-- 1 rootroot    0 Jan 14 09:40 "centos6-102.txt" #利用变量创建出的文件
  -rw-r--r-- 1 rootroot    0 Jan 14 01:49 testsrv
  drwx------ 4 user1 root 4096 Jan 14 09:15 user1
  

  playbook中使用的变量ansible_hostname就是setpu模块中过滤出来的变量,这种方法让我们可以不用定义变量,直接所使用setup模块里自带的变量。
  (四):/etc/ansible/hosts主机清单配置文件中定义变量
  1)定义普通变量;普通变量就是对每一个主机单独定义一个变量只能这个主机使用
  请看下面的例子:
  

  
192.168.136.6 hostname="httpd"
  
这个可以在命令行调用
  
#这个例子就是利用在主机清单中定义的变量修改主机名
  
#ansible 192.168.136.6 -m hostname-a 'name={{ hostname }}'
  
192.168.136.6 | SUCCESS => {
  "ansible_facts": {
  "ansible_domain": "magedu.com",
  "ansible_fqdn": "centos6-102.magedu.com",
  "ansible_hostname": "httpd",
  "ansible_nodename": "httpd"
  
},
  
"changed": true,
  
"name": "httpd"
  

  }
  2)在/etc/ansible/hosts文件中定义公共变量;公共变量就是一个主机组定义一个共有的变量
  看下面的例子:
  

  
192.168.136.6
  
192.168.136.5
  

  
"#中括号里的【web】表示上面的web组,重点是冒号后面的vars加上这个关键次就表示对上面的web组创建共有变量。变量可以有多个"
  

  
hostname=websrvs
  
port=80
  

  利用变量更改主机名:
  

#ansible web -m hostname -C -a 'name="{{ hostname }}-{{ port }}"'  
192.168.136.6 | SUCCESS => {
  "ansible_facts": {
  "ansible_domain": "",
  "ansible_fqdn": "httpd",
  "ansible_hostname": "websrvs-80",
  "ansible_nodename": "websrvs-80"
  },
  "changed": true,
  "name": "websrvs-80"
  
}
  
192.168.136.5 | SUCCESS => {
  "ansible_facts": {
  "ansible_domain": "localdomain",
  "ansible_fqdn": "localhost.localdomain",
  "ansible_hostname": "websrvs-80",
  "ansible_nodename": "websrvs-80"
  },
  "changed": true,
  "name": "websrvs-80"
  
}
  

  4)在playbook里面调用在/etc/ansible/hosts文件中定义的变量
  

看下面的例子:  

  
  192.168.136.6
  192.168.136.5
  

  
  host=websrvs
  port=8080
  

  ---
  - hosts: web
  remote_user: root
  

  tasks:
  - name: set hostname
  hostname: name={{ host }}-{{ port }}
  

  5),在一个单独的文件存放playbok变量与值
  创建一个文件:
  

   touch var.txt  vim var.txt
  文件格式:
  var1: xiaoming
  var2: xiaohang
  

  6)在playbook调用文件var.txt里的变量
  

    #变量文件内容  var1: xiaoming
  var2: httpd
  

  playboot内容
  ---
  - hosts: web
  remote_user: root
  vars_files:
  - var.yml
  

  tasks:
  - name: create user
  user: name={{ var1 }} shell=/bin/bash home=/app/{{ var1 }}
  - name: create file
  file: name=/app/{{ var2 }}.txtstate=touch mode=644 owner=wang
  

  #最后命令执行结果
  1)创建用户结果
  #ansible web -a 'tail -n1 /etc/passwd'
  192.168.136.6 | SUCCESS | rc=0 >>
  xiaoming2:x:503:503::/app/xiaoming:/bin/bash
  

  192.168.136.5 | SUCCESS | rc=0 >>
  xiaoming2:x:1002:1002::/app/xiaoming:/bin/bash
  

  2)创建文件的结果
  #ansible web -a 'ls -l /app'
  192.168.136.5 | SUCCESS | rc=0 >>
  total 0
  -rw------- 1 root   root      0 Jan 18 18:45 httpd.txt
  drwxr-xr-x 2 xiaoming xiaoming 62 Jan 18 07:05 xiaoming
  

  192.168.136.6 | SUCCESS | rc=0 >>
  total 4
  -rw------- 1 root   root      0 Jan 14 11:59 httpd.txt
  drwxr-xr-x 4 xiaoming xiaoming 4096 Dec 17 17:40 xiaoming
  

template模板模块
  

1)文本文件,嵌套有脚本(使用模板编程语言编写)2)Jinja2语言,使用字面量,有下面形式  ①:字符串:使用单引号或双引号
  ②:数字:整数,浮点数
  ③:列表:
  ④:元组:(item1, item2, ...)
  ⑤:字典:{key1:value1, key2:value2, ...} ⑥:布尔型:true/false 
  
3)算术运算:+, -, *, /, //<整除>, %, **<次方>
  
4)比较操作:==, !=, >, >=, <, <=
  
5)逻辑运算:and, or, not
  
6)流表达式:For IfWhen
  

  功能:
  templates功能:根据模块文件动态生成对应的配置文件
  templates文件必须存放于templates目录下,且命名为 .j2 结尾
  

yaml/yml 文件需和templates目录平级,目录结构如下:  

  
./
  
├── temnginx.yml #调用temnginx模块的文件必须跟真正存放模板的文件属于平级关系
  
└── templates
  └── nginx.conf.j2 #模板文件
  

  使用templates模块功能需要创建一个目录名为templates,然后在这个目录下存放模板文件,而文件名推荐改下后缀<.j2>

示例:利用templates同步nginx配置文件
  

1)准备templates/nginx.conf.j2文件  

  
2)编辑playbook文件
  
vim temnginx.yml
  ---
  - hosts: web
  remote_user: root
  

  tasks:
  - name: install nginx
  yum: name=nginx
  #调用template模块,src表示本机的template目录下的某一个文件 ,dest表示远程被控主机的存放路径,做用类似copy模块,但是template模板文件里可以支持变量以及算数运算
  "- name: templates
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf"
  - name: start nginx
  service: name=nginx state=started
  
这个例子作用就是:
  第一步:在远程被控主机安装nginx
  第二步:将本机template模板文件复制到远程被控主机上
  第三步:启动nginx服务
  

  可能有时候我们需要判断某一个版本,在复制某一个文件到对应的机器上,这时候可以加上when这个关键词,就可以帮我们来解决这个问题,

&quot;when关键字的用法,作用类似一判断当满足某一个条件时就执行这个动作&quot;
  看下面的例子
  

#ls templates/  
nginx-6.conf.j2nginx-7.conf.j2
  

  
#cat temnginx.yml
  
---
  
- hosts: web
  remote_user: root
  

  tasks:
  - name: install nginx
  yum: name=nginx
  

  - name: templates 6
  template: src=nginx-6.conf.j2 dest=/etc/nginx/nginx.conf
  #这是setup模块里的一个存放主版本的变量"ansible_distribution_major_version" 而"=="就表示判断的意思,作用就是判断如果主版本号是否等于6
  when: ansible_distribution_major_version=="6"
  

  - name: templates 7
  template: src=nginx-7.conf.j2 dest=/etc/nginx/nginx.conf
  #同上面的when作用相同
  when: ansible_distribution_major_version=="7"
  

  - name: start nginx
  service: name=nginx state=started
  
上面这个例子:作用是在web这个主机组里面的所有主机上都安装nginx服务,并把判断如果系统是centos6是复制本机上的6的nginx配置文件,同时7也是一样,然后在启动nginx服务
  

迭代 with_item
  

迭代的作用就类似与shell里的for循环的作用,with_item会把它里面定义的所有值,每次都传递一个给item这个特殊的变量里面,而with_item理由几个值item就循环几次知道没有才会停止  

  请看下面的例子
  

  #cat user_with_items.yml
  ---
  - hosts: web
  remote_user: root
  

  tasks:
  - name: add several users
  #item特殊变量代表的就是with_items里面的每一个值
  user: name={{ "item" }} group=root
  #with_items下面的所有值都属于被循环的值
  "with_items":
  - xiaohong
  - xiaolan
  
执行结果:
  

  #ansible web -a 'tail -n2 /etc/passwd'
  192.168.136.6 | SUCCESS | rc=0 >>
  xiaohong:x:504:0::/home/xiaohong:/bin/bash
  xiaolan:x:505:0::/home/xiaolan:/bin/bash
  

  192.168.136.5 | SUCCESS | rc=0 >>
  xiaohong:x:1003:0::/home/xiaohong:/bin/bash
  xiaolan:x:1004:0::/home/xiaolan:/bin/bash
  
上面的例子作用就是创建两个普通用户,但是使用with_items关键词来完成的
  

  

迭代嵌套子变量
  看下面的例子:
  

   #cat user_with_items.yml  ---
  - hosts: web
  remote_user: root
  

  tasks:
  - name: add group
  group: name={{ item }}
  with_items:
  - group1
  - group2
  - group3
  

  - name: add users
  #item.name <.>后面的name以及group都属于item的自变量
  user: name={{ item.name }} group={{ item.group }}
  #这个写法,迭代里面嵌套了另外的子变量(name)(group)
  with_items:
  - { name: 'laifu3',group: group1 }
  - { name: 'laifu2',group: group2 }
  - { name: 'laifu3',group: group3 }
  

  #ansible web -m shell -a 'id laifu3'
  192.168.136.6 | SUCCESS | rc=0 >>
  uid=506(laifu3) gid=506(group3) groups=506(group3)
  

  192.168.136.5 | SUCCESS | rc=0 >>
  uid=1005(laifu3) gid=1005(group3) groups=1005(group3)
  

  #ansible web -a 'tail -n3 /etc/group'
  192.168.136.6 | SUCCESS | rc=0 >>
  group1:x:504:
  group2:x:505:
  group3:x:506:
  

  192.168.136.5 | SUCCESS | rc=0 >>
  group1:x:1003:
  group2:x:1004:
  group3:x:1005:
  
这个playbook作用就是创建组,再创键新用户,然后再把用户加到创建好的组里面去
  

playbook中使用template模板文件的for循环 if判断
  例子一:for循环
  

模板文件  

  #cat templates/for1.conf.j2
  "#for循环的列表ports来自下面的文件中定义的vaes变量中的ports变量的值。而每一次循环都会把ports里的值赋给port这个 变量,因为ports只有3个值所以只会循环3三遍"
  语法要求:
  开头:双{%里面的格式与shell里的格式基本相同%}
  中间:循环内容
  结尾:双{%endfor%}
  {%for port in ports%}
  server {
  listen {{ port }}
  }
  {%endfor%}
  

  playbook文件
  #cat for.yml
  ---
  - hosts: web
  remote_user: root
  vars:
  ports:
  - 81
  - 82
  - 83
  

  tasks:
  - name: tesk for
  template: src=for1.conf.j2 dest=/app/for1.conf
  

  执行结果:
  

  #ansible web -a 'cat /app/for1.conf'
  192.168.136.6 | SUCCESS | rc=0 >>
  server {
  listen 81
  }
  server {
  listen 82
  }
  server {
  listen 83
  }
  

  192.168.136.5 | SUCCESS | rc=0 >>
  server {
  listen 81
  }
  server {
  listen 82
  }
  server {
  listen 83
  }
  

  例子二:for循环嵌套子变量
  

template模板文件  #cat templates/for2.conf.j2
  {%for port in ports%}
  server {
  listen {{ port.listen_port }}
  }
  {%endfor%}
  

  
playbook文件
  #cat for2.yml
  ---
  - hosts: web
  remote_user: root
  vars:
  ports:
  - listen_port: 81
  - listen_port: 82
  - listen_port: 83
  

  tasks:
  - name: tesk for
  template: src=for2.conf.j2 dest=/app/for2.conf
  

  
执行结果:
  #ansible web -a 'cat /app/for2.conf'
  192.168.136.6 | SUCCESS | rc=0 >>
  server {
  listen 81
  }
  server {
  listen 82
  }
  server {
  listen 83
  }
  

  192.168.136.5 | SUCCESS | rc=0 >>
  server {
  listen 81
  }
  server {
  listen 82
  }
  server {
  listen 83
  }
  

  

  例子三:for循环嵌套多个元素
  

template模板文件  #cat templates/for3.conf.j2
  {%for vhost in vhosts%}
  server {
  port {{ vhost.port }}
  webserver {{ vhost.name }}
  webdir {{ vhost.root }}
  }
  {%endfor%}
  

  
playbook文件
  #cat for3.yml
  ---
  - hosts: web
  remote_user: root
  vars:
  vhosts:
  - web1:
  port: 81
  name: web1.magedu.com
  root: /app/webroot1
  - web2:
  port: 82
  name: web1.magedu.com
  root: /app/webroot2
  - web3:
  port: 83
  name: web1.magedu.com
  root: /app/webroot3
  tasks:
  - name: tesk for
  template: src=for3.conf.j2 dest=/app/for3.conf
  
执行结果
  #ansible web -a 'cat /app/for3.conf'
  192.168.136.6 | SUCCESS | rc=0 >>
  server {
  port 81
  webserver web1.magedu.com
  webdir /app/webroot1
  }
  server {
  port 82
  webserver web1.magedu.com
  webdir /app/webroot2
  }
  server {
  port 83
  webserver web1.magedu.com
  webdir /app/webroot3
  }
  

  192.168.136.5 | SUCCESS | rc=0 >>
  server {
  port 81
  webserver web1.magedu.com
  webdir /app/webroot1
  }
  server {
  port 82
  webserver web1.magedu.com
  webdir /app/webroot2
  }
  server {
  port 83
  webserver web1.magedu.com
  webdir /app/webroot3
  }
  

  
例子四:for循环嵌套if判断
  

  

  template模板文件
  

#cat templates/for4.conf.j2  
{%for vhost in vhosts%}
  
server {
  port {{ vhost.port }}
  

  #判断循环列表中变量&quot;vhost.name&quot;是否定义,如果定义了就把它的值复制到目标主机,
  &quot;语法要求:
  开头:{%前面可以任意变量,后面必须写&quot;is defined关键词&quot;%}
  中间:执行的任务
  结尾:{%endif%}&quot;
  &quot;{%if vhost.name is defined %}&quot;
  webserver {{ vhost.name }}
  &quot;{%endif%}&quot;
  webdir {{ vhost.root }}
  }
  {%endfor%}

playbook文件
  #cat for4.yml
  

- hosts: web  remote_user: root
  vars:
  vhosts:
  - web1:
  port: 81
  root: /app/webroot1
  

  - web2:
  port: 82
  name: web1.magedu.com
  root: /app/webroot2
  

  - web3:
  port: 83
  root: /app/webroot3
  tasks:
  - name: tesk for
  template: src=for4.conf.j2 dest=/app/for4.conf
  

  执行结果:
  #ansible web -a 'cat /app/for4.conf'
  192.168.136.6 | SUCCESS | rc=0 >>
  server {
  port 81
  webdir /app/webroot1
  }
  server {
  port 82
  webserver web1.magedu.com
  webdir /app/webroot2
  }
  server {
  port 83
  webdir /app/webroot3
  }
  

192.168.136.5 | SUCCESS | rc=0 >>  
server {
  port 81
  webdir /app/webroot1
  
}
  
server {
  port 82
  webserver web1.magedu.com
  webdir /app/webroot2
  
}
  
server {
  port 83
  webdir /app/webroot3
  
}
  

  
```
页: [1]
查看完整版本: ansible基础三