IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 干货篇 一文带你了解Ansible(下) -> 正文阅读

[系统运维]干货篇 一文带你了解Ansible(下)

干货篇 | 一文带你了解Ansible(上)中,我们了解了什么是ansible、 ansible 的原理以及一些常用的 ansible 命令和 ansible 模块

但是这在一些实际场景上还是不能算是最优解决方案,例如以下场景

一天,老板让你用 ansible 给多台主机部署http服务,往往在部署httpd服务的时候我们需要下载httpd包
,还要根据每台主机的实际情况(CPU、内存等)来进行不同的配置,除此之外还要开启我们的
httpd服务等等一系列操作

按照上篇文章所讲的内容,我们是可以使用 ansible 来进行一键部署的,但是需要我们根据不同的操作(创建用户、修改配置、下载管理包等)来使用不同的 ansible 模块(user、file、yum等),这样一来,也是比较繁琐的,不算是比较好的解决方案

那么我们有什么方法将上面这些操作只需要一个命令就能都进行而不是我们一条一条的敲呢?

答案是:有!

接下来我将介绍 ansible 中的一大神器——playbook。翻译成中文就是剧本

playbook

playbook字面意思,即剧本,现实中由演员按照剧本表演,在Ansible中,这次由计算机进行表演,由计算机安装、部署应用,提供对外服务,以及组织计算机处理各种各样的事情

通俗点来讲,playbook是由一个或多个“play”组成的列表。而“play”就相当于执行的每条 ansible 命令,每条 ansible 命令组成起来成一个playbook,来实现复杂的任务

我们也可以理解为脚本,这个脚本包括 ansible 单条命令的集合

playbook执行过程

1.将以编排好的任务集(ansible 单条命令集合)写进playbook

2.通过ansible-playbook命令分拆任务集逐条执行ansible命令,按预定规则逐条执行

其次,playbook 采用 YAML 语言编写,看到这里可能有些读者不知道什么是 YAML 语言,这里我简单介绍一下

更多的内容及规范参见http://www.yaml.org

YAML语言

1.YAML是一个可读性高的用来表达资料序列的格式。YAML参考了其他多种语言,包括: XML、C语言、Python、 Perl以及电子邮件格式RFC2822等。Clark Evans在2001年在首次发表了这种语言,另外Ingy dot Net与Oren Ben-Kiki也是这语言的共同设计者YAML Ain’t Markup Language ,即YAML不是XML。不过,在开发的这种语言时, YAML的意思其实是: “Yet Another Markup Language” (仍是一种标记语言)

2.特性:

  • 可读性好

  • 和脚本语言的交互性好

  • 使用实现语言的数据类型

  • 有一致的信息模型

  • 易于实现

  • 可以基于流来处理

  • 表达能力强,扩展性好

我们先来看一下 playbook 的基本格式

[root@ansible ansible]# vim hello.yml
  ---
  - hosts:webservers
    remote_user: root  #指定远程登录用户
?
    tasks:
      - name: hello
        command: hostname

我们可以看到,palybook 由于是 YAML 语言编写的,所以后缀名是 .yml 或者 .yaml

其次,开头我们一般会用连续三个连字号(-)区分不同内容,而 hosts 是执行的远程主机列表,tasks 就是我们的任务列表,在tasks里面一个name对应一个task,command也就是 ansible 单个模块

核心要素

在playbook中,有这几大核心要素

  1. hosts:主机列表
  2. tasks:任务
  3. variables:变量
  4. templates:模板
  5. handlers和notity:触发器
  6. tags:标签

hosts

即我们要执行的远程主机列表,我们在上一篇文章中介绍过主机列表(主机清单)

playbook 中的每一个task都的目的都是为了让某个或者某些主机以指定的某个用户来执行

所以说我们在写 playbook 时首先要先告知是哪些主机来执行task(执行task的主机要先在主机清单里定义好)

我们的主机清单存储路径在 /etc/ansible/hosts

首先定义好我们的主机清单,添加 webserver 主机组

[root@ansible ansible]# vim /etc/ansible/hosts
  [webserver1]
  www.salted1.com
  www.salted2.com
  192.168.0.1

之后我们在 playbook 中指出是哪些主机要执行

[root@ansible ansible]# vim test1.yml
---
-hosts:webserver1
 remote_user:root  #指定在远程主机上执行task的用户为root

tasks

任务列表。在任务列表下面有许多个任务,每个任务只能对应一个模块,执行顺序为由上到下

例如我想让主机清单里的 webserver 主机组以root身份创建一个新的文件 newfile,并且添加一个系统用户user1,其shell为/sbin/nologin

