Ansible自动化运维工具

一、Ansible概述和运行机制

1、Ansible概述

Ansible是Red Hat公司使用python研发的开源的自动化运维工具,类似于saltstack和Puppet这样老牌的自动化运维工具。

ansible作为一个后起之秀,在发布的短时间内迅速崛起,超越了大部分老牌的自动化运维工具,其中就包括了Saltstack和Puppet,能获得这样成绩的原因,有一个不同和优点是我们不需要在节点中安装任何客户端。它使用SSH来和节点进行通信。所以只需要被管理节点具备SSH服务以及python即可,无需任何多余操作就可实现自动化管理,而管理节点只需要安装Ansible工具,以及python,openssl即可。

总结:

Ansible是一个部署一群远程主机的工具;Ansible通过SSH协议实现远程节点和管理节点之间的通信。理论上说,只要管理员通过ssh登录到一台远程主机上能做的操作,Ansible都可以做到。Ansible是python开发的,故依赖一些python库和组件,如:paramiko,PyYaml和jinja三个关键组件;
官方网站:https://www.ansible.com/

2、Ansible的工作模块

  • 连接插件connection plugins:负责和被监控端实现通信;
  • host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;
  • 各种模块核心模块、command模块、自定义模块;
  • 借助于插件完成记录日志邮件等功能;
  • playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。

3、Ansible的工作原理

  • 管理端支持local 、ssh、zeromq 三种方式连接被管理端,默认使用基于ssh的连接---这部分对应基本架构图中的连接模块;
  • 可以按应用类型等方式进行Host Inventory(主机群)分类,管理节点通过各类模块实现相应的操作---单个模块,单条命令的批量执行,我们可以称之为ad-hoc;
  • 管理节点可以通过playbooks 实现多个task的集合实现一类功能,如web服务的安装部署、数据库服务器的批量备份等。playbooks我们可以简单的理解为,系统通过组合多条ad-hoc操作的配置文件 。

4、Ansible基本架构

ansible系统由管理节点和被管理节点组成,Ansible 在管理节点将 Ansible 模块通过SSH 协议推送到被管理端执行,执行完之后自动删除,可以使用 SVN、GIT 等来管理自定义模块及编排。


由上面的图可以看到 Ansible 的组成由 5 个部分组成:

  • Ansible: ansible的核心程序
  • Modules:包括 Ansible 自带的核心模块及自定义模块。
  • Core Modules:Ansible执行任何管理任务都不是由Ansible自己完成,而是由核心模块完成;Ansible管理主机之前,先调用core Modules中的模块,然后指明管理Host Inventory中的主机,就可以完成管理主机。
  • Custom Modules:自定义模块,完成Ansible核心模块无法完成的功能,此模块支持任何语言编写。
  • Plugins:模块功能补充,通过插件来实现记录日志,发送邮件或其他功能。
  • Connectior Plugins:连接插件, ansible基于连接插件连接到各个主机上,默认是使用ssh。
  • Playbooks:剧本,YAML格式文件。多个任务定义在一个文件中,定义主机需要调用哪些模块来完成的功能定义,即实现自动化部署文件。
  • Host Inventory: 记录由Ansible管理的主机信息,包括端口、密码、ip等。 ˈɪnvəntri 清单。

右边绿色部分是被管理的主机(虚拟机,物理机,云主机等),从以上架构图中可以看出ansible是由主机清单,playbook以及各模块插件组成。

简单的说就是,用户(管理员)通过ansible的主机清单配置或Playbook配置(一组任务),调用ansible的各种模块及参数来对清单中的主机进行统一管理。

5、Ansible特点

部署简单, 只需要在管理主机上部署ansible环境,被管理端上只要求安装ssh和python 2.5以上版本,这个对于类unix系统来说相当与无需配置。

1、部署简单,只需在管理端部署Ansible环境,被管理端无需做任何操作,即不需要安装agent

2、默认使用SSH协议对设备进行管理

3、易读的语法,基于yaml语法编写playbook

4、模块化设计,调用特定的模块来完成特定任务

5、基于Python语言实现,由Paramiko(python的一个可并发连接ssh主机功能库), PyYAML和Jinja2(模板化)三个关键模块实现。支持API(供第三方程序调用的应用程序编程接口)及自定义模块,可通过Python轻松扩展

6、支持playbook剧本,连续任务按先后设置顺序完成。通过Playbooks来定制强大的配置、状态管理

7、幂等性,一个任务执行一遍和执行n遍效果一样,不会因为重复执行带来意外情况。意味着在同一台服务器上多次执行同一个playbook是安全的

8、对云计算平台、大数据都有很好的支持;

6、安装Ansible

复制代码
 安装阿里源和epel源
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo && yum install -y epel-release

# 安装ansible
yum install -y ansible

7、Ansible配置文件说明

通过rpm -ql ansible可以看到有很多文件,主要是配置文件和和可执行文件,以及所依赖的python库文件。

1)主配置文件**/etc/ansible/ansible.cfg**

  1. inventory = /etc/ansible/hosts #这个参数表示资源清单inventory文件的位置
  2. library = /usr/share/ansible #指向存放Ansible模块的目录,支持多个目录方式,只要用冒号(:)隔开就可以
  3. forks = 5 #并发连接数,默认为5
  4. sudo_user = root #设置默认执行命令的用户
  5. remote_port = 22 #指定连接被管节点的管理端口,默认为22端口,建议修改,能够更加安全
  6. host_key_checking = False #设置是否检查SSH主机的密钥,值为True/False。关闭后第一次连接不会提示配置实例
  7. timeout = 60 #设置SSH连接的超时时间,单位为秒
  8. log_path = /var/log/ansible.log #指定一个存储ansible日志的文件(默认不记录日志)

2)主机清单文件**/etc/ansible/hosts**


公钥认证检查关闭,这样我们就可以正常的访问被管理节点了

编辑主机清单文件

复制代码
vim /etc/ansible/hosts
[all:vars]
ansible_ssh_user=root
ansible_ssh_pass=1
ansible_ssh_port=22
[kubernetes]
192.168.1.111
192.168.1.112
192.168.1.113
192.168.1.114

# ping测试
[root@master ~]# ansible all -m ping 
192.168.1.114 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.1.112 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.1.113 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.1.111 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

8、Ansible命令参数

复制代码
ansible详细参数:
-v   #详细模式,如果命令执行成功,输出详细的结果 (-vv --vvv -vvvv)
-i   #指定清单文件(hosts)的路径,默认是在 /etc/ansible/hosts 
-m  #指定使用的module名称,默认使用 command模块
-a   #指定module模块的参数
-u   #ssh连接的用户名,默认用root,ansible.cfg中可以配置
-k   #提示输入ssh登录密码,当使用密码验证的时候用
-s,--sudo:远程执行命令时使用sudo方式,相当于Linux系统下的sudo命令。
-U  SUDO_USERNAME,sudo到哪个用户,默认为root
注意:上述的-s和-U选项在新版中已经失效。新版本选项如下两项:
-s,--sudo 被改成 -b,--become
-U,--sudo-user被改成  --become-user
-K, --ask-become-pass:使用--become或者--become-user时使用的密码认证(即提示输入sudo密码,当不是NOPASSWD模式时使用)。
-C   #测试此命令执行会改变什么内容,不会真正的去执行
-f FORKS, --forks=FORKS:并行线程数量,当有数量巨大的机器需要配置,可以使用高并发线程,默认是5个。
--list-host:只打印有哪些主机会执行这个命令,不会实际执行


 ansible-doc详细参数:
	ansible-doc -l           #列出所有的模块列表
	ansible-doc -s 模块名    #查看指定模块的参数 -s, --snippet   # [ˈsnɪpɪt]   片断

