ansible详解之部署简介和使用

Ansible--快速入门 - 别来无恙- - 博客园

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的特点

  1. ansible不需要单独安装客户端,也不需要启动任何服务
  2. ansible是python中的一套完整的自动化执行任务模块
  3. ansible playbook 采用yaml配置,对于自动化任务执行过一目了然
  4. 部署简单,只需在主控端部署Ansible环境,被控端无需做任何操作;
  5. 默认使用SSH协议对设备进行管理;
  6. 有大量常规运维操作模块,可实现日常绝大部分操作;
  7. 配置简单、功能强大、扩展性强;
  8. 支持API及自定义模块,可通过Python轻松扩展;
  9. 通过Playbooks来定制强大的配置、状态管理;
  10. 轻量级,无需在客户端安装agent,更新时,只需在操作机上进行一次更新即可;
  11. 提供一个功能强大、操作性强的Web管理界面和REST API接口——AWX平台。

ansible 架构图

上图中我们看到的主要模块如下:

Ansible:Ansible核心程序。
HostInventory:记录由Ansible管理的主机信息,包括端口、密码、ip等。
Playbooks:“剧本”YAML格式文件,多个任务定义在一个文件中,定义主机需要调用哪些模块来完成的功能。
CoreModules核心模块,主要操作是通过调用核心模块来完成管理任务。
CustomModules:自定义模块,完成核心模块无法完成的功能,支持多种语言。
ConnectionPlugins:连接插件,Ansible和Host通信使用

ansible 任务执行

ansible 任务执行模式

  Ansible 系统由控制主机对被管节点的操作方式可分为两类,即adhocplaybook

  • ad-hoc模式(点对点模式)
      使用单个模块,支持批量执行单条命令。ad-hoc 命令是一种可以快速输入的命令,而且不需要保存起来的命令。就相当于bash中的一句话shell。
  • playbook模式(剧本模式)
      是Ansible主要管理方式,也是Ansible功能强大的关键所在。playbook通过多个task集合完成一类功能,如Web服务的安装部署、数据库服务器的批量备份等。可以简单地把playbook理解为通过组合多条ad-hoc操作的配置文件。

简单理解就是Ansible在运行时, 首先读取ansible.cfg中的配置, 根据规则获取Inventory中的管理主机列表, 并行的在这些主机中执行配置的任务, 最后等待执行返回的结果。

ansible 命令执行过程

  1. 加载自己的配置文件,默认/etc/ansible/ansible.cfg
  2. 查找对应的主机配置文件,找到要执行的主机或者组;
  3. 加载自己对应的模块文件,如 command;
  4. 通过ansible将模块或命令生成对应的临时py文件(python脚本), 并将该文件传输至远程服务器;
  5. 对应执行用户的家目录的.ansible/tmp/XXX/XXX.PY文件;
  6. 给文件 +x 执行权限;
  7. 执行并返回结果;
  8. 删除临时py文件,sleep 0退出;

Ansible组成结构

    • Ansible
      Ansible的命令工具,核心执行工具;一次性或临时执行的操作都是通过该命令执行。
    • Ansible Playbook
      任务剧本(又称任务集),编排定义Ansible任务集的配置文件,由Ansible顺序依次执行,yaml格式。
    • Inventory
      Ansible管理主机的清单,默认是/etc/ansible/hosts文件。
    • Modules
      Ansible执行命令的功能模块,Ansible2.3版本为止,共有1039个模块。还可以自定义模块。
    • Plugins
      插件,模块功能的补充,常有连接类型插件,循环插件,变量插件,过滤插件,插件功能用的较少。
    • API
      提供给第三方程序调用的应用程序编程接口。

环境准备#

IP系统主机名描述
10.10.1.142CentOS8.210.10.1.142 mbs.cclinux.net.cn mbsansible管理节点
10.10.1.181CentOS8.210.10.1.181 mbs.cclinux.net.cn mbs1被管理节点1
10.10.1.134CentOS8.210.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与我们其他的服务在这一点上有很大不同,这里的配置文件查找是从多个地方找的,顺序如下:

  1. 检查环境变量ANSIBLE_CONFIG指向的路径文件(export ANSIBLE_CONFIG=/etc/ansible.cfg);
  2. ~/.ansible.cfg,检查当前目录下的ansible.cfg配置文件;
  3. /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中文文档

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内置参数

Ansible Ad-Hoc#

Ad-Hoc中文文档

ad-hoc —— 临时的,在ansible中是指需要快速执行,并且不需要保存的命令。说白了就是执行简单的命令——一条命令。对于复杂的命令则为playbook,类似于saltstackstate 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

原理如下:

  1. 将任务执行的结果注册到变量,此变量的作用域为当前的 playbook
  2. 使用set_fact模块将变量注册到fact这个全局对象。
  3. 使用跨主机变量引用
  4. 但是在【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,有三个选项
    1. sunart:默认收集 facts,但在 facts已有的情况下就不收集,即使用 facts缓存
    2. implicit:默认收集 facts,要禁止收集,必须显式的申明: gather facts: false
    3. 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记录,那么模块会把他们连在一起,并且每次调用时的连接顺序可能不同

breezey - 博客园

路径问题

Special Variables — Ansible Documentation

在Ansible中获取父目录? - VoidCC

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开始)。这只会在角色中起作用

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值