Linux云计算 |【第二阶段】AUTOMATION-DAY5

主要内容:

YAML语法格式,层级关系、Ansible Playbook文件及语法格式、Ansible变量(定义变量方法、优先级顺序、setup和debug查看变量)

补充:Ansible ad-hoc 可以通过命令行形式远程管理其他主机,适合执行一些临时性简单任务。另外还有一种远程管理的方式叫 Playbook,Ansible Playbook中文名称叫剧本,它将经常需要执行的任务写入一个文件,这个文件就叫剧本;

一、Playbook概述

1、Ansible playbook

中文名称为剧本,将经常需要执行的任务写入一个文件(剧本);剧本中可以包含多个任务;剧本写后可随时根据剧本执行相关的任务命令;playbook剧本要求按照YAML格式编写;适合执行周期性经常执行的复杂任务;

Ansible 提供了两种主要的方式来执行自动化任务:ad-hoc 命令和 Playbooks。这两种方式各有特点,适用于不同的场景。

1)Ansible ad-hoc 命令

Ad-hoc 命令是一种快速执行单个任务的方式,适合于临时性的操作。Ad-hoc 命令通常用于一次性任务,不需要编写复杂的脚本或 Playbooks。

ansible <host-pattern> -m <module> -a <arguments>
  • <host-pattern>:指定目标主机或主机组。
  • -m <module>:指定要使用的模块。
  • -a <arguments>:传递给模块的参数。

示例:

# 检查所有主机的 uptime
ansible all -m command -a "uptime"

# 在 webservers 组中的所有主机上安装 Apache
ansible webservers -m yum -a "name=httpd state=present" --become

# 重启 webservers 组中的所有主机的 Apache 服务
ansible webservers -m service -a "name=httpd state=restarted" --become

2)Ansible Playbooks

Playbooks 是 Ansible 的配置、部署和编排语言。它们使用 YAML 格式编写,定义了一系列任务,这些任务可以按顺序执行,以实现自动化目标。Playbooks 适合于复杂的、可重复的自动化任务。

- name: Playbook 名称
  hosts: 目标主机或主机组
  become: yes/no  # 是否提升权限
  tasks:
    - name: 任务名称
      module: 模块参数

示例:

# playbook.yml
- name: Install and configure Apache
  hosts: webservers
  become: yes
  tasks:
    - name: Ensure Apache is installed
      yum:
        name: httpd
        state: present

    - name: Ensure Apache is running and enabled
      service:
        name: httpd
        state: started
        enabled: yes

    - name: Configure Apache
      template:
        src: templates/httpd.conf.j2
        dest: /etc/httpd/conf/httpd.conf

运行 Playbook

ansible-playbook -i inventory.ini playbook.yml

ad-hoc 命令和 Playbooks 比较:

特性Ad-hoc 命令Playbooks
适用场景临时性、一次性任务复杂、可重复的自动化任务
语法简单,命令行格式复杂,YAML 格式
可读性较差,适合简单操作较好,适合复杂操作
可重用性低,不适合重复使用高,适合编写可重用的脚本
扩展性低,不适合复杂逻辑高,支持变量、条件、循环等
适用性适合快速检查或执行简单任务适合配置管理、应用部署等复杂任务

2、YAML简介(YAML Ain’t a Markup Language)

YAML是一个可读性高,用来表达数据序列的格式语言,YAML以数据为中心,重点描述数据的关系和结构;

YAML的格式要求如下:

① "#" 代表注释;一般第一行为三个横杠【---】;

键值对(key/value)使用【:】表示,数组使用【-】表示;

        注意:key和value之间使用":"分隔,且":" 后面必须有空格

        注意:数组使用”-“表示,且"-" 后面必须有空格

③ 一般缩进由两个或以上空格组成,相同层级的缩进必须对齐,缩进代表层级关系

        注意:全文不可以使用tab键,YAML不识别

④ 区分大小写

⑤ 扩展名为 yml 或者 yaml

⑥ 跨行数据需要使用【>】或者【|】,其中|会保留换行符

YAML格式,示例1:

  • YAML格式的键值对数据;
  • key和value之间使用“:”分隔;(“:”后面必须有空格)
  • 缩进代表层级关系

YAML格式,示例2:

  • YAML格式的数组数据
  • 使用短横杠和空格表示,一行表示数据格式[值,值,值...]

YAML格式,示例3:

YAML格式,示例4:(注意空格)

YAML格式,示例5:(“|”会保留换行符)