二、Ansible常用模块

1、命令模块

command

command 模块可以帮助我们在远程主机上执行命令。

注意:使用 command 模块在远程主机中执行命令时,不会经过远程主机的 shell处理,在使用 command 模块时,如果需要执行的命令中含有重定向、管道符等操作时,这些符号也会失效,比如"<", ">", "|", ";" 和 "&" 这些符号,如果你需要这些功能,可以参考后面介绍的 shell 模块。还有一点需要注意,执行ansible时,不加-m 默认使用

默认如果使用别的模块,可以在/etc/ansible/ansible.cfg 中修改

|-----------|--------------------------|
| 参数 | 释义 |
| chdir | 在执行命令前,进入到指定目录中 |
| creates | 判断指定文件是否存在,如果存在,不执行后面的操作 |
| removes | 判断指定文件是否存在,如果存在,执行后面的操作 |
| free_form | 必须要输入一个合理的命令 |

复制代码
# 用ansible查看远程主机的内存
[root@master ~]# ansible kubernetes -m command -a "free -h | grep Mem"
192.168.1.114 | CHANGED | rc=0 >>
              total        used        free      shared  buff/cache   available
Mem:           974M        393M        215M        7.7M        365M        381M
Swap:          2.0G          0B        2.0G
192.168.1.113 | CHANGED | rc=0 >>
              total        used        free      shared  buff/cache   available
Mem:           3.8G        571M        2.3G        4.6M        989M        2.8G
Swap:            0B          0B          0B
192.168.1.112 | CHANGED | rc=0 >>
              total        used        free      shared  buff/cache   available
Mem:           3.8G        778M        2.1G        5.6M        971M        2.6G
Swap:            0B          0B          0B
192.168.1.111 | CHANGED | rc=0 >>
              total        used        free      shared  buff/cache   available
Mem:           3.8G        836M        1.5G        4.1M        1.6G        2.7G
Swap:            0B          0B          0B

可以发现我们的管道符没有起作用。想解决这个问题把command替换为shell模块就可以

# chdir 在执行命令前进入到指定目录
[root@master ~]# ansible kubernetes -m command -a "chdir=/tmp ls -l"
192.168.1.114 | CHANGED | rc=0 >>
total 0
drwx------ 2 root root 41 Jul 18 15:04 ansible_command_payload_bkPqHr
drwx------ 3 root root 17 Jul 18 09:41 systemd-private-db3e50d8d9e947fa916d484e2d394644-chronyd.service-haCV0y
192.168.1.112 | CHANGED | rc=0 >>
total 0
drwx------ 2 root root 41 Jul 18 23:04 ansible_command_payload_sRyXPw
drwx------ 2 root root  6 Jul 11 18:27 vmware-root
192.168.1.113 | CHANGED | rc=0 >>
total 0
drwx------ 2 root root 41 Jul 18 23:04 ansible_command_payload_gER0WV
drwx------ 2 root root  6 Jul 18 17:41 vmware-root
192.168.1.111 | CHANGED | rc=0 >>
total 0
drwx------ 2 root root 41 Jul 18 23:04 ansible_command_payload_xYA2ms
drwx------ 2 root root  6 Jul  9 02:34 vmware-root

# creates 判断判断指定文件是否存在,如果存在,不执行操作
[root@master ~]# ansible kubernetes -m command -a "touch /root/1.txt creates=/root/1.txt"

[root@master ~]# ansible kubernetes -m command -a "touch /root/2.txt creates=/root/1.txt"

# romoves 判断指定文件是否存在,如果存在,执行操作
[root@master ~]# ansible kubernetes -m command -a "rm -rf /root/1.txt removes=/root/1.txt"

shell

shell 模块可以帮助我们在远程主机上执行命令。与 command 模块不同的是,shell模块在远程主机中执行命令时,会经过远程主机上的/bin/sh程序处理,shell模块支持管道与重定向等符号;所以,我们在终端输入的各种命令方式,都可以使用。

复制代码
[root@master ~]# ansible kubernetes -m shell -a "free -h | grep Mem"
192.168.1.114 | CHANGED | rc=0 >>
Mem:           974M        393M        215M        7.8M        365M        380M
192.168.1.112 | CHANGED | rc=0 >>
Mem:           3.8G        776M        2.1G        5.6M        976M        2.6G
192.168.1.113 | CHANGED | rc=0 >>
Mem:           3.8G        572M        2.3G        4.6M        990M        2.8G
192.168.1.111 | CHANGED | rc=0 >>
Mem:           3.8G        839M        1.5G        4.1M        1.5G        2.7G

2、文件模块

copy

实现主控端向目标主机拷贝文件或目录,类似scp功能

|----------------|----------|------------------------------------------------------|
| 参数 | 选项/默认值 | 释义 |
| src | | 指定将本地管理主机的什么数据信息进行远程复制 |
| backup | no* yes | 默认数据复制到远程主机,会覆盖原有文件(yes 将源文件进行备份) |
| content | | 在文件中添加信息 |
| dest(required) | | 将数据复制到远程节点的路径信息 |
| group | | 文件数据复制到远程主机,设置文件属组用户信息 |
| mode | | 文件数据复制到远程主机,设置数据的权限 eg 0644 0755 |
| owner | | 文件数据复制到远程主机,设置文件属主用户信息 |
| remote_src | no* yes | 如果设置为yes,表示将远程主机上的数据进行移动操作如果设置为no, 表示将管理主机上的数据进行分发操作 |

备注:

required:为必须使用的参数

*:为默认参数

copy模块在复制数据时,如果数据为软链接文件,会将链接指定源文件进行复制

修改权限时候 需要加0 例如:chmod 0644 0755

复制代码
[root@master ~]# ansible kubernetes -m copy -a "src=/root/1.txt dest=/root/1.txt"

# backup 如果源文件和目标位置文件的内容不一样,会进行备份,如果内容一样,就不会备份
ansible kubernetes -m copy -a "src=/root/1.txt dest=/tmp backup=yes"
[root@master ~]# ls /tmp/
1.txt  1.txt.60916.2022-07-19@00:20:55~  vmware-root

# owner设置文件属主信息
# group设置文件属组信息
# mode设置文件权限

ansible kubernetes -m copy -a "src=./1.txt dest=/root owner=www group=www mode=0644"

# content 在文件中添加信息 如果文件中有内容的话会被覆盖
ansible kubernetes -m copy -a "content=123 dest=/root/1.txt"

[root@master ~]# cat 1.txt 
123[root@master ~]#
注:content添加内容不会添加回车符 

fetch

从管理主机抓取文件

|---------------|--------------------------|
| 参数 | 释义 |
| src(required) | 要获取的远程系统上的文件,必须是文件,而不是目录 |
| dest | 用于保存文件的目录 |

复制代码
# 将管理主机的hosts文件保存到自己的root下
[root@master ~]# ansible kubernetes -m fetch -a "src=/etc/hosts dest=/root/hosts"

file

实现创建/删除文件信息 对数据权限进行修改

