ansible-playbook高级用法
- ansible-playbook介绍
- playbook 剧本是由一个或多个"play"组成的列表
- play的主要功能在于将预定义的一组主机,装扮成事先通过ansible中的task定义好的角色。Task实际是调用ansible的一个module,将多个play组织在一个playbook中,即可以让它们联合起来,按事先编排的机制执行预定义的动作
- Playbook 文件是采用YAML语言编写的
YAML的格式
- 在单一文件第一行,用连续三个连字号"-" 开始,还有选择性的连续三个点号( … )用来表示文件的结尾
- 次行开始正常写Playbook的内容,一般建议写明该Playbook的功能
- 使用#号注释代码
- 缩进必须是统一的,不能空格和tab混用
- 缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的
- YAML文件内容是区别大小写的,key/value的值均需大小写敏感
- 多个key/value可同行写也可换行写,同行使用,分隔
- key后面冒号要加一个空格 比如: key: value
- value可是个字符串,也可是另一个列表
- YAML文件扩展名通常为yml或yaml
scalar 标量
#key对应value
name: wang
age: 18
#使用缩进的方式
name:
wang
age:
18
Dictionary 字典
- 字典由多个key与value构成,key和value之间用 :分隔, 并且 : 后面有一个空格,所有k/v可以放在一行,或者每个 k/v 分别放在不同行
#汇总模式
account: { name: wang, age: 30 }
#缩进模式
account:
name: wang
age: 18
List 列表
- 列表由多个元素组成,每个元素放在不同行,且元素前均使用"-"打头,并且 - 后有一个空格, 或者将所有元素用 [ ] 括起来放在同一行
course: [ linux , golang , python ]
#缩进模式
course:
- linux
- golang
- python
#数据里面也可以包含字典
course:
- linux: manjaro
- golang: gin
- python: django
三种常见的数据格式
- XML:Extensible Markup Language,可扩展标记语言,可用于数据交换和配置
- JSON:JavaScript Object Notation, JavaScript 对象表记法,主要用来数据交换或配置,不支持注释
- YAML:YAML Ain’t Markup Language YAML 不是一种标记语言, 主要用来配置,大小写敏感,不支持tab
- 可以用工具互相转换,参考网站:
- https://www.json2yaml.com/
- http://www.bejson.com/json/json2yaml/
Playbook 核心组件
- 一个playbook 中由多个组件组成,其中所用到的常见组件类型如下:
- Hosts 执行的远程主机列表
- Tasks 任务集,由多个task的元素组成的列表实现,每个task是一个字典,一个完整的代码块功能需最少元素需包括 name 和 task,一个name只能包括一个task
- Variables 内置变量或自定义变量在playbook中调用
- Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
- Handlers 和 notify 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
- tags 标签 指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断
hosts 组件
- Hosts:playbook中的每一个play的目的都是为了让特定主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机,须事先定义在主机清单中
one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*
Websrvs:dbsrvs #或者,两个组的并集
Websrvs:&dbsrvs #与,两个组的交集
webservers:!dbsrvs #在websrvs组,但不在dbsrvs组
remote_user 组件
- remote_user: 可用于Host和task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户
- hosts: websrvs
remote_user: root
tasks:
- name: test connection
ping:
remote_user: nameke
sudo: yes #默认sudo为root
sudo_user:chengzi #sudo为chengzi
task列表和action组件
- play的主体部分是task list,task list中有一个或多个task,各个task 按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个task后,再开始第二个task
- task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致
- 每个task都应该有其name,用于playbook的执行结果输出,建议其内容能清晰地描述任务执行步骤。
- 如果未提供name,则action的结果将用于输出
- task两种格式:
action: module arguments #示例: action: shell wall hello
module: arguments #建议使用 #示例: shell: wall hello
#注意:shell和command模块后面跟命令,而非key=value
---
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: install httpd
yum: name=httpd
- name: start httpd
service: name=httpd state=started enabled=yes
其它组件说明
- 某任务的状态在运行后为changed时,可通过"notify"通知给相应的handlers任务
- 还可以通过"tags"给task 打标签,可在ansible-playbook命令上使用-t指定进行调
ShellScripts VS Playbook 案例
#1、SHELL脚本实现
#!/bin/bash
# 安装Apache
yum install --quiet -y httpd
# 复制配置文件
cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
cp/tmp/vhosts.conf /etc/httpd/conf.d/
# 启动Apache,并设置开机启动
systemctl enable --now httpd
#2、Playbook实现
---
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: "安装Apache"
yum: name=httpd
- name: "复制配置文件"
copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
- name: "复制配置文件"
copy: src=/tmp/vhosts.conf dest=/etc/httpd/conf.d/
- name: "启动Apache,并设置开机启动"
service: name=httpd state=started enabled=yes
playbook 命令
- 格式:ansible-playbook <filename.yml> … [options]
#常用选项
--syntax-check #语法检查,可缩写成--syntax, 相当于bash -n
-C --check #模拟执行,只检测可能会发生的改变,但不真正执行操作,dry run
--list-hosts #列出运行任务的主机
--list-tags #列出tag
--list-tasks #列出task
--limit 主机列表 #只针对主机列表中的特定主机执行
-i INVENTORY #指定主机清单文件,通常一个项对应一个主机清单文件
--start-at-task START_AT_TASK #从指定task开始执行,而非从头开始,START_AT_TASK为任务的
name
-v -vv -vvv #显示过程
playbook应用案例
- 利用 playbook 创建 mysql 用户
---
- hosts: dbsrvs
remote_user: root
gather_facts: no
tasks:
- {name: create group, group: name=mysql system=yes gid=306}
- name: create user
user: name=mysql shell=/sbin/nologin system=yes group=mysql uid=306 home=/data/mysql create_home=no
- 利用 playbook 安装 nginx
---
# install nginx
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: add group nginx
group: name=nginx state=present
- name: add user nginx
user: name=nginx state=present group=nginx
- name: Install Nginx
yum: name=nginx state=present
- name: web page
copy: src=files/index.html dest=/usr/share/nginx/html/index.html
- name: Start Nginx
service: name=nginx state=started enabled=yes
- 利用 playbook 安装和卸载 httpd
[root@centos8 ansible]#cat install_httpd.yml
---
#install httpd
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: Instal1 httpd
yum: name=httpd
- name: Modify config list port
lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: '^Listen'
line: 'Listen 8080'
- name: Modify config data1
lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: '^DocumentRoot "/var/www/html"'
line: 'DocumentRoot "/data/html"'
- name: Modify config data2
lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: '^<Directory "/var/www/html">'
line: '<Directory "/data/html">'
- name: Mkdir website dir
file: path=/data/html state=directory
- name: Web html
copy: src=files/index.html dest=/data/html/
- name: Start service
service: name=httpd state=started enabled=yes
ansible-playbook instal_httpd.yml --limit 192.168.56.15
#remove_httpd.yml
---
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: remove httpd package
yum: name=httpd state=absent
- name: remove apache user
user: name=apache state=absent
- name: remove config file
file: name=/etc/httpd state=absent
- name: remove web html
file: name=/data/html/ state=absent
- 安装mysql-5.6.46-linux-glibc2.12
[root@ansible ~]#cat /data/ansible/files/my.cnf
[mysqld]
socket=/tmp/mysql.sock
user=mysql
symbolic-links=0
datadir=/data/mysql
innodb_file_per_table=1
log-bin
pid-file=/data/mysql/mysqld.pid
[client]
port=3306
socket=/tmp/mysql.sock
[mysqld_safe]
log-error=/var/log/mysqld.log
[root@ansible ~]#cat /data/ansible/files/secure_mysql.sh
#!/bin/bash
/usr/local/mysql/bin/mysql_secure_installation <<EOF
y
magedu
magedu
yyyy
EOF
[root@ansible ~]#tree /data/ansible/files/
/data/ansible/files/
├── my.cnf
├── mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
└── secure_mysql.sh
[root@ansible ~]#cat /data/ansible/install_mysql.yml
---
# install mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
- hosts: dbsrvs
remote_user: root
gather_facts: no
tasks:
- name: install packages
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 remote host and file mode
unarchive: src=/data/ansible/files/mysql-5.6.46-linux-glibc2.12-
x86_64.tar.gz dest=/usr/local/ owner=root group=root
- name: create linkfile /usr/local/mysql
file: src=/usr/local/mysql-5.6.46-linux-glibc2.12-x86_64
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 service
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
- 安装mariadb
---
#Installing MariaDB Binary Tarballs
- hosts: dbsrvs
remote_user: root
gather_facts: no
tasks:
- name: create group
group: name=mysql gid=27 system=yes
- name: create user
user: name=mysql uid=27 system=yes group=mysql shell=/sbin/nologin home=/data/mysql create_home=no
- name: mkdir datadir
file: path=/data/mysql owner=mysql group=mysql state=directory
- name: unarchive package
unarchive: src=/data/ansible/files/mariadb-10.2.27-linux-x86_64.tar.gz dest=/usr/local/ owner=root group=root
- name: link
file: src=/usr/local/mariadb-10.2.27-linux-x86_64 path=/usr/local/mysql state=link
- name: install database
shell: chdir=/usr/local/mysql ./scripts/mysql_install_db --datadir=/data/mysql --user=mysql
- name: config file
copy: src=/data/ansible/files/my.cnf dest=/etc/ backup=yes
- name: service script
shell: /bin/cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
- name: start service
service: name=mysqld state=started enabled=yes
- name: PATH variable
copy: content='PATH=/usr/local/mysql/bin:$PATH' dest=/etc/profile.d/mysql.sh
忽略错误 ignore_errors
- 如果一个task出错,默认将不会继续执行后续的其它task,利用 ignore_errors: yes 可以忽略此task的错误,继续向下执行playbook其它task
[root@ansible ansible]#cat test_ignore.yml
---
- hosts: websrvs
tasks:
- name: error
command: /bin/false
ignore_errors: yes
- name: continue
command: wall continue
handlers和notify
- Handlers本质是task list ,类似于MySQL中的触发器触发的行为,其中的task与前述的task并没有本质上的不同,主要用于当关注的资源发生变化时,才会采取一定的操作。
- 而Notify对应的action可用于在每个play的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作
- 注意:
- 如果多个task通知了相同的handlers, 此handlers仅会在所有tasks结束后运行一 次。
- 只有notify对应的task发生改变了才会通知handlers, 没有改变则不会触发handlers
- handlers 是在所有前面的tasks都成功执行才会执行,如果前面任何一个task失败,会导致handler跳过执行,可以使用force_handlers: yes 强制执行handler
---
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: Install httpd
yum: name=httpd state=present
- name: Install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/
notify:
- restart httpd
- wall
- name: ensure apache is running
service: name=httpd state=started enabled=yes
handlers:
- name: restart httpd
service: name=httpd state=restarted
- name: wall
command: wall "The config file is changed"
---
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: add group nginx
user: name=nginx state=present
- name: add user nginx
user: name=nginx state=present group=nginx
- name: Install Nginx
yum: name=nginx state=present
- name: config
copy: src=/root/config.txt dest=/etc/nginx/nginx.conf
notify: ["Restart Nginx","Check Nginx Process"] #或者下面格式
- Restart Nginx
- Check Nginx Process
handlers:
- name: Restart Nginx
service: name=nginx state=restarted enabled=yes
- name: Check Nginx process
shell: killall -0 nginx &> /tmp/nginx.log
tags组件
- 在playbook文件中,可以利用tags组件,为特定 task 指定标签,当在执行playbook时,可以只执行特定tags的task,而非整个playbook文件
- 可以一个task对应多个tag,也可以多个task对应一个tag
- 还有另外3个特殊关键字用于标签, tagged, untagged 和 all,它们分别是仅运行已标记,只有未标记和所有任务。
cat >httpd.yml<<EOF
---
# tags example
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: Install httpd
yum: name=httpd state=present
- name: Install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/
tags: [ conf,file ] #写在一行
- conf #写成多行
- file
- name: start httpd service
tags: service
service: name=httpd state=started enabled=yes
EOF
ansible-playbook --list-tags httpd.yml
ansible-playbook -t conf,service httpd.yml
ansible-playbook --skip-tags conf httpd.yml
ansible-playbook httpd.yml --skip-tags untagged
Playbook中使用变量
- 变量名:仅能由字母、数字和下划线组成,且只能以字母开头
#定义
variable=value
variable: value
#范例
http_port=80
http_port: 80
- 变量调用方式:通过 {{ variable_name }} 调用变量,且变量名前后建议加空格,有时用"{{ variable_name }}"才生效
- 变量来源
- \1. ansible 的 setup facts 远程主机的所有变量都可直接调用
- \2. 通过命令行指定变量,优先级最高
ansible-playbook -e varname=value test.yml
-
- \3. 在playbook文件中定义
vars:
var1: value1
var2: value2
-
- \4. 在独立的变量YAML文件中定义
- hosts: all
vars_files:
- vars.yml
-
- \5. 在主机清单文件中定义
- 主机(普通)变量:主机组中主机单独定义,优先级高于公共变量
- 组(公共)变量:针对主机组中所有主机定义统一变量
- \6. 在项目中针对主机和主机组定义
- 在项目目录中创建 host_vars和group_vars目录
- \7. 在role中定义
- \5. 在主机清单文件中定义
-
变量的优先级从高到低如下
-e选项定义变量-->playbook中vars_files -->playbook中vars变量定义-->host_vars/主机名文件-->主机清单中主机变量-->group_vars/主机组名文件-->group_vars/all文件-->主机清单组变量
#普通用户下[03:16:58 nameke@admin-dns ~/ansible]$ ansible --version
ansible 2.9.27
config file = /home/nameke/ansible/ansible.cfg
configured module search path = [u'/home/nameke/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
........#root用户家目录下
[03:17:19 root@admin-dns ~]# ansible --version
ansible 2.9.27
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
........#root用户指定目录下
[03:17:27 root@admin-dns ~]# cd ansible/
[03:17:36 root@admin-dns ~/ansible]# ansible --version
ansible 2.9.27
config file = /root/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
........
setup 模块中变量
-
facts 变量的实际使用场景案例
- 通过facts变量获取被控端CPU的个数信息,从而生成不同的Nginx配置文件
- 通过facts变量获取被控端内存大小信息,从而生成不同的memcached的配置文件
- 通过facts变量获取被控端主机名称信息,从而生成不同的Zabbix配置文件
- …
-
显示 eth0 网卡的 IP 地址
[root@ansible ansible]#cat show_ip.yml
- hosts: websrvs
tasks:
- name: show eth0 ip address {{ ansible_facts["eth0"]["ipv4"]["address"] }}
debug:
msg: IP address {{ ansible_eth0.ipv4.address }}
#msg: IP address {{ ansible_facts["eth0"]["ipv4"]["address"] }}
#msg: IP address {{ ansible_facts.eth0.ipv4.address }}
#msg: IP address {{ ansible_eth0.ipv4.address }}
#msg: IP address {{ ansible_eth0.ipv4.address.split('.')[-1] }} #取IP中的最后一个数字
[root@ansible ansible]#ansible-playbook -v show_ip.yml
- 在playbook 命令行中定义变量
vim var2.yml
---
- hosts: websrvs
remote_user: root
tasks:
- name: install package
yum: name={{ pkname }} state=present
[root@ansible ~]#ansible-playbook -e pkname=httpd var2.yml
#也可以将多个变量放在一个文件中
[root@ansible ~]#cat vars
pkname1: memcached
pkname2: vsftpd
[root@ansible ~]#vim var2.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@ansible ~]#ansible-playbook -e pkname1=memcached -e pkname2=httpd var5.yml
[root@ansible ~]#ansible-playbook -e '@vars' var2.yml
- 在playbook文件中定义变量
[root@ansible ~]#vim var3.yml
---
- 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@ansible ~]#ansible-playbook -e "username=user2 groupname=group2" var3.yml
- 变量的相互调用
[root@ansible ~]#cat var4.yaml
---
- hosts: websrvs
remote_user: root
vars:
collect_info: "/data/test/{{ansible_default_ipv4['address']}}/"
tasks:
- name: create IP directory
file: name="{{collect_info}}" state=directory
#执行结果
tree /data/test/
/data/test/
└── 10.0.0.102
1 directory, 0 files
[root@ansible ansible]#cat var2.yml
---
- hosts: websrvs
vars:
suffix: "txt"
file: "{{ ansible_nodename }}.{{suffix}}"
tasks:
- name: test var
file: path="/data/{{file}}" state=touch
#安装httpd
[root@ansible ~]#cat install.yml
- hosts: websrvs
vars:
web: httpd
db: mariadb-server
tasks:
- name: install {{ web }} {{ db }}
yum:
name:
- "{{ web }}"
- "{{ db }}"
state: latest
#安装httpd
[root@ansible ~]#cat install2.yml
- hosts: websrvs
tasks:
- name: install packages
yum: name={{ pack }}
vars:
pack:
- httpd
- memcached
- 范例:安装指定版本的MySQL
[root@ansible ansible]#cat install_mysql.yml
---
# install mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
- hosts: dbsrvs
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 packages
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 remote 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 service
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中定义的变量优化级高
vim vars.yml
---
# variables file
package_name: mariadb-server
service_name: mariadb
vim var5.yml
---
#install package and start service
- hosts: dbsrvs
remote_user: root
vars_files:
- vars.yml
tasks:
- name: install package
yum: name={{ package_name }}
tags: install
- name: start service
service: name={{ service_name }} state=started enabled=yes
主机和主机组的变量
#在inventory 主机清单文件中为指定的主机定义变量以便于在playbook中使用
[websrvs]
www1.magedu.com http_port=80 maxRequestsPerChild=808
www2.magedu.com http_port=8080 maxRequestsPerChild=909
- 所有项目的组(公共)变量
#在inventory 主机清单文件中赋予给指定组内所有主机上的在playbook中可用的变量,如果和主机变是同名,优先级低于主机变量
[websrvs:vars]
http_port=80
ntp_server=ntp.magedu.com
nfs_server=nfs.magedu.com
[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="magedu.local."
- 范例
[root@ansible ~]#vim /etc/ansible/hosts
[websrvs]
192.168.56.14 hname=www1 domain=chengzi.io
192.168.56.15 hname=www2
[websrvs:vars]
mark="-"
[all:vars]
domain=chengzi.org
[root@ansible ~]#ansible websrvs -m hostname -a 'name={{ hname }}{{ mark }}{{ domain }}'
#命令行指定变量:
[root@ansible ~]#ansible websrvs -e domain=chengzi.cn -m hostname -a 'name={{ hname }}{{ mark }}{{ domain }}'
- 范例: k8s 的ansible 变量文件
[etcd]
192.168.56.104 NODE_NAME=etcd1
192.168.56.105 NODE_NAME=etcd2
192.168.56.106 NODE_NAME=etcd3
[kube-master]
192.168.56.103 NEW_MASTER=yes
192.168.56.101
192.168.56.102
[kube-node]
192.168.56.109 NEW_NODE=yes
192.168.56.107
192.168.56.108
[harbor]
[ex-lb]
192.168.56.111 LB_ROLE=master EX_APISERVER_VIP=192.168.56.100 EX_APISERVER_PORT=8443
192.168.56.112 LB_ROLE=backup EX_APISERVER_VIP=192.168.56.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="chengzi.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/192.168.56.08
id: 2
[root@ansible ansible]#cat host_vars/192.168.56.07
id: 1
[root@ansible ansible]#cat group_vars/websrvs
name: web
[root@ansible ansible]#cat group_vars/all
domain: chengzi.org
[root@ansible ansible]#tree host_vars/ group_vars/
host_vars/
├── 192.168.56.08
└── 192.168.56.07
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中获取数据。
[root@centos8 ~]#ansible-playbook register1.yml
- 范例:使用 register 注册变量创建文件
[root@centos8 ~]#cat register2.yml
- hosts: dbsrvs
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模块
[root@centos8 ~]#cat debug_test.yml
---
- hosts: dbsrvs
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
- 范例: 安装启动服务并检查
[root@ansible ansible]#cat service.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 }} state=started enabled=yes
- name: check
shell: ps axu|grep {{ service_name }}
register: check_service
- name: debug
debug:
msg: "{{ check_service.stdout_lines }}"
[root@ansible ansible]#ansible-playbook service.yml
- 范例: 批量修改主机名
[root@ansible ansible]#cat hostname.yml
- hosts: websrvs
vars:
host: web
domain: chengzi.org
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 }}
[root@ansible ansible]#ansible-playbook hostname.yml