YAML格式,示例6:(注意“-”和“:”后面必须有空格)

补充:一个【-】为数组,可以存放多个值,需注意层级关系

二、Playbook剧本

1)Playbook 语法格式

  • playbook采用YAML格式编写;
  • playbook文件中由一个或多个play组成(使用【-】区分);
  • 每个play中关键词包含:hosts(主机)、tasks(任务)、vars(变量)等元素组成;(必须要有hosts和tasks
  • 使用ansible-playbook命令运行playbook剧本;
  • 编写剧本时,必须要在~/ansible目录,否则无法调用配置文件;

测试Playbook语法格式

1)编写第一个Playbook(剧本)

  • hosts、tasks、name是关键词(不可修改),ping是模块,调用不同模块完成不同任务。
[root@control ansible]# vim ~/ansible/test.yml
---
- hosts: all       //hosts定义要远程的主机(可一个或多个)
  tasks:         //tasks定义远程后要执行的任务有哪些
    - name: This is my first playbook     //任务描述,后面的具体内容可以任意
      ping:      //第一个任务调用ping模块,该模块没有参数
[root@control ansible]# ansible-playbook ~/ansible/test.yml

补充:name任务描述可忽略,name后面的具体内容可以任意;(用来自定义描述)

2)定义多个主机和任务的剧本

  • hosts由一个或多个组或主机组成,主机之间用逗号【,】分隔;
  • tasks由一个或多个任务组成,多个任务按顺序执行
  • 执行ansible-playbook命令可以使用[ -f ]选项自定义并发量。
[root@control ansible]# vim ~/ansible/test.yml
---
- hosts: test,webserver    //hosts定义需要远程哪些被管理主机
  tasks:       //tasks定义需要执行哪些任务
    - name: This is my first playbook
      ping:
    - name: Run a shell command
      shell: touch ~/shell.txt    //第二个任务调用shell模块在被管理主机创建一个空文件~/shell.txt
[root@control ansible]# ansible-playbook ~/ansible/test.yml
[root@control ansible]# ansible test -a "ls ~/shell.txt"
node1 | CHANGED | rc=0 >>
/root/shell.txt

 3)多个 play的Playbook文件

[root@control ansible]# vim ~/ansible/test.yml
---
- hosts: test       //第一个play剧目
  tasks:
    - name: This is my first playbook
      ping:
- hosts: webserver     //第二个play剧目
  tasks:
    - name: This is my second playbook
      ping:    
[root@control ansible]# ansible-playbook ~/ansible/test.yml  

 常见报错:”- name”中,”-”后面没有空格

1、Playbook 应用案例

案例1:用户管理,创建系统账户、账户属性、设置密码(ansible-doc user)

1)创建用户并设置UID、基本组、Password

[root@control ansible]# vim ~/ansible/test_tom.yml
---
- hosts: webserver
  tasks:
    - name: Add the user "tom"     //任务描述信息
      user:
        name: tom       //name参数
        uid: 1040
        group: daemon
        password: "{{ '123' | password_hash('sha512') }}"
[root@control ansible]# ansible-playbook ~/ansible/test_tom.yml
[root@control ansible]# ansible webserver -a "id tom"     //验证
node4 | CHANGED | rc=0 >>
uid=1040(tom) gid=2(daemon) groups=2(daemon)
node3 | CHANGED | rc=0 >>
uid=1040(tom) gid=2(daemon) groups=2(daemon)

解释说明:

# hosts定义需要远程的对象是webserver组,hosts是关键词

# tasks定义需要执行的任务,tasks是关键词

# name是第一个任务的描述信息,描述信息可以任意

# user是第一个任务需要调用的模块,user下面的缩进内容是给user模块的参数

# name是需要创建的用户名,uid是用户ID号,group是用户属于哪个基本组

# password是用户的密码,密码是123,密码经过sha512算法加密

补充:tasks的name为任务的描述信息,方便观察(可忽略),user模块下的name为参数,用来指定需要创建的用户名;


2)创建用户并设置登录解释器、附加组、Password

[root@control ansible]# vim ~/ansible/test_jerry.yml
---
- hosts: webserver
  tasks:
    - name: Add "jerry" with a bash shell
      user:
        name: jerry
        shell: /bin/bash
        groups: bin,adm
        password: "{{ '123' | password_hash('sha512') }}"