|--------------------------|-----------|----------------------------------|
| 参数 | 选项/默认值 | 释义 |
| dest/path/name(required) | | 将数据复制到远程节点的路径信息 |
| group | | 文件数据复制到远程主机,设置文件属组用户信息 |
| mode | | 文件数据复制到远程主机,设置数据的权限 eg 0644 0755 |
| owner | | 文件数据复制到远程主机,设置文件属主用户信息 |
| src | | 指定将本地管理主机的什么数据信息进行远程复制 |
| state | absent | 将数据进行删除 |
| state | directory | 创建一个空目录信息 |
| state | file | 查看指定目录信息是否存在 |
| state | touch | 创建一个空文件信息 |
| state | hard/link | 创建链接文件 |

复制代码
# 将目标主机的文件权限修改为777
ansible kubernetes -m file -a "path=/etc/hosts mode=777"
# 验证权限
[root@master ~]# ansible kubernetes -m shell -a "ls -ld /etc/hosts"
192.168.1.112 | CHANGED | rc=0 >>
-rwxrwxrwx 1 root root 220 Jun 10 13:53 /etc/hosts
192.168.1.114 | CHANGED | rc=0 >>
-rwxrwxrwx. 1 root root 158 Jun  7  2013 /etc/hosts
192.168.1.113 | CHANGED | rc=0 >>
-rwxrwxrwx 1 root root 220 Jun 10 13:53 /etc/hosts
192.168.1.111 | CHANGED | rc=0 >>
-rwxrwxrwx 1 root root 220 Jun 10 13:53 /etc/hosts

# 将目标主机上的/root/1.txt文件创建符号链接到/tmp下
ansible kubernetes -m file -a "src=/root/1.txt dest=/tmp/1.txt state=link"

# 验证
[root@master ~]# ansible kubernetes -m shell -a "ls -ld /tmp/1.txt"
192.168.1.114 | CHANGED | rc=0 >>
lrwxrwxrwx 1 root root 11 Jul 21 10:25 /tmp/1.txt -> /root/1.txt
192.168.1.112 | CHANGED | rc=0 >>
lrwxrwxrwx 1 root root 11 Jul 21 18:25 /tmp/1.txt -> /root/1.txt
192.168.1.113 | CHANGED | rc=0 >>
lrwxrwxrwx 1 root root 11 Jul 21 18:25 /tmp/1.txt -> /root/1.txt
192.168.1.111 | CHANGED | rc=0 >>
lrwxrwxrwx 1 root root 11 Jul 21 18:25 /tmp/1.txt -> /root/1.txt

# 在目标主机判断目录是否存在,不存在则创建
ansible kubernetes -m file -a "path=/root/dir state=directory"
# 验证
[root@master ~]# ansible kubernetes -m shell -a "ls -ld /root/dir"
192.168.1.114 | CHANGED | rc=0 >>
drwxr-xr-x 2 root root 6 Jul 21 10:31 /root/dir
192.168.1.112 | CHANGED | rc=0 >>
drwxr-xr-x 2 root root 6 Jul 21 18:31 /root/dir
192.168.1.113 | CHANGED | rc=0 >>
drwxr-xr-x 2 root root 6 Jul 21 18:31 /root/dir
192.168.1.111 | CHANGED | rc=0 >>
drwxr-xr-x 2 root root 6 Jul 21 18:31 /root/dir

# 在目标主机创建一个空文件
ansible kubernetes -m file -a "path=/root/test.txt state=touch"
# 验证
[root@master ~]# ansible kubernetes -m shell -a "ls /root/test.txt"
192.168.1.114 | CHANGED | rc=0 >>
/root/test.txt
192.168.1.113 | CHANGED | rc=0 >>
/root/test.txt
192.168.1.112 | CHANGED | rc=0 >>
/root/test.txt
192.168.1.111 | CHANGED | rc=0 >>
/root/test.txt

3、安装模块

yum

使用yum软件包管理器安装,升级,降级,删除和列出软件包和组。

|----------------|-------------------|--------------------|
| 参数 | 选项/默认值 | 释义 |
| name(required) | | 指定软件名称信息 |
| state | absent/removed | 将软件进行卸载(慎用) |
| state | present/installed | 将软件进行安装 |
| state | latest | 安装最新的软件 yum update |

复制代码
# 在目标主机安装最新的httpd
ansible kubernetes -m yum -a "name=httpd state=latest"
# 验证
[root@master ~]# ansible kubernetes -m shell -a "rpm -qa | grep httpd"
192.168.1.112 | CHANGED | rc=0 >>
httpd-tools-2.4.6-97.el7.centos.5.x86_64
httpd-2.4.6-97.el7.centos.5.x86_64
192.168.1.113 | CHANGED | rc=0 >>
httpd-2.4.6-97.el7.centos.5.x86_64
httpd-tools-2.4.6-97.el7.centos.5.x86_64
192.168.1.114 | CHANGED | rc=0 >>
httpd-tools-2.4.6-97.el7.centos.5.x86_64
httpd-2.4.6-97.el7.centos.5.x86_64
192.168.1.111 | CHANGED | rc=0 >>
httpd-2.4.6-97.el7.centos.5.x86_64
httpd-tools-2.4.6-97.el7.centos.5.x86_64

4、服务模块

service

用于管理服务运行状态

|-----------------|------------|-------------------------------------|
| 参数 | 选项/默认值 | 释义 |
| enabled | no yes | 设置服务是否开机自启动 如果参数不指定,原有服务开机自启动状态进行保留 |
| name (required) | | 设置要启动/停止服务名称 |
| state= | reloaded | 平滑重启 |
| state= | restarted | 重启 |
| state= | started | 启动 |
| state= | stopped | 停止 |

复制代码
# 启动httpd服务并设置为开机自启动
ansible kubernetes -m service -a "name=httpd enabled=yes state=started"

# 删除httpd服务
ansible kubernetes -m yum -a "name=httpd state=removed"

5、挂载模块

mount

用于批量管理主机进行挂载卸载操作

|--------|-----------|---------------------|
| 参数 | 选项/默认值 | 释义 |
| fstype | | |
| opts | | |
| path | | |
| src | | |
| state | absent | 会进行卸载,也会修改fstab文件信息 |
| state | unmounted | 会进行卸载,不会修改fstab文件 |
| state | present | 不会挂载,只会修改fstab文件 |
| state | mounted | 会进行挂载,会修改fstab文件 |

复制代码
#只是在/etc/fstab文件中添加了配置信息,不会真正进行挂载(mount -a)
ansible kubernetes -m mount -a "src=172.16.1.31:/data/  path=/mnt fstype=nfs state=present"

# 在/etc/fstab文件中添加了配置信息,并且也会真正进行挂载
ansible kubernetes -m mount -a "src=172.16.1.31:/data/  path=/mnt fstype=nfs state=mounted"

6、定时任务模块

cron

定时任务模块

|-------------------------------|------------|-------------|
| 参数 | 选项/默认值 | 释义 |
| minute/hour/day/month/weekday | | 和设置时间信息相关参数 |
| job | | 和设置定时任务相关参数 |
| name(required) | | 设置定时任务注释信息 |
| state | absent | 删除指定定时任务 |
| disabled | yes | 将指定定时任务进行注释 |
| = | no | 取消注释 |

备注:时间参数不写时,默认为 *

复制代码
# 每五分钟同步一下时间
ansible kubernetes -m cron -a "name='ntpdate time' minute=*/5 job='/usr/sbin/ntpdate ntp1.aliyun.com &>/dev/null' "

# 注释定时任务
注意:注释和取消注释时必须填写 job和时间 参数

