@ansible自动化运维详解(总述)

ansible

@ansible自动化运维详解(总述)_第1张图片

[自动化运维应用场景]

“运维的未来是,让研发人员能够借助工具、自动化和流程,并且让他们能够在运维干预极少的情况下部署和运营服务,从而实现自助服务。每个角色都应该努力使工作实现自动化。” ——《运维的未来》

[企业实际应用场景分析]

  • Dev开发环境
  • Test测试环境
  • Pre预发布环境
  • Master生成环境

[自动化运维应用场景]

  • 文件传输
  • 应用部署
  • 配置管理
  • 任务流编排

[常用自动化运维工具]

  • Ansible:python,Agentless,中小型应用环境
  • Saltstack:python,一般需部署agent,执行效率更高
  • Puppet:ruby, 功能强大,配置复杂,重型,适合大型环境
  • Fabric:python,agentless
  • Chef:ruby,国内应用少

[Ansible]

Ansible是一个自动化统一配置管理工具,自动化主要体现在Ansible集成了丰富模块以及功能组件,可以通过一个命令完成一系列的操作,进而能减少重复性的工作和维护成本,可以提高工作效率。

官网:https://www.ansible.com/
官方文档:https://docs.ansible.com/
源代码仓库:https://github.com/ansible/ansible

[Ansible发展史]

作者:Michael DeHaan( Cobbler 与 Func 作者)

ansible 的名称来自科幻小说《安德的游戏》中跨越时空的即时通信工具,使用它可以在相距数光年的距离,远程实时控制前线的舰队战斗。

2012-03-09,发布0.0.1版,

2015-10-17,Red Hat宣布1.5亿美元收购

[同类型软件对比]

- 1.puppet 学习难,安装ruby环境难,没有远程执行功能
- 2.ansible 轻量级,大规模环境下只通过ssh会很慢,串行的
- 3.saltstack 一般选择salt会使用`C/S`结构的模式,`salt-master``salt-minion`,并行的,大规模批量操作的情况下,会比Ansible速度快一些,底层使用的是`zero-MQ`消协队列

[Ansible特性]

- 模块化:调用特定的模块完成特定任务,支持自定义模块,可使用任何编程语言写模块
- Paramiko(python对ssh的实现),PyYAML,Jinja2(模板语言)三个关键模块
- 基于Python语言实现
- 部署简单,基于python和SSH(默认已安装),agentless,无需代理不依赖PKI(无需ssl)
- 安全,基于OpenSSH
- 幂等性:一个任务执行1遍和执行n遍效果一样,不因重复执行带来意外情况,此特性非绝对
- 支持playbook编排任务,YAML格式,编排任务,支持丰富的数据结构
- 较强大的多层解决方案 role

[Ansible架构]

上一篇

[Ansible安装与入门]

ansible的安装方法有多种,官方文档:https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html

Ansible安装

Ansible安装有多种方式,常用的方式有yum、源码包编译安装等

yum安装

[root@localhost ~]# curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
[root@localhost ~]# yum install ansible -yCopy to clipboardErrorCopied

编译安装

[root@localhost ~]# yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto
[root@localhost ~]# wget https://releases.ansible.com/ansible/ansible-2.9.18.tar.gz
[root@localhost ~]# tar xf ansible-2.9.18.tar.gz
[root@localhost ~]# cd ansible-2.9.18
[root@localhost ~]# python setup.py build
[root@localhost ~]# python setup.py install
[root@localhost ~]# mkdir /etc/ansible
[root@localhost ~]# cp -r examples/* /etc/ansibleCopy to clipboardErrorCopied

[PIP安装]

[root@localhost ~]# yum install python-pip
[root@localhost ~]# pip install --upgrade pip
[root@localhost ~]# pip install ansible --upgradeCopy to clipboardErrorCopied

检验(版本)

[root@localhost ~]# ansible --version
ansible 2.9.18
  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.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Nov 16 2020, 22:23:17) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
Copy to clipboardErrorCopied

[Ansible相关文件]

[配置文件]

  • /etc/ansible/ansible.cfg 主配置文件,配置ansible工作特性
  • /etc/ansible/hosts 主机清单
  • /etc/ansible/roles/ 存放角色的目录

[ansible主配置文件]

Ansible 的配置文件 /etc/ansible/ansible.cfg ,其中大部分的配置内容无需进行修改

[defaults]
#inventory                = /etc/ansible/hosts             # 主机列表配置文件
#library                  = /usr/share/my_modules/         # 库文件存放目录
#remote_tmp               = $HOME/.ansible/tmp             # 临时py命令文件存放在远程主机目录
#local_tmp                = $HOME/.ansible/tmp             # 本机的临时命令执行目录
#forks                    = 5                              # 默认并发数
#sudo_user                = root                           # 默认sudo 用户
#ask_sudo_pass            = True                           # 每次执行ansible命令是否询问ssh密码
#ask_pass                 = True   
#remote_port              = 22
#host_key_checking        = False                          # 检查对应服务器的host_key,建议取消注释
#log_path                 = /var/log/ansible.log           # 日志文件,建议启用
#module_name              = command                        # 默认模块,可以修改为shell模块Copy to clipboardErrorCopied

[inventory 主机清单]

ansible的主要功用在于批量主机操作,为了便捷地使用其中的部分主机,可以在inventory file中将其分组命名,默认的inventory file为 /etc/ansible/hosts,inventory file可以有多个,且也可以通过Dynamic Inventory来动态生成

官方文档:https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html

[主机清单文件格式]

inventory文件遵循INI文件风格,中括号中的字符为组名。可以将同一个主机同时归并到多个不同的组中

此外,当如若目标主机使用了非默认的SSH端口,还可以在主机名称之后使用冒号加端口号来标明,如果主机名称遵循相似的命名模式,还可以使用列表的方式标识各主机。

场景一、基于密码连接
[[email protected] ~]# cat /etc/ansible/hosts
#方式一、主机+端口+密码
[webservers]
172.16.1.7 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass='123456'
172.16.1.8 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass='123456'

#方式二、主机+端口+密码
[webservers]
web[1:2].oldboy.com ansible_ssh_pass='123456'

#方式三、主机+端口+密码
[webservers]
web[1:2].oldboy.com
[webservers:vars]
ansible_ssh_pass='123456'

[test]
192.168.15.8  ansible_connection=local   #指定本地连接,无需ssh配置
#ansible_connection=ssh 需要StrictHostKeyChecking no
192.168.15.7  ansible_connection=ssh   ansible_port=2222  ansible_user=chenyang ansible_password=chenyang  
192.168.15.6  ansible_connection=ssh   ansible_user=root  ansible_password=1


场景二、基于密钥连接,需要先创建公钥和私钥,并下发公钥至被控端
[root@m01 ~]# ssh-keygen
[root@m01 ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]
[root@m01 ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]

-----------------------------------------------------------
[root@m01 ~]# cat hosts 
#方式一、主机+端口+密钥
[webservers]
172.16.1.7
172.16.1.8

[root@m01 ~]# ansible webservers -m ping -i ./hosts 
172.16.1.8 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
172.16.1.7 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

-----------------------------------------------------------
[root@m01 ~]# cat hosts 
#方式二、别名+主机+端口+密钥
[webservers]
web01 ansible_ssh_host=172.16.1.7 ansible_ssh_port=22
web02 ansible_ssh_host=172.16.1.8


[root@m01 ~]# ansible webservers -m ping -i ./hosts 
web02 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
web01 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

场景三、主机组使用方式
#1.定义两个组
[lbservers]
172.16.1.5
172.16.1.6

[webservers]
172.16.1.7
172.16.1.8

#2.servers组包括两个子组[lbservers,webserver]
[servers:children]
lbservers
webserver


#列出当前某个组有多少台主机
[root@m01 ~]# ansible lbservers -m ping -i ./hosts --list-hosts
  hosts (1):
    web01
[root@m01 ~]# ansible webservers -m ping -i ./hosts --list-hosts
  hosts (1):
    web02
[root@m01 ~]# ansible servers -m ping -i ./hosts --list-hosts
  hosts (2):
    web01
    web02
[root@m01 ~]# ansible all -m ping -i ./hosts --list-hosts
  hosts (3):
    web03
    web02
    web01
Copy to clipboardErrorCopied

[Ansible相关工具]

命令 解释
/usr/bin/ansible 主程序,临时命令执行工具
/usr/bin/ansible-doc 查看配置文档,模块功能查看工具,相当于man
/usr/bin/ansible-playbook 定制自动化任务,编排剧本工具,相当于脚本/usr/bin/ansible-pull 远程执行命令的工具
/usr/bin/ansible-vault 文件加密工具
/usr/bin/ansible-console 基于Console界面与用户交互的执行工具
/usr/bin/ansible-galaxy 下载/上传优秀代码或Roles模块的官网平台

利用ansible实现管理的主要方式:

  • Ad-Hoc即利用ansible命令,主要用于临时命令使用场景
    -> Ansible-playbook主要用于长期规划好的,大型项目的场景,需要有前期的规划过程

上一篇

[ansible-doc]

此工具用来显示模块帮助,相当于man

格式:

ansible-doc[options][module...]
-l,--list     # 列出可用模块
-s,--snippet  # 显示指定模块的playbook片段

范例:
#列出所有模块
[root@localhost ~]# ansible-doc -l
#查看指定模块帮助用法
[root@localhost ~]# ansible-doc ping 

[root@localhost ~]# ansible-doc -l | wc -l
3387Copy to clipboardErrorCopied

上一篇

[ansible]

此工具通过ssh协议,实现对远程主机的配置管理、应用部署、任务执行等功能。

建议:使用此工具前,先配置ansible主控端能基于密钥认证的方式联系各个被管理节点

  • 范例:利用sshpass批量实现基于key验证脚本
[root@instance-gvpb80ao ~]# vim /etc/ssh/ssh_config
StrictHostKeyChecking no
[root@instance-gvpb80ao ~]# cat hosts.list 
172.16.0.4
[root@instance-gvpb80ao ~]# vim push_ssh_key.sh 
#!/bin/bash 
#********************************************************************#
# WelCome To Login                                                    #
# Author:chenyang                                                    #
# WX:Alvins0918                                                      #
# Date:2021-05-20                                                    #
# Description:老男孩IT教育Linux学院                                    #
# Copyright©:2021 All rightsreserved                                 #
#********************************************************************#
rpm -q sshpass &> /dev/null || yum -y install sshpass 
[ -f /root/.ssh/id_rsa ] || ssh-keygen -f /root/.ssh/id_rsa -P '' 
export SSHPASS=1
while read IP;do
        sshpass  -e  ssh-copy-id  -o  StrictHostKeyChecking=no $IP 
