ansible是一个配置管理系统,也称为运维自动化工具,基于 Python 语言实现,由 Paramiko 和 PyYAML 两个关键模块构建。
不同与SaltStack、Puppet,有如下特点:
>> 部署简单,只需在主控端部署 Ansible 环境,被控端无需做任何操作。
>> 默认使用 SSH(Secure Shell)协议对设备进行管理。
>> 主从集中化管理。
>> 配置简单、功能强大、扩展性强。
>> 支持 API 及自定义模块,可通过 Python 轻松扩展。
>> 通过 Playbooks 来定制强大的配置、状态管理。
>> 对云计算平台、大数据都有很好的支持。
>> 提供一个功能强大、操作性强的 Web 管理界面和 REST API 接口 ---- AWX 平台。
安装ansible
yum install ansible -y
#ansible目录
[root@node1 ~]# cd /etc/ansible/
[root@node1 ansible]# ls
ansible.cfg hosts roles test.sh
创建SSH key
ansible与其他主机可以用密码登录,也可以用免密登录
#创建SSH key
[root@node1 ~]#ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:e7gWeyRa8YMtnf4W+NLzQx+dd8Bso2aSNof/rgu8+k8 root@node2
The key's randomart image is:
+---[RSA 2048]----+
| |
| |
| o |
| . * |
| S* = o oo|
| *+# * .o+|
| ooO+@Eo .+|
| . oo++* . .|
| .o+o==B+. |
+----[SHA256]-----+
#推送秘钥
[root@node1 ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.1.106
配置主机清单
[root@node1 ansible]# grep -Ev '^$|^#' hosts
[lsy]
192.168.1.106
#主机清单可以进行多个分组,可以使ip和主机名,分组可以嵌套,也可以不分组,使用all代表所用。
#以下举例
[lsy1]
ip1
ip2
host1
host2
[lsy1]
ip3
ip4
host3
host4
[lsy:children]
[lsy1]
[lsy2]
#对于使用密码的情况
ip1 ansible_ssh_user='root' ansible_ssh_pass='1'
ip2 ansible_ssh_user='root' ansible_ssh_pass='1'
#也可以这样
[lsy]
IP1
iP2
[lsy:vars]
ansible_ssh_user=root
ansible_ssh_pass=1
#取消交互式登录
在配置文件/etc/ansible/ansible.cfg的[defaults]中
打开注释
host_key_checking = False
基础模块
#ping模块,最常用来测试联通性 -m 指定模块 all指所有主机
ansible all -m ping
#copy模块 -a 指定参数
ansible centos -m copy -a "src=/etc/file_mbp.txt dest=/tmp/ [owner=root group=root
mode=0755]"
#fetch模块
ansible 10.1.1.60 -m fetch -a "src=/etc/fstab dest=/testdir/ansible/"
#yum模块
ansible centos -m yum -a "name=lrzsz state=latest" #state=present表示已安装不重新安装
#user模块 添加用户,需要已经加密的密码
[root@node1 ansible]# echo "123456" | openssl passwd -1 -stdin
$1$1KmeCnsK$HGnBE86F/XkXufL.n6sEb.
ansible centos -m user -a "name=foo password=$1$1KmeCnsK$HGnBE86F/XkXufL.n6sEb."
#移除用户
ansible all -m user -a 'name=foo state=absent'
# server模块 启动服务
ansible centos -m service -a "name=httpd state=started"
# 重启服务,效果类似 stopped+started,如果服务已经停止的,执行完,会重启
ansible centos -m service -a "name=httpd state=restarted"
# 重载服务,不会中断服务,如果服务之前未启动,那么会启动服务,如果启动了不一定会使用新的配置文件,还是推荐重启
ansible centos -m service -a "name=httpd state=reloaded"
# 停止服务
ansible centos -m service -a "name=httpd state=stopped"
# crontab模块
[root@m01 ~]# ansible lsy -m cron -a "minute=* hour=* day=* month=* weekday=* job='/bin/sh /server/scripts/test.sh'"
#磁盘挂载模块
[root@m01 ~]# ansible web -m mount -a "src=192.168.1.105:/data path=/data fstype=nfs opts=defaults state=mounted"
present ---开机挂载,仅将挂载配置写入/etc/fstab
mounted ---挂载设备,并将配置写入/etc/fstab
unmounted ---卸载设备,不会清除/etc/fstab写入的配置
absent ---卸载设备,会清理/etc/fstab写入的配置
#shell模块 执行一条命令
ansible two -m shell -a "cat /etc/fstab"
#注意:如果命令中的操作ansible中有对应的模块可以实现,他会有一个告警,说你最好还是使用模块实现
#script模块
ansible two -m script -a " ./test.sh"
#注意:ansible相当不推荐使用这个模块,跟shell模块一样的道理,
#他认为直接执行脚本或命令可能会出现不可预料的错误,比如环境变量的问题等等,可以翻看源码,
#他模块的实现不是简单的linux命令,他会根据各种情况做出各种处理,确保命令正常执行。然而,大多数人一般还是写直接脚本
#不会去记或者查询他众多模块的使用方法。
play-book剧本
剧本使用yaml格式
---
- hosts: web
tasks:
- name: Install Httpd Server
yum: name=httpd,httpd-tools state=installed
- name: Configure Httpd Server
copy: src=./httpd.conf dest=/etc/httpd/conf/httpd.conf
- name: Start Httpd Server
service: name=httpd state=started enabled=yes
#一个任务下只能做一个操作,要不然会报错
#通常需要把结果输出到标准输出,那么可以这样写
---
- hosts: web
tasks:
- name: Install Httpd Server
yum: name=httpd,httpd-tools state=installed
- name: Configure Httpd Server
copy: src=./httpd.conf dest=/etc/httpd/conf/httpd.conf
- name: Start Httpd Server
service: name=httpd state=started enabled=yes
register: show_swapon
- name: swapon
debug: var=show_swapon.stdout
with_items: show_swapon.results
#Start Httpd Server的结果会输出
#执行
ansible-playbook test.yml
ansible-playbook test.yml -f 10 #并行执行该脚本,默认是5
#对于输出太多,喜欢这样
ansible-playbook test.yml | grep something
ansible-playbook test.yml>test.log
切换用户
实际环境都是禁止root远程登录,所以大多情况都要切换用户执行root操作
[lsy]
IP1
iP2
[lsy:vars]
ansible_ssh_user=root
ansible_ssh_pass=1
ansible_become_pass=2
#注:ansible_become_pass替换了之前的ansible_sudo_pass 或者 ansible_su_pass
#命令 -b表示切换用户 --become-method切换方式,--become-use指定用户 默认root
ansible lsy -b --become-method su --become-user root -m shell -a "id"
#ansible -h查看时,会看到如下条目:
Privilege Escalation Options:
control how and which user you become as on target hosts
-b, --become run operations with become (does not imply password
prompting)
--become-method=BECOME_METHOD
privilege escalation method to use (default=sudo), use
`ansible-doc -t become -l` to list valid choices.
--become-user=BECOME_USER
run operations as this user (default=root)
-K, --ask-become-pass
ask for privilege escalation password
palybook中切换用户
---
- hosts: lsy
vars:
ansible_su_pass: 123456 #要切换用户的密码
remote_user: usertest #切换之前的用户
become: yes
become_user: root #要切换的用户
become_method: su #切换方式
tasks:
- name: copy
copy: 'src=/root/test.rpm dest=/root/'
- name: install
shell: rpm -ivh /root/test.rpm
- name: change
shell: sed -i "s#ProtectCenter=http://127.0.0.1:18080#ProtectCenter=https://192.168.1.105:18443#" /usr/local/hips/conf/hips.conf && systemctl restart hips
register: show_swapon
- name: swapon
debug: var=show_swapon.stdout
with_items: show_swapon.results
#清日志
---
- hosts: saapp
vars:
- clear_log: find /opt/lsy/logs/app/app -mtime +15 -name "*.log" -exec rm -rf {} \;
- clear_log: find -mtime +7 -name "*.log" -exec rm -rf {} \;
- clear_zip: find -mtime +7 -name "*.zip" -exec rm -rf {} \;
- path: /opt/mateinfo/logs
tasks:
- name: Get in logs dir and set var
shell: cd {{ path }}/{{ item }}/app && {{ clear_log }} && {{ clear_zip }}
loop:
- app1
- app2
- app3
- app4
-
-
---
- hosts: getlog
become: yes
become_method: su
become_user: root
gather_facts: true
tasks:
- name: test
shell: ls /opt/lsy/get_log
register: results
connection: local
- name: rm last log
file:
path: /opt/lsy/get_log/*
state: absent
connection: local
when: results.stdout != ""
- name: create log dir
file:
path: /opt/lsy/get_log/
state: directory
connection: local
- name: zip on service_node
archive:
path: /opt/lsy/logs/{{ service_name }}/app/{{ service_name }}.log.{{ year }}{{ date }}.*.zip
dest: /opt/lsy/logs/{{ service_name }}/app/{{ service_name }}_{{ ansible_all_ipv4_addresses[1] }}.zip
format: zip
ignore_errors: true
- name: getlog
fetch:
src: /opt/lsy/logs/{{ service_name }}/app/{{ service_name }}_{{ ansible_all_ipv4_addresses[1] }}.zip
dest: /opt/lsy/get_log/
flat: yes
ignore_errors: true
- name: rm service_node zip log file
file:
path: /opt/lsy/logs/{{ service_name }}_{{ ansible_all_ipv4_addresses[1] }}.zip
state: absent
- name: zip on mgmt
shell: zip -qr {{ service_name }}.zip *
args:
chdir: /opt/lsy/get_log
connection: local
run_once: true
- name: rm no need log
file:
path: /opt/lsy/get_log/{{ service_name }}_{{ ansible_all_ipv4_addresses[1] }}.zip
state: absent
connection: local
[getlog]
10.2.5.142
10.2.4.168
10.2.5.154
10.2.5.4
[getlog:vars]
service_name=app2
year=2019
date=1106
ssh_user=lsy
ansible_ssh_pass=123456
ansible_become_user=root
ansible_become_pass=root_123456
[thread_dump]
10.5.5.177
10.5.5.179
[thread_dump:vars]
ansible_ssh_user=lsy
ansible_ssh_pass='123456'
ansible_become_password='root_123456'
service_name=app
loops=20
#########################################################################
- hosts: thread_dump
vars:
ansible_su_pass: root_123456
remote_user: lsy
become: yes
become_user: root
become_method: su
tasks:
- name: get time
shell: date +%Y%m%d
register: dump_time
- name: test dir
shell: ls /opt/lsy/get_thread_dump
register: results
connection: local
ignore_errors: true
- name: rm dir
file:
path: /opt/lsy/get_thread_dump
state: absent
connection: local
when: results.stdout != ""
ignore_errors: true
- name: exec dump
script: ./thread_stack.sh {{service_name}} {{loops}}
- name: create dir
file:
path: /opt/lsy/get_thread_dump/
state: directory
connection: local
ignore_errors: true
- name: copy to maintenance
fetch:
src: /opt/lsy/logs/{{service_name}}/dump_{{service_name}}_{{ ansible_all_ipv4_addresses[1]}}.tar
dest: /opt/lsy/get_thread_dump/
flat: yes
- name: zip the all
shell: zip -qr dump_{{service_name}}_{{dump_time.stdout}}.zip dump_{{service_name}}*.tar
args:
chdir: /opt/lsy/get_thread_dump
connection: local
run_once: true