ansible kubernetes -m cron -a "name='ntpdate time' minute=*/5 job='/usr/sbin/ntpdate ntp1.aliyun.com &>/dev/null' disabled=yes"


# 取消注释
ansible kubernetes -m cron -a "name='ntpdate time' minute=*/5 job='/usr/sbin/ntpdate ntp1.aliyun.com &>/dev/null' disabled=no"

7、用户模块

group

远程批量创建用户组信息

|--------|------------|-----------|
| 参数 | 选项/默认值 | 释义 |
| gid | | 指创建的组ID信息 |
| name | | 指创建组名称信息 |
| state | absent | 删除指定的用户组 |
| = | present | 创建指定的用户组 |

复制代码
# 创建一个指定的用户组zhangsan gid=1055
ansible kubernetes -m group -a "name=zhangsan gid=1055"

# 删除一个指定的用户组 gid=1055
ansible kubernetes -m group -a "name=zhangsan state=absent"
删除成功的前提是不能有用户把被删除的组当成基本组。会报如下错误:
"msg": "groupdel: cannot remove the primary group of user 'zhangsan'\n",

user

远程批量创建用户信息

|------------------|-------------------------|-----------------------------------------------------------------------------------------------------------------|
| 参数 | 选项/默认值 | 释义 |
| password | | 请输入密码信息 |
| name | | 指定用户名信息 |
| uid | | 指定用户uid信息 |
| group | | 指定用户主要属于哪个组 |
| groups | | 指定用户属于哪个附加组信息 |
| shell | /bin/bash;/sbin/nologin | 指定是否能够登录 |
| create_home | yes/no | 是否创建家目录信息 |
| home | | 指定家目录创建在什么路劲默认是/home |
| state | present | 表示用户需要存在 |
| state | absent | 表示删除用户 |
| remove | yes/no | 是否删除用户的家目录 |
| generate_ssh_key | yes/no | 表示为对应的用户生成 ssh 密钥对,默认在用户家目录的 ./ssh 目录中生成名为 id_rsa 的私钥和名为 id_rsa.pub 的公钥,如果同名的密钥已经存在与对应的目录中,原同名密钥并不会被覆盖(不做任何操作)。 |

备注:password设置密码时不能使用明文方式,只能使用密文方式

可以给用户设置密码 还可以给用户修改密码

复制代码
root@master ~]# python
Python 2.7.5 (default, Apr 11 2018, 07:36:10) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import crypt
>>> crypt.crypt('123456')
'$6$QYPyripe94Z.Cu5a$oYEUFA4eDqJxGgb4VhypXoapt7ZQTTVB8LQbseF4xb.2P202tAoiQzK2kc.3XyJT7eiptjXoetAuftDcKh5WD1'

# 创建一个用户指定密码
[root@master ~]# ansible kubernetes -m user -a "name=zhangsan password='$6$QYPyripe94Z.Cu5a$oYEUFA4eDqJxGgb4VhypXoapt7ZQTTVB8LQbseF4xb.2P202tAoiQzK2kc.3XyJT7eiptjXoetAuftDcKh5WD1'"

# 删除用户及家目录
ansible kubernetes -m user -a "name=zhangsan remove=yes state=absent"

# 创建用户berry,登录shell为/sbin/nologin
ansible kubernetes -m user -a "name=berry shell=/sbin/nologin state=present"

# 删除刚才创建的用户berry及其宿主目录
ansible kubernetes -m user -a "name=berry remove=yes state=absent"

8、脚本模块

script

script只能执行脚本,不能调用其他指令,但是script执行的是存放在ansbile管理端上的脚本

复制代码
管理端的脚步在目标端执行
ansible kubernetes -m script -a "/root/1.sh"

三、Ansible PlayBook

1、PlayBook概述

之前的模块都是使用Ad-hoc方式(Ad-hoc方式是一种可以快速输入的命令,而且不需要保存起来的命令)点对点命令执行,可以管理远程主机,但如果服务器数量比较多,配置信息也比较多,可以利用Ansible PlayBook编写剧本,以更加简便的方式实现任务处理的自动化和流程化。

playbook是Ansible的配置、部署和编排的语言。Playbook可以定制配置,他们可以按照你指定的操作步骤有序执行,支持同步和异步方式。形象点的说就是:如果ansible的各模块(能实现各种功能)是车间里的各工具;playbook就是指导手册,目标远程主机就是库存和原料对象。

playbook可作为一个适合部署复杂应用程序的基础。

PlayBook是由一个或多个"play"组成的列表,在play中的内容被我们称之为tasks,也叫任务,也就是说多个tasks组成了一个play,task调用Ansible的各种模块(module)。将多个play组织在一个playbook剧本中,组成一个完整的流程控制集合,完成一个复杂的工作。

复制代码
说明:
playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。
hosts用于指定要执行指定任务的主机,其可以是一个或多个由冒号分隔主机组。
vars 执行对应任务时,携带的到远端主机的变量信息
remote_user则用于指定远程主机上的执行任务的用户。
play的主体部分是task list。task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。在运行自上而下某playbook时,如果中途发生错误,所有已执行任务都将回滚,因此,在更正playbook后重新执行一次即可。
task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致。
每个task都应该有其name,name 是我们对当前任务的说明,用于playbook的执行结果输出,建议其内容尽可能清晰地描述任务执行步骤。如果未提供name,则执行的模块名将用于输出。
定义task的action(动作)可以使用module_name:module_args"。
一个name只能包括一个task。
在众多模块中,只有command和shell模块仅需要给定一个列表而无需使用"key=value"格式
复制代码
注:
如果命令或脚本的退出码不为零,可以使用如下方式替代:
tasks:
   - name: run this command and ignore the result
    shell: /usr/bin/somecommand || /bin/true
或者使用ignore_errors来忽略错误信息:
tasks:
  - name: run this command and ignore the result
   shell: /usr/bin/somecommand    
   ignore_errors: True

playbook是基于YAML语言格式配置,通过YAML格式来进行描述定义的,扩展名是yml或yaml。

总结:简单来说playbook就是一个用yaml语法把多个模块堆起来的一个文件而已,把不同的模块按照顺序编排在剧本中,ansible就会按照剧本一步一步的执行,最终达到我们的目的。

更多playbook官方说明参考:

http://docs.ansible.com/ansible/latest/playbooks_intro.html

Ansible中文学习手册

https://ansible-tran.readthedocs.io/en/latest/docs/playbooks.html

2、Yaml语言

Playbook采用YAML语言编写,每一个Ansible的Playbook都是一个YAML格式的文件,因此要学习编写剧本(playbook),我们先来了解YAML语法的基本用法。

Yaml语言规则

1、yaml文件以---开头,以表明这是一个yaml文件,就像xml文件在开头使用<?xml version="1.0" encoding="utf-8"?>宣称它是xml文件一样。但即使没有使用---开头,也不会有什么影响。

2、yaml中使用"#"作为注释符。

3、大小写敏感

4、使用缩进表示层级关系:YAML使用一个固定的缩进风格表示层级结构,同样的缩进代表同样的级别。缩进时不允许使用Tab键,只允许使用空格。

注:缩进的空格数目没有限制,但要求同一层级左对齐。判断是否是同一级别是通过缩进结合换行来实现的。

5、冒号,以冒号结尾的除外,其他所有冒号后面必须有空格。

6、短横线,表示列表项,使用一个短横杠加一个空格。多个项使用同样的缩进级别作为同一列表。

