ansible操作笔记

ansible

ansible安装

#!/bin/bash
: <<!
**********************************************************
 * Name          : 安装ansible
 * Author        : 黄登基
 * Email         : huangdengji@126.com
 * Last modified : 2021-11-02 10:30
 * Filename      : openldap_install
 * Version       : 1.0
 * Description   : 目前在 CentOS 7.x 运行稳定,这个脚本需要使用 root 用户运行
 * *******************************************************
!

wget https://www.python.org/ftp/python/3.6.15/Python-3.6.15.tar.xz
tar -xf Python-3.6.15.tar.xz
cd Python-3.6.15 || exit
#编辑 取消注释 如下几行:
# ./Modules/Setup.dist
# 大约在 209 行
# 209 SSL=/usr/local/ssl
# 210 _ssl _ssl.c \
# 211 -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
# 212 -L$(SSL)/lib -lssl -lcrypto

./configure --prefix=/usr/local --with-ensurepip=install --enable-shared
make && make altinstall
ln -s /usr/local/bin/pip3.6 /usr/local/bin/pip
pip install virtualenv -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

useradd deploy
su - deploy
#使用deploy用户执行下面操作
virtualenv -p /usr/local/bin/python3.6 .py3-a2.9-env
source /home/deploy/.py3-a2.9-env/bin/activate
#下载ansible  https://github.com/ansible/ansible.git
git clone https://github.com/ansible/ansible.git
#stable-2.9 分支
git checkout stable-2.9
source /home/deploy/.py3-a2.9-env/ansible/hacking/env-setup -p
pip install cryptography -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
pip install paramiko -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
pip install pyyaml -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
pip install jinja2 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
ansible --version

ansible配置

#在.bash_profile追加环境变量切换
echo "source /home/deploy/.py3-a2.9-env/bin/activate" >>.bash_profile
echo "source /home/deploy/.py3-a2.9-env/ansible/hacking/env-setup -p" >>.bash_profile

cat >sudeploy.sh <<EOF
#!/bin/bash

chown -R deploy:deploy /home/deploy
su - deploy
EOF
#免密登录配置
cat ~/.ssh/id_*.pub | ssh root@210.26.116.128 'cat >> .ssh/authorized_keys'
cat ~/.ssh/id_*.pub | ssh root@210.26.116.90 'cat >> .ssh/authorized_keys'

ansible操作

ping检查

ansible all -i root@210.26.116.128,root@210.26.116.90 -m ping

复制文件

ansible all -i root@210.26.116.128,root@210.26.116.90 -m copy -a "src=/opt/shell-util/utils.sh dest=/tmp/utils.sh"

资源查询

ansible all -i inventory.ini --list-hosts
ansible southeast -i inventory.ini --list-hosts

查看文档

ansible-doc
ansible-doc -l
ansible-doc -l | grep copy
ansible-doc -l copy
ansible-doc copy
ansible-doc -s copy

编写资源菜单

cat >hosts <<EOF
[dbserver]
root@210.26.116.128

[webserver]
root@210.26.116.90
EOF

查看资源列表

ansible all hosts --list-hosts
ansible webserver -i hosts --list-hosts

commond 执行命令

ansible all -i hosts -a "echo 'hello'"
ansible all -i hosts -a "hostname -i"

shell 执行命令

ansible all -i hosts -m shell -a "hostname -i"
ansible all -i hosts -m shell -a "echo 'hello' | grep -o e"

script

cat >a.sh <<EOF
touch /tmp/testfile
EOF
ansible webserver -i hosts -m script -a "/home/deploy/.py3-a2.9-env/workspace/a.sh"
ansible webserver -i hosts -m shell -a "ls /tmp/testfile"

copy

ansible webserver -i hosts -m copy -a "src=nginx-1.20.1.tar.gz dest=/tmp/nginx-1.20.1.tar.gz"
ansible webserver -i hosts -m shell -a "file /tmp/nginx-1.20.1.tar.gz"
ansible webserver -i hosts -m copy -a "src=nginx-1.20.1.tar.gz dest=/tmp/nginx-1.20.1.tar.gz backup=yes"
nsible all -i hosts -m copy -a "src=nginx-1.20.1.tar.gz dest=/tmp/nginx-1.20.1.tar.gz backup=yes group=nobody owner=nobody"
ansible all -i hosts -m copy -a "src=nginx-1.20.1.tar.gz dest=/tmp/nginx-1.20.1.tar.gz backup=yes group=nobody owner=nobody mode=755"