[root@ansible ansible]# vim test.yml
---
- hosts: webserver
  remote_user: root
  # 定义任务列表
  tasks:
    - name: create a newfile
      file: name=/data/newfile state=touch
    - name: create a user
      user: name=user1 shell=/sbin/nologin system=yes

之后我们运行即可

# 可以先用 -C 参数先测试
ansible-playbook -C test.yml
?
# 发现没有报错,执行
ansible-playbook test.yml

variables

为了使得我们的 playbook 更加灵活,playbook 里面引用了变量的概念

变量名规范:仅由字母,数字和下划线组成,并且只能以数字开头

变量来源:

  • 远程主机上的变量(可以直接调用)

  • 在主机列表中定义变量

    • 普通变量:主机组中的主机单独定义
    • 公共变量:也称组变量,针对主机组里面的主机统一定义
  • 在playbook中定义并通过命令行赋值

    • ansible-playbook -e varname=value

**调用变量:**需要在变量名外面加上花括号,例:{{ varname }}

存放变量的文件

为了便于维护定义的变量,我们可以将常用的变量写进一个文件里面

[root@ansible ansible]# vim vars.yml
var1: httpd
var2: ospfd

当我们编写 palybook 需要使用文件里的变量时,可以直接调用

[root@ansible ansible]# vim test.yml
---
 - hosts: webserver
   remote_user: root
   var_files:
     - vars.yml
     
   tasks:
     - name: install httpd
       yum: name={{ var1 }}
     - name:install ospfd
       yum:name={{ var2 }}

远程主机变量

当我们运行 playbook 时,默认都会运行一个名为 “Gathering Facts” 的任务,ansible 通过这个默认任务去搜集远程主机的相关信息(例如远程主机的ip地址、主机名、系统版本、硬件配置等信息),这些相关信息会保存在对应的变量中,当我们想要使用这些信息时,可以通过获取相应的变量来使用这些信息

如果想要查看远程主机的相关的变量,我们可以使用 setup 模块

[root@ansible ansible]# ansible 192.168.10.2 -m setup
192.168.10.2 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.10.2",
            "192.168.122.1"
        ],
        "ansible_all_ipv6_addresses": [
            "fe80::1f2f:cc8b:e62b:863b"
        ],
        "ansible_apparmor": {
            "status": "disabled"
        },
        "ansible_architecture": "x86_64",
        "ansible_bios_date": "05/19/2017",
        "ansible_bios_version": "6.00",
        "ansible_cmdline": {
            "BOOT_IMAGE": "/vmlinuz-3.10.0-957.27.2.el7.x86_64",
            "LANG": "zh_CN.UTF-8",
            "crashkernel": "auto",
            "quiet": true,
            "rd.lvm.lv": "centos/swap",
            "rhgb": true,
            "ro": true,
            "root": "/dev/mapper/centos-root"
        }
 ......................

我们可以看到,返回的信息上是json格式的字符串

我们也可以通过过滤工具 filter ,这样就不用一下子获取这么多变量,去获取我们想要的变量

例如我们想要获取远程主机的 hostname

ansible webserver -m setup -a "filter=ansible_hostname"

或者我们想要获得远程主机的主机名

ansible all -m setup -a "filter=ansible_fqdn"

playbook中定义的变量

我们还可以在 playbook 中定义我们的变量,再通过命令将我们定义好的变量进行赋值,好处就是灵活性更高

设置单个变量

[root@ansible ansible]# vim test.yml
---
- hosts: werbserver
  remote_user: root
?
  tasks:
    - name: install package
      yum: name={{ varname }}
    - name: start service
      service: name={{ varname }} state=started
?
# 在命令行里通过 -e 参数 给变量赋值
anisble-palybook webserver -e 'varname=httpd' test.yml

设置多个变量

[root@ansible ansible]# vim test.yml
---
- hosts: webserver
  remote_user: root
?
  tasks:
    - name: install package
      yum: name={{ varname1 }}
    - name: install package
      yum: name={{ varname2 }}
?
# 在命令行里通过 -e 参数 给变量赋值
anisble-palybook webserver -e 'varname1=httpd varname2=ospfd' test.yml

设置变量组

[root@ansible ansible]# vim test.yml
---
- hosts: werbserver
  remote_user: root
?
  vars:
    - varname1: httpd
    - varname2: vsftpd
?
  tasks:
    - name: install package
      yum: name={{ varname1 }}
    - name: install package
      yum: name={{ varname2 }}

普通变量和公共变量

这类变量一般在主机清单里面定义

普通变量:仅针对主机组中的单个主机单独定义

