Ansible之Playbook中使用变量

Playbook中同样也支持变量
变量名:仅能由字母、数字和下划线组成,且只能以字母开头

变量定义:

variable=value
variable: value

范例:

http_port=80
http_port: 80

变量调用方式:

通过{{ variable_name }} 调用变量,且变量名前后建议加空格,有时用"{{ variable_name }}"才生效

变量来源:

  1. ansible 的 setup facts 远程主机的所有变量都可直接调用
  2. 通过命令行指定变量,优先级最高
[root@centos8 ~]# ansible-playbook -e varname=value test.yml
  1. 在playbook文件中定义
vars:
  var1: value1
  var2: value2
  1. 在独立的变量YAML文件中定义
- hosts: all
  vars_files:
    - vars.yml
  1. 在主机清单文件中定义
    主机(普通)变量:主机组中主机单独定义,优先级高于公共变量
    组(公共)变量:针对主机组中所有主机定义统一变量
  2. 在项目中针对主机和主机组定义
    在项目目录中创建 host_vars和group_vars目录
  3. 在role中定义

变量的优先级从高到低如下

-e 选项定义变量 -->playbook中vars_files --> playbook中vars变量定义 -->host_vars/主机名文件 -->主机清单中主机变量--> group_vars/主机组名文件-->group_vars/all文件--> 主机清单组 变量

使用 setup 模块中变量

本模块自动在playbook调用,不要用ansible命令调用,生成的系统状态信息, 并存放在facts变量中
facts 包括的信息很多,如: 主机名,IP,CPU,内存,网卡等

facts 变量的实际使用场景案例

通过facts变量获取被控端CPU的个数信息,从而生成不同的Nginx配置文件
通过facts变量获取被控端内存大小信息,从而生成不同的memcached的配置文件
通过facts变量获取被控端主机名称信息,从而生成不同的Zabbix配置文件
....

案例:使用setup变量