yum_repository

# 添加 epel yum源
ansible dbserver -i hosts -m yum_repository -a "name=epel baseurl='http://download.fedoraproject.org/pub/epel/$releaserver/$basearch' description='EPEL YUM REPO'"
# 查看 epel yum源
ansible dbserver -i hosts -m shell -a "cat /etc/yum.repos.d/epel.repo"
#删除 epel yum源
ansible dbserver -i hosts -m yum_repository -a "name=epel state=absent"

systemd

# 重启systemd
ansible dbserver -i hosts -m systemd -a "daemon_reload=yes"
# 启动nginx服务
ansible dbserver -i hosts -m systemd -a "name=nginx state=started"
# 停止nginx服务
ansible dbserver -i hosts -m systemd -a "name=nginx state=stopped"
# 重启nginx服务
ansible dbserver -i hosts -m systemd -a "name=nginx state=restarted"
# 重启nginx服务
ansible dbserver -i hosts -m systemd -a "name=nginx enable=yes"

group

# 添加组
ansible dbserver -i hosts -m group -a "name=db_admin"
#删除组
ansible dbserver -i hosts -m group -a "name=db_admin state=absent"

user

# 加密密码
pass=$(echo "123456" | openssl passwd -1 -stdin)
# 添加用户 foo,密码123456
ansible all -i hosts -m user -a "name=foo password=${pass}"
#创建huangdengji用户,生成密钥对,秘钥类型:ecdsa
ansible all -i hosts -m user -a "name=huangdengji generate_ssh_key=yes ssh_key_type=ecdsa"
#创建用户tom,失效时间20211105 追加的db_admin组中
ansible all -i hosts -m user -a "name=tom expires=$(date +%s -d 20211105) groups=db_admin append=yes"
#创建用户tom,失效时间20211105 追加的db_admin,db2组中
ansible all -i hosts -m user -a "name=tom expires=$(date +%s -d 20211105) groups=db_admin,db2 append=yes"

file

# 创建文件
ansible all -i hosts -m file -a "path=/tmp/foo.conf state=touch"
#创建文件,指定group、owner
ansible all -i hosts -m file -a "path=/tmp/foo.conf state=touch group=0644 group=nobody owner=nobody"
#创建软连接
ansible all -i hosts -m file -a "src=/tmp/foo.conf dest=/tmp/link.con state=link"
#创建目录
ansible all -i hosts -m file -a "path=/tmp/testdir state=directory"
#删除软连接
ansible all -i hosts -m file -a "path=/tmp/link.conf state=absent"
#删除文件夹
ansible all -i hosts -m file -a "path=/tmp/testdir state=absent"
#删除文件
ansible all -i hosts -m file -a "path=/tmp/foo.conf state=absent"

cron

#添加定时任务
ansible all -i hosts -m cron -a "name='create new job' minute='0' job='ls -alh > /dev/null'"
#删除定时任务
ansible all -i hosts -m cron -a "name='create new job' state=absent"

debug

#变量打印
ansible all -i hosts -m debug -a "var=role" -e "role=web"
#格式化变量打印
ansible all -i hosts -m debug -a "msg='role is {{role}}'" -e "role=web"

template

cat >hello_word.j2 <<EOF
Hello {{var}} !!!
EOF
# 模板方式复制文件
ansible all -i hosts -m template -a "src=hello_word.j2 dest=/tmp/hello_word.txt" -e "var=word"
# 查看复制文件
ansible all -i hosts -a "cat /tmp/hello_word.txt"

lineinfile

#删除 Hello开头的一行
ansible all -i hosts -m lineinfile -a "path=/tmp/hello_word.txt regexp='^Hello' state=absent"
#替换 Hello开头的一行
ansible all -i hosts -m lineinfile -a "path=/tmp/hello_word.txt regexp='^Hello' line='are you a pig?' state=present"