[root@control ansible]# ansible-playbook ~/ansible/test_jerry.yml
[root@control ansible]# ansible webserver -a "id jerry"    //验证
node4 | CHANGED | rc=0 >>
uid=1041(jerry) gid=1041(jerry) groups=1041(jerry),1(bin),4(adm)
node3 | CHANGED | rc=0 >>
uid=1041(jerry) gid=1041(jerry) groups=1041(jerry),1(bin),4(adm)

解释说明:

# shell指定用户属于哪个解释器

# groups指定用户属于哪些附加组

注意:passowrd “{{}}”,花括号为固定格式,外面必须要有双引号; 


3)删除用户及家目录、邮箱

[root@control ansible]# vim ~/ansible/test_jerry.yml
---
- hosts: webserver
  tasks:
    - name: Remove the user "jerry"
      user:
        name: jerry
        state: absent
        remove: yes       //删除用户家目录,邮件
[root@control ansible]# ansible-playbook test_jerry.yml
[root@node3 home]# id jerry      //验证,查看用户是否被删除
id: 'jerry': no such user
[root@node3 home]# ls /var/mail/    //验证。查看用户邮箱是否被删除;
tom

解释:# state的值设置为absent是删除用户

案例2:使用playbook管理逻辑卷(ansible-doc parted,ansible-doc lvg,ansible-doc lvol)

  • 准备工作:给node2主机再添加一块磁盘并安装软件包lvm2
