ansible之playbook

81 阅读7分钟

YAML 语言介绍

YAML:YAML Ain't Markup Language,即YAML不是标记语言。不过,在开发的这种语言时,YAML的意思其实是:"Yet Another Markup Language"(仍是一种标记语言)

YAML是一个可读性高的用来表达资料序列的格式。YAML参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822等。Clark Evans在2001年在首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者,目前很多最新的软件比较流行采用此格式的文件存放配置信息,如:ubuntu,anisble,docker,kubernetes等

YAML 官方网站:www.yaml.org

ansible 官网: docs.ansible.com/ansible/lat…

YAML 语言特性

  • YAML的可读性好
  • YAML和脚本语言的交互性好
  • YAML使用实现语言的数据类型
  • YAML有一个一致的信息模型
  • YAML易于实现
  • YAML可以基于流来处理
  • YAML表达能力强,扩展性好

YAML语法简介

  • 在单一文件第一行,用连续三个连字号"-" 开始,还有选择性的连续三个点号( ... )用来表示文件的结尾
  • 次行开始正常写Playbook的内容,一般建议写明该Playbook的功能
  • 使用#号注释代码
  • 缩进必须是统一的,不能空格和tab混用
  • 缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的
  • YAML文件内容是区别大小写的,key/value的值均需大小写敏感
  • 多个key/value可同行写也可换行写,同行使用,分隔
  • key后面冒号要加一个空格 比如: key: value
  • value可是个字符串,也可是另一个列表
  • YAML文件扩展名通常为yml或yaml

支持的数据类型

  • YAML 支持以下常用几种数据类型:
  • 标量:单个的、不可再分的值
  • 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
  • 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)

playbook 命令

ansible-playbook <filename.yml> ... [options]

--syntax-check      #语法检查,可缩写成--syntax, 相当于bash -n 
-C --check #模拟执行,只检测可能会发生的改变,但不真正执行操作,dry run 
--list-hosts    #列出运行任务的主机
--list-tags #列出tag
--list-tasks #列出task
--limit 主机列表 #只针对主机列表中的特定主机执行  --limit  主机地址
-i INVENTORY        #指定主机清单文件,通常一个项对应一个主机清单文件
--start-at-task START_AT_TASK #从指定task开始执行,而非从头开始,START_AT_TASK为任务的name
-v -vv  -vvv #显示过程

tags 标签

在playbook文件中,可以利用tags组件,为特定 task 指定标签,当在执行playbook时,可以只执行特定tags的task,而非整个playbook文件

tags: [ test1,test2 ]  # 写在一行
​
tags:
  - test1
  - test2 

案例:

vim httpd.yml
---
# tags example
- hosts: websrvs
 remote_user: root
 gather_facts: no
  
 tasks:
    - name: Install httpd
     yum: name=httpd state=present
    - name: Install configure file
     copy: src=files/httpd.conf dest=/etc/httpd/conf/
     tags: conf
    - name: start httpd service
     tags: service
      service: name=httpd state=started enabled=yes
      
      
[root@ansible ~]#ansible-playbook –t conf,service httpd.yml

3.6 指定清单文集 hosts

[root@localhost data]#ansible-playbook  --list-hosts    install_nginx.yml 
​
playbook: install_nginx.yml
​
  play #1 (web): web    TAGS: []
    pattern: [u'web']
    hosts (2):
      192.168.91.102
      192.168.91.101
[root@localhost data]#ansible-playbook  --list-hosts    install_nginx.yml  -i hosts 
​
playbook: install_nginx.yml
​
  play #1 (web): web    TAGS: []
    pattern: [u'web']
    hosts (3):
      192.168.91.102
      192.168.91.103
      192.168.91.101

3.7 Playbook中使用变量

变量名:仅能由字母、数字和下划线组成,且只能以字母开头

变量定义:

variable=value
例子:
http_port=80

变量调用方式:

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

变量来源:

  1. ansible 的 setup facts 远程主机的所有变量都可直接调用
  2. 通过命令行指定变量,优先级最高
ansible-playbook -e varname=value test.yml

3.7.1 使用setup模块中变量

本模块自动在playbook调用,不要用ansible命令调用,生成的系统状态信息, 并存放在facts变量中

facts 包括的信息很多,如: 主机名,IP,CPU,内存,网卡等

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

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

案例:使用setup变量

  • 查看所有变量
[root@localhost data]#ansible  localhost  -m setup
localhost | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.122.1", 
            "192.168.91.100"
        ], 
        "ansible_all_ipv6_addresses": [
            "fe80::fe7:ca03:81f:2887"
        ], 
        "ansible_apparmor": {
            "status": "disabled"
        }, 
        "ansible_architecture": "x86_64", 
        "ansible_bios_date": "07/29/2019", 
.............................................
  • 查看 本机的内存大小
[root@localhost data]#ansible  localhost  -m setup  -a "filter=ansible_memtotal_mb"
localhost | SUCCESS => {
    "ansible_facts": {
        "ansible_memtotal_mb": 1823
    }, 
    "changed": false
}
​
  • 查看本机的主版本号