7、关于布尔值的书写格式,即true/false的表达方式。其实playbook中的布尔值类型非常灵活,可分为两种情况:

  • 模块的参数:这时布尔值作为字符串被ansible解析。接受yes/on/1/true/no/off/0/false。例如上面示例中的update_cache=yes。
  • 非模块的参数:这时布尔值被yaml解释器解析,完全遵循yaml语法。接受不区分大小写的true/yes/on/y/false/no/off/n。例如上面的gpgcheck=False和enabled=True。

建议遵循ansible的官方规范,模块的布尔参数采用yes/no,非模块的布尔参数采用True/False。

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

对于Ansible, 每一个YAML文件都是从一个列表(列表list,又称为序列 sequence)开始。列表中的每一项都是一个键值对,通常它们被称为一个 "哈希" 或 "字典"或映射。所以, 我们需要知道如何在YAML中编写列表和字典。

  • 列表中的所有成员都开始于相同的缩进级别, 并且使用一个 "- " 作为开头(一个减号和一个空格)。
  • 具体在ansible playbook中,列表所描述的是局部环境,它不一定要有名称,只要使用"- ",它就表示圈定一个范围,范围内的项都属于该列表。例如:


  • 一个字典是由一个简单的 键: 值 的形式组成(这个冒号后面必须是一个空格),它一般当作列表项的属性。
  • n k/v的值可同行写也可换行写。同行使用:分隔
  • n v可是个字符串,也可是另一个列表
  • YAML列表与字典是可以自由组合在一起的,它们之间可以相互嵌套,通过非常灵活的组合,可以帮助我们描述更加复杂的对象属性。
  • 此外, Ansible使用"{{ var }}"来引用变量.。如果一个值以 "{" 开头, YAML 将认为它是一个字典, 所以我们必须引用它, 像这样foo: "{{ var }}"。

PlayBook核心元素及常用参数

playbook核心元素包括:

target:定义playbook的远程主机组

variables:定义playbook使用的变量

tasks:定义远程主机上执行的任务列表

handlers:处理器,当某条件满足时,触发执行的操作,例如修改配置文件之后,启动跟 handlers任务重启相关联的服务

roles:角色,用于层次性,结构化的组织playbook。roles能够根据层次型结构自动装载 变量文件、tasks以及handlers等。

target常用参数
  • hosts:运行指定任务的目标主机,可以是一个主机组、主机、多个主机,中间以冒号分隔,也可以用all参数表示所有主机。
  • remote_user:指定远程主机上的执行任务的用户。
  • gather_facks:获取远程主机facts基础信息

注:remote_user参数以前称为user。它在ansibe1.4中被重命名,以使其与用户模块(用于在远程系统上创建用户)区别。

注:gather_facts: True 表示在远程主机运行setup模块,获取远程主机的facts,facts就是变量,内建变量 。每个主机的各种信息,cpu颗数、内存大小等,会存在facts中的某个变量中,调用后返回很多对应主机的信息。

variable常用参数
  • vars:在yaml文件中定义变量赋值。定义格式,变量名:变量值
  • vars_files:指定变量文件,在文件中定义变量
tasks常用参数
  • name:任务显示名称也是屏幕显示信息
  • module_name: module_args: 需要使用的模块名字: 模块参数
hardler常用参数
  • notify: "notify"这个action可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,取而代之,仅在所有的变化发生完成后一次性地执行指定操作。
  • handler: 也是task的列表。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作

3、PlayBook运行方式

1、ansible-playbook --check playbook.yaml #只检测可能会发生的改变,但不真执行操作

2、ansible-playbook --list-hosts playbook.yaml #列出运行任务的主机

3、ansible-playbook --syntax-check playbook.yaml #检查yaml文件的语法是否正确

4、ansible-playbook -t TAGS_NAME playbook.yaml #表示跳过标签前的步骤,直接从标签位置开始。-t选项执行指定的tag标签任务

注:通过tags参数给指定的任务定义一个调用标识。

复制代码
格式:
- name: NAME
  module: arguments
  tags TAG_ID

例如:

ansible-playbook -C -t 'update config file' /ansible/test1.yaml

5、ansible-playbook playbook.yaml # 运行

四、通过PlayBook批量部署Lnmp环境

本案例是通过rpm包部署LNMP环境(基于aliyun和epel源),如果要通过源码包部署的话,可以编写shell脚本,通过script模块进行批量部署LNMP。

首先,我们可以在 ansible 服务器上安装 LNMP 环境,然后,再将配置文件通过 ansible 拷贝到远程主机上

1、安装lnmp

所以机器安装阿里源

