3.0 Playbooks基础

概览

Ansible的核心是Playbooks(可翻译为剧本),剧本是用YAML语法书写的,来描述对被管理机器需要进行的一系列操作。剧本相当于做菜手册,上面按顺序记录了,如何把被管理机器一步步打造成指定的样子。

YAML语法相当简单,即使读者之前从未听过YAML也毫无关系,YAML书写起来比JSON格式更简单

接下来我们以运维朋友几乎都非常熟悉的,安装nginx,来演示playbooks的基础用法

示例 - 安装nginx

我们分别使用3种方法:纯手动、shell脚本、playbooks,来部署nginx,让读者有直观的认识

机器需要开启EPEL源,参考 https://blog.csdn.net/xys2015/article/details/109378741

1 纯手动

yum install --quiet -y nginx
cat << 'EOF' > /etc/nginx/conf.d/xtest1.conf
server {
    listen       7001;
    server_name  localhost;
    location / {
        root   /opt/xtest1;
        index  index.html;
    }
}
EOF
mkdir -p /opt/xtest1
echo "xtest-7001" > /opt/xtest1/index.html
systemctl start nginx
systemctl enable nginx
curl localhost:7001

2 shell脚本

上面手动执行的命令,直接可以当成脚本用

3 playbooks

# cat nginx_playbook.yml
---
- hosts: all
  tasks: 
    - name: Install Nginx
      shell: yum install --quiet -y nginx
    - name: Copy configuration files
      shell: cp xtest1.conf /etc/nginx/conf.d/xtest1.conf
    - name: Start Nginx and configure it to run at boot
      shell: systemctl start nginx && systemctl enable nginx

如果大家现在执行这份playbook,即命令

ansible-playbook nginx_playbook.yml

是会报错的,会提示cannot stat ‘xtest1.conf’: No such file or directory,这是在我们预料之内的,原因是上面的playbook直接使用的shell命令,就相当于我们把上面的每一行命令单独拿出来,登录到目标机器去执行一样,因此无对应的配置文件,而在实际工作中,nginx的配置文件都是被我们放到管理节点上的,下面我们使用Ansible自带的模块,改写上面的playbook

# cat nginx_playbook.yml
---
- hosts: 192.168.31.100
  tasks: 
    - name: Install Nginx
      yum: 
        name: nginx
        state: present 
    - name: Copy configuration files
      copy:
        src: xtest1.conf
        dest: /etc/nginx/conf.d/xtest1.conf
        owner: root
        group: root
        mode: 0644
    - name: Make sure Nginx is started now and at boot
      service: name=nginx state=started enabled=yes

目前我们无需关注Ansible资源的目录合理规划问题,任意创建一个目录,把上面的文件放进去,然后在该目录放一个配置文件,配置文件的内容参见上文,如下截图

在这里插入图片描述

如果要执行上面的playbook,移动到playbook所在的目录,然后运行ansible-playbook nginx_playbook.yml,不过别急执行,我们仔细解释下这份playbook

--- 
固定写法,一个标记,类似php代码开头都有<?php一样,在k8s里如果一个yml文件里定义多个资源也是用---分割

- hosts: 192.168.31.100
表示管理的机器,同样这个IP必须已经存放到主机清单里,all表示所有机器,这块的规则跟使用ad-hoc命令一致

yum、service模块这里非常简单,即便无任何Ansible经验也能读懂,不多解释

copy模块这里,表示的是把本机(管理机器)当前目录(相对于执行的命令)下的xtest1.conf,拷贝到目标机器的 /etc/nginx/conf.d/xtest1.conf

执行一下,看看效果

在这里插入图片描述

可以看到反复执行,目标机器不会再改变,拥有幂等性

基础语法规则

# cat nginx_playbook.yml
---
- hosts: 192.168.31.100
  tasks: 
    - name: Install Nginx
      yum: 
        name: nginx
        state: present 
    - name: Copy configuration files
      copy:
        src: xtest1.conf
        dest: /etc/nginx/conf.d/xtest1.conf
        owner: root
        group: root
        mode: 0644
    - name: Make sure Nginx is started now and at boot
      service: name=nginx state=started enabled=yes
  • 需要以 — 3个减号开始,且需顶行首写
  • 使用#号注释(可以在开头注释写上playbook的功能)
  • 缩进必须是统一的,不能将空格和Tab混用,建议统一使用2个空格作为缩进
  • key / value 可以写在一行,也可写在多行,区分大小写
  • playbook的执行是有顺序的,从上到下

真要比较起来,写在多行有个好处是,方便git追踪对比区别

常用核心参数

--inventory=PATH (-i PATH)  手动指定主机清单文件,默认是 /etc/ansible/hosts
-v    输出详细信息
-vvv  输出更详细信息
-vvvv 调试(debug)模式
--forks=NUM  指定并发执行数,默认是5
--check (-C) 不实际执行,运行检查模式
--syntax-check  语法检查
--limit ${ip}  限制执行只在单个或多个IP内(逗号分割)
--list-hosts  显示本次执行操控的IP

下面例举两个实际工作场景:初始化一批机器,和初始化单台机器,看一下上面的参数我们如何使用,准备的环境如下