done<hosts.listCopy to clipboardErrorCopied
  • 范例:实现基于key验证的脚本
[root@instance-gvpb80ao ~]# vim push_ssh_key.sh 
#!/bin/bash 
#********************************************************************#
# WelCome To Login                                                    #
# Author:chenyang                                                    #
# WX:Alvins0918                                                      #
# Date:2021-05-20                                                    #
# Description:老男孩IT教育Linux学院                                    #
# Copyright©:2021 All rightsreserved                                 #
#********************************************************************#
IPLIST="
172.16.0.7
172.16.0.8
172.16.0.9"

rpm -q sshpass &> /dev/null || yum -y install sshpass  
[ -f /root/.ssh/id_rsa ] || ssh-keygen -f /root/.ssh/id_rsa  -P ''
export SSHPASS=1
for IP in $IPLIST;do
   sshpass -e ssh-copy-id -o StrictHostKeyChecking=no $IP
doneCopy to clipboardErrorCopied

[Ansible格式]

ansible <host-pattern> [-m module_name] [-a args]
选项说明:
--version #显示版本
-m module   #指定模块,默认为command
-v #详细过程 –vv -vvv更详细
--list-hosts #显示主机列表,可简写 --list
-C, --check   #检查,并不执行
-T, --timeout=TIMEOUT #执行命令的超时时间,默认10s
-k, --ask-pass     #提示输入ssh连接密码,默认Key验证
-u, --user=REMOTE_USER #执行远程执行的用户
-b, --become    #代替旧版的sudo 切换
--become-user=USERNAME  #指定sudo的runas用户,默认为root
-K, --ask-become-pass  #提示输入sudo时的口令Copy to clipboardErrorCopied

[ansible的Host-pattern]

用于匹配被控制的主机的列表。

  • 范例:
[root@instance-gvpb80ao ~]# cat /etc/ansible/hosts
172.16.0.4
[root@instance-gvpb80ao ~]# ansible all -m ping
172.16.0.4 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}Copy to clipboardErrorCopied

[通配符]

[root@instance-gvpb80ao ~]# cat /etc/ansible/hosts
[私网]
172.16.0.4
[公网]
106.13.81.75

# 第一种方式
[root@instance-gvpb80ao ~]# ansible "*" -m ping 
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
172.16.0.4 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
106.13.81.75 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

# 第二种方式
[root@instance-gvpb80ao ~]# ansible "私网" -m ping
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
172.16.0.4 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

# 第三种方式
[root@instance-gvpb80ao ~]# ansible '172*' -m ping
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
172.16.0.4 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

# 第四种方式
[root@instance-gvpb80ao ~]# ansible '172.16.0.4 106.13.81.75' -m ping
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
172.16.0.4 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
106.13.81.75 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}Copy to clipboardErrorCopied

[或关系]

# 在公网组里面或者在私网组里面
[root@instance-gvpb80ao ~]# ansible '公网:私网' -m ping
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
172.16.0.4 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
106.13.81.75 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}Copy to clipboardErrorCopied

[逻辑与]

# 在公网组并且在私网组
[root@instance-gvpb80ao ~]# cat /etc/ansible/hosts
[私网]
172.16.0.4
106.13.81.75
[公网]
106.13.81.75
[root@instance-gvpb80ao ~]# ansible '公网:&私网' -m ping
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
106.13.81.75 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}Copy to clipboardErrorCopied

[逻辑非]

# 在公网组不在私网组
[root@instance-gvpb80ao ~]# cat /etc/ansible/hosts
[私网]
172.16.0.4
[公网]
106.13.81.75
[root@instance-gvpb80ao ~]# ansible '公网:!私网' -m ping
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
106.13.81.75 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}Copy to clipboardErrorCopied

[正则表达式]

[root@instance-gvpb80ao ~]# cat /etc/ansible/hosts
[private]
172.16.0.4
[public]
106.13.81.75

# 以pu开头
[root@instance-gvpb80ao ~]# ansible '~pu' -m ping
106.13.81.75 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}Copy to clipboardErrorCopied

[显示具体的IP]

[root@instance-gvpb80ao ~]# ansible private --list-hosts
  hosts (1):
    172.16.0.4Copy to clipboardErrorCopied

[ansible命令执行过程]

1. 加载自己的配置文件,默认/etc/ansible/ansible.cfg
2. 加载自己对应的模块文件,如:ping。通过ansible将模块或命令生成对应的临时py文件,并将该文件传输至远程服务器的对应执行用户$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY文件
3. 给文件+x执行
4. 执行并返回结果
5. 删除临时py文件,退出

[ansible的执行状态]

[root@instance-gvpb80ao tmp]# grep -A 14 '\[colors\]' /etc/ansible/ansible.cfg
[colors]
#highlight = white
#verbose = blue
#warn = bright purple
#error = red
#debug = dark gray
#deprecate = purple
#skip = cyan
#unreachable = red
#ok = green
#changed = yellow
#diff_add = green
#diff_remove = red
#diff_lines = cyanCopy to clipboardErrorCopied
  • 绿色:执行成功并且不需要做改变的操作
  • 黄色:执行成功并且对目标主机做变更
  • 红色:执行失败

[ansible使用范例]

#以shanhe用户执行ping存活检测
[root@instance-gvpb80ao tmp]# ansible all -m ping -u shanhe -k
SSH password: 
106.13.81.75 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
172.16.0.4 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
#以wang sudo至root执行ping存活检测
[root@instance-gvpb80ao tmp]# ansible all -m ping -u shanhe -k -b
SSH password: 
106.13.81.75 | UNREACHABLE! => {
    "changed": false, 
    "msg": "Invalid/incorrect password: Permission denied, please try again.", 
    "unreachable": true
}
172.16.0.4 | UNREACHABLE! => {
    "changed": false, 
    "msg": "Invalid/incorrect password: Permission denied, please try again.", 
    "unreachable": true
}
#以shanhe sudo至chenyang用户执行ping存活检测
[root@instance-gvpb80ao tmp]# ansible all -m ping -u shanhe -k -b --become-user=chenyang
SSH password: 
172.16.0.4 | FAILED! => {
    "msg": "Missing sudo password"
}
106.13.81.75 | FAILED! => {
    "msg": "Missing sudo password"
}
#以shanhe sudo至root用户执行ls 
[root@instance-gvpb80ao ~]# ansible all -m command -u shanhe -a 'ls /root' -b --become-user=root -k -K
SSH password: # root密码
BECOME password[defaults to SSH password]: # shanhe密码
172.16.0.4 | CHANGED | rc=0 >>
hosts.list
open-user-crt.sh
push_ssh_key.sh
106.13.81.75 | CHANGED | rc=0 >>
hosts.list
open-user-crt.sh
push_ssh_key.shCopy to clipboardErrorCopied

上一篇

[Ansible-playbook]

此工具用于执行编写好的 playbook 任务

[root@instance-gvpb80ao ~]# cat hello.yaml 
- hosts: public
  remote_user: root
  gather_facts: no
  tasks:
    - name: hello world
      command: echo "Hello Chenyang" > /root/123456
[root@instance-gvpb80ao ~]# ansible-playbook hello.yaml 

PLAY [public] ***********************************************************************************************

TASK [hello world] ******************************************************************************************
changed: [106.13.81.75]

PLAY RECAP **************************************************************************************************
106.13.81.75               : ok=1    changed=1    unreachable=0    failed=0    s

[ansible-vault]

此工具可以用于加密解密yml文件。

格式

ansible-vault [create|decrypt|edit|encrypt|rekey|view]Copy to clipboardErrorCopied

范例

ansible-vault encrypt hello.yml #加密

[root@instance-gvpb80ao ~]# ansible-vault encrypt hello.yaml 
New Vault password: 
Confirm New Vault password: 
Encryption successful
[root@instance-gvpb80ao ~]# cat hello.yaml 
$ANSIBLE_VAULT;1.1;AES256
32613137393965313332353065366264303763323230323766366261636430376661373038626432
3732623762313131316565386338633635613530653736640a363462373930396562343565653936
34333035633365343063303966386264343366383839333439643961383438316537616666353931
3234323937363565660a303931313032346134393534653662363266613563386633613537313664
37313434333764656637623761346662656238393631323230326366396364613138623430663063
34396532646266336136333566313164656232366336653932396634643565366266666464623631
65366163343764613166336430613564306633333331343166343236323834343631613438333865
30346430363465356562643932653766636230383137346332323064636236616532333432353432
62373435386162613961376134643237366461653734626664353737363432323761366263336461
36323537633837316664306439303534343536373162333537646462303864323233303436643839
336130356436613230633231623035633536

ansible-vault decrypt hello.yml #解密

[root@instance-gvpb80ao ~]# ansible-vault decrypt hello.yaml 
Vault password: 
Decryption successful
[root@instance-gvpb80ao ~]# cat hello.yaml 
- hosts: public
  remote_user: root
  gather_facts: no
  tasks:
    - name: hello world
      command: echo "Hello Chenyang" > /root/123456

ansible-vault view hello.yml #查看

[root@instance-gvpb80ao ~]# ansible-vault view hello.yaml
Vault password: 
- hosts: public
  remote_user: root
  gather_facts: no
  tasks:
    - name: hello world
      command: echo "Hello Chenyang" > /root/123456
      
ansible-vault edit hello.yml #编辑加密文件

[root@instance-gvpb80ao ~]# ansible-vault edit hello.yaml
Vault password: 
[root@instance-gvpb80ao ~]# cat hello.yaml 
$ANSIBLE_VAULT;1.1;AES256
32623539636538376665373330626334643538306161613462393334656633613030663634396334
6266386165643361323137343161313536643038393661650a623861366330343135623365623336
37323064623562316162613034636232333535366637613461396434363938643532616133643836
3766343533616637650a313737316262366233396433353030393262633366333939636537316165
65623861643233353939653430623334323138366435326234353638666635373132616162666332
36643834313263393237323232323537633933313430323530343032313637643332653862326465
66333438303737663463386363383034343135643431316634363737376265336366363764656437
66666333316466313161333061383930376562366631643962386462353535363535333461353035
62376463663630383465666662616139636631626334373564346131363531636439386431623666
3933393266353638346232366666313137653962356130373739

ansible-vault rekey hello.yml #修改口令

[root@instance-gvpb80ao ~]# ansible-vault rekey hello.yaml
Vault password: 
New Vault password: 
Confirm New Vault password: 
Rekey successful

ansible-vault create new.yml #创建新文件