[root@node2 ~]# lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sr0     11:0    1 1024M  0 rom  
vda    253:0    0   30G  0 disk
`-vda1 253:1    0   20G  0 part /
vdb    253:16   0   20G  0 disk
[root@node2 ~]# yum -y install lvm2   //安装软件包才可使用vgcreate、lvcreate

[root@control ansible]# vim ~/ansible/lvm.yml
---
- hosts: node2
  tasks:
    - name: Create a new Primary partition with a size of 1GiB
      parted:         //调用parted模块进行分区
        device: /dev/vdb    //对/dev/vdb磁盘进行分区
        label: gpt     //分区表类型为gpt,或msdos
        number: 1    //分区编号(创建第几个分区)
        state: present  //present是创建分区,absent是删除分区
        part_start: 1MiB  //分区的开始位置(默认从最开始位置分区)
        part_end: 1GiB  //分区的结束位置(不写就分到磁盘最后位置)
    - name: Create a volume group "my_vg"
      lvg:     //调用lvg模块,创建VG卷组
        vg: my_vg    //创建的卷组名称
        pvs: /dev/vdb1    //使用哪个分区创建PV
    - name: Create a logical volume of 512m
      lvol:    //调用lvol模块创建LV
        lv: my_lv    //需要创建的LV名称
        vg: my_vg   //使用哪个VG创建LV
        size: 512M   //需要创建的LV大小,可以不指定单位,默认单位m
[root@control ansible]# ansible-playbook lvm.yml
[root@node2 ~]# lsblk     //验证
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sr0     11:0    1 1024M  0 rom  
vda    253:0    0   30G  0 disk
`-vda1 253:1    0   20G  0 part /
vdb    253:16   0   20G  0 disk
`-vdb1 253:17   0 1023M  0 part
[root@node2 ~]# vgs    //验证
  VG    #PV #LV #SN Attr   VSize    VFree  
  my_vg   1   1   0 wz--n- 1020.00m 508.00m
[root@node2 ~]# lvs    //验证
  LV    VG    Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  my_lv my_vg -wi-a----- 512.00m   

注意:使用parted、lvg、lvol有幂等性,所以创建分区后下次不会再创建;

注意:使用parted分区,按照ansible-doc parted帮助,需要加state: present;

补充:part_start可忽略,默认从最开始位置分区;part_end不写默认分配磁盘最后位置

补充:format模块,用来进行格式化

常见报错:在分区进行的开始和结束位置时,单位(GiB、MiB)必须补全,否则报错;

案例3:使用playbook管理软件(ansible-doc yum)

补充:RHEL或CentOS系统中的软件有组包的概念,使用yum grouplist或者dnf grouplist可以查看组包的名称。(RHEL8中还有module模块概念,与group组包一样)

补充:有关yum针对组包(group)的命令

  • yum groupinfo     //查看组包信息(类似yum info)
  • yum groupinstall   //下载组包(类似yum install)
  • yum grouplist      //列出组包(类似yum grouplist)
  • yum groupremove   //删除组包(类似yum remove)
  • yum groupupdate   //升级组包(类似yum update)

例如:

[root@control ansible]# yum grouplist    //列出软件包组
Available Environment Groups:    //可用的环境组包
   Server with GUI
   Server
   Workstation
   Virtualization Host
...

例如:

[root@control ansible]# vim ~/ansible/package.yml
---
- hosts: webserver
  tasks:
    - name: Install a list of packages   //任务1描述,下载一些软件包
      yum:    //调用yum模块安装软件
        name:     //安装软件的名字,它的值有多个,使用数组-
          - httpd
          - mariadb
          - mariadb-server
    - name: Intall the 'RPM Development Tools' packages group  //任务2描述,下载组包
      yum:     //调用yum模块安装软件组包
        name: "@RPM Development Tools"    //安装哪个组包,@是关键词,代表组包
    - name: update software    //任务3描述,升级软件
      yum:     //调用yum模块升级软件
        name: '*'     //需要升级哪些软件,【*】代表所有
        state: latest    //latest代表升级软件
[root@control ansible]# ansible-playbook package.yml

[root@node3 ~]# rpm -qa httpd mariadb mariadb-server       //验证软件包
mariadb-server-10.3.17-1.module+el8.1.0+3974+90eded84.x86_64
mariadb-10.3.17-1.module+el8.1.0+3974+90eded84.x86_64
httpd-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64
[root@node3 ~]# yum grouplist | grep 'RPM Development Tools'    //验证组包
   RPM Development Tools
或者
[root@node3 ~]# yum grouplist
Installed Groups:      //已安装的组包
   RPM Development Tools
   ...

解释:state的值可以是(present安装 | absent卸载 | latest升级)

遇到问题:验证组包时,出现“Failed to set locale, defaulting to C.UTF-8”报错,表示没有设置正确的语言环境;

解决办法:#

echo "export LC_ALL=en_US.UTF-8"  >>  /etc/profile
source /etc/profile


2、Ansible变量应用案例

案例要求:熟悉setup与debug模块、熟悉各种常见的变量定义方式

2.1 Ansible特殊模块

1)setup模块

  • setup模块可显示ansible_facts变量;
  • ansible_facts用于采集被管理设备的系统信息,所有收集的信息都被保存在变量中,每次执行playbook默认第一个任务就是Gathering Facts,使用setup模块可以查看收集到的facts信息;

例如:假设只编写1个任务,默认还有Gathering Facts任务,收集被控制端系统信息

[root@control ansible]# vim ping.yml
---
- hosts: test
  tasks:
    - name: ping test
      ping:

结果:显示完成任务OK为2个,其中一个为Facts任务,另一个为Play任务;

例如:使用setup模块查看收集到的facts信息(类似shell中的env查看环境变量)

[root@control ansible]# ansible test -m setup  //收集到的fasts信息即变量
node1 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.4.11"
        ],
...

实验:找出以下facts变量(可使用ansible test -m setup | less  //可翻页和【/】搜索查看)

  • ansible_all_ipv4_addresses #IP地址
  • ansible_bios_version #主板BIOS版本
  • ansible_memtotal_mb #总内存
  • ansible_hostname #主机名
  • ansible_fqdn #主机的域名
  • ansible_devices.vda.partitions.vda1.size #某磁盘分区大小(有父子关系使用【.】分隔)

2)debug模块

  • debug模块可显示变量的值,可辅助排错
  • 通过msg参数可以显示变量的值,变量必须要使用【{{}}】扩起来(类似shell中引用变量的$)
  • 格式:msg: “{{需要显示的变量}}”

例如:通过debug模块+ msg参数显示变量的值

[root@control ansible]# vim ~/ansible/debug.yml
---
- hosts: test
  tasks:
     - debug:
         msg: "Hostname is :{{ ansible_hostname }}"   //显示被控制端主机名
     - debug:
         msg: "Mem is :{{ ansible_memtotal-mb }}"    //显示被控制端内存
[root@control ansible]# ansible-playbook debug.yml

2.2 定义变量的方法

  • Ansible支持十几种定义变量的方式,这里我们仅介绍其中一部分变量。

下面是根据优先级排序的定义方式:(从小到大排序)

① Inventory变量 ↓

② Host Facts变量 ↓

③ Playbook变量 ↓

④ 变量文件

定义变量优先级顺序:变量文件> Playbook变量> Host Facts变量> Inventory变量


① Inventory变量(在主机清单配置文件中定义变量)

[root@control ansible]# vim ~/ansible/inventory
[test]
node1 iname="nb"   //在node1主机后面给该主机添加变量iname,值为nb
[proxy]
node2
[webserver]
node[3:4]
[database]
node5
[cluster:children]
webserver
database
[webserver:vars]  //给webserver组定义变量,vars是关键词不可以改变,webserver是上面定义的组
iname="dachui"   //给这个组定义变量iname="dachui"

补充:定义的变量iname虽然变量名相同,但在不同主机/主机组所以不会覆盖;

下面编写剧本调用刚才的变量:(在剧本中需要调用变量是要使用{{}})

[root@control ansible]# vim ~/ansible/inventory_var.yml
---
- hosts: test,webserver
  tasks:
    - name: create a user with var.
      user:        //调用user模块,创建用户
        name: "{{ iname }}"     //创建的用户名是iname这个变量
[root@control ansible]# ansible-playbook inventory_var.yml

[root@node1 ~]# id nb      //验证
uid=1000(nb) gid=1000(nb) groups=1000(nb)
[root@node3 ~]# id dachui      //验证
uid=1041(dachui) gid=1041(dachui) groups=1041(dachui)

注意事项:

  • ① 在ansible剧本中当调用变量时,开始位置就调用变量,需要在{{}}外面加双引号【“”】
  • ② 如果是在后面或者中间位置调用变量{{}},外面可以不加双引号

"{{ iname }}"

nihao {{ iname }}


② Host Facts变量(可以直接调用ansible收集的系统信息,“ansible_facts变量”)

[root@control ansible]# vim ~/ansible/facts_var.yml
---
- hosts: test
  tasks:
    - name: create user.
      user:         //调用user模块,创建用户
        name: "{{ansible_hostname}}"   //创建用户名为变量ansible_hostname的主机,“ansible_hostname”是一个ansible_facts变量。
[root@control ansible]# ansible-playbook facts_var.yml
[root@node1 ~]# id node1    //验证查看node1主机是否有与主机名同名的用户
uid=1001(node1) gid=1001(node1) groups=1001(node1)

③ Playbook变量(使用vars关键词可以在playbook内定义变量)

[root@control ansible]# vim ~/ansible/playbook_var.yml
---
- hosts: test
  vars:         //vars是关键词,用来定义变量用的
    iname: heal    //定义变量名iname,值是heal
    ipass: '123456'   //定义变量名ipass,值是123456
  tasks:
    - name: Use variables create user.    //任务描述信息,使用变量创建用户
      user:     //调用user模块创建用户
        name: "{{iname}}"   //创建的用户名是vars定义的变量iname
        password: "{{ipass | password_hash('sha512')}}"  //创建的密码是vars定义的变量ipass,管道给password_hash把密码进行sha512加密
[root@control ansible]# ansible-playbook playbook_var.yml

[root@node1 ~]# id heal    //验证
uid=1002(heal) gid=1002(heal) groups=1002(heal)

注意:密码必须是字符串,需要引号;

注意:使用vars关键词,需要在tasks任务前面定义,否则执行任务无法调用定义的变量

定义变量优先级顺序:变量文件> Playbook变量> Host Facts变量> Inventory变量


④ 单独定义个变量文件,在playbook中用vars_files模块调用该文件

  • 当变量比较多时,可以专门定义一个文件用来存变量,然后在通过playbook调用文件;
[root@control ansible]# vim ~/ansible/variables.yml  //定义变量文件(文件名随意)
---
iname: cloud
ipass: '123456'

[root@control ansible]# vim ~/ansible/file_var.yml
---
- hosts: test
  vars_files: variables.yml     //调用变量文件
  tasks:
    - name: Use variables.yml create user.
      user:
        name: "{{iname}}"     //调用user模块创建用户
        password: "{{ipass | password_hash('sha512')}}"
[root@control ansible]# ansible-playbook file_var.yml
[root@node1 ~]# id cloud     //验证
uid=1003(cloud) gid=1003(cloud) groups=1003(cloud)

解释:用户名是变量文件variables.yml中定义的变量iname,密码是变量文件中定义的ipass变量;

思维导图:

小结:

本篇章节为【第二阶段】AUTOMATION-DAY5 的学习笔记,这篇笔记可以初步了解到 YAML语法格式,层级关系、Ansible Playbook文件及语法格式、Ansible变量。


Tip:毕竟两个人的智慧大于一个人的智慧,如果你不理解本章节的内容或需要相关笔记、视频,可私信小安,请不要害羞和回避,可以向他人请教,花点时间直到你真正的理解

  • 26
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值