[root@192-168-31-106 ~/install_nginx]# ls
nginx_playbook.yml  xtest1.conf
[root@192-168-31-106 ~/install_nginx]# cat nginx_playbook.yml 
---
- hosts: all
  tasks: 
    - name: Install Nginx
      yum: 
        name: nginx
        state: present 
    - name: Copy configuration files
      copy:
        src: xtest1.conf
        dest: /etc/nginx/conf.d/xtest1.conf
        owner: root
        group: root
        mode: 0644
    - name: Make sure Nginx is started now and at boot
      service: name=nginx state=started enabled=yes

[root@192-168-31-106 ~/install_nginx]# cat xtest1.conf 
server {
    listen       7001;
    server_name  localhost;
    location / {
        root   /opt/xtest1;
        index  index.html;
    }
}

场景1: 初始化一批nginx机器作为七层负载均衡

#查看操控了哪些机器
ansible-playbook nginx_playbook.yml --list-hosts
#检查语法
ansible-playbook nginx_playbook.yml --syntax-check
#模拟执行 (这个模拟执行并不是万能模拟)
ansible-playbook nginx_playbook.yml --check
#实际执行
ansible-playbook nginx_playbook.yml

在这里插入图片描述

如下图,模拟执行没有报错,而实际执行确报错了,原因是192.168.31.106这台机器上已经把80端口占用,再启动一个nginx也监听再80端口上,有冲突所以报错,因此模拟执行这个功能,并不是万能的,只能大致去模拟,从这里我们也可以看到一台机器执行报错,并不影响其它机器的正常运行

在这里插入图片描述

场景2 量大,之前的七层机器顶不住,新增一台七层机器(192.168.31.102)

#查看操控了哪些机器
ansible-playbook nginx_playbook.yml --list-hosts
#检查语法
ansible-playbook nginx_playbook.yml --syntax-check
#限制某台机器模拟执行
ansible-playbook nginx_playbook.yml --check --limit 192.168.31.102
#如果要限制多台,则以逗号分割
ansible-playbook nginx_playbook.yml --check --limit 192.168.31.102,192.168.31.100
#可以配合--list-hosts,再次确认
ansible-playbook nginx_playbook.yml --check --limit 192.168.31.102,192.168.31.100 --list-hosts
#实际执行
ansible-playbook nginx_playbook.yml --limit 192.168.31.102

在这里插入图片描述

顺便给大家看眼,-v参数输出的效果

在这里插入图片描述

Playbook 与 Shell 脚本差异对比

  1. Ansible 执行时会留下清晰到痕迹,告诉我们Ansible都干了什么
  2. 如果设计合理,Ansible能提供相当程度都幂等性支持 (至少能够校验该playbook是否实现了幂等)
  3. 提供了类似 --check 参数,在之际执行前,进行模拟执行,不会对目标机器实际作出改变
  4. 大型Shell脚本含义维护,一旦出问题难以debug,而设计良好的Ansible Playbook几乎无此问题

ansible-doc 查看帮助

#1 查看系统里全部模块
ansible-doc --list > /tmp/tmp.txt

#2 搜索某个模块的用法
ansible-doc --list > /tmp/tmp.txt; grep copy /tmp/tmp.txt
ansible-doc copy

这个很多时候比查看官方文档方便些,毕竟不用联网,更重要的是版本肯定一致

debug模块

这个模块用来测试Ansible一些常用的功能非常方便

[root@192-168-31-106 ~/install_nginx]# cat debug_playbook.yml 
---
- hosts: all
  tasks:
    - name: debug test 1
      debug:
        msg: 主机名 {{ ansible_hostname }}
    - name: debug test 2
      debug:
        msg: 操作系统 {{ ansible_distribution }} 版本 {{ ansible_distribution_major_version }}
[root@192-168-31-106 ~/install_nginx]# ansible-playbook debug_playbook.yml 

在这里插入图片描述

上面用的变量都是Ansible系统内置的变量,双花括号,两边留一个空格,中间写变量名称,这是固定用法,其它可以使用的变量可以通过下面的命令查询

ansible 192.168.31.100 -m setup

使用非root用户执行

# cat none-root-user.yml
- hosts: test
  tasks:
    - name: debug info 4
      become: yes
      become_user: www
      shell: whoami > /tmp/tmp2.txt

标签和指定操作系统

---
cat tags_playbook.yml
- name: copy node-ps single binary to remote machine /etc/dAppCluster
  copy: src=node-ps dest=/etc/dAppCluster/node-ps mode=0744
  tags:
  - INSTALL_OR_UPDATE
  when: 
  - ansible_distribution == "CentOS"
  - ansible_distribution_major_version == "6" or ansible_distribution_major_version == "7"

- name: copy node-ps manager scripts CENTOS7
  copy: src=node-ps.service dest=/usr/lib/systemd/system/node-ps.service
  tags:
  - UPDATE
  when: 
  - ansible_distribution == "CentOS"
  - ansible_distribution_major_version == "7"


#不指定tag,则全部执行
ansible-playbook  tags_playbook.yml --limit 192.168.31.100
#指定具体的tag,则只执行该tag下面的任务
ansible-playbook  tags_playbook.yml --tags UPDATE --limit 192.168.31.100

加上特定的标签,可以区分不同场景执行的任务,如安装是一种标签,升级是一种标签,也可以用来做测试

Ansible提示颜色信息说明

  • 翔黄色:对远程节点进行相应修改
  • 帽子绿:对远程节点不进行相应修改,或者只是对远程节点信息进行查看
  • 深红色:操作执行命令有异常
  • 浅紫色:表示对命令执行发出警告信息(可能存在的问题,给你一下建议)

参考链接

https://docs.ansible.com/ansible/latest/cli/ansible-doc.html