ansible自动化基础学习笔记

引言

本节主要讲解的是 Ansible 工具,虽然 Chef、Puppet、SaltStack and Fabric(后面章节会讲) 等等这些都是比较流行的自动化运维管理工具,但是相较于 Ansible 来说要复杂得多,不过每个工具也是各有各的好处,这里我们就先来学习这个比较简单的一款自动化运维工具—— Ansible。

Ansible 是一款基于 python 开发,能够实现了批量系统配置、程序部署、运行命令等功能的自动化运维工具。Ansible 主要是基于模块进行工作的,本身没有批量部署的能力,真正实现部署功能的是运行的模块。

  • Ansible :运行在中央计算机上;

  • Connection Plugins :连接插件,主要用于本地与操作端之间的连接与通信;

  • Host Inventory:指定操作的主机,是一个配置文件里面定义监控的主机;

  • Modules:核心模块、自定义模块等等;

  • Plugins :使用插件来完成记录日志、邮件等功能;

  • Playbooks:执行多任务,通过 SSH 部署模块到节点上,可多个节点也可以单个节点。

Ansible 主要有两种类型的服务器:控制机器和节点。控制机器用于控制协调,而节点由控制机器通过 SSH 进行管理,并且控制机通过 inventory 来描述节点的位置。在节点的编排上,Ansible 通过 SSH 部署模块到节点上,模块临时存储在节点上,并以标准输出的 JSON 协议进行通信,从而在远程机上检索信息,发送命令等。

实验环境

两台腾讯云服务器,服务器除装过docker外,宿主机python环境皆未变动。

  • 轻量型服务器 106.55.50.77
  • G4服务器 150.158.115.54

ansible安装

ansible安装有两种方式,与supervisor一样,可以用python的pip安装,也可以用apt-get直接安装,为防止踩坑,我这里直接选择安装。

# apt安装方式
$ sudo apt update
$ sudo apt install software-properties-common    # 安装通用的管理软件库的工具
$ sudo add-apt-repository --yes --update ppa:ansible/ansible
$ sudo apt install ansible

# 直接pip安装
$ python -m pip install --user ansible
$ python -m pip install --user paramiko

安装无报错后,就能输入一些简单命令查看当前状态,ansible --version查看当前运行情况:

$ anible --version
"""
ansible 2.9.27
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/ubuntu/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.17 (default, Feb 27 2021, 15:10:58) [GCC 7.5.0]

"""

Ansible 能够同时对单台或多台机器亦或部分机器操作是通过 Inventory 来实现的, Inventory 默认保存在 /etc/ansible/hosts 配置文件中,而 Ansible 通过这个文件就可以知道要追踪的服务器了,我们这里就能加入对另一台服务器进行ssh通信,写入ssh的配置信息:

$ vim /etc/ansible/hosts

[test]
150.158.115.54 ansible_ssh_user=root ansible_ssh_pass=xxxxx

这里说明一下,nventory 文件可以有多种不同的格式(如:INI、YAML 等),具体要取决于相应的插件,这里我们举几个 Ansible 的默认格式(INI)的示例,我们可以看到如下几个例子,上述我所使用的是ssh密码方式:

# 1.常用主机(IP 地址)分组,标题是组名,用于分类系统和决定系统的控制等,可以有一台或多台。
[test]
127.0.0.1
foo.example.com

# 2.分组后添加对该组机器的登录用户和验证方式。添加主机和用户名以及私钥文件。
[dev_test]
192.168.42.3 ansible_ssh_user=ubuntu ansible_ssh_private_key_file=/path/of/keyfile

# 3.不使用分组,采用文件别名的方式。通过端口及主机来描述。
Alias ansible_host=192.168.1.50 ansible_port=6666

这三种连接方式定义为:

主机连接:

  • ansible_connection 连接到主机的类型,任何可能的连接插件名称,例如,SSH 协议类型中有:sshsmartparamiko

一般连接:

  • ansible_host 要连接的主机名称。

  • ansible_port ssh 端口号。

  • ansible_user 默认 ssh 用户名。

具体的 SSH 连接:

  • ansible_ssh_pass ssh 密码

  • ansible_ssh_private_key_file 由 ssh 使用的私钥文件。

AD-HOC 临时命令

ad-hoc :临时命令,是在输入内容后,快速执行某些操作,但不希望保存下来的命令。

