自动化运维管理工具 - Ansible
本文参考文章
Ansible
Ansible部署
pip download ansible
pip install *whl
默认没有创建 /etc/ansible 需要手动创建
Ansible配置说明
/etc/ansible/ansible.cfg
主配置文件, 配置ansible的工作特性./etc/ansible/ansible.cfg
主机列表清单./etc/ansible/roles/
存放(roles)角色的目录./usr/local/bin/ansible
二进制执行文件, ansible 主程序./usr/local/bin/ansilbe-doc
配置文档, 模块功能查看工具./usr/local/bin/ansible-galaxy
用于上传/下载 roles 模块到官方平台的工具./usr/local/bin/ansible-playbook
自动化任务、编排剧本工具/usr/bin/ansible-pull 远程执行命令的工具./usr/local/bin/ansible-vault
文件(如: playbook 文件) 加密工具./usr/local/bin/ansible-console
基于 界面的用户交互执行工具.
Ansible执行过程
-
load配置文件 /etc/ansible/ansible.cfg
-
Load 模块配置文件
-
通过 Ansible 将调用的模块或PlayBook生成对应的临时 py文件, 并将该临时文件传输至远程服务器的对的执行用户目录下
$HOME/.ansible/tmp/ansible-tmp-2123/xxxxxxx.py
>文件. -
对生成的文件添加可执行权限.
-
执行生成文件,并返回对应的结果.
-
删除生成文件,退出.
执行返回状态:
-
- 绿色:执行成功,无更改操作。如 ping模块
- 黄色:执行成功,更新过主机的操作。如执行shell模块执行ifconfig命令。
- 红色:执行失败返回结果。如FAILED、UNREACHABLE状态。
Ansible-Doc
# 显示可用的模块
ansible-doc -l
ansible-doc ping
# 显示指定模块的playbook阶段
ansible-doc -s ping
Ansible
ansible <host-pattern> [-m module_name] [-a args]
- host-pattern: 主机ip、主机名、主机组。
- module_name: 模块的名称。默认为 -m command 。
- args: 模块的参数, 需要加上 -a 进行指定模块的参数。如:
ansible all -a 'hostname'
- -v、-vv、-vvv: 显示详细的命令输出日志, v 越多越详细。如:
ansible all -m ping -vvv
- --list: 显示主机的列表。如:
ansible all --list
- -k / --ask-pass: 提示输入ssh连接密码, 默认为 ssh-key 认证。如:
ansible all -m ping -k
- -K / --ask-become-pass: 提示输入 sudo 的密码。
- -C / --check: 检查命令操作, 并不会执行。如:
ansible all -m ping -C
- -T / --timeout: 执行命令的超时时间, 默认为 10s。如:
ansible all -m ping -T=2
- -u / --user: 执行远程操作的用户. 如:
ansible all -m ping -u=root
- -b / --become: 代替旧版的 sudo 切换。
- -i 指定主机清单文件
ansible -i /data/ansible/hosts containers -m ping -o
/etc/ansible/ansible.cfg
# defaults 为默认配置
[defaults]
# 主机清单的路径, 默认为如下
# inventory = /etc/ansible/hosts
# 模块存放的路径
# library = /usr/share/my_modules/
# utils 模块存放路径
# module_utils = /usr/share/my_module_utils/
# 远程主机脚本临时存放目录
# remote_tmp = ~/.ansible/tmp
# 管理节点脚本临时存放目录
# local_tmp = ~/.ansible/tmp
# 插件的配置文件路径
# plugin_filters_cfg = /etc/ansible/plugin_filters.yml
# 执行并发数
# forks = 5
# 异步任务查询间隔 单位秒
# poll_interval = 15
# sudo 指定用户
# sudo_user = root
# 运行 ansible 是否提示输入sudo密码
# ask_sudo_pass = True
# 运行 ansible 是否提示输入密码 同 -k
# ask_pass = True
# 远程传输模式
# transport = smart
# SSH 默认端口
# remote_port = 22
# 模块运行默认语言环境
# module_lang = C
# roles 存放路径
# roles_path = /etc/ansible/roles
# 不检查 /root/.ssh/known_hosts 文件 建议取消
# host_key_checking = False
# ansible 操作日志路径 建议打开
# log_path = /var/log/ansible.log
主机存活探测模块 ping
/etc/ansible/hosts主机资产配置
[containers]
172.17.0.4 # 主机1
172.17.0.[5:7] # 主机 172.17.0.5 - 172.17.0.7
# 设置containers的登陆用户及密码
[containers:vars]
ansible_ssh_user='root'
ansible_ssh_pass='666666'
跳过第一次登陆认证(输入yes的那个操作)
# uncomment this to disable SSH key host checking
host_key_checking = False
执行
ansible containers -m ping -o
172.17.0.4 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"},"changed": false,"ping": "pong"}
172.17.0.5 | UNREACHABLE!: Failed to connect to the host via ssh: ssh: connect to host 172.17.0.5 port 22: No route to host
172.17.0.7 | UNREACHABLE!: Failed to connect to the host via ssh: ssh: connect to host 172.17.0.7 port 22: No route to host
172.17.0.6 | UNREACHABLE!: Failed to connect to the host via ssh: ssh: connect to host 172.17.0.6 port 22: No route to host
内置变量模块 setup
使用范例
ansible all -m setup -a 'filter=ansible_hostname '
123.57.71.226 | SUCCESS => {
"ansible_facts": {
"ansible_hostname": "123-57-71-226",
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false
}
172.17.0.4 | SUCCESS => {
"ansible_facts": {
"ansible_hostname": "64076cdad7f4",
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}
172.17.0.5 | SUCCESS => {
"ansible_facts": {
"ansible_hostname": "eb3d371118b7",
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}
ansible_form_factor 服务器类型
ansible_virtualization_role 虚拟机角色(宿主机或者虚拟机)
ansible_virtualization_type 虚拟机类型(kvm)
ansible_system_vendor 供应商(Dell)
ansible_product_name 产品型号(PowerEdge?R530)
ansible_product_serial 序列号(sn)
ansible_machine 计算机架构(x86_64)
ansible_bios_version BIOS版本
ansible_system 操作系统类型(linux)
ansible_os_family 操作系统家族(RedHat)
ansible_distribution 操作系统发行版(CentOS)
ansible_distribution_major_version 操作系统发行版主版本号(7)
ansible_distribution_release 操作系统发行版代号(core)
ansible_distribution_version 操作系统发行版本号(7.3.1611)
ansible_architecture 体系(x86_64)
ansible_kernel 操作系统内核版本号
ansible_userspace_architecture 用户模式体系(x86_64)
ansible_userspace_bits 用户模式位数
ansible_pkg_mgr 软件包管理器
ansible_selinux.status selinux状态
ansible_processor CPU产品名称
ansible_processor_count CPU数量
ansible_processor_cores 单颗CPU核心数量
ansible_processor_threads_per_core 每个核心线程数量
ansible_processor_vcpus CPU核心总数
ansible_memtotal_mb 内存空间
ansible_swaptotal_mb 交换空间
ansible_fqdn 主机的域名
ansible_default_ipv4.interface 默认网卡
ansible_default_ipv4.address 默认IP地址
ansible_default_ipv4.gateway 默认网关
ansible_devices 硬盘设备名
ansible_devices.vendor 硬盘供应商
ansible_devices.model 硬盘整列卡型号
ansible_devices.host 硬盘整列卡控制器
ansible_devices.size 设备存储空间
ansible_interfaces 网卡
ansible_{interfaces}.ipv4.address 网卡IP地址
ansible_{interfaces}.ipv6.0.address 网卡IPv6地址
ansible_{interfaces}.macaddress 网卡mac地址
Ansible Palybook
变量引用 vars
定义变量文件
---
package_name: nginx
env_name: prod
palybook
- register 用于接收
- debug 用于输出
- hosts: 123.57.71.226
remote_user: root
# vars:
# - package_name: nginx
# - env_name: prod
vars_files:
- vars.yaml
tasks:
- name: "{{ env_name }} install {{ package_name }}"
shell: echo {{ package_name }}
register: print_package_name
- name: "输出{{ print_package_name }}信息"
debug: var=print_package_name.stdout
- name: "{{ inventory_hostname }}"
shell: echo {{ inventory_hostname }}
register: print_inventory_hostname
- name: "输出{{ inventory_hostname }}信息"
debug: var=print_inventory_hostname.stdout
服务安装 yum
ansible-playbook yum.yaml -C --limit 172.17.0.4,172.17.0.5
过程... 结果
172.17.0.4 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.17.0.5 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
- -C 检查脚本运行情况,不在服务器执行
- --limit 指定节点机器运行 --limit 172.17.0.4,172.17.0.5
- hosts: containers
remote_user: root
vars:
- pak_name: httpd
- env_name: prod
tasks:
- name: "{{ env_name}} install {{ pak_name }}"
yum:
name: '{{ pak_name }}'
二进制服务安装Nginx(例子)
目录结构
tree
.
├── index.html.j2 # nginx首页文件
└── install_nginx.yaml # 安装nginx的playbook
index.html.j2 文件内容
- inventory_hostname 获取主机ipv4地址
<h1> {{ inventory_hostname }} </h1>
安装Nginx剧本
- 可以通过 -t tag 来进行配置文件检测、拷贝首页、 并触发重启动作。
ansible-playbook -t html,check install_nginx.yaml
- hosts: containers
remote_user: root
# 默认采集主机的信息,不采集执行会快一点
gather_facts: False
# 变量
vars:
- nginx_user: nginx
- nginx_group: nginx
- nginx_version: 1.18.0
- nginx_tmp_dir: /opt
- nginx_listen_port: 80
- nginx_prefix_dir: /usr/local/nginx
# 任务列表
tasks:
# 安装nginx依赖包
- name: "install nginx rely packages"
yum:
name:
- net-tools
- pcre
- pcre-devel
- openssl
- openssl-devel
- zlib-devel
- gcc
- wget
# 新建用户
- name: "Add nginx group"
group: name={{ nginx_user }} system=yes
# 新增组 并关联用户
- name: "Add nginx user"
user: name={{ nginx_user }} shell=/sbin/nologin system=yes group={{ nginx_group }}
# 下载nginx二进制包保存到 /opt
- name: "Download nginx package"
get_url:
url: http://nginx.org/download/nginx-{{ nginx_version }}.tar.gz
dest: "{{ nginx_tmp_dir }}/nginx-{{ nginx_version }}.tar.gz"
# 获取nginx的文件是否存在、以决定是否编译nginx
- name: "nginx exists"
stat:
path: "{{ nginx_prefix_dir }}/sbin/nginx"
register: file_status
# 安装nginx
- name: "install nginx"
shell: "cd {{ nginx_tmp_dir }};tar -xf nginx-{{ nginx_version }}.tar.gz;cd nginx-{{ nginx_version }};./configure --user={{ nginx_user }} --group={{ nginx_group }} --prefix={{ nginx_prefix_dir }} --with-http_stub_status_module --with-http_ssl_module --with-pcre --with-http_realip_module;make&& make install"
when: file_status.stat.exists == False
# 检查nginx的端口 并接收 shell返回的结果
- name: "check nginx status"
shell: netstat -anpt |grep {{ nginx_listen_port }} |grep LISTEN |wc -l
register: port_result
# 检查nginx配置文件
- name: check config
shell: "{{ nginx_prefix_dir }}/sbin/nginx -t "
register: status_result
tags: check
# 当接收的结果 == 0,此时80端口没有被占用, 启动nginx 否则直接跳过
- name: startd nginx
shell: "{{ nginx_prefix_dir }}/sbin/nginx"
# 这里返回的是字符串, 后面需要加双引号
when: port_result.stdout == "0"
# 拷贝本地j2文件模板到远程主机并触发nginx reload
- name: "Copy html file"
template: src=index.html.j2 dest={{ nginx_prefix_dir }}/html/index.html
notify: reload nginx
# 为任务设置tag 可以通过tag执行单个任务
# ansible-playbook -t html install_nginx.yaml
tags: html
# 触发器 任务中通过 notify 进行调用
handlers:
- name: reload nginx
shell: "{{ nginx_prefix_dir }}/sbin/nginx -s reload"
when: status_result.rc == 0
Roles 角色
roles角色结构如下
roles目录结构
playbook.yml
roles/
project/
tasks/
files/
vars/
templates/
handlers/
default/
meta/
- files/ :存放由copy或script模块等调用的文件
- templates/:template模块查找所需要模板文件的目录
- tasks/:定义task,role的基本元素,至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
- handlers/:至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
- vars/:定义变量,至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
- meta/:定义当前角色的特殊设定及其依赖关系,至少应该包含一个名为main.yml的文件,其它文件需在此文件中通过include进行包含
- default/:设定默认变量时使用此目录中的main.yml文件,比vars的优先级低
二进制服务安装Docker(例子)
目录结构
├── install_docker.yaml
└── roles
└── docker
├── file
│ ├── daemon.json
│ └── docker.service
├── tasks
│ ├── copybin.yaml
│ ├── copyconfig.yaml
│ ├── createdir.yaml
│ ├── download.yaml
│ ├── main.yaml
│ └── service.yaml
└── vars
└── main.yaml
playbook调用角色
cat install_docker.yaml
- hosts: localhost
remote_user: root
roles:
- docker
file目录
more roles/docker/file/*
::::::::::::::
roles/docker/file/daemon.json
::::::::::::::
{
"registry-mirrors":[
"https://kfwkfulq.mirror.aliyuncs.com",
"https://2lqq34jg.mirror.aliyuncs.com",
"https://pee6w651.mirror.aliyuncs.com",
"http://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn",
"https://registry.docker-cn.com"
]
}
::::::::::::::
roles/docker/file/docker.service
::::::::::::::
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd --graph /home/docker
ExecReload=/bin/kill -s HUP
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
tasks目录
more roles/docker/tasks/*
::::::::::::::
roles/docker/tasks/main.yaml
::::::::::::::
- include: download.yaml
- include: copybin.yaml
- include: createdir.yaml
- include: copyconfig.yaml
- include: service.yaml
::::::::::::::
roles/docker/tasks/copybin.yaml
::::::::::::::
- name: copy bin file
copy: src="{{ docker_tmp_dir }}/docker/{{ item }}" dest="/usr/bin/{{ item }}" remote_src=yes mode=0755
with_items:
- containerd
- containerd-shim
- ctr
- docker
- dockerd
- docker-init
- docker-proxy
- runc
::::::::::::::
roles/docker/tasks/copyconfig.yaml
::::::::::::::
- name: copy system file
copy: src="file/docker.service" dest="/usr/lib/systemd/system/docker.service"
- name: copy config file
copy: src="file/daemon.json" dest="/etc/docker/daemon.json"
::::::::::::::
roles/docker/tasks/createdir.yaml
::::::::::::::
- name: create directory
file: path="{{item}}" state=directory
with_items:
- /home/docker
- /etc/docker
- /etc/systemd/system/docker.service.d/
::::::::::::::
roles/docker/tasks/download.yaml
::::::::::::::
- name: "Download docker package"
get_url:
url: https://download.docker.com/linux/static/stable/x86_64/docker-{{ docker_version}}.tgz
dest: "{{ docker_tmp_dir }}/docker-{{docker_version}}.tgz"
- name: open tgz
shell: "cd {{ docker_tmp_dir }} ; tar xf docker-{{docker_version}}.tgz "
::::::::::::::
roles/docker/tasks/service.yaml
::::::::::::::
- name: start docker service
shell: systemctl daemon-reload && systemctl restart docker
- name: enable docker service
shell: systemctl enable docker
vars目录
more roles/docker/vars/*
docker_version: "19.03.9"
docker_tmp_dir: "/opt"
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?