[root@centos8 ~]# ansible 172.31.0.28 -m setup -a 'filter="ansible_default_ipv4"'
172.31.0.28 | SUCCESS => {
    "ansible_facts": {
        "ansible_default_ipv4": {
            "address": "172.31.0.28",
            "alias": "eth0",
            "broadcast": "172.31.255.255",
            "gateway": "172.31.0.254",
            "interface": "eth0",
            "macaddress": "00:0c:29:ac:f5:a4",
            "mtu": 1500,
            "netmask": "255.255.0.0",
            "network": "172.31.0.0",
            "type": "ether"
        },
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false
}

[root@centos8 ~]# ansible 172.31.0.28 -m setup -a 'filter="ansible_nodename"'
172.31.0.28 | SUCCESS => {
    "ansible_facts": {
        "ansible_nodename": "centos8.longxuan.vip",
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false
}

范例:

---
# var1
- hosts: websrvs
  remote_user: root
  gather_facts: yes
  tasks:
    - name: create log file
      file: name=/data/{{ ansible_nodename }}.log state=touch owner=long mode=600

执行

[root@centos8 ~]# ansible-playbook var1.yml

范例: 显示 eth0 网卡的 IP 地址

- hosts: websrvs
  tasks:
    - name: show eth0 ip address {{ ansible_facts["eth0"]["ipv4"]["address"]}}
      debug:
        msg: ip address {{ ansible_eth0.ipv4.address }}

执行

[root@centos8 ~]# ansible-playbook -v show_ip.yml 
Using /etc/ansible/ansible.cfg as config file

PLAY [websrvs] *********************************************************************************

TASK [Gathering Facts] *************************************************************************
ok: [172.31.0.48]
ok: [172.31.0.38]

TASK [show eth0 ip address 172.31.0.38] ********************************************************
ok: [172.31.0.38] => {
    "msg": "ip address 172.31.0.38"
}
ok: [172.31.0.48] => {
    "msg": "ip address 172.31.0.48"
}

PLAY RECAP *************************************************************************************
172.31.0.38                : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
172.31.0.48                : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

范例:

---
- hosts: websrvs
  tasks:
    - name: test var
      file: path=/data/{{ ansible_facts["eth0"]["ipv4"]["address"]}}.log state=touch
      #file: path=/data/{{ ansible_eth0.ipv4.address }}.log state=touch  #和上面效果一样

执行

[root@centos8 ~]# ansible-playbook  test.yml 

[root@centos8 ~]# ll /data/172.31.0.38.log 
-rw-r--r-- 1 root root 0 May 26 01:37 /data/172.31.0.38.log

在playbook 命令行中定义变量

范例:

---
- hosts: websrvs
  remote_user: root
  tasks:
    - name: install package
      yum: name={{ pkname }} state=present

执行安装任意一个软件包

[07 root@centos8 ~]# ansible-playbook -e pkname=httpd var2.yml
# 执行安装任意多个软件包
[root@centos8 ~]# ansible-playbook -e pkname=zip,unzip var2.yml

范例:

[root@centos8 ~]# cat vars 
pkname1: memcached
pkname2: vsftpd

root@centos8 ~]# cat var3.yml
---
- hosts: websrvs
  remote_user: root
  tasks:
    - name: install package {{ pkname1 }}
      yum: name={{ pkname1 }} state=present
    - name: install package {{ pkname2 }}
      yum: name={{ pkname2 }} state=present

执行:两条命令效果一样

[root@centos8 ~]# ansible-playbook -e pkname1=memcached -e pkname2=vsftpd var3.yml

[root@centos8 ~]# ansible-playbook -e '@vars' var3.yml

在playbook文件中定义变量

范例:

---
- hosts: websrvs
  remote_user: root
  vars:
    username: user1
    groupname: group1
  tasks:
    - name: create group {{ groupname }}
      group: name={{ groupname }} state=present
    - name: create user {{ username }}
      user: name={{ username }} group={{ groupname }} state=present

执行

[root@centos8 ~]# ansible-playbook -e 'username=user1 groupname=group1' var4.yml

范例:变量的相互调用

---
- hosts: websrvs
  remote_user: root
  vars:
    collect_info: "/data/test/{{ansible_default_ipv4['address']}}/"
    
  tasks:
    - name: create ip directoty
      file: name="{{collect_info}}" state=directory

执行:

[root@centos8 ~]# ansible-playbook var5.yml

执行之后的目标主机的结果如下

[root@centos8 ~]# tree /data/test/
/data/test/
└── 172.31.0.48

1 directory, 0 files

范例: 变量的相互调用

---
- hosts: websrvs
  vars:
    suffix: "txt"
    file: "{{ ansible_nodename }}.{{suffix}}"
  tasks:
    - name: test var
      file: path="/data/{{file}}" state=touch

执行:

[root@centos8 ~]# ansible-playbook var6.yml 

范例: 安装多个包

- hosts: websrvs
  vars:
    web: httpd
    db: mariadb-server
  tasks:
    - name: install {{ web }} {{ db }}
      yum:
        name:
          - "{{ web }}"
          - "{{ db }}"
        state: latest

- hosts: websrvs
  tasks:
    - name: install package
      yum: name={{ pack }}
      vars:
        pack: 
          - httpd
          - memcached

范例: 安装指定版本的MySQL

[root@centos8 ~]# cat install_mysql.yml 
---
# install mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
- hosts: dbserver
  remote_user: root
  gather_facts: no
  vars:
    version: "mysql-5.6.46-linux-glibc2.12-x86_64"
    suffix: "tar.gz"
    file: "{{version}}.{{suffix}}"

  tasks:
    - name: install package
      yum: name=libaio,perl-Data-Dumper,perl-Getopt-Long
    - name: create mysql group
      group: name=mysql gid=306
    - name: create mysql user
      user: name=mysql uid=306 group=mysql shell=/sbin/nologin system=yes create_home=no home=/data/mysql
    - name: copy tar to remove host and file mode
      unarchive: src=/data/ansible/files/{{file}} dest=/usr/local/ owner=root group=root
    - name: create linkfile /usr/local/mysql
      file: src=/usr/local/{{version}} dest=/usr/local/mysql state=link
    - name: data dir
      shell: chdir=/usr/local/mysql/ ./scripts/mysql_install_db --datadir=/data/mysql --user=mysql
      tags: data
    - name: config my.cnf
      copy: src=/data/ansible/files/my.cnf dest=/etc/my.cnf
    - name: service script
      shell: /bin/cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
    - name: enable servcie
      shell: /etc/init.d/mysqld start;chkconfig --add mysqld;chkconfig mysqld on
      
      tags: service
    - name: PATH variable
      copy: content='PATH=/usr/local/mysql/bin:$PATH' dest=/etc/profile.d/mysql.sh
    - name: secure script
      script: /data/ansible/files/secure_mysql.sh
      tags: script

使用变量文件

可以在一个独立的playbook文件中定义变量,在另一个playbook文件中引用变量文件中的变量,比playbook中定义的变量优化级高

[root@centos8 ~]# vim var7.yml
---
# variable file
package_name: mariadb-server
service_name: mariadb

# 这个yml文件调用上面的var7.yml文件
[root@centos8 ~]# vim var8.yml
---
# install package and start service
- hosts: dbserver
  remote_user: root
  vars_files:
    - var7.yml
  tasks:
    - name: install package
      yum: name={{ package_name }}
      tags: install
    - name: start service
      service: name={{service_name}} state=started enabled=yes

执行

[root@centos8 ~]# ansible-playbook var8.yml

范例:

[root@centos8 ~]# cat vars2.yml
---
var1: httpd
var2: nginx

[root@centos8 ~]# cat var9.yml
---
- hosts: web
  remote_user: root
  vars_files:
    - vars2.yml
  tasks:
    - name: create httpd log
      file: name=/app/{{ var1 }}.log state=touch
    - name: create nginx log
      file: name=/app/{{ var2 }}.log state=touch

针对主机和主机组的变量

在主机清单中针对所有项目的主机和主机分组的变量

所有项目的主机变量

在inventory 主机清单文件中为指定的主机定义变量以便于在playbook中使用
范例:

[websrvs]
www1.longxuan.vip http_port=80 maxRequestsPerChild=808
www2.longxuan.vip http_port=8080 maxRequestsPerChild=909

所有项目的组(公共)变量

在inventory 主机清单文件中赋予给指定组内所有主机上的在playbook中可用的变量,如果和主机变是同名,优先级低于主机变量

范例:

[websrvs:vars]
http_port=80
ntp_server=ntp.longxuan.vip
nfs_server=nfs.longxuan.vip
[all:vars]
# --------- Main Variables ---------------
# Cluster container-runtime supported: docker, containerd
CONTAINER_RUNTIME="docker"
# Network plugins supported: calico, flannel, kube-router, cilium, kube-ovn
CLUSTER_NETWORK="calico"
# Service proxy mode of kube-proxy: 'iptables' or 'ipvs'
PROXY_MODE="ipvs"
# K8S Service CIDR, not overlap with node(host) networking
SERVICE_CIDR="192.168.0.0/16"
# Cluster CIDR (Pod CIDR), not overlap with node(host) networking
CLUSTER_CIDR="172.16.0.0/16"
# NodePort Range
NODE_PORT_RANGE="20000-60000"
# Cluster DNS Domain
CLUSTER_DNS_DOMAIN="longxuan.local."

范例:

[root@ansible ~]# vim /etc/ansible/hosts
[websrvs]
172.31.0.8 hname=www1 domain=longxuan.io
172.31.0.7 hname=www2
[websrvs:vars]
mark="-"
[all:vars]
domain=longxuan.org
[root@ansible ~]# ansible websrvs -m hostname -a 'name={{ hname }}{{ mark }}{{ domain }}'
#命令行指定变量:
[root@ansible ~]# ansible websrvs -e domain=longxuan.cn -m hostname -a 'name={{ hname }}{{ mark }}{{ domain }}'

范例: k8s 的ansible 变量文件

[etcd]
172.31.0.104 NODE_NAME=etcd1
172.31.0.105 NODE_NAME=etcd2
172.31.0.106 NODE_NAME=etcd3
[kube-master]
172.31.0.103 NEW_MASTER=yes
172.31.0.101
172.31.0.102
[kube-node]
172.31.0.109 NEW_NODE=yes
172.31.0.107
172.31.0.108
[harbor]

[ex-lb]

172.31.0.111 LB_ROLE=master EX_APISERVER_VIP=172.31.0.100 EX_APISERVER_PORT=8443
172.31.0.112 LB_ROLE=backup EX_APISERVER_VIP=172.31.0.100 EX_APISERVER_PORT=8443
[chrony]
[all:vars]
CONTAINER_RUNTIME="docker"
CLUSTER_NETWORK="calico"
PROXY_MODE="ipvs"
SERVICE_CIDR="192.168.0.0/16"
CLUSTER_CIDR="172.16.0.0/16"
NODE_PORT_RANGE="20000-60000"
CLUSTER_DNS_DOMAIN="longxuan.local."
bin_dir="/usr/bin"
ca_dir="/etc/kubernetes/ssl"
base_dir="/etc/ansible"

针对当前项目的主机和主机组的变量

上面的方式是针对所有项目都有效,而官方更建议的方式是使用ansible特定项目的主机变量和组变量
生产建议在项目目录中创建额外的两个变量目录,分别是host_vars和group_vars
host_vars下面的文件名和主机清单主机名一致,针对单个主机进行变量定义,格式:host_vars/hostname
group_vars下面的文件名和主机清单中组名一致,针对单个组进行变量定义,格式:
gorup_vars/groupname
group_vars/all文件内定义的变量对所有组都有效

范例: 特定项目的主机和组变量

[root@ansible ansible]# pwd
/data/ansible
[root@ansible ansible]# mkdir host_vars
[root@ansible ansible]# mkdir group_vars
[root@ansible ansible]# cat host_vars/172.31.0.8
id: 2
[root@ansible ansible]# cat host_vars/172.31.0.7
id: 1
[root@ansible ansible]# cat group_vars/websrvs
name: web
[root@ansible ansible]# cat group_vars/all
domain: longxuan.org
[root@ansible ansible]# tree host_vars/ group_vars/
host_vars/
├── 172.31.0.7
└── 172.31.0.8
group_vars/
├── all
└── websrvs
0 directories, 4 files
[root@ansible ansible]# cat test.yml
- hosts: websrvs
  tasks:
    - name: get variable
      command: echo "{{name}}{{id}}.{{domain}}"
      register: result
    - name: print variable
      debug:
        msg: "{{result.stdout}}"
        
[root@ansible ansible]# ansible-playbook test.yml

register 注册变量

在playbook中可以使用register将捕获命令的输出保存在临时变量中,然后使用debug模块进行显示输出

范例: 利用debug 模块输出变量

[root@centos8 ~]# cat register1.yml
- hosts: dbsrvs
  tasks:
    - name: get variable
      shell: hostname
      register: name
    - name: "print variable"
        debug:
          msg: "{{ name }}" #输出register注册的name变量的全部信息,注意
变量要加" "引起来
#msg: "{{ name.cmd }}"    #显示命令
#msg: "{{ name.rc }}"     #显示命令成功与否
#msg: "{{ name.stdout }}" #显示命令的输出结果为字符串形式
#msg: "{{ name.stdout_lines }}"    #显示命令的输出结果为列表形式
#msg: "{{ name.stdout_lines[0] }}" #显示命令的输出结果的列表中的第一个元素
#msg: "{{ name['stdout_lines'] }}" #显示命令的执行结果为列表形式
#说明
第一个 task 中,使用了 register 注册变量名为 name ;当 shell 模块执行完毕后,会将数据放到该变量中。
第二给 task 中,使用了 debug模块,并从变量name中获取数据。

范例:使用 register 注册变量创建文件

- hosts: websrvs
  tasks:
    - name: get variable
      shell: hostname
      register: name
    - name: create file
      file: dest=/tmp/{{name.stdout}}.log state=touch

执行

[root@centos8 ~]# ansible-playbook register2.yml 

范例: register和debug模块

---
- hosts: websrvs
  tasks:
    - shell: echo hello world
      register: say_hi
    - shell: "awk -F: 'NR==1{print $1}' /etc/passwd"
      register: user
    - debug: var=say_hi.stdout  #自定义输出变量代替msg
    - debug: var=user.stdout    #自定义输出变量代替msg

执行

[root@centos8 ~]# ansible-playbook debug_test.yml

范例: 安装启动服务并检查

---
- hosts: websrvs
  vars:
    package_name: nginx
    service_name: nginx
  tasks:
    - name: install {{package_name}}
      yum: name={{package_name}}
    - name: start {{service_name}}
      service: name={{service_name}}
    - name: check
      shell: ps axu | grep {{service_name}}
      register: check_service
    - name: debug
      debug:
        msg: "{{check_service.stdout_lines}}"

执行

[root@centos8 ~]# ansible-playbook service.yml

范例: 批量修改主机名

- hosts: websrvs
  vars:
    host: web
    domain: longxuan.vip
  tasks:
    - name: get variable
      shell: echo $RANDOM | md5sum | cut -c 1-8
      register: get_random
    - name: print variable
      debug:
        msg: "{{get_random.stdout}}"
    - name: set hostname
      hostname: name={{host}}-{{get_random.stdout}}.{{domain}}

执行

[04:06:55 root@centos8 ~]# ansible-playbook hostname.yml 

PLAY [websrvs] *********************************************************************************

TASK [Gathering Facts] *************************************************************************
ok: [172.31.0.48]
ok: [172.31.0.38]

TASK [get variable] ****************************************************************************
changed: [172.31.0.48]
changed: [172.31.0.38]

TASK [print variable] **************************************************************************
ok: [172.31.0.38] => {
    "msg": "453e7750"
}
ok: [172.31.0.48] => {
    "msg": "b89111a1"
}

TASK [set hostname] ****************************************************************************
changed: [172.31.0.38]
changed: [172.31.0.48]

PLAY RECAP *************************************************************************************
172.31.0.38                : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
172.31.0.48                : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 
原文地址:https://www.cnblogs.com/xuanlv-0413/p/14815179.html