一般来说,Ansible 主要在于我们后面会学到的 playbook 的脚本编写,但是,ad-hoc 相较来说,它的优势在于当你收到一个临时任务时,你只用快速简单的执行一个 ad-hoc 临时命令,而不用去编写一个完整的 playbook 脚本就可以了。

我们知道 Ansible 主要是通过模块来实现各种功能的,下面我们就通过 ping 这个简单的模块来操作一下 ad-hoc 命令。

# 对 test 分组执行命令
ansible test -m ping

# 对所有机器执行命令
ansible all -m ping

下图是实验过程:
在这里插入图片描述
可以看到首先操作执行后可能会出现图上的报错,其主要原因是 ssh 连接时需要检查验证 HOST KEY ,可在 ssh 连接命令中使用 -o 参数将 StrictHostKeyChecking 设置为 no 来临时禁用检查。如果要保存设置,可修改 Ansible 配置文件,将 /etc/ansible/ansible.cfg 中的 host_key_checking 的注释符删除即可。如下操作:
在这里插入图片描述
修改完成后再次进行相同操作,就会看到success,另外还有一些其它的基础命令为:

# 查看操作机器信息
ansible all -m setup

# 执行让操作机器输出“hello world”
ansible test -a "/bin/echo Hello world"

# 指定目标主机在某一路径下创建文件
ansible test -m file -a "dest=/home/file state=touch mode=777"

# 查询目标主机的内存
ansible test -m shell -a 'free -m'

在这里插入图片描述

针对上述这些AD-HOC的操作与结果,我们可以看到返回的类型种类为:

  • success:这个结果表示操作成功,其中有两种情况,第一种情况是当执行一些查询的简单操作并且不需要修改内容时,表示该操作没问题;第二种情况就是当这个操作曾经执行过再执行时就会直接表示成功。

  • changed:true 这样的结果表示执行的一些修改操作执行成功,如上文的创建了一个文件,或者修改了配置文件,复制了一个文件等等这类的操作就会有这样的结果。

  • failed:这样的结果表示这个操作执行失败,可能是密码错误,参数错误等等,具体看提示中的 msg 的值。并且在 playbook 中会有多个任务,中间的某个任务出现这样的情况都不会继续往下执行。

Play Book执行控制

Playbook 是一种非常简单的配置管理系统以及是多机器部署系统的基础,十分适合复杂的应用部署。同时,Playbook 还可以用于声明配置,以及编排有序的执行过程,使得在多组机器之间有序的执行指定步骤,或者同步或异步的发起任务。

Ansible 官方默认使用 YAML 这种格式来书写 Playbook,这极大的简化了语法格式,key-value的形式也让读写更加便捷。我们知道 Playbooks 是有一个或多个 plays 组成,也就是它的内容是以 plays 为元素的列表。play 的内容也被称为 task (任务),执行一个任务就是对模块的调用。

---
- hosts: test
  remote_user: root
  vars:

  tasks:
    - name: Install the package "bc"
      apt:
        name: bc
        state: present
  handlers:
...

结构说明:

  • 主机和用户(hosts)

    • hosts 参数表示一个或多个组或主机,多个时用逗号分隔。
    • remote_user 表示用户名,这里还可用 become: true 来表示使用 sudo 的权限执行操作。(原来没注意过有这操作,需要额外echo 密码,再加上sudo -S的操作太过于繁琐,而且每一步要加)
  • vars(变量)
    在任务行中可以使用变量来定义,像这样 “{ {item}}” 括起来。jinjia2语法,将变量独立出来,可以方便后期的修改和维护等,也可以在其他任务中使用。


    变量的定义可以放在如下几处:

    1. Inventory 中
    2. 全局中(var:)或者某个任务(task)中
    3. 在 roles 结构中用于存放单独的文件
    4. 在 registered 模块中注册变量,主要用于调试和判断
  • tasks(任务)
    在运行 playbook 时是从上到下依次执行,并且一个 task 在其对应的所有主机上执行完毕之后才会执行下一个 task。如果一个 host 执行 task 失败,那么这个 host 将会从整个 playbook 的 rotation 中移除。如果发生执行失败的情况,需要修正 playbook 中的错误,然后再重新执行。

    每一个 task 必须有一个 name,这样在输出任务时才可以清楚地辨别出属于哪个任务,若没有定义将会被特定标记。

  • handlers
    Handlers (可选项)和一般的 task 没有什么区别,也是一个列表项,只是通过名字来对它进行引用。Handlers 是由通知者进行 notify,如果没有被通知 handlers 不会被执行,不管有多少个通知者进行了 notify,等到所有 task 执行完成之后,handlers 也只会被执行一次。同时 handlers 也会按照声明的顺序执行。

    Handlers 最佳的应用场景是用来重启服务,或者触发系统重启操作,除此以外很少用到了。

