Ansible,一款运维手上都有的工具

今天给大家带来一个运维手上都有的工具 —— Ansible。

一、入门

Ansible是一款基于Python开源的自动化工具,结合了许多运维工具的优点。可以实现批量系统设置批量程序部署运行命令。不过ansible是基于模块工作,本身没有批量部署能力真正具有批量部署的是ansible所运行的模块,ansible只是一个框架。

相比于市场上的运维工具,都有什么差别:

软件名称语言实现形式缺点
puppetrubyc/s(client/server)配置太复杂了!
saltstackpythonc/s(client/server)需要核心服务器
ansiblepython无核心服务器

Ansible具有什么特性?:选自@千峰教育

  • no agents:不需要在被管控主机上安装任何客户端,更新时,只需在操作机上进行一次更新即可
  • no server:无服务器端,使用时直接运行命令即可
  • modules in any languages:基于模块工作,可使用任意语言开发模块
  • yaml,not code:使用yaml语言定制剧本playbook
  • ssh by default:基于SSH工作
  • strong multi-tier solution:可实现多级指挥

贴一张 Ansible 的架构:

总的来说,就是用户通过 Ansible 中的插件/模块 来控制访问主机清单上的所有服务器

二、安装和基本使用

1、安装

如何安装?我这边用的是Debian系统,直接输入以下命令即可:

apt -y install ansible

安装完成之后验证安装是否成功:

ansible --version

其他系统的安装方式可以看:Ansible 社区文档

当你验证安装完后你会发现一个问题,就是我的配置文件为什么是None?

config file = None

我也不知道为什么没生成,理论上应该会自动生成一个配置文件夹的,但是没关系,你可以手动生成一个:

ansible-config init --disabled > ansible.cfg

输入此命令后,会在你当前的目录下生成配置文件:

当我们打开之后就可以看见默认配置了:

是的,我们用了 –disabled 这个参数,把所有的可配置项全部注释起来了
在配置文件中,你不难发现他有一个默认的主机清单,接下来我们讲从主机清单来到基本使用

2、主机清单使用

①主机分类

打开主机清单,或者自行创建一个主机清单:

vim /etc/ansible/hosts

接下来给大家介绍一下这个基本的使用方式,可以看见配置文件的注释给我们介绍了一个最简单的分组

[web] # [] 内填写一个名字,就算是一个分组了
#组内填写受控主机的IP地址或者主机名
服务器IP地址
或者主机名 (/etc/hosts 里面设置的)
[dba]
#第二组
主机名即为 /etc/hosts 内的内容(如红色框框标注的test),最终的示例写法就是这样:
[web]
192.168.1.1
test
[servers]
test # 在哪里都可以 重复也可以

②主机名范围指定

配置文件中还有一种方式,可以指定范围内的主机名,就不需要打很多主机名了:

www[001:003].example.com

这个东西相当于:

www001.example.com
www002.example.com
www003.example.com

欸,对的!你不需要再写这么多的主机名来划定范围了,这样的话可以减少不必要的麻烦!也不一定要001 002 这样子,我们正常的写法也是可以的:

www[99:101].example.com

以上就是主机清单比较基本的内容,也是我们经常用到的。当然主机清单的基本使用还是很多的,详细的话可以看这个:Ansible 社区文档

3、基本使用

①查看主机清单生效

首先的话,我们先查看自己设置的主机清单是否生效

ansible <主机清单分类名> --list-hosts
命令执行成功效果如图,当然也可以看全部清单的内容
ansible all --list-hosts
命令执行成功效果如图

我们前面都说,Ansible是一个框架,你能所了解到的功能,都是因为它的模块。输入以下命令可以展示出Ansible的所有模块

ansible-doc -l
好多好多,就不方便展示出来了

这些都是Ansible允许各个公司根据它的准则去开发自己的模块,这些都是第三方模块,被叫做collections。这些模块都有一个统一的官方库,叫做galaxy

我们现在的话可以通过以下命令,来下载一个 windows的 Galaxy

ansible-galaxy collection install community.windows
当你看见红色框框部分 即为安装成功,同时的话你也会发现它成功安装在:
Installing 'ansible.windows:3.3.0' to '/root/.ansible/collections/ansible_collections/ansible/windows'