[root@instance-gvpb80ao ~]# ansible-vault create abc.yaml
New Vault password: 
Confirm New Vault password: 
[root@instance-gvpb80ao ~]# cat abc.yaml 
$ANSIBLE_VAULT;1.1;AES256
32653230653437313566623734666166346632613366373732346533396130396132323433653238
6139333135386637303939306437306637303837663361650a653466663938313032613330653636
66346639613937333939393036336334396234616139633066386330343831333439643039353436
6134313033616235390a353362643562633763303063313264633435306635643965356636303964
6430Copy to clipboardErrorCopied

[ansible-console]

此工具可交互执行命令,支持tab,ansible 2.0+新增

提示符格式

执行用户@当前操作的主机组 (当前组的主机数量)[f:并发数]$Copy to clipboardErrorCopied

常用子命令

  • 设置并发数: forks n 例如: forks 10
  • 切换组: cd 主机组 例如: cd web
  • 列出当前组主机列表: list
  • 列出所有的内置命令: ?或help

范例:

[root@instance-gvpb80ao ~]# ansible-console
Welcome to the ansible console.
Type help or ? to list commands.

root@all (2)[f:5]$ ping
172.16.0.4 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
106.13.81.75 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
root@all (2)[f:5]$ list
106.13.81.75
172.16.0.4Copy to clipboardErrorCopied

上一篇

[ansible-galaxy]

此工具会连接 https://galaxy.ansible.com 下载相应的roles

# 查看列表
[root@instance-gvpb80ao ~]# ansible-galaxy list
# /root/.ansible/roles
- geerlingguy.nginx, 3.0.0
# /usr/share/ansible/roles
# /etc/ansible/roles

# 下载nginx roles
[root@instance-gvpb80ao ~]# ansible-galaxy install geerlingguy.nginx
- downloading role 'nginx', owned by geerlingguy
- downloading role from https://github.com/geerlingguy/ansible-role-nginx/archive/3.0.0.tar.gz
- extracting geerlingguy.nginx to /root/.ansible/roles/geerlingguy.nginx
- geerlingguy.nginx (3.0.0) was installed successfully

# 删除
[root@instance-gvpb80ao ~]# ansible-galaxy remove geerlingguy.nginx
- successfully removed geerlingguy.nginxCopy to clipboardErrorCopied

[Ansible模块(一)]

2015年底270多个模块,2016年达到540个,2018年01月12日有1378个模块,2018年07月15日1852个模块,2019年05月25日(ansible 2.7.10)时2080个模块,2020年03月02日有3387个模块。虽然模块众多,但最常用的模块也就2,30个而已,针对特定业务只用10几个模块。

常用模块帮助文档参考:

https://docs.ansible.com/ansible/2.9/modules/modules_by_category.html

https://docs.ansible.com/ansible/2.9/modules/list_of_all_modules.html

https://docs.ansible.com/ansible/latest/modules/list_of_all_modules.html

https://docs.ansible.com/ansible/latest/modules/modules_by_category.html

[Command 模块]

Ansible中的默认模块,

功能:在远程主机执行命令,此为默认模块,可忽略-m选项

注意:此命令不支持 $VARNAME < > | ; & 等,用shell模块实现

[root@instance-gvpb80ao ~]# ansible all -a 'hostname'
106.13.81.75 | CHANGED | rc=0 >>
instance-gvpb80ao.novalocal
172.16.0.4 | CHANGED | rc=0 >>
instance-gvpb80ao.novalocal

[root@instance-gvpb80ao ~]# ansible public -m command -a 'ls /root'
106.13.81.75 | CHANGED | rc=0 >>
abc.yaml
hello.yaml
hosts.list
open-user-crt.sh
push_ssh_key.sh
Copy to clipboardErrorCopied

[Shell模块]

功能:和command相似,用shell执行命令,支持各种符号,比如:*,$, >

范例:

[root@instance-gvpb80ao ~]# ansible all -m shell -a "echo $HOSTNAME"
106.13.81.75 | CHANGED | rc=0 >>
instance-gvpb80ao.novalocal
172.16.0.4 | CHANGED | rc=0 >>
instance-gvpb80ao.novalocalCopy to clipboardErrorCopied
注意:调用bash执行命令 类似 cat /tmp/test.md | awk -F'|' '{print $1,$2}' &> /tmp/example.txt 这些复杂命令,即使使用shell也可能会失败。

解决办法:写到脚本时,copy到远程,执行,再把需要的结果拉回执行命令的机器。

将shell模块代替command,设为默认模块
[root@instance-gvpb80ao ~]# vim /etc/ansible/ansible.cfg
module_name = shellCopy to clipboardErrorCopied

[Script 模块]

功能:在远程主机上运行ansible服务器上的脚本(无需执行权限)

# /root/test.sh 脚本必须放在ansible执行机器上面
[root@instance-gvpb80ao ~]# ansible public -m script -a /root/test.sh 
106.13.81.75 | CHANGED => {
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to 106.13.81.75 closed.\r\n", 
    "stderr_lines": [
        "Shared connection to 106.13.81.75 closed."
    ], 
    "stdout": "", 
    "stdout_lines": []
}
[root@instance-gvpb80ao ~]# cat date.txt 
Wed May 19 16:05:10 CST 2021Copy to clipboardErrorCopied

[Copy模块]

功能:从ansible服务器主控端复制文件到远程主机

  • 参数
参数 解释
src 用于指定需要copy的文件或目录。
dest 用于指定文件将被拷贝到远程主机的哪个目录中,dest为必须参数。
content 当不使用src指定拷贝的文件时,可以使用content直接指定文件内容,src与content两个参数必有其一,否则会报错。
force 当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,是否强制覆盖,可选值有yes和no,默认值为yes,表示覆盖,如果设置为no,则不会执行覆盖拷贝操作,远程主机中的文件保持不变。
backup 当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,是否对远程主机的文件进行备份,可选值有yes和no,当设置为yes时,会先备份远程主机中的文件,然后再将ansible主机中的文件拷贝到远程主机。
owner 指定文件拷贝到远程主机后的属主,但是远程主机上必须有对应的用户,否则会报错。
group 指定文件拷贝到远程主机后的属组,但是远程主机上必须有对应的组,否则会报错。
mode 指定文件拷贝到远程主机后的权限,如果你想将权限设置为”rw-r–r--“,则可以使用mode=0644表示,如果你想要在user对应的权限位上添加执行权限,则可以使用mode=u+x表示。
  • 范例1:将本机的push_ssh_key.sh复制到远程的/tmp目录,用户为shanhe,权限为600
[root@instance-gvpb80ao ~]# ansible public -m copy -a "src=push_ssh_key.sh dest=/tmp owner=shanhe mode=600"
106.13.81.75 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "0b836bbe30e61896040525bee00ffee867f4a08c", 
    "dest": "/tmp/push_ssh_key.sh", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "410a687367c54811ff9ce34791319e0c", 
    "mode": "0600", 
    "owner": "shanhe", 
    "size": 264, 
    "src": "/root/.ansible/tmp/ansible-tmp-1621494824.72-317-250283194147221/source", 
    "state": "file", 
    "uid": 1001
}
[root@instance-gvpb80ao ~]# ll /tmp/push_ssh_key.sh 
-rw------- 1 shanhe root 264 May 20 15:13 /tmp/push_ssh_key.shCopy to clipboardErrorCopied
  • 范例2:将本机test.sh复制到远程,并备份。
[root@instance-gvpb80ao ~]# ansible 172* -m copy -a "src=test.sh dest=/tmp/push_ssh_key.sh backup=yes"
172.16.0.4 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "backup_file": "/tmp/push_ssh_key.sh.2054.2021-05-20@15:18:31~", 
    "changed": true, 
    "checksum": "488c35d2c33b1e4cef55ff0d85cab928e68f3330", 
    "dest": "/tmp/push_ssh_key.sh", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "1adcefd1e3aea3dbd54f0da29e586732", 
    "mode": "0600", 
    "owner": "shanhe", 
    "size": 43, 
    "src": "/root/.ansible/tmp/ansible-tmp-1621495109.9-1879-108678135537148/source", 
    "state": "file", 
    "uid": 1001
}
[root@instance-gvpb80ao ~]# ll /tmp/
total 2844
-rw------- 1 shanhe  root         43 May 20 15:18 push_ssh_key.sh
-rw------- 1 shanhe  root        264 May 20 15:13 push_ssh_key.sh.2054.2021-05-20@15:18:31~Copy to clipboardErrorCopied

[Fetch 模块]

功能:从远程主机提取文件至ansible的主控端,copy相反,目前不支持目录

  • 参数
参数 解释
src (必需)要获取的远程系统上的文件。
dest (必需)要将文件保存到的目录。
fail_on_missing 当设置为 Trueyes,如果由于不明因素导致从远程主机中不能读取到该文件,则会显示 fail
validate_checksum 当文件fetch之后进行md5检查
Flat 允许覆盖默认行为从hostname/path到/file的,如果dest以/结尾,它将使用源文件的基础名称
  • 范例1
[root@instance-gvpb80ao ~]# ansible public -m fetch -a "src=/tmp/push_ssh_key.sh dest=shanhe.sh "
106.13.81.75 | CHANGED => {
    "changed": true, 
    "checksum": "488c35d2c33b1e4cef55ff0d85cab928e68f3330", 
    "dest": "/root/shanhe.sh/106.13.81.75/tmp/push_ssh_key.sh", 
    "md5sum": "1adcefd1e3aea3dbd54f0da29e586732", 
    "remote_checksum": "488c35d2c33b1e4cef55ff0d85cab928e68f3330", 
    "remote_md5sum": null
}
[root@instance-gvpb80ao ~]# tree shanhe.sh
/root/shanhe.sh/
└── 106.13.81.75
    └── tmp
        └── push_ssh_key.sh

2 directories, 1 fileCopy to clipboardErrorCopied
  • 范例2
[root@instance-gvpb80ao /]# ansible public -m fetch -a "src=/tmp/push_ssh_key.sh dest=/opt validate_checksum=yes"
106.13.81.75 | CHANGED => {
    "changed": true, 
    "checksum": "488c35d2c33b1e4cef55ff0d85cab928e68f3330", 
    "dest": "/opt/106.13.81.75/tmp/push_ssh_key.sh", 
    "md5sum": "1adcefd1e3aea3dbd54f0da29e586732", 
    "remote_checksum": "488c35d2c33b1e4cef55ff0d85cab928e68f3330", 
    "remote_md5sum": null
}Copy to clipboardErrorCopied

[File模块]

功能:设置文件属性,创建软链接等。

  • 参数
