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)
相关推荐
D4c-lovetrain2 小时前
linux实战之多配置部署(ansible、nginx、keepalived、dhcp、dns多元化操作)
linux·运维·服务器
147API2 小时前
Claude 4.6 API 接入全流程避坑:OpenAI 迁移、长上下文超时、429 限流一次讲清
运维·服务器·网络·claude·api大模型
CDN3602 小时前
高防服务器无法远程连接?端口、防火墙与安全组排查
运维·服务器·安全
我爱学习好爱好爱2 小时前
Ansible force_handlers delegate委托 playbook语法格式 template模块
linux·运维·ansible
wzl202612132 小时前
自动化脚本模拟人工操作 — 基于RPA绕过企微API次数限制
自动化·企业微信·rpa
CDN3602 小时前
高防服务器被攻击后 IP 被封?黑洞解封与清洗策略设置
运维·服务器·tcp/ip
2401_827499992 小时前
python项目实战07-DeepSeek调用测试(本地部署)
linux·运维·服务器
longxibo2 小时前
【Ubuntu datasophon1.2.1 二开之九:验证离线数据入湖】
大数据·linux·运维·ubuntu
rainy雨2 小时前
精益班组建设通过标准化作业解决现场管理混乱难题,推动精益班组建设落地
大数据·运维·数据挖掘·数据分析·精益工程