变量概述

1.变量

变量:以一个固定的字符串去表示一个不固定的值。 x = 12 shell中变量: 定义: Host=oldxu.com 使用:${Host}

Ansible中变量: 定义: Host=oldxu.com 使用:{{ Host }}

2.Ansible中定义变量分为如下三种方式

  1. 通过命令行进行变量定义
  2. 在play文件中进行定义变量
  3. 通过inventory在主机组或单个主机中设置变量

1. 通过传参的方式定义变量

  1. [root@manager ansible_variables]# cat var6.yml
  2. - hosts: webservers
  3. tasks:
  4. - name: Install Rpm Packages "{{ test_packages }}"
  5. yum:
  6. name:
  7. - "{{ test_packages }}"
  8. state: present

[root@manager ansible_variables]# ansible-playbook var6.yml`` -e ``"test_packages=sl"

2.通过在play文件中进行定义变量

  • 一 (在playbook中直接定义变量)
    [root@manager ansible_variables]# cat var1.yml ```bash
  • hosts: webservers vars: #定义变量关键字

    • web_packages: httpd
    • ftp_packages: vsftpd

    tasks:

    • name: Installed Rpm Packages “{{ web_packages }}” “{{ ftp_packages }}” yum: name:
      1. - "{{ web_packages }}"
      2. - "{{ ftp_packages }}"
      state: present ```

      注意:vars关键字定义的变量,无法与其他的playbook进行共享。

  • 二 (vars_files来进行定义变量)
    [root@manager ansible_variables]# cat test.yml
    web_packages: httpd-tools
    ftp_packages: vsftpd
    

[root@manager ansible_variables]# cat var1.yml

- hosts: webservers
  vars_files: test.yml

  tasks:
    - name: Installed Rpm Packages "{{ web_packages }}" "{{ ftp_packages }}"
      yum:
        name:
          - "{{ web_packages }}"
          - "{{ ftp_packages }}"
        state: present

**

3. 通过inventory在主机组或单个主机中设置变量

[root@manager ansible_variables]# mkdir host_vars
[root@manager ansible_variables]# mkdir group_vars
[root@manager ansible_variables]# cat group_vars/webservers
web_packages: wget
ftp_packages: tree

[root@manager ansible_variables]# cat var4.yml

- hosts: webservers
  tasks:
    - name: Install Rpm Packages "{{ web_packages }}" "{{ ftp_packages }}"
      yum:
        name:
          - "{{ web_packages }}"
          - "{{ ftp_packages }}"
        state: present

[root@manager ansible_variables]# cat group_vars/all

web_packages: nfs-utils
ftp_packages: rsync

[root@manager ansible_variables]# cat var5.yml

- hosts: db
  tasks:
    - name: Install Rpm Packages "{{ web_packages }}" "{{ ftp_packages }}"
      yum:
        name:
          - "{{ web_packages }}"
          - "{{ ftp_packages }}"
        state: present

  • 变量的查找顺序:

    设定同一个变量,不同的值,去测试,看谁优先被使用。
    

    filename=   1)在plabook中定义vars变量   2)在playbook中定义vars_files变量   3)在host_vars中定义变量   4)在group_vars中定义变量   5)通过执行命令传递变量

  • 变量的查找优先级:

    1.外置传参 -e 2.playbook vars_files vars 3.host_vars 4.group_vars/组名 4.group_vars/all

4.NFS ansible搭建

[root@manager ansible_variables]# cat group_vars/all

share_dir: /data3

[root@manager ansible_variables]# cat var8.yml

- hosts: webservers
  tasks:

    - name: Installed NFS Server
      yum:
        name: nfs-utils

    - name: Configure NFS Server  #配置文件中使用 了share_dir #共享的目录/data3
      template:      
       #copy:模块 变量描述也拷贝 //  template:模块 支持拷贝变量的配置文件
        src: ./exports.j2
        dest: /etc/exports
      notify: Restart NFS Server

    - name: Create Share Directory         #创建共享的目录使用share_dir  /data3
      file:
        path: "{{ share_dir }}"
        state: directory
        owner: www
        group: www
        mode: 755

    - name: Started NFS Server
      systemd:
        name: nfs
        state: started
        enabled: yes

  handlers:
    - name: Restart NFS Server
      systemd:
        name: nfs
        state: restarted

- hosts: db
  tasks:
    - name: Client Mount NFS Server
      mount:
        src: 172.16.1.7:{{ share_dir }}
        path: /ansible_mount
        fstype: nfs
        state: mounted

5. 🚀🚀🚀Register变量注册

将执行的结果存储至变量中,后期可以通过结果进行判断的操作。
[root@manager ansible_variables]# cat var9.yml

- hosts: webservers
  tasks:
    - name: Get Network Status
      shell: netstat -lntp
      register: System_Net
      #将shell命令的执行输出结果,存储至System_Net变量中

    - name: Print Variables
      debug:
        msg: "{{ System_Net.stdout_lines }}"             #

PS: changed_when: False #有时候我们仅仅是ls 了一下, ansible-playbook 也会认为是changed了,可能这并不是我们想要的,这个时候我们就要用例子中方法来修改task的状态了

{{ System_Net }} 能看到变量的所有信息 {{ System_Net.stderr }} #能捕获到错误,如果没有就是空,如果有错误就会限制在终端窗口

注意: 
1. register变量的命名不能用 -中横线,比如dev-sda6_result,则会被解析成sda6_result,dev会被丢掉,所以不要用- 
2. ignore_errors这个关键字很重要,一定要配合设置成True,否则如果命令执行不成功,即 echo $?不为0,则在其语句后面的ansible语句不会被执行,导致程序中止。
  • 进阶用法: ```bash ansible register 这个功能非常有用。当我们需要判断对执行了某个操作或者某个命令后,如何做相应的响应处理(执行其他 ansible 语句),则一般会用到register 。