参数 解释
path 必须参数,用于指定要操作的文件或目录,在之前版本的ansible中,使用dest参数或者name参数指定要操作的文件或目录,为了兼容之前的版本,使用dest或name也可以。
recurse 当要操作的文件为目录,将recurse设置为yes,可以递归的修改目录中文件的属性。
state 此参数非常灵活,其对应的值需要根据情况设定。 directory:在远端创建目录 touch:在远端创建文件 link:创建链接文件 absent:表示删除文件或目录 mode:设置文件或目录权限 owner:设置文件或目录属主 group:设置文件或目录属组
src 当state设置为link或者hard时,表示我们想要创建一个软链或者硬链,所以,我们必须指明软链或硬链链接的哪个文件,通过src参数即可指定链接源。
force 当state=link的时候,可配合此参数强制创建链接文件,当force=yes时,表示强制创建链接文件。不过强制创建链接文件分为三种情况。情况一:当要创建的链接文件指向的源文件并不存在时,使用此参数,可以先强制创建出链接文件。情况二:当要创建链接文件的目录中已经存在与链接文件同名的文件时,将force设置为yes,会将同名文件覆盖为链接文件,相当于删除同名文件,创建链接文件。情况三:当要创建链接文件的目录中已经存在与链接文件同名的文件,并且链接文件指向的源文件也不存在,这时会强制替换同名文件为链接文件。
owner 用于指定被操作文件的属主,属主对应的用户必须在远程主机中存在,否则会报错。
group 用于指定被操作文件的属组,属组对应的组必须在远程主机中存在,否则会报错。
mode 用于指定被操作文件的权限,比如,如果想要将文件权限设置为”rw-r-x---“,则可以使用mode=650进行设置,或者使用mode=0650,效果也是相同的。如果想要设置特殊权限,比如为二进制文件设置suid,则可以使用mode=4700。
  • 范例1
[root@instance-gvpb80ao opt]# ansible public -m file -a "path=/root/1.txt state=touch"
106.13.81.75 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/root/1.txt", 
    "gid": 0, 
    "group": "root", 
    "mode": "0644", 
    "owner": "root", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}
[root@instance-gvpb80ao opt]# ll /root/
total 28
-rw-r--r-- 1 root root   0 May 20 15:55 1.txt

# 删除文件
ansible public -m file -a "path=/root/1.txt state=absent"Copy to clipboardErrorCopied
  • 范例2
[root@instance-gvpb80ao ~]# ansible public -m file -a "path=/root/txt state=directory owner=shanhe group=chenyang"
106.13.81.75 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "gid": 1002, 
    "group": "chenyang", 
    "mode": "0755", 
    "owner": "shanhe", 
    "path": "/root/txt", 
    "size": 4096, 
    "state": "directory", 
    "uid": 1001
}
[root@instance-gvpb80ao ~]# ll
total 36
drwxr-xr-x 2 shanhe chenyang 4096 May 20 16:08 txtCopy to clipboardErrorCopied
  • 范例3
[root@instance-gvpb80ao ~]# ansible public -m file -a "path=/root/test src=/root/txt  state=link owner=shanhe group=chenyang"
106.13.81.75 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/root/test", 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "size": 9, 
    "src": "/root/txt", 
    "state": "link", 
    "uid": 0
}
[root@instance-gvpb80ao ~]# ll
total 36
lrwxrwxrwx 1 root   root        9 May 20 16:11 test -> /root/txtCopy to clipboardErrorCopied

[unarchive模块]

功能:解压缩。

实现有两种用法:

1、将ansible主机上的压缩包传到远程主机后解压缩至特定目录,设置copy=yes

2、将远程主机上的某个压缩包解压缩到指定路径下,设置copy=no

  • 参数
参数 解释
copy 默认为yes,当copy=yes,拷贝的文件是从ansible主机复制到远程主机上,如果设置为
remote_src 和copy功能一样且互斥,yes表示在远程主机,不在ansible主机,no表示文件在ansible主机上
src 源路径,可以是ansible主机上的路径,也可以是远程主机(被管理端或者第三方主机)上的路径,如果是远程主机上的路径,则需要设copy=no
dest 远程主机上的目标路径
mode 设置解压缩后的文件权限
  • 范例
[root@instance-gvpb80ao ~]# ansible all -m unarchive -a "src=/root/test.tar.gz dest=/opt "
172.16.0.4 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/opt", 
    "extract_results": {
        "cmd": [
            "/usr/bin/gtar", 
            "--extract", 
            "-C", 
            "/opt", 
            "-z", 
            "-f", 
            "/root/.ansible/tmp/ansible-tmp-1621499907.17-5491-141851802518117/source"
        ], 
        "err": "", 
        "out": "", 
        "rc": 0
    }, 
    "gid": 0, 
    "group": "root", 
    "handler": "TgzArchive", 
    "mode": "0755", 
    "owner": "root", 
    "size": 4096, 
    "src": "/root/.ansible/tmp/ansible-tmp-1621499907.17-5491-141851802518117/source", 
    "state": "directory", 
    "uid": 0
}
106.13.81.75 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "dest": "/opt", 
    "gid": 0, 
    "group": "root", 
    "handler": "TgzArchive", 
    "mode": "0755", 
    "owner": "root", 
    "size": 4096, 
    "src": "/root/.ansible/tmp/ansible-tmp-1621499906.94-5490-71573166890415/source", 
    "state": "directory", 
    "uid": 0
}
[root@instance-gvpb80ao ~]# ll /opt/
total 1448
-rw-------   1 root  root      808 May 19 15:09 hello.yamlCopy to clipboardErrorCopied
  • 范例2
[root@instance-gvpb80ao ~]# ansible public -m unarchive -a "src=https://repo.huaweicloud.com/etcd/v3.2.24/etcd-v3.2.24-linux-arm64.tar.gz dest=/opt copy=no owner=shanhe group=chenyang"
106.13.81.75 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/opt", 
    "extract_results": {
        "cmd": [
            "/usr/bin/gtar", 
            "--extract", 
            "-C", 
            "/opt", 
            "-z", 
            "--owner=shanhe", 
            "--group=chenyang", 
            "-f", 
            "/root/.ansible/tmp/ansible-tmp-1621500444.96-6522-191985417198936/etcd-v3.2.24-linux-arm64.tarsHzxWS.gz"
        ], 
        "err": "", 
        "out": "", 
        "rc": 0
    }, 
    "gid": 0, 
    "group": "root", 
    "handler": "TgzArchive", 
    "mode": "0755", 
    "owner": "root", 
    "size": 4096, 
    "src": "/root/.ansible/tmp/ansible-tmp-1621500444.96-6522-191985417198936/etcd-v3.2.24-linux-arm64.tarsHzxWS.gz", 
    "state": "directory", 
    "uid": 0
}
[root@instance-gvpb80ao ~]# ll /opt/
total 1452
drwxr-xr-x   3 shanhe chenyang    4096 Jul 25  2018 etcd-v3.2.24-linux-arm64Copy to clipboardErrorCopied

[Archive模块]

功能:打包压缩保存在被管理节点。

  • 参数
参数 解释
path 要压缩的文件或目录
dest 压缩后的文件
format 指定打包的类型
mode 权限
group 属组
owner 属主
  • 范例
[root@instance-gvpb80ao ~]# ansible public -m archive -a "path=/root dest=/opt/root.tar.gz format=gz"
106.13.81.75 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "archived": [
        "/root/.tcshrc", 
        "/root/.cshrc", 
        "/root/.bash_history", 
        "/root/.bash_profile", 
        "/root/.mysql_history", 
        "/root/.viminfo", 
        "/root/hello.yaml", 
        "/root/test.tar.gz", 
        "/root/abc.yaml", 
        "/root/.ansible-console_history", 
        "/root/hosts.list", 
        "/root/open-user-crt.sh", 
        "/root/date.txt", 
        "/root/push_ssh_key.sh", 
        "/root/.bash_logout", 
        "/root/test.sh", 
        "/root/.rnd", 
        "/root/.bashrc", 
        "/root/.ansible/galaxy_token", 
        "/root/.ansible/tmp/ansible-local-7657zoXLcU/ansiballz_cache/archive-ZIP_DEFLATED", 
        "/root/.ansible/tmp/ansible-tmp-1621502833.44-7666-63618490609724/AnsiballZ_archive.py", 
        "/root/.ansible/cp/4e1832b56d", 
        "/root/.cache/abrt/lastnotification", 
        "/root/.ssh/authorized_keys", 
        "/root/.ssh/id_rsa", 
        "/root/.ssh/id_rsa.pub", 
        "/root/.ssh/known_hosts"
    ], 
    "arcroot": "//", 
    "changed": true, 
    "dest": "/opt/root.tar.gz", 
    "expanded_exclude_paths": [], 
    "expanded_paths": [
        "/root"
    ], 
    "gid": 0, 
    "group": "root", 
    "missing": [], 
    "mode": "0644", 
    "owner": "root", 
    "size": 188991, 
    "state": "file", 
    "uid": 0
}
[root@instance-gvpb80ao ~]# ll /opt/
total 1640
-rw-r--r--   1 root   root      188991 May 20 17:27 root.tar.gz
[root@instance-gvpb80ao ~]# Copy to clipboardErrorCopied

[Hostname模块]

功能:管理主机名。

  • 参数
参数 解释
name 主机名
  • 范例
[root@instance-gvpb80ao ~]# ansible public -m hostname -a 'name=kubernetes'
106.13.81.75 | CHANGED => {
    "ansible_facts": {
        "ansible_domain": "", 
        "ansible_fqdn": "kubernetes", 
        "ansible_hostname": "kubernetes", 
        "ansible_nodename": "kubernetes", 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "kubernetes"
}
[root@instance-gvpb80ao ~]# bash
[root@kubernetes ~]# Copy to clipboardErrorCopied

上一篇

[Ansible模块(二)]

Ansible常用模块二。

[Cron模块]

功能:计划任务

支持时间:minute,hour,day,month,weekday

  • 参数
参数 解释
minute 分钟
hour 小时
day
month
weekday 星期
job 脚本路径
name 定时任务名称
disabled 是否启用
state 状态:absent删除
  • 范例1
[root@instance-gvpb80ao ~]# ansible public -m cron -a "minute=* job='echo date >> /root/ttt.log' name=test  disabled=yes"
106.13.81.75 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": [
        "test"
    ]
}
[root@instance-gvpb80ao ~]# crontab -l
#Ansible: test
#* * * * * echo date >> /root/ttt.logCopy to clipboardErrorCopied
  • 范例2