blockinfile

#/tmp/hello_word.txt追加两行
ansible all -i hosts -m blockinfile -a "path=/tmp/hello_word.txt block='i am girl\nyou know a?'"
#/tmp/hello_word.txt 删除追加的两行
ansible all -i hosts -m blockinfile -a "path=/tmp/hello_word.txt block='i am girl\nyou know a?' state=absent"

全局变量

cat >a.json <<EOF
{"name1":"zhangsan","type":"school"}
EOF
ansible all -i localhost, -m debug -a "msg='name1 is {{name1}}, type is {{type}}'" -e @a.json
cat >a.yaml <<EOF
---
name1: hdj
type: home
...
EOF
ansible all -i localhost, -m debug -a "msg='name1 is {{name1}}, type is {{type}}'" -e @a.yaml

剧本变量

cat >playbook/testplay_vars.yaml <<EOF
---
- name: test play vars
  hosts: all
  vars: 
    user: lilei
    home: /home/lilei
  tasks:
    - name: create the user {{user}}
      user: 
        name: "{{user}}"
        home: "{{home}}"
...
EOF
ansible-playbook -i root@210.26.116.128, /home/deploy/.py3-a2.9-env/workspace/playbook/testplay_vars.yaml -C

###资产变量

cat >hosts_use_vars <<EOF
[webserver]
root@210.26.116.128 var1=test1 var2=test2
root@210.26.116.98
EOF
ansible root@210.26.116.128 -i hosts_use_vars -m debug -a "msg='{{var1}} {{var2}}'"
#资产变量 组变量
cat >hosts_use_vars <<EOF
[webserver]
root@210.26.116.128
root@210.26.116.98
[webserver:vars]
home="/home/centos"
EOF
ansible all -i hosts_use_vars -m debug -a "msg='{{home}}'"
# 资产变量 主机变量 组变量  ,主机变量优先主机组变量
cat >hosts_use_var_vars <<EOF
[webserver]
root@210.26.116.128 user=test
root@210.26.116.98
[webserver:vars]
user="centos"
EOF
ansible all -i hosts_use_var_vars -m debug -a "msg='{{user}}'"
# 资产变量 变量继承
cat >hosts_use_var_extends <<EOF
[webserver]
root@210.26.116.128
[dbserver]
root@210.26.116.98
[allserver]
[allserver:children]
webserver
dbserver
[allserver:vars]
user="centos"
EOF
ansible all -i hosts_use_var_extends -m debug -a "msg='{{user}}'"

inventory内置变量

cat >hosts_use_inventory_var_pass <<EOF
[webserver_centos]
210.26.116.128 ansible_ssh_user=centos ansible_ssh_pass="hdj123!2"
[dbserver_centos]
210.26.116.90 ansible_ssh_user=centos ansible_ssh_pass="hdj123!2"
EOF
ansible all -i hosts_use_inventory_var_pass -m shell -a "id"

facts变量

ansible all -i hosts_use_inventory_var_pass -c local -m setup
# facts 过滤
ansible all -i hosts_use_inventory_var_pass -m setup -a "filter=*memory*"

ansible all -i hosts_use_inventory_var_pass -m setup -a "filter=*mount*"

#facts变量使用
cat >facts.yaml <<EOF
---
- name: print facts variable
  hosts: all
  tasks:
    - name: print facts variable
      debug:
        msg: "Thre default ipv4 address is {{ansible_default_ipv4.address}}"
EOF
ansible-playbook -i hosts facts.yaml
#关闭facts变量收集 gather_facts: no
cat >facts_no.yaml <<EOF
---
- name: pwd ~
  hosts: all
  gather_facts: no
  remote_user: root
  tasks:
    - name: pwd ~
      shell: "ls /"        
EOF
ansible-playbook -i 210.26.116.128, facts_no.yaml

变量注册

cat >facts_register.yaml <<EOF
---
- name: install a package and print the result
  hosts: all
  gather_facts: no
  tasks:
    - name: install nginx package
      yum: name=nginx state=present
      register: install_result
    - name: print result
      debug: var=install_result
