Introduction To Ad-Hoc Commands — 国内最专业的Ansible中文官方学习手册
自动化运维工具——ansible详解(一) - 珂儿吖 - 博客园
【Ansible】记一次技术博客害死人的经历——ansible模板变量注入探究 - 黄烤鸭 - 博客园
自动化运维工具——ansible详解(二) - 珂儿吖 - 博客园
https://www.zsythink.net/archives/3063/
ansible笔记(1):ansible的基本概念-朱双印博客
Ansible快速入门#
介绍#
Ansible
是一款简单的运维自动化工具,只需要使用ssh
协议连接就可以来进行系统管理,自动化执行命令,部署等任务。ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。
ansible是基于 paramiko 开发的,并且基于模块化工作,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。ansible不需要在远程主机上安装client/agents,因为它们是基于ssh来和远
程主机通讯的。ansible目前已经已经被红帽官方收购,是自动化运维工具中大家认可度最高的,并且上手容易,学习简单。是每位运维工程师必须掌握的技能之一。
Ansible的特点
- ansible不需要单独安装客户端,也不需要启动任何服务
- ansible是python中的一套完整的自动化执行任务模块
- ansible playbook 采用yaml配置,对于自动化任务执行过一目了然
- 部署简单,只需在主控端部署Ansible环境,被控端无需做任何操作;
- 默认使用SSH协议对设备进行管理;
- 有大量常规运维操作模块,可实现日常绝大部分操作;
- 配置简单、功能强大、扩展性强;
- 支持API及自定义模块,可通过Python轻松扩展;
- 通过Playbooks来定制强大的配置、状态管理;
- 轻量级,无需在客户端安装agent,更新时,只需在操作机上进行一次更新即可;
- 提供一个功能强大、操作性强的Web管理界面和REST API接口——AWX平台。
ansible 架构图
上图中我们看到的主要模块如下:
Ansible
:Ansible核心程序。HostInventory
:记录由Ansible管理的主机信息,包括端口、密码、ip等。Playbooks
:“剧本”YAML格式文件,多个任务定义在一个文件中,定义主机需要调用哪些模块来完成的功能。CoreModules
:核心模块,主要操作是通过调用核心模块来完成管理任务。CustomModules
:自定义模块,完成核心模块无法完成的功能,支持多种语言。ConnectionPlugins
:连接插件,Ansible和Host通信使用
ansible 任务执行
ansible 任务执行模式
Ansible 系统由控制主机对被管节点的操作方式可分为两类,即adhoc
和playbook
:
- ad-hoc模式(点对点模式)
使用单个模块,支持批量执行单条命令。ad-hoc 命令是一种可以快速输入的命令,而且不需要保存起来的命令。就相当于bash中的一句话shell。 - playbook模式(剧本模式)
是Ansible主要管理方式,也是Ansible功能强大的关键所在。playbook通过多个task集合完成一类功能,如Web服务的安装部署、数据库服务器的批量备份等。可以简单地把playbook理解为通过组合多条ad-hoc操作的配置文件。
简单理解就是Ansible在运行时, 首先读取ansible.cfg
中的配置, 根据规则获取Inventory
中的管理主机列表, 并行的在这些主机中执行配置的任务, 最后等待执行返回的结果。
ansible 命令执行过程
- 加载自己的配置文件,默认
/etc/ansible/ansible.cfg
; - 查找对应的主机配置文件,找到要执行的主机或者组;
- 加载自己对应的模块文件,如 command;
- 通过ansible将模块或命令生成对应的临时py文件(python脚本), 并将该文件传输至远程服务器;
- 对应执行用户的家目录的
.ansible/tmp/XXX/XXX.PY
文件; - 给文件 +x 执行权限;
- 执行并返回结果;
- 删除临时py文件,
sleep 0
退出;
Ansible组成结构
-
- Ansible
是Ansible
的命令工具,核心执行工具;一次性或临时执行的操作都是通过该命令执行。 - Ansible Playbook
任务剧本(又称任务集),编排定义Ansible
任务集的配置文件,由Ansible
顺序依次执行,yaml
格式。 - Inventory
Ansible
管理主机的清单,默认是/etc/ansible/hosts
文件。 - Modules
Ansible
执行命令的功能模块,Ansible2.3
版本为止,共有1039
个模块。还可以自定义模块。 - Plugins
插件,模块功能的补充,常有连接类型插件,循环插件,变量插件,过滤插件,插件功能用的较少。 - API
提供给第三方程序调用的应用程序编程接口。
- Ansible
环境准备#
IP | 系统 | 主机名 | 描述 |
---|---|---|---|
10.10.1.142 | CentOS8.2 | 10.10.1.142 mbs.cclinux.net.cn mbs | ansible管理节点 |
10.10.1.181 | CentOS8.2 | 10.10.1.181 mbs.cclinux.net.cn mbs1 | 被管理节点1 |
10.10.1.134 | CentOS8.2 | 10.10.1.134 mbs.cclinux.net.cn mbs2 | 被管理节点2 |
Ansible安装#
ansible 配置详解
ansible安装常用两种方式,yum安装
和pip程序安装
。下面我们来详细介绍一下这两种安装方式。
使用 pip(python的包管理模块)安装
首先,我们需要安装一个python-pip
包,安装完成以后,则直接使用pip
命令来安装我们的包,具体操作过程如下:
yum install python-pip
pip install ansible
使用 yum 安装
yum 安装是我们很熟悉的安装方式了。我们需要先安装一个epel-release
包,然后再安装我们的 ansible 即可。
yum install epel-release -y
yum install ansible –y
1)配置epel
源
[root@mbs roles]# dnf install epel-release -y
[root@mbs roles]# dnf install ansible -y
# 查看ansible版本
[root@mbs roles]# ansible --version
ansible 2.9.15
config file = /etc/ansible/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.6/site-packages/ansible
executable location = /usr/bin/ansible
python version = 3.6.8 (default, Apr 16 2020, 01:36:27) [GCC 8.3.1 20191121 (Red Hat 8.3.1-5)]
[root@mbs roles]#
ansible 程序结构
安装目录如下(yum安装):
配置文件目录:/etc/ansible/
执行文件目录:/usr/bin/
Lib库依赖目录:/usr/lib/pythonX.X/site-packages/ansible/
Help文档目录:/usr/share/doc/ansible-X.X.X/
Man文档目录:/usr/share/man/man1/
ansible配置文件查找顺序
ansible与我们其他的服务在这一点上有很大不同,这里的配置文件查找是从多个地方找的,顺序如下:
- 检查环境变量
ANSIBLE_CONFIG
指向的路径文件(export ANSIBLE_CONFIG=/etc/ansible.cfg); ~/.ansible.cfg
,检查当前目录下的ansible.cfg配置文件;/etc/ansible.cfg
检查etc目录的配置文件。
ansible配置文件
ansible 的配置文件为/etc/ansible/ansible.cfg
,ansible 有许多参数,下面我们列出一些常见的参数:
inventory = /etc/ansible/hosts #这个参数表示资源清单inventory文件的位置
library = /usr/share/ansible #指向存放Ansible模块的目录,支持多个目录方式,只要用冒号(:)隔开就可以
forks = 5 #并发连接数,默认为5
sudo_user = root #设置默认执行命令的用户
remote_port = 22 #指定连接被管节点的管理端口,默认为22端口,建议修改,能够更加安全
host_key_checking = False #设置是否检查SSH主机的密钥,值为True/False。关闭后第一次连接不会提示配置实例
timeout = 60 #设置SSH连接的超时时间,单位为秒
log_path = /var/log/ansible.log #指定一个存储ansible日志的文件(默认不记录日志)
ansuble主机清单
在配置文件中,我们提到了资源清单,这个清单就是我们的主机清单,里面保存的是一些 ansible 需要连接管理的主机列表。我们可以来看看他的定义方式:
1、 直接指明主机地址或主机名:
## green.example.com#
# blue.example.com#
# 192.168.100.1
# 192.168.100.10
2、 定义一个主机组[组名]把地址或主机名加进去
[mysql_test]
192.168.253.159
192.168.253.160
192.168.253.153
需要注意的是,这里的组成员可以使用通配符来匹配,这样对于一些标准化的管理来说就很轻松方便了。
我们可以根据实际情况来配置我们的主机列表,具体操作如下:
[root@server ~]# vim /etc/ansible/hosts
[web]
192.168.37.122
192.168.37.133
Ansible Inventory文件#
Inventory
文件通常用于定义要管理的主机的认证信息,例如ssh
登录用户名、密码以及key
相关信息。可以同时操作一个组的多台主机,组与主机组之间的关系都是通过inventory
文件配置。配置文件路径为:/etc/ansible/hosts
基于密码连接
介绍
# 方法一 主机+端口+密码
[webserver]
192.168.1.31 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass="123456"
192.168.1.32 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass="123456"
192.168.1.33 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass="123456"
192.168.1.36 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass="123456"
# 方法二 主机+端口+密码
[webserver]
192.168.1.3[1:3] ansible_ssh_user=root ansible_ssh_pass="123456"
# 方法二 主机+端口+密码
[webserver]
192.168.1.3[1:3]
[webserver:vars]
ansible_ssh_pass="123456"
本人
[root@mbs roles]# cat /etc/ansible/hosts
# This is the default ansible 'hosts' file.
#
# It should live in /etc/ansible/hosts
#
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups
# Ex 1: Ungrouped hosts, specify before any group headers.
## green.example.com
## blue.example.com
## 192.168.100.1
## 192.168.100.10
# Ex 2: A collection of hosts belonging to the 'webservers' group
## [webservers]
## alpha.example.org
## beta.example.org
## 192.168.1.100
## 192.168.1.110
[wubo]
10.10.1.134 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass="123456aA"
10.10.1.181 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass="123456aA"
#[nginx]
#10.10.1.134
#10.10.1.181
#[nginx.vars]
#ansible_ssh_port=22
#ansible_ssh_user=root
#ansible_ssh_pass='123456aA'
#[wubo:children]
#nginx
基于秘钥连接#
基于秘钥连接需要先创建公钥和私钥,并发送给被管理机器
1)生成公私钥
[root@ansible ~]# ssh-keygen
[root@ansible ~]# for i in {1,2,3,6}; do ssh-copy-id -i 10.10.1.3$i ; done
主机组的使用#
# 主机组变量名+主机+密码
[apache]
10.10.1.181
10.10.1.134
[apache.vars]
ansible_ssh_pass='123456aA'
# 主机组变量名+主机+密钥
[nginx]
10.10.1.3[1:2]
# 定义多个组,把一个组当另外一个组的组员
[webserver:children] #webserver组包括两个子组:apache nginx
apache
nginx
临时指定inventory#
1)先编辑一个主机定义清单
[root@ansible ~]# vim /etc/dockers
[dockers]
192.168.1.31 ansible_ssh_pass='123456'
192.168.1.32
192.168.1.33
2)在执行命令是指定inventory
[root@ansible ~]# ansible dockers -m ping -i /etc/dockers -o
192.168.1.33 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
192.168.1.32 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
192.168.1.31 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
Inventory内置参数![](https://img-blog.csdnimg.cn/img_convert/c6c790b00afb923b529957080d018795.png)
Ansible Ad-Hoc#
ad-hoc —— 临时的,在ansible
中是指需要快速执行,并且不需要保存的命令。说白了就是执行简单的命令——一条命令。对于复杂的命令则为playbook
,类似于saltstack
的state sls
状态文件。
ansible命令格式#
1)常用命令参数
[root@ansible ~]# ansible -h
Usage: ansible <host-pattern> [options]
-a MODULE_ARGS #模块参数
-C, --check #检查语法
-f FORKS #并发
--list-hosts #列出主机列表
-m MODULE_NAME #模块名字
-o 使用精简的输出
2)示例
[root@mbs roles]# ansible wubo -m shell -a 'uptime' -o
[root@mbs roles]# ansible wubo -m shell -a 'uptime' -o
10.10.1.134 | CHANGED | rc=0 | (stdout) 16:34:28 up 7:17, 2 users, load average: 0.00, 0.00, 0.00
10.10.1.181 | CHANGED | rc=0 | (stdout) 16:34:28 up 7:17, 2 users, load average: 0.00, 0.00, 0.00
3)命令说明
host-pattern格式#
目标target
主机,主机组匹配方式
主机的匹配
[root@mbs roles]# ansible 10.10.1.181 -m ping
10.10.1.181 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
[root@mbs roles]#
组的匹配
# 组的配置信息如下:这里定义了一个nginx组和一个apache组
[root@ansible ~]# ansible nginx --list
hosts (2):
192.168.1.31
192.168.1.32
[root@ansible ~]# ansible apache --list
hosts (3):
192.168.1.36
192.168.1.33
192.168.1.32
# 一个组的所有主机匹配
[root@ansible ~]# ansible apache -m ping
# 匹配apache组中有,但是nginx组中没有的所有主机
#匹配apache组nginx组两个组所有的机器(差集)
[root@ansible ~]# ansible 'apache:!nginx' -m ping -o
192.168.1.36 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
192.168.1.33 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
# 匹配apache组和nginx组中都有的机器(并集)
[root@ansible ~]# ansible 'apache:&nginx' -m ping -o
192.168.1.32 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
# 匹配apache组nginx组两个组所有的机器(合集);等于ansible apache,nginx -m ping
[root@ansible ~]# ansible 'apache:nginx' -m ping -o
192.168.1.32 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
192.168.1.31 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
192.168.1.33 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
192.168.1.36 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
复制代码
ansible 常用命令
ansible 命令集
/usr/bin/ansible
Ansibe AD-Hoc 临时命令执行工具,常用于临时命令的执行/usr/bin/ansible-doc
Ansible 模块功能查看工具/usr/bin/ansible-galaxy
下载/上传优秀代码或Roles模块 的官网平台,基于网络的/usr/bin/ansible-playbook
Ansible 定制自动化的任务集编排工具/usr/bin/ansible-pull
Ansible远程执行命令的工具,拉取配置而非推送配置(使用较少,海量机器时使用,对运维的架构能力要求较高)/usr/bin/ansible-vault
Ansible 文件加密工具/usr/bin/ansible-console
Ansible基于Linux Consoble界面可与用户交互的命令执行工具
其中,我们比较常用的是/usr/bin/ansible
和/usr/bin/ansible-playbook
。
ansible-doc 命令
ansible-doc 命令常用于获取模块信息及其使用帮助,一般用法如下:
ansible-doc -l #获取全部模块的信息
ansible-doc -s MOD_NAME #获取指定模块的使用帮助
我们也可以查看一下ansible-doc的全部用法:
[root@server ~]# ansible-doc
Usage: ansible-doc [options] [module...]
Options:
-h, --help show this help message and exit # 显示命令参数API文档
-l, --list List available modules #列出可用的模块
-M MODULE_PATH, --module-path=MODULE_PATH #指定模块的路径
specify path(s) to module library (default=None)
-s, --snippet Show playbook snippet for specified module(s) #显示playbook制定模块的用法
-v, --verbose verbose mode (-vvv for more, -vvvv to enable # 显示ansible-doc的版本号查看模块列表:
connection debugging)
--version show program's version number and exit
我们可以来看一下,以mysql相关的为例:
[root@server ~]# ansible-doc -l |grep mysql
mysql_db Add or remove MySQL databases from a remote...
mysql_replication Manage MySQL replication
mysql_user Adds or removes a user from a MySQL databas...
mysql_variables Manage MySQL global variables
[root@server ~]# ansible-doc -s mysql_user
ansible 命令详解
命令的具体格式如下:
ansible <host-pattern> [-f forks] [-m module_name] [-a args]
也可以通过ansible -h
来查看帮助,下面我们列出一些比较常用的选项,并解释其含义:
-a MODULE_ARGS
#模块的参数,如果执行默认COMMAND的模块,即是命令参数,如: “date”,“pwd”等等-k
,--ask-pass
#ask for SSH password。登录密码,提示输入SSH密码而不是假设基于密钥的验证--ask-su-pass
#ask for su password。su切换密码-K
,--ask-sudo-pass
#ask for sudo password。提示密码使用sudo,sudo表示提权操作--ask-vault-pass
#ask for vault password。假设我们设定了加密的密码,则用该选项进行访问-B SECONDS
#后台运行超时时间-C
#模拟运行环境并进行预运行,可以进行查错测试-c CONNECTION
#连接类型使用-f FORKS
#并行任务数,默认为5-i INVENTORY
#指定主机清单的路径,默认为/etc/ansible/hosts
--list-hosts
#查看有哪些主机组-m MODULE_NAME
#执行模块的名字,默认使用 command 模块,所以如果是只执行单一命令可以不用 -m参数-o
#压缩输出,尝试将所有结果在一行输出,一般针对收集工具使用-S
#用 su 命令-R SU_USER
#指定 su 的用户,默认为 root 用户-s
#用 sudo 命令-U SUDO_USER
#指定 sudo 到哪个用户,默认为 root 用户-T TIMEOUT
#指定 ssh 默认超时时间,默认为10s,也可在配置文件中修改-u REMOTE_USER
#远程用户,默认为 root 用户-v
#查看详细信息,同时支持-vvv
,-vvvv
可查看更详细信息
ansible 配置公私钥
上面我们已经提到过 ansible 是基于 ssh 协议实现的,所以其配置公私钥的方式与 ssh 协议的方式相同,具体操作步骤如下:
#1.生成私钥
[root@server ~]# ssh-keygen
#2.向主机分发私钥
[root@server ~]# ssh-copy-id root@192.168.37.122
[root@server ~]# ssh-copy-id root@192.168.37.133
这样的话,就可以实现无密码登录,我们的实验过程也会顺畅很多。
注意,如果出现了一下报错:
-bash: ssh-copy-id: command not found
那么就证明我们需要安装一个包:
yum -y install openssh-clientsansible
把包安装上即可。
[root@mbs roles]# ls
httpd mysql nginx roles.yml
[root@mbs roles]# pwd
/root/ansible/roles
[root@mbs roles]# find ./nginx/
./nginx/
./nginx/default
./nginx/files
./nginx/files/a.txt
./nginx/handlers
./nginx/handlers/main.yml
./nginx/meta
./nginx/tasks
./nginx/tasks/main.yml
./nginx/templates
./nginx/templates/nginx.conf.j2
./nginx/vars
./nginx/vars/main.yml
roles.yml
[root@mbs roles]# cat roles.yml
- hosts: wubo
remote_user: root
roles:
- nginx
task:main.yml
[root@mbs roles]# cat nginx/tasks/main.yml
- name: install {{ rpmname }}
dnf: name={{ rpmname }} state=present
- name: copy a.txt
copy: src=a.txt dest=/tmp/ backup=yes
- name: copy {{ rpmname }}.config
template: src={{ rpmname }}.conf.j2 dest=/etc/{{ rpmname }}/{{ rpmname }}.conf backup=yes
notify: reload
tags: reload{{ rpmname }}
- name: starting server
service: name={{ rpmname }} state=started
tags: start{{ rpmname }}
file:a.txt
[root@mbs roles]# cat nginx/files/a.txt
aaa
templates:nginx.conf.j2
[root@mbs roles]# cat nginx/templates/nginx.conf.j2
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes {{ ansible_processor_vcpus }};
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
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;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen {{ nginxport }} default_server;
listen [::]:{{ nginxport }} default_server;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
# Settings for a TLS enabled server.
#
# server {
# listen 443 ssl http2 default_server;
# listen [::]:443 ssl http2 default_server;
# server_name _;
# root /usr/share/nginx/html;
#
# ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers PROFILE=SYSTEM;
# ssl_prefer_server_ciphers on;
#
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
#
# location / {
# }
#
# error_page 404 /404.html;
# location = /40x.html {
# }
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
}
vars:main.yml
[root@mbs roles]# cat nginx/vars/main.yml
rpmname: nginx
nginxport: 9999
handlers:main.yml
[root@mbs roles]# cat nginx/handlers/main.yml
- name: reload
service: name=nginx state=restarted
如你所见,我创建的示例角色的角色名为demorole,demorole目录就代表了这个角色,此目录中包含了defaults 、files 、handlers 、meta 、tasks 、templates 、vars等子目录,而且在defaults 、handlers 、meta 、tasks 、vars等目录中,还都有一个名为”main.yml”的文件,那么这样的目录结构代表了什么含义呢?我们一起来了解一下,在角色中,上述目录结构的作用如下:
注:此处先进行大致介绍,以便你有一个大概的印象,之后会有对应的示例,所以,如果有疑问请先保留。
tasks目录:角色需要执行的主任务文件放置在此目录中,默认的主任务文件名为main.yml,当调用角色时,默认会执行main.yml文件中的任务,你也可以将其他需要执行的任务文件通过include的方式包含在tasks/main.yml文件中。
handlers目录:当角色需要调用handlers时,默认会在此目录中的main.yml文件中查找对应的handler
defaults目录:角色会使用到的变量可以写入到此目录中的main.yml文件中,通常,defaults/main.yml文件中的变量都用于设置默认值,以便在你没有设置对应变量值时,变量有默认的值可以使用,定义在defaults/main.yml文件中的变量的优先级是最低的。
vars目录:角色会使用到的变量可以写入到此目录中的main.yml文件中,看到这里你肯定会有疑问,vars/main.yml文件和defaults/main.yml文件的区别在哪里呢?区别就是,defaults/main.yml文件中的变量的优先级是最低的,而vars/main.yml文件中的变量的优先级非常高,如果你只是想提供一个默认的配置,那么你可以把对应的变量定义在defaults/main.yml中,如果你想要确保别人在调用角色时,使用的值就是你指定的值,则可以将变量定义在vars/main.yml中,因为定义在vars/main.yml文件中的变量的优先级非常高,所以其值比较难以覆盖。
meta目录:如果你想要赋予这个角色一些元数据,则可以将元数据写入到meta/main.yml文件中,这些元数据用于描述角色的相关属性,比如 作者信息、角色主要作用等等,你也可以在meta/main.yml文件中定义这个角色依赖于哪些其他角色,或者改变角色的默认调用设定,在之后会有一些实际的示例,此处不用纠结。
templates目录: 角色相关的模板文件可以放置在此目录中,当使用角色相关的模板时,如果没有指定路径,会默认从此目录中查找对应名称的模板文件。
files目录:角色可能会用到的一些其他文件可以放置在此目录中,比如,当你定义nginx角色时,需要配置https,那么相关的证书文件即可放置在此目录中。
当然,上述目录并不全是必须的,也就是说,如果你的角色并没有相关的模板文件,那么角色目录中并不用包含templates目录,同理,其他目录也一样,一般情况下,都至少会有一个tasks目录。
启动服务
[root@mbs roles]# ansible-playbook roles.yml
PLAY [wubo] **************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************************************************************************************************************
ok: [10.10.1.134]
ok: [10.10.1.181]
TASK [install nginx] *****************************************************************************************************************************************************************************************************************
ok: [10.10.1.134]
ok: [10.10.1.181]
TASK [nginx : copy a.txt] ************************************************************************************************************************************************************************************************************
ok: [10.10.1.134]
ok: [10.10.1.181]
TASK [copy nginx.config] *************************************************************************************************************************************************************************************************************
ok: [10.10.1.134]
ok: [10.10.1.181]
TASK [nginx : starting server] *******************************************************************************************************************************************************************************************************
ok: [10.10.1.181]
ok: [10.10.1.134]
PLAY RECAP ***************************************************************************************************************************************************************************************************************************
10.10.1.134 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.10.1.181 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@mbs roles]#
重点 变量范围问题
1.vars变量只能同主机同play使用,不可以跨主机和play使用
2.注册变量register:不能跨主机,可以跨play,也就是相同主机的不同play是可以使用注册变量的
3.set_fact:变量走的是【TASK [Gathering Facts]】 相当于往“Gathering Facts” 里面添加的信息属于主机信息了所以想使用必须是yes状态 gather_facts: yes才可以,这样是可以跨主机使用的,而且是必须是在使用者之前执行才可以
4.组变量,主机变量
5.魔法变量
6.lookup生成变量
结构如下
[root@localhost k3s-ansible-master]# ls
ansible.cfg a.yaml b.yaml inventory LICENSE reset_role.yml roles site_role.yml test.yml
[root@localhost k3s-ansible-master]# ls roles/
copy download k3s prereq raspberrypi registry reset test test1 ui
案例一 vars:当前play 局部变量
[root@localhost k3s-ansible-master]# cat test.yml
---
- hosts: master
remote_user: root
gather_facts: yes
become: yes
roles:
- role: test
- hosts: master
remote_user: root
gather_facts: yes
become: yes
roles:
- role: test1
test 的task:
/root/wubo/k3s/k3s-ansible-master/roles/test/tasks
[root@localhost tasks]# cat main.yml
---
- name: set-fact-test
vars:
name : wubo
debug:
msg: "wubo===>{{name}}"
test1 的task:
/root/wubo/k3s/k3s-ansible-master/roles/test1/tasks
[root@localhost tasks]# cat main.yml
---
- name: debug-test1
debug:
msg: "{{ name }}"
执行结果
[root@localhost k3s-ansible-master]# ansible-playbook -i inventory/jettech-cluster/hosts.ini test.yml
PLAY [master] *********************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************
Wednesday 12 January 2022 10:05:13 +0800 (0:00:00.031) 0:00:00.031 *****
ok: [172.16.10.5]
TASK [set-fact-test] **************************************************************************************************************************************************************
Wednesday 12 January 2022 10:05:18 +0800 (0:00:04.556) 0:00:04.588 *****
ok: [172.16.10.5] => {
"msg": "wubo===>wubo"
}
PLAY [master] *********************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************
Wednesday 12 January 2022 10:05:18 +0800 (0:00:00.085) 0:00:04.673 *****
ok: [172.16.10.5]
TASK [debug-test1] ****************************************************************************************************************************************************************
Wednesday 12 January 2022 10:05:22 +0800 (0:00:03.799) 0:00:08.473 *****
fatal: [172.16.10.5]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'name' is undefined\n\nThe error appears to be in '/root/wubo/k3s/k3s-ansible-master/roles/test1/tasks/main.yml': line 3, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: debug-test1\n ^ here\n"}
PLAY RECAP ************************************************************************************************************************************************************************
172.16.10.5 : ok=3 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
Wednesday 12 January 2022 10:05:22 +0800 (0:00:00.062) 0:00:08.536 *****
===============================================================================
Gathering Facts ------------------------------------------------------------------------------------------------------------------------------------------------------------ 4.56s
Gathering Facts ------------------------------------------------------------------------------------------------------------------------------------------------------------ 3.80s
set-fact-test -------------------------------------------------------------------------------------------------------------------------------------------------------------- 0.09s
debug-test1 ---------------------------------------------------------------------------------------------------------------------------------------------------------------- 0.06s
说明vars定义的变量不能夸paly,不能夸play就更不能夸主机了,目前是相同主机都是master
案例二 register:play之间的局部变量,不能夸节点(host),可以通过set_fact实现跨节点
test 的task:
[root@localhost tasks]# cat main.yml
---
- name: set-fact-test
#set_fact:
shell: "echo wubo"
register: result
test1的task:
[root@localhost tasks]# cat main.yml
---
- name: debug-test1
debug:
msg: "{{ result }}"
执行结果,相同主机
[root@localhost k3s-ansible-master]# ansible-playbook -i inventory/jettech-cluster/hosts.ini test.yml
PLAY [master] *********************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************
Wednesday 12 January 2022 10:08:23 +0800 (0:00:00.031) 0:00:00.031 *****
ok: [172.16.10.5]
TASK [set-fact-test] **************************************************************************************************************************************************************
Wednesday 12 January 2022 10:08:28 +0800 (0:00:04.385) 0:00:04.417 *****
changed: [172.16.10.5]
PLAY [master] *********************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************
Wednesday 12 January 2022 10:08:28 +0800 (0:00:00.762) 0:00:05.180 *****
ok: [172.16.10.5]
TASK [debug-test1] ****************************************************************************************************************************************************************
Wednesday 12 January 2022 10:08:32 +0800 (0:00:03.834) 0:00:09.014 *****
ok: [172.16.10.5] => {
"msg": {
"changed": true,
"cmd": "echo wubo",
"delta": "0:00:00.059649",
"end": "2022-01-12 10:08:28.658308",
"failed": false,
"rc": 0,
"start": "2022-01-12 10:08:28.598659",
"stderr": "",
"stderr_lines": [],
"stdout": "wubo",
"stdout_lines": [
"wubo"
]
}
}
PLAY RECAP ************************************************************************************************************************************************************************
172.16.10.5 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Wednesday 12 January 2022 10:08:32 +0800 (0:00:00.082) 0:00:09.097 *****
===============================================================================
Gathering Facts ------------------------------------------------------------------------------------------------------------------------------------------------------------ 4.39s
Gathering Facts ------------------------------------------------------------------------------------------------------------------------------------------------------------ 3.83s
set-fact-test -------------------------------------------------------------------------------------------------------------------------------------------------------------- 0.76s
debug-test1 ---------------------------------------------------------------------------------------------------------------------------------------------------------------- 0.08s
执行结果,不同主机
[root@localhost k3s-ansible-master]# cat test.yml
---
- hosts: master
remote_user: root
gather_facts: yes
become: yes
roles:
- role: test
- hosts: node
remote_user: root
gather_facts: yes
become: yes
roles:
- role: test1
[root@localhost k3s-ansible-master]# ansible-playbook -i inventory/jettech-cluster/hosts.ini test.yml
PLAY [master] *********************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************
Wednesday 12 January 2022 10:09:28 +0800 (0:00:00.034) 0:00:00.034 *****
ok: [172.16.10.5]
TASK [set-fact-test] **************************************************************************************************************************************************************
Wednesday 12 January 2022 10:09:32 +0800 (0:00:04.321) 0:00:04.356 *****
changed: [172.16.10.5]
PLAY [node] ***********************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************
Wednesday 12 January 2022 10:09:33 +0800 (0:00:00.750) 0:00:05.107 *****
ok: [172.16.10.15]
TASK [debug-test1] ****************************************************************************************************************************************************************
Wednesday 12 January 2022 10:09:37 +0800 (0:00:03.856) 0:00:08.964 *****
fatal: [172.16.10.15]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'result' is undefined\n\nThe error appears to be in '/root/wubo/k3s/k3s-ansible-master/roles/test1/tasks/main.yml': line 3, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: debug-test1\n ^ here\n"}
PLAY RECAP ************************************************************************************************************************************************************************
172.16.10.15 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
172.16.10.5 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Wednesday 12 January 2022 10:09:37 +0800 (0:00:00.060) 0:00:09.024 *****
===============================================================================
Gathering Facts ------------------------------------------------------------------------------------------------------------------------------------------------------------ 4.32s
Gathering Facts ------------------------------------------------------------------------------------------------------------------------------------------------------------ 3.86s
set-fact-test -------------------------------------------------------------------------------------------------------------------------------------------------------------- 0.75s
debug-test1 ---------------------------------------------------------------------------------------------------------------------------------------------------------------- 0.06s
结果报错变量没有定义,说明注册变量只能是相同主机,相同play或不同play可以使用边变量
案例三 set_fact定义新的变量:全局变量,可以跨主机跨play
test的task
[root@localhost tasks]# cat main.yml
---
- name: set-fact-test
set_fact:
name: wubo
test1的task
[root@localhost tasks]# cat main.yml
---
- name: debug-test1
debug:
msg: "{{ name }}"
相同主机情况下
[root@localhost k3s-ansible-master]# cat test.yml
---
- hosts: master
remote_user: root
gather_facts: yes
become: yes
roles:
- role: test
- hosts: master
remote_user: root
gather_facts: yes
become: yes
roles:
- role: test1
执行看结果
[root@localhost k3s-ansible-master]# ansible-playbook -i inventory/jettech-cluster/hosts.ini test.yml
PLAY [master] *********************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************
Wednesday 12 January 2022 10:12:40 +0800 (0:00:00.031) 0:00:00.031 *****
ok: [172.16.10.5]
TASK [set-fact-test] **************************************************************************************************************************************************************
Wednesday 12 January 2022 10:12:44 +0800 (0:00:04.380) 0:00:04.411 *****
ok: [172.16.10.5]
PLAY [master] *********************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************
Wednesday 12 January 2022 10:12:44 +0800 (0:00:00.046) 0:00:04.458 *****
ok: [172.16.10.5]
TASK [debug-test1] ****************************************************************************************************************************************************************
Wednesday 12 January 2022 10:12:48 +0800 (0:00:03.746) 0:00:08.204 *****
ok: [172.16.10.5] => {
"msg": "wubo"
}
PLAY RECAP ************************************************************************************************************************************************************************
172.16.10.5 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Wednesday 12 January 2022 10:12:48 +0800 (0:00:00.065) 0:00:08.270 *****
===============================================================================
Gathering Facts ------------------------------------------------------------------------------------------------------------------------------------------------------------ 4.38s
Gathering Facts ------------------------------------------------------------------------------------------------------------------------------------------------------------ 3.75s
debug-test1 ---------------------------------------------------------------------------------------------------------------------------------------------------------------- 0.07s
set-fact-test -------------------------------------------------------------------------------------------------------------------------------------------------------------- 0.05s
[root@localhost k3s-ansible-master]#
不同主机情况下
[root@localhost k3s-ansible-master]# cat test.yml
---
- hosts: master
remote_user: root
gather_facts: yes
become: yes
roles:
- role: test
- hosts: node
remote_user: root
gather_facts: yes
become: yes
roles:
- role: test1
执行看结果
[root@localhost k3s-ansible-master]# ansible-playbook -i inventory/jettech-cluster/hosts.ini test.yml
PLAY [master] *********************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************
Wednesday 12 January 2022 10:13:18 +0800 (0:00:00.030) 0:00:00.030 *****
ok: [172.16.10.5]
TASK [set-fact-test] **************************************************************************************************************************************************************
Wednesday 12 January 2022 10:13:22 +0800 (0:00:04.293) 0:00:04.323 *****
ok: [172.16.10.5]
PLAY [node] ***********************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************
Wednesday 12 January 2022 10:13:22 +0800 (0:00:00.043) 0:00:04.366 *****
ok: [172.16.10.15]
TASK [debug-test1] ****************************************************************************************************************************************************************
Wednesday 12 January 2022 10:13:26 +0800 (0:00:03.876) 0:00:08.243 *****
fatal: [172.16.10.15]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'name' is undefined\n\nThe error appears to be in '/root/wubo/k3s/k3s-ansible-master/roles/test1/tasks/main.yml': line 3, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: debug-test1\n ^ here\n"}
PLAY RECAP ************************************************************************************************************************************************************************
172.16.10.15 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
172.16.10.5 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Wednesday 12 January 2022 10:13:26 +0800 (0:00:00.060) 0:00:08.303 *****
===============================================================================
Gathering Facts ------------------------------------------------------------------------------------------------------------------------------------------------------------ 4.29s
Gathering Facts ------------------------------------------------------------------------------------------------------------------------------------------------------------ 3.88s
debug-test1 ---------------------------------------------------------------------------------------------------------------------------------------------------------------- 0.06s
set-fact-test -------------------------------------------------------------------------------------------------------------------------------------------------------------- 0.04s
也报错了没有定义为啥呢?使用方法不对
hostvars可以帮助我们在操作当前主机时获取到其他主机中的信息。假设,我想要在操作node主机时获取到master主机中的facts信息,我该怎么办呢?示例如下
test1 的task 改成如下使用
[root@localhost tasks]# cat main.yml
---
- name: debug-test1
debug:
msg: "{{ hostvars[groups['master'][0]]['name'] }}"
执行看结果
[root@localhost k3s-ansible-master]# ansible-playbook -i inventory/jettech-cluster/hosts.ini test.yml
PLAY [master] *********************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************
Wednesday 12 January 2022 10:59:43 +0800 (0:00:00.043) 0:00:00.043 *****
ok: [172.16.10.5]
TASK [set-fact-test] **************************************************************************************************************************************************************
Wednesday 12 January 2022 10:59:48 +0800 (0:00:04.397) 0:00:04.440 *****
ok: [172.16.10.5]
PLAY [node] ***********************************************************************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************************************************
Wednesday 12 January 2022 10:59:48 +0800 (0:00:00.037) 0:00:04.478 *****
ok: [172.16.10.15]
TASK [debug-test1] ****************************************************************************************************************************************************************
Wednesday 12 January 2022 10:59:52 +0800 (0:00:03.739) 0:00:08.217 *****
ok: [172.16.10.15] => {
"msg": "wubo"
}
PLAY RECAP ************************************************************************************************************************************************************************
172.16.10.15 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.16.10.5 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Wednesday 12 January 2022 10:59:52 +0800 (0:00:00.082) 0:00:08.300 *****
===============================================================================
Gathering Facts ------------------------------------------------------------------------------------------------------------------------------------------------------------ 4.40s
Gathering Facts ------------------------------------------------------------------------------------------------------------------------------------------------------------ 3.74s
debug-test1 ---------------------------------------------------------------------------------------------------------------------------------------------------------------- 0.08s
set-fact-test -------------------------------------------------------------------------------------------------------------------------------------------------------------- 0.04s
原理如下:
- 将任务执行的结果注册到变量,此变量的作用域为当前的 playbook
- 使用set_fact模块将变量注册到fact这个全局对象。
- 使用跨主机变量引用
- 但是在【TASK [Gathering Facts]】 中是没有通过set_fact定义的变量的,这点可以通过如下证明
[root@localhost tasks]# cat main.yml --- - name: debug-test1 setup: register: fact_result debug: #msg: "{{ hostvars[groups['master'][0]]['name'] }}" msg: "{{ fact_result }}"
[root@localhost k3s-ansible-master]# ansible-playbook -i inventory/jettech-cluster/hosts.ini test.yml > a
在a中是找不到通过set_fact定义的变量"name"的,但是这只是setup模块没有获取到这个信息。其实还是有这个信息的
[root@localhost tasks]# cat main.yml
---
- name: debug-test1
debug:
#msg: "{{ hostvars[groups['master'][0]]['name'] }}"
msg: "{{ hostvars[groups['master'][0]] }}"
[root@localhost k3s-ansible-master]# ansible-playbook -i inventory/jettech-cluster/hosts.ini test.yml > a
cat a
},
"host_ip": "172.16.10.5",
"image_registry_url": "172.16.10.5:5000",
"inventory_dir": "/root/wubo/k3s/k3s-ansible-master/inventory/jettech-cluster",
"inventory_file": "/root/wubo/k3s/k3s-ansible-master/inventory/jettech-cluster/hosts.ini",
"inventory_hostname": "172.16.10.5",
"inventory_hostname_short": "172",
"k3s_version": "v1.22.5+k3s1",
"kuboard_port": "32567",
"master_ip": "172.16.10.5",
"module_setup": true,
"name": "wubo",
"playbook_dir": "/root/wubo/k3s/k3s-ansible-master",
"systemd_dir": "/etc/systemd/system"
}
}
PLAY RECAP ************************************************************************************************************************************************************************
172.16.10.15 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.16.10.5 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
能看到name信息,也能看到在inventory/jettech-cluster/group_vars/all.yml 里面定义的信息
[root@localhost k3s-ansible-master]# cat inventory/jettech-cluster/group_vars/all.yml
---
k3s_version: v1.22.5+k3s1
ansible_user: root
systemd_dir: /etc/systemd/system
image_registry_url: "172.16.10.5:5000"
kuboard_port: "32567"
host_ip: "{{ ansible_default_ipv4.address }}"
master_ip: "{{ hostvars[groups['master'][0]]['ansible_host'] | default(groups['master'][0]) }}"
extra_server_args: "--write-kubeconfig-mode 666 --service-node-port-range=1024-65535 --bind-address=0.0.0.0 --https-listen-port=6443 --cluster-cidr=10.42.0.0/16 --service-cidr=10.43.0.0/16 --cluster-dns=10.43.0.254 --cluster-domain=jettech.com --node-name={{ host_ip }}"
extra_agent_args: "--node-name={{ host_ip }}"
案例三 手动设置fact
ansible除了能获取到预定义的fact的内容,还支持手动为某个主机定制fact。称之为本地fact。本地fact默认存放于被控端的/etc/ansible/facts.d
目录下,如果文件为ini
格式或者json
格式,ansible会自动识别。以这种形式加载的fact是key为ansible_local
的特殊变量。
下面是一个简单的示例,在ansibler主控端定义一个ini
格式的custom.fact文件内容如下
[root@node1 ansible]# vim custom.fact
[general]
package = httpd
service = httpd
state = started
验证
[root@node1 ansible]# ansible master -m setup -a "filter=ansible_local"
调用这个变量·
[root@node1 ansible]# vim use_users.yml
- hosts: master
#gather_facts: false
tasks:
- debug:
msg: "{{ ansible_os_family }}"
- debug:
msg: "{{ ansible_local.custom.general.package }}"
案例三 setup就是依赖fact自动获取系统信息你,可以直接使用
手动采集fact
通常情况下,我们在运行play的时候,ansible会先尝试ssh到被控端采集fact,如果此时,被控制端的ssh还没有完全启动,就会导致整个play执行失败。这个时候,我们可以先显示的关闭fact采集,然后在task中通过wait_for等待被控端ssh端口被正常监听,再在task中使用setup模块来手动采集fact:
- name: Deploy apps
hosts: master
gather_facts: False
tasks:
- name: wait for ssh to be running
local_action: wait_for port=22 host="{{ inventory_hostname }}" search_regex=OpenSSH
- name: gather facts
setup:
启用fact缓存
如果在play中需要引入fact,则可以开启fact缓存。fact缓存目前支持三种存储方式,分别为JSON、memcached、redis。
1. Json文件fact缓存后端
使用JSON文件作为fact缓存后端的时候,ansible将会把采集的fact写入到控制主机的文件中。
[root@node1 ansible]# vim ansible.cfg
[defaults]
gathering = smart
#缓存时间,单位为秒
fact_caching_timeout = 86400
fact_caching = jsonfile
#指定ansible包含fact的json文件位置,如果目录不存在,会自动创建,这里存放就是fact相关的缓存
fact_caching_connection = /tmp/ansible_fact_cache
选项说明:
- gathering:是否启用fact,有三个选项
-
- sunart:默认收集 facts,但在 facts已有的情况下就不收集,即使用 facts缓存
- implicit:默认收集 facts,要禁止收集,必须显式的申明: gather facts: false
- explicit:默认不收集,要收集,必须显示的申明: gather facts:true
- fact cacheing timeout:缓存时间,单位为s
- fact caching:缓存的方式,支持 jsonfile、 redis、 memcached
- fact caching connection:指定 ansible缓存fac的连接方式,如果是 jsonfile,则指定 jsonfile的缓存路
2 Redis fact缓存后端
使用redis作为fact缓存后端,需要在控制主机上安装redis服务并保持运行。需要安装python操作redis的软件包。
ansible.cfg配置如下:
[defaults]
gathering = smart
fact_caching_timeout = 86400
fact_caching = redis
3 Memcached fact缓存后端
使用memcached作为fact缓存后端,需要在控制主机上安装Memcached服务并保持运行,需要安装python操作memcached的软件包。
ansible.cfg配置如下:
[defaults]
gathering = smart
fact_caching_timeout = 86400
fact_caching = memcached
关于fact就上面三种情况的案例
案例四:主机变量和组变量 可以跨主机跨play全局变量
在inventory中定义主机变量或组变量变量
[root@localhost jettech-cluster]# cat hosts.ini
[master]
#172.16.10.5 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass=123456
172.16.10.5
name="wubo" #主机变量
[master:vars] #组变量
name="jettech"
age="10"
其实,除了像上例中那样直接在hosts文件中定义主机变量和组变量,还有另外一种方法也可以定义主机变量和组变量,我们可以在清单文件(inventory)的同级目录中创建两个目录,这两个目录的名字分别为”group_vars”和”host_vars”,我们可以将组变量文件放在”group_vars”目录中,将主机变量文件放在”host_vars”目录中,这样ansible就能获取到对应组变量和主机变量了。
我们先来看看怎样使用”group_vars”目录引入组变量,示例如下:
首先,我在hosts文件的同级目录中创建了一个group_vars目录,并且在group_vars目录中创建了一个名为master的文件,master文件的内容如下
[root@localhost jettech-cluster]# ls
group_vars hosts.ini host_vars
[root@localhost group_vars]# cat master
testvar1: testGroupVar1
“group_vars”目录中的文件之所以命名为”master”,是因为在上例的hosts文件中,有一个名为”master”的组,这个”变量文件的文件名”与”hosts文件中的组名”其实是对应的,定义在group_vars/master文件中的变量就相当于定义在master组中的”组变量”,同理,如果hosts文件中的其他组需要定义”组变量”,也可以在”group_vars”目录中创建一个与其组名同名的变量文件,我已经写好了一个测试用的playbook,测试一下刚才设置的组变量是否生效,测试playbook如下:
[root@localhost k3s-ansible-master]# cat test.yml
---
- hosts: k3s_cluster
remote_user: root
gather_facts: yes
become: yes
- hosts: master
remote_user: root
gather_facts: yes
become: yes
roles:
- role: test
- hosts: node
remote_user: root
gather_facts: yes
become: yes
roles:
- role: test1
[root@localhost roles]# cat test/tasks/main.yml
---
#- name: debug-test1
# debug:
# msg: "{{ hostvars[groups['master'][0]]['name'] }}"
#msg: "{{ hostvars[groups['master'][0]] }}"
- name: debug-test
debug:
msg: "================nonde-test======={{testvar1}}=========="
其实,我们也可以为test文件加上后缀名,文件的后缀名可以为”.yml”或”.yaml”或者”.json”中的任意一种,也就是说,我们将”group_vars/test”重命名为”group_vars/master.yml”,其中的变量也是能够完全正常的被调用的。
我们来思考一个问题,当group_vars/master文件中的定义的组变量与hosts文件中的组变量重复时,会以哪个为准呢?
我们来测试一下,由于当前hosts文件中已经有一个名为testvar的组变量,我们只需要在group_vars/master文件中再定义一个同名的变量.当”group_vars/master”文件中的组变量和hosts文件中的组变量冲突时,”group_vars/master”文件中的组变量的优先级更高。
在group_vars目录中,不仅能够使用”master文件”表示master组,也可以使用”master目录”表示master组,在”master目录”中又可以定义多个变量文件,这些文件中的变量都会被当做master组的组变量,示例如下:
# ls group_vars/master
a.yml b.yml
# cat group_vars/test/a.yml
testvar: testvar in group_vars/master/a.yml
# cat group_vars/test/b.yml
testvar1: testvar1 in group_vars/master/b.yml
如上例所示,master目录中有两个变量文件,”a.yml”和”b.yml”,这两个文件中分别定义了两个变量,master目录的目录名与hosts文件中的master组其实是对应的,同理,如果hosts文件中的其他组需要定义组变量,也可以在”group_vars”目录中创建一个与其组名同名的目录,然后在这个目录中创建一些变量文件,在这些变量文件中定义变量相当于在hosts文件中的组中定义的组变量。
综上所述,在group_vars目录中,有两种方式可以定义组变量。
方式一:直接使用变量文件,变量文件的文件名需要与组名相同(可以添加”.yml”、”.yaml”、”.json”作为后缀)。
方式二:使用目录,目录名需要与组名相同,然后再在目录中定义变量文件。
方式三:就是在group_vars或host_vars里面定义all.yml文件即可不用跟组名,主机名相同
[root@localhost group_vars]# pwd
/root/wubo/k3s/k3s-ansible-master/inventory/jettech-cluster/group_vars
[root@localhost group_vars]# ls
all.yml
[root@localhost group_vars]# cat all.yml
---
k3s_version: v1.22.5+k3s1
ansible_user: root
systemd_dir: /etc/systemd/system
image_registry_url: "172.16.10.5:5000"
token: "{{ lookup('file', '/var/lib/rancher/k3s/server/node-token') }}"
#token: "{{ lookup('pipe', 'cat /var/lib/rancher/k3s/server/node-token') }}"
kuboard_port: "32567"
host_ip: "{{ ansible_default_ipv4.address }}"
master_ip: "{{ hostvars[groups['master'][0]]['ansible_host'] | default(groups['master'][0]) }}"
extra_server_args: "--write-kubeconfig-mode 666 --service-node-port-range=1024-65535 --bind-address=0.0.0.0 --https-listen-port=6443 --cluster-cidr=10.42.0.0/16 --service-cidr=10.43.0.0/16 --cluster-dns=10.43.0.254 --cluster-domain=jettech.com --node-name={{ host_ip }}"
extra_agent_args: "--node-name={{ host_ip }}"
之前的示例中,”group_vars目录”一直定义在hosts文件的同级目录中,其实,”group_vars目录”也可以放在你所执行的playbook的同级目录中,比如,上例中,测试时使用的playbook为”test.yml”,我也可以在”test.yml”的同级目录中创建”group_vars目录”,然后再选择使用方式一或者方式二去定义组变量,而且,playbook的同级目录中的”group_vars目录”的优先级更高,也就是说,当hosts文件的同级目录和playbook的同级目录中同时存在”group_vars目录”时,并且存在同名的组变量时,会优先使用playbook同级目录中的”group_vars目录”中定义的组变量,通常情况下,我更习惯在playbook的同级目录中使用group_vars目录。
“host_vars”目录能够定义在主机清单的同级目录下,也能定义在playbook的同级目录下,定义在playbook同级目录中的优先级更高。
案例五:魔法变量 全局系统变量
Ansible默认会提供一些内置的变量以实现一些特定的功能,我们称之为魔法变量。下面列举一些常用的魔法变量
5.1 hostvars
获取某台指定的主机的相关变量。如果有一台web服务器的配置文件中需要指定db服务器的ip地址,我们假定这台db服务器的hostname为master,ip地址绑定在eth0网卡上,我们可以通过如下方法在web服务器上调用db服务器的ip地址:
[root@node1 ansible]# vim var_test.yml
- hosts: master
tasks:
- debug:
msg: "{{ ansible_ens33.ipv4.address }}"
获取node的地址
- hosts: master
tasks:
- debug:
msg: "{{ hostvars['node'].ansible_ens33.ipv4.address }}"
5.2 inventory_hostname
inventory_hostname是Ansible所识别的当前正在运行task的主机的主机名。如果在inventory里定义过别名,那么这里就是那个别名,如果inventory包含如下一行:
test5 ansible_ssh_host=172.16.10.5
则inventory_hostname即为test5,利用hostvars和inventory_hostname变量,可以输出与当前主机相关联的所有变量
- hosts: test5
tasks:
- debug:
msg: "{{ inventory_hostname }}" #别名
- debug:
msg: "{{ ansible_fqdn }}" #本机真名
5.3 变量优先级
1. extra vars(命令中-e)最优先
2 inventory主机清单中连接变量( ansible ssh user等)
3.play中vars、 vars files等
4.剩余的在 Inventory中定义的变量
5.系统的 facts变量
6.角色走义的默认变量 roles/ rolesname/ defaults/ main ym)
案例六: 使用lookup生成变量
简单说明
在通常情况下,所有的配置信息都会被作为ansible的变量保存了,而且可以保存在ansible允许定义变量的各种地方,诸如vars区段,vars_files
加载的文件中,以及host_vars和group_vars目录中。
但在有些时候,我们希望从诸如文本文件或者.csv文件中收集数据作为ansible的变量,或者直接获取某些命令的输出作为ansible的变量,甚至从redis或者etcd这样的键值存储中取得相应的值作为ansible的变量。这个时候,我们就需要通过ansible的lookup插件来从这些数据源中读取配置数据,传递给ansbile变量,并在playbook或者模板中使用这些数据。
ansible支持一套从不同数据源获取数据的lookup,包括file, password, pipe, env, template, csvfile, dnstxt, redis_kv, etcd等
6.1 pipe
使用file lookup可以从文本文件中获取数据,并在这些数据传递给ansible变量,在task或者jinja2模板中进行引用。下面是一个从文本文件中获取ssh公钥并复制到远程主机的示例:
[root@node1 ansible]# vim lookup_files_ex.yml
- hosts: demo2.example.com
tasks:
- debug:
msg: "{{ lookup('file','./hosts') }}"
可以把这个获取的值,使用set_fact变量
- hosts: master
tasks:
- set_fact: aaa={{ lookup('file','./hosts') }}
- debug:
msg: "{{ aaa }}"
6.2 pipe
使用pipe lookup可以直接调用外部命令,并将命令执行的结果打印到标准输出,作为ansible变量。下面的例子通过pipe调用date指令拿到一个以时间数字组成的字串,获取的是服务端命令
[root@node1 ansible]# vim lookup_pipe_ex.yml
- hosts: master
tasks:
- debug:
msg: "{{ lookup('pipe','ip addr') }}"
6.3 env
env lookup实际就是获取在控制主机上的某个环境变量的值。下面是一个读取控制机上$JAVA_HOME变量值的示例:
- name: get JAVA_HOME
debug: msg="{{ lookup('env', 'JAVA_HOME')}}"
6.4. template
template lookup可以指定一个jinja2模板,然后返回这个模板中的变量被替换以后的结果。
假设我们有一个message.j2模板,内容如下:
cat message.j2
This host runs {{ ansible_distribution }}
- name: print message from template
debug: msg="{{ lookup('template', 'message.j2')}}"
输出的msg的结果如下:
This host runs CentOS
6.5. csvfile
csvfile可以从.csv文件中读取一个条目。假设我们有如下示例的名为users.csv的文件:
[root@node1 ansible]# vim test.csv
username,email,gender
lorin,lorin@test.com,female
john,john@example.com,female
sue,sue@exmaple.com,male
[root@node1 ansible]# vim lookup_csvf_ex.yml
- name: get sue's email
hosts: master
tasks:
- debug:
msg: "{{ lookup('csvfile','sue file=test.csv delimiter=, col=1')}}"
可以看到,一共向插件传递了四个参数:sue, file=test.csv, delimiter=,以及col=1。说明如下:
- 第一个参数指定一个名字,该名字必须出现在其所在行的第0列,需要说明的是,如果指定的第一个参数名字在文件中出现多次,则匹配第一次出现的结果
- 第二个参数指定csv文件的文件名
- 第三个参数指定csv文件的中条目的分隔符,
- 第四个参数指定要取得哪一列的值,这一列正是第一个参数所在行的那一列的值
使用pipe,执行awk
[root@node1 ansible]# cat lookup_csvf_ex.yml
- name: get sue's email
hosts: master
tasks:
- debug:
msg: "{{ lookup('csvfile','sue file=test.csv delimiter=, col=1')}}"
- debug:
msg: lookup('pipe',"awk -F , '$1 ~/sue/ {print $2}' test.csv" )
6.6. redis_kv
redis_kv lookup可以直接从redis存储中来获取一个key的value,key必须是一个字符串,如同Redis GET指令一样。需要注意的是,要使用redis_kv lookup,需要在主控端安装python的redis客户端,在centos上,软件包为python-redis。
下面是一个在playbook中调用redis lookup的task,从本地的redis中取中一个key为weather的值:
- name: lookup value in redis
debug: msg="{{ lookup('redis_kv', 'redis://localhost:6379,weather')}}"
其中URL部分如果不指定,该模块会默认连接到redis://localhost:6379,所以实际上在上面的实例中,调用可以直接写成如下:
{{ lookup('redis_kv', 'weather')}}
6.7. etcd
etcd是一个分布式的key-value存储,通常被用于保存配置信息或者被用于实现服务发现。可以使用etcd lookup来从etcd中获取指定key的value。
我们通过如下方法往一个etcd中写入一个key:
curl -L http://127.0.0.1:2379/v2/keys/weather -XPUT -d value=sunny
定义一个调用etcd插件的task:
- name: look up value in etcd
debug: msg="{{ lookup('etcd','weather')}}"
默认情况下,etcd lookup会在http://127.0.0.1:4001上查找etcd服务器。但我们在执行playbook之前可以通过设置ANSIBLE_ETCD_URL环境变量来修改这个设置。
6.8.password
password lookup会随机生成一个密码,并将这个密码写入到参数指定的文件中。如下示例,创建一个名为bob的mysql用户,并随机生成该用户的密码,并将密码写入到主控端的bob-password.txt中:
- name: create deploy mysql user
mysql_user: name=bob password={{ lookup('password', 'bob-password,txt')}} priv=*.*:ALL state=present
6.9. dnstxt
dnstxt lookup用于获取指定域名的TXT记录。需要在主控端安装python-dns。
使用方法如下:
- name: lookup TXT record
debug: msg="{{ lookup('dnstxt', "aliyun.com") }}"
如果某一个主机有多个相关联的TXT记录,那么模块会把他们连在一起,并且每次调用时的连接顺序可能不同
路径问题
Special Variables — Ansible Documentation
task:
---
- name: set-fact-test
set_fact:
name: wubo
#- name: Wait for k3s_registries_config_dir
# wait_for:
# path: "/etc/rancher/k3s"
- name: debug-test
debug:
msg: "{{ dir_name }}"
register: dir_wubo
- name: debug-test1
shell: pwd
register: dir_wubo
- name: debug-test2
debug:
#msg: "{{ role_path }}" #当前角色 只对角色起作用
#msg: "{{ inventory_dir }}" #主机
#msg: "{{ playbook_dir }}" #剧本的绝对路径
#msg: "{{ play_hosts }}"
#msg: "{{ ansible_play_name }}"
#msg: "{{ role_name }}"
#msg: "{{ role_names }}"
msg: "{{ }}"
也可用,
inventory_dir
是目录持有Ansible的库存主机文件路径名
或者,如果你所说的“父目录”你的任务是在角色的路径意味着,{{ role_path }}
可能做的招。
最后,
role_path
将返回当前角色的路径名(自1.8开始)。这只会在角色中起作用