同时你也会在所有模块中发现 Windows 的 Galaxy。然后…你会发现你卡了,因为模块太多了…我也发现莫名其妙卡了,还不能清屏…

②测试基本功能

好的,接下来的话我们来进行一个功能的基础测试,大概的语法内容如下:

ansible <主机名> -m <模块名字> -a <传递给模块的参数>
参数备注
主机名是主机清单定义的主机组名,主机名,IP,别名,all为所有主机。 支持通配符&正则:
: — 多个组,组名之间用冒号隔开
*web* — 组名或主机名中包含 web 的
webservers[0] — webservers组中的第一台主机
模块名字不填写默认 command 模块。
最常用的模块为:command 和 shell
传递给模块的参数比如说,你用 command 模块,那传过去的参数即为被控主机所需要输入的命令

那我们以 command 这个最基础的模块来给大家来一个测试,首先的话我们对刚刚所增加的 test 服务器发送一个 ls 命令输入的请求:

ansible test -m command -a "ls"
你说这个熟悉不熟悉,不就是SSH的请求嘛——添加密钥,你可以增加密钥后输入密码,就可以执行好操作。但是我们为了后期方便进行操作,我们先进行手动添加密钥
ssh-copy-id 用户名@test

如果输入此命令时,出现:

证明你这台主机没有SSH密钥,可以输入以下命令生成:
ssh-keygen -t ed25519
一路回车就可以了,接下来你可以再次输入以上命令尝试:
输入被控主机的密码,就可以保存被控主机的密钥了。接下来我们继续尝试对被控主机发送输入 ls 命令
这就完成了 他不会显示最终输出了什么结果,如果想试试看有没有效果可以自己创建文件…之类的操作测试,欸 那 Shell和 Command 二者都是执行命令操作,那到底有什么区别?
模块区别缺点
Command只能执行那么一条命令
Shell支持管道符号 | 等内容性能比 Command差点

到目前为止的话,你基本上已经掌握了 Ansible 的最基本的内容,但是我们要学习的内容其实很多。比如说因为 Shell 的性能问题,我们总不能说直接通过 Shell 脚本搞一个 SCP 来复制文件呀,因为 Ansible 有一个模块叫做 Copy有更高的效率为什么不用高效率的模块。你说是不是?

但是话说回来,咱尽量能用 Command 就用Command模块,因为 Shell 本身会多 fork 个新的 Bash 进程出来。什么情况下得用 Shell 模块?只有当你需要管道、重定向、环境变量或其他 Shell 语法时,才使用 Shell 模块。

比如说如图,管道符号被当作 echo 的内容输出了

三、常用组件

1、补充

①关于SSH指定用户问题

基于上面的内容,这边的话有几个点/几个功能,要给大家补充一下,一个是使用指定的 ssh账户和密码,参数如下:

  • -u <用户名> # 指定ssh账户
  • -k # 指定使用 ssh 密码

示例代码:

ansible test1 -a "uptime" -u w -k

注意:这个命令还未经考证能否使用,建议小伙伴们在自己的操作系统中进行测试。@千锋教育 中测试 Centos Stream 10 中 -k无效,不管密码是否正确都可以使用。

②重定向补充

我们可以将被控主机执行的内容通过重定向输出到本地文件当中,示例代码:

ansible test1 -a "df -h" > a.txt
最终执行成功效果如图

2、Ping组件

使用 Ping 模块来测试 Ansible 节点可用性,示例代码:

ansible test1 -m ping
当完成 Ping 的传送时,会发送 Pong 响应回来。还有一个参数 -o 在这里做一个补充:
就多行变成了单行,仅仅只是显示上的区别,当然还能指定多台主机的 Ping:
ansible test1,test2,test3 -m ping

3、Ad-Hoc

这只是一个临时的用法,谈不上什么模块,相当于临时的“文档”。下列命令可以获取模块列表:

ansible-doc -l

获取指定模块的使用信息:

ansible-doc -s yum

那如果说,我们要一口气配置100台主机,比如说我要让100台主机同时安装 Nginx,这要怎么操作?难道要一个一个发公钥吗?