复制代码
# 首先安装阿里源
[root@localhost ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
[root@localhost ~]# yum install -y epel-release

安装nginx

复制代码
[root@localhost ~]# yum -y install nginx && systemctl start nginx && systemctl enable nginx


修改nginx.conf,支持php访问
[root@localhost ~]#  vim /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;
        index index.php index.html;
        include /etc/nginx/default.d/*.conf;

        location / {
        }
        location ~ .*\.(php|php5)?$ {
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            include fastcgi.conf;
        } 
        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
}


# 重启服务
[root@localhost ~]# systemctl restart nginx

安装mysql

复制代码
[root@localhost ~]# yum -y install mariadb-server mariadb

创建数据保存目录
[root@localhost ~]# mkdir -p /data/mysql/data && chown -R mysql:mysql /data/mysql/

启动
[root@localhost ~]# systemctl start mariadb && systemctl enable mariadb

安装php

复制代码
[root@localhost ~]# yum install -y php php-mysql php-fpm && systemctl start php-fpm && systemctl enable php-fpm


创建php的测试页面
[root@localhost ~]# vim /usr/share/nginx/html/index.php
<?php
phpinfo();
?>

2、roles角色

Roles相当于我们剧本当中的角色,每个角色都有不同的事情要做,也正是分工才体现出了每个角色不同的作用,当你需要做不同的事情时,只需要调用不同角色即可。

比如一个互联网公司,想要研发新的软件时,就需要找产品去设计软件,找开发去研发软件,找测试去测试软件,找运维去维护软件,每一个角色都会完成各自的功能,这就是Role的作用。

总结:

Roles 角色:以特定的层级目录结构进行组织的tasks、variables、handlers、templates、files等;相当于函数的调用把各个事件切割成片段来执行。

relos目录结构

复制代码
[root@ceph01 lnmp]# tree /ansible/lnmp/
/ansible/lnmp/
├── ansible.cfg                                     # 整个项目的配置文件
├── hosts                                              # 定义主机的配置文件
├── roles                                               # 定义角色的名字(不能修改)
│   ├── mysql                                        # 角色目录(名字可以修改)
│   │   ├── files                                      
│   │   ├── handlers
│   │   ├── meta
│   │   ├── tasks
│   │   ├── templates
│   │   └── vars
│   ├── nginx                                            # 角色目录(名字可以修改)
│   │   ├── files
│   │   ├── handlers
│   │   ├── meta
│   │   ├── tasks
│   │   ├── templates
│   │   └── vars
│   ├── php                                                # 角色目录(名字可以修改)
│   │   ├── files
│   │   ├── handlers
│   │   ├── meta
│   │   ├── tasks
│   │   ├── templates
│   │   └── vars
│   └── prepare                                           # 角色目录(名字可以修改)
│       ├── files
│       ├── handlers
│       ├── meta
│       ├── tasks
│       ├── templates
│       └── vars        
├── site.yml                                                 # 整个项目的入口文件
└── webserver.yml                                      # 分支的入口文件

注:这些目录、文件都需要自己创建

files/:存储由copy或script等模块调用的文件,例如存放需要同步到远程服务器的源码文件及配置文件等。

tasks/:此目录中至少应该有一个名为main.yml的文件,用于定义各task;其它的文件需要由main.yml进行"包含"调用;

handlers/:此目录中至少应该有一个名为main.yml的文件,用于定义各handler;其它的文件需要由main.yml进行"包含"调用;例如当服务的配置文件发生变化时需要进行的操作,比如:重启服务,重新加载配置文件。

vars/:此目录中至少应该有一个名为main.yml的文件,用于定义各variable(变量);其它的文件需要由main.yml进行"包含"调用;

templates/:存储由template模块调用的模板文本。如用于执行lnmp相关配置文件的模板文件。

meta/:角色定义,可留空。此目录中至少应该有一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关系;其它的文件需要由main.yml进行"包含"调用;

3、配置PlayBook

1)创建相关的目录

复制代码
[root@localhost roles]# mkdir -p /ansible/lnmp/roles/{prepare,nginx,mysql,php}/{tasks,files,templates,vars,meta,handlers}

[root@localhost roles]# touch /ansible/lnmp/ansible.cfg
[root@localhost roles]# touch /ansible/lnmp/hosts
[root@localhost roles]# touch /ansible/lnmp/site.yml
[root@localhost roles]# touch /ansible/lnmp/webserver.yml

2)配置管理主机

复制代码
[root@localhost ~]# ssh-keygen 

[root@ceph01 ~]# ssh-keygen
[root@ceph01 ~]# for i in 14 15; do ssh-copy-id root@192.168.1.$i ;done

# 添加主机清单
[root@localhost ~]# vim /ansible/lnmp/hosts
[nginx]
nginx01 ansible_ssh_host=192.168.1.14 ansible_ssh_port=22 ansible_ssh_user=root
nginx02 ansible_ssh_host=192.168.1.15 ansible_ssh_port=22 ansible_ssh_user=root

[mysql]
mysql01 ansible_ssh_host=192.168.1.14 ansible_ssh_port=22 ansible_ssh_user=root

[php]
php01 ansible_ssh_host=192.168.1.14 ansible_ssh_port=22 ansible_ssh_user=root
php02 ansible_ssh_host=192.168.1.15 ansible_ssh_port=22 ansible_ssh_user=root

[lnmp:children]
nginx
mysql
php

说明:
是不是突然发现了一个不一样的组[lnmp:children],它的意思是,lnmp组由别的组成,具体成员是其他组的组名,这样当调用lnmp组时就会调用其他组内的组员了,同时要注意,lnmp组里的组员,要在lnmp之前声明。

现在我们执行Ansible命令无法找到Lnmp组
因为我们默认是用的是/etc/ansible/hosts文件,这个文件中并没有定义lnmp组,我们的lnmp组存在于我们ansible项目根目录(/ansible/lnmp/)的hosts文件内,如果想使用/ansible/lnmp/路径下的hosts文件,需要修改ansible.cfg配置文件,修改成这样:

复制代码
[root@localhost ~]# vim /ansible/lnmp/ansible.cfg 
[defaults]
host_key_checking = True
inventory = ./hosts

ping 测试
[root@localhost ~]# cd /ansible/lnmp/
[root@localhost lnmp]# ansible lnmp -m ping

3)配置入口文件(site.yaml)

现在我们已经调整好了配置,设置好了主机,接下里就开始写Roles以及Playbook,我们site.yml文件是一切任务的入口文件,因此我们从site.yml开始写。

复制代码
[root@localhost lnmp]# vim site.yml 
---
- import_playbook: webserver.yml

Import_playbook意为包含webserver.yml这个文件,当执行到site.yml文件中的这一行时,就会跑去执行webserver.yml里面的内容,这样我们的项目将会更加模块化,利于管理。

4)配置角色分支的入口文件(webserver.yaml)

webserver.yml当中又要写些什么呢?webserver当中写的是要完成对应的模块功能需要的角色,也就是需要什么样的Role。

例如:我们要完成lnmp项目的第一个role,也就是prepare角色(prepare角色主要任务是:远程主机配置yum源,关闭防火墙,关闭selinux),webserver.yml文件内容如下:

复制代码
[root@localhost lnmp]# vim webserver.yml 
---
- hosts: all
  gather_facts: True
  remote_user: root
  name: prepare system
  roles:
    - prepare
  tags: prepare

说明:

all的意思是,让所有主机执行prepare这个role,如果想要针对于组执行roles,那么就将all换成组名,如果针对于某个主机执行,就写主机的别名或者IP

roles列表当中的prepare是指,我们要执行prepare这个Role,那么我们就需要在roles这个目录下创建一个叫做prepare的文件夹,保证我们的Role能够执行,我们roles选项下的名称就是我们在roles目录中文件夹的名称。

gather_facts: True开启收集主机静态信息,如版本号,操作系统内容等;

tags: prepare,对当前内容进行标记,也就是打标签,在执行时可以使用标签从指定位置开始向下执行,为测试节省时间;
prepare内容说明,存在两个目录,一个是tasks,执行对应任务的目录,一个是templates,进行模版文件复制的目录。

当执行到对应的Role时,Ansbile就会调用对应Role目下的Playbook,也就是调用我们的tasks,所以我们在对应的Role目录下都会存在一个叫做tasks的目录

tasks目录当中文件说明,main.yml,任务的入口文件,执行任务时从此文件开始执行,yum.yml、firewalld.yml、selinux.yml完成对应功能的目录

复制代码
tasks/
├── firewalld.yml      # 防火墙
├── main.yml            # task的入口文件,帮助我们加载对应的功能(名字不可变)
├── selinux.yml        # selinux
└── yum.yml             # 配置yum源

# 创建对应的文件
[root@localhost lnmp]# cd /ansible/lnmp/roles/prepare/tasks/
[root@localhost tasks]# touch {firewalld,main,selinux,yum}.yml
编辑main文件
复制代码
[root@localhost tasks]# vim main.yml 
---
- import_tasks: yum.yml
- import_tasks: firewalld.yml
- import_tasks: selinux.yml

对于关键字段说明:

import_tasks字段,是在main.yml文件当中导入相关功能文件的内容,来执行相关文件name字段,相当于对执行任务的说明

编辑yum.yml
复制代码
[root@localhost tasks]# vim yum.yml 
---
- name: delete repo for system
  shell: rm -fr /etc/yum.repos.d/*

- name: get repo centos6 for aliyun
  get_url:
    url: http://mirrors.aliyun.com/repo/Centos-6.repo
    dest: /etc/yum.repos.d/CentOS-Base.repo
  when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "6")


- name: get repo centos7 for aliyun
  get_url:
    url: http://mirrors.aliyun.com/repo/Centos-7.repo
    dest: /etc/yum.repos.d/CentOS-Base.repo
  when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "7")

- name: get epel repo centos6 for aliyun
  get_url:
    url: http://mirrors.aliyun.com/repo/epel-6.repo
    dest: /etc/yum.repos.d/epel.repo
  when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "6")

- name: get epel repo centos7 for aliyun
  get_url:
    url: http://mirrors.aliyun.com/repo/epel-7.repo
    dest: /etc/yum.repos.d/epel.repo
  when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "7")
编辑firewalld.yml
复制代码
[root@localhost tasks]# vim firewalld.yml 
---
- name: close firewalld
  service: name=firewalld state=stopped enabled=no
编辑selinux.yml
复制代码
[root@localhost tasks]# vim selinux.yml 
---
- name: forever close selinux
  template: src=config.j2 dest=/etc/selinux/config

- name: current close selinux
  command: setenforce 0
  ignore_errors: true            # 忽略错误的意思

对于关键字段说明:

template字段,指定模版文件,该文件必须存在于prepare角色目录下的templates目录中,起名需要加上.j2结尾,将templates下的文件复制到对应主机的对应目录下,src指定源文件,dest指定目标目录及复制到目录后改成什么名字。

在webserver.yml文件将我们要干的事情,全部用角色的身份填写完毕,然后注释掉暂时不执行的内容,以便后续修改

复制代码
[root@localhost lnmp]# vim webserver.yml 
---
- hosts: all
  gather_facts: True
  remote_user: root
  name: prepare system
  roles:
    - prepare
  tags: prepare

#- hosts: nginx
#  gather_facts: True
#  remote_user: root
#  name: Install and config nginx
#  roles:
#    - nginx
#  tags: nginx
#
#- hosts: php
#  gather_facts: True
#  remote_user: root
#  name: Install and config php
#  roles:
#    - php
#  tags: php
#
#- hosts: mysql
#  gather_facts: True
#  remote_user: root
#  name: Install and config mysql
#  roles:
#    - mysql
#  tags: mysql

5)配置nginx相关角色

Nginx角色说明,在nginx目录中除了和prepare目录中一样,具备的tasks和templates以外,还多一个目录叫做handlers,该目录使用来执行notify,handler功能的,后续说明该功能。另外还会用到files和vars目录。

配置nginx的tasks
tasks,templates下目录内容和prepare一样,就不再详细说明,只看内容即可,tasks当中的内容查看。

复制代码
[root@localhost ~]# cd /ansible/lnmp/roles/nginx/tasks
[root@localhost tasks]#  touch {config,install,main,webpage}.yml
main.yml
复制代码
[root@localhost tasks]# vim main.yml 
---
- import_tasks: install.yml
- import_tasks: config.yml
- import_tasks: webpage.yml
install.yml
复制代码
[root@localhost tasks]# vim install.yml 
---
- name: install nginx
  yum: name=nginx state=present
config.yml
复制代码
[root@localhost tasks]# vim config.yml 
---
- name: config nginx
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
  notify: restart nginx

- name: start nginx
  service: name=nginx enabled=yes state=started

说明:

Ansible的template模块。该模块和copy模块作用基本一样,都是把某个文件复制到远端主机上,但是区别在于template模块可以获取变量的值,而copy则是原封不动的把文件内容复制过去。

notify模块,在是在做消息通知,notify上面的内容如果执行成功,就会发出消息,通知notify下方的内容执行,如果上面的内容没有执行,就不会通知下面的内容,如何判断是否执行就看执行过程的返回结果,是changed还是ok,changed是执行了,ok是没执行。

webpage.yml
复制代码
[root@localhost tasks]# vim webpage.yml 
---
- name: provide web page
  #copy: src=index.php dest=/usr/share/nginx/html
  copy: src=/ansible/lnmp/roles/nginx/files/ dest=/usr/share/nginx/html
测试nginx组

准备远程的文件

复制代码
[root@localhost tasks]# vim /ansible/lnmp/roles/nginx/files/testdb.php
<?php
$link=mysql_connect('192.168.1.14','zhangsan','123456');
if ($link)echo "connection success......";
mysql_close();
?>

[root@localhost tasks]# cp /usr/share/nginx/html/index.php /ansible/lnmp/roles/nginx/files/
[root@localhost tasks]# cp /etc/nginx/nginx.conf /ansible/lnmp/roles/nginx/templates/nginx.conf.j2

根据需要修改nginx的配置文件模板

复制代码
[root@localhost tasks]# vim /ansible/lnmp/roles/nginx/templates/nginx.conf.j2
user nginx;
worker_processes {{ ansible_processor_vcpus}};  # 修改cpu进程核心数
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;


-------------

server {
    listen       {{ ngxport }};   # 端口变量
    listen       [::]:80 default_server;
    server_name  _;
    root         /usr/share/nginx/html;
    index index.php index.html;
    include /etc/nginx/default.d/*.conf;

构建nginx的handlers目录和vars/下的main.yml 文件

复制代码
[root@localhost tasks]# vim /ansible/lnmp/roles/nginx/handlers/main.yml
---
- name: restart nginx
  service: name=nginx state=restarted

[root@localhost tasks]# vim /ansible/lnmp/roles/nginx/vars/main.yml
---
ngxport: 80    # 变量的值

[root@localhost lnmp]# ansible-playbook site.yml -t nginx

PLAY [prepare system] *******************************************************************************************************************************************************************************************

PLAY [Install and config nginx] *********************************************************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************************************************************************
ok: [nginx02]
ok: [nginx01]

TASK [install nginx] ********************************************************************************************************************************************************************************************
ok: [nginx01]
ok: [nginx02]

TASK [config nginx] *********************************************************************************************************************************************************************************************
changed: [nginx01]
changed: [nginx02]

TASK [start nginx] **********************************************************************************************************************************************************************************************
changed: [nginx01]
changed: [nginx02]

TASK [nginx : provide web page] *********************************************************************************************************************************************************************************
changed: [nginx02]
changed: [nginx01]

RUNNING HANDLER [restart nginx] *********************************************************************************************************************************************************************************
changed: [nginx01]
changed: [nginx02]

PLAY RECAP ******************************************************************************************************************************************************************************************************
nginx01                    : ok=6    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

6)配置php相关角色

构建php任务,这里我们只用到了tasks,templates和handlers目录,tasks当中的内容查看。

复制代码
[root@localhost lnmp]# cd /ansible/lnmp/roles/php/tasks/
[root@localhost tasks]#  touch {config,install,main}.yml
main.yml
复制代码
[root@localhost tasks]# vim main.yml 
---
- import_tasks: install.yml
- import_tasks: config.yml
install.yml
复制代码
[root@localhost tasks]# vim install.yml 
---
- name: install php php-mysql php-fpm
  yum: name={{ item }} state=latest
  with_items:
    - php
    - php-mysql
    - php-fpm

说明:

发现虽然同是安装应用,用的模块也是yum模块,但是安装名却发生变化,使用了{{ item }}变量,这种方式意味携带变量执行,{{ item }}当中大括号是在说明,我们当前的item是个变量,并不是实际安装的软件名,那么实际的软件名字在哪里,就在下面的with_items当中,每个减号开头字符,都是一个实际软件名,这条task会在执行yum模块时,循环执行,有多少个变量item就执行几回,直到将所有with_items当中的字符全部带入到yum模块中,执行一遍为止。

那么实际这个with_items方法不光能用在yum模块中,只要涉及到循环执行的内容都可以使用,其本质是python的列表,执行过程是遍历一个叫做item的列表,然后来执行其操作内容。

config.yml
复制代码
[root@localhost tasks]# vim config.yml 
---
- name: config php
  template: src=php.ini.j2 dest=/etc/php.ini
  notify: restart php-fpm

- name: config php-fpm
  template: src={{ item.src }} dest={{ item.dest }}
  with_items:
    - { src: "php-fpm.conf.j2",dest: "/etc/php-fpm.conf",mode: "0644" }
    - { src: "www.conf.j2",dest: "/etc/php-fpm.d/www.conf",mode: "0644" }
  notify: restart php-fpm

- name: start php-fpm
  service: name=php-fpm enabled=yes state=started
配置php的handlers目录下的main.yml文件
复制代码
[root@localhost tasks]# vim /ansible/lnmp/roles/php/handlers/main.yml
---
- name: restart php-fpm
  service: name=php-fpm state=restarted
测试php组
复制代码
[root@localhost tasks]# cp /etc/php.ini /ansible/lnmp/roles/php/templates/php.ini.j2
[root@localhost tasks]# cp /etc/php-fpm.conf /ansible/lnmp/roles/php/templates/php-fpm.conf.j2
[root@localhost tasks]# cp /etc/php-fpm.d/www.conf /ansible/lnmp/roles/php/templates/www.conf.j2

打开php组的注释

复制代码
[root@localhost tasks]# vim /ansible/lnmp/webserver.yml
---
- hosts: all
  gather_facts: True
  remote_user: root
  name: prepare system
  roles:
    - prepare
  tags: prepare

- hosts: nginx
  gather_facts: True
  remote_user: root
  name: Install and config nginx
  roles:
    - nginx
  tags: nginx

- hosts: php
  gather_facts: True
  remote_user: root
  name: Install and config php
  roles:
    - php
  tags: php

#- hosts: mysql
#  gather_facts: True
#  remote_user: root
#  name: Install and config mysql
#  roles:
#    - mysql
#  tags: mysql

[root@localhost tasks]# cd /ansible/lnmp/
[root@localhost lnmp]# ansible-playbook site.yml -C -t php   # -C 测试结果不执行

警告不用理会

复制代码
# 执行php组
[root@localhost lnmp]# ansible-playbook site.yml -t php

访问测试

7)配置mysql相关角色

构建mysql任务,这里我们只用到了tasks,templates和handlers目录,tasks当中的内容查看。

复制代码
[root@localhost lnmp]# cd /ansible/lnmp/roles/mysql/tasks/
[root@localhost tasks]# touch {config,install,main}.yml
main.yml
复制代码
[root@localhost tasks]# vim main.yml 
---
- import_tasks: install.yml
- import_tasks: config.yml
install.yml
复制代码
[root@localhost tasks]# vim install.yml 
- name: Installed Mariadb Server
  yum: name={{ packages }} state=present
  vars:
    packages:
      - mariadb
      - mariadb-server
      - MySQL-python

说明:

我们发现在安装数据库的同时,安装了一个叫装MySQL-python的包,这个包是在我们即将配置mysql时使用的,因为我们在配置mysql时调用了Ansible的mysql模块,所以需要由这个包对我们的操作进行支持,没有这个包我们无法使用Ansible的mysql模块。

config.yml
复制代码
[root@localhost tasks]# vim config.yml 
---
- name: create data directory
  file: path=/data/mysql/data state=directory owner=mysql group=mysql

- name: copy mysql config
  template: src=my.cnf.j2 dest=/etc/my.cnf
  notify: restart mysql

- name: start mysql
  service: name=mariadb enabled=yes state=started

- name: set root password
  shell: /usr/bin/mysqladmin -uroot password '1' | /bin/true

- name: create a database
  mysql_db:
    login_host: localhost
    login_user: root
    login_password: "1"
    login_port: 3306
    name: test
    encoding: utf8
    state: present
- name: create a user
  mysql_user:
    login_host: localhost
    login_user: root
    login_password: "1"
    login_port: 3306
    name: zhangsan
    host: '192.168.1.%'
    password: "123456"
    priv: 'test.*:ALL'
    state: present

说明:
其他模块在前面已经说明过了,不再进行赘述,主要介绍涉及的新模块,分别是mysql_db,mysql_user模块
mysql_db模块,对数据库当中的数据库进行操作,可以帮助我们完成create,drop,show等针对数据库的操作。
mysql_user模块,针对于数据库当中用户进行操作,可以帮助我们完成,create,delete,select,grant等对于用户的操作。
如果我们要操作数据库,那必不可少的过程是要登录数据库,对于这点,如果手动执行登录命令,复杂且不好管理,还好Ansible提供了数据库相关模块,对于数据库的操作,我们只需要调用相关模块即可
在调用mysql_db和mysql_user时,统一会用到的参数login_host,login_user,login_password,login_port都是在指定登录时相关信息。
对于mysql_db模块来说,name指定是数据库名,encoding指定创建数据库或操作数据库时使用的字符集,state是指对数据库进行什么样的操作,persent相当于创建数据库,import的是导入数据库,导入数据时使用的数据库文件由target指定,那么如果你想删除一个数据库,只需要将state由persent改成asbent。
在调用mysql_user模块时,我们除了使用了登录的参数外,还有几个额外的参数,name创建或者操作用户时指定用户名,password指定创建用户的密码,host指定创建的用户能在哪里登录,priv指定创建出来的用户具备什么样的权限,state当中作用就和数据库一样了,persent表示创建,absent表示删除
对mysql_user模块的priv书写方式为 "在哪个数据库上.对哪个表:有什么权限"的方式书写,举例:"*.*:all"表示,对所有数据库当中的所有表具备所有权限
构建mysql的handlers目录下的main.yml文件
复制代码
[root@localhost tasks]# vim /ansible/lnmp/roles/mysql/handlers/main.yml
---
- name: restart mysql
  service: name=mariadb state=restarted
测试mysql组
复制代码
[root@localhost tasks]# cp /etc/my.cnf /ansible/lnmp/roles/mysql/templates/my.cnf.j2
[root@localhost tasks]# vim /ansible/lnmp/roles/mysql/templates/my.cnf.j2
[mysqld]
datadir=/data/mysql/data  #修改此行,其他参数保持默认即可

打开mysql组的注释

复制代码
[root@localhost tasks]# vim /ansible/lnmp/webserver.yml 
复制代码
# 执行
[root@localhost lnmp]# ansible-playbook site.yml -t mysql

看一下Python-mysql模块的结果

登录到对应的主机

复制代码
[root@localhost ~]# mysql -uroot -p1
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+
4 rows in set (0.00 sec)

MariaDB [(none)]> select user,host from mysql.user where user="zhangsan";
+----------+-------------+
| user     | host        |
+----------+-------------+
| zhangsan | 192.168.1.% |
+----------+-------------+
1 row in set (0.00 sec)

MariaDB [(none)]> show grants for zhangsan@'192.168.1.%';
+-------------------------------------------------------------------------------------------------------------------+
| Grants for zhangsan@192.168.1.%                                                                                   |
+-------------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'zhangsan'@'192.168.1.%' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' |
| GRANT ALL PRIVILEGES ON `test`.* TO 'zhangsan'@'192.168.1.%'                                                      |
+-------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
相关推荐
XIAOHEZIcode2 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户0328472220702 天前
如何搭建本地yum源(上)
运维
大树885 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠5 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质5 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
Inhand陈工6 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智6 天前
ARP代理--工作原理
运维·网络·arp·arp代理
shushangyun_6 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化
施努卡机器视觉6 天前
SNK施努卡侧滑门锁上滑轮总成自动化装配线,从零件到组件,全流程精密制造方案
运维·自动化·制造
dayuOK63076 天前
写作卡壳怎么办?我的“5分钟启动法”
人工智能·职场和发展·自动化·新媒体运营·媒体