[root@instance-gvpb80ao ~]# ansible public -m cron -a "minute=* job='echo date >> /root/ttt.log' name=test  disabled=yes state=absent"
106.13.81.75 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": []
}
[root@instance-gvpb80ao ~]# crontab -lCopy to clipboardErrorCopied

[Yum和Apt模块]

yum 管理软件包,只支持RHEL,CentOS,fedora,不支持Ubuntu其它版本。

apt 模块管理 Debian 相关版本的软件包。

  • 参数
参数 解释
name 安装的服务的名字
state 执行命令 present installed removed latest absent 其中installed and present等效 latest标志安装yum中最新版本,absent and removed 等效 表示删除安装包
disable_gpg_check 用于禁用rmp包的公钥gpg验证,默认值no 表示不做验证
enablerepo 用于指定安装软件包是临时启用的yum元
disablerepo 用于指定安装软件包是临时禁止用的yum元
  • 范例1
[root@instance-gvpb80ao ~]# ansible public -m yum -a "name=httpd state=present"
106.13.81.75 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "changes": {
        "installed": [
            "httpd"
        ]
    }, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "Loaded plugins: langpacks, versionlock\nExcluding 1 update due to versionlock (use \"yum versionlock status\" to show it)\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.4.6-97.el7.centos will be installed\n--> Processing Dependency: httpd-tools = 2.4.6-97.el7.centos for package: httpd-2.4.6-97.el7.centos.x86_64\n--> Processing Dependency: /etc/mime.types for package: httpd-2.4.6-97.el7.centos.x86_64\n--> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd-2.4.6-97.el7.centos.x86_64\n--> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd-2.4.6-97.el7.centos.x86_64\n--> Running transaction check\n---> Package apr.x86_64 0:1.4.8-7.el7 will be installed\n---> Package apr-util.x86_64 0:1.5.2-6.el7 will be installed\n---> Package httpd-tools.x86_64 0:2.4.6-97.el7.centos will be installed\n---> Package mailcap.noarch 0:2.1.41-2.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package           Arch         Version                     Repository     Size\n================================================================================\nInstalling:\n httpd             x86_64       2.4.6-97.el7.centos         updates       2.7 M\nInstalling for dependencies:\n apr               x86_64       1.4.8-7.el7                 base          104 k\n apr-util          x86_64       1.5.2-6.el7                 base           92 k\n httpd-tools       x86_64       2.4.6-97.el7.centos         updates        93 k\n mailcap           noarch       2.1.41-2.el7                base           31 k\n\nTransaction Summary\n================================================================================\nInstall  1 Package (+4 Dependent packages)\n\nTotal download size: 3.0 M\nInstalled size: 10 M\nDownloading packages:\n--------------------------------------------------------------------------------\nTotal                                               14 MB/s | 3.0 MB  00:00     \nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : apr-1.4.8-7.el7.x86_64                                       1/5 \n  Installing : apr-util-1.5.2-6.el7.x86_64                                  2/5 \n  Installing : httpd-tools-2.4.6-97.el7.centos.x86_64                       3/5 \n  Installing : mailcap-2.1.41-2.el7.noarch                                  4/5 \n  Installing : httpd-2.4.6-97.el7.centos.x86_64                             5/5 \n  Verifying  : httpd-2.4.6-97.el7.centos.x86_64                             1/5 \n  Verifying  : apr-1.4.8-7.el7.x86_64                                       2/5 \n  Verifying  : mailcap-2.1.41-2.el7.noarch                                  3/5 \n  Verifying  : httpd-tools-2.4.6-97.el7.centos.x86_64                       4/5 \n  Verifying  : apr-util-1.5.2-6.el7.x86_64                                  5/5 \n\nInstalled:\n  httpd.x86_64 0:2.4.6-97.el7.centos                                            \n\nDependency Installed:\n  apr.x86_64 0:1.4.8-7.el7                     apr-util.x86_64 0:1.5.2-6.el7    \n  httpd-tools.x86_64 0:2.4.6-97.el7.centos     mailcap.noarch 0:2.1.41-2.el7    \n\nComplete!\n"
    ]
}
[root@instance-gvpb80ao ~]# systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
   Active: inactive (dead)
     Docs: man:httpd(8)
           man:apachectl(8)
[root@instance-gvpb80ao ~]# Copy to clipboardErrorCopied

[Service模块]

功能:管理服务。

  • 参数
参数 解释
name 定义要启动服务的名称
state started #启动服务 stopped #停止服务 restarted #重启服务 reloaded #重载服务
enabled 开机自启
  • 范例
#1.启动crond服务,并加入开机自启
[root@m01 ~]# ansible webservers -m service -a "name=crond state=started enabled=yes"
#2.停止crond服务,并删除开机自启
[root@m01 ~]# ansible webservers -m service -a "name=crond state=stopped enabled=no"
#3.重启crond服务
[root@m01 ~]# ansible webservers -m service -a "name=crond state=restarted"
#4.重载crond服务
[root@m01 ~]# ansible webservers -m service -a "name=crond state=reloaded"Copy to clipboardErrorCopied

[User模块]

功能:管理用户。

  • 参数
参数 解释
uid 指定用户的uid
group 指定用户组名称
groups 指定附加组名称
password 给用户添加密码(记得单引号)
shell 指定用户登录shell
create_home 是否创建家目录
state 用户状态:absent(删除)
home 家目录路径
system 是否是系统用户
remove 是否删除家目录数据:yes(删除)
  • 范例
[root@instance-gvpb80ao ~]# ansible public -m user -a "name=www uid=1200"
106.13.81.75 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "comment": "", 
    "create_home": true, 
    "group": 1200, 
    "home": "/home/www", 
    "name": "www", 
    "shell": "/bin/bash", 
    "state": "present", 
    "system": false, 
    "uid": 1200
}
[root@instance-gvpb80ao ~]# id www
uid=1200(www) gid=1200(www) groups=1200(www)Copy to clipboardErrorCopied

[Group模块]

功能:管理组。

#创建组
ansible public -m group  -a 'name=nginx gid=88 system=yes'
#删除组
ansible public -m group  -a 'name=nginx state=absent'Copy to clipboardErrorCopied

[get_url模块]

功能:下载模块(类似于wget)。

  • 参数
参数 解释
url 下载的URL
mode 权限
dest 下载的路径
checksum md5值
timeout 下载文件的超时时间
url_password URL密码
url_username URL用户
  • 范例
[root@instance-gvpb80ao ~]# ansible public -m get_url -a 'url=https://repo.huaweicloud.com/etcd/v3.4.0-rc.4/etcd-v3.4.0-rc.4-linux-arm64.tar.gz mode=777 dest=/opt'
106.13.81.75 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum_dest": null, 
    "checksum_src": "c721f9904ff9c47cb34f304ee7d48eb99253e13a", 
    "dest": "/opt/etcd-v3.4.0-rc.4-linux-arm64.tar.gz", 
    "elapsed": 6, 
    "gid": 0, 
    "group": "root", 
    "md5sum": "0372460bbdf457166391e5e71c074f1c", 
    "mode": "0777", 
    "msg": "OK (15997556 bytes)", 
    "owner": "root", 
    "size": 15997556, 
    "src": "/root/.ansible/tmp/ansible-tmp-1621516877.39-15455-75914400512400/tmpbxzrIQ", 
    "state": "file", 
    "status_code": 200, 
    "uid": 0, 
    "url": "https://repo.huaweicloud.com/etcd/v3.4.0-rc.4/etcd-v3.4.0-rc.4-linux-arm64.tar.gz"
}Copy to clipboardErrorCopied

[mount模块]

功能:挂载目录。

  • 参数
参数 解释
src 挂载IP及目录
path 挂载的路径
fstype 挂载的类型
opts
state 挂载的状态
  • state参数
参数 解释
present 开机挂载,仅将挂载配置写入/etc/fstab
mounted 挂载设备,并将配置写入/etc/fstab
unmounted 卸载设备,不会清除/etc/fstab写入的配置
absent 卸载设备,会清理/etc/fstab写入的配置
  • 范例
[root@m01 ~]# ansible web02 -m mount -a "src=172.16.1.7:/data path=/data fstype=nfs opts=defaults state=present"
[root@m01 ~]# ansible web02 -m mount -a "src=172.16.1.7:/data path=/data fstype=nfs opts=defaults state=mounted"
[root@m01 ~]# ansible web02 -m mount -a "src=172.16.1.7:/data path=/data fstype=nfs opts=defaults state=unmounted"
[root@m01 ~]# ansible web02 -m mount -a "src=172.16.1.7:/data path=/data fstype=nfs opts=defaults state=absent"Copy to clipboardErrorCopied

[Setup模块]

功能: setup 模块来收集主机的系统信息,这些 facts 信息可以直接以变量的形式使用,但是如果主机较多,会影响执行速度,可以使用 gather_facts: no 来禁止 Ansible 收集 facts 信息。

  • 范例
ansible all -m setup -a "filter=ansible_nodename"
ansible all -m setup -a "filter=ansible_hostname"
ansible all -m setup -a "filter=ansible_domain"
ansible all -m setup -a "filter=ansible_memtotal_mb"
ansible all -m setup -a "filter=ansible_memory_mb"
ansible all -m setup -a "filter=ansible_memfree_mb"
ansible all -m setup -a "filter=ansible_os_family"
ansible all -m setup -a "filter=ansible_distribution_major_version"
ansible all -m setup -a "filter=ansible_distribution_version"
ansible all -m setup -a "filter=ansible_processor_vcpus"
ansible all -m setup -a "filter=ansible_all_ipv4_addresses"
ansible all -m setup -a "filter=ansible_architecture"
ansible all -m setup -a "filter=ansible_processor*"Copy to clipboardErrorCopied

上一篇

[playbook-剧本(一)]

playbooks是 一个不同于使用Ansible命令行执行方式的模式,其功能更强大灵活。简单来说,playbook是一个非常简单的配置管理和多主机部署系统,不同于任何已经存在的模式,可作为一个适合部署复杂应用程序的基础。Playbook可以定制配置,可以按照指定的操作步骤有序执行,支持同步和异步方式。值得注意的是playbook是通过YAML格式来进行描述定义的。

[YAML语法结构]

playbook使用yml标记语言,这是一种标记语言,这种标记语言在文件的最开始需要使用三个“-”来说明文件开始,然后使用缩进来说明代码块的范围。下面通过一个简易的实例,来说明playbook的语法。

YAML 官方网站:http://www.yaml.org