一个个主机一直 yes 是不是有点麻烦了?具体怎么做?如下:

首先的话先生成公钥:

ssh-keygen -t rsa -P "" -f ~/.ssh/id rsa

取消掉我们 yes/no :

vim /etc/ssh/sshd_config
将此项和 StrictHostKeyChecking 都更改为 no 并取消注释

给每一台主机发公钥(可以用 for 循环的形式进行发放):

ssh-copy-id 100台主机

然后你就可以开始发放安装 Nginx 的命令了,但是你发现效率很低,基本上是一台台主机慢慢执行操作。以下参数可以设置并行进程数(默认为5个)

-f <并行数量>

4、Copy

Copy 模块的用途很明显了,就是把 Ansible及其上的文件复制到远程被控的服务器上。基础命令如下:

ansible <服务器名称> -m copy -a "src=/etc/hosts dest=/etc/hosts owner=root group=root mode=644 backup=yes"

当然 dest 之外的后面部分都是可省略选项,没有这么多东西,那我们来分析下这些可选参数的作用:

参数名称作用选项
srcAbsible本地机器上的文件路径必选
dest被控服务器的粘贴路径必选
owner用户名可选
group可选
mode权限可选
backup当被控服务器粘贴路径有同名文件是否备份?可选(yes/no)
remote_src如果想复制被控服务器上的文件就用这个选项可选(yes/no)

5、User

也很明显,这玩意就是用户管理,直接展示代码内容,首先先生成密码为 123 的密钥:

echo '123' | openssl passwd -1 -stdin
执行成功如图

接下来添加用户:

ansible test1 -m user -a 'name=user1 password="$1$W5j0Iln/$IVzm7xTCalORzn9hbbPNg/"'

注意:单引号和双引号的位置,否则会出现不用密码就可以登录上去的漏洞!额外补充使用命令替换需要用双引号:

ansible test1 -m user -a "name=user1 password='echo '1234' | openssl passwd -1 stdin'"

你可以通过以下命令确认是否有该用户创建成功:

id <用户名>

接下来就是删除用户:

ansible test1 -m user -a "name=user1 state=absent"

6、Apt

软件包管理,就是我们常用的 apt -y install <软件包名称>,当然在 CentOS 系统中叫做 yum,首先的话展示删除软件:

ansible test1 -m apt -a 'name=nginx state=removed'

安装软件:

ansible test1 -m apt -a 'name=nginx state=latest'
就这样直接安装 Nginx

7、Service

服务管理,就是我们常用的 Systemctl <状态> <软件名> ,接下来展示示例

ansible test1 -m service -a 'name=nginx state=started'

这个基础的命令即为对 nginx 服务进行启动操作,具体参数如下:

参数名称参数
state服务状态:
started:启动
reloaded:重启
stopped:关闭
enabled是否开机自启动,选项
yes:是
no:否

8、Facts

facts其实算是一个组件不算是一个模块。那他的主要作用是用于采集被管理主机信息的一个功能,通过 setup 模块查看主机的有的 facts 信息。以下是它的一个基础命令:

ansible test1 -m setup
显示的信息非常多,因此我们可以使用如下命令来进行筛选:
ansible test1 -m setup -a 'filter=ansible_all_ipv4_addresses'
以下筛选的结果为被控服务器的IP地址,当然你也可以使用通配符来进行匹配需要的结果

四、Paybook

1、入门

Paybook是什么东西,他是一个由一个多个“play”组成的列表。讲明白点,其实就是将你要执行的 Ansible 任务集成成一个 YAML 文件来执行。关于 YAML 是什么东西,详情可以移步到:菜鸟教程,接下来给大家带来最基本的写法。

首先的话我们在需要的工作路径下创建一个 yaml 文件:

vim test.yaml

里面可以写上最基本的内容:

- name: test # 整个文件名称标识
  hosts: test1 # 主机清单的主机名称
  user: root # 用户名
  tasks: # 任务列表
  - name: test01 # 任务描述
    command: ls # 模块 + 参数
    tags: douxing # 这是一个任务标记,可用来单独执行此任务

当然可以写出多任务,多模块:

