文章目录
CentOS 7环境
一、简介
ansible是一款自动化运维工具,基于python开发,可以实现批量系统设置、批量程序部署、批量执行命令等功能,默认通过SSH协议管理机器,客户端需要有Python环境,其他无需配置,只需管理终端即可。
- 特性
- 只需要在主控机安装ansible即可,被控端需要有python环境
- 默认使用SSH协议对被控机器进行管理
- 可以基于任何语言开发新模块
- 部分模块具有幂等性,执行同一动作多次,对被执行对象的影响状态总是一致的,但是shell、command等一些模块是没有幂等性的,执行时不会检查状态。
- 工作过程
- ansible命令执行
- 读取ansible.cfg配置文件
- 通过规则过滤inventory(hosts)中定义的主机列表
- 加载对应的模块
- 通过ansible core将模块或命令打包成python脚本文件
- 将python脚本文件传输至目标主机
.ansible/tmp/xxx/xxx.py
- 给文件加执行权限
- 执行python脚本并返回结果
- 删除执行过的脚本
二、安装及简单使用
主机 | 用途 |
---|---|
192.168.0.81 | ansible主控机器 |
192.168.0.207 | 被控机器 |
192.168.0.215 | 被控机器 |
- 安装
$ yum install ansible -y
$ ansible --version
ansible 2.9.27
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, Oct 14 2020, 14:45:30) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
- 配置文件路径
$ pwd
/etc/ansible
$ ls
ansible.cfg hosts roles
# 解释:
ansible.cfg:配置文件
hosts:ansible管理的inventory主机资产清单
roles:存放角色目录
- 配置主机清单
# 配置过后不能正常使用,需要配置ssh登录被控机器
$ vim /etc/ansible/hosts
192.168.0.207
192.168.0.215
- 配置ssh登录
任选其一
- 通过ssh免密实现
$ ssh-keygen
$ ssh-copy-id root@192.168.0.207
$ ssh-copy-id root@192.168.0.215
- 通过ansible主机清单实现
$ vim /etc/ansible/hosts
192.168.0.207 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass='xxx'
192.168.0.215 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass='xxx'
- 命令使用方法
$ ansible 主机/主机组/all(所有主机) -m 模块名 -a 模块参数
-m:模块
-a:模块参数
-syntax-check:检查剧本语法,但不执行
$ ansible-doc 模块名 #查看模块使用方法及参数
- 通过ping模块测试,检查主机是否能ping通
$ ansible all -m ping
192.168.0.215 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.0.207 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
- 至此,已实现ansible批量化管理被控主机
三、配置文件解析
# 以下是部分配置解析
$ cat /etc/ansible/ansible.cfg
[defaults]
inventory = /etc/ansible/hosts #指定主机清单文件
forks = 5 #并发连接数,并行执行5个任务
roles_path = /etc/ansible/roles #指定剧本位置
host_key_checking = False #是否检查SSH主机的密钥
timeout = 10 #ssh连接超时时间
[inventory]
[privilege_escalation]
[paramiko_connection]
[ssh_connection]
[persistent_connection]
[accelerate]
[selinux]
[colors]
[diff]
四、资产清单文件解析
- 主机与组
$ vim /etc/ansible/hosts
192.168.0.1 #未分组主机
[group_name1] #组名,可以将主机归属到不通的组,到时通过组对被控端进行批量化操作
192.168.0.2
192.168.0.3
[group_name2]
192.168.0.2 #一个主机可以属于不同的组
# 配置192.168.0.4主机别名为test1
test1 ansible_ssh_host=192.168.0.4 ansible_ssh_port=22
- 把一个组作为另一个组的子成员
$ vim /etc/ansible/hosts
[group_name1]
192.168.0.1
[group_name2]
192.168.0.2
[group_name3:children]
group_name1
group_name2
- 主机变量
$ vim /etc/ansible/hosts
[group_name1]
192.168.0.2 var1=app
- 组变量
$ vim /etc/ansible/hosts
[group_name1]
192.168.0.1
192.168.0.2
[group_name1:vars] #配置组变量格式
port=80
name=nginx
- 资产清单相关参数
# 远程主机
ansible_ssh_host
# 远程主机ssh端口
ansible_ssh_port
# 远程主机ssh用户密码
ansible_ssh_pass
五、模块
ping
检查被控主机是否能进行通信。
$ ansible all -m ping
192.168.0.207 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.0.215 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
shell
在被控主机上执行shell命令。
$ ansible all -m shell -a 'date'
192.168.0.215 | CHANGED | rc=0 >>
Fri Jan 5 08:45:56 CST 2024
192.168.0.207 | CHANGED | rc=0 >>
Fri Jan 5 08:45:56 CST 2024
script
在被控主机上执行主控机器上的脚本。
# 在主控机器上创建脚本
$ cat /root/test.sh
#!/bin/sh
date
$ ansible all -m script -a '/root/test.sh'
192.168.0.207 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.0.207 closed.\r\n",
"stderr_lines": [
"Shared connection to 192.168.0.207 closed."
],
"stdout": "Fri Jan 5 08:50:07 CST 2024\r\n",
"stdout_lines": [
"Fri Jan 5 08:50:07 CST 2024"
]
}
192.168.0.215 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.0.215 closed.\r\n",
"stderr_lines": [
"Shared connection to 192.168.0.215 closed."
],
"stdout": "Fri Jan 5 08:50:07 CST 2024\r\n",
"stdout_lines": [
"Fri Jan 5 08:50:07 CST 2024"
]
}
copy
复制文件到被控主机。
$ ansible all -m copy -a 'src=/root/test.sh dest=/tmp'
相关参数:
- src:源文件路径,可以指定文件或目录。当目录以
/
结尾时,只复制目录里边的内容,不带时,包含目录直接全部复制。 - dest:复制文件到被控主机的文件路径。
- backup:覆盖被控主机文件时,是否进行备份,选项有yes/no。
- forces:被控主机上又相同文件时,强制覆盖,选项有yes/no。
- mode:设置文件或目录的权限。
- owner:设置文件或目录的属主。
- group:设置文件或目录的属组。
unarchive
复制压缩文件到远程机器并解压。
$ ansible all -m unarchive -a 'src=/root/nginx-1.20.2.tar.gz dest=/tmp copy=yes'
相关参数:
- src:压缩文件路径,可以是被控主机上的路径,也可以是中控机上的路径,如果是被控主机上的路径,则需设置copy=no。
- dest:压缩文件复制到被控主机上的路径
- copy:默认为yes,复制中控机上的文件到远程主机,为no时,复制被控主机上的文件到对应路径。
- owner:解压后文件或目录的属主。
- group:解压后文件或目录的属组。
- mode:设置解压后的文件权限。
template
将变量传入配置jinja2文件并将文件复制到远程机器。
jinja2文件:可代替配置文件,里边可以传参。
$ cat nginx.conf.j2
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen {{ port }}; #设置变量
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
$ ansible all -m template -a "src=/root/nginx.conf.j2 dest=/tmp"
#被控主机查看
$ cat /tmp/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 82; #已改为82
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
fetch
从被控主机上拉取(即复制,不会删除被控主机上的文件)文件到本地。
$ ansible all -m fetch -a 'src=/tmp/test.sh dest=/opt'
$ tree /opt/
/opt/
├── 192.168.0.207
│ └── tmp
│ └── test.sh
└── 192.168.0.215
└── tmp
└── test.sh
4 directories, 2 files
相关参数:
- src:被控主机文件路径。
- dest:主控机文件存储路径。
- flat:拉取文件到本地时,是否只需要文件或者文件所在的目录都拉取,选项有yes/no,默认为no。
cron
在被控主机上设置计划任务。
# 创建一个名为clean_mem的每天凌晨一点清理buff/cache的计划任务
$ ansible all -m cron -a 'name=clean_mem minute=0 hour=1 day=* month=* weekday=* job="echo 3 > /proc/sys/vm/drop_caches"'
相关参数:
- minute:分钟
- hour:小时
- day:日
- month:月
- weekday:周
- job:计划任务内容
- name:计划任务名称
- disabled:注释计划任务
- state:对计划任务执行的操作。选项有absent(删除计划任务),present(创建计划任务),默认为present。
yum
安装软件。
# 在被控主机上安装iftop命令
$ ansible all -m yum -a 'name=iftop state=present'
相关参数:
- name:软件名
- state:安装或卸载,选项有present或absent。
systemd
管理托管到systemd的服务。
$ ansible all -m systemd -a 'name=mysql state=stopped'
相关参数:
- name:服务名称
- daemon-reload:重载服务,选项有yes/no,默认为no。
- enabled:是否配置开机自启,选项有yes/no,默认为no。
- state:期望服务状态,选项有reloaded, restarted, started, stopped.
六、playbook(剧本)
当需要对被控主机一次下发多个指令时,可以通过playbook实现。playbook由YAML语言编写。
示例:
nginx编译安装,设置端口为82并启动
- 相关文件准备
$ ls
nginx-1.20.2.tar.gz nginx.conf.j2 nginx.service nginx.yml
$ nginx.conf.j2
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen {{ port }};
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
$ cat nginx.service
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
ExecStartPre=/data/nginx/sbin/nginx -t
ExecStart=/data/nginx/sbin/nginx -c /data/nginx/conf/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true
[Install]
WantedBy=multi-user.target
- 执行playbook
$ cat nginx.yml
---
- hosts: 192.168.0.215
remote_user: root
gather_facts: no
vars:
- version: 1.20.2
- port: 82
tasks:
- name: install lib
yum:
name:
- gcc
- gcc-c++
- gd
- gd-devel
- gperftools
- libxml2
- libxslt-devel
- openssl
- openssl-devel
- pcre-devel
- perl-ExtUtils-Embed
state: present
- name: create nginx group
group:
name: nginx
state: present
- name: create nginx user
user:
name: nginx
group: nginx
shell: /sbin/nologin
create_home: no
state: present
- name: unarchive nginx
unarchive:
src: "./nginx-{{ version }}.tar.gz"
dest: "/tmp"
copy: yes
- name: make install nginx
shell: |
cd /tmp/nginx-{{ version }} && ./configure --prefix=/data/nginx --user=nginx --group=nginx --with-file-aio --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-stream_ssl_preread_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-http_auth_request_module --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-google_perftools_module --with-debug && make && make install
-name: copy nginx conf
copy:
src: "/root/nginx.conf.j2"
dest: "/data/nginx/conf"
- name: to systemd
copy:
src: "/root/nginx.service"
dest: "/usr/lib/systemd/system"
notify: daemon-reload
- name: start nginx
systemd:
name: nginx
state: started
handlers:
- name: daemon-reload
systemd:
daemon-reload: yes
# 剧本语法检查
$ ansible-playbook nginx.yml --syntax-check
#执行剧本
$ ansible-playbook nginx.yml
七、role(角色)
role(角色),用于层次性、结构化的组织playbook,使结构层次更分明,更加方便的进行管理。像上述的Nginx安装playbook,如果有MySQL、Kafka等的安装,配置文件、安装包都放在一个目录,就会显得凌乱,无法管理。
示例:
- 初始化
# 初始化一个nginx安装的role
$ cd /etc/ansible/roles
$ ansible-galaxy init nginx
#查看角色
$ ansible-galaxy role list
# /etc/ansible/roles
- nginx, (unknown version)
$ tree -L 1 nginx
nginx
├── defaults #填写默认变量
├── files #要传输到被控主机的文件
├── handlers #触发器
├── meta #定义依赖关系
├── README.md #角色描述文件
├── tasks #创建任务信息
├── templates #Jinja2模版存放目录
├── tests
└── vars #变量存放目录
- 存放相关文件
$ tree /etc/ansible/roles/nginx
nginx
├── defaults
│ └── main.yml
├── files
│ ├── nginx-1.20.2.tar.gz #安装包
│ └── nginx.service #托管到systemd的配置文件
├── handlers
│ └── main.yml #触发器
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml #任务列表
├── templates
│ └── nginx.conf.j2 #nginx jinja2模版文件
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml #变量文件
- role角色相关文件编写
# 执行任务
$ cat /etc/ansible/roles/nginx/tasks/main.yml
---
# tasks file for nginx
- name: install lib
yum:
name:
- gcc
- gcc-c++
- gd
- gd-devel
- gperftools
- libxml2
- libxslt-devel
- openssl
- openssl-devel
- pcre-devel
- perl-ExtUtils-Embed
state: present
- name: create nginx group
group:
name: nginx
state: present
- name: create nginx user
user:
name: nginx
group: nginx
shell: /sbin/nologin
create_home: no
state: present
- name: unarchive nginx
unarchive:
src: "./nginx-{{ version }}.tar.gz"
dest: "/tmp"
copy: yes
- name: make install nginx
shell: |
cd /tmp/nginx-{{ version }} && ./configure --prefix=/data/nginx --user=nginx --group=nginx --with-file-aio --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-stream_ssl_preread_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-http_auth_request_module --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-google_perftools_module --with-debug && make && make install
- name: to systemd
copy:
src: "nginx.service"
dest: "/usr/lib/systemd/system"
notify: daemon-reload
- name: start nginx
systemd:
name: nginx
state: started
# 触发器
$ cat /etc/ansible/roles/nginx/handlers/main.yml
---
# handlers file for nginx
- name: daemon-reload
systemd:
daemon-reload: yes
# 变量
$ cat /etc/ansible/roles/nginx/vars/main.yml
---
# vars file for nginx
---
# vars file for nginx
port: '82'
version: '1.20.2'
- 编写调用角色的剧本
$ vim /etc/ansible/roles/nginx.yml
---
- hosts: all
remote_user: root
gather_facts: no
roles:
- nginx # 对应的角色名称
# 执行角色
$ ansible-playbook /etc/ansible/roles/nginx.yml