---                             #标记文件的开始
- hosts: webservers             #指定该playbook在哪个服务器上执行
  vars:                         #表示下面是定义的变量,
    http_port: 80               #变量的形式,key: value,这里http_port是变量名,80是值
    max_clients: 200
  remote_user: root             #指定远程的用户名,这里缩进和vars保持了一致,说明变量的代码块已经结束。
  tasks:                        #下面构成playbook的tasks,每个task都有 - name: 开始,name指定该任务的名称。
  - name: ensure apache is at the latest version  #指定该任务的名称。
    yum: pkg=httpd state=latest                   #yum说明要是用的模板名称,后面指定对应的参数,这两行结合起来就相当于一个shell命令。
  - name: write the apache config file            #每个task之间可以使用空行来做区分。
    template: src=/srv/httpd.j2 dest=/etc/httpd.conf #需要说明的是缩进的意义和python中缩进的意义是一样,是来区分代码块的。Copy to clipboardErrorCopied

[YAML语言特性]

- YAML的可读性好

- YAML和脚本语言的交互性好

- YAML使用实现语言的数据类型

- YAML有一个一致的信息模型

- YAML易于实现

- YAML可以基于流来处理

- YAML表达能力强,扩展性好

  ### [YAML语法简介](http://192.168.13.73:3000/#/file/Playbook?id=yaml语法简介)

- 在单一文件第一行,用连续三个连字号"-" 开始,还有选择性的连续三个点号( ... )用来表示文件的结尾

- 次行开始正常写Playbook的内容,一般建议写明该Playbook的功能

- 使用#号注释代码

- 缩进必须是统一的,不能空格和tab混用

- 缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的

- YAML文件内容是区别大小写的,key/value的值均需大小写敏感

- 多个key/value可同行写也可换行写,同行使用,分隔

- key后面冒号要加一个空格 比如: key: value

- value可是个字符串,也可是另一个列表

- YAML文件扩展名通常为yml或yaml

[支持的数据类型]

YAML 支持以下常用几种数据类型:

- 标量:单个的、不可再分的值
- 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
- 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)

[标量]

不可在分的量。包括字符串,布尔值,整数,浮点数,Null,时间,日期。
key对应value

name: chenyangCopy to clipboardErrorCopied

[字典]

字典由多个key与value构成,key和value之间用 :分隔, 并且 : 后面有一个空格,所有k/v可以放在一行,或者每个 k/v 分别放在不同行。

account: 
 name: chenyang
 age: 30Copy to clipboardErrorCopied

[列表]

列表由多个元素组成,每个元素放在不同行,且元素前均使用"-"打头,并且 - 后有一个空格, 或者将所有元素用 [ ] 括起来放在同一行。

course:
 - linux: centos
 - golang: gin
 - python: djangoCopy to clipboardErrorCopied

[三种常见的数据格式](

  • XML:Extensible Markup Language,可扩展标记语言,可用于数据交换和配置
  • JSON:JavaScript Object Notation, JavaScript 对象表记法,主要用来数据交换或配置,不支持注释
  • YAML:YAML Ain’t Markup Language YAML 不是一种标记语言, 主要用来配置,大小写敏感,不支持tab

可以用工具互相转换,参考网站:

https://www.json2yaml.com/

http://www.bejson.com/json/json2yaml/

[Playbook核心组件]

一个playbook 中由列表组成,其中所用到的常见组件类型如下:

- Hosts 执行的远程主机列表
- Tasks 任务集,由多个task的元素组成的列表实现,每个task是一个字典,一个完整的代码块功能需最少元素需包括 name 和 task,一个name只能包括一个task
- Variables 内置变量或自定义变量在playbook中调用
- Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
- Handlers 和 notify 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
- tags 标签 指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断

[host组件]

Hosts:playbook中的每一个play的目的都是为了让特定主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机,须事先定义在主机清单中。

one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*
public:private     #或者,两个组的并集
public:&private   #与,两个组的交集
public:!private  #在public组,但不在private组Copy to clipboardErrorCopied
  • 案例
- hosts: public:!privateCopy to clipboardErrorCopied

[remote_user组件]

remote_user: 可用于Host和task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户。

- hosts: public
  remote_user: root
  gather_facts: no             #不收集对应主机的信息,这样运行会快点。
  
  tasks:
    - name: test connection
      ping:
      remote_user: chenyang
      sudo: yes                         #默认sudo为root
      sudo_user: shanhe        #sudo为shanheCopy to clipboardErrorCopied

[task列表]

playbook的主体部分是task list,task list中有一个或多个task,各个task 按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个task后,再开始第二个task。

task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致。

每个task都应该有其name,用于playbook的执行结果输出,建议其内容能清晰地描述任务执行步骤。

如果未提供name,则action的结果将用于输出

---
- hosts: public
  remote_user: root
  gather_facts: no
  
  tasks:
    - name: install httpd
      yum: name=httpd 
    - name: start httpd
      service: name=httpd state=started enabled=yesCopy to clipboardErrorCopied

[playbook命令]

格式

ansible-playbook <filename.yml> ... [options]Copy to clipboardErrorCopied

常见选项

--syntax-check      #语法检查
-C --check                     #只检测可能会发生的改变,但不真正执行操作
--list-hosts    #列出运行任务的主机
--list-tags         #列出tag
--list-tasks         #列出task
--tags                     # 只run 一个tag
--skip-tags        # 跳过某个task
--limit 主机列表 #只针对主机列表中的特定主机执行
-v -vv  -vvv #显示过程Copy to clipboardErrorCopied
  • 案例1
[root@instance-gvpb80ao ~]# cat hello.yaml 
- hosts: public
  remote_user: root
  gather_facts: no
  tasks:
    - name: hello world
      command: echo "Hello Chenyang"
[root@instance-gvpb80ao ~]# ansible-playbook hello.yaml 

PLAY [public] ************************************************************************************************

TASK [hello world] *******************************************************************************************
changed: [106.13.81.75]

PLAY RECAP ***************************************************************************************************
106.13.81.75               : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   Copy to clipboardErrorCopied
  • 案例2
[root@instance-gvpb80ao ~]# ansible-playbook -v hello.yaml 
Using /etc/ansible/ansible.cfg as config file

PLAY [public] ************************************************************************************************

TASK [hello world] *******************************************************************************************
changed: [106.13.81.75] => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "cmd": ["echo", "Hello Chenyang"], "delta": "0:00:00.022512", "end": "2021-05-21 10:33:43.493102", "rc": 0, "start": "2021-05-21 10:33:43.470590", "stderr": "", "stderr_lines": [], "stdout": "Hello Chenyang", "stdout_lines": ["Hello Chenyang"]}

PLAY RECAP ***************************************************************************************************
106.13.81.75               : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   Copy to clipboardErrorCopied

[Playbook 初步]

[利用playbook创建mysql用户]

[root@instance-gvpb80ao ~]# cat mysql.yaml 
- hosts: public
  remote_user: root
  gather_facts: no
  tasks:
    - name: Create Group
      group: name=mysql system=yes gid=666
    - name: Create User
      user: name=mysql shell=/sbin/nologin system=yes group=mysql uid=666 home=/home/mysql create_home=no
[root@instance-gvpb80ao ~]# ansible-playbook mysql.yaml 

PLAY [public] ************************************************************************************************

TASK [Create Group] ******************************************************************************************
ok: [106.13.81.75]

TASK [Create User] *******************************************************************************************
changed: [106.13.81.75]

PLAY RECAP ***************************************************************************************************
106.13.81.75               : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@instance-gvpb80ao ~]# Copy to clipboardErrorCopied

[利用playbook安装NGINX]

- hosts: public
  remote_user: root
  gather_facts: no
  tasks:
    - name: Create Group
      group: name=nginx system=yes gid=666
    - name: Create User
      user: name=nginx shell=/sbin/nologin system=yes group=nginx uid=666 home=/home/nginx create_home=no
    - name: Install nginx
      yum: name=nginx state=present
    - name: Start Nginx
      service:  name=nginx state=started enabled=yesCopy to clipboardErrorCopied

[利用 playbook 安装和卸载 httpd]

# 安装httpd
- hosts: public
  remote_user: root
  gather_facts: no
  tasks:
    - name: Create Group
      group: name=www system=yes gid=777
    - name: Create User
      user: name=www shell=/sbin/nologin system=yes group=www uid=777 home=/home/www create_home=no
    - name: Install nginx
      yum: name=httpd state=present
    - name: Start Nginx
      service:  name=httpd state=started enabled=yes

# 卸载httpd
- hosts: public
  remote_user: root
  tasks:
    - name: remove httpd package
      yum: name=httpd state=absent
    - name: remove apache user
      user: name=www state=absent
    - name: remove config file
      file: name=/etc/httpd state=absent
    - name: remove web html
      file: name=/var/html/ state=absent
   Copy to clipboardErrorCopied

[Playbook中使用handlers和notify]

Handlers本质是task list ,类似于MySQL中的触发器触发的行为,其中的task与前述的task并没有本质上的不同,主要用于当关注的资源发生变化时,才会采取一定的操作。而Notify对应的action可用于在每个play的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作。

- hosts: public 
  remote_user: root
  gather_facts: no

  tasks:
    - name: Install httpd
      yum: name=httpd state=present
    - name: Install configure file
      copy: src=httpd.conf dest=/etc/httpd/conf/
      notify: restart httpd
    - name: ensure apache is running
      service: name=httpd state=started enabled=yes

  handlers:
    - name: restart httpd
      service: name=httpd state=restarted

[root@instance-gvpb80ao ~]# ansible-playbook test.yaml 

PLAY [public] ************************************************************************************************

TASK [Install httpd] *****************************************************************************************
ok: [106.13.81.75]

TASK [Install configure file] ********************************************************************************
changed: [106.13.81.75]

TASK [ensure apache is running] ******************************************************************************
changed: [106.13.81.75]

RUNNING HANDLER [restart httpd] ******************************************************************************
changed: [106.13.81.75]

PLAY RECAP ***************************************************************************************************
106.13.81.75               : ok=4    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
Copy to clipboardErrorCopied

[Playbook中使用tags组件]

在playbook文件中,可以利用tags组件,为特定 task 指定标签,当在执行playbook时,可以只执行特定tags的task,而非整个playbook文件。

- hosts: public 
  remote_user: root
  gather_facts: no

  tasks:
    - name: Install httpd
      yum: name=httpd state=present
      tags: install
    - name: Install configure file
      copy: src=httpd.conf dest=/etc/httpd/conf/
      notify: restart httpd
    - name: ensure apache is running
      service: name=httpd state=started enabled=yes

  handlers:
    - name: restart httpd
      service: name=httpd state=restarted

ansible-playbook –t install httpd.ymlCopy to clipboardErrorCopied

[Playbook中使用变量]

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

[在playbook的开头通过vars进行定义]