[root@localhost data]#ansible localhost -m setup -a "filter=ansible_distribution_major_version"
localhost | SUCCESS => {
    "ansible_facts": {
        "ansible_distribution_major_version": "7"
    }, 
    "changed": false
}
​
  • 查看cpu核数
[root@localhost data]#ansible 192.168.91.101 -m setup -a "filter=ansible_processor_vcpus"
192.168.91.101 | SUCCESS => {
    "ansible_facts": {
        "ansible_processor_vcpus": 2, 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}
​
  • 利用setup 模块中的变量生成日志文件
---
- hosts:  web
  remote_user: root
  gather_facts: yes


  tasks:
    - name: create log file
      file: name=/data/{{ ansible_nodename }}.log state=touch owner=zhangsan mode=600


#ansible_nodename
  • 显示 es33 网卡的 IP 地址
---
- hosts:  web
  remote_user: root
  gather_facts: yes


  tasks:
    - name: create log file
      debug:
        msg: IP address {{ ansible_ens33.ipv4.address }}
        #msg: IP address {{ ansible_facts["ens33"]["ipv4"]["address"] }}
        #msg: IP address {{ ansible_facts.ens33.ipv4.address }}
        #msg: IP address {{ ansible_default_ipv4.address }}
        #msg: IP address {{ ansible_ens33.ipv4.address }}
        #msg: IP address {{ ansible_ens33.ipv4.address.split('.')[-1] }} #取IP中的最后一个数字

3.7.2 在playbook 命令行中定义变量

"{{ 变量名 }}"

使用 ansible-playbook -e 选项

例子: 在使用命令时定义变量

vim  test2.yml

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


ansible-playbook   -e  pkname=httpd  var2.yml
     

新建用户

---
- hosts: web
  gather_facts: no


  tasks:
    - name: create  user
      user: name={{ myname }}   system=yes  create_home=no
    - name: create  user
      user: name={{ myname1 }}   system=yes  create_home=no


ansible-playbook   -e  myname=cxk  -e myname1=wyf  playbook名字

3.7.3 定义变量文件

例子:

[root@localhost data]#vim var
# 定义变量  pkname1  pkname2
pkname1: tree
pkname2: telnet


vim   test1.yml
---
- hosts: web
  gather_facts: no
  
  tasks:
    - name: install  {{pkname1}}
      yum:  name={{pkname1}}  state=present
    - name: install {{pkname2}}
      yum: name={{pkname2}}  state=present

[root@localhost data]#ansible-playbook -e "@var"  test1.yml 
#  @代表文件    var 即是文件名

3.7.4直接在 playbook 文件 中建立变量

例子:

使用 vars组件

---
- hosts: web
  vars:
    username: test1
    groupname: group1


  tasks:
    - name: create group
      group: name={{ groupname }}  state=present
    - name: create user
      user: name={{ username }} state=present

例子: 安装多个软件包

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

例子: 变量之间的互相调用

---
- hosts: web
  vars:
    collect_info: "/data/test/{{ansible_default_ipv4['address']}}/"

  tasks:
    - name: create ip  directory
      file: name="{{collect_info}}"  state=directory





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

3.7.5 使用独立的变量文件

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


#先写一个变量文件
vim vars.yml
---
# variables file
package_name: mariadb-server
service_name: mariadb







#调用这个文件
vim var5.yml
---
#install package and start service
- hosts: dbsrvs
 remote_user: root
 vars_files:
    - vars.yml
    
tasks:
    - name: install package
     yum: name={{ package_name }}
     tags: install
    - name: start service
      service: name={{ service_name }} state=started enabled=yes

3.7.6 针对主机和主机组的变量

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

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

[websrvs]
www1.kgc.com http_port=80   maxRequestsPerChild=808
www2.kgc.com http_port=8080 maxRequestsPerChild=909
#只是针对单个主机

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

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

范例:

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

例子:

[root@localhost data]#vim /etc/ansible/hosts 
[web]
192.168.91.101   hname=www1   domain=accp.com
192.168.91.102   hname=www2
​
​
[web:vars]
mark="-"
​
[all:vars]
domain=www.kgc.com
​
​
[root@localhost data]#ansible web -m hostname  -a 'name={{ hname }}{{ mark }}{{ domain }}'
192.168.91.102 | CHANGED => {
    "ansible_facts": {
        "ansible_domain": "sollutium.com", 
        "ansible_fqdn": "dedicated.sollutium.com", 
        "ansible_hostname": "www2-kgc", 
        "ansible_nodename": "www2-kgc.com", 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "www2-kgc.com"
}
192.168.91.101 | CHANGED => {
    "ansible_facts": {
        "ansible_domain": "sollutium.com", 
        "ansible_fqdn": "dedicated.sollutium.com", 
        "ansible_hostname": "www1-kgc", 
        "ansible_nodename": "www1-kgc.com", 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "www1-kgc.com"
}
​