Playbook中同样也支持变量
变量名:仅能由字母、数字和下划线组成,且只能以字母开头
变量定义:
variable=value
variable: value
范例:
http_port=80
http_port: 80
变量调用方式:
通过{{ variable_name }} 调用变量,且变量名前后建议加空格,有时用"{{ variable_name }}"才生效
变量来源:
- ansible 的 setup facts 远程主机的所有变量都可直接调用
- 通过命令行指定变量,优先级最高
[root@centos8 ~]# ansible-playbook -e varname=value test.yml
- 在playbook文件中定义
vars:
var1: value1
var2: value2
- 在独立的变量YAML文件中定义
- hosts: all
vars_files:
- vars.yml
- 在主机清单文件中定义
主机(普通)变量:主机组中主机单独定义,优先级高于公共变量
组(公共)变量:针对主机组中所有主机定义统一变量 - 在项目中针对主机和主机组定义
在项目目录中创建 host_vars和group_vars目录 - 在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