[root@m01 project1]# cat  p2.yml 
- hosts: webservers
  vars:
    - web_package: httpd
    - ftp_package: vsftpd
  tasks:
    - name: Installed Packages
      yum: 
        name: 
          - "{{ web_package }}"
          - "{{ ftp_package }}"
        state: presentCopy to clipboardErrorCopied

[playbook中使用vars_files指定文件作为变量文件]

[root@m01 project1]# cat vars.yml 
web_package: httpd
ftp_package: vsftpd

[root@m01 project1]# cat p2.yml 
- hosts: webservers
  vars_files: ./vars.yml
  tasks:
    - name: Installed Packages
      yum: 
        name: 
          - "{{ web_package }}"
          - "{{ ftp_package }}"
        state: present
Copy to clipboardErrorCopied

[在inventory中定义变量,主机变量优先级高于主机组变量(不推荐,容易将环境弄的特别乱)]

[root@m01 project1]# vim /etc/ansible/hosts 
[webservers]
web01 ansible_ssh_host=172.16.1.7
web02 ansible_ssh_host=172.16.1.8
[webservers:vars]
filename=group_vars

[root@m01 project1]# cat p3.yml 
- hosts: webservers
  tasks:
    - name: Create File
      file: path=/tmp/{{ filename }} state=touchCopy to clipboardErrorCopied

[更好的方式是在ansible的项目目录中创建额外的两个变量目录]

group_vars目录下必须存放和inventory清单文件中定义的组名一致,如下
[root@m01 project1]# cat /etc/ansible/hosts 
[webservers]
web01 ansible_ssh_host=172.16.1.7
web02 ansible_ssh_host=172.16.1.8

[root@m01 project1]# cat group_vars/webservers 
web_package: httpd
ftp_package: vsftpd
# 注意:系统提供了特殊的组,all,也就说在group_vars目录下创建一个all文件,定义变量对所有的主机都生效


[root@m01 project1]# cat host_vars/web01 
web_package: zlib-static
ftp_package: zmap

[root@m01 project1]# cat group_vars/webservers 
web_package: httpd
ftp_package: vsftpd


[root@m01 project1]#  cat p4.yml 
- hosts: webservers
  tasks:
    - name: Installed Packages
      yum: 
        name: 
          - "{{ web_package }}"
          - "{{ ftp_package }}"
        state: present


[root@m01 project1]# ansible-playbook p4.yml 

PLAY [webservers] ********************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************
ok: [web02]
ok: [web01]

TASK [Installed Packages] ************************************************************************************************
ok: [web02]
changed: [web01]

PLAY RECAP ***************************************************************************************************************
web01                      : ok=2    changed=1    unreachable=0    failed=0   
web02                      : ok=2    changed=0    unreachable=0    failed=0   
Copy to clipboardErrorCopied

[通过命令行覆盖变量]

令行直接指定变量所覆盖。使用--extra-vars或-e设定变量。
[root@m01 project1]# ansible-playbook p4.yml -e "web_package=zarafa-devel" -e "ftp_package=zarafa-utils"Copy to clipboardErrorCopied

[变量优先级]

命令行变量—>play中的vars_files—>play中的vars变量–>host_vars中定义的变量—>group_vars/组—>group_vars/all

[root@m01 project1]# cat p5.yml 
- hosts: webservers
#  vars:
#    filename: play_vars
#  vars_files:
#    - ./vars.yml
  tasks:

    - name: Create 
      shell: mkdir -pv /tmp/{{ filename }}
      register: mk_test

    - name: debug
      debug: msg={{ mk_test }}
Copy to clipboardErrorCopied

上一篇

[Playbook(二)]

[template模板]

模板是一个文本文件,可以做为生成文件的模版,并且模板文件中还可嵌套jinja语法。

[jinja2语言]

官方网站:

http://jinja.pocoo.org/

https://jinja.palletsprojects.com/en/2.11.x/

[数据类型]

jinja2 语言支持多种数据类型和操作:


- 字符串:使用单引号或双引号,
- 数字:整数,浮点数
- 列表:[item1, item2, ...]
- 元组:(item1, item2, ...)
- 字典:{key1:value1, key2:value2, ...}
- 布尔型:true/false
- 算术运算:+, -, *, /, //, %, **
- 比较操作:==, !=, >, >=, <, <=
- 逻辑运算:and,or,not
- 流表达式:For,If,When

### [template](http://192.168.13.73:3000/#/file/Playbook2?id=template)

>template功能:可以根据和参考模块文件,动态生成相类似的配置文件,template文件必须存放于templates目录下,且命名为 .j2 结尾,yaml/yml 文件需和templates目录平级,目录结构如下示例:

```bash
 ./
├── temnginx.yml
└── templates
    └── nginx.conf.j2Copy to clipboardErrorCopied

范例:利用template 同步nginx配置文件

#准备templates/nginx.conf.j2文件
[root@ansible ~]#vim temnginx.yml
---
- hosts: web
  remote_user: root
  tasks:
    - name: template config to remote hosts
     template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
 [root@ansible ~]#ansible-playbook temnginx.ymlCopy to clipboardErrorCopied

[template变更替换]

#修改文件nginx.conf.j2 
[root@ansible ~]#mkdir templates
[root@ansible ~]#vim templates/nginx.conf.j2
......
worker_processes {{ ansible_processor_vcpus }};
......
[root@ansible ~]#vim temnginx2.yml
---
- hosts: web
  remote_user: root
  
  tasks:
    - name: install nginx
      yum: name=nginx
    - name: template config to remote hosts
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf 
    - name: start service
      service: name=nginx state=started enabled=yes
       
[root@ansible ~]#ansible-playbook temnginx2.ymlCopy to clipboardErrorCopied

[常用的系统参数]

ansible_all_ipv4_addresses:仅显示ipv4的信息
ansible_devices:仅显示磁盘设备信息
ansible_distribution:显示是什么系统,例:centos,suse等
ansible_distribution_version:仅显示系统版本
ansible_machine:显示系统类型,例:32位,还是64位
ansible_eth0:仅显示eth0的信息
ansible_hostname:仅显示主机名
ansible_kernel:仅显示内核版本
ansible_lvm:显示lvm相关信息
ansible_memtotal_mb:显示系统总内存
ansible_memfree_mb:显示可用系统内存
ansible_memory_mb:详细显示内存情况
ansible_swaptotal_mb:显示总的swap内存
ansible_swapfree_mb:显示swap内存的可用内存
ansible_mounts:显示系统磁盘挂载情况
ansible_processor:显示cpu个数(具体显示每个cpu的型号)
ansible_processor_vcpus:显示cpu个数(只显示总的个数)
ansible_python_version:显示python版本Copy to clipboardErrorCopied

[template算术运算]

[root@ansible ansible]#vim templates/nginx.conf.j2
worker_processes {{ ansible_processor_vcpus**3 }};
[root@ansible ansible]#cat templnginx.yml
---
- hosts: websrvs
  remote_user: root
  tasks:
    - name: install nginx
      yum: name=nginx
    - name: template config to remote hosts
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
      notify: restart nginx
    - name: start service
      service: name=nginx state=started enabled=yes
 handlers:
    - name: restart nginx
      service: name=nginx state=restarted
[root@ansible ~]#-playbook templnginx.yml --limit 10.0.0.8Copy to clipboardErrorCopied

[template中使用流程控制for和if]

template中也可以使用流程控制 for 循环和 if 条件判断,实现动态生成文件功能

#temlnginx2.yml
---
- hosts: websrvs
 remote_user: root
 vars:
   nginx_vhosts:
     - 81
     - 82
     - 83
 tasks:
   - name: template config
     template: src=nginx.conf2.j2 dest=/data/nginx.conf
#templates/nginx.conf2.j2
{% for vhost in nginx_vhosts %}
server {
   listen {{ vhost }}
}
{% endfor %}
ansible-playbook -C templnginx2.yml --limit 192.168.15.8
#生成的结果:
server {
   listen 81   
}
server {
   listen 82   
}
server {
   listen 83   
}




#templnginx4.yml
- hosts: websrvs
 remote_user: root
 vars:
   nginx_vhosts:
     - listen: 8080
       server_name: "web1.oldboy.com"
       root: "/var/www/nginx/web1/"
     - listen: 8081
       server_name: "web2.oldboy.com"
       root: "/var/www/nginx/web2/"
     - {listen: 8082, server_name: "web3.oldboy.com", root: 
"/var/www/nginx/web3/"}
 tasks:
   - name: template config 
     template: src=nginx.conf4.j2 dest=/data/nginx4.conf
      
   
# templates/nginx.conf4.j2
{% for vhost in nginx_vhosts %}
server {
   listen {{ vhost.listen }}
   server_name {{ vhost.server_name }}
   root {{ vhost.root }}  
}{% endfor %} 

[root@ansible ~]#ansible-playbook templnginx4.yml --limit 10.0.0.8
#生成结果:
server {
   listen 8080
   server_name web1.oldboy.com
   root /var/www/nginx/web1/  
}
server {
   listen 8081
   server_name web2.oldboy.com
   root /var/www/nginx/web2/  
}
server {
   listen 8082
   server_name web3.oldboy.com
   root /var/www/nginx/web3/  
}Copy to clipboardErrorCopied

[playbook使用when]

when语句,可以实现条件测试。如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,通过在task后添加when子句即可使用条件测试,jinja2的语法格式。

tasks:
  - name: "shut down CentOS 6 and Debian 7 systems"
   command: /sbin/shutdown -t now
   when: (ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_major_version'] == "6") or (ansible_facts['distribution'] == "Debian" and ansible_facts['distribution_major_version'] == "7")Copy to clipboardErrorCopied

[playbook使用迭代with_items(loop)]

迭代:当有需要重复性执行的任务时,可以使用迭代机制对迭代项的引用,固定内置变量名为"item",要在task中使用with_items给定要迭代的元素列表

注意: ansible2.5版本后,可以用loop代替with_items

---
- hosts: websrvs
 remote_user: root
  
 tasks:
    - name: add several users
     user: name={{ item }} state=present groups=wheel
     with_items:
        - testuser1
        - testuser2
        - testuser3
        
#上面语句的功能等同于下面的语句
    - name: add several users
      user: name=testuser1 state=present groups=wheel
    - name: add several users
      user: name=testuser2 state=present groups=wheel
    - name: add several users
      user: name=testuser3 state=present groups=wheel



---
#remove mariadb server
- hosts: 172.16.1.7
  remote_user: root
  tasks:
    - name: stop service
      shell: /etc/init.d/mysqld stop
    - name: delete files and dir
      file: path={{item}} state=absent
      with_items:
        - /usr/local/mysql
        - /usr/local/mariadb-10.2.27-linux-x86_64
        - /etc/init.d/mysqld
        - /etc/profile.d/mysql.sh
        - /etc/my.cnf
        - /data/mysql
    - name: delete user
      user: name=mysql state=absent remove=yesCopy to clipboardErrorCopied

**迭代嵌套子变量:**在迭代中,还可以嵌套子变量,关联多个变量在一起使用

---
- hosts: websrvs
  remote_user: root
  
  tasks:
    - name: add some groups
      group: name={{ item }} state=present
      with_items:
        - nginx
        - mysql
        - apache
    - name: add some users
      user: name={{ item.name }} group={{ item.group }} state=present
      with_items:
        - { name: 'nginx', group: 'nginx' }
        - { name: 'mysql', group: 'mysql' }
        - { name: 'apache', group: 'apache' }Copy to clipboardErrorCopied

[管理节点过多导致的超时问题解决方法]

默认情况下,Ansible将尝试并行管理playbook中所有的机器。对于滚动更新用例,可以使用serial关键字定义Ansible一次应管理多少主机,还可以将serial关键字指定为百分比,表示每次并行执行的主机数占总数的比例

#vim test_serial.yml
---
- hosts: all
  serial: 2  #每次只同时处理2个主机,将所有task执行完成后,再选下2个主机再执行所有task,直至所有主机
  gather_facts: False
  tasks:
    - name: task one
  comand: hostname
    - name: task two
      command: hostname


# 案例2:
- name: test serail
  hosts: all
  serial: "20%"   #每次只同时处理20%的主机Copy to clipboardErrorCopied

[Role]

角色是ansible自1.2版本引入的新特性,用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中

#运维复杂的场景:建议使用 roles,代码复用度高

roles:多个角色的集合目录, 可以将多个的role,分别放至roles目录下的独立子目录中,如下示例


roles/
 mysql/
 nginx/
 tomcat/
 redis/Copy to clipboardErrorCopied

默认roles存放路径

/root/.ansible/roles
/usr/share/ansible/roles
/etc/ansible/rolesCopy to clipboardErrorCopied

[Ansible Roles目录编排]

├── nginx -------------role1名称
│   ├── defaults  ---------必须存在的目录,存放默认的变量,模板文件中的变量就是引用自这里。defaults中的变量优先级最低,通常我们可以临时指定变量来进行覆盖
│   │   └── main.yml
│   ├── files -------------ansible中unarchive、copy等模块会自动来这里找文件,从而我们不必写绝对路径,只需写文件名
│   │   ├── mysql.tar.gz
│   │   └── nginx.tar.gz
│   ├── handlers -----------存放tasks中的notify指定的内容
│   │   └── main.yml
│   ├── meta
│   ├── tasks --------------存放playbook的目录,其中main.yml是主入口文件,在main.yml中导入其他yml文件,要采用import_tasks关键字,include要弃用了
│   │   ├── install.yml
│   │   └── main.yml -------主入口文件
│   ├── templates ----------存放模板文件。template模块会将模板文件中的变量替换为实际值,然后覆盖到客户机指定路径上
│   │   └── nginx.conf.j2
│   └── varsCopy to clipboardErrorCopied

[Roles各目录作用]

- files/ :存放由copy或script模块等调用的文件

- templates/:template模块查找所需要模板文件的目录

- tasks/:定义task,role的基本元素,至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含

- handlers/:至少应该包含一个名为main.yml的文件;此目录下的其它的文件需要在此文件中通过

- include进行包含

- vars/:定义变量,至少应该包含一个名为main.yml的文件;此目录下的其它的变量文件需要在此文件中通过include进行包含

- meta/:定义当前角色的特殊设定及其依赖关系,至少应该包含一个名为main.yml的文件,其它文件需在此文件中通过include进行包含

- default/:设定默认变量时使用此目录中的main.yml文件,比vars的优先级低

[创建role]

创建role的步骤

1 创建以roles命名的目录
2 在roles目录中分别创建以各角色名称命名的目录,如mysql等
3 在每个角色命名的目录中分别创建files、handlers、tasks、templates和vars等目录;用不到的目录可以创建为空目录,也可以不创建
4 在每个角色相关的子目录中创建相应的文件,如 tasks/main.yml,templates/nginx.conf.j2
5 在playbook文件中,调用需要的角色Copy to clipboardErrorCopied

[针对大型项目使用Roles进行编排]

# 范例
nginx-role.yml 
roles/
└── nginx 
     ├── files
     │   └── main.yml 
     ├── tasks
     │   ├── groupadd.yml 
     │   ├── install.yml 
     │   ├── main.yml 
     │   ├── restart.yml 
     │   └── useradd.yml 
     └── vars 
         └── main.ymlCopy to clipboardErrorCopied

[playbook调用角色]

  • 调用角色方法1
---
- hosts: web
  remote_user: root
  roles:
    - mysql
    - memcached
    - nginx  Copy to clipboardErrorCopied
  • 调用角色方法2
---
- hosts: all
  remote_user: root
  roles:
    - mysql
    - { role: nginx, username: nginx }Copy to clipboardErrorCopied
  • 调用角色方法3
---
- hosts: all
  remote_user: root
  roles:
    - { role: nginx, username: nginx, when: ansible_distribution_major_version == '7' }Copy to clipboardErrorCopied
  • 调用角色方法4
---
- hosts: appsrvs
  remote_user: root
  roles:
    - { role: nginx ,tags: [ 'nginx', 'web' ] ,when: ansible_distribution_major_version == "6" }
    - { role: httpd ,tags: [ 'httpd', 'web' ] }
    - { role: mysql ,tags: [ 'mysql', 'db' ] }
    - { role: mariadb ,tags: [ 'mariadb', 'db' ] }Copy to clipboardErrorCopied

[案例]

[httpd角色]

#创建角色相关的目录
[root@ansible ~]#mkdir -pv /data/ansible/roles/httpd/{tasks,handlers,files}
  
#创建角色相关的文件
[root@ansible ~]#cd /data/ansible/roles/httpd/

#main.yml 是task的入口文件
[root@ansible ~]#vim tasks/main.yml
- include: group.yml
- include: user.yml
- include: install.yml
- include: config.yml
- include: index.yml
- include: service.yml

[root@ansible ~]#vim tasks/group.yml
- name: create apache group
  group: name=apache system=yes gid=80
  
[root@ansible ~]#vim tasks/user.yml
- name: create apache user
  user: name=apache system=yes shell=/sbin/nologin home=/var/www/ uid=80 group=apache
  
[root@ansible ~]#vim tasks/install.yml
- name: install httpd package
  yum: name=httpd
[root@ansible ~]#vim tasks/config.yml
- name: config file
  copy: src=httpd.conf dest=/etc/httpd/conf/ backup=yes
  notify: restart
[root@ansible ~]# tasks/index.yml
- name: index.html
  copy: src=index.html dest=/var/www/html/
[root@ansible ~]#vim tasks/service.yml
- name: start service
  service: name=httpd state=started enabled=yes
[root@ansible ~]#vim handlers/main.yml
- name: restart
  service: name=httpd state=restarted
  
#在files目录下准备两个文件
[root@ansible ~]#ls files/
httpd.conf index.html
[root@ansible ~]#tree /data/ansible/roles/httpd/
/data/ansible/roles/httpd/
├── files
│   ├── httpd.conf
│   └── index.html
├── handlers
│   └── main.yml
└── tasks
   ├── config.yml
   ├── group.yml
   ├── index.yml
   ├── install.yml
   ├── main.yml
   ├── service.yml
   └── user.yml
3 directories, 10 files
#在playbook中调用角色
[root@ansible ~]#vim /data/ansible/role_httpd.yml
---
# httpd role
- hosts: websrvs
  remote_user: root
  roles:
    - httpd
    
#运行playbook
[root@ansible ~]#ansible-playbook /data/ansible/role_httpd.ymlCopy to clipboardErrorCopied

[NGINX角色]

[root@ansible ~]#mkdir -pv /data/ansible/roles/nginx/{tasks,handlers,templates,vars}

#创建task文件
[root@ansible ~]#cd /data/ansible/roles/nginx/
[root@ansible nginx]#vim tasks/main.yml 
- include: install.yml
- include: config.yml
- include: index.yml
- include: service.yml
[root@ansible nginx]#vim tasks/install.yml 
- name: install
  yum: name=nginx 
 
[root@ansible nginx]#vim tasks/config.yml 
- name: config file for centos7
  template: src=nginx7.conf.j2 dest=/etc/nginx/nginx.conf
  when: ansible_distribution_major_version=="7"
  notify: restart
- name: config file for centos8
  template: src=nginx8.conf.j2 dest=/etc/nginx/nginx.conf
  when: ansible_distribution_major_version=="8"
  notify: restart
  
#跨角色调用文件
[root@ansible nginx]#vim tasks/index.yml 
- name: index.html
  copy: src=roles/httpd/files/index.html dest=/usr/share/nginx/html/
[root@ansible nginx]#vim tasks/service.yml 
- name: start service
  service: name=nginx state=started enabled=yes
#创建handler文件
[root@ansible nginx]#cat handlers/main.yml 
- name: restart
  service: name=nginx state=restarted
#创建两个template文件
[root@ansible nginx]#cat templates/nginx7.conf.j2
...省略...
user {{user}};
worker_processes {{ansible_processor_vcpus+3}};   #修改此行
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
...省略...
[root@ansible nginx]#cat templates/nginx8.conf.j2
...省略...
user nginx;
worker_processes {{ansible_processor_vcpus**3}};  #修改此行
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
...省略...
#创建变量文件
[root@ansible nginx]#vim vars/main.yml 
user: daemon
#目录结构如下
[root@ansible ~]#tree /data/ansible/roles/nginx/
/data/ansible/roles/nginx/
├── handlers
│   └── main.yml
├── tasks
│   ├── config.yml
│   ├── file.yml
│   ├── install.yml
│   ├── main.yml
│   └── service.yml
├── templates
│   ├── nginx7.conf.j2
│   └── nginx8.conf.j2
└── vars
   └── main.yml
4 directories, 9 files
#在playbook中调用角色
[root@ansible ~]#vim /data/ansible/role_nginx.yml 
---
#nginx role 
- hosts: web
 roles:
    - role: nginx
    
#运行playbook
[root@ansible ~]#ansible-playbook /data/ansible/role_nginx.ymlCopy to clipboardErrorCopied

你可能感兴趣的:(基础架构,运维服务器管理工具,ansible,自动化,服务器,运维)