EOF
ansible-playbook -i hosts facts_register.yaml
#变量优先级: -e全局变量 > playbook.yaml中变量 > 资产主机变量 > 资产组变量
cat >facts_priority.yaml <<EOF
---
- name: test variable priority
  hosts: all
  vars:
    user: mysql
  tasks:
    - name: print the user value
      debug: msg='the value is {{user}}'
EOF
ansible-playbook -i hosts_use_var_vars facts_priority.yaml -e "user=www"
ansible-playbook -i hosts_use_var_vars facts_priority.yaml

条件判断when

cat >site.yaml <<EOF
---
- name: test when playbook example
  hosts: webserver
  gather_facts: no
  tasks:
    - name: yum nginx
      yum: name=nginx state=present
    - name: update nginx conf
      copy: src=nginx.conf dest=/etc/nginx/
    - name: check nginx syntax
      shell: /usr/sbin/nginx -t
      register: nginxSyntax
    - name: print nginx syntax
      debug: var=nginxSyntax.rc
    - name: start nginx server
      service: name=nginx state=started
      when: nginxSyntax.rc == 0
EOF
ansible-playbook -i hosts site.yaml

tags

cat >site.yaml <<EOF
---
- name: test when,with_item playbook example
  hosts: webserver
  gather_facts: no
  vars:
    createUser:
      - tomcat
      - www
      - mysql
  tasks:
    - name: create user
      user: name="{{item}}" state=present
      with_items: "{{createUser}}"

    - name: yum nginx
      yum: name=nginx state=present

    - name: update nginx conf
      copy: src=nginx.conf dest=/etc/nginx/
      tags: updateconfig

    - name: check nginx syntax
      shell: /usr/sbin/nginx -t
      register: nginxSyntax
      tags: updateconfig

    - name: check nginx running
      stat: path=/var/run/nginx.pid
      register: nginxrunning
      tags: updateconfig

    - name: print nginx syntax
      debug: var=nginxSyntax.rc
      tags: updateconfig

    - name: print nginx running
      debug: var=nginxrunning
      tags: updateconfig

    - name: start nginx server
      service: name=nginx state=started
      when: 
        - nginxSyntax.rc == 0
        - nginxrunning.stat.exists == false
      tags: updateconfig

    - name: restart nginx server
      service: name=nginx state=restarted
      when: 
        - nginxSyntax.rc == 0
        - nginxrunning.stat.exists == true
      tags: updateconfig
EOF
#只执行 updateconfig tag的task。
ansible-playbook -i hosts site.yaml -t updateconfig

handlers

cat >site.yaml <<EOF
---
- name: test when,with_item playbook example
  hosts: webserver
  gather_facts: no
  vars:
    createUser:
      - tomcat
      - www
      - mysql
  tasks:
    - name: create user
      user: name="{{item}}" state=present
      with_items: "{{createUser}}"

    - name: yum nginx
      yum: name=nginx state=present

    - name: update nginx conf
      copy: src=nginx.conf dest=/etc/nginx/
      tags: updateconfig
      notify: restart nginx server

    - name: check nginx syntax
      shell: /usr/sbin/nginx -t
      register: nginxSyntax
      tags: updateconfig

    - name: check nginx running
      stat: path=/var/run/nginx.pid
      register: nginxrunning
      tags: updateconfig

    - name: print nginx syntax
      debug: var=nginxSyntax.rc
      tags: updateconfig

    - name: print nginx running
      debug: var=nginxrunning
      tags: updateconfig

    - name: start nginx server
      service: name=nginx state=started
      when: 
        - nginxSyntax.rc == 0
        - nginxrunning.stat.exists == false
      tags: updateconfig

  handlers:
    - name: restart nginx server
      service: name=nginx state=reloaded
      when: 
        - nginxSyntax.rc == 0
        - nginxrunning.stat.exists == true
      tags: updateconfig
EOF
#只执行 updateconfig tag的task,当nginx.conf改变了才触发重启服务task
ansible-playbook -i hosts site.yaml -t updateconfig

jinja2

cat >nginx.j2 <<EOF
user  root;
{# get cpu process #}
worker_processes  {{ ansible_processor_vcpus }};

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}