当然上面这个模板只是部分playbook的语句,可以在官网找到还有service、shell、condition、when等语句的使用条件与书写规范,这里就不再过多介绍,掌握上面几个就能做多服务器修改同文件文件传输服务启动等例子。如下就是安装软件包的一个例子:

#  在指定目录下创建一个文件,并赋予权限
- name: create a file
    file:
         path: /home/file
         state: touch
         owner: shiyanlou
         mode: 'u+rw,g+rw'

# 复制一个文件到指定目录
  - name: copy a file
    copy:
         src: /etc/ansible/ansible.cfg
         dest: /home/file

# 安装一个软件包
- hosts: test
  become: true
  vars:
      apt_packages_ca:
         - apt-transport-https
         - ca-certificates
         - apparmor-utils

  tasks:
    - name: add CA certificates are installed.
      apt:
          name: "{
    
    { item }}"
          update_cache: yes
      with_items: apt_packages_ca

循环(Loop):

这里主要想记录一下循环(Loop),因为之前没用过。若在一个任务中想要创建大量用户或安装许多包,或者重复轮询步骤,这是通过循环(loop)就能高效的实现结果。和一般循环相似,playbook 也有标准循环、嵌套循环、哈希循环、Do-Until 循环等等,这里我们只讲解几个简单的循环语句,详细的可以参考官方的 Loop 部分。

demo:


# demo1:添加多个用户
- name: add several users
  user:
    name: "{
    
    { item }}"
    state: present
    groups: "ubuntu"
  with_items:
     - testuser1
     - testuser2

# demo2:给用户赋予多个数据库权限
- name: give users access to multiple databases
  mysql_user:
  name: "{
    
    { item[0] }}"
  priv: "{
    
    { item[1] }}.*:ALL"
  append_privs: yes
  password: "xxxx"
  with_nested:
    - [ 'Jay', 'Chou' ]
    - [ '20220311_db', '20220312_db', '20220313_db' ]

# demo3:打印一下条件输出
---
- hosts: test

  tasks:
      - name: test condition
        command: echo {
    
    {
    
     item }}
        with_items: [ 0, 2, 4, 6, 8, 10 ]
        when: item > 5
...

item:用于放置需要读取的变量的位置

with_items:用来指定需要读取出来的值

when:列出判断的条件,条件为真则执行命令,为假则 skipping 略过

playbook的执行命令为:

$ sudo vim test.yaml
$ ansible-playbook test.yaml

至于这之后,官方最后给出了一个docker.yml的例子去用playbook安装docker,我目前看来,好像是没什么必要了,其实从多服务器角度来看,如果是新机并且有做集群打算,厂家一般docker自带2019以上版本,当然,某国内系统除外,当时那docker问题坑了我好一会儿,各种报错看呆我了,结果一查版本是2018年上半年的版本,重装也要更新各种依赖,搞完一台后,其余整个系统直接ghost,都懒得再进了。

然后ansible-playbook还有很多参数与debug设置,社区也有很多Developing Plugins,但是我基本上用不到,我的使用场景就很简单,就是根据服务器不同配置去更新不同文件,或者说再启动项目,但是项目是在镜像里的,ansible的进程是不能控制docker镜像的进程,这是操作系统决定的,也是规则。所以我大部分操作都是写在sh脚本,或者说docker-compose里面,然后让ansible去调用,至于为啥不用docker swarm或者说k8s,我只能说工作中的迭代更新,不是由一个人说了算,除非说某领域已经非常完善,架构也定义得非常清楚,不然总是会尝试各种不同的东西,按照简单原则,就像网上流行的一个段子:人和程序,有一个能跑就行!emmm。。。

猜你喜欢

转载自blog.csdn.net/submarineas/article/details/123397584