• 运维工具 ansible


    一、简介 

    ansible 不是服务端-客户端,在一台机器安装ansible后,ansible通过ssh服务,给其他机器下发任务

    ansible # 命令
    ansible # 模块,模块理解为命令
    ansible playbook  # ansible的脚本,使用的yaml语法格式
    playbook中可实现 # 变量、tags 标签、handlers 触发器、playbook 模板(templates)、playbook条件判断(when)、playbook 字典(with_items)、循环等等,脚本能做的 playbook 几乎都可以
    ansible roles  # 一个功能可能需要使用多个playbook脚本,我们需要组合各种不同的脚本实现不同的功能,进而来实现一个复杂功能。组合各种playbook,以及把各种相关不同类型的文件分别类组合,进行管理,叫做角色,可以理解多个脚本的集合,实现复杂任务。

    Ansible 组成:

    HOSTS  管理的设备,如Linux、windoes
    NETWORKING  交换机、路由器
    INVENTORY  将需要将管理的设备(HOSTS、NETWORKING)加入到清单中
    MODULES  模块、PLIGINS 插件、
    API 做软件开发调用API,可以通过运维平台调用ansible 的API,进而让Ansible来管理后端HOSTS
    USERS 代表用户,使用命令直接调用模块、插件来管理后端
    ANSIBLE PLAYBOOOK 代表脚本来管理后端
    PUBLIC/PRIVITE CLOUD 公有云/私有云去调用
    CMDB 配置管理数据库,也是一个软件,调用Ansible来管理后端
    等等,还有其他的软件,比如运维平台,一个web 调用ansible 的API,进而让Ansible来管理后端

    二、安装Ansible

    Ansible部署方式有4种,包括yum、二进制、Git clone,由于Ansible是基于python,所以可以通过python的命令 pip 部署

    1、yum (EPEL源的 rpm 包安装)

    1. yum info ansible # 查看ansible当前的版本
    2. yum install ansible

    2、二进制编译安装

    1、下载ansible安装包
    https://releases.ansible.com/ansible/

    ]# wget https://releases.ansible.com/ansible/ansible-2.9.5.tar.gz
    

    2、下载python安装包
    https://www.python.org/downloads/

    wget https://www.python.org/ftp/python/3.8.12/Python-3.8.12.tar.xz

    3、安装python,配置pip

    1. 1、yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel libffi-devel gcc
    2. 2、安装python
    3. tar -xvf Python-3.8.12.tar.xz
    4. cd Python-3.8.12
    5. ./configure --prefix=/usr/local/python3.8
    6. make && make install
    7. linux默认自带的python是2.7.5
    8. 编译期间报错查看https://blog.csdn.net/Jerry00713/article/details/127380845
    9. 3、添加软连接
    10. rm -f /usr/bin/python /usr/bin/pip
    11. ln -s /usr/local/python3.8/bin/python3.8 /usr/bin/python
    12. ln -s /usr/local/python3.8/bin/pip3.8 /usr/bin/pip
    13. 4、配置pip源
    14. mkdir /root/.pip
    15. ]# cat <<EOF > /root/.pip/pip.conf
    16. [global]
    17. index-url = https://mirrors.huaweicloud.com/repository/pypi/simple
    18. trusted-host = mirrors.huaweicloud.com
    19. timeout = 120
    20. EOF

    4、安装ansible

    1. 1、解压并安装
    2. tar -xvf ansible-2.9.5.tar.gz
    3. cd ansible-2.9.5
    4. python setup.py install
    5. 报错:
    6. Ansible now needs setuptools in order to build. Install it using your package manager
    7. (usually python-setuptools) or via pip (pip install setuptools).
    8. 安装依赖:
    9. 更新pip
    10. python -m pip install --upgrade pip
    11. 卸载并重装setuptools
    12. pip uninstall setuptools ##需要输入Y确定
    13. pip install setuptools
    14. 2、继续安装
    15. python setup.py install
    16. ##如果缺少依赖就会卡住,可以ctrl +c停掉,使用pip安装完依赖,再重新执行安装命令
    17. 3、添加软连接
    18. ansible安装完默认都安装到/usr/local/python3.8/bin下面
    19. ln -s /usr/local/python3.8/bin/ansible* /usr/bin/
    20. 4、创建默认配置文件
    21. 二进制安装的,配置文件在解压包里面有个模板
    22. mkdir /etc/ansible
    23. cp /root/ansible-2.9.5/examples/ansible.cfg /etc/ansible
    24. 5、验证
    25. ansible localhost -m ping

    查看版本

    注意:Centos7 安装为python3后,yum将会有问题

    1. File "/usr/bin/yum", line 30
    2.     except KeyboardInterrupt, e:
    3.                             ^
    4. SyntaxError: invalid syntax

    原因:yum需要用python2编译,如果服务器安装的是python3以上,并作为默认编译器的话,就会出现这个错误。

    解决方法:whereis python

    修改yum配置文件:vim  /usr/bin/yum
    第一行修改为你python2.7的路经所在位置即可!

     如果还不好使,可以yum的卸载与重新安装

    一、将现有的yum源卸载

    1. [root@linux-node3 ~]# rpm -qa yum
    2. yum-3.4.3-150.el7.centos.noarch
    3. [root@linux-node3 ~]# rpm -qa | grep yum | xargs rpm -e --nodeps  #这一步一定要执行,而且要将所有的组件卸载掉,如果卸载不干净,后面安装会有问题
    4. [root@linux-node3 ~]# rpm -qa yum

    二、从centos官网上下载和yum有关的rpm包

    1、下载rpm包,如果提示404,去地址查看具体现在是什么版本

    1. wget http://mirror.centos.org/centos/7/os/x86_64/Packages/yum-3.4.3-168.el7.centos.noarch.rpm
    2. wget http://mirror.centos.org/centos/7/os/x86_64/Packages/yum-metadata-parser-1.1.4-10.el7.x86_64.rpm
    3. wget http://mirror.centos.org/centos/7/os/x86_64/Packages/yum-plugin-fastestmirror-1.1.31-54.el7_8.noarch.rpm

    2、安装

    1. [root@linux-node3 ~]# ls 
    2. yum-3.4.3-167.el7.centos.noarch.rpm
    3. yum-metadata-parser-1.1.4-10.el7.x86_64.rpm
    4. yum-plugin-fastestmirror-1.1.31-53.el7.noarch.rpm
    5. [root@linux-node3 ~]# rpm -ivh yum-*     #安装
    6. [root@linux-node3 ~]# rpm -qa yum    #查看是否已经安装上
    7. yum-3.4.3-150.el7.centos.noarch.rpm

    包括 yum install 的时候

    vi /usr/libexec/urlgrabber-ext-down 修改报错文件,将头行"#!/usr/bin/python" 改为 "#!/usr/bin/python2"即可

    3、Git 安装

    1. git clone git://github.com/ansible/ansible.git --recursive
    2. cd ./ansible
    3. source ./hacking/env-setup

    4、pip 安装

    1. yum install python-pip python-devel
    2. yum install gcc glibc-devel zibl-devel rpm-build openssl-devel
    3. pip install --upgrade pip
    4. pip install ansible --upgrade

    三、部署配置使用

    两台设备:

    192.168.86.5  hostname=86-5-master   控制端
    192.168.86.6  hostname=86-6-slave     被控制端

    1、配置hostname

    1. [root@localhost ~]# hostnamectl set-hostname 86-5-master
    2. [root@localhost ~]# bash
    3. [root@86-5-master ~]# cat /etc/hosts # 配置域名解析
    4. 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
    5. ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
    6. 192.168.86.6 86-6-slave
    7. 192.168.86.5 86-5-master
    8. [root@86-5-master ~]#
    9. [root@localhost ~]# hostnamectl set-hostname 86-6-slave
    10. [root@localhost ~]# bash
    11. [root@86-5-slave ~]# cat /etc/hosts
    12. 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
    13. ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
    14. 192.168.86.6 86-6-slave
    15. [root@86-5-slave~]#

    2、86-5-master部署ansible,查看ansible的工具命令

    ansible 基于python 编写

    3、配置文件讲解

    /etc/ansible/ansible.cfg  # 主配置文件,配置ansible工作特性,一般不需要改
    /etc/ansible/hosts           # 主机清单,管理的网络设备,写入目标主机地址
    /etc/ansible/roles/           # 存放角色的目录

    /etc/ansible/ansible.cfg  # 主配置文件详解

    1. [defaults] # 默认配置
    2. #inventory = /etc/ansible/hosts # 主机列表配置文件
    3. #library = /usr/share/my_modules/ # 库文件存放目录,基于python实现
    4. #remote_tmp = ~/.ansible/tmp # ansible 执行命令,是将执行的命令(py命令文件)推送到远程主机的一个目录中随后执行,此文件只是临时文件执行完毕清空,此配置配置对端存储在哪
    5. #local_tmp = ~/.ansible/tmp # 对标remote_tmp,执行命令时候在本机生成命令py文件,存储在local_tmp目录,远程主机的时候会自动获取此文件,推送给对端,此文件时临时文件执行完毕清空
    6. #plugin_filters_cfg = /etc/ansible/plugin_filters.yml # 插件配置
    7. #forks = 5 # 默认并发数,给多少台机器同时发送
    8. #poll_interval = 15
    9. #sudo_user = root # 使用什么用户执行,需要配置ssh授权有此用户的权限
    10. #ask_sudo_pass = True # 每次执行ansible命令是否询问ssh密码
    11. #ask_pass = True # 这些配置都不用,我么使用基于key的ssh认证
    12. #transport = smart
    13. #remote_port = 22 # 连接对端的端口号
    14. #module_lang = C
    15. #module_set_locale = False
    16. #host_key_checcking = False # 检查对应服务器的host_key,建议取消注释,第一次ssh提示Yes/no,此提示ssh配置可以改,ansible也可以改
    17. #log_path=/var/log/ansible.log # 日志文件,建议启用
    18. #module_name = command # 默认模块,可以修改为shell模块
    19. [inventory] # 主机清单相关的
    20. [privilege_escalation] # 权限相关信息
    21. [paramiko_connection] # python 模块连接情况
    22. [ssh_connection] # ssh连接情况

    4、开启日志

    1. [root@86-5-master tmp]# grep 'log_path' /etc/ansible/ansible.cfg
    2. log_path = /var/log/ansible.log
    3. [root@86-5-master tmp]#

    5、配置主机清单文件

    /etc/ansible/hosts   

    # 需要做分类管理,数据库、tomcat 服务器安装的程序是不一样的,通过自定义名字用[] 括起来
    # 可以写IP或者写域名,也可以写IP范围 

    1. 192.168.23.1 # 不属于任何类,每一个ansible语句都要执行
    2. [webserver] # 定义webserver类,名字自定义,说明一下的机器都是webserver,区分那些机器需要执行webserver的命令
    3. 192.168.68.7 # 单台ip
    4. 192.168.23.1:2222 # 指定端口号,比如此机器没有使用标准的22端口号,给此IP特指2222
    5. alpha.example.org # 域名
    6. [dbservers]
    7. db-1.server
    8. db-2.server
    9. db-[3:100].server # 范围
    10. db-[a:f].server # 范围
    11. 192.168.78.4
    12. 192.168.8.[1:100] # 192.168.8.1 ~ 192.168.8.100

    基于当前只有一台机器, vi /etc/ansible/hosts   

    1. [root@86-5-master tmp]# vi /etc/ansible/hosts
    2. [root@86-5-master tmp]# cat /etc/ansible/hosts
    3. [dbserver]
    4. 86-6-slave

    四、Ansible相关命令使用

    1、ansible-doc命令

    Ad-Hoc 即利用ansible命令,主要用于临时命令使用场景,一条一条执行
    ansible-doc命令查看模块帮助,ansible模块太多。

    1. ansible-doc -l # 查看模块
    2. ansible-doc -l |wc -l # 查看有多少个模块
    3. ansible-doc -s 模块名字 # 查看模块使用方式,-s 只显示重点

    2、ansible 命令

    格式:ansible 分类管理的类名字(如果要所有的写all)   模块名  模块参数

    1. --version # 显示版本
    2. -m module # 指定 模块
    3. -v # 大略执行过程
    4. -vv # 详细过程
    5. -vvv # 超级详细过程
    6. --list-hosts # 显示匹配的主机列表,可简写 --list
    7. -k, --ask-pass # 添加-k,才会提示输入ssh连接密码。一般不用,一般使用ssh_key验证
    8. -c, --check # 检查,并不执行
    9. -T, --timeout=TIMEOUT # 检查命令的超时时间,默认10s
    10. -u, --user=REMOTE_USER # 指定使用哪个角色登录远程和操作
    11. -b, --become # 到远程机器后,使用sudo命令切换哪个用户,后续操作都在这个角色中,默认root。具体使用 -b --become-user=USERNAME
    12. 例如--become --become-method=sudo --become-user=root
    13. -k, --ask-become-pass # 提示输入sudo时的口令

    3、ansible-playbook 简单案例

    cat hello.yaml   # 编写playbook

    1. ---
    2. #hello world yaml file
    3. - hosts: dbserver
    4. remote_user: root
    5. tasks:
    6. - name: hello world
    7. command: /usr/bin/wall hello world

    ansible-playbook hello.yaml  # 执行hello.yaml 

    1. PLAY [dbserver] *****************************************************************************************************************************
    2. TASK [Gathering Facts] **********************************************************************************************************************
    3. ok: [192.168.86.6]
    4. ok: [86-6-slave]
    5. TASK [hello world] **************************************************************************************************************************
    6. changed: [86-6-slave]
    7. changed: [192.168.86.6]
    8. PLAY RECAP **********************************************************************************************************************************
    9. 192.168.86.6 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
    10. 86-6-slave : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

    4、ansible-vault 

    ansible-vault 是 加密/解密 yaml 的工具

    1. [root@86-5-master ansible_playbook]# ansible-vault
    2. usage: ansible-vault [-h] [--version] [-v] {create,decrypt,edit,view,encrypt,encrypt_string,rekey} ...
    3. ansible-vault: error: the following arguments are required: action

    ansible-vault encrypt 加密

    1. [root@86-5-master ansible_playbook]# ansible-vault encrypt hello.yaml
    2. New Vault password:
    3. Confirm New Vault password:
    4. Encryption successful
    5. [root@86-5-master ansible_playbook]# cat hello.yaml
    6. $ANSIBLE_VAULT;1.1;AES256
    7. 65366232383766313134373164623664633361633266613232623030356364306635386538353165
    8. 3535313563323432386539363730336135353633323932310a343236373365316333303339353165
    9. 34363938326463303637383931646437343362393736396438613461386462323833633537383238
    10. 6430313566383434660a333135393437653836333836313961306134303630313437363965333638
    11. 66663564653262613830396465643730303463616533363935343531396264393333383732656164
    12. 36303939646530653862363134643934303534336361353330623932623837333935366536333137
    13. 65346434386263613533376338323833383533633836363837323163323531333538396265396164
    14. 31343965306362646631303535643337646233643664343864353633666632373562386433376338
    15. 38313062323961633031356433396462666639353562333537376135323135313064353133373265
    16. 62313334373935316333643764613063343133623462343939313435663963636662306337663934
    17. 376663303732636263366339616635366262

    加密后无法使用ansible-playbook

    1. [root@86-5-master ansible_playbook]# ansible-playbook hello.yaml
    2. ERROR! Attempting to decrypt but no vault secrets found

    ansible-vault decrypt 解密

    1. [root@86-5-master ansible_playbook]# ansible-vault decrypt hello.yaml
    2. Vault password:
    3. Decryption successful
    4. [root@86-5-master ansible_playbook]# cat hello.yaml
    5. ---
    6. #hello world yaml file
    7. - hosts: dbserver
    8. remote_user: root
    9. tasks:
    10. - name: hello world
    11. command: /usr/bin/wall hello world

    5、ansible-console 用的不多

    ansible-console 是 ansible 的控制台

    1. [root@86-5-master ansible_playbook]# ansible-console
    2. Welcome to the ansible console.
    3. Type help or ? to list commands.
    4. root@all (2)[f:5]$ list # 默认不加参数,真对的是all,默认使用当前的用户权限,list显示hosts,f 代表5个并发
    5. 86-6-slave
    6. 192.168.86.6
    7. root@all (2)[f:5]$ cd 123 # 切换all类到123类,找不到
    8. [WARNING]: Could not match supplied host pattern, ignoring: 123
    9. no host matched
    10. root@all (2)[f:5]$ cd dbserver # 切换all类到dbserver
    11. root@dbserver (2)[f:5]$ cd all
    12. root@all (2)[f:5]$ forks 10 # 修改并发数
    13. root@all (2)[f:10]$ yum name=httpd state=present # yum 是ansible模块,也就是Linux中的安装卸载等操作
    14. root@all (2)[f:10]$ service name=httpd state=started

    6、ansible-galaxy

    使用galaxy提供好的playbook https://galaxy.ansible.com/geerlingguy

    Ansible Galaxy命令行工具,从命令行搜索角色,用户可以使用–author、–platforms和–galaxy-tags选项来缩小搜索结果的范围。搜索到的都是可以用的,命令ansible-galaxy search --author geerlingguy将显示由用户geerlingguy提交的所有角色

    1. ansible-galaxy search --author geerlingguy
    2. Found 101 roles matching your search:
    3. Name Description
    4. ---- -----------
    5. geerlingguy.adminer Installs Adminer for Database management.
    6. geerlingguy.ansible Ansible for RedHat/CentOS/Debian/Ubuntu.
    7. geerlingguy.apache Apache 2.x for Linux.
    8. geerlingguy.apache-php-fpm Apache 2.4+ PHP-FPM support for Linux.
    9. geerlingguy.aws-inspector AWS Inspector installation for Linux.
    10. geerlingguy.awx Installs and configures AWX (Ansible Tower's open source version).
    11. geerlingguy.awx-container Ansible AWX container for Docker.
    12. geerlingguy.backup Backup for Simple Servers.
    13. geerlingguy.bad_judgement DO NOT USE THIS ROLE! It is for demonstration purposes.
    14. geerlingguy.blackfire Blackfire installation for Linux
    15. geerlingguy.certbot Installs and configures Certbot (for Let's Encrypt).
    16. geerlingguy.clamav ClamAV installation and configuration.

    显示包含redis并且适用于企业Linux(EL)平台的角色的名称

    1. [root@86-5-master ~]# ansible-galaxy search 'redis' --platforms EL
    2. Found 255 roles matching your search:
    3. Name Description
    4. ---- -----------
    5. 0x0i.consul Consul - a service discovery, mesh and configuration control plane and networking tool
    6. 0x0i.grafana Grafana - an analytics and monitoring observability platform
    7. 0x5a17ed.ansible_role_netbox Installs and configures NetBox, a DCIM suite, in a production setting.
    8. 1it.sudo Ansible role for managing sudoers
    9. abarrak.redis_ansible_role Ansible role to install and configure redis instances based on Bitnami's chart.
    10. adfinis-sygroup.redis Ansible role for Redis
    11. AerisCloud.librato Install and configure the Librato Agent
    12. AerisCloud.redis Installs redis on a server
    13. AlbanAndrieu.java Manage Java installation
    14. alikins.php_pecl PHP PECL extension installation.
    15. alikins.php_redis PhpRedis support for Linux
    16. alikins.redis Redis for Linux
    17. andrewrothstein.redis builds Redis from src and installs
    18. anjia0532.ansible_beats Beats for Linux
    1. [root@86-5-master ~]# ansible-galaxy search --author abarrak
    2. Found 3 roles matching your search:
    3. Name Description
    4. ---- -----------
    5. abarrak.docker_server_role Ansible role to install and expose docker server on RHEL
    6. abarrak.plik_ansible_role Ansible role to install and configure plik file server.
    7. abarrak.redis_ansible_role Ansible role to install and configure redis instances based on Bitnami's chart.
    8. [root@86-5-master ~]#

    ansible-galaxy info子命令显示与角色相关的更多详细信息。Ansible Galaxy从多个位置获取这一信息,包括角色的meta/main.yml文件及其GigHub存储库

    1. [root@86-5-master ~]# ansible-galaxy info geerlingguy.redis
    2. Role: geerlingguy.redis
    3. 平台说明 description: Redis for Linux
    4. 是否能用 active: True
    5. 特征码 commit: 4f6fbdff6b566a596b2eaac168f88be820d4bbc5
    6. 忽略 commit_message: Ignore the tyranny of ansible-lint rule 106.
    7. 提交的url commit_url: https://api.github.com/repos/geerlingguy/ansible-role-red>
    8. 所属公司 company: Midwestern Mac, LLC
    9. 创建时间 created: 2014-03-06T16:48:12.451903Z
    10. 下载次数 download_count: 378170
    11. 转载次数 forks_count: 131
    12. 放置位置 github_branch: master
    13. github_repo: ansible-role-redis
    14. github_user: geerlingguy
    15. id: 468
    16. 进口 imported: 2020-09-18T15:06:33.499261-04:00
    17. is_valid: True
    18. issue_tracker_url: https://github.com/geerlingguy/ansible-role-redis/>
    19. 许可 license: license (BSD, MIT)
    20. min_ansible_version: 2.4
    21. modified: 2020-09-18T19:06:33.507214Z
    22. open_issues_count: 6
    23. 路径 path: ('/root/.ansible/roles', '/usr/share/ansible/roles', '/etc/ansi>
    24. role_type: ANS
    25. stargazers_count: 161
    26. travis_status_url: https://travis-ci.org/geerlingguy/ansible-role-red>
    27. (END)

    从Ansible Galaxy安装角色,ansible-galaxy install,从Ansible Galaxy下载角色,并将它安装到控制节点本地,默认为Ansible设置的默认roles_path,~/.ansible/roles目录。默认的roles_path可能会被用户当前Ansible配置文件或环境变量ANSIBLE_ROLES_PATH覆盖

    1. [root@86-5-master ~]# ansible-galaxy install geerlingguy.mysql
    2. [root@86-5-master ~]# ll /root/.ansible/roles/geerlingguy.mysql/ # 下载成功后,默认在/root/.ansible/roles/
    3. 总用量 16
    4. drwxr-xr-x 2 root root 22 1018 13:02 defaults
    5. drwxr-xr-x 2 root root 22 1018 13:02 handlers
    6. -rw-rw-r-- 1 root root 1080 830 22:40 LICENSE
    7. drwxr-xr-x 2 root root 50 1018 13:02 meta
    8. drwxr-xr-x 3 root root 21 1018 13:02 molecule
    9. -rw-rw-r-- 1 root root 9056 830 22:40 README.md
    10. drwxr-xr-x 2 root root 231 1018 13:02 tasks
    11. drwxr-xr-x 2 root root 67 1018 13:02 templates
    12. drwxr-xr-x 2 root root 147 1018 13:02 vars
    13. [root@86-5-master ~]# ansible-galaxy install geerlingguy.mysql # 在执行提示已经下载了
    14. [WARNING]: - geerlingguy.mysql (4.1.0) is already installed - use --force to change version to unspecified

    用户可以通过使用-p 选项,指定具体的目录来安装角色

    1. [root@ansible project]# ls
    2. playbook.yml roles
    3. [root@ansible project]# ansible-galaxy install geerlingguy.redis -p roles/
    4. - downloading role 'redis', owned by geerlingguy
    5. - downloading role from https://github.com/geerlingguy/ansible-role-redis/archive/1.6.0.tar.gz
    6. - extracting geerlingguy.redis to /project/roles/geerlingguy.redis
    7. - geerlingguy.redis (1.6.0) was installed successfully
    8. [root@ansible project]# ls roles/
    9. geerlingguy.redis httpd
    10. [root@ansible project]# pwd
    11. /project

    根据某一文本文件中的定义来安装一个角色列表。src指定角色的来源,本例中为来自Ansible Galaxy的geerlingguy.redis角色。version属性是可选的,指定要安装的角色版本,本例中为1.5.0。例如,一个用于安装geerlingguy.redis的简单requirements.yml可能类似于如下:

    1. [root@ansible roles]# rm -rf geerlingguy.redis/ //先删掉刚下载的角色
    2. [root@ansible roles]# rm -rf robertdebock.httpd/
    3. [root@86-5-master project]# pwd
    4. /root/project
    5. [root@86-5-master project]# ll
    6. drwxr-xr-x 2 root root 6 1020 03:04 roles
    7. [root@ansible project]# vi roles/requirements.yml //写个文件添加要下载的角色
    8. - src: geerlingguy.redis # 下载geerlingguy人的redis项目,在sraech --author中可找
    9. - src: robertdebock.httpd # 下载robertdebock人的httpd项目,在sraech --author中可找

    -r指定要安装文件的内容,-p指定安装位置

    1. [root@ansible project]# ansible-galaxy install -r roles/requirements.yml -p roles/
    2. - downloading role 'redis', owned by geerlingguy
    3. - downloading role from https://github.com/geerlingguy/ansible-role-redis/archive/1.6.0.tar.gz
    4. - extracting geerlingguy.redis to /project/roles/geerlingguy.redis
    5. - geerlingguy.redis (1.6.0) was installed successfully
    6. - downloading role 'httpd', owned by robertdebock
    7. - downloading role from https://github.com/robertdebock/ansible-role-httpd/archive/5.3.0.tar.gz
    8. - extracting robertdebock.httpd to /project/roles/robertdebock.httpd
    9. - robertdebock.httpd (5.3.0) was installed successfully
    10. - src: geerlingguy.redis
    11. version: "1.5.0"
    12. [root@ansible project]# ls roles/ //查看,成功安装角色
    13. geerlingguy.redis httpd requirements.yml robertdebock.httpd

    重要
    应当在requirements.yml文件中指定角色版本,特别是生产环境中的playbook。
    如果不指定版本,将会获取角色的最新版本。如果作者对角色做出了更改,并与用户的playbook不兼容,这可能会造成自动化失败或其他问题

    用户可以使用ansible-galaxy来安装不在Ansible Galaxy中的角色。可以在私有的Git存储库或Web服务器上托管自有的专用或内部角色。下例演示了如何利用各种远程来源配置要求文件

    1. [root@localhost project]# cat roles/requirements.yml
    2. # from Ansible Galaxy, using the latest version
    3. - src: geerlingguy.redis
    4. # from Ansible Galaxy, overriding the name and using a specific version
    5. - src: geerlingguy.redis
    6. version: "1.5.0"
    7. name: redis_prod # 自定义名字
    8. # from any Git-based repository, using HTTPS
    9. - src: https://gitlab.com/guardianproject-ops/ansible-nginx-acme.git
    10. scm: git
    11. version: 56e00a54
    12. name: nginx-acme
    13. # from any Git-based repository, using SSH
    14. - src: git@gitlab.com:guardianproject-ops/ansible-nginx-acme.git
    15. scm: git
    16. version: master
    17. name: nginx-acme-ssh
    18. # from a role tar ball, given a URL
    19. # supports 'http', 'https', or 'file' protocols
    20. - src: file:///opt/local/roles/myrole.tar
    21. name: myrole

    src关键字指定Ansible Galaxy角色名称。如果角色没有托管在Ansible Galaxy中,则src关键字将指明角色的URL

    如果角色托管在来源控制存储库中,则需要使用scm属性。ansible-galaxy命令能够从基于git或mercurial的软件存储库下载和安装角色。基于Git的存储库要求scm值为git,而托管在Mercurial存储库中的角色则要求值为hg。如果角色托管在Ansible Galaxy中,或者以tar存档形式托管在Web服务器上,则省略scm关键字

    name关键字用于覆盖角色的本地名称。version关键字用于指定角色的版本。version关键字可以是与严自角色的软件存储库的分支、标记或提交哈希对应的任何值
     

    管理下载的角色

    ansible-galaxy命令也可管理本地的角色,如位于playbook项目的roles目录中的角色。ansible-galaxy list子命令列出本地找到的角色

    1. [root@ansible project]# ansible-galaxy list
    2. # /root/.ansible/roles
    3. - geerlingguy.redis, 1.6.0
    4. # /usr/share/ansible/roles
    5. - linux-system-roles.kdump, (unknown version)
    6. - linux-system-roles.network, (unknown version)
    7. - linux-system-roles.postfix, (unknown version)
    8. - linux-system-roles.selinux, (unknown version)
    9. - linux-system-roles.storage, (unknown version)
    10. - linux-system-roles.timesync, (unknown version)
    11. - rhel-system-roles.kdump, (unknown version)
    12. - rhel-system-roles.network, (unknown version)
    13. - rhel-system-roles.postfix, (unknown version)
    14. - rhel-system-roles.selinux, (unknown version)
    15. - rhel-system-roles.storage, (unknown version)
    16. - rhel-system-roles.timesync, (unknown version)
    17. # /etc/ansible/roles
    1. [root@ansible project]# mv roles/* /etc/ansible/roles/ //把所有角色移动到能搜索到的角色目录下
    2. [root@ansible project]# ansible-galaxy list
    3. # /root/.ansible/roles
    4. - geerlingguy.redis, 1.6.0
    5. # /usr/share/ansible/roles
    6. - linux-system-roles.kdump, (unknown version)
    7. - linux-system-roles.network, (unknown version)
    8. - linux-system-roles.postfix, (unknown version)
    9. - linux-system-roles.selinux, (unknown version)
    10. - linux-system-roles.storage, (unknown version)
    11. - linux-system-roles.timesync, (unknown version)
    12. - rhel-system-roles.kdump, (unknown version)
    13. - rhel-system-roles.network, (unknown version)
    14. - rhel-system-roles.postfix, (unknown version)
    15. - rhel-system-roles.selinux, (unknown version)
    16. - rhel-system-roles.storage, (unknown version)
    17. - rhel-system-roles.timesync, (unknown version)
    18. # /etc/ansible/roles //搜的刚下载的两个角色
    19. - geerlingguy.redis, 1.6.0
    20. - httpd, (unknown version)
    21. - robertdebock.httpd, 5.3.0

    可以使用ansible-galaxy remove子命令本地删除角色

    1. [root@ansible roles]# ansible-galaxy remove geerlingguy.redis
    2. [root@ansible roles]# ansible-galaxy list

    在playbook中使用下载并安装的角色的方式与任何其他角色都一样。在roles部分中利用其下载的角色名称来加以引用。如果角色不在项目的roles目录中,则将检查roles_path来查看角色是否安装在了其中一个目录中,将使用第一个匹配项。以下use-role.ymlplaybook引用了redis_prod和geerlingguy.redis角色:

    1. [root@localhost project]# cat use-role.yml
    2. ---
    3. - name: use redis_prod for prod machines
    4. hosts: redis_prod_servers
    5. remote_user: devops
    6. become: True
    7. roles:
    8. - redis_prod
    9. - name: use geerlingguy.redis for Dev machines
    10. hosts: redis_dev_servers
    11. remote_user: devops
    12. become: True
    13. roles:
    14. - geerlingguy.redis

    此playbook使不同版本的geerlingguy.redis角色应用到生产和开发服务器。借助这种方式可以对角色更改进行系统化测试和集成,然后再部署到生产服务器上。如果角色的近期更改造成了问题,则借助版本控制来开发角色,就能回滚到过去某一个稳定的角色版本

    五、Ansible 的模块

    1、Command 模块

    1. 格式:ansible 类 -m command -a '命令'
    2. 例如:ansible srvs -m command -a 'systemctl restart mysqld'
    3. 他是一个默认模块,所以可以省略-m command
    1. [root@86-5-master ~]# ansible-doc -s command
    2. - name: Execute commands on targets
    3. command:
    4. argv: # 将命令作为列表而不是字符串传递。使用“argv”避免引用否则会解释不正确(例如“用户名”)。只有字符串或列表
    5. chdir: # 在运行命令之前,请切换到此目录
    6. cmd: # 要运行的命令
    7. creates: # 文件名或(自2.0以来)glob模式。如果它已经存在,则此步骤不会运行
    8. free_form: # 命令模块采用自由格式命令运行。没有名为“free form”的实际参数
    9. removes: # 文件名或(自2.0以来)glob模式。如果它已经存在,则将运行此步骤。
    10. stdin: # 将命令的stdin直接设置为指定值
    11. stdin_add_newline: # If set to `yes', append a newline to stdin data.
    12. strip_empty_ends: # Strip empty lines from the end of stdout/stderr in result.
    13. warn: # Enable or disable task warnings.

    案例:

    1. [root@86-5-master ~]# ansible dbserver -m command -a 'chdir=/etc cat redhat-release' # 文件在/etc/redhat-release,使用chdir=/etc 等价于 cd /etc
    2. 192.168.86.6 | CHANGED | rc=0 >>
    3. CentOS Linux release 7.5.1804 (Core)
    4. 86-6-slave | CHANGED | rc=0 >>
    5. CentOS Linux release 7.5.1804 (Core)
    1. [root@86-5-master ~]# ansible dbserver -m command -a 'creates=/etc/redhat-release chdir=/etc cat redhat-release'
    2. 192.168.86.6 | SUCCESS | rc=0 >>
    3. skipped, since /etc/redhat-release exists
    4. 86-6-slave | SUCCESS | rc=0 >>
    5. skipped, since /etc/redhat-release exists
    6. [root@86-5-master ~]#
    7. [root@86-5-master ~]# ansible dbserver -m command -a 'removes=/etc/redhat-release chdir=/etc cat redhat-release'
    8. 192.168.86.6 | CHANGED | rc=0 >>
    9. CentOS Linux release 7.5.1804 (Core)
    10. 86-6-slave | CHANGED | rc=0 >>
    11. CentOS Linux release 7.5.1804 (Core)
    12. [root@86-5-master ~]#

    缺点:不识别通配符(* .* ^ 等等)、重定向(echo)、管道符( | )、变量 ($hostname) 等等

    2、Shell 模块

    功能:和 Command 相似,相对 Command 没有过多的限制 

    1. 格式:ansible 类 -m shell -a '命令'
    2. 例如:ansible srvs -m shell -a 'systemctl restart mysqld'
    1. [root@86-5-master ~]# ansible dbserver -m shell -a 'echo 123456|passwd --stdin jerry'
    2. 192.168.86.6 | CHANGED | rc=0 >>
    3. 更改用户 jerry 的密码 。
    4. passwd:所有的身份验证令牌已经成功更新。
    5. 86-6-slave | CHANGED | rc=0 >>
    6. 更改用户 jerry 的密码 。
    7. passwd:所有的身份验证令牌已经成功更新。
    1. [root@86-5-master ~]# ansible-doc -s shell
    2. - name: Execute shell commands on targets
    3. shell:
    4. chdir: # Change into this directory before running the command.
    5. cmd: # The command to run followed by optional arguments.
    6. creates: # A filename, when it already exists, this step will *not* be run.
    7. executable: # Change the shell used to execute the command. This expects an absolute path to the executable.
    8. free_form: # The shell module takes a free form command to run, as a string. There is no actual parameter named 'free
    9. form'. See the examples on how to use this module.
    10. removes: # A filename, when it does not exist, this step will *not* be run.
    11. stdin: # Set the stdin of the command directly to the specified value.
    12. stdin_add_newline: # Whether to append a newline to stdin data.
    13. warn: # Whether to enable task warnings.
    14. [root@86-5-master ~]#

    既然 shell 模块比 Command好,如果修改默认模块为 shell 

    1. [root@86-5-master ~]# grep "module_name" /etc/ansible/ansible.cfg
    2. #module_name = command
    3. [root@86-5-master ~]# vi /etc/ansible/ansible.cfg # 修改为shell
    4. module_name = shell

    3、Script 模块

    功能:将远程机器上运行 ansible 服务器上的脚本

    1. [root@86-5-master ansible_playbook]# vi test.sh
    2. echo "My hostname is `echo $HOSTNAME`"
    3. [root@86-5-master ansible_playbook]# chmod +x test.sh
    4. [root@86-5-master ansible_playbook]# ./test.sh
    5. My hostname is 86-5-master
    1. [root@86-5-master ansible_playbook]# ansible-doc -s script
    2. - name: Runs a local script on a remote node after transferring it
    3. script:
    4. chdir: # Change into this directory on the remote node before running the script.
    5. cmd: # Path to the local script to run followed by optional arguments.
    6. creates: # A filename on the remote node, when it already exists, this step will *not* be run.
    7. decrypt: # This option controls the autodecryption of source files using vault.
    8. executable: # Name or path of a executable to invoke the script with.
    9. free_form: # Path to the local script file followed by optional arguments.
    10. removes: # A filename on the remote node, when it does not exist, this step will *not* be run.
    11. [root@86-5-master ansible_playbook]#
    [root@86-5-master ansible_playbook]# ansible dbserver -m script -a '/root/ansible_playbook/test.sh'

    4、Copy模块

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

    1. # 如果目标存在,默认覆盖
    2. ansible srv -m copy -a "src=/root/test.sh dest=/tmp/test2.sh"
    3. # 拷贝过去,如果目标存在,先备份,在覆盖
    4. ansible dbserver -m copy -a "src=/root/ansible_playbook/test.sh dest=/tmp/test2.sh backup=yes"
    5. [root@86-6-slave tmp]# ll
    6. -rw-r--r-- 1 root root 50 1018 17:29 test2.sh
    7. -rw-r--r-- 1 root root 39 1018 17:28 test2.sh.6765.2022-10-18@17:29:46~
    8. # 可以修改其权限,owner所属主、mode=权限
    9. ansible srv -m copy -a "src=/root/test.sh dest=/tmp/test2.sh owner=jerry mode=600"
    10. [root@86-6-slave tmp]# ll
    11. -rw------- 1 jerry root 50 1018 17:29 test2.sh
    1. # 指定内容,直接生成目标文件
    2. ansible dbserver -m copy -a "content='test content\n' dest=/tmp/test.txt"
    3. [root@86-6-slave tmp]# cat /tmp/test.txt
    4. test content
    1. # 复制/etc/下的文件。不包括/etc/目录自身
    2. ansible dbserver -m copy -a "src=/etc/ dest=/backup"
    1. # 拷贝文件夹
    2. ansible dbserver -m copy -a "src=/etc/sysconfig dest=/backup1/"
    3. [root@86-6-slave /]# ll /backup1/*
    4. -rw-r--r-- 1 root root 260 1018 17:44 anaconda
    5. -rw-r--r-- 1 root root 483 1018 17:44 authconfig
    6. drwxr-xr-x 2 root root 43 1018 17:44 cbq
    7. -rw-r--r-- 1 root root 150 1018 17:44 cpupower

    5、Fetch模块

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

    1. [root@86-5-master ansible_playbook]# ansible-doc -s fetch
    2. - name: Fetch files from remote nodes
    3. fetch:
    4. dest: # (required) A directory to save the file into. For example, if the `dest' directory is `/backup' a `src' file
    5. named `/etc/profile' on host `host.example.com', would be saved into
    6. `/backup/host.example.com/etc/profile'. The host name is based on the
    7. inventory name.
    8. fail_on_missing: # When set to `yes', the task will fail if the remote file cannot be read for any reason. Prior to Ansible 2.5,
    9. setting this would only fail if the source file was missing. The default was
    10. changed to `yes' in Ansible 2.5.
    11. flat: # Allows you to override the default behavior of appending hostname/path/to/file to the destination. If `dest'
    12. ends with '/', it will use the basename of the source file, similar to the
    13. copy module. This can be useful if working with a single host, or if
    14. retrieving files that are uniquely named per host. If using multiple hosts
    15. with the same filename, the file will be overwritten for each host.
    16. src: # (required) The file on the remote system to fetch. This `must' be a file, not a directory. Recursive fetching
    17. may be supported in a later release.
    18. validate_checksum: # Verify that the source and destination checksums match after the files are fetched.
    19. [root@86-5-master ansible_playbook]#
    1. [root@86-5-master ansible_playbook]# ansible dbserver -m fetch -a "src=/etc/redhat-release dest=/tmp/"
    2. [root@86-5-master ansible_playbook]# ll /tmp/
    3. drwxr-xr-x 3 root root 17 1018 17:48 192.168.86.6
    4. drwxr-xr-x 3 root root 17 1018 17:48 86-6-slave
    5. [root@86-5-master ansible_playbook]# ll /tmp/86-6-slave/
    6. drwxr-xr-x 2 root root 28 1018 17:48 etc
    7. [root@86-5-master 86-6-slave]# ll /tmp/86-6-slave/etc/
    8. -rw-r--r-- 1 root root 38 1018 17:48 redhat-release

    6、File 模块

    功能:设置文件属性,比如所属主、组、权限等

    1. # 创建空文件
    2. ansible dnbserver -m file -a "path=/data/test.txt state=touch" 创建文件
    3. ansible dnbserver -m file -a "path=/data/test.txt state=absent" 删除文件
    4. ansible dnbserver -m file -a "path=/data/test.sh owner=jerry mode=755" 修改文件所属主、组
    5. # 创建目录
    6. ansible dnbserver -m file -a "path=/data/mysql state=directory owner=mysql group=mysql"
    7. # 创建软连接
    8. ansible dnbserver -m file -a 'src=/data/testfile dest=/data/testfile-link state=link'
    1. [root@86-5-master ~]# ansible-doc -s file
    2. - name: Manage files and file properties
    3. file:
    4. state: #如果是“absent”,代表删除,目录将被递归删除,文件或符号链接将被取消链接。
    5. #如果是“touch”(1.4中新增),代表创建
    6. #如果为“directory”,则将创建所有中间子目录(如果它们不存在)。
    7. #如果为“link”,将创建软连接或更改软连接符号
    8. recurse: # 递归设置目录内容的指定文件属性。这仅适用于“state”设置`directory”。

    8、unarchive 模块

    功能:解包解压缩

    实现两种方法:
    1、将ansible主机上的压缩包传到远程主机后解压缩至特定目录,设置copy=yes
    2、将远程主机上的某个压缩包解压缩到指定路径下,设置copy=no

    参数:

    copy: 默认是yes,当copy=yes,拷贝的文件是从ansible主机复制到远程主机上,如果设置为copy=no,会在远程主机上 寻找src源文件
    remote_src: 和copy功能一样且互斥,yes表示在远程主机,不在ansible主机,no表示文件在ansible主机上
    src: 源路径,可以是ansible主机上的路径,也可以是远程主机上的路径,如果是远程主机上的路径,则需要设置copy=no
    dest: 远程主机上的目标路径
    mode: 设置解压缩后的文件权限

    传递解包

    1. # 如果dest没有/root/ansible/目录则会报错,修改owner group是递归
    2. ansible dbserver -m unarchive -a "src=/root/ansible-2.9.5.tar.gz dest=/root/ansible/ owner=jerry group=jerry"
    3. [root@86-6-slave ~]# ll /root/
    4. drwxr-xr-x 3 root root 27 1019 05:37 ansible
    5. [root@86-6-slave ~]# ll /root/ansible/
    6. drwxr-xr-x 12 jerry jerry 320 214 2020 ansible-2.9.5
    7. [root@86-6-slave ~]# ll /root/ansible/ansible-2.9.5/
    8. drwxr-xr-x 2 jerry jerry 243 214 2020 bin
    9. drwxr-xr-x 2 jerry jerry 53 214 2020 changelogs
    10. drwxr-xr-x 3 jerry jerry 40 214 2020 contrib
    1. [root@86-5-master ~]# ansible dbserver -m copy -a 'src=/root/ansible-2.9.5.tar.gz dest=/root'
    2. [root@86-5-master ~]# ansible dbserver -m unarchive -a "src=/root/ansible-2.9.5.tar.gz dest=/root/ansible/ copy=no"
    3. [root@86-6-slave ~]# ll /root/
    4. drwxr-xr-x 3 root root 27 1019 05:45 ansible
    5. -rw-r--r-- 1 root root 14186885 1019 05:44 ansible-2.9.5.tar.gz
    6. [root@86-6-slave ~]# ll /root/ansible
    7. drwxr-xr-x 12 root root 320 214 2020 ansible-2.9.5

    9、archive 模块

    功能:打包压缩

    1. # -m archive 打包
    2. # path=/tmp/ ansible主机目录
    3. # dest=/root/tmp.tar.gz 打包位置
    4. # format=bz2 打包类型
    5. ansible dbserver -m archive -a 'path=/tmp/ dest=/root/tmp.tar.gz format=bz2 owner=jerry mode=0600'
    6. [root@86-6-slave ~]# ll /root/
    7. -rw------- 1 jerry root 140249 1019 05:54 tmp.tar.gz

    10、Hostname 模块

    功能:管理主机名

    1. 真对特定主机、变量修改名字
    2. [root@86-5-master ~]# ansible dbserver -m hostname -a "name=centos7-ans"
    3. [root@86-6-slave ~]# bash
    4. [root@centos7-ans ~]#

    11、Cron 模块

    功能:计划任务

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

    1. # 备份数据库脚本
    2. [root@86-5-master ansible_playbook]# pwd
    3. /root/ansible_playbook
    4. [root@86-5-master ansible_playbook]# vi mysql_backup.sh
    5. mysqldump -A -F --single-transaction --master-data=2 -q -uroot |gzip > /data/mysql_`data +%F_%T`.sql.gz
    6. # 创建脚本任务
    7. 其中没有定义day,month 代表* * 每天每月,hour=2 minute=30 代表每2小时30分钟
    8. name起个名字,job 是执行的任务,定期在此机器上执行的ansible上的这个脚本
    9. 注意,job后的脚本必须在远程主机上有
    10. ansible 192.168.78.6 -m cron -a "hour=2 minute=30 weekday=1-5 name='backup mysql' job=/root/ansible_playbook/mysql_backup.sh"
    11. [root@86-6-slave ~]# crontab -l
    12. #Ansible: backup mysql
    13. 30 2 * * 1-5 /root/ansible_playbook/mysql_backup.sh
    14. [root@86-6-slave ~]#
    15. # 创建命令任务
    16. 其中没有定义hour,day,month,weekday 代表* * * * 每时每天每月每周,minute=*/5 代表每5分钟
    17. ansible dbserver -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 & >/dev/null' name=Synctime "
    18. [root@86-6-slave ~]# crontab -l
    19. #Ansible: Synctime
    20. */5 * * * * /usr/sbin/ntpdate 172.20.0.1 & >/dev/null
    21. [root@86-6-slave ~]#
    22. # 禁用任务
    23. ansible dbserver -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 & >/dev/null' name=Synctime disabled=yes"
    24. [root@86-6-slave ~]# crontab -l
    25. #Ansible: backup mysql
    26. 30 2 * * 1-5 /root/ansible_playbook/mysql_backup.sh
    27. #Ansible: Synctime
    28. #*/5 * * * * /usr/sbin/ntpdate 172.20.0.1 & >/dev/null
    29. # 启动计划任务
    30. ansible dbserver -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 & >/dev/null' name=Synctime disabled=no"

    总结:Cron 模块就是修改的本地的 crontab 定时任务,所以,创建就是添加。禁用就是注释。启动就是去掉注释

    12、Yum 模块

    功能:管理软件包,只支持RHEL,Centos,fedora,不支持 Ubuntu 其他版本

    1. [root@86-5-master ~]# ansible-doc -s yum
    2. state: # 安装(“present”还是“installed”,“latest”),还是删(“absent”或“removed”)软件包
    3. # latest 代表安装的最新版,present 和 installed 可以指定版本,如果不指定则尽量也是最新版。
    4. # absent 和 removed 将删除指定的包

    安装,默认安装后不会协助启动

    1. # yum install -y httpd,如果本机已经存在httpd,则不执行
    2. [root@86-5-master ~]# ansible dbserver -m yum -a "name=httpd state=present"
    3. # 如果要安装多个,直接用,隔离 name=libaio,perl-Date-Dumper,per-Getopt-Long
    4. [root@86-6-slave ~]# rpm -qa httpd
    5. 部署后
    6. [root@86-6-slave ~]# rpm -qa httpd
    7. httpd-2.4.6-97.el7.centos.5.x86_64
    8. [root@86-6-slave ~]# rpm -qi httpd
    9. Name : httpd
    10. Version : 2.4.6
    11. Release : 97.el7.centos.5
    12. Architecture: x86_64
    13. Install Date: 20221019日 星期三 074024
    14. Group : System Environment/Daemons
    15. Size : 9821136
    16. License : ASL 2.0
    17. Signature : RSA/SHA256, 20220325日 星期五 022156秒, Key ID 24c6a8a7f4a80eb5
    18. Source RPM : httpd-2.4.6-97.el7.centos.5.src.rpm
    19. Build Date : 20220324日 星期四 225942
    20. Build Host : x86-02.bsys.centos.org
    21. Relocations : (not relocatable)
    22. Packager : CentOS BuildSystem <http://bugs.centos.org>
    23. Vendor : CentOS
    24. URL : http://httpd.apache.org/
    25. Summary : Apache HTTP Server
    26. Description :
    27. The Apache HTTP Server is a powerful, efficient, and extensible
    28. web server.

    卸载

    1. [root@86-5-master ~]# ansible dbserver -m yum -a "name=httpd state=removed"
    2. [root@86-6-slave ~]# rpm -qa httpd
    3. [root@86-6-slave ~]#

    13、Service 模块

    功能:管理服务,启动查看服务,使用的是service/systemctl start 服务

    1. [root@86-5-master ~]# ansible-doc -s service
    2. - name: Manage services
    3. service:
    4. arguments: # Additional arguments provided on the command line.
    5. enabled: # Whether the service should start on boot. *At least one of state and enabled are required.*
    6. name: # (required) Name of the service.
    7. pattern: # If the service does not respond to the status command, name a substring to look for as would be found in the
    8. output of the `ps' command as a stand-in for a status result. If the string is
    9. found, the service will be assumed to be started.
    10. runlevel: # For OpenRC init scripts (e.g. Gentoo) only. The runlevel that this service belongs to.
    11. sleep: # If the service is being `restarted' then sleep this many seconds between the stop and start command. This
    12. helps to work around badly-behaving init scripts that exit immediately after
    13. signaling a process to stop. Not all service managers support sleep, i.e when
    14. using systemd this setting will be ignored.
    15. state: # started/stopped/enabled
    16. use: # The service module actually uses system specific modules, normally through auto detection, this setting can
    17. force a specific module. Normally it uses the value of the
    18. 'ansible_service_mgr' fact and falls back to the old 'service' module when
    19. none matching is found.
    20. [root@86-5-master ~]#

    yum 安装httpd,service启动httpd

    1. # 没有启动80端口
    2. [root@86-6-slave ~]# netstat -anp |grep 80
    3. unix 2 [ ACC ] STREAM LISTENING 15809 636/VGAuthService /var/run/vmware/guestServicePipe
    4. unix 3 [ ] STREAM CONNECTED 17780 997/sshd
    5. unix 2 [ ] DGRAM 18053 999/rsyslogd
    6. # 启动httpd
    7. [root@86-5-master ~]# ansible dbserver -m service -a "name=httpd state=started"
    8. # 启动80端口
    9. [root@86-6-slave ~]# netstat -anp |grep 80
    10. tcp6 0 0 :::80 :::* LISTEN 23974/httpd
    11. unix 2 [ ACC ] STREAM LISTENING 15809 636/VGAuthService /var/run/vmware/guestServicePipe
    12. unix 3 [ ] STREAM CONNECTED 17780 997/sshd
    13. unix 2 [ ] DGRAM 18053 999/rsyslogd
    14. [root@86-6-slave ~]# ps -ef |grep httpd
    15. root 23974 1 0 07:49 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
    16. apache 23975 23974 0 07:49 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
    17. apache 23976 23974 0 07:49 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
    18. apache 23977 23974 0 07:49 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
    19. apache 23980 23974 0 07:49 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
    20. apache 23981 23974 0 07:49 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
    21. root 23999 22870 0 07:49 pts/0 00:00:00 grep --color=auto httpd
    22. [root@86-6-slave ~]# systemctl status httpd
    23. ● httpd.service - The Apache HTTP Server
    24. Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
    25. Active: active (running) since 三 2022-10-19 07:49:10 CST; 47s ago
    26. Docs: man:httpd(8)
    27. man:apachectl(8)
    28. Main PID: 23974 (httpd)
    29. Status: "Total requests: 0; Current requests/sec: 0; Current traffic: 0 B/sec"
    30. CGroup: /system.slice/httpd.service
    31. ├─23974 /usr/sbin/httpd -DFOREGROUND
    32. ├─23975 /usr/sbin/httpd -DFOREGROUND
    33. ├─23976 /usr/sbin/httpd -DFOREGROUND
    34. ├─23977 /usr/sbin/httpd -DFOREGROUND
    35. ├─23980 /usr/sbin/httpd -DFOREGROUND
    36. └─23981 /usr/sbin/httpd -DFOREGROUND
    37. 1019 07:49:10 86-6-slave systemd[1]: Starting The Apache HTTP Server...
    38. 1019 07:49:10 86-6-slave httpd[23974]: AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.168.86.6. ...s message
    39. 10月 19 07:49:10 86-6-slave systemd[1]: Started The Apache HTTP Server.
    40. Hint: Some lines were ellipsized, use -l to show in full.

    设置 httpd 服务 enabled

    1. # 设置自启动httpd
    2. [root@86-5-master ~]# ansible dbserver -m service -a "name=httpd state=started enabled=yes"
    3. # 配置reload
    4. [root@86-5-master ~]# ansible dbserver -m service -a "name=httpd state=reload"
    5. # 修改httpd的80端口
    6. [root@86-5-master ~]# ansible dbserver -m shell -a "sed -i 's/^Listen 80$/Listen 8080/' /etc/httpd/conf/httpd.conf"
    7. # 重启httpd服务
    8. [root@86-5-master ~]# ansible dbserver -m service -a "name=httpd state=restarted"

    14、User 模块

    功能  :管理用户 

    1. 常见的参数:
    2. name:用户名,必选参数
    3. state=present|absent:创建账号或者删除账号,present表示创建,absent表示删除
    4. system=yes|no:是否为系统账号
    5. uid:用户uid
    6. group:用户基本组
    7. shell:默认使用的shell
    8. move_home=yes|no:如果设置的家目录已经存在,是否将已经存在的家目录进行移动
    9. password:用户的密码,建议使用加密后的字符串
    10. comment:用户的注释信息
    11. remove=yes|no:当state=absent时,是否删除用户的家目录
    1. # 创建用户
    2. # name用户名、comment描述、home家目录、group所属组(前提有这个组,使用Group模块)
    3. ansible 192.168.86.6 -m user -a "name=user1 comment='test user' uid=2048 home=/app/user1 group=root"
    4. # 创建用户
    5. # group所属组、groups属于多个组都有哪些
    6. # shell=/sbin/nologin 此账号禁止登陆系统无法su登录
    7. # system=yes 是不是系统账号
    8. # create_home=no 默认创建家目录,此位置指定没有家目录
    9. # non_unoque=yes uid是不是唯一性,可不可以重复。也就是Linux的-o 配合-u选项,不检查UID的唯一性,通常用来让两个用户使用相同的uid useradd 用户 -ou uid
    10. ansible 192.168.86.6 -m user -a "name=nginx comment=nginx uid=88 group=nginx groups="root,daeon" shell=/sbin/nologin system=yes create_home=no home=/data/nginx non_unoque=yes'
    11. # 删除用户及家目录等数据
    12. # state=absent删除用户
    13. # remove=yes删除家目录、邮箱等数据
    14. ansible 192.168.86.6 -m user -a "name=nginx state=absent remove=yes'

    15、Group 模块

    功能:管理组

    1. # 创建组
    2. [root@86-5-master ~]# ansible 192.168.86.6 -m group -a "name=nginx gid=88 system=yes"
    3. # 删除组
    4. [root@86-5-master ~]# ansible 192.168.86.6 -m group -a "name=nginx state=absent"

    16、Lineinfile 模块

    ansible 在使用 sed 进行替换的时候,经常会遇到需要转义的问题,而且ansible在遇到特殊符号进行替换,存在问题,无法正常替换。其实在ansible自身提供了两个模块:Lineinfile 模块和replacce模块,可以方便的进行替换

    功能:通过regexp匹配到带有此信息的最后一行,整行替换成 line=

    1. # path=指定修改那个文件
    2. # regexp=写正则表达式,表示修改哪行
    3. # line=写要替换的内容
    4. [root@86-6-slave ~]# cat /root/selinux_config
    5. # This file controls the state of SELinux on the system.
    6. SELINUX=disabled
    7. SELINUX=enforcing
    8. SELINUX=disable
    9. SELINUX=disabled 113
    10. [root@86-5-master ~]# ansible dbserver -m lineinfile -a "path=/root/selinux_config regexp='^SELINUX=' line='SELINUX=enforcing'"
    11. [root@86-6-slave ~]# cat selinux_config
    12. # This file controls the state of SELinux on the system.
    13. SELINUX=disabled
    14. SELINUX=enforcing
    15. SELINUX=disable
    16. SELINUX=enforcing

    删除匹配到的此信息所有行

    1. [root@86-6-slave ~]# cat selinux_config
    2. # This file controls the state of SELinux on the system
    3. SELINUX=disabled
    4. #SELINUX=disabled
    5. #SELINUX=enforcing
    6. [root@86-5-master ~]# ansible 192.168.86.6 -m lineinfile -a "dest=/root/selinux_config state=absent regexp='^#'"
    7. [root@86-6-slave ~]# cat selinux_config
    8. SELINUX=disabled
    9. [root@86-6-slave ~]#

    17、Replace 模块

    功能:该模块有点类似于sed命令,主要也是基于正则进行匹配和替换

    1. [root@86-6-slave ~]# vi /root/selinux_config
    2. SELINUX=disabled
    3. UUID123
    4. UUID456
    5. # ^(UUID.*) 以UUID开头的
    6. # #\1 其中\1代表()中的信息,也就是UUID.* ,#\1则代表在()之前添加一个#,就是sed 's/^(UUID.*)/#\1/'
    7. [root@86-5-master ~]# ansible 192.168.86.6 -m replace -a "path=/root/selinux_config regexp='^(UUID.*)' replace='#\1'"
    8. [root@86-6-slave ~]# cat selinux_config
    9. SELINUX=disabled
    10. #UUID123
    11. #UUID456
    12. # 去除#
    13. [root@86-5-master ~]# ansible 192.168.86.6 -m replace -a "path=/root/selinux_config regexp='^#(.*)' replace='\1'"

    如下可知,Replace只是替换正在匹配的信息,并不会替换整行

    1. [root@86-6-slave ~]# cat /root/selinux_config
    2. # This file controls the state of SELinux on the system.
    3. NUX=disabled
    4. SELINUX=enforcing
    5. SELINUX=disable
    6. SELINUX=disabled 113
    7. [root@86-5-master ~]# ansible 192.168.86.6 -m replace -a "path=/root/selinux_config regexp='^SELINUX=' replace='SELINUX=enforcing'"
    8. [root@86-6-slave ~]# cat selinux_config
    9. NUX=disabled
    10. SELINUX=enforcingenforcing
    11. SELINUX=enforcingdisable
    12. SELINUX=enforcingdisabled 113
    13. [root@86-6-slave ~]#
    14. [root@86-5-master ~]# ansible 192.168.86.6 -m replace -a "path=/root/selinux_config regexp='^SELINUX=.*' replace='SELINUX=enforcing'"
    15. [root@86-6-slave ~]# cat selinux_config
    16. NUX=disabled
    17. SELINUX=enforcing
    18. SELINUX=enforcing
    19. SELINUX=enforcing

    18、Setup 模块

    功能:收集远程主机的信息、硬件、系统、软件、网络设置等信息。

    后期写 playbook 时候可能会用到这些 facts 信息,可以直接将 facts 信息中的 key 以变量的形式使用 ,但是如果主机较多,Setup 模块会影响执行速度,所以 playbook 并不用的时候,可以使用 gather_facts:no 来禁止 Ansible 收集 facts 信息

    1. [root@86-5-master ~]# ansible 192.168.86.6 -m setup # 显示IP、挂载等等。
    2. [root@86-5-master ~]# ansible 192.168.86.6 -m setup |grep ansible_dis # 用处是可以根据当前系统的信息,决定执行的命令,比如Centos 执行的是yum ,Centos 执行的是dnf
    3. "ansible_distribution": "CentOS",
    4. "ansible_distribution_file_parsed": true,
    5. "ansible_distribution_file_path": "/etc/redhat-release",
    6. "ansible_distribution_file_variety": "RedHat",
    7. "ansible_distribution_major_version": "7",
    8. "ansible_distribution_release": "Core",
    9. "ansible_distribution_version": "7.5",
    10. [root@86-5-master ~]#

    查看指定的数值

    1. [root@86-5-master ~]# ansible 192.168.86.6 -m setup -a "filter=ansible_distribution_version"
    2. 192.168.86.6 | SUCCESS => {
    3. "ansible_facts": {
    4. "ansible_distribution_version": "7.5",
    5. "discovered_interpreter_python": "/usr/bin/python"
    6. },
    7. "changed": false
    8. }

    六、Playbook

    yaml 形式的文本文件,会通过编写 yaml,实现 Ansible 的各种模块调用
    playbook 由一个或者多个play组成

    1、yaml 格式

    List 列表

    1. 多元素组成,且所有元素前均使用'-'开头
    2. # A list of tasty fruits
    3. - Apple
    4. - Orange
    5. - Strawberry
    6. - Mango
    7. 可以写成一行
    8. [Apple,Orange,Strawberry,Mango]

    dict 字典

    1. key value 组成
    2. name : Example Developer
    3. job : Devolper
    4. skill : Elite
    5. 也可以写成一行
    6. {name : Example Developer,job : Devolper,skill : Elite}

    2、Playbook 核心元素

    1. Hosts    执行的远程主机列表
    2. Task    任务集,实现每个Playbook的调用,每个模块的使用
    3. Variables 内置变量或自定义变量在playbook中调用
    4. Templates 支持模板,可替换模板文件中的变量并实现一些简单逻辑的文件
    5. Handlers 和 notify 结合使用,由特定条件触发操作,满足条件方可执行,否则不执行。比如修改文件会触发另外动作的执行。
    6. Tags 标签给某个任务起名字,指定某条任务执行,可以实现挑出 playbook 中的部分任务起标签,然后执行标签,而不是所有的。用于选择运行playbook中的部分代码,
    7. ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此 ,有些 代码为 测试其确实没有发生变化的时间依然会非常的长。此时,如果确定其没有变化,就可以通过Tage跳过这些代码片段

    3、Hosts 组建 

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

    1. one.example.com
    2. one.example.com:two.example.com
    3. 192.168.1.50
    4. webserver:dbserver # 或者,两个组的并集
    5. webserver:&dbserver # 与,两个组的交集
    6. webserver:!dbserver # 在webserver组,但是不在dbserver组

    案例:

    - host:webserver:dbserver

    4、remote_user 组件

    remote_user:可用于Host 和 task 中,连接到远程主机上,使用什么身份执行操作。可以用于全局或者某任务,使用此身份。此外,可以在 sudo 时使用 sudo_user 指定 sudo 时切换的用户 。

    1. - hosts: webserver
    2. remote_user: root
    3. tasks:

    简单的playbook案例:

    1. ---
    2. - hosts: websrvs # 使用过websrvs的主机
    3. remote_user: root # 切换root身份执行后续操作
    4. tasks:
    5. - name: install httpd # 起个名字
    6. yum: name=httpd # 使用 yum 模块,安装httpd
    7. - name: start httpd
    8. service: name=httpd state=started enabled=yes # 使用service模块,启动httpd服务。并且设置为enabled

    5、playbook 命令执行

    格式:

    1. ansible-playbook yaml文件 参数
    2. 参数:
    3. --check -C # 执行前,运行检测语法,会提示可能会发生的错误,此过程不真正执行操作
    4. --list-hosts # 列出运行任务的主机
    5. --list-tags # 列出tag
    6. --list-tasks # 列出task
    7. --limit 主机列表 # 只针对主机列表中的主机执行
    8. -v -vv -vvv # 显示过程
    9. 解释:
    10. ansible-playbook file.yaml --limit 192.168.86.6
    11. ansible-playbook file.yaml --limit websrvs
    12. --limit 主机列表 # 只针对主机列表中的主机执行,什么意思,如下--limit 192.168.86.6 只针对websrvs下的192.168.86.6主机执行,而不是所有的主机都执行
    13. ---
    14. - hosts: websrvs # 使用过websrvs的主机
    15. remote_user: root # 切换root身份执行后续操作
    16. tasks:
    17. ansible-playbook file.yaml --check -C

    6、简单案例

    1、利用 Ploybook 创建 mysql 用户

    1. [root@86-5-master ansible_playbook]# cat mysql_user.yaml
    2. ---
    3. - hosts:dbserver
    4. remote_user: root
    5. tasks:
    6. - name: create group
    7. group: name=mysql system=yes gid=306
    8. - name: create user
    9. user: name=mysql shell=/sbin/nologon system=yes group=mysql uid=306 home=/data/mysql create_home=no

    检查语法有没有问题

    1. [root@86-5-master ansible_playbook]# ansible-playbook -C mysql_user.yaml
    2. PLAY [dbserver] *****************************************************************************************************************************
    3. TASK [Gathering Facts] **********************************************************************************************************************
    4. ok: [86-6-slave]
    5. ok: [192.168.86.6]
    6. 注释:一个问题,Facts 代表默认 playbook 会使用 Setup 模块收集你远程主机的信息,所以可以考虑添加gather_facts: no

    TASK [Gathering Facts] ,Facts 代表默认 playbook 会使用 Setup 模块收集你远程主机的信息,所以可以考虑添加gather_facts: no

    1. [root@86-5-master ansible_playbook]# cat mysql_user.yaml
    2. ---
    3. - hosts:dbserver
    4. remote_user: root
    5. gather_facts: no
    6. tasks:
    7. - name: create group
    8. group: name=mysql system=yes gid=306
    9. - name: create user
    10. user: name=mysql shell=/sbin/nologon system=yes group=mysql uid=306 home=/data/mysql create_home=no
    1. [root@86-5-master ansible_playbook]# ansible-playbook -C mysql_user.yaml
    2. PLAY [dbserver] *****************************************************************************************************************************
    3. TASK [create group] *************************************************************************************************************************
    4. changed: [86-6-slave]
    5. changed: [192.168.86.6]
    6. TASK [create user] **************************************************************************************************************************
    7. changed: [86-6-slave]
    8. changed: [192.168.86.6]
    9. PLAY RECAP **********************************************************************************************************************************
    10. 192.168.86.6 : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
    11. 86-6-slave : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
    12. [root@86-5-master ansible_playbook]#

    执行

    [root@86-5-master ansible_playbook]# ansible-playbook mysql_user.yaml
    1. [root@86-5-master ansible_playbook]# ansible dbserver -a "getent passwd mysql"
    2. 86-6-slave | CHANGED | rc=0 >>
    3. mysql:x:306:306::/data/mysql:/sbin/nologon
    4. [root@86-5-master ansible_playbook]# ansible dbserver -a "id mysql"
    5. 86-6-slave | CHANGED | rc=0 >>
    6. uid=306(mysql) gid=306(mysql) 组=306(mysql)
    7. [root@86-5-master ansible_playbook]#

    2、利用 Ploybook 安装和卸载 httpd

    安装

    1. [root@86-5-master ansible_playbook]# vi install_httpd.yaml
    2. ---
    3. # install httpd
    4. - hosts: dbserver
    5. remote_user: root
    6. gather_facts: no
    7. tasks:
    8. - name: Install httpd
    9. yum: name=httpd state=present
    10. - name: Install configure file
    11. copy: src=/root/httpd.conf dest=/etc/httpd/conf/
    12. - name:
    13. service: name=httpd state=stared enabled=yes

    卸载

    1. [root@86-5-master ansible_playbook]# vi install_nginx
    2. ---
    3. # install nginx
    4. - hosts: dbserver
    5. remote_user: root
    6. gather_facts: no
    7. tasks:
    8. - name: remove httpd
    9. yum: name=httpd state=absent
    10. - name: remove httpd user
    11. user: name=nginx state=absent
    12. - name: remove httpd group
    13. group: name=nginx state=absent
    14. - name: remove date file
    15. file: name=/etc/httpd state=absent

    3、利用 Ploybook 安装nginx

    1. [root@86-5-master ansible_playbook]# vi install_nginx
    2. ---
    3. # install nginx
    4. - hosts: dbserver
    5. remote_user: root
    6. gather_facts: no
    7. tasks:
    8. - name: add group nginx
    9. group: name=nginx system=yes
    10. - name: add user nginx
    11. user: name=nginx state=present group=nginx
    12. - name: Install nginx
    13. yum: name=nginx state=present
    14. - name: Start nginx
    15. service: name=nginx state=started enabled=yes

    通过检查可能有如下提示

    问题:ansible yum模块安装nginx,提示:No package matching 'nginx' found available, installed or updated

    解决方案:

    1. 在被管远程主机添加nginx仓库 ,
    2. 参考url: http://nginx.org/en/linux_packages.html#RHEL-CentOS
    3. vim /etc/yum.repos.d/nginx.repo
    4. [nginx-stable]
    5. name=nginx stable repo
    6. baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
    7. gpgcheck=1
    8. enabled=1
    9. gpgkey=https://nginx.org/keys/nginx_signing.key
    10. module_hotfixes=true
    11. [nginx-mainline]
    12. name=nginx mainline repo
    13. baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
    14. gpgcheck=1
    15. enabled=0
    16. gpgkey=https://nginx.org/keys/nginx_signing.key
    17. module_hotfixes=true

    安装部署

    1. [root@86-5-master ansible_playbook]# ansible-playbook -C install_nginx ^C
    2. [root@86-5-master ansible_playbook]# ansible-playbook install_nginx
    3. [root@86-6-slave ~]# rpm -qi nginx
    4. Name : nginx
    5. Epoch : 1
    6. Version : 1.22.0
    7. Release : 1.el7.ngx
    8. Architecture: x86_64
    9. Install Date: 20221019日 星期三 2024

    执行过的方案,下次是不会在执行,如下我们编写一个nginx的html文件,传递给远程端的默认网页位置

    1. [root@86-5-master ansible_playbook]# vi install_nginx
    2. ---
    3. # install nginx
    4. - hosts: dbserver
    5. remote_user: root
    6. gather_facts: no
    7. tasks:
    8. - name: add group nginx
    9. group: name=nginx system=yes
    10. - name: add user nginx
    11. user: name=nginx state=present group=nginx
    12. - name: Install nginx
    13. yum: name=nginx state=present
    14. - name: nginx Page
    15. copy: src=files/index.html dest=/usr/share/nginx/html # 代表当前目录下的files目录下的/index.html
    16. - name: Start nginx
    17. service: name=httpd state=restarted enabled=yes

    再次执行后发现,以前执行过的不发生改动。

    Ansible执行的时候根据结果会显示为绿色(成功执行),黄色(成功伴随状态改变)和红色(执行失败)等颜色,颜色的显示与changed的状态相关联,并可以在ansible.cfg中进行定制颜色的设定。

    8、playbok 的 limit

    默认ansible-playbook install_nginx  执行的是整个hosts

    1. [root@86-5-master ansible_playbook]# ansible-playbook --list-hosts install_nginx
    2. playbook: install_nginx
    3. play #1 (dbserver): dbserver TAGS: []
    4. pattern: ['dbserver']
    5. hosts (2):
    6. 192.168.86.6
    7. 86-6-slave

    如果只是想对 dbserver 下的主机清单执行

    [root@86-5-master ansible_playbook]# ansible-playbook --list-hosts install_nginx --limit dbserver

    如果只是想对 hosts下的192.168.86.6主机执行

    [root@86-5-master ansible_playbook]# ansible-playbook --list-hosts install_nginx --limit 192.168.86.6
    

    7、案例安装 mysql

    安装 mysql 5.6.46

    1、准备 mysql-5.6.46-linux-glibc2.12-×86_64.tar.gz  (/root/mysql-5.6.46-linux-glibc2.12-×86_64.tar.gz)

    2、准备my.cnf (/data/ansible/files/my.cnf)

    3、准备安全加固的脚本(/data/ansible/files/secure_mysql.sh)

    1. a)为root用户设置密码
    2. b)删除匿名账号
    3. c)取消root用户远程登录
    4. d)删除test库和对test库的访问权限
    5. e)刷新授权表使修改生效

    4、playbook 的 mysql_install.yaml

    1. [root@86-5-master ansible_playbook]# vi mysql_install.yaml
    2. ---
    3. # install mysql-5.6.46
    4. - hosts: dbserver
    5. remote_user: root
    6. tasks:
    7. - name: install package
    8. yum: name=libaio,perl-Date-Dumper,per-Getopt-Long
    9. - name: create mysql group
    10. group: name=mysql gid=306
    11. - name: create mysql user
    12. user: name=mysql uid=306 group=mysql shell=/sbin/nologin system=yes create_home=no home=/data/mysql
    13. - name: copy tar to remote host and file mode
    14. unarchive: src=/data/ansible/files/mysql-5.6.46-linux-glibc2.1286_64.tar.gz dest=/usr/local/ owner=root group=root
    15. - name: mkdir /usr/local/mysql
    16. file: src=/usr/local/mysql-5.6.46-linux-glibc2.1286_64 dest=/usr/local/mysql state=link
    17. - name: data dir
    18. shell: chdir=/usr/local/mysql/ ./scripts/mysql_install_db --datadir=/data/mysql --user=mysql # 脚本实现初始数据库导入
    19. tags: data # 打标签
    20. - name: config my.cnf
    21. copy: src=/data/ansible/files/my.cnf dest=/etc/my.cnf
    22. - name: service script
    23. shell: /bin/cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
    24. - name: enable service
    25. shell: /etc/init.d/mysqld start;chkconfig --add mysqld;chkconfig mysqld on
    26. tags: service
    27. - name: PATH variable
    28. copy: content='PATH=/usr/local/mysql/bin:$PATH' dest=/etc/profile.d/mysql.sh
    29. - name: secure script
    30. sripte: /data/ansible/files/secure_mysql.sh
    31. tags: script

    注意:在使用ansible-playbook -C 检查的时候,遇到检查软连接失败,是正常党的,因为我们是解压mysql-5.6.46后才生成的目录,而检查是不会解压缩,所以判断目录没有,软连接失败

    七、Pkaybook中使用 handlers 和 notify

    handlers 本质是 task list,类似于 Mysql 中的触发器触发行为,handlers 要求需要配合 notify , notify (通知) 就是触发器本身,handlers 触发的动作。当某件事发生之后,我可以让其通知触发器中的定义的一个行为,触发的行为在handlers 。notify 那个事件发生了,造成了触发器的执行。handlers 本质上就是一个task,多个task形成了task list,只不过这么多的task list不会互动执行,是需要notify对应的某个动作发生变化后,触发。

    简单案例

    比如监控配置文件,如果发生更改需要重新触发重启服务。

    1. ---
    2. - hosts: dbserver
    3. remote_user: root
    4. gather_facts: no
    5. tasks:
    6. - name: Install httpd
    7. yum: name=httpd state=present
    8. - name: Install configure file
    9. copy: src=files/httpd.conf dest=/etc/httpd/conf
    10. notify: restart httpd
    11. - name: ensure apache is running
    12. service: name=httpd state=started enabled=yes
    13. handlers:
    14. - name: restart httpd
    15. service: name=httpd state=restarted

    1. [root@86-5-master ansible_playbook]# pwd
    2. /root/ansible_playbook
    3. [root@86-5-master ansible_playbook]# cat http_handler.yaml
    4. ---
    5. - hosts: dbserver
    6. remote_user: root
    7. gather_facts: no
    8. tasks:
    9. - name: Install httpd
    10. yum: name=httpd state=present
    11. - name: Install configure file
    12. copy: src=files/httpd.conf dest=/etc/httpd/conf
    13. notify: restart httpd
    14. - name: ensure apache is running
    15. service: name=httpd state=started enabled=yes
    16. handlers:
    17. - name: restart httpd
    18. service: name=httpd state=restarted
    19. [root@86-5-master ansible_playbook]# yum install -y httpd # 本机安装httpd,以便获取httpd.conf
    20. [root@86-5-master ansible_playbook]# cp /etc/httpd/conf/httpd.conf files/
    21. [root@86-5-master ansible_playbook]# grep "Listen" files/httpd.conf # 对端口修改808081
    22. # Listen: Allows you to bind Apache to specific IP addresses and/or
    23. # Change this to Listen on specific IP addresses as shown below to
    24. #Listen 12.34.56.78:80
    25. Listen 8081
    26. [root@86-5-master ansible_playbook]# ansible-playbook -C http_handler.yaml # 检查
    27. [root@86-5-master ansible_playbook]# ansible-playbook http_handler.yaml --limit
    28. [root@86-5-master ansible_playbook]# ansible 192.168.86.6 -a "ss -ntl"
    29. 192.168.86.6 | CHANGED | rc=0 >>
    30. State Recv-Q Send-Q Local Address:Port Peer Address:Port
    31. LISTEN 0 128 *:80 *:*
    32. LISTEN 0 128 *:22 *:*
    33. LISTEN 0 100 127.0.0.1:25 *:*
    34. LISTEN 0 128 :::8081 :::* # 8081 已经启动
    35. LISTEN 0 128 :::22 :::*
    36. LISTEN 0 100 ::1:25 :::*

    修改配置文件,在执行一次

    1. [root@86-5-master ansible_playbook]# vi files/httpd.conf
    2. [root@86-5-master ansible_playbook]# grep "Listen" files/httpd.conf
    3. Listen 8082
    4. [root@86-5-master ansible_playbook]# ansible-playbook http_handler.yaml --limit 192.168.86.6

    会发现只有RUNNING HANDLER [restart httpd]是黄色,代表的是执行并发生改变,其他的都是绿色,代表是执行成功 ,但是没有修改

     

     可以触发多个任务,如下

    1. ---
    2. - hosts: dbserver
    3. remote_user: root
    4. gather_facts: no
    5. tasks:
    6. - name: add group nginx
    7. group: name=nginx state=present
    8. - name: add user nginx
    9. user: name=nginx state=present group=nginx
    10. - name: Install nginx
    11. yum: name=httpd state=present
    12. - name: Install configure file
    13. copy: src=files/nginx.conf dest=/etc/nginx/nginx.conf
    14. notify:
    15. - restart httpd
    16. - Check nginx process
    17. - name: ensure nginx is running
    18. service: name=nginx state=started enabled=yes
    19. handlers:
    20. - name: restart nginx
    21. service: name=nginx state=restarted
    22. - name: Check nginx process
    23. shell: killall -0 nginx &> /tmp/nginx.log # 向nginx 发送一个0信号,检查进程是不是存在,比如给某个程序发送kill -0信号,如果程序运行异常就会返回一个非0的状态码,运行正常则无任何提示,echo $?则返回0的状态码

    八、Pkaybook中使用 tags 组件

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

    简单案例

    1. vi nginx_tags.yaml
    2. ---
    3. - hosts: dbserver
    4. remote_user: root
    5. gather_facts: no
    6. tasks:
    7. - name: Install httpd
    8. yum: name=httpd state=present
    9. - name: Install configure file
    10. copy: src=files/httpd.conf dest=/etc/httpd/conf
    11. tags: conf
    12. - name: start httpd service
    13. tags: service
    14. service: name=httpd state=started enabled=yes

    将触发器合并

    1. [root@86-5-master ansible_playbook]# cat http_tags.yaml
    2. ---
    3. - hosts: dbserver
    4. remote_user: root
    5. gather_facts: no
    6. tasks:
    7. - name: Install httpd
    8. yum: name=httpd state=present
    9. - name: Install configure file
    10. copy: src=files/httpd.conf dest=/etc/httpd/conf
    11. notify: restart httpd
    12. tags: conf
    13. - name: start httpd service
    14. tags: service
    15. service: name=httpd state=started enabled=yes
    16. handlers:
    17. - name: restart httpd
    18. service: name=httpd state=restarted

    显示出有几个标签

    1. [root@86-5-master ansible_playbook]# ansible-playbook http_tags.yaml --list-tags
    2. playbook: http_tags.yaml
    3. play #1 (dbserver): dbserver TAGS: []
    4. TASK TAGS: [conf, service] # 两个标签conf 和 service
    5. [root@86-5-master ansible_playbook]#

    执行tags = conf ,通过执行操作发现,并没有触发notify: restart httpd,是因为配置文件没有被修改

    1. [root@86-5-master ansible_playbook]# ansible-playbook -t conf http_tags.yaml --limit 192.168.86.6

    执行tags中的任务,此任务中顺便带有触发notify,恰好配置文件被修改,触发器是执行

    八、Pkaybook 的变量

    变量名:仅能由数字、字母和下划线组成,且只能以字母开头
    定义: key=value      比如: http_port = 80,其中 key 就是变量
    变量调用方式:{{ variable_name }}  {{ key }} 建议前后加空格

    变量来源:

    1、ansible 的 setup模块中的 facts ,远程主机的所有变量都可直接调用,如下操作系统的版本 key:value   "ansible_distribution_version": "7.5"   其中 key 就是变量,所以ansible_distribution_version 就是变量,变量调用方式:{{ ansible_distribution_version }}

    1. [root@86-5-master ~]# ansible 192.168.86.6 -m setup |grep ansible_dis # 用处是可以根据当前系统的信息,决定执行的命令,比如Centos 执行的是yum ,Centos 执行的是dnf
    2. "ansible_distribution": "CentOS",
    3. "ansible_distribution_file_parsed": true,
    4. "ansible_distribution_file_path": "/etc/redhat-release",
    5. "ansible_distribution_file_variety": "RedHat",
    6. "ansible_distribution_major_version": "7",
    7. "ansible_distribution_release": "Core",
    8. "ansible_distribution_version": "7.5",
    9. [root@86-5-master ~]# ansible 192.168.86.6 -m setup -a 'filter="ansible_distribution_version"'
    10. 192.168.86.6 | SUCCESS => {
    11. "ansible_facts": {
    12. "ansible_distribution_version": "7.5",
    13. "discovered_interpreter_python": "/usr/bin/python"
    14. },
    15. "changed": false
    16. }
    17. [root@86-5-master ~]#

    2、通过命令行指定变量,优先级最高

    ansible-playbook -e varname=vaule

    3、在playbook文件夹定义

    1. vars:
    2. - var1: value1
    3. - var2: value2

    4、在独立的变量YAML文件中定义

    简单案例

    1、获取 setup 模块的变量

    1. #注意,直接执行命令,会提示无法找到变量,需要在playbook才生效,为什么后续会说
    2. [root@86-5-master ansible_playbook]# ansible 192.168.86.6 -m file -a "path=/tmp/{{ ansible_distribution_version }}.txt state=touch"

    1. # 重点,一定不要开启gather_facts: no,默认playbook是开启到的gather_facts,检索远程端的信息,如果关闭后,扫描不出来,就会报错,无法找到此变量。
    2. # 这就是为什么上述的 ansible -m file -a "path=/tmp/{{ ansible_distribution_version }}.txt state=touch"不好使的原因,直接执行命令是不检索远程端的信息
    3. [root@86-5-master ansible_playbook]# cat setup_variable.yaml
    4. ---
    5. - hosts: dbserver
    6. remote_user: root
    7. # gather_facts: no
    8. tasks:
    9. - name: create log file
    10. file: name=/var/log/{{ ansible_distribution_version }}.log state=touch owner=jerry mode=600
    11. [root@86-5-master ansible_playbook]# ansible-playbook -C setup_variable.yaml # 检查无问题
    12. [root@86-5-master ansible_playbook]# ansible-playbook setup_variable.yaml # 执行
    13. [root@86-5-master ansible_playbook]# ansible 192.168.86.6 -a "ls /var/log/*.log"
    14. 192.168.86.6 | CHANGED | rc=0 >>
    15. /var/log/7.5.log
    16. /var/log/boot.log
    17. /var/log/vmware-vmsvc.log
    18. /var/log/yum.log

    2、自定义变量-ansible-playbook  -e

    1. [root@86-5-master ansible_playbook]# ansible-playbook --help
    2. -e EXTRA_VARS, --extra-vars EXTRA_VARS
    3. 将其他变量设置为key=value或YAML/JSON,如果文件名前缀为@

    在playboook外定义变量,传递给playboook内。如下playb定义ok使用yum命令,通过外部定义需要yum什么软件

     并没有对pkname 变量定义

    1. [root@86-5-master ansible_playbook]# cat var1.yaml
    2. ---
    3. - hosts: dbserver
    4. remote_user: root
    5. tasks:
    6. - name: create_group
    7. yum: name={{ pkname }} state=present

     由我们自己指定ansible -e定义

    1. [root@86-5-master ansible_playbook]# ansible-playbook -e pkname=memcached var1.yaml # 指定给var1.yaml中的pkname=memcached,此语句直接执行
    2. [root@86-5-master ansible_playbook]# ansible-playbook -C var1.yaml -e pkname=memcached # 如果要检查加上-C

    3、在 playboook 中定义变量vars

    可以配置主组跟附加组,这种形式的用处在于,一个 playboook 中要使用多个相同的值,减少代码到的冗余性,可以定义变量 

    1. [root@86-5-master ansible_playbook]# cat var.yaml
    2. ---
    3. - hosts: dbserver
    4. remote_user: root
    5. vars:
    6. - username: user1
    7. - groupname: group1
    8. tasks:
    9. - name: create_group
    10. group: name={{ groupname }} state=present
    11. - name: create_user
    12. user: name={{ username }} state=present
    13. [root@86-5-master ansible_playbook]# ansible-playbook -C var.yaml
    14. [root@86-5-master ansible_playbook]# ansible-playbook var.yaml

    4、单独一个文件,只存放变量

    1. [root@86-5-master ansible_playbook]# cat /root/ansible_playbook/variables_list.yaml
    2. ---
    3. package_name: vsftpd
    4. service_name: vsftpd
    1. [root@86-5-master ansible_playbook]# cat install_vsft.yaml
    2. ---
    3. - hosts: dbserver
    4. remote_user: root
    5. vars_files:
    6. - /root/ansible_playbook/variables_list.yaml # 如果在同目录直接写文件名
    7. tasks:
    8. - name: install package
    9. yum: name={{ package_name }}
    10. tags: install
    11. - name: start service
    12. service: name={{ service_name }} state=started enabled=yes
    13. handlers:
    14. - name: restart httpd service
    15. service: name={{ service }} state=restarted
    16. [root@86-5-master ansible_playbook]# ansible-playbook -C install_vsft.yaml

    5、主机清单中定义变量

    第一种:单个主机变量

    在 inventory 主机清单文件中(/etc/ansible/hosts)为指定的主机定义变量以便于playbook中使用

    1. [dbserver] # 真对[dbserver] 下的主机
    2. 86-6-slave http_port=80 uid=80 # 真对86-6-slave的主机
    3. 192.168.86.7 http_port=8081 uid=421 # 真对192.168.86.6的主机

    第二种:组(公共)变量 

    在inventory主机清单文件(/etc/ansible/hosts)赋予给指定组内所有的机器上的playbook中使用

    1. [dbserver] # [dbserver] 下的所有主机
    2. 86-6-slave
    3. 192.168.86.7
    4. [dbserver:vars] # 代表[dbserver] 下的主机进行变量赋值
    5. ntp_server=ntp.jerry.com
    6. nts_server=nts.jerry.com

    简单案例1:

    1. [root@86-5-master ansible_playbook]# cat /etc/ansible/hosts # 定义主机清单文件
    2. [dbserver]
    3. 86-6-slave host=node1
    4. 192.168.86.7 host=node2
    5. [dbserver:vars]
    6. domain=jerry.com
    1. [root@86-5-master ansible_playbook]# ansible dbserver -m hostname -a "name={{ host }}.{{ domain }}"
    2. [root@86-6-slave ~]# hostname
    3. node1.jerry.com
    4. [root@86-7-slave ~]# hostname
    5. node2.jerry.com

    简单案例2:

    1. [root@86-5-master ansible_playbook]# cat /etc/ansible/hosts # 定义主机清单文件
    2. [dbserver] # [dbserver] 下的所有主机
    3. 86-6-slave http_port=8080 hname=www1
    4. 192.168.86.7 http_port=8080 hname=www1
    5. [dbserver:vars] # 代表[dbserver] 下的主机进行变量赋值
    6. http_port=808
    7. mark="-"
    8. ansible dbserver -m hostname -a "name={{ hname }}{{ http_port }}"

    注意:

    单个主机变量、组(公共)变量都定义了http_port,听谁的,听单个主机变量

    1. [root@86-5-master ~]# cat /etc/ansible/hosts
    2. [dbserver]
    3. 86-6-slave http_port=8080
    4. [dbserver:vars]
    5. http_port=808

    主机清单文件已经定义了http_port,ansible-playbook  -e 也定义了,听谁的,听ansible-playbook  -e

    ansible-playbook dnserver -e http_port=8080 -m hostname -a "name={{ hname }}{{ http_port }}"

    九、playboook 模板Templeate

    模板是一个文本文件,可以作为生成文件的模板,模板文件中还可嵌套 jinja 语法

    1、 jinja 语法

    jinja2 语言使用字面量,有下面形式:
    字符串:使用单引号或双引号
    数字:整数、浮点数
    列表:[item1,item2,.....]
    元组、字典、布尔、算术运算、比较操作、逻辑运算、流表达式、jinjn相关等等

    字面量:

    表达式最简单的形式就是字面量。字面量表示诸如字符串和数值的Python对象。如"Hello World"
    双引号或单引号中间的一切都是字符串。无论何时你需要在模板中使用一个字符串(比如函数调用、过滤器或只是包含或继承一个模板的参数),如42,42.23
    数值可以为整数和浮点数。如果有小数点,则为浮点数,否则为整数。在Python里,42和42.0是不一样的

    算术运算:

    Jinja允许用计算值。支持下面的运算符
    +:把两个对象加到一起。通常对象是数字,但是如果两者是字符串或列表,你可以用这种方式来衔接它们。无论如何这都不是首选的连接字符串的方式!连接字符串见~运算符。{{ 1 + 1 }}等于 2
    -:用第一个数减去第二个数。{{ 3 - 2 }}等于 1
    /:对两个数做除法。返回值会是一个浮点数。 {{ 1 / 2 }}等于{{ 0.5 }}
    //:对两个数做除法,返回整数商。{{ 20 // 7 }}等于2
    %:用右边的数乘左边的操作数。{{ 11 % 7 }}等于 4
    *:用右边的数乘左边的操作数。{{ 2 * 2 }}会返回4 。 也可以用于重复一个字符串多次。{{ ‘=’ * 80 }}会打印80个等号的横条
    **:取左操作数的右操作数次幂。{{ 2 ** 3}}

    比较操作符

    == 比较两个对象是否相等
    != 比较两个对象是否不等
    > 如果左边大于右边,返回true
    >= 如果左边大于等于右边,返回true
    < 如果左边小于右边,返回true
    <= 如果左边小于等于右边,返回true

    逻辑运算符

    对于 if 语句,在 for 过滤或 if 表达式中,它可以用于联合多个表达式
    and 如果左操作数和右操作数同为真,返回true
    or 如果左操作数和右操作数有一个为真,返回true
    not 对一个表达式取反
    (expr)表达式组
    true / false true永远是true,而false始终是false
     

    2、模板Templeate介绍

    1. [root@86-5-master ansible_playbook]# ansible-doc -s templeate
    2. [WARNING]: module templeate not found in: /root/.ansible/plugins/modules:/usr/share/ansible/plugins/modules:/usr/lib/python2.7/site-
    3. packages/ansible/modules
    4. [root@86-5-master ansible_playbook]# ansible-doc -s template
    5. - name: Template a file out to a remote server
    6. template:
    7. attributes: # The attributes the resulting file or directory should have. To get supported flags look at the man page for
    8. `chattr' on the target system. This string should contain the attributes in
    9. the same order as the one displayed by `lsattr'. The `=' operator is assumed
    10. as default, otherwise `+' or `-' operators need to be included in the string.
    11. backup: # Create a backup file including the timestamp information so you can get the original file back if you somehow
    12. clobbered it incorrectly.
    13. block_end_string: # The string marking the end of a block.
    14. block_start_string: # The string marking the beginning of a block.
    15. dest: # (required) Location to render the template to on the remote machine.
    16. follow: # Determine whether symbolic links should be followed. When set to `yes' symbolic links will be followed, if
    17. they exist. When set to `no' symbolic links will not be followed. Previous to
    18. Ansible 2.4, this was hardcoded as `yes'.
    19. force: # Determine when the file is being transferred if the destination already exists. When set to `yes', replace
    20. the remote file when contents are different than the source. When set to `no',
    21. the file will only be transferred if the destination does not exist.
    22. group: # Name of the group that should own the file/directory, as would be fed to `chown'.
    23. lstrip_blocks: # Determine when leading spaces and tabs shou

    官网:http://jinja.pocoo.org/docs/templates/

    注意:Templeate模板只能用在plybook中,不能再 ansible 命令中

    模板可以放在相对路径和绝对路径,所以一般都放在一个文件夹中

    模板需要以.j2 为后缀命名文件

    3、案例 template 同步 nginx 配置文件

    利用 template 同步 nginx 配置文件,直接使用copy模块,能实现拷贝过去,但想让 nginx 通过取本机的cpu核数,进而启动几个 nginx 的进程,需要配置 nginx.conf 的 worker_processes。怎么动态发现,并自动修改 nginx.conf 的 worker_processes

    1. [root@86-5-master templates]# pwd
    2. /root/ansible_playbook/templates
    3. [root@86-5-master ansible_playbook]# mkdir templates;cd templates # 创建templates工作目录
    4. [root@86-5-master templates]# vi temnginx.yaml #
    5. ---
    6. - hosts: dbserver
    7. remote_user: root
    8. tasks:
    9. - name: install nginx
    10. yum: name=nginx
    11. - name: template config to remote hosts
    12. template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf # 将nginx.conf.j2文件拷贝到远程端/etc/nginx/下并改名字叫nginx.conf。注意必须是.j2文件。
    13. notify: restart nginx
    14. - name: start service
    15. service: name=nginx state=started enabled=yes
    16. handlers:
    17. - name: restart nginx
    18. service: name=nginx state=restarted
    19. 思考:原封不动的拷贝过来,使用copy模块就行了,那template跟copy有什么区别呢?template根本区别
    20. 是src=的是一个.j2文件,我们要做些一些内容,里面包含的是jinja2的语法等

    编写 jinja2 文件 nginx.conf.j2

    1. [root@86-5-master templates]# cp /etc/nginx/nginx.conf ./nginx.conf.j2
    2. [root@86-5-master templates]# vi nginx.conf.j2 # 修改worker_processes
    3. [root@86-5-master templates]# grep "worker" nginx.conf.j2
    4. worker_processes {{ ansible_processor_vcpus+2 }};
    5. 解释:
    6. 此处调用了setup的变量,.j2 文件,就能可以调用之前讲过得所有的变量
    7. worker_processes设置好合适大小,可以提升nginx处理性能,非常重要。worker_processes,设置几个就有几个工作进程数
    8. worker_processes {{ ansible_processor_vcpus }}; 的意思就是根据cpu的核数,进行启动几个nginx的工作进程
    9. worker_processes {{ ansible_processor_vcpus+2 }}; # 加2
    10. worker_processes {{ ansible_processor_vcpus**2 }}; # 乘以2

    执行 playbook

    1. [root@86-5-master templates]# ansible-playbook -C temnginx.yaml
    2. [root@86-5-master templates]# ansible-playbook temnginx.yaml

    查看 nginx 的进程数

    1. [root@86-5-master templates]# ansible dbserver -m setup -a 'filter="ansible_processor_vcpus"'
    2. 86-6-slave | SUCCESS => {
    3. "ansible_facts": {
    4. "ansible_processor_vcpus": 1,
    5. "discovered_interpreter_python": "/usr/bin/python"
    6. },
    7. "changed": false
    8. }
    9. [root@86-5-master templates]# ansible dbserver -a "pstree"
    10. 86-6-slave | CHANGED | rc=0 >>
    11. systemd-+-NetworkManager---2*[{NetworkManager}]
    12. |-VGAuthService
    13. |-agetty
    14. |-auditd---{auditd}
    15. |-crond
    16. |-dbus-daemon
    17. |-lvmetad
    18. |-master-+-pickup
    19. | `-qmgr
    20. |-nginx---3*[nginx] # 进程数3
    21. |-polkitd---5*[{polkitd}]
    22. |-rsyslogd---2*[{rsyslogd}]
    23. |-sshd-+-sshd---bash
    24. | `-sshd---sh---python---pstree
    25. |-systemd-journal
    26. |-systemd-logind
    27. |-systemd-udevd
    28. |-tuned---4*[{tuned}]
    29. `-vmtoolsd---{vmtoolsd}
    30. [root@86-6-slave ~]# head -n 10 /etc/nginx/nginx.conf
    31. # For more information on configuration, see:
    32. # * Official English Documentation: http://nginx.org/en/docs/
    33. # * Official Russian Documentation: http://nginx.org/ru/docs/
    34. user nginx;
    35. worker_processes 3;
    36. error_log /var/log/nginx/error.log;
    37. pid /run/nginx.pid;
    38. # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
    39. [root@86-6-slave ~]#

    ​注意:远程主机内核已经是1,所以就算+2,实际物理上实现不到,所以还是1

    ​4、Template 使用 for 和 if

    利用 for 循环动态的生成指令,for 循环可以循环列表、字典等

    循环列表:作用可以批量快速生成配置文件信息

    1. [root@86-5-master templates]# cat list.conf.j2
    2. {% for vhost in vhosts %}
    3. server {
    4. listen {{ vhost }}
    5. }
    6. {% endfor %}
    7. [root@86-5-master templates]# cat template_list.yaml
    8. ---
    9. - hosts: dbserver
    10. remote_user: root
    11. vars:
    12. vhosts:
    13. - 81
    14. - 82
    15. - 83
    16. tasks:
    17. - name: template config
    18. template: src=list.conf.j2 dest=/data/list.conf
    19. [root@86-5-master templates]# ansible-playbook -C template_list.yaml
    20. [root@86-5-master templates]# ansible dbserver -a "cat /data/list.conf"
    21. 86-6-slave | CHANGED | rc=0 >>
    22. server {
    23. listen 81
    24. }
    25. server {
    26. listen 82
    27. }
    28. server {
    29. listen 83
    30. }
    31. [root@86-5-master templates]#

     循环字典:

    1. [root@86-5-master templates]# cat template_dict.yaml
    2. ---
    3. - hosts: dbserver
    4. remote_user: root
    5. vars:
    6. key_port:
    7. - listen: 8080
    8. server_name: "web1.jerry.com"
    9. root: "/var/www/nginx/web1/"
    10. - listen: 8081
    11. server_name: "web2.jerry.com"
    12. root: "/var/www/nginx/web2"
    13. - {listen: 8082, server_name: "web3.jerry.com", root: "/var/www/nginx/web3"}
    14. tasks:
    15. - name: template config
    16. template: src=dict.conf.j2 dest=/data/dict.conf
    17. [root@86-5-master templates]#
    18. [root@86-5-master templates]# cat dict.conf.j2
    19. {% for vhost in key_port %}
    20. server {
    21. listen {{ vhost.listen }} # 获取listen中的value
    22. server_name {{ vhost.server_name }} # 获取server_name 中的value
    23. root {{ vhost.root}} # 获取root 中的value
    24. }
    25. {% endfor %}
    26. [root@86-5-master templates]#
    1. [root@86-5-master templates]# ansible-playbook template_dict.yaml
    2. [root@86-6-slave ~]# cat /data/dict.conf
    3. server {
    4. listen 8080
    5. server_name web1.jerry.com
    6. root /var/www/nginx/web1/
    7. }
    8. server {
    9. listen 8081
    10. server_name web2.jerry.com
    11. root /var/www/nginx/web2
    12. }
    13. server {
    14. listen 8082
    15. server_name web3.jerry.com
    16. root /var/www/nginx/web3
    17. }

    if  循环判断,上述的字典,如果在某一个字典中,有一项比如 server_name 没有写,for 循环到,则会提示找不到

    1. [root@86-5-master templates]# cat template_dict.yaml
    2. ---
    3. - hosts: dbserver
    4. remote_user: root
    5. vars:
    6. key_port:
    7. - listen:
    8. root: "/var/www/nginx/web1/"
    9. - listen: 8081
    10. server_name: "web2.jerry.com"
    11. root: "/var/www/nginx/web2"
    12. - {listen: 8082, server_name: "web3.jerry.com", root: "/var/www/nginx/web3"}
    13. tasks:
    14. - name: template config
    15. template: src=dict.conf.j2 dest=/data/dict.conf
    16. [root@86-5-master templates]# cat dict.conf.j2
    17. {% for vhost in key_port %}
    18. server {
    19. listen {{ vhost.listen }}
    20. server_name {{ vhost.server_name }}
    21. root {{ vhost.root}}
    22. }
    23. {% endfor %}
    24. [root@86-5-master templates]# ansible-playbook template_dict.yaml
    25. fatal: [86-6-slave]: FAILED! => {"changed": false, "msg": "AnsibleUndefinedVariable: 'dict object' has no attribute 'server_name'"}

    则增加if判断

    1. [root@86-5-master templates]# cat dict.conf.j2
    2. {% for vhost in key_port %}
    3. server {
    4. listen {{ vhost.listen }}
    5. {% if vhost.server_name is defined %}
    6. server_name {{ vhost.server_name }} # 有if后注意缩进,要不无法对其
    7. {% endif %}
    8. root {{ vhost.root}} # 注意缩进,要不无法对其
    9. }
    10. {% endfor %}
    11. [root@86-5-master templates]#
    12. [root@86-5-master templates]# cat template_dict.yaml
    13. ---
    14. - hosts: dbserver
    15. remote_user: root
    16. vars:
    17. key_port:
    18. - listen:
    19. server_name: "web1.jerry.com"
    20. root: "/var/www/nginx/web1/"
    21. - listen: 8081
    22. root: "/var/www/nginx/web2"
    23. - {listen: 8082, server_name: "web3.jerry.com", root: "/var/www/nginx/web3"}
    24. tasks:
    25. - name: template config
    26. template: src=dict.conf.j2 dest=/data/dict.conf
    27. [root@86-5-master templates]#

    通过上述,在一台物理机器上搭建了好几个网站

    1. [root@86-6-slave ~]# cat /data/dict.conf
    2. server {
    3. listen
    4. server_name web1.jerry.com
    5. root /var/www/nginx/web1/
    6. }
    7. server {
    8. listen 8081
    9. root /var/www/nginx/web2
    10. }
    11. server {
    12. listen 8082
    13. server_name web3.jerry.com
    14. root /var/www/nginx/web3
    15. }
    16. [root@86-6-slave ~]#

    字典,案例可以做证书之类,有效期、OU、CN等等。

    shell 没有字典,可以通过数组、关联数组等下标进行便利

    5、playbook 使用 when

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

    案例:

    1. ---
    2. - hosts: dbserver
    3. remote_user: root
    4. tasks:
    5. - name: "shutdown RedHat flavored systems"
    6. command: /sbin/shutdown -h now
    7. when: ansible_os_family == "RedHat" # 模块是属于setup
    8. ---
    9. - hosts: dbserver
    10. remote_user: root
    11. tasks:
    12. - name: install conf file to centos7
    13. template: src=nginx.conf.c7.j2 dest=/etc/nginx/nginx.conf
    14. when: ansible_distribution_major_version == "7"
    15. - name: install conf file to centos6
    16. template: src=nginx.conf.c6.j2 dest=/etc/nginx/nginx.conf
    17. when: ansible_distribution_major_version == "6"

    6、playbook 使用迭代 with_items

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

    列表元素格式:字符串、字典

    字符串案例:

    1. # 用 with_item 把我们要调用的不同的元素,都写到最后以列表的形式
    2. ---
    3. - hosts: dbserver
    4. remotes_user: root
    5. tasks:
    6. - name: add serveral users
    7. user: name={{ item }} state=present groups=whell
    8. with_items: # 列表序列
    9. - testuser1
    10. - testuser2
    11. - testuser3
    12. # 上面的语句的功能等同于下面的语句
    13. - name: add user testuser1
    14. user: name=testuser1 state=present groups=whell
    15. - name: add user testuser2
    16. user: name=testuser2 state=present groups=whell
    17. - name: add user testuser3
    18. user: name=testuser3 state=present groups=whell
    19. ---
    20. - hosts: dbserver:!192.168.86.7 # dbserver组中除了192.168.86.7
    21. remotes_user: root
    22. tasks:
    23. - name: stop service
    24. shell: /etc/init.d/mysqld stop
    25. - name: delete files and dir
    26. file: path={{ item }} state=absent
    27. with_items:
    28. - /usr/local/mysql
    29. - /usr/local/mariadb
    30. - /etc/init.d/mysqld.sh
    31. - /etc/my.cnf
    32. - name delete user
    33. user: name=mysql state=absent remove=yes
    34. ---
    35. - hosts: dbserver:!192.168.86.7 # dbserver组中除了192.168.86.7
    36. remotes_user: root
    37. tasks:
    38. - name: copy file
    39. copy: src={{item }} dest=/tmp/{{ item }}
    40. - name: delete files and dir
    41. file: path={{ item }} state=absent
    42. with_items:
    43. - file1
    44. - file2

    字典案例:

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

    字符串with_items,有局限性,如何通过字典创建用户,有自己的属性

    1. ---
    2. - hosts: dbserver:!192.168.86.7 # dbserver组中除了192.168.86.7
    3. remotes_user: root
    4. tasks:
    5. - name: add some users
    6. group: name={{ item.name }} group={{ item.group }} state=present
    7. with_items:
    8. - { name: 'nginx',group: 'nginx'}
    9. - { name: 'mysql',group: 'mysql'}
    10. - { name: 'apache',group: 'apache'}

    十、roles角色

    角色是ansible自1.2版本引入的新特性,用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用incluede指令即可。简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中
    运维复杂的场景:建议使用roles,代码复用度高
    如果不写 role,可能要写多个 playbook,如何能提高整合率,实现在一个 playbook 有多个功能(安装mysql、httpd 等等),或者playbook 能不能调用另一个 playbook,所以有了角色。shell 脚本可以调用另一个脚本,角色也可以互相之间调用,但这样会导致很乱,为了解决,角色中有严格规定,他把不同类型的资源,分别放在不同的路径下。一个yaml中写的拆开到不同目录中。好处是修改后不影响其他,而且其他项目也能调用。

    先创一个roles目录,在创建多个的 role 目录 (mysql、redis目录等),分别放至 roles 目录下,作为独立子目录中

    1. roles/
    2. mysql/
    3. httpd/
    4. nginx/
    5. redis/

    1、Ansible Roles目录编排

    roles目录结构如下所示,roles 目录下有 git 、user 目录,在 git 、user 目录还继续有多层子目录,思想将所有的服务打散到不同地方,降低耦合度,甚至可以将 Handlers 触发器也单独做一个目录

     比如 mysql 

    1. roles/
    2. mysql/
    3. file/ # 放配置文件
    4. package # 放安装包
    5. vars # 变量
    6. 。。。。

    查看 ansible-galaxy 下载的官方提供的

    1. [root@86-5-master ~]# tree /root/.ansible/roles/geerlingguy.redis/
    2. /root/.ansible/roles/geerlingguy.redis/
    3. ├── defaults
    4. │   └── main.yml
    5. ├── handlers
    6. │   └── main.yml
    7. ├── LICENSE
    8. ├── meta # 元数据
    9. │   └── main.yml
    10. ├── molecule
    11. │   └── default
    12. │   ├── converge.yml
    13. │   └── molecule.yml
    14. ├── README.md
    15. ├── tasks
    16. │   ├── main.yml
    17. │   ├── setup-Archlinux.yml
    18. │   ├── setup-Debian.yml
    19. │   └── setup-RedHat.yml
    20. ├── templates
    21. │   └── redis.conf.j2
    22. └── vars
    23. ├── Archlinux.yml
    24. ├── Debian.yml
    25. └── RedHat.yml

    常见的目录结构

    Roles各目录作用

    /roles/project/ :项目名称,有以下子目录

    • 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的优先级低

    2、创建 role

    创建role的步骤
    (1)创建以roles命名的目录
    (2)在roles目录中分别创建以各角色名称命名的目录,如webservers等
    (3)在每个角色命名的目录中分别创建files、handlers、meta、tasks、templates和vars目录;用不到的目录可以创建为空目录,也可以不创建
    (4)在playbook中调用各角色
    针对大型项目使用Roles进行编排
    范例: roles的目录结构

    1. nginx-role.yml
    2. roles/
    3. └── nginx
    4. ├── files
    5. │ └── main.yml
    6. ├── tasks # 存放的所有任务
    7. │ ├── groupadd.yml # 专门建组的
    8. │ ├── install.yml # 安装软件的
    9. │ ├── main.yml # 主函数,在tasks任务中,先执行谁在执行谁?main定义
    10. │ ├── restart.yml # 重启服务
    11. │ └── useradd.yml # 创建账号
    12. └── vars
    13. └── main.yml

    3、调用角色

    定义了角色将来怎么用,还需要定义palybook,调用 role

    方式一:

    1. ---
    2. - hosts: dbserver
    3. remote_user: root
    4. roles: # 定义调用的角色,也就是roles目录
    5. - mysql # 定义调用mysql角色, 也就是roles/mysql目录
    6. - memcached
    7. - nginx

    方式二:

    定义角色role,后续的key value用于传递变量给角色

    1. ---
    2. - hosts: dbserver
    3. remote_user: root
    4. roles:
    5. - mysql # 单纯的调用mysql角色
    6. - { role: nginx, username: nginx} # 调用nginx角色,并给这个角色赋值username=nginx

    方式三:

    还可以基于条件测试实现角色的调用

    1. ---
    2. - hosts: dbserver
    3. remote_user: root
    4. roles:
    5. - { role: nginx, username: nginx, when: ansible_distribuion_version == '7' } # 调用nginx角色,并给这个角色赋值username=nginx,前提是要满足是centos 7

    4、roles 中的 tags 使用

    1. # role.yaml
    2. ---
    3. - hosts: dbserver
    4. remote_user: root
    5. roles:
    6. - { role: httpd, tags: httpd } # 给httpd角色贴一个标签
    7. - { role: nginx, tags: ['nginx','web'], when: ansible_distribuion_version == '7' }
    8. - { role: mysql, tags: ['mysql','db'] } # 给mysql角色贴两个标签
    9. - { role: mysql, tags: ['mariadb','db'] } # 给mysql角色贴两个标签
    10. 多标签的好处是
    11. # 比如我想执行mysql安装
    12. ansible-playbook --tags="mysql" role.yaml
    13. # 比如我想执行mysql、mariadb安装
    14. ansible-playbook --tags="db" role.yaml # 由于数据库都有db的标签,所以直接使用db标签
    15. # 比如我想执行mysql、nginx、httpd 安装
    16. ansible-playbook --tags="mysql,nginx,httpd" role.yaml

    5、roles案例

    先创建一个roles目录,官方建议在如下位置创建

    1. [root@86-5-master ansible]# ansible-galaxy list
    2. # /root/.ansible/roles
    3. - geerlingguy.redis, 1.8.0
    4. # /usr/share/ansible/roles
    5. # /etc/ansible/roles
    6. [root@86-5-master ansible]# grep "roles" /etc/ansible/ansible.cfg
    7. #roles_path = /etc/ansible/roles

    我们在 /data/ansible/roles 

    1. [root@86-5-master ~]# mkdir /data/ansible
    2. [root@86-5-master ~]# cd /data/ansible/ && mkdir roles

    案例1:http 服务(使用 tasks,files,handers)

    第一步:先创建 httpd 的 role 目录

    1. [root@86-5-master roles]# pwd
    2. /data/ansible/roles
    3. [root@86-5-master roles]# mkdir httpd/{tasks,files,handers} -pv # 目前先定义这些,后续需要可以在扩充
    4. [root@86-5-master roles]# cd ../
    5. [root@86-5-master ansible]# tree roles/
    6. roles/
    7. └── httpd
    8. ├── files
    9. ├── handers
    10. └── tasks

    第二步:

    在/data/ansible/roles/httpd/tasks/下创建每一个操作的yaml文件
    创建main.yaml 主程序入口,必须有不能改名字,里面记录的是每一个操作的yaml文件,按照顺序执行。
    在data/ansible/roles/httpd/handlers/handlers.yaml 下必须创建 main.yaml 作为触发器
    修改/data/ansible/roles/httpd/tasks/config.yaml 添加 handlers 的 name

    1. [root@86-5-master httpd]# pwd
    2. /data/ansible/roles/httpd
    3. [root@86-5-master tasks]# cat tasks/group.yaml
    4. - name: create apache group
    5. group: name=apache system=yes gid=80 # 为什么要指定gid=80,一般指定uid和gid=你服务的端口号,虽然说uid gid是多少无所谓,但是这样规划是有层次的
    6. [root@86-5-master tasks]# cat tasks/user.yaml
    7. - name: create user
    8. user: name=apache system=yes shell=/sbin/nologin home=/var/www/ uid=80 group=apache
    9. # shell=/sbin/nologin 代表的是人不能登录
    10. # home=/var/www/ 代表如果能登录你会发现,默认登录在/var/www/下,如果/sbin/nologin人登录不了,程序在
    11. # 后台运行是可以登录,默认执行程序是从/var/www/下作为当前目录。比如你登录root账户,默认在/root下
    12. [root@86-5-master tasks]# cat tasks/config.yaml
    13. - name: index.html
    14. copy: src=httpd.conf dest=/etc/httpd/conf backup=yes # 注意,其实httpd.conf文件在../files/httpd.conf,这里可以直接写httpd.conf,playbook会自动检索../files目录
    15. notify: restart httpd
    16. [root@86-5-master httpd]# cat tasks/index.yaml
    17. - name: index.html
    18. copy: src=index.html dest=/var/www/html/ # 注意,其实index.html文件在../files/index.html,这里可以直接写index.html,playbook会自动检索../files目录
    19. [root@86-5-master httpd]# cat stasks/ervice.yaml
    20. - name: start service
    21. service: name=httpd state=started enabled=yes
    22. [root@86-5-master httpd]# cat handlers/main.yaml # 注意在httpd/handlers目录中,创建
    23. - name: restart httpd
    24. service: name=httpd state=restarted
    25. [root@86-5-master httpd]# cat stasks/main.yaml # 主程序入口,必须有而且是main.yaml,按照顺序执行
    26. - include: group.yaml
    27. - include: user.yaml
    28. - include: install.yaml
    29. - include: config.yaml
    30. - include: index.yaml
    31. - include: service.yaml

    第三步:

    制作httpd.conf  到 httpd/files/httpd.conf下,并做端口的修改以便我们的观察
    添加自定义的index.html

    1. [root@86-5-master httpd]# cp /etc/httpd/conf/httpd.conf files/
    2. # 修改Listen=8081,以便我们的观察
    3. [root@86-5-master httpd]# grep "Listen" files/httpd.conf
    4. Listen 8081
    5. # 添加自定义的index.html
    6. [root@86-5-master httpd]# cat files/index.html
    7. <h1> welcome to world </h1>

    第四步:制作调用此 httpd 角色的playbook, 文件所在的路径一定是跟 roles 平级

    1. [root@86-5-master ansible]# ll
    2. drwxr-xr-x 3 root root 19 1020 17:02 roles
    3. [root@86-5-master ansible]# pwd
    4. /data/ansible
    5. [root@86-5-master ansible]# vi /data/ansible/role_httpd.yaml
    6. ---
    7. - hosts: dbserver
    8. remote_user: root
    9. roles:
    10. - role: httpd
    11. 运行playbook
    12. ansible-playbook -C /data/ansible/role_httpd.yaml
    13. ansible-playbook /data/ansible/role_httpd.yaml
    14. [root@86-6-slave ~]# netstat -anp |grep 80
    15. tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 980/sshd
    16. tcp6 0 0 :::8081 :::* LISTEN 26866/httpd
    17. tcp6 0 0 :::22 :::* LISTEN 980/sshd
    18. unix 2 [ ACC ] STREAM LISTENING 18580 1114/master private/proxywrite
    19. unix 3 [ ] STREAM CONNECTED 17777 980/sshd
    20. [root@86-6-slave ~]# curl 192.168.86.6:8081
    21. <h1> welcome to world </h1>

    案例2:nginx 服务(tasks,handlers,templates,vars)

    第一步:先创建 nginx 的 role 目录

    1. [root@86-5-master roles]# pwd
    2. /data/ansible/roles
    3. [root@86-5-master roles]# mkdir nginx/{tasks,handlers,templates,vars} -pv # 目前先定义这些,后续需要可以在扩充
    4. [root@86-5-master roles]# cd ../
    5. [root@86-5-master ansible]# tree roles/
    6. roles/
    7. ├── httpd
    8. │   ├── files
    9. │   │   ├── httpd.conf
    10. │   │   └── index.html
    11. │   ├── handlers
    12. │   │   └── main.yaml
    13. │   └── tasks
    14. │   ├── config.yaml
    15. │   ├── group.yaml
    16. │   ├── index.yaml
    17. │   ├── install.yaml
    18. │   ├── main.yaml
    19. │   ├── service.yaml
    20. │   └── user.yaml
    21. └── nginx
    22. ├── handlers
    23. ├── tasks
    24. ├── templates
    25. └── vars

    第二步:

    在/data/ansible/roles/nginx/tasks/下创建每一个操作的yaml文件
    在/data/ansible/roles/nginx/tasks/下创建config.yaml 并添加 when 条件判断是哪个系统进行哪个操作
    在/data/ansible/roles/nginx/tasks/下创建main.yaml 主程序入口,必须有不能改名字,里面记录的是每一个操作的yaml文件,按照顺序执行。
    在data/ansible/roles/httpd/handlers/handlers.yaml 下必须创建 main.yaml 作为触发器
    修改/data/ansible/roles/nginx/tasks/config.yaml 添加 handlers 的 name

    1. [root@86-5-master nginx]# cat tasks/install.yaml
    2. - name: install nginx
    3. yum: name=nginx
    4. [root@86-5-master nginx]# cat tasks/index.yaml
    5. - name: index.html
    6. copy: src=roles/httpd/files/index.html dest=/usr/share/nginx/html/ # 可以直接将httpd/files/index.html下的index.html拿来用,注意真对当前项目,会默认从roles下找,作为相对路径
    7. [root@86-5-master nginx]# cat tasks/config.yaml
    8. - name: config file for centos7
    9. template: src=nginx7.conf.j2 dest=/etc/nginx/nginx.conf # 使用template代替copy,使用template就需要使用.j2文件,文件中可以定义变量
    10. when: ansible_distribution_major_version=='7' # 增加判断,只有是7版本的才能执行
    11. notify: restart nginx
    12. - name: config file for centos8
    13. template: src=nginx8.conf.j2 dest=/etc/nginx/nginx.conf
    14. when: ansible_distribution_major_version=='8' # 增加判断,只有是7版本的才能执行
    15. notify: restart nginx
    16. [root@86-5-master nginx]# cat tasks/service.yaml
    17. - name: start service
    18. service: name=nginx state=started enabled=yes
    19. [root@86-5-master nginx]# cat handlers/main.yaml
    20. - name: restart nginx
    21. service: name=nginx state=restarted
    22. [root@86-5-master nginx]# cat tasks/main.yaml
    23. - include: install.yaml
    24. - include: config.yaml
    25. - include: index.yaml
    26. - include: service.yaml

    第三步:

    在/data/ansible/roles/nginx/templates/下创建nginx7.conf.j2 nginx8.conf.j2,其中里面调用了setup变量和自定义变量,自定义变量写在 templates/main.yaml 下

    1. # 注意,建议先进行操作系统的yum源更新 ,都是用同一个yum源,比如阿里源跟Centos源,他们的最nginx版本不一样,
    2. # 会导致你拷贝过去的是nginx:1.22.1,而下方使用的源yum安装后是nginx:1.16.1,nginx版本差异发,配置文件不通用
    3. [root@86-5-master tasks]# cp /etc/nginx/nginx.conf templates/nginx7.conf.j2
    4. [root@86-5-master tasks]# cp /etc/nginx/nginx.conf templates/nginx8.conf.j2
    5. [root@86-5-master nginx]# head -n 10 templates/nginx7.conf.j2
    6. # For more information on configuration, see:
    7. user {{ user }}; # 默认是 user nginx ,修改为获取变量user,变量从哪来,如果是setup,则自动获取,如果不是,可以在roles/nginx/vars/下定义main.yaml,声明变量
    8. worker_processes {{ ansible_processor_vcpus+1 }}; # 修改按照cpu的个数,启动ngin的工作进行,此变量就是setup的变量
    9. error_log /var/log/nginx/error.log;
    10. pid /run/nginx.pid;
    11. [root@86-5-master nginx]# head -n 10 templates/nginx8.conf.j2
    12. # For more information on configuration, see:
    13. user nginx;
    14. worker_processes {{ ansible_processor_vcpus }};
    15. error_log /var/log/nginx/error.log;
    16. pid /run/nginx.pid;
    17. [root@86-5-master nginx]# cat vars/main.yaml # 上述templates/nginx7.conf.j2中定义了{{ user }}; 此user 在vars/main.yaml配置
    18. user: daemon

    第四步:制作调用此 nginx 角色的 playbook, 文件所在的路径一定是跟 roles 平级

    1. [root@86-5-master ansible]# ll
    2. drwxr-xr-x 3 root root 19 1020 17:02 roles
    3. [root@86-5-master ansible]# pwd
    4. /data/ansible
    5. [root@86-5-master ansible]# vi /data/ansible/role_nginx.yaml
    6. ---
    7. - hosts: dbserver
    8. remote_user: root
    9. roles:
    10. - role: nginx
    11. # 如果你想调用nginx和httpd,如下
    12. [root@86-5-master ansible]# vi /data/ansible/role_nginx.yaml
    13. ---
    14. - hosts: dbserver
    15. remote_user: root
    16. roles:
    17. - role: nginx
    18. - role: httpd
    19. [root@86-5-master ansible]# tree roles/nginx/
    20. roles/nginx/
    21. ├── handlers
    22. │   └── main.yaml
    23. ├── tasks
    24. │   ├── config.yaml
    25. │   ├── index.yaml
    26. │   ├── install.yaml
    27. │   ├── main.yaml
    28. │   └── service.yaml
    29. ├── templates
    30. │   ├── nginx7.conf.j2
    31. │   └── nginx8.conf.j2
    32. └── vars
    33. └── main.yaml
    34. 运行playbook
    35. ansible-playbook -C /data/ansible/role_nginx.yaml
    36. ansible-playbook /data/ansible/role_nginx.yaml

    案例3:实现 memcached 角色(tasks,templates)

    memcached  是一个将内存作为缓存使用,思考内存占用多大空间当缓存使用,默认分配缓存比较小,大约应该是64M,如果是一个大内存的物理机,只是用了64M,根本没充分使用,因此可以修改此配置。功能不强,已经不建议使用了,可以使用 redis 。

    第一步:先创建 memcached 的 role 目录

    1. [root@86-5-master roles]# pwd
    2. /data/ansible/roles
    3. [root@86-5-master roles]# mkdir memcached/{tasks,templates} -pv # 目前先定义这些,后续需要可以在扩充
    4. [root@86-5-master roles]# cd ../
    5. [root@86-5-master ansible]# tree roles/
    6. [root@86-5-master ansible]# tree roles/
    7. roles/
    8. ├── httpd
    9. │   ├── files
    10. │   │   ├── httpd.conf
    11. │   │   └── index.html
    12. │   ├── handlers
    13. │   │   └── main.yaml
    14. │   └── tasks
    15. │   ├── config.yaml
    16. │   ├── group.yaml
    17. │   ├── index.yaml
    18. │   ├── install.yaml
    19. │   ├── main.yaml
    20. │   ├── service.yaml
    21. │   └── user.yaml
    22. ├── memcached
    23. │   ├── tasks
    24. │   └── templates
    25. └── nginx
    26. ├── handlers
    27. │   └── main.yaml
    28. ├── tasks
    29. │   ├── config.yaml
    30. │   ├── index.yaml
    31. │   ├── install.yaml
    32. │   ├── main.yaml
    33. │   └── service.yaml
    34. ├── templates
    35. │   ├── nginx7.conf.j2
    36. │   └── nginx8.conf.j2
    37. └── vars
    38. └── main.yaml

    第二步:

    1. [root@86-5-master memcached]# cat tasks/install.yaml
    2. - name: install memcached
    3. yum: name=memcached
    4. [root@86-5-master memcached]# cat tasks/config.yaml
    5. - name: config file
    6. template: src=memcached.j2 dest=/etc/sysconfig/memcached
    7. [root@86-5-master memcached]# cat tasks/service.yaml
    8. - name: start service
    9. service: name=memcached state=started enabled=yes
    10. [root@86-5-master nginx]# cat tasks/main.yaml
    11. - include: install.yaml
    12. - include: config.yaml
    13. - include: service.yaml

    第三步:

    1. # 在ansible机器上,部署memcached,获取对应的配置文件
    2. [root@86-5-master ansible]# yum install -y memcached
    3. [root@86-5-master memcached]# cp /etc/sysconfig/memcached templates/memcached.j2
    4. [root@86-5-master memcached]# vi templates/memcached.j2
    5. PORT="11211" # 端口号
    6. USER="memcached" # 用户名
    7. MAXCONN="1024" # 最大并发连接数
    8. CACHESIZE="{{ ansible_memtotal_mb//4 }}" # 缓存的空间,默认CACHESIZE="64" 64M,ansible_memtotal_mb是setup获取的内存大小,ansible_memtotal_mb/4 占用1/4,但都知道一般内存都是虚标,大概率是不能整除的,所以//4的意思是,除以4后不能整除去掉小数,取整
    9. OPTIONS="" # 其他选项

    第四步:制作调用此 nginx 角色的 playbook, 文件所在的路径一定是跟 roles 平级

    1. [root@86-5-master ansible]# ll
    2. drwxr-xr-x 3 root root 19 1020 17:02 roles
    3. [root@86-5-master ansible]# pwd
    4. /data/ansible
    5. [root@86-5-master ansible]# vi /data/ansible/role_memcached.yaml
    6. ---
    7. - hosts: dbserver
    8. remote_user: root
    9. roles:
    10. - role: memcached
    11. 运行playbook
    12. ansible-playbook -C /data/ansible/role_memcached.yaml
    13. ansible-playbook /data/ansible/role_memcached.yaml
    14. [root@86-6-slave ~]# cat /etc/sysconfig/memcached
    15. PORT="11211"
    16. USER="memcached"
    17. MAXCONN="1024"
    18. CACHESIZE="248" # 虚拟机内存1G。1024//4=248
    19. OPTIONS=""

    案例4:部署 mysql5.6 角色(tasks,files)

    第一步:先创建 mysql5.6 的 role 目录

    1. [root@86-5-master roles]# pwd
    2. /data/ansible/roles
    3. [root@86-5-master roles]# mkdir mysql5.6/{tasks,files} -pv
    4. [root@86-5-master roles]# tree mysql5.6/
    5. mysql5.6/
    6. ├── files
    7. └── tasks

    第二步:

    安装、 建组、 建用户、 解包解压缩、  建软连接、 建数据库初始目录,生成初始数据库、 拷贝配置文件、 启动服务、 配置PATH变量、  执行安全加固脚本

    1. [root@86-5-master mysql5.6]# cat tasks/install.yaml
    2. - name: install mysql5.6 environment
    3. yum: name=libaio,perl-Date-Dumper,perl-Getopt-Long
    4. [root@86-5-master mysql5.6]# cat tasks/group.yaml
    5. - name: create mysql5.6 group
    6. group: name=mysql gid=306 # 之前说过,主动配置是为了规整,为什么是306,因为uid数值201999:系统用户用来运行服务,不需要登录系统(动态分配),对应gid也规划uid数值
    7. [root@86-5-master mysql5.6]# cat tasks/user.yaml
    8. - name: create mysql5.6 user
    9. user: name=mysql uid=306 group=mysql shell=/sbin/nologin system=yes create_home=no home=/data/mysql
    10. [root@86-5-master mysql5.6]# cat tasks/unarchive.yaml
    11. - name: copy mysql5.6 package
    12. unarchive: src=mysql-5.6.44-linux-glibc2.12-x86_64.tar.gz dest=/usr/local/ owner=root group=root
    13. [root@86-5-master mysql5.6]# cat tasks/link.yaml
    14. - name: link /usr/local/mysql
    15. file: src=/usr/local/mysql-5.6.44-linux-glibc2.12-x86_64 dest=/usr/local/mysql state=link
    16. [root@86-5-master mysql5.6]# cat tasks/data.yaml # 切换目录,对 mysql 初始化
    17. - name: data dir
    18. shell: chdir=/usr/local/mysql ./scripts/mysql_install_db --datadir=/data/mysql --user=mysql
    19. [root@86-5-master mysql5.6]# cat tasks/config.yaml
    20. - name: config my.cnf
    21. copy: src=my.cnf dest=/etc/my.cnf
    22. # 由于是二进制安装,不能使用service模块,servicem模块是通过systemctl或者service启动,默认yum安
    23. # 装生成mysqld.service文件,二进制不生成,所以只能是二进制启动,并加入到启动启动列表chkconfig
    24. [root@86-5-master mysql5.6]# cat tasks/service.yaml
    25. - name: service start
    26. shell: /bin/cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld;/etc/init.d/mysqld start;chkconfig --add mysqld;chkconfig mysqld on
    27. [root@86-5-master mysql5.6]# cat tasks/path.yaml # 使用copy模块将content后的内容写入文件并拷贝,将mysql/bin下的所有执行文件加入环境变量,这样以后能直接使用命令
    28. - name: PATH variable
    29. copy: content='PATH=/usr/local/mysql/bin:$PATH' dest=/etc/profile.d/mysql.sh
    30. [root@86-5-master mysql5.6]# cat tasks/secure.yaml
    31. - name: secure script
    32. script: secure_mysql.sh
    33. [root@86-5-master nginx]# cat tasks/main.yaml
    34. - include: install.yaml # 安装
    35. - include: group.yaml # 建组
    36. - include: user.yaml # 建用户
    37. - include: unarchive.yaml # 解包解压缩
    38. - include: link.yaml # 建软连接
    39. - include: data.yaml # 建数据库初始目录,生成初始数据库
    40. - include: config.yaml # 拷贝配置文件
    41. - include: service.yaml # 启动服务
    42. - include: path.yaml # 配置PATH变量
    43. - include: secure.yaml # 执行安全加固脚本

    第三步:

    1. [root@86-5-master files]# pwd
    2. /data/ansible/roles/mysql5.6/files
    3. [root@86-5-master files]# ll
    4. 总用量 321404
    5. -rw-r--r-- 1 root root 232 1021 07:58 my.cnf
    6. -rw-r--r-- 1 root root 329105487 33 2020 mysql-5.6.44-linux-glibc2.12-x86_64.tar.gz
    7. -rw-r--r-- 1 root root 94 1021 07:57 secure_mysql.sh
    8. [root@86-5-master files]# cat my.cnf
    9. [mysqld]
    10. socket=/tmp/mysql.sock
    11. user=mysql
    12. symbolic-links=0
    13. datadir=/data/mysql
    14. innodb_file_per_table=1
    15. log-bin
    16. pid-file=/data/mysql/mysqld.pid
    17. [client]
    18. port=3306
    19. socket=/tmp/mysql.sock
    20. [mysqld_safe]
    21. log-error=/var/log/mysqld.log
    22. [root@86-5-master files]# cat secure_mysql.sh
    23. #!/bin/bash
    24. /usr/local/mysql/bin/mysql_secure_installation <<EOF
    25. y
    26. magedu
    27. magedu
    28. y
    29. y
    30. y
    31. y
    32. EOF
    33. [root@86-5-master files]# chmod +x secure_mysql.sh

    第四步:制作调用此 nginx 角色的 playbook, 文件所在的路径一定是跟 roles 平级

    1. [root@86-5-master ansible]# ll
    2. drwxr-xr-x 3 root root 19 1020 17:02 roles
    3. [root@86-5-master ansible]# pwd
    4. /data/ansible
    5. [root@86-5-master ansible]# vi /data/ansible/role_mysql5.6.yaml
    6. ---
    7. - hosts: dbserver
    8. remote_user: root
    9. roles:
    10. - role: mysql5.6
    11. 运行playbook
    12. ansible-playbook -C /data/ansible/role_mysql5.6.yaml
    13. ansible-playbook /data/ansible/role_mysql5.6.yaml

    报错提示:matching 'libio.perl-Data-Dumper' found 

    解决方案:1、本地生成 mysql 的 yum 源(没好事) 2、改成安装 autoconf,此包安装时会安装Data:Dumper模块( perl-Data-Dumper-2.145-3.el7.x86_64)

    案例5:实现多角色的选择,剧本 

    1. vim /data/ansible/role_httpd_nginx.yml
    2. ---
    3. - hosts: dbserver
    4. roles:
    5. - {role: httpd,tags: [httpd,web], when: ansible_distibution_major_version=='7'}
    6. - {role: httpd,tags: [httpd,web], when: ansible_distibution_major_version=='8'}
    7. ansibel-playbook -t nginx /data/ansible/role_httpd_nginx.yml



     

  • 相关阅读:
    计算机毕业设计Java教师职称评定系统(源码+系统+mysql数据库+lw文档)
    试除法求素数
    MacOS电脑上面怎么运行Windows软件程序?
    防抖与节流
    POI实现Excel导入和导出(源码测试)
    webrtc性能优化:MacOS下的快速截屏录屏方式
    1162 Postfix Expression – PAT甲级真题
    Java 根据Map的值对 List<Map<String, Object>> 进行排序
    String的常用方法
    01-Linux
  • 原文地址:https://blog.csdn.net/Jerry00713/article/details/127380473