Ansible Register
Register简介
register 可以将 task 执行的任务结果存储至某个变量中,便于后续的引用
Register场景示例
使用 Register 获取被控节点的端口信息
正常在playbook中执行shell是不会有结果输出的
[root@k81 an]# cat register1.yaml --- - hosts: centos tasks: - name: Get port listen info shell: netstat -lntp register: Ports - name: Debug debug: msg: # 下面是将变量格式化一下,否则会输出很多东西很乱 - "执行的命令为: {{ Ports.cmd }}" - "输出的结果为: " - " {{ Ports.stdout_lines }}" ## 测试 [root@k81 an]# ansible-playbook register1.yaml ...... TASK [Get port listen info] ************************************************************************************************** changed: [c2] changed: [c1] TASK [Debug] ***************************************************************************************************************** ok: [c1] => { "msg": [ "执行的命令为: netstat -lntp", "输出的结果为: ", " [u'Active Internet connections (only servers)', u'Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name ', u'tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 630/rpcbind ', u'tcp 0 0 192.168.122.1:53 0.0.0.0:* LISTEN 1628/dnsmasq ', u'tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1471/sshd ', u'tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 1024/cupsd ', u'tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1256/master ', u'tcp 0 0 0.0.0.0:10050 0.0.0.0:* LISTEN 1029/zabbix_agentd ', u'tcp6 0 0 :::111 :::* LISTEN 630/rpcbind ', u'tcp6 0 0 :::22 :::* LISTEN 1471/sshd ', u'tcp6 0 0 ::1:631 :::* LISTEN 1024/cupsd ', u'tcp6 0 0 ::1:25 :::* LISTEN 1256/master ']" ] } ok: [c2] => { "msg": [ "执行的命令为: netstat -lntp", "输出的结果为: ", " [u'Active Internet connections (only servers)', u'Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name ', u'tcp 0 0 0.0.0.0:10050 0.0.0.0:* LISTEN 1032/zabbix_agentd ', u'tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 642/rpcbind ', u'tcp 0 0 192.168.122.1:53 0.0.0.0:* LISTEN 1630/dnsmasq ', u'tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1488/sshd ', u'tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 1026/cupsd ', u'tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1273/master ', u'tcp6 0 0 :::111 :::* LISTEN 642/rpcbind ', u'tcp6 0 0 :::22 :::* LISTEN 1488/sshd ', u'tcp6 0 0 ::1:631 :::* LISTEN 1026/cupsd ', u'tcp6 0 0 ::1:25 :::* LISTEN 1273/master ']" ] }
批量修改随机200台主机名称
[root@k81 an]# cat register2.yaml --- - hosts: all tasks: - name: define random shell: echo $RANDOM |md5sum |cut -c 2-5 register: HOSTNAME - name: check vars debug: msg="{{ HOSTNAME }}" - name: change hostname hostname: name="host-{{ HOSTNAME.stdout }}" ## 测试 [root@k81 an]# ansible-playbook register2.yaml ## 查看结果 [root@k81 an]# ansible centos -m shell -a 'hostname ' c1 | CHANGED | rc=0 >> host-0a79 c2 | CHANGED | rc=0 >> host-9d33
使用 register 关键字完成某些tocken的创建
[root@k81 an]# cat register3.yaml #比如k8s中生成token.csv #[root@k8s-master ~]# head -c 16 /dev/urandom | od -An -t x | tr -d ' ' #b870778a2a9e4175d09af21a83c8963a --- - hosts: c1 tasks: - name: Output token.csv shell: head -c 16 /dev/urandom | od -An -t x | tr -d ' ' register: urandom_str - name: check token.csv debug: msg={{ urandom_str.stdout }} ## 测试 [root@k81 an]# ansible-playbook register3.yaml ...... TASK [check token.csv] ********************************************************************************************************************************************************************************************** ok: [c1] => { "msg": "9659bcaf9f0a4aeb45c7ce77f590f892" } PLAY RECAP ********************************************************************************************************************************************************************************************************** c1 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 ......
Ansible FactsVariables
facts介绍
Ansible facts 变量主要用来自动采集被控端主机自身的状态信息。
比如:被动端的,主机名、IP地址、系统版本、CPU数量、内存状态、磁盘状态等等。
默认每次执行playbook都会有如下task
PLAY [centos] ******************************************************************************************************************************************************************************************************* TASK [Gathering Facts] ********************************************************************************************************************************************************************************************** ok: [c2] ok: [c1]
本质上是通过setup模块获取的
[root@k81 an]# ansible c1 -m setup # 输出的信息很多,可以需要提前的时候先grep过滤出变量关键字 [root@k81 an]# ansible localhost -m setup -a 'filter=ansible_eth*’ # 或者指定过滤哪些信息 [root@k81 an]# cat fact1.yaml --- - hosts: centos tasks: - name: Print IP debug: msg: "this host fqdn is {{ ansible_fqdn }}, this host ip is {{ ansible_eth0.ipv4.address }}" ## 测试结果 [root@k81 an]# ansible-playbook fact1.yaml TASK [Print IP] ***************************************************************************************************************************************************************************************************** ok: [c1] => { "msg": "this host fqdn is host-0a79, this host ip is 10.10.21.196" } ok: [c2] => { "msg": "this host fqdn is host-9d33, this host ip is 10.10.21.197" } PLAY RECAP ********************************************************************************************************************************************************************************************************** c1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 c2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
实际上每次执行playbook的时候都去获取被控端信息会很浪费时间,因此我们在优化play执行速度的时候可以将这项关闭
[root@k81 an]# cat fact2.yaml --- - hosts: centos gather_facts: no tasks: - name: Print IP debug: msg: "this host fqdn is {{ ansible_fqdn }}, this host ip is {{ ansible_eth0.ipv4.address }}" ## 测试结果 [root@k81 an]# ansible-playbook fact2.yaml PLAY [centos] ******************************************************************************************************************************************************************************************************* TASK [Print IP] ***************************************************************************************************************************************************************************************************** fatal: [c1]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'ansible_fqdn' is undefined\n\nThe error appears to be in '/an/fact2.yaml': line 5, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n tasks:\n - name: Print IP\n ^ here\n"} fatal: [c2]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'ansible_fqdn' is undefined\n\nThe error appears to be in '/an/fact2.yaml': line 5, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n tasks:\n - name: Print IP\n ^ here\n"} PLAY RECAP ********************************************************************************************************************************************************************************************************** c1 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0 c2 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0 ## 会提示变量未定义 ## 测试是否有 gather_facts时候playbook执行时间 [root@k81 an]# cat fact-no.yaml - hosts: centos gather_facts: no tasks: - name: test shell: sleep 3 [root@k81 an]# cat fact-yes.yaml - hosts: centos gather_facts: yes tasks: - name: test shell: sleep 3 ## 开始测试 [root@k81 an]# time ansible-playbook fact-no.yaml ...... real 0m3.910s user 0m0.672s sys 0m0.204s [root@k81 an]# time ansible-playbook fact-yes.yaml real 0m39.800s user 0m2.281s sys 0m0.372s
facts使用场景
通过facts变量检查被控端硬件CPU信息,从而生成不同的Nginx配置文件(获取cpu数量)。
# {{ ansible_processor_cores }} 核心数 ( 每颗物理CPU的核心数) # {{ ansible_processor_count }} 颗数 (有几个CPU ) # {{ ansible_processor_vcpus }} 8 总核心数
通过facts变量检查被控端内存状态信息,从而生成不同的memcached的配置文件。
# 根据内存状态生成不同的配置(支持+-*/运算) # CACHESIZE="{{ ansible_memtotal_mb //2 }}"# 总内存/2 # CACHESIZE="{{ ansible_memtotal_mb * 0.8 }}" # 使用内存80%
通过facts变量检查被控端主机名称信息,从而生成不同的Zabbix配置文件。
# {{ ansible_hostname }} 被控端主机名称
通过facts变量检查被控端主机IP地址信息,从而生成不同的redis配置文件(获取需要bind的IP地址)。
# {{ ansible_eth1.ipv4.address }} 被控端IP地址
facts语法示例
利用变量在不同的机器上起redis
[root@k81 an]# cat redis.conf.j2 ...... bind 127.0.0.1 {{ ansible_eth0.ipv4.address }} # 用变量 ...... [root@k81 an]# cat fact-redis.yaml - hosts: centos tasks: - name: Config epel yum: name=epel-release - name: Installed Redis Server yum: name: redis state: present enablerepo: epel - 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@k81 an]# ansible-playbook fact-redis.yaml [root@k81 an]# redis-cli -h 10.10.21.196 10.10.21.196:6379> set name zs OK 10.10.21.196:6379> keys * 1) "name" 10.10.21.196:6379> get name "zs" 10.10.21.196:6379> exit [root@k81 an]# redis-cli -h 10.10.21.197 10.10.21.197:6379> set name ls OK 10.10.21.197:6379> keys * 1) "name" 10.10.21.197:6379> get name "ls" 10.10.21.197:6379> exit
修改被控机器名字且后缀带上机器IP的最后一截
[root@k81 an]# cat f1.yaml --- - hosts: centos tasks: - name: check msg debug: msg={{ ansible_eth0.ipv4.address.split('.')[-1] }} # 这里用的python中字符串的切割,切完了之后变成列表然后取出来列表最后一个值 - name: change hostname hostname: name=host-{{ ansible_eth0.ipv4.address.split('.')[-1] }} ## 测试修改结果 [root@k81 an]# ansible centos -m shell -a 'hostname ' c2 | CHANGED | rc=0 >>
facts变量性能优化
前面我们看到了如果不获取被控端的变量会快很多,但是有些时候又必须得获取,那么我们可以想办法获取之后将这些信息临时存储起来,一段时间不去被控端再次获取(为了防止被控端配置改变,我们可以设置数据过期时间)
既想用 facts 信息,又希望能提高 playbook 的效率的话,可以采用 facts 缓存来实现。
facts 缓存支持多种方式:json 文件方式,redis 方式,memcache 方式等。各种方式的配置都是在 ansible.cfg 中配置。
json文件方法
设置ansible.cfg
gathering=smart fact_caching_timeout=86400 # 这里是数据过期时间,单位是s,这里设置的是一天 fact_caching=jsonfile fact_caching_connection=/opt/fact_cache # 这里是需要缓存的路径
在设置完成之后我们再来测试之前的fact-yes.yaml的playbook执行时间
[root@k81 an]# time ansible-playbook fact-yes.yaml ... real 0m45.958s user 0m2.507s sys 0m0.421s ... [root@k81 an]# time ansible-playbook fact-yes.yaml # 第二次获取的是本地的信息 ... real 0m3.827s user 0m0.666s sys 0m0.181s ... # 同时在设置的目录里面是会生成对应文件的 [root@k81 an]# ls /opt/fact_cache/ c1 c2 # 如果打开对应文件就可以看到内容是setup获取的内容
redis方法
设置ansible.cfg
注: 这种方法需要python安装redis连接模块
gathering=smart fact_caching_timeout=86400 fact_caching=redis fact_caching_connection: localhost:6379 # 如果连接其他的redis这里应该写具体的IP地址+端口,如果redis中有多个库,也可以在地址的最后面写上 :0类似的字样来声明库,如 192.168.123.230:6379:1 这里的1就是指的 1 库
设置完成之后可以进行测试
yum -y install python-pip pip install --upgrade pip pip install redis 然后和上面一样,可以用time命令测试时间
memcache方法
设置ansible.cfg
注: 这种方法需要python安装memcache连接模块
gathering=smart fact_caching_timeout=86400 fact_caching=memcached