举个例子: 我们需要判断sda6是否存在,如果存在了就执行一些相应的脚本,则可以为该判断注册一个register变量,并用它来判断是否存在,存在返回 succeeded, 失败就是 failed.

  - name: Create a register to represent the status if the /dev/sda6 exsited
    shell: df -h | grep sda6
    register: dev_sda6_result
    ignore_errors: True
    tags: docker

  - name: Copy docker-thinpool.sh to all hosts
    copy: src=docker-thinpool.sh dest=/usr/bin/docker-thinpool mode=0755
    when: dev_sda6_result | succeeded
    tags: docker

其他示例:

   - name: List File OF Repo Dir
     shell:
       cmd: ls
       chdir: /etc/yum.repos.d/
     register: files_list

   - name: Remove Repo File
     file:
       path: '/etc/yum.repos.d/{{ item }}'
       state: absent
     with_items:
       - "{{ files_list.stdout_lines }}"       
> [参考链接](https://blog.csdn.net/qianggezhishen/article/details/53939188?utm_medium=distribute.pc_relevant.none-task-blog-title-2&spm=1001.2101.3001.4242) [链接1](https://blog.csdn.net/a13568hki/article/details/103880156?utm_medium=distribute.pc_relevant.none-task-blog-title-6&spm=1001.2101.3001.4242)
> [ansible-playbook去掉特定主机组或主机](https://blog.csdn.net/jihu0412/article/details/80175758)



- jumpserver安装时生成随机数的应用示例: 
```bash
- hosts: webservers
  gather_facts: no
  tasks:

    - name: Run Shell Command Random string
      shell:
        cmd: 'if ! grep "SECRET_KEY" ~/.bashrc; then
                SECRET_KEY=`cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 50`;
                echo "SECRET_KEY=$SECRET_KEY" >> ~/.bashrc;
                echo $SECRET_KEY;
              else
                 echo $SECRET_KEY;
              fi'
      register: SECRET_KEY


    - name: Run Shell Command BOOTSTRAP_TOKEN
      shell:
        cmd: 'if ! grep "BOOTSTRAP_TOKEN" ~/.bashrc; then
                BOOTSTRAP_TOKEN=`cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 16`;
                echo "BOOTSTRAP_TOKEN=$BOOTSTRAP_TOKEN" >> ~/.bashrc;
                echo $BOOTSTRAP_TOKEN;
             else
                echo $BOOTSTRAP_TOKEN;
             fi'
      register: BOOTSTRAP_TOKEN

    - name: Copy Jms Configure
      template:
        src: ./j-config.yml
        dest: /tmp/jms_config.yml

    - name: Copy Koko Configure
      template:
        src: ./k-config.yml
        dest: /tmp/koko_config.yml
  • 配置文件推送时调用变量信息:

[root@m01 ~/jumpserver]# cat j-config.yml 渲染模板


# SECURITY WARNING: keep the secret key used in production secret!
# 加密秘钥 生产环境中请修改为随机字符串,请勿外泄, 可使用命令生成 
# $ cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 49;echo
SECRET_KEY: {{ SECRET_KEY.stdout.split('=')[1] }}

# SECURITY WARNING: keep the bootstrap token used in production secret!
# 预共享Token coco和guacamole用来注册服务账号,不在使用原来的注册接受机制
BOOTSTRAP_TOKEN: {{ BOOTSTRAP_TOKEN.stdout.split('=')[1] }}

# Development env open this, when error occur display the full process track, Production disable it
# DEBUG 模式 开启DEBUG后遇到错误时可以看到更多日志
DEBUG: false
...

[root@m01 ~/jumpserver]# cat k-config.yml 渲染模板

# 项目名称, 会用来向Jumpserver注册, 识别而已, 不能重复
# NAME: {{ ansible_hostname }}

# Jumpserver项目的url, api请求注册会使用
CORE_HOST: http://127.0.0.1:8080

# Bootstrap Token, 预共享秘钥, 用来注册coco使用的service account和terminal
# 请和jumpserver 配置文件中保持一致,注册完成后可以删除
BOOTSTRAP_TOKEN:  {{ BOOTSTRAP_TOKEN.stdout.split('=')[1] }}

...

6.facts变量(采集被控端状态)

(非常强大,可以根据不同的主机生成不同配置文件。是灵魂)

ansible localhost -m setup 采集主机信息 ansible locathost -m setup > dco.txt 方便查看

实战一、根据IP地址生成不同的Redis配置

web01  bind 172.16.1.7
web02  bind 172.16.1.8

[root@manager ansible_variables]# cat redis.yml

- hosts: webservers
  tasks:

    - name: Installed Redis Server
      yum:
        name: redis
        state: present

    - name: Configure Redis Server
      template:
        src: ./redis.conf.j2
        dest: /etc/redis.conf
      notify: Restart Redis Server

    - name: Started Redis Server
      systemd:
        name: redis
        state: started
        enabled: yes

  handlers:
    - name: Restart Redis Server
      systemd:
        name: redis
        state: restarted

[root@manager ansible_variables]# cat redis.conf.j2
bind 127.0.0.1 {{ ansible_eth1.ipv4.address }}

实战二、根据CPU核心生成不同的Nginx配置

web01 1核心 1GB      2
web02 2核心 2GB    4

cpu核心那个变量

[root@manager ansible_variables]# cat nginx.yml

- hosts: webservers
  tasks:
    - name: Configure  Nginx.conf
      template:
        src: ./nginx.conf.j2
        dest: /tmp/nginx.conf

[root@manager ansible_variables]# cat nginx.conf.j2
worker {{ ansible_processor_vcpus * 2 }};

实战三、根据主机内存生成不同的Memcached配置 ( 使用物理内存的一半 )

web01 1G    512
web02 2G    1024
web03 4G    2048

1.找到物理内存的变量
2.将变量除以2

[root@manager ansible_variables]# yum install memcached -y
[root@manager ansible_variables]# cp /etc/sysconfig/memcached ./memcached.j2
[root@manager ansible_variables]# cat memcached.j2

PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="{{ ansible_memtotal_mb //2 }}"
OPTIONS=""

[root@manager ansible_variables]# cat memcached.yml

- hosts: webservers
  tasks:
    - name: Installed Memcached Server
      yum:
        name: memcached
        state: present

    - name: Configure Memcached Server
      template:
        src: memcached.j2
        dest: /etc/sysconfig/memcached
      notify: Restart Memcached Server

    - name: Started Memcached Server
      systemd:
        name: memcached
        state: started
        enabled: yes

  handlers:
    - name: Restart Memcached Server
      systemd:
        name: memcached
        state: restarted

实战四、根据主机名称生成不同的zabbix配置

zabbix: https://mirror.tuna.tsinghua.edu.cn/zabbix/zabbix/4.0/rhel/7/x86_64/zabbix-agent-4.0.0-2.el7.x86_64.rpm

[root@manager ansible_variables]# cat zabbix_agent.yml

- hosts: all
  tasks:
    - name: Installed ZabbixAgent
      yum:
        name: https://mirror.tuna.tsinghua.edu.cn/zabbix/zabbix/4.0/rhel/7/x86_64/zabbix-agent-4.0.0-2.el7.x86_64.rpm
        state: present

    - name: Configure ZabbixAgent
      template:
        src: ./zabbix_agentd.conf.j2
        dest: /etc/zabbix/zabbix_agentd.conf
      notify: Restart ZabbixAgent

    - name: Started ZabbixAgent
      systemd:
        name: zabbix-agent
        state: started
        enabled: yes

  handlers:
    - name: Restart ZabbixAgent
      systemd:
        name: zabbix-agent
        state: restarted

[root@manager ansible_variables]# grep "^Hostname" zabbix_agentd.conf.j2
Hostname={{ ansible_hostname }}

7.facts优化:

facts变量开启会影响playbook运行的效率? 但是关闭又会造成无法提取被控端的状态。 最佳的方案使用缓存来解决。
( redis )

没有使用缓存时的时间:** 4台机器同时操作: 20台

real 0m28.738s user 0m12.064s sys 0m3.725s

增加redis缓存:

real 0m6.345s user 0m3.021s sys 0m1.039s

1.安装一个redis   172.16.1.51 安装过了,就不要需要安装,直接使用就行了。
2.配置ansible配置文件,让其支持redis缓存:    

[root@manager ansible_variables]# cat ansible.cfg
[defaults]
inventory = ./hosts
forks     = 15               #进程数

command_warnings=False    
host_key_checking= false     #关闭指纹验证

gathering = smart            #接入redis缓存
fact_caching_timeout = 86400
fact_caching = redis
fact_caching_connection = 172.16.1.62:6379

yum install python-pip pip install redis