- name: test # 整个文件名称标识
  hosts: test1 # 主机清单的主机名称
  user: root # 用户名
  tasks: # 任务列表
  - name: test01 # 任务描述
    command: ls # 模块 + 参数
    tags: douxing # 这是一个任务标记,可用来单独执行此任务
#第二个任务
  - name: test02
    file: name="/tmp/test02.txt" state=touch
    tags: suibiannila

也可以将具体的参数拆分开来:

- name: test # 整个文件名称标识
  hosts: test1 # 主机清单的主机名称
  user: root # 用户名
  tasks: # 任务列表

  - name: test02
    file:
# 展开参数
      name: "/tmp/test02.txt"
      state: touch
    tags: suibiannila

设置好之后保存即可,执行以下命令就可以执行任务了

ansible-playbook test.yaml
执行成功如图

2、详解

①核心元素&补充

接下来就是给大家详解 Playbooks核心元素了:

  • Variables:变量元素,可传递给 Tasks/Templates使用
  • Tasks:任务元素,由模块定义的操作的列表,即调用模块完成任务
  • Templates:模块元素,使用了模块语法的文本文件,可根据变量动态生成配置文件
  • Handlers:处理器元素,通常指在某事件满足时触发的操作
  • Roles:角色元素

接下来详细补充一下上部分的 YAML 文件的具体内容,来自:@千锋教育

仅作为补充,基本上有用的都讲到了

②命令补充

以下的命令可以对 YAML 进行一个语法检测(感觉很少用):

ansible-playbook --syntax-check test.yaml
测试通过如图
测试不通过会具体给你打上具体错误的地方

接下来介绍的命令是测试运行:

ansible-playbook -C test.yaml
测试运行结果如图

运行指定任务

ansible-playbook -t test test.yaml
注意:-t参数指的是 tags 部分内容,必须符合才会运行

跳过指定任务:

ansible-playbook --skip-tags=标记名称 test.yaml

指定任务开始往下执行

ansible-playbook --start-at-task test05 test.yaml

③PlayBook模板

Ⅰ多个PlayBook模板

接下来的话给大家一个多个 Playbook 的模板

- hosts: test1
  remote_user: root
  tasks:
  - name: install a group
  	group: name=mygrp system=true

 # 下面是第二个 play
- hosts: test2
  remote_user: root
  tasks:
  - name: install a group
  	group: name=mygrp system=true
Ⅱ变量使用模板

下面是变量使用的模板

- hosts: test1
  remote_user: root
  # 变量在这里
  vars:
    user: "root"
  tasks:
  - name: install a group
  	group: name={{ user }} # 应用变量

 # 下面是第二个 play
- hosts: test2
  remote_user: root
  tasks:
  - name: install a group
  	group: name=mygrp system=true
Ⅲ条件执行模板

条件执行模板:

- hosts: test2
  remote_user: root
  tasks:
  - name: install a group
  	shell: shutdown -h now
  	when: ansible_menfree_mb <= 114514 # 当内存小于 114514 MB的时候执行

也有 == 的条件,比如说:

ansible_architecture == "x86_64"

也支持二级变量:

ansible_selinux.status == "disabled"
当然可以不用写这么全,你可以指定第几个元素:
ansible_lo.ipv4[0] # 这个就是第一个元素 address

当然有些情况肯定要指定第几个元素,比如说同时有好几个 address ,这种肯定要指定了

Ⅳhandlers模板

这是什么东西?接下来给大家一个模板,解释一下就通了!

- name: 123
  hosts: test1
  remote_user: root
  tasks:
  - name: install a group
  	shell: shutdown -h now
  	notify: test # 注意名字要一样
  handlers:
  - name: test
  	shell: echo "OK!"

说明:只有当 Shell 模块真正运行时,才会调用 notify 所描述的 handlers 一样的任务的相关操作,追加内容。适合那些保存文件后需要重启服务的操作。

ⅤPause模板

这是一个暂停服务,在 PlayBook 执行的过程中暂停一定时间或者提示用户进行的某些操作。示例模板:

- name: 123
  hosts: test1
  remote_user: root
  tasks:
  - name: wait on user input
  	pause: prompt="你好,任意按键继续运行"
  - name: timed wait
  	pause: seconds=30

