Ansible 概述¶
由于互联网的快速发展导致产品更新换代速度逐步增长,运维人员每天都要进行 大量的维护操作,按照传统方式进行维护使得工作效率低下。这时部署自动化运维就 可以尽可能安全、高效的完成这些工作。
Ansible 是基于 Python 开发,集合了众多优秀运维工具的优点,实现了批量运行 命令、部署程序、配置系统等功能的自动化运维管理工具。默认通过 SSH 协议进行 远程命令执行或下发配置,无需部署任何客户端代理软件,从而使得自动化环境部署 变得更加简单。可同时支持多台主机并行管理,使得管理主机更加便捷。
Ansible 可以看作是一种基于模块进行工作的框架结构,批量部署能力就是由 Ansible 所运行的模块实现的。简而言之 Ansible 是基于“模块”完成各种“任务”的。其 基本框架结构如图 3.1 所示。
由图 3.1 可以得出 Ansible 的基本架构由六大件构成。
-
Ansible core 核心引擎:即 Ansible 本身;
-
Host Inventory 主机清单:用来定义 Ansible 所管理主机,默认是在 Ansible 的 hosts 配置文件中定义被管理主机,同时也支持自定义动态主机清单和指定其它 配置文件的位置;
-
Connect plugin 连接插件:负责和被管理主机实现通信。除支持使用 SSH 连接 被管理主机外,Ansible 还支持其它的连接方式,所以需要有连接插件将各个主 机用连接插件连接到 Ansible;
-
Playbook(yaml,jinjia2)剧本:用来集中定义 Ansible 任务的配置文件,即将 多个任务定义在一个剧本中由 Ansible 自动执行,可以由控制主机针对多台被管 理主机同时运行多个任务;
-
Core modules 核心模块:是 Ansible 自带的模块,使用这些模块将资源分发到被 管理主机使其执行特定任务或匹配特定的状态;
-
Custom modules 自定义模块:用于完成模块功能的补充,可借助相关插件完成 记录日志、发送邮件等功能。
安装部署 Ansible 服务¶
Ansible 自动化运维环境由控制主机与被管理主机组成。由于 Ansible 是基于 SSH 协议 进行通信的,所以控制主机安装 Ansible 软件后不需要重启或运行任何程序,被管理主机也 不需要安装和运行任何代理程序。
安装 Ansible¶
- Centos 系统
Ansible 可以使用源码方式进行安装,也可以使用操作系统中 YUM 软件包管理工 具进行安装。 YUM 方式安装 Ansible,需要依赖第三方的 EPEL 源,下面配置 EPEL 源 作为部署 Ansible 的 YUM 源
[root@ansible-node1 ~]# yum install -y epel-release
[root@ansible-node1 ~]# yum install -y ansible
[root@ansible-node1 ~]# ansible --version //查看ansible版本
- Mac 系统
这里一般我会使用Mac电脑作为ansible-server 来执行ansible脚本
brew install ansible
配置主机清单¶
准备工作
- 配置inventory/pve
[pve] master.pve hostname=master ansible_host=192.168.1.11 ansible_ssh_user=root ansible_ssh_pass="pass@word1"
这里首先我们先明白,每一个被控制的主机默认肯定会有一个帐号和密码,我们可以使用这个普通用户来对该主机进行一系列操作~
温馨提示
- 可能出现sudo权限不够的问题,那么可以在inventory添加以下内容
gtx3090.c1 hostname=ubuntu ansible_ssh_user=xxx ansible_sudo_pass=xxx ansible_ssh_pass="password"
设置SSH无密码登陆¶
如果上个步骤配置好,这个步骤可以忽略~ 当然可以结合使用,具体场景还需要根据自己情况来配置
为了避免 Ansible 下发指令时需要输入被管理主机的密码,可以通过证书签名达到 SSH 无密码登录。使用 ssh-keygen 产生一对密钥,并通过 ssh-copy-id 命令来发送生成的公钥。
Ansible 命令应用基础¶
Ansible 可以使用命令行的方式进行自动化管理。命令的基本语法如下所示:
ansible <host-pattern> [-m module_name] [-a args]
Ansible 常用选项
- host-pattern:指定被管理主机
- [-m module_name]:指定所使用的模块
-
[-a args]:设置模块对应的参数
-
-C //预执行
- --list-hosts //列出正在运行任务的主机
- --list-tasks //列出tasks
- --limit 主机列表 //只针对特定主机执行
Ansible 的命令行管理工具都是由一系列模块、参数组成的,使用某些模块或参数之前, 可以在命令后面加上-h 或--help 来获取帮助。例如,ansible-doc 工具可以使用 ansible-doc -h 或者 ansible-doc --help 查看其帮助信息。
ansible-doc 工具用于查看模块帮助信息。主要选项包括:
-l 用来列出可使用的模块; -s 用来列出某个模块的描述信息和使用示列。 例如:下面操作可以列出 yum 模块的描述信息和操作动作。
[root@ansible-node1 ~]# ansible-doc -s yum
Ansible 自带了很多模块,能够下发执行 Ansible 的各种管理任务。首先来了解下 Ansible 常用的这些核心模块。
探测模块:
$ ansible mac -m ping
cpu-4.mac | SUCCESS => {
"changed": false,
"ping": "pong"
}
cpu-3.mac | SUCCESS => {
"changed": false,
"ping": "pong"
}
cpu-1.mac | SUCCESS => {
"changed": false,
"ping": "pong"
}
1. command 模块¶
Ansibale 管理工具使用-m 选项来指定所使用模块,默认使用 command 模块,即 -m 选 项省略时会运行此模块,用于在被管理主机上运行命令。例如在被管理主机上执行 date 命令,显示被管理主机时间。有三种执行命令的方式来管理写入主机清单中的主机。
示例一:使用 IP 地址查看被管理主机日期
$ ansible cka -m command -a 'date' --limit cka.master
cka.master | CHANGED | rc=0 >>
Wed Oct 12 12:24:17 AM CST 2022
温馨提示
- 这里我使用的mac笔记本,使用的ansible-playbook,在仓库中有一个关于ansible.cfg的配置文件。
$ cat ansible.cfg [defaults] pipelining = True strategy = free host_key_checking = False inventory = inventory //这里主要的目录,主机清单文件位置 library = library # gathering = smart fact_caching = redis # redis on stg-master fact_caching_connection = 106.75.63.184:3389:0:OpenBayesAnsibleCache fact_caching_timeout = 0 forks = 16 [privilege_escalation] become = True [diff] always = yes
示例二:使用管控主机分别查看被管理 cka-1 和 cka-2 组里面所有主机的日期
首先,需要准备主机文件
$ cat inventory/cka
[cka-1]
cka.master hostname=master0 ansible_host=172.30.42.244 ansible_user=lixie
[cka-2]
cka.node1 hostname=node1 ansible_host=172.30.192.106 ansible_user=lixie
cka.node2 hostname=node2 ansible_host=172.30.226.223 ansible_user=lixie
分组执行ansible 命令
$ ansible cka-1 -m command -a 'date' //第一组
cka.master | CHANGED | rc=0 >>
Wed Oct 12 12:42:15 AM CST 2022
$ ansible cka-2 -m command -a 'date' //第二组
cka.node1 | CHANGED | rc=0 >>
Wed Oct 12 12:38:55 AM CST 2022
cka.node2 | CHANGED | rc=0 >>
Wed Oct 12 12:38:55 AM CST 2022
当然了,如果上面的可以正确执行,那么其实命令也就是有手就行
示例:
$ ansible cka-2 -m command -a 'df -h'
示例三:查看所有被管理主机上的日期
[root@ansible-node1 ~]# ansible all -m command -a 'date
2. User 模块¶
Ansible 中的 user 模块用于创建新用户和更改、删除已存在的用户。其中 name 选项用 于指明创建的用户名称。主要包括两种状态(state):
- present 表示添加 (省略状态时默认使用);
- absent 表示移除
示例一:在被管理组 cka-1 里所有主机上创建一个 user1 用户。
$ ansible cka-1 -m user -a 'name="user1"'
示例二:删除上述创建的用户 user1。
$ ansible cka-1 -m user -a 'name="user1" state=absent '
示例三: ansible创建用户并指定密码
生成加密密码
$ a=$(python3 -c 'import crypt,getpass;pw="pass@word";print(crypt.crypt(pw))')
$ echo $a
8e7klQ1BR7DIY
更新密码
$ ansible note1 -m user -a 'name=test password="$a" update_password=always' //可以使用变量
$ ansible cka-1 -m user -a 'name="user1" password=8e7klQ1BR7DIY update_password=always'
3. cron 模块¶
Ansible 中的 cron 模块用于定义任务计划。主要包括两种状态(state):
-
present 表示添加 (省略状态时默认使用)
-
absent 表示移除。
4. group 模块¶
Ansible 中的 group 模块用于对用户组进行管理。
示例一:被管理组 cka-1 里所有主机创建 mysql 组,gid 为 555。
$ ansible cka-1 -m group -a 'name=mysql gid=555 system=yes'
示例二:将被管理组 cka-1 里所有主机的 mysql 用户添加到 mysql 组中。
ansible cka-1 -m user -a 'name=mysql uid=555 system=yes group=mysql'
5. copy 模块¶
Ansible 中的 copy 模块用于实现文件复制和批量下发文件。其中使用 src 来定义本地源文件路径;使用 dest 定义被管理主机文件路径;使用 content 则是使用指定信息内容生成 目标文件。
示 例 一 : 将本地文件 ucloud.yaml 复制到被管理组 cka-1 里的所有主机上的 /tmp/(当然也可以重命名),并将所有者设置为 root,权限设置为 640。
$ ansible cka-1 -m copy -a 'src=ucloud.yaml dest=/tmp/ owner=root mode=640'
登录被管理主机,验证上述命令执行结果。
[cka] root@master0:/tmp# ll
total 44
drwxrwxrwt 10 root root 4096 Oct 12 10:37 ./
drwxr-xr-x 19 root root 4096 May 24 23:27 ../
-rw-r----- 1 root root 1172 Oct 12 10:33 ucloud.yaml
温馨提示
如果出现以下的报错信息,是因为被管理主机开启了 SELinux,需要在被管理机上安装 libselinux-python 软件包,才可以使用 Ansible 中与 copy、file 相关的函数。
"msg": "Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!"
示例二:将”Hello Ansible Hi Ansible” 写入到被管理组 cka-1 里所有主机上的/tmp/ucloud.yaml 文件中。 当然这个例子我觉得很鸡肋~,注意这将完全替换ucloud.yaml里的文件内容
$ ansible cka-1 -m copy -a 'content="Hello Ansible Hi Ansible" dest=/tmp/ucloud.yaml'
登录被管理主机 cka-1,验证上述命令执行结果。
[cka] root@master0:/tmp# cat ucloud.yaml
Hello Ansible Hi Ansible
6. file 模块¶
Ansible 中使用 file 模块来设置文件属性。其中使用 path 指定文件路径;使用 src 定义 源文件路径;使用 name 或 dest 来替换创建文件的符号链接。
示例一:设置被管理组 cka-1 里所有主机中/tmp/ucloud.yaml 文件的所属主为 mysql,所属组为 mysql,权限为 644。
$ ansible cka-1 -m file -a 'owner=mysql group=mysql mode=644 path=/tmp/ucloud.yaml'
登录被管理主机,验证上述命令执行结果
[cka] root@master0:/tmp# ll
-rw-r--r-- 1 mysql mysql 24 Oct 12 10:44 ucloud.yaml
7. ping 模块¶
Ansible 中使用 ping 模块来检测指定主机的连通性。
示例:检测所有被管理主机的连通性。
$ ansible cka-1 -m ping
cka.master | SUCCESS => {
"changed": false,
"ping": "pong"
}
cka.node2 | SUCCESS => {
"changed": false,
"ping": "pong"
}
cka.node1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
8. service 模块¶
Ansible 中使用 service 模块来控制管理服务的运行状态。其中使用 enabled 表示是否 开机自动启动,取值为 true 或者 false;使用 name 定义服务名称;使用 state 指定服务状 态,取值有 started、stoped、restarted。
示例一:查看被管理组 cka-1 里所有主机 lxcfs 服务的状态。
$ ansible cka-1 -a 'systemctl status lxcfs'
示例二:查看被管理组 cka-1 里所有主机的 lxcfs 服务是否是开机自动启动状态。
$ ansible cka-1 -a 'systemctl is-enabled lxcfs'
cka.node2 | CHANGED | rc=0 >>
enabled
cka.master | CHANGED | rc=0 >>
enabled
cka.node1 | CHANGED | rc=0 >>
enabled
启动被管理组里所有主机的 lxcfs 服务并且设置为开机自动启动状态。
ansible cka-1 -m service -a 'enabled=true name=lxcfs state=started'
启动被管理组里所有主机的 lxcfs 服务并且关闭为开机自动启动状态
$ ansible cka-1 -m service -a 'enabled=false name=lxcfs state=started'
9. shell 模块¶
Ansible 中的 shell 模块可以在被管理主机上运行命令,并支持像管道符等功能的复杂命令。
示例一:被管理组 cka-1 里所有主机创建用户 user2,uid和gid 都为 1001,用 户家目录为/home/user1,shell 为/bin/bash。
$ ansible cka-1 -m user -a 'name=user2'
示例二:被管理组 cka-1 里的所有主机使用无交互模式给用户设置密码。
$ ansible cka-1 -m shell -a 'echo redhat|passwd --stdin user2'
$ ansible cka-1 -m shell -a "echo 'user:tju_openbayes'|chpasswd"
示例三: 可以使用管道符
$ ansible cka-1 -m shell -a 'cat /etc/passwd |wc -l'
10. script 模块¶
Ansible 中的 script 模块可以将本地脚本复制到被管理主机上进行运行。需要注 意的是使用相对路径指定脚本位置。
示例:编辑一个本地脚本 test.sh,复制到被管理组 cka-1 里所有主机上运行。
$ cat test.sh
#!/bin/bash
echo "hello tom" >> /tmp/1.txt //准备一个测试脚本
chmod +x test.sh
$ ansible cka-1 -m script -a '../scripts/test.sh'
登录被管理主机,查看执行结果
[cka] root@master0:/tmp# cat 1.txt
hello tom
11. atp 模块¶
Ansible 中的 apt模块负责在被管理主机上安装与卸载软件包,但是需要提前在每个节点配置自己的 apt 仓库。
-
使用 name 指定要安装的软件包,还可以带上软件包的版本号;否则安装最新的软件包
-
使用 state 指定安装软件包的状态,present、latest 用来表示安装,absent 表示卸载。
-
update_cache=yes 当这个参数为yes的时候等于apt-get update
安装tree包
$ ansible cka-1 -m apt -a 'name=tree update_cache=yes'
卸载tree包
$ ansible cka-1 -m apt -a 'name=tree state=absent'
12. yum 模块¶
这里被控主机没有centos系统,就略~
13. setup 模块¶
Ansible 中使用 setup 模块收集、查看被管理主机的 facts(facts 是 Ansible 采集 被管理主机设备信息的一个功能)。每个被管理主机在接收并运行管理命令之前,都 会将自己的相关信息(操作系统版本、IP 地址等)发送给控制主机。
$ ansible cka-1 -m setup
14. hostname 模块¶
可以利用hostname 给主机修改主机名
$ ansible cka-1 -m hostname -a 'name=nginx01'
15. cron 模块¶
$ ansible mac -m cron -a 'hour=2 minute=30 weekday=1-5 name="backup mysql" job=/root/lixie.sh' # 创建计划任务
$ ansible mac -m cron -a 'hour=2 minute=30 weekday=1-5 name="backup mysql" job=/root/lixie.sh disabled=yes' # 禁用计划任务
$ ansible mac -m cron -a 'hour=2 minute=30 weekday=1-5 name="backup mysql" job=/root/lixie.sh disabled=no' # 启用计划任务
$ ansible mac -m cron -a 'hour=2 minute=30 weekday=1-5 name="backup mysql" job=/root/lixie.sh state=absent' # 删除计划任务
$ ansible mac -m shell -a "crontab -l" # 查看计划任务
16. Lineinfile 模块¶
允许你在文件中搜索特定的行,并在找到匹配项时替换它。如果没有找到匹配项,它将添加一个新的行
你可以使用Ansible的命令行方式来执行lineinfile
模块。这是一个示例,它使用ansible
命令来确保SELinux设置为强制模式:
ansible localhost -m lineinfile -a "path=/etc/selinux/config regexp='^SELINUX=' line='SELINUX=enforcing'"
Ansible 案例¶
案例一:create_user.yaml¶
Ansible 批量创建用户
- 这里设置password需要使用python命令生成sha-512算法,pw是要加密的密码
a=$(python3 -c 'import crypt,getpass;pw="123456";print(crypt.crypt(pw))') $ echo $a QUbhMQ9BAGQBE
示例一 用户密码
- hosts: pve
tasks:
- name: ensure admin group
group:
name: admin
state: present
- name: ensure admin group nopasswd sudo
copy:
dest: /etc/sudoers.d/admin
content: |
%admin ALL=(ALL:ALL) NOPASSWD: ALL
- name: add user
user: name={{ item }} groups=admin password=d6F1o2yfgTymU shell=/bin/bash
with_items:
- user1
- user2
- user3
示例二: 公钥形式
tasks:
- name: ensure admin group
group:
name: admin
state: present
- name: ensure admin group nopasswd sudo
copy:
dest: /etc/sudoers.d/admin
content: |
%admin ALL=(ALL:ALL) NOPASSWD: ALL
- user:
name: "{{ item }}"
groups: admin
shell: /bin/bash
with_items:
- lixie
- user:
name: "{{ item }}"
state: absent
with_items:
- user
# - ubuntu
- authorized_key:
user: "{{ item.u }}"
key: "https://github.com/{{ item.k }}.keys" # 公钥上传到github
with_items:
- {u: lixie, k: lixie021}
执行ansible-playbook
ansible-playbook -i inventory/pve pve.yaml
官方参考文献: https://gist.github.com/alces/f7e3de25d98a19550a4e4f97cabc2cf4?from_wecom=1
ansible-playbook -i ucd-mysql, add-ssh-users.yml
附件¶
- ubuntu22.04 运行ansible报错
ubuntu22.04 执行报错
TASK [Gathering Facts] *******************************************************************************************************
fatal: [axis]: FAILED! => {"ansible_facts": {}, "changed": false, "failed_modules": {"ansible.legacy.setup": {"failed": true, "module_stderr": "/bin/sh: 1: /usr/bin/python: not found\n", "module_stdout": "", "msg": "The module failed to execute correctly, you probably need to set the interpreter.\nSee stdout/stderr for the exact error", "rc": 127}}, "msg": "The following modules failed to execute: ansible.legacy.setup\n"}