公共变量:也称组变量。对主机组中的所有主机统一定义

我们先来看下普通变量

[root@ansible ansible]# vim /etc/ansible/hosts
[webserver]
192.168.244.100 http_port=81
192.168.244.101 http_port=82

编写playbook

[root@ansible ansible]# vim test.yml
---
- hosts:webserver
  remote_user: root
?
  tasks:
    - name: set hostname
      hostname: name=www{{ http_port }}.com

这里我们可以看到,不同的主机定义的 http_port 是不一样的,所以在执行 playbook 之后每台主机的 hostname 也不一样

接下来我们设置公共变量

[webserver]
192.168.244.100 
192.168.244.101 
[werserver:vars]
nodenmae=www
domainname=edu.com

编写 playbook

[root@ansible ansible]# vim test.yml
---
- hosts:webserver
  remote_user: root
?
  tasks:
    - name: set hostname
      hostname: name={{ nodename }}.{{ domainname }}
?

因为是公共变量,所以该主机组内的所有主机的 hostname 都是一样的

template 模板

template是一种使用 jinjia2 语言格式作为文本文件模板,我们可以通过编写 template 来替换文件中的一些变量并实现一些简单逻辑

下面我们通过两个个例子来让大家对template 模板有一个初步印象

                                     例一

在nginx的配置文件中,产生的worker进程数默认是自动的,nginx会根据当前主机的cpu个数来产生相应的worker进程。

真实情况下我们的远程主机的硬件配置跟ansible服务器不是完全相同的,ansible服务器可能只有一个CPU,而有的主机可能有2个CPU,有的可能有4个CPU

如果我们单纯地用copy模块将ansible服务器的nginx配置文件传送到不同的主机下,往往就会导致worker进程数跟主机的CPU个数不对应

这时候我们就可以通过 template 模块来根据不同主机的CPU数量产生不同的worker进程数

首先我们创建一个 名为template的目录(建议与 playbook 目录为同一层级)

[root@ansible ansible]# mkdir templates
[root@ansible ansible]# ls
ansible.cfg  templates  test_template.yml

新建一个template 模板 nginx.conf.j2,注意后缀名为 .j2,并且将 nginx 配置文件复制到 template 模板下

cp /etc/nginx/nginx.conf templates/nginx.conf.j2

然后编写我们的playbook

[root@ansible ansible]# cat test_template.yml
---
- hosts: webserver
  remote_user: root
?
  tasks:
    - name: install package
      yum: name=nginx
    - name: copy template
      template: src=nginx.conf.j2  dest=/etc/nginx/nginx.conf
      notify: restart service
    - name: start service
      service: name=nginx state=started enabled=yes

注意:ansible服务器下的 template 模板后缀名有 .j2,传送到远程主机后应把 .j2后缀名给去掉

这样我们就能实现根据不同远程主机的 worker 进程数跟远程主机的CPU数量所对应

                                   例二

使用template模板使得都是 nginx 服务,但不同远程主机的nginx 端口不一样

首先我们定义普通变量,使得不同远程主机的端口号不一样

[webserver]
192.168.244.141 http_port=8080
192.168.244.135 http_port=9090

将 nginx 配置文件复制到template模板下,并将监听的端口修改为在主机清单里定义的变量