常用参数:

参数名作用
minutes暂停多少分钟
seconds暂停多少秒
prompt打印一串信息提示用户操作

五、变量

1、在命令行补充参数

接下来的话给大家补充一个关于 Vars 变量的有关内容,在 YAML 的 PlayBook 文件当中,我们将某些值设置为变量,可以从命令行中传递变量值:

- hosts: '{{ hosts }}'
  remote_user: '{{ user }}'

可以在命令行中进行传值:

ansible-playbook test.yaml --extra-vars "hosts=test1 user=root"

也可以用 JSON 的格式进行传递:

ansible-playbook test.yaml --extra-vars "{'hosts':'test1', 'user':'root'}"

还可以将参数放在文件里面:

ansible-playbook test.yaml --extra-vars "@vars.json"

2、在主机清单中设置变量

直接在主机清单设置独一的变量,仅限该主机有效:

[web]
test1 hostname=web1

这样的话就为主机 test1 设置了独一的变量 hostname

六、Roles

1、入门

Roles的话是 Playbook 的一部分,这玩意就是让 Playbook 这个模块变成更有组织。它将层级目录分成了以下:

  • role_name/
    • files/ : 存储 copy 或 script 等模块调用的文件(也就是你想要复制粘贴的内容)
    • tasks/ : 此目录至少要有一个 main.yml 文件,用于定义每个 task
    • handlders/ : 此目录至少要有一个 main.yml 文件,用于定义每个 handler
    • vars/ : 此目录至少要有一个 main.yml 文件,用于定义各 variable
    • templates/ : 存储由 template 模块调用的模块文本
    • meta/ : 此目录至少要有一个 main.yml 文件,定义当前角色的特殊设定及其依赖关系
    • default/ : 此目录至少要有一个 main.yml 文件,用于设定默认变量

那具体如何调用这些呢?方法如下:

- hosts: HOSTS
  remote_user: USERNAME
  roles:
  - ROLE1
  - ROLE2
  - { role: ROLE3, VARIABLE: VALUE, ...}
  - { role: ROLE4, when: CONDITION}

这是一个标准的文件结构:

可以直接输入以下命令快捷创建:

mkdir {files,tasks,handlers,vars,templates}

2、案例展示

我们现在想要安装一个 Nginx 并且要部署好一个 index.html 的测试网站,我们首先在 site.yaml(随便一个名字),先补充好主机的基本信息:

- hosts: test1
  roles:
  - nginx # 如上我们所阐述的 role_name

接着在 nginx/templates 中放入我们常规的 nginx.conf 的配置文件(不懂就是 nginx 配置网站的基本配置就行)注意:模板的文件格式是 .j2

nginx/task 中创建一个 main.yml 基本任务:

# 先安装 nginx
- name: install nginx
  apt: name=nginx state=latest

# 将配置文件送到被控主机的 nginx 当中
- name: copy nginx.conf template
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf # src 就是直接引用 roles 中的模板 不需要指定具体的本机文件路径,其次 dest 是送到被控主机的路径
  notify: restart nginx # 丢到 handlers 记得重启 nginx

# 将 index.html 网站送到被控主机中
- name: copy index.html
  copy: src=index.html dest=/usr/share/nginx/html/index.html

# 确保 nginx 在运行状态中
- name: make sure nginx service running
  service: nginx=nginx state=started

nginx/handlers 中创建一个 main.yml:

- name: restart nginx
  service: name=nginx state=restarted
# 就是委托 notify 过来的重启 nginx

nginx/vars 创建一个 main.yml :

worker_connections: 1024

因为模板 j2 当中是存在一些变量的(也是 {{ worker_connections }} 的格式),因此我们需要设置变量。至此,我们 nginx 安装到部署网站这一套流程就到这结束,最后只需要输入以下命令即可开始:

ansible-playbook site.yaml

流程顺利运行,网站成功部署!


我们的 Ansible 的基础教程就给大家介绍到这里!感谢各位的阅读和支持,有问题欢迎提出!希望本教程能够帮助到各位~

暂无评论

发送评论 编辑评论

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