从零开始尝试Ansible实操
首先
这是拉克斯(LACS)圣诞降临日历2017中的第八天内容。
12月已经过去了一周,圣诞节确实越来越近了!
昨天我去了大阪港开港纪念活动车船编程马拉松,超级艰苦!
今天是我在Qiita的首次投稿,我负责。
今天的话题是最近在公司内各个地方经常听到的一个词叫做「Ansible」,
Ansible?是一种配置管理工具?而不是版本管理工具?
因为这种情况,所以我决定从零开始学习。
本文是针对初学者开始使用Ansible的人写的。目的是通过记录在参与Hands-On过程中获取的知识和通过各种调查获得的信息,用初学者的语言简单地总结并把握大体情况。请注意,本文的目标读者只有不了解”Ansible”的人。
Ansible是什么?
Ansible被称为一种配置管理工具,类似的工具有Puppet和Chef。
配置管理工具不同于像shell脚本那样只是自动化处理机器的角度,而是指为了将机器调整为特定状态而创建的工具。
如果单单听这样说可能还不太明白,我们可以通过将”在目标机器上添加用户”作为例子来确认区别。
从自动化处理的角度来看,执行”添加用户”操作会导致机器自动化处理。如果用户已经存在,则在重新执行时,如果没有进行任何错误处理,则会出现”用户已经存在”的错误。
相反,从将机器置于所需状态的角度来看,重要的是将其置于”用户已添加”的状态。判断”用户是否存在”由配置管理工具来处理,因此不会出错。
你明白了吗,有没有理解到区别呢?
不只是会不会出错的问题吗?不能轻视错误,是绝对不可以的。
Ansible的特点
以下是Ansible的特点:
一. 简单易用:Ansible具有直观的语法和用户友好的界面,使得操作与配置变得轻松。
二. 自动化:Ansible可以自动化各种任务和工作流程,减少人工干预并提高效率。
三. 可扩展性:Ansible支持模块化设计和插件系统,可以灵活地扩展功能。
四. 高度可定制性:Ansible提供丰富的选项和配置,使用户能够根据自身需求进行个性化定制。
五. 好的可扩展性:Ansible能够与各种云平台、操作系统和网络设备进行集成,适应不同的环境和需求。
六. 强大的协作能力:Ansible支持批量操作和并行执行,方便团队协作和管理多个主机。
七. 安全性:Ansible提供了各种安全机制和认证方式,确保系统和数据的安全性。
-
- エージェントレスである
-
- 何度同じ操作をしても同じ状態になる(冪等性)
- 設定ファイルがシンプルに記述できる
当你实际亲自动手尝试之后,你会发现”能够简单地编写设置文件”这一部分需要一些知识,但其中所写的内容应该会让你产生”啊,原来如此”的感觉。
Ansible培训指南
我对Ansible的解释可能有点长,但正题从这里开始。
我试着实际操作了一些在“适合Ansible初学者”的介绍中提到的内容。
作为一个对配置管理没有了解的人,有些东西我可能不太明白,所以让我们先整理一下涉及的人物角色。
在Hands-On使用的软件。
VirtualBox:言わずと知れた仮想化ソフト
Vagrant:VirtualBoxなどの仮想化ソフトの操作を代行してくれます。使用方法までは割愛しますがOSインストール済みVMの作成、ネットワーク設定やSSH環境の整備までやってくれちゃいます。(素晴らしい)
Ansible:本日の主人公です。ここまで律儀に読んでくださった方、読み飛ばした方には説明不要でしょう。
这三个角色在其中扮演了重要角色。
为了进行实践,我们已经准备好了基于Vagrant+VirtualBox的虚拟机,并将使用Ansible进行试验。
这就是我们的实践流程。
我们可以通过ssh从自己的电脑连接到实践用虚拟机,并轻松地进行实践。(感到幸福)
准备用于Ansible Hands-on的虚拟机。
好的,为了进行Ansible实践,在Vagrant中准备虚拟机。利用Box和Vagrantfile创建虚拟机环境。
Box是虚拟机的基础镜像,在实践中使用的是CentOS 6.7,但也有其他各种选择。
通过以下命令准备Box。
vagrant box add centos6.7 https://github.com/CommanderK5/packer-centos-template/releases/download/0.6.7/vagrant-centos-6.7.box
现在我们来看一下 Vagrantfile 中描述另一个虚拟机配置的内容。
Vagrant.configure(2) do |config|
config.vm.define "controller" do |node|
node.vm.box = "centos6.7"
node.vm.hostname = "controller"
node.vm.network :private_network, ip: "192.168.100.10"
node.vm.network :forwarded_port, id: "ssh", guest: 22, host: 2210
end
config.vm.define "target" do |node|
node.vm.box = "centos6.7"
node.vm.hostname = "target"
node.vm.network :private_network, ip: "192.168.100.20"
node.vm.network :forwarded_port, id: "ssh", guest: 22, host: 2220
end
end
我能大致理解这个意思。
根据Vagrantfile的内容,我认为在实践中我们将准备一个控制器和目标环境。
我们将在控制器(管理机器)上运行Ansible来操作目标(受控机器)的状态。
然后,在与Vagrantfile相同的目录下执行vagrant up命令来构建虚拟机环境。
完成以上步骤后,我们将得到如下所示的状态。
准备Ansible
现在我们已经准备好了Hands-on的环境,让我们开始准备Ansible吧。
我们将通过SSH连接到controller来安装Ansible。
Ansible的管理机器需要满足以下要求之一:已安装Python 2(版本为2.6或2.7)或Python 3(版本为3.5以上)。因此,让我们首先确认Python的版本。
[root@controller ~]# python --version
Python 2.6.6
终于轮到Ansible出场了。
我们将使用yum命令进行安装。
[root@controller ~]# yum install ansible
省略
[root@controller ~]# ansible --version
ansible 2.4.1.0
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.6/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.6.6 (r266:84292, Jul 23 2015, 15:22:56) [GCC 4.4.7 20120313 (Red Hat 4.4.7-11)]
成功安装了Ansible。
我们将进行使用Ansible的配置。由于在Ansible中通过SSH连接并执行管理目标机器的操作,因此为了方便起见,我们将进行配置以实现无密码登录(发送公钥)。详细信息请查看此处。
[root@controller ~]# ssh-keygen -t rsa
特に設定しないのでEnter
[root@controller ~]# ssh-copy-id root@192.168.100.20
尝试使用Ansible①
终于可以尝试使用Ansible了。
剩下的只需要编写配置文件并执行命令即可。
在Ansible中,存在两个配置文件,一个是用于编写管理目标的inventory文件,另一个是用于编写管理目标配置内容的Playbook文件。
首先从清单文件中将要管理的对象整理成列表并进行描述。
[root@controller ~]# mkdir /ansible
[root@controller ~]# cd /ansible
[root@controller ansible]# mkdir inventory
[root@controller ansible]# vi inventory/hosts
[target]
192.168.100.20
由于这次只有一个目标,所以非常简单。
这意味着192.168.100.20属于名为”target”的组。
(本来可能需要进行分组处理,听说不是很简单…)
接下来,我们将创建一个包含管理对象配置内容描述的Playbook。
可以说Playbook是Ansible的主要组成部分,毫不夸张地说。大概的!
message: "Hello Ansible !"
fruits:
apples:
amount: 10
bananas:
amount: 20
oranges:
amount: 30
目标.yml不是Playbook。
它是描述组变量的文件。
关于YAML格式,先不谈。(重要的是空格的数量)
- hosts: targets
user: root
tasks:
- name: output message.
debug: msg="{{ message }}"
- name: output fruits
debug: msg="We want {{ item.value.amount }} {{ item.key }} !"
with_dict: "{{ fruits }}"
这个test.yml是一个Playbook。它包含了要执行的组、执行的用户和执行的内容。
为了更直观地查看执行结果,我们将使用ansible-playbook命令进行执行。
[root@controller ansible]# ansible-playbook -i inventory/hosts test.yml
PLAY [targets] ****************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.100.20]
TASK: [output message.] *******************************************************
ok: [192.168.100.20] => {
"msg": "Hello Ansible !"
}
TASK: [output fruits] *********************************************************
ok: [192.168.100.20] => (item={'key': 'apples', 'value': {'amount': 10}}) => {
"item": {
"key": "apples",
"value": {
"amount": 10
}
},
"msg": "We want 10 apples !"
}
ok: [192.168.100.20] => (item={'key': 'oranges', 'value': {'amount': 30}}) => {
"item": {
"key": "oranges",
"value": {
"amount": 30
}
},
"msg": "We want 30 oranges !"
}
ok: [192.168.100.20] => (item={'key': 'bananas', 'value': {'amount': 20}}) => {
"item": {
"key": "bananas",
"value": {
"amount": 20
}
},
"msg": "We want 20 bananas !"
}
PLAY RECAP ********************************************************************
192.168.100.20 : ok=3 changed=0 unreachable=0 failed=0
哦,好像执行了一个我熟悉的东西。
我要查看执行的命令。
ansible-playbook -i inventory/hosts test.yml
指定的参数是什么。
-
- inventory
- Playbook
这两个是的。
然而,无论怎么看,似乎使用了在targets.yml中记载的群组变量。(很奇怪)
因为在test.yml文件中指定了hosts: targets这个组作为执行目标,所以会自动从group_vars目录加载targets.yml文件,并且定义的变量会被应用。
据说这个机制是由Ansible的依赖关系驱动的,它会从指定的目录等隐式地获取信息。(理解这一点似乎很困难)
试用Ansible②
进行了上一次的执行只是输出,但接下来将使用Ansible的模块对目标进行操作。
-
- パッケージのインストール > yamモジュール
-
- ジョブの設定 > cronモジュール
-
- ディレクトリの作成、ファイルの配置 > fileモジュール
- ファイルのコピー > copyモジュール
我会继续进行。
- hosts: targets
user: root
tasks:
- name: install packages from yum
yum: name={{ item }} state=latest
with_items:
- jq
- ruby
- httpd
- name: register cron job
cron: name="check ping" day="*/2" hour="12" minute="0" job="ping -c 3 192.168.100.10"
- name: create directories
file: path={{ item.path }} owner={{ item.owner }} group={{ item.group }} mode=0{{ item.mode }} state=directory
with_items:
- { "path":"/opt/ansible", "owner":"root", "group":"root", "mode":"755" }
- { "path":"/opt/vagrant", "owner":"vagrant", "group":"vagrant", "mode":"755" }
- name: copy files
copy: src=./files/hoge dest=/opt/ansible/hoge owner=root group=root mode=0755
这份Playbook
-
- jq, ruby, httpdをインストール
-
- pingを実行するjobの設定
-
- ansible,vagrantディレクトリの作成
- hogeファイルのコピー
进行。
[root@controller ansible]# ansible-playbook -i inventory/hosts main.yml
PLAY [targets] ****************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************************************************************************
ok: [192.168.100.20]
TASK [install packages from yum] **********************************************************************************************************************************************************************************
changed: [192.168.100.20] => (item=[u'jq', u'ruby', u'httpd'])
TASK [register cron job] ******************************************************************************************************************************************************************************************
changed: [192.168.100.20]
TASK [create directories] *****************************************************************************************************************************************************************************************
changed: [192.168.100.20] => (item={u'owner': u'root', u'path': u'/opt/ansible', u'group': u'root', u'mode': u'755'})
changed: [192.168.100.20] => (item={u'owner': u'vagrant', u'path': u'/opt/vagrant', u'group': u'vagrant', u'mode': u'755'})
TASK [copy files] *************************************************************************************************************************************************************************************************
changed: [192.168.100.20]
PLAY RECAP ********************************************************************************************************************************************************************************************************
192.168.100.20 : ok=5 changed=4 unreachable=0 failed=0
执行成功!很明显地看到了所期望的四项变更。
幂等性
如果你继续进行到这一步的实践,你将了解到Ansible的特点。
-
- エージェントレスである
- 設定ファイルがシンプルに記述できる
让我们确认一下无论进行多少次相同的操作,最终将得到相同的状态(冪等性)。再次执行相同的 main.yml 的 Playbook。
[root@controller ansible]# ansible-playbook -i inventory/hosts main.yml
PLAY [targets] ****************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************************************************************************
ok: [192.168.100.20]
TASK [install packages from yum] **********************************************************************************************************************************************************************************
ok: [192.168.100.20] => (item=[u'jq', u'ruby', u'httpd'])
TASK [register cron job] ******************************************************************************************************************************************************************************************
ok: [192.168.100.20]
TASK [create directories] *****************************************************************************************************************************************************************************************
ok: [192.168.100.20] => (item={u'owner': u'root', u'path': u'/opt/ansible', u'group': u'root', u'mode': u'755'})
ok: [192.168.100.20] => (item={u'owner': u'vagrant', u'path': u'/opt/vagrant', u'group': u'vagrant', u'mode': u'755'})
TASK [copy files] *************************************************************************************************************************************************************************************************
ok: [192.168.100.20]
PLAY RECAP ********************************************************************************************************************************************************************************************************
192.168.100.20 : ok=5 changed=0 unreachable=0 failed=0
得到了一个结果,称为没有任何变化。当该机器已经处于目标状态时,不会进行任何更改,多次相同的操作也会得到相同的状态。这种性质被称为幂等性。不进行包的安装,也不进行文件的复制。将跳过所有不必要的处理。
最后
这次省略了一部分实际操作的解释,但是为了抓住大致内容,敬请谅解。
這個工作坊是根據在公司內討論熱烈的工具而進行的,即使是完全沒有知識基礎的人也能輕鬆參與,我覺得我至少能理解到一定程度。(這僅僅是我的個人感想)也許這也是Ansible的特點之一吧。
我不太自然地说出这句话,但如果大家能够接触Ansible,我会感到非常高兴。
参考资料:
参考文献
-
- Ansibleをはじめる人に。
https://qiita.com/t_nakayama0714/items/fe55ee56d6446f67113c
サーバ管理者も開発者も知っておきたい構成管理ツールとAnsibleの基礎知識
http://www.atmarkit.co.jp/ait/articles/1603/24/news014.html
エージェントレスでシンプルな構成管理ツール「Ansible」入門
https://knowledge.sakura.ad.jp/3124/
VagrantとDockerについて名前しか知らなかったので試した
https://qiita.com/hidekuro/items/fc12344d36d996198e96
ssh-copy-idで公開鍵を渡す
https://qiita.com/kentarosasaki/items/aa319e735a0b9660f1f0