http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;

        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;

        keepalive_timeout  65;

        #gzip  on;

        include /etc/nginx/conf.d/*.conf;
        client_max_body_size 100m;

        server {
            listen  8888;
            server_name {{ ansible_default_ipv4.address }};
            #autoindex on; 
            root /www;
            location / {
                root    /www/site;
                index   index.html index.htm;
            }
        }
}
EOF
#tags-handlers-template
cat >template_nginx_conf.yaml <<EOF
---
- name: test when,with_item,template playbook example
  hosts: webserver
  vars:
    createUser:
      - tomcat
      - www
      - mysql
  tasks:
    - name: create user
      user: name="{{item}}" state=present
      with_items: "{{createUser}}"

    - name: yum nginx
      yum: name=nginx state=present

    - name: update nginx conf
      template: src=nginx.j2 dest=/etc/nginx/nginx.conf
      tags: updateconfig
      notify: restart nginx server

    - name: check nginx syntax
      shell: /usr/sbin/nginx -t
      register: nginxSyntax
      tags: updateconfig

    - name: check nginx running
      stat: path=/var/run/nginx.pid
      register: nginxrunning
      tags: updateconfig

    - name: print nginx syntax
      debug: var=nginxSyntax.rc
      tags: updateconfig

    - name: print nginx running
      debug: var=nginxrunning
      tags: updateconfig

    - name: start nginx server
      service: name=nginx state=started
      when: 
        - nginxSyntax.rc == 0
        - nginxrunning.stat.exists == false
      tags: updateconfig

  handlers:
    - name: restart nginx server
      service: name=nginx state=reloaded
      when: 
        - nginxSyntax.rc == 0
        - nginxrunning.stat.exists == true
      tags: updateconfig
EOF
#根据nginx.j2模板替换CPU核心数和服务器ip地址
ansible-playbook -i hosts template_nginx_conf.yaml -t updateconfig
ansible all -i root@210.26.116.90, -m shell -a "cat /etc/nginx/nginx.conf"

role

mkdir -p role/nginx
cd role/nginx/ || exit
mkdir {files,handles,tasks,templates,vars}
#for d in $(ls); do touch "${d}"/main.yaml; done
#rm -rf nginx/files/main.yaml
cp ../nginx.j2 nginx/templates/
cat >nginx/handles/main.yaml <<EOF
---
- name: restart nginx server
  service: name=nginx state=reloaded
  when: 
    - nginxSyntax.rc == 0
    - nginxrunning.stat.exists == true
  tags: updateconfig
EOF
cat >nginx/tasks/main.yaml <<EOF
- name: create user
  user: name="{{item}}" state=present
  with_items: "{{createUser}}"

- name: yum nginx
  yum: name=nginx state=present

- name: update nginx conf
  template: src=nginx.j2 dest=/etc/nginx/nginx.conf
  tags: updateconfig
  notify: restart nginx server

- name: check nginx syntax
  shell: /usr/sbin/nginx -t
  register: nginxSyntax
  tags: updateconfig

- name: check nginx running
  stat: path=/var/run/nginx.pid
  register: nginxrunning
  tags: updateconfig

- name: print nginx syntax
  debug: var=nginxSyntax.rc
  tags: updateconfig

- name: print nginx running
  debug: var=nginxrunning
  tags: updateconfig

- name: start nginx server
  service: name=nginx state=started
  when: 
    - nginxSyntax.rc == 0
    - nginxrunning.stat.exists == false
  tags: updateconfig
EOF
cat >nginx/vars/main.yaml <<EOF
createUser:
  - tomcat
  - www
  - mysql
EOF
cat >nginx_deploy.yaml <<EOF
---
- name: role deploy nginx
  hosts: webserver
  roles:
    - nginx
EOF
cd ..
ansible-playbook -i hosts role/nginx_deploy.yaml
#目录结构
tree role
# role
# ├── nginx
# │   ├── files
# │   │   └── nginx.j2
# │   ├── handles
# │   │   └── main.yaml
# │   ├── tasks
# │   │   └── main.yaml
# │   ├── templates
# │   │   ├── main.yaml
# │   │   └── nginx.j2
# │   └── vars
# │       └── main.yaml
# └── nginx_deploy.yaml

# 6 directories, 7 files

import role

cat >role/nginx_deploy_import_role.yaml <<EOF
---
- name: role deploy inport role nginx playbook example
  hosts: webserver
  tasks:
    - debug:
        msg: "befor we run our role"
    - import_role:
        name: nginx
    - debug:
        msg: "agter we run our role"
EOF
ansible-playbook -i hosts role/nginx_deploy_import_role.yaml
ansible-playbook -i hosts role/nginx_deploy_import_role.yaml -t updateconfig
#此时目录结构
tree role
# role
# ├── nginx
# │   ├── files
# │   │   └── nginx.j2
# │   ├── handles
# │   │   └── main.yaml
# │   ├── tasks
# │   │   └── main.yaml
# │   ├── templates
# │   │   ├── main.yaml
# │   │   └── nginx.j2
# │   └── vars
# │       └── main.yaml
# ├── nginx_deploy_import_role.yaml
# └── nginx_deploy.yaml

# 6 directories, 8 files

ansible-galaxy

#https://galaxy.ansible.com/
#下载nginx role
ansible-galaxy collection install community.mysql
#初始化huangdengji.nginx role
ansible-galaxy init huangdengji.nginx
#得到目录
tree huangdengji.nginx
# huangdengji.nginx
# ├── defaults
# │   └── main.yml
# ├── files
# ├── handlers
# │   └── main.yml
# ├── meta
# │   └── main.yml
# ├── README.md
# ├── tasks
# │   └── main.yml
# ├── templates
# ├── tests
# │   ├── inventory
# │   └── test.yml
# └── vars
#     └── main.yml

# 8 directories, 8 files

ansible优化

开启ssh长连接

#去掉 ansible.cfg中ssh下的 长连接配置前的 #,修改ControlPersist的长连接断开时长值,下面这句
#ssh_args = -C -o ControlMaster=auto -o ControlPersist=86400s
cat >ping.yaml <<EOF
---
- name: ping
  hosts: all
  tasks:
    - ping:
EOF
#执行一次ping后,ss -nat #可以看到ESTAB 连接
ansible-playbook -i hosts ping.yaml

开启pipeline

#ansible.cfg 添加:
#pipelining = True
#执行ping,看不到put
ansible-playbook -i hosts ping.yaml -vvv

–limit

#使用--limit,可以覆盖inventory中的选择器
ansible-playbook -i hosts ping.yaml --limit dbserver -vvv

fact 缓存本地文件中

#ansible.cfg 添加:
# gathering = smart  #智能方式获取fact
# fact_caching = jsonfile  #json文件方式缓存
# fact_caching_connection=/dev/shm/ansiable_fact_cache/  #缓存地址
# fact_caching_timeout=120  #缓存120秒后失效
#配置之后,执行ansible命令后,120秒内再不重新获取fact,直接从本地/dev/shm/ansiable_fact_cache/目录中获取

fact 缓存redis中

#ansible.cfg 添加:
# gathering = smart  #智能方式获取fact
# fact_caching = reids  #redis方式缓存
# fact_caching_connection=localhost:6379:0:password  #缓存地址 格式:    地址:端口:库索引:密码    此处密码不可以加双引号
# fact_caching_timeout=120  #缓存120秒后失效
#安装redis模块
pip install redis
#再执行ansible命令后,会将fact信息缓存到redis中

修改playbook默认返回为json

#ansible.cfg 添加:
# stdout_callback = json
#此时执行playbook后,返回json格式
#修改ad-hock默认返回为json
# bin_ansible_callbacks = True
#此时执行ad-hock后,返回json格式

inventory

多个inventory

#可以跟多个 -i
ansible -i 1.yaml -i 2.yaml xxxx
#可以跟一个目录,目录下的文件后者可以是 yaml/yml/json/没有文件后缀
ansible -i inventory xxxx
#可以直接修改ansible.cfg 中inventory的值,此值可以接收文件或者目录,如果是目录,目录下的文件后者可以是 yaml/yml/json/没有文件后缀,支持可执行文件如:.py/.sh/等等

动态inventory脚本

cat >inventory.py <<EOF
#!/usr/bin/env python

import json
import sys
import argparse
def lists():
    dic = {}
    host_list = ['210.26.116.128', '210.26.116.98']
    hosts_dict = {'hosts': host_list}
    dic['computes'] = hosts_dict
    return json.dumps(dic, indent=4)

def hosts(name):
    dic = {'ansible_ssh_pass': 'hdj123!2'}
    return json.dumps(dic)

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-l', '--list', help='host list', action='store_true')
    parser.add_argument('-H', '--host', help='hosts vars')
    args = vars(parser.parse_args())

    if args['list']:
        print( lists() )
    elif args['host']:
        print( hosts(args['host']) )
    else:
        parser.print_help()
EOF
chmod +x inventory.py
inventory.py
inventory.py -H 210.26.116.90
inventory.py -l
ansible all -i inventory.py --list-host

log_files使用

查看log_plays说明

ansible-doc -t callback log_plays

调用日志写入文件

#ansible.cfg 添加:
# callback_whitelist = timer, log_plays #添加白名单
# [callback_log_plays]
# log_folder=/tmp/ansible/hosts/ #日志目录
#此时执行playbook之后就可以再/tmp/ansible/hosts/下找到命令的日志
#添加下行,ad-hock也会记录日志
# bin_ansible_callbacks = True

自定义回调插件

实现将回调信息写入到mysql库中

cat >~/.ansible/plugins/callback/mysql_log_plays.py <<EOF
# (C) 2021, huangdengji, <huangdengji@126.com>


from __future__ import (absolute_import, division, print_function)
from ansible.plugins.callback import CallbackBase
from ansible.parsing.ajson import AnsibleJSONEncoder
from ansible.module_utils.common._collections_compat import MutableMapping
from ansible.module_utils._text import to_bytes
from ansible.utils.path import makedirs_safe
from ansible.errors import AnsibleError
from ansible.module_utils._text import to_native
import json
import time
import os
import getpass

try:
    import pymysql as mysqldb
    pwd = "password"
    database = "db"
except ImportError as e:
    try:
        import MySQLdb as mysqldb
        pwd = "passwd"
        database = "database"
    except ImportError:
        raise AnsibleError("can not find pymysql or mysqldb model")

__metaclass__ = type

DOCUMENTATION = '''
    callback: mysql_log_plays
    type: notification
    short_description: write playbook output to mysql table
    version_added: historical
    description:
      - This callback writes playbook output to a mysql table ,use create db table sql;
      - CREATE DATABASE IF NOT EXISTS ansible_db CHARACTER SET utf8 COLLATE utf8_general_ci;  
      - USE ansible_db;  
      - CREATE TABLE $(ansible_send_result) ( $(id) bigint(20) NOT NULL AUTO_INCREMENT, $(host) varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL, $(user) varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL, $(category) varchar(2000) COLLATE utf8mb4_unicode_ci NOT NULL, $(result) text COLLATE utf8mb4_unicode_ci NOT NULL, PRIMARY KEY ($(id)) ) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
    requirements:
     - Whitelist in configuration
     - A valid MySQL connection configuration
    options:
      log_host:
        version_added: '2.9'
        default: localhost
        description: the mysql host.
        env:
          - name: ANSIBLE_MYSQL_LOG_HOST
        ini:
          - section: callback_mysql_log_plays
            key: log_host
      log_port:
        version_added: '2.9'
        default: 3306
        description: the mysql port.
        env:
          - name: ANSIBLE_MYSQL_LOG_PORT
        ini:
          - section: callback_mysql_log_plays
            key: log_port
        type: int
      log_user:
        version_added: '2.9'
        default: root
        description: the mysql user.
        env:
          - name: ANSIBLE_MYSQL_LOG_USER
        ini:
          - section: callback_mysql_log_plays
            key: log_user
      log_pwd:
        version_added: '2.9'
        default: 123456
        description: the mysql user password.
        env:
          - name: ANSIBLE_MYSQL_LOG_PWD
        ini:
          - section: callback_mysql_log_plays
            key: log_pwd
      log_db:
        version_added: '2.9'
        default: ansible
        description: the mysql database.
        env:
          - name: ANSIBLE_MYSQL_LOG_DB
        ini:
          - section: callback_mysql_log_plays
            key: log_db
      log_table:
        version_added: '2.9'
        default: ansible_send_result
        description: the mysql host.
        env:
          - name: ANSIBLE_MYSQL_LOG_TABLE
        ini:
          - section: callback_mysql_log_plays
            key: log_table

'''


# NOTE: in Ansible 1.2 or later general logging is available without
# this plugin, just set ANSIBLE_LOG_PATH as an environment variable
# or log_path in the DEFAULTS section of your ansible configuration
# file.  This callback is an example of per hosts logging for those
# that want it.


class CallbackModule(CallbackBase):
    """
    logs playbook results, per host, in /var/log/ansible/hosts
    """
    CALLBACK_VERSION = 2.0
    CALLBACK_TYPE = 'notification'
    CALLBACK_NAME = 'mysql_log_plays'
    CALLBACK_NEEDS_WHITELIST = True

    TIME_FORMAT = "%b %d %Y %H:%M:%S"
    MSG_FORMAT = "%(now)s - %(category)s - %(data)s\n\n"

    def __init__(self):

        super(CallbackModule, self).__init__()

    def set_options(self, task_keys=None, var_options=None, direct=None):
        super(CallbackModule, self).set_options(
            task_keys=task_keys, var_options=var_options, direct=direct)
        self.log_host = self.get_option("log_host")
        self.log_port = self.get_option("log_port")
        self.log_user = self.get_option("log_user")
        self.log_pwd = self.get_option("log_pwd")
        self.log_db = self.get_option("log_db")
        self.log_table = self.get_option("log_table")
        self.user = getpass.getuser()

    def _get_connect(self):
        db_cfg = {
            "host": self.log_host,
            "port": self.log_port,
            "user": self.log_user,
            pwd: self.log_pwd,
            database: self.log_db
        }
        try:
            db = mysqldb.connect(**db_cfg)
            cursor = db.cursor()
        except Exception as e:
            raise AnsibleError("%s" % to_native(e))
        return db, cursor

    def log2mysql(self, host, category, data):
        if isinstance(data, MutableMapping):
            if '_ansible_verbose_override' in data:
                # avoid logging extraneous data
                data = 'omitted'
            else:
                data = data.copy()
                invocation = data.pop('invocation', None)
                data = json.dumps(data, cls=AnsibleJSONEncoder)
                if invocation is not None:
                    data = json.dumps(invocation) + " => %s " % data

        sql = """
          insert into {}(host,user,category,result) 
          values(%s,%s,%s,%s)
        """.format(self.log_table)

        db, cursor = self._get_connect()
        try:
            cursor.execute(sql, (host, self.user, category, data))
            db.commit()
        except Exception as e:
            raise AnsibleError("%s" % to_native(e))
        finally:
            cursor.close()
            db.close()

    def runner_on_failed(self, host, res, ignore_errors=False):
        self.log2mysql(host, 'FAILED', res)

    def runner_on_ok(self, host, res):
        self.log2mysql(host, 'OK', res)

    def runner_on_skipped(self, host, item=None):
        self.log2mysql(host, 'SKIPPED', '...')

    def runner_on_unreachable(self, host, res):
        self.log2mysql(host, 'UNREACHABLE', res)

    def runner_on_async_failed(self, host, res, jid):
        self.log2mysql(host, 'ASYNC_FAILED', res)

    def playbook_on_import_for_host(self, host, imported_file):
        self.log2mysql(host, 'IMPORTED', imported_file)

    def playbook_on_not_import_for_host(self, host, missing_file):
        self.log2mysql(host, 'NOTIMPORTED', missing_file)

EOF

自定义插件调用

#/etc/ansible/ansible.cfg中加入下面配置
# callback_whitelist 后面追加mysql_log_plays
# [callback_mysql_log_plays]
# log_host=xx
# log_port=3306
# log_db=ansible_db
# log_user=root
# log_pwd=xx
# log_table=ansible_send_result

#下面这句看mysql_log_plays的帮助文档
ansible-doc -t callback mysql_log_plays
#之后所有执行都会写入到mysql表中
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值