[root@ansible ansible]# vim templates/nginx.conf.j2 
....
   server {
        listen       {{ http_port }} default_server;
        listen       [::]:{{ http_port }} default_server;
?
....

这样在192.168.244.141主机下的监听端口为8080,而在另一台主机下的监听端口为9090

handlers和notify 触发器

我们通过handlers和notify结合使用来实现触发器操作

**handlers:**在task列表中,只有当关注的资源发生变化时,才会采取相应的操作

notify:与handlers配套使用。调用handlers中的定义的操作;用于每个play的最后被触发,这样就可以避免多次发生改变时每次都会执行notify的操作。仅在所有的变化发生完成后一次性地执行指定操作

下面我们结合一个案例来进行讲解

案例
一般情况下,当修改了 httpd 的配置文件后我们需要重启httpd服务才会使得配置文件生效,这时候我们就可以通过触发器来实现一旦发现配置文件有修改就重启服务的操作

下面编写playbook

需求:在远程主机上安装httpd服务并将ansible主机上的配置文件复制过去,当被控机收到传送过来的配置文件后就重启服务使得配置文件生效

[root@ansible ~]# vim httpd.yml
---
- hosts: webserver
  remote_user: root
?
  tasks:
    - name: install httpd package
        yum: name=httpd 
    - name: copy config file
        file: src=/etc/httpd/httpd.conf dest=/etc/httpd/ backup=yes
        notify: restart service
    - name: service start
        service: name=httpd state=started enabled=yes
?
  handlers:
    - name: restart service
      service: name=httpd state=restarted

我们还可以编写多个触发器

当ansible主机的配置文件传送到远程主机上后,就会触发重启服务和检查nginx进程这两个操作

[root@ansible ~]# vim httpd.yml
---
- host: webserver
  remote_user: root
?
  tasks:
    - name: add group nginx
      group: name=nginx 
    - name: add user nginx
      user: name=nginx group=nginx
    - name: install nginx
      yum: name=nginx enabled=yes
    - name: copy conf
      file: src=/root/conf.txt dest=/etc/nginx/nginx.conf
      notify:
        - restart nginx
        - check nginx process
  handlers:
    - name: restart nginx
      service: name=nginx state=restarted 
    - name: check nginx process 
      shell: killall -0 nginx > /tmp/nginx.log

tags标签

使用 tag 标签可以让我们执行 playbook 里面指定的内容,无需按照从上到下的顺序依次执行

比如说我们编写一个部署 httpd 的 playbook,并且后期想跳过安装,文件配置等操作直接开启服务

[root@ansible ~]# vim tags.yml
---
- hosts: webserver
  remote_user: root
?
  tasks:
    - name: install httpd package
      yum: name=httpd
    - name: copy config file
      flie: src=/etc/httpd/httpd.conf dest=/etc/httpd/httpd.conf
    - name: start service
      service: name=httpd state=started enabled=yes
      tags: httpdservice

编写后在命令行里面使用 -t 参数来实现标签操作

ansible-palybook -t httpdservice tags.yml

多个动作也可以使用同一标签

[root@ansible ~]# vim tags.yml
---
- hosts: webserver
  remote_user: root
?
  tasks:
    - name: install httpd package
      yum: name=httpd
      tags: httpdservice
    - name: copy config file
      flie: src=/etc/httpd/httpd.conf dest=/etc/httpd/httpd.conf
    - name: start service
      service: name=httpd state=started enabled=yes
      tags: httpdservice

命令行里指定标签执行

ansible-palybook -t httpdservice httpd.yml

以上就是 ansible playbook 的核心要素了

除此之外,我们还可以在 playbook 中使用一些编程语言上的条件控制语句来实现一些简单的逻辑

逻辑实现

when

根据某一判断条件(变量、执行结果等)来实现逻辑

[root@ansible ~]# vim when.yml
---
- hosts: webserver
  remote_user: root
  tasks:
    - name: shutdown RedHat flavored systems
      conmand: /sbin/shutdown -h now
      when: ansible_ os_ family == "RedHat"

迭代

1.当有需要重复性执行的任务时,可以使用迭代机制

2.对迭代项的引用,固定变量名为{{ item }}

3.要在task中使用with_ items给定要迭代的元素列表

**利用迭代创建多个文件

**

[root@ansible ansible]# vim test_item.yml
---
- host: webserver
  remote_user: root
?
  tasks:
    - name: create some files
      file: name=/data/{{ item }} state=touch
      with_items:
        - file1
        - file2
        - file3

利用迭代安装多个包

[root@ansible ansible]# vim test_item.yml
---
- host: webserver
  remote_user: root
?
  tasks:
    - name: install package
      yum: name={{ item }}
      with_items:
        - nginx
        - sysstat
        - httpd

迭代+when判断语句

[root@ansible ansible]# vim test_item.yml
---
- host: webserver
  remote_user: root
?
  tasks:
    - name: create some files
      file: name=/data/{{ item }} state=touch
      when:ansible_distribution_major_version == '7'
      with_items:
        - file1
        - file2
        - file3

迭代还可以嵌套

使用迭代来创建组和用户,并将用户添加到不同的组当中

[root@localhost ansible]# cat test_item.yml 
---
- hosts: webserver
  remote_user: root
?
  tasks:
    - name: create some group
      group: name={{ item }}
      with_items:
        - g1
        - g2
        - g3
    - name: create some user
      user: name={{ item.name }} group={{ item.group }}
      with_items:
        - {name: "user1" , group:  "g1"}
        - {name: "user2" , group:  "g2"}
        - {name: "user3" , group:  "g3"}

总结

今天这篇文章写的比较长,干货比较多,希望你们可以耐着性子看下去,并结合自己的思考,如果有不懂的地方可以后台私信我或留言

以下是今天这篇文章的脑图

img

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-08-19 12:28:08  更:2021-08-19 12:30:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 9:45:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码