Ansible自动化运维工具

Ansible自动化运维工具

介绍

ansible是新出现的自动化运维工具,由python开发,集合了众多自动化运维工具的优点,实现了批量 系统部署、批量程序部署,批量运行命令等功能。ansible是基于模块工作的,本身没有批量部署的能 力,真正具有批量部署能力的是ansible运行的模块,ansible只是提供一个框架。

核心组件

img

Ansible:Ansible核心程序。
HostInventory:记录由Ansible管理的主机信息,包括端口、密码、ip等。
Playbooks:“剧本”YAML格式文件,多个任务定义在一个文件中,定义主机需要调用哪些模块来完成的功能。
CoreModules核心模块,主要操作是通过调用核心模块来完成管理任务。
CustomModules:自定义模块,完成核心模块无法完成的功能,支持多种语言。
ConnectionPlugins:连接插件,Ansible和Host通信使用

ansible 特点

  1. 部署简单,只需在主控端部署Ansible环境,被控端无需做任何操作;
  2. 默认使用SSH协议对设备进行管理;
  3. 有大量常规运维操作模块,可实现日常绝大部分操作;
  4. 配置简单、功能强大、扩展性强;
  5. 支持API及自定义模块,可通过Python轻松扩展;
  6. 通过Playbooks来定制强大的配置、状态管理;
  7. 轻量级,无需在客户端安装agent,更新时,只需在操作机上进行一次更新即可;
  8. 提供一个功能强大、操作性强的Web管理界面和REST API接口——AWX平台。

ansible 命令执行过程

  1. 加载自己的配置文件,默认/etc/ansible/ansible.cfg
  2. 查找对应的主机配置文件,找到要执行的主机或者组;
  3. 加载自己对应的模块文件,如 command;
  4. 通过ansible将模块或命令生成对应的临时py文件(python脚本), 并将该文件传输至远程服务器;
  5. 对应执行用户的家目录的.ansible/tmp/XXX/XXX.PY文件;
  6. 给文件 +x 执行权限;
  7. 执行并返回结果;
  8. 删除临时py文件,sleep 0退出;

ansible 配置详解

ansible 安装方式

ansible安装常用两种方式,yum安装pip程序安装

使用 pip(python的包管理模块)安装

首先,我们需要安装一个python-pip包,安装完成以后,则直接使用pip命令来安装我们的包

	yum install python-pip
	pip install ansible
使用 yum 安装
	yum install epel-release -y
	yum install ansible –y

ansible 程序结构

安装目录如下(yum安装):
  配置文件目录:/etc/ansible/

  • /etc/ansible/ansible.cfg:主配置文件
  • /etc/ansible/hosts:主机清单文件
  • /etc/ansible/roles:角色目录

执行文件目录:/usr/bin/
  Lib库依赖目录:/usr/lib/pythonX.X/site-packages/ansible/
  Help文档目录:/usr/share/doc/ansible-X.X.X/
  Man文档目录:/usr/share/man/man1/

nsible配置文件查找顺序

  1. 检查环境变量ANSIBLE_CONFIG指向的路径文件(export ANSIBLE_CONFIG=/etc/ansible.cfg);
  2. ~/.ansible.cfg,检查当前目录下的ansible.cfg配置文件;
  3. /etc/ansible.cfg检查etc目录的配置文件。

ansible配置文件

ansible 的配置文件为/etc/ansible/ansible.cfg,ansible 有许多参数,下面列出一些常见的参数:

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

ansuble主机清单

  • 定义主机hosts文件
[root@ansible ~]# tail /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.174.10 ansible
192.168.174.20 node1
192.168.174.30 node2
  • 定义ansible主机清单
[root@ansible ~]# grep -Ev '#|^$' /etc/ansible/hosts 
[all]
ansible
node1
node2
[nodes]
node1
node2
  • 生成主机密钥对
[root@ansible ~]# ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:IVCukQxzkroHAUvVovvB4ga3JrY4OlkwMnV9rZhVEFE root@ansible
The key's randomart image is:
+---[RSA 2048]----+
|o.=o+o. +BE      |
|o.oB.=. o .      |
|.+..= o=..       |
|B.   oo...       |
|.*o .   S        |
|oo+o             |
|o=o..            |
|*+o.             |
|**.              |
+----[SHA256]-----+

  • 发送主机公钥到受控节点实现免密登录
[root@ansible ~]# cd .ssh/
[root@ansible .ssh]# ll
总用量 8
-rw------- 1 root root 1679 9月  11 09:54 id_rsa
-rw-r--r-- 1 root root  394 9月  11 09:54 id_rsa.pub

[root@ansible .ssh]# ssh-copy-id -i id_rsa.pub root@192.168.174.20
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "id_rsa.pub"
The authenticity of host '192.168.174.20 (192.168.174.20)' can't be established.
ECDSA key fingerprint is SHA256:l5y8+0D0KcBmCK2edW3ZSY7RyIDgBdlLOE10JAlVtKk.
ECDSA key fingerprint is MD5:60:21:02:4d:b8:ce:cd:bc:19:33:0d:58:d6:4c:bd:fe.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.174.20's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@192.168.174.20'"
and check to make sure that only the key(s) you wanted were added.

[root@ansible .ssh]# ssh-copy-id -i id_rsa.pub root@192.168.174.30
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "id_rsa.pub"
The authenticity of host '192.168.174.30 (192.168.174.30)' can't be established.
ECDSA key fingerprint is SHA256:l5y8+0D0KcBmCK2edW3ZSY7RyIDgBdlLOE10JAlVtKk.
ECDSA key fingerprint is MD5:60:21:02:4d:b8:ce:cd:bc:19:33:0d:58:d6:4c:bd:fe.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.174.30's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@192.168.174.30'"
and check to make sure that only the key(s) you wanted were added.

  • 测试ssh免密登录
[root@ansible ~]# ssh root@node1
The authenticity of host 'node1 (192.168.174.20)' can't be established.
ECDSA key fingerprint is SHA256:l5y8+0D0KcBmCK2edW3ZSY7RyIDgBdlLOE10JAlVtKk.
ECDSA key fingerprint is MD5:60:21:02:4d:b8:ce:cd:bc:19:33:0d:58:d6:4c:bd:fe.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'node1' (ECDSA) to the list of known hosts.
Last login: Sat Sep 11 09:59:04 2021 from 192.168.174.10

[root@node1 ~]# 登出
Connection to node1 closed.
[root@ansible ~]# ssh root@node2
The authenticity of host 'node2 (192.168.174.30)' can't be established.
ECDSA key fingerprint is SHA256:l5y8+0D0KcBmCK2edW3ZSY7RyIDgBdlLOE10JAlVtKk.
ECDSA key fingerprint is MD5:60:21:02:4d:b8:ce:cd:bc:19:33:0d:58:d6:4c:bd:fe.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'node2' (ECDSA) to the list of known hosts.
Last login: Sat Sep 11 09:59:21 2021 from 192.168.174.10
[root@node2 ~]# 
  • 测试主机连通性
[root@ansible ~]# ansible -m ping nodes			# 显示为绿色
node2 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
node1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

ansible的执行状态

  • 绿色:执行成功并且不需要做改变的操作
  • 黄色:执行成功并且对目标主机做变更
  • 红色:执行失败
  • 粉色:警告信息
  • 蓝色:显示ansible命令执行的过程

ansible 常用命令

ansible 命令集

/usr/bin/ansible  Ansibe AD-Hoc 临时命令执行工具,常用于临时命令的执行
/usr/bin/ansible-doc  Ansible 模块功能查看工具
/usr/bin/ansible-galaxy  下载/上传优秀代码或Roles模块 的官网平台,基于网络的
/usr/bin/ansible-playbook  Ansible 定制自动化的任务集编排工具
/usr/bin/ansible-pull  Ansible远程执行命令的工具,拉取配置而非推送配置(使用较少,海量机器时使用,对运维的架构能力要求较高)
/usr/bin/ansible-vault  Ansible 文件加密工具
/usr/bin/ansible-console  Ansible基于Linux Consoble界面可与用户交互的命令执行工具

其中,我们比较常用的是/usr/bin/ansible/usr/bin/ansible-playbook

ansible-doc 命令

ansible-doc 命令常用于获取模块信息及其使用帮助,一般用法如下:

	ansible-doc -l				#获取全部模块的信息
	ansible-doc -s MOD_NAME		#获取指定模块的使用帮助
[root@server ~]# ansible-doc
Usage: ansible-doc [options] [module...]

Options:
  -h, --help            show this help message and exit  # 显示命令参数API文档
  -l, --list            List available modules  #列出可用的模块
  -M MODULE_PATH, --module-path=MODULE_PATH  #指定模块的路径
                        specify path(s) to module library (default=None)
  -s, --snippet         Show playbook snippet for specified module(s)  #显示playbook制定模块的用法
  -v, --verbose         verbose mode (-vvv for more, -vvvv to enable  # 显示ansible-doc的版本号查看模块列表:
                        connection debugging)
  --version             show program's version number and exit
  • 以mysql为例
[root@server ~]# ansible-doc -l |grep mysql
mysql_db                           Add or remove MySQL databases from a remote...
mysql_replication                  Manage MySQL replication                   
mysql_user                         Adds or removes a user from a MySQL databas...
mysql_variables                    Manage MySQL global variables      
[root@server ~]# ansible-doc -s mysql_user
[root@ansible ~]# ansible-doc -s mysql_user
- name: Adds or removes a user from a MySQL database
  mysql_user:
      append_privs:          # Append the privileges defined by priv to the existing ones
                               for this user instead of
                               overwriting existing ones.
      ca_cert:               # The path to a Certificate Authority (CA) certificate. This
                               option, if used, must
                               specify the same certificate
                               as used by the server.
      check_implicit_admin:   # Check if mysql allows login as root/nopassword before
                               trying supplied credentials.
      client_cert:           # The path to a client public key certificate.
      client_key:            # The path to the client private key.
      config_file:           # Specify a config file from which user and password are to
                               be read.
      connect_timeout:       # The connection timeout when connecting to the MySQL server.
      encrypted:             # Indicate that the 'password' field is a
                               `mysql_native_password`
                               hash.
      host:                  # The 'host' part of the MySQL username.
      host_all:              # Override the host option, making ansible apply changes to
                               all hostnames for a given
                               user. This option cannot be
                               used when creating users.
      login_host:            # Host running the database.
      login_password:        # The password used to authenticate with.
      login_port:            # Port of the MySQL server. Requires `login_host' be defined
                               as other than localhost if
                               login_port is used.
      login_unix_socket:     # The path to a Unix domain socket for local connections.
      login_user:            # The username used to authenticate with.
      name:                  # (required) Name of the user (role) to add or remove.
      password:              # Set the user's password..

ansible 命令详解

命令的具体格式如下:

ansible <host-pattern> [-f forks] [-m module_name] [-a args]

也可以通过ansible -h来查看帮助,下面我们列出一些比较常用的选项,并解释其含义:

-a MODULE_ARGS   #模块的参数,如果执行默认COMMAND的模块,即是命令参数,如: “date”,“pwd”等等
-k--ask-pass #ask for SSH password。登录密码,提示输入SSH密码而不是假设基于密钥的验证
--ask-su-pass #ask for su password。su切换密码
-K--ask-sudo-pass #ask for sudo password。提示密码使用sudo,sudo表示提权操作
--ask-vault-pass #ask for vault password。假设我们设定了加密的密码,则用该选项进行访问
-B SECONDS #后台运行超时时间
-C #模拟运行环境并进行预运行,可以进行查错测试
-c CONNECTION #连接类型使用
-f FORKS #并行任务数,默认为5
-i INVENTORY #指定主机清单的路径,默认为/etc/ansible/hosts
--list-hosts #查看有哪些主机组
-m MODULE_NAME #执行模块的名字,默认使用 command 模块,所以如果是只执行单一命令可以不用 -m参数
-o #压缩输出,尝试将所有结果在一行输出,一般针对收集工具使用
-S #用 su 命令
-R SU_USER #指定 su 的用户,默认为 root 用户
-s #用 sudo 命令
-U SUDO_USER #指定 sudo 到哪个用户,默认为 root 用户
-T TIMEOUT #指定 ssh 默认超时时间,默认为10s,也可在配置文件中修改
-u REMOTE_USER #远程用户,默认为 root 用户
-v #查看详细信息,同时支持-vvv-vvvv可查看更详细信息

ansible 常用模块

1) 主机连通性测试

我们使用ansible web -m ping命令来进行主机连通性测试

[root@ansible ~]# ansible nodes -m ping
node2 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
node1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

2)command 模块

  • 默认使用的模块

  • 这个模块可以直接在远程主机上执行命令,并将结果返回本主机。

  • 不支持管道,变量及重定向等

[root@ansible ~]# ansible-doc -s command - name: Executes a command on a remote node
[root@ansible ~]# ansible node1 -m command -a 'ss -tanl'
node1 | CHANGED | rc=0 >>
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
LISTEN     0      128          *:22                       *:*                  
LISTEN     0      100    127.0.0.1:25                       *:*                  
LISTEN     0      128         :::22                      :::*                  
LISTEN     0      100        ::1:25                      :::* 

3)shell 模块

shell模块可以在远程主机上调用shell解释器运行命令,支持shell的各种功能,例如管道等。

[root@ansible ~]# ansible node1 -m shell -a "cat /etc/passwd | grep 'root'"
node1 | CHANGED | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

4)user模块

[root@node1 ~]# ansible-doc -s user
comment # 用户的描述信息
createhom # 是否创建家目录
force # 在使用`state=absent'是, 行为与`userdel --force'一致.
group # 指定基本组
groups # 指定附加组,如果指定为('groups=')表示删除所有组
home # 指定用户家目录
name # 指定用户名
password # 指定用户密码
remove # 在使用 `state=absent'时, 行为是与 `userdel --remove'一致.
shell # 指定默认shell
state #设置帐号状态,不指定为创建,指定值为absent表示删除
system # 当创建一个用户,设置这个用户是系统用户。这个设置不能更改现有用户
uid #指定用户的uid
update_password # 更新用户密码
expires #指明密码的过期时间

示例:

1.添加系统用户,指定uid、家目录、主组及注释
[root@ansible ~]# ansible -m user -a "system=yes name=zhangsan home=/home/zhangsan uid=111  comment='hello zhangsan'" node1
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "comment": "hello zhangsan", 
    "create_home": true, 
    "group": 111, 
    "home": "/home/zhangsan", 
    "name": "zhangsan", 
    "shell": "/bin/bash", 
    "state": "present", 
    "system": true, 
    "uid": 111
}
2.删除用户及家目录
[root@ansible ~]# ansible -m user -a "name=zhangsan state=absent remove=yes" node1
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "force": false, 
    "name": "zhangsan", 
    "remove": true, 
    "state": "absent", 
    "stderr": "userdel: zhangsan 邮件池 (/var/spool/mail/zhangsan) 未找到\n", 
    "stderr_lines": [
        "userdel: zhangsan 邮件池 (/var/spool/mail/zhangsan) 未找到"
    ]
}

5)group模块

[root@node1 ~]# ansible-doc -s group
- name: 添加或删除组
action: group
gid # 设置组的GID号
name= # 管理组的名称
state # 指定组状态,默认为创建,设置值为absent为删除
system # 设置值为yes,表示为创建系统组

示例:

1.创建用户组
[root@ansible ~]# ansible -m group -a "name=mocking gid=111 system=yes" node1
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 111, 
    "name": "mocking", 
    "state": "present", 
    "system": true
}
2.删除用户组
[root@ansible ~]# ansible -m group -a "name=mocking gid=111 state=absent" node1
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "mocking", 
    "state": "absent"
}

6)script 模块

该模块用于将本机的脚本在被管理端的机器上运行。

free_form参数: 必须参数,指定需要执行的脚本,脚本位于 ansible 管理主机本地,并没有具体的一个参数名叫 free_form,具体解释请参考 command 模块。
chdir参数: 此参数的作用就是指定一个远程主机中的目录,在执行对应的脚本之前,会先进入到chdir 参数指定的目录中。
creates参数: 使用此参数指定一个远程主机中的文件,当指定的文件存在时,就不执行对应脚本,可参考 command 模块中的解释。
removes参数: 使用此参数指定一个远程主机中的文件,当指定的文件不存在时,就不执行对应脚本,可参考 command 模块中的解释。

示例:

  • 首先,我们写一个脚本,并给其加上执行权限:
[root@server ~]# vim /tmp/df.sh
	#!/bin/bash

	date >> /tmp/disk_total.log
	df -lh >> /tmp/disk_total.log 
[root@server ~]# chmod +x /tmp/df.sh 
  • 运行命令来实现在被管理端执行该脚本
[root@ansible ~]# ansible node1 -m script -a "/tmp/df.sh"
node1 | CHANGED => {
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to node1 closed.\r\n", 
    "stderr_lines": [
        "Shared connection to node1 closed."
    ], 
    "stdout": "", 
    "stdout_lines": []
}
  • 查看文件内容
[root@ansible ~]# ansible node1 -m shell -a " cat /tmp/disk_total.log"
node1 | CHANGED | rc=0 >>
2021年 09月 11日 星期六 12:13:31 CST
文件系统                 容量  已用  可用 已用% 挂载点
/dev/mapper/centos-root   17G  1.5G   16G    9% /
devtmpfs                 898M     0  898M    0% /dev
tmpfs                    910M     0  910M    0% /dev/shm
tmpfs                    910M  9.6M  901M    2% /run
tmpfs                    910M     0  910M    0% /sys/fs/cgroup
/dev/sda1               1014M  146M  869M   15% /boot
tmpfs                    182M     0  182M    0% /run/user/0

7) copy

[root@node1 ~]# ansible-doc -s copy
backup:在覆盖之前,将源文件备份,备份文件包含时间信息。
content:用于替代“src”,可以直接设定指定文件的值
dest:必选项。要将源文件复制到的远程主机的绝对路径
directory_mode:递归设定目录的权限,默认为系统默认权限
force:强制覆盖目的文件内容,默认为yes
others:所有的file模块里的选项都可以在这里使用
src:被复制到远程主机的本地文件,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归 复制
ansible -m copy -a "src=/本地文件 dest=/远程文件" nodes
  • 在创建文件时修改文件的属主和属组信息
[root@ansible ~]# ansible -m copy -a "src=/root/test1 dest=/root/test owner=root group=root" node1
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709", 
    "dest": "/root/test", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "d41d8cd98f00b204e9800998ecf8427e", 
    "mode": "0644", 
    "owner": "root", 
    "size": 0, 
    "src": "/root/.ansible/tmp/ansible-tmp-1631335550.82-23060-93283576299397/source", 
    "state": "file", 
    "uid": 0
}
  • 在传输文件时修改文件的权限信息,并且备份远程主机文件
[root@ansible ~]# ansible -m copy -a "src=/root/test1 dest=/root/test bakup=yes mode=1777" node1 
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709", 
    "dest": "/root/test", 
    "gid": 0, 
    "group": "root", 
    "mode": "01777", 
    "owner": "root", 
    "path": "/root/test", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}
  • 创建一个文件并直接编辑文件
[root@ansible ~]# ansible -m copy -a "content='hello siri' dest=/root/test1" node1

8) file

该模块主要用于设置文件的属性,比如创建文件、创建链接文件、删除文件等。

[root@node1 ~]# ansible-doc -s file
- name: Sets attributes of files
force:需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况下;另一
种是目标软 链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no
group:定义文件/目录的属组
mode:定义文件/目录的权限
owner:定义文件/目录的属主
path:必选项,定义文件/目录的路径
recurse:递归设置文件的属性,只对目录有效
src:被链接的源文件路径,只应用于state=link的情况
dest:被链接到的路径,只应用于state=link的情况
state:
absent: 删除文件
directory:如果目录不存在,就创建目录
file:验证文件是否存在,即使文件不存在,也不会被创建
link:创建软链接
hard:创建硬链接
touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其后修改时间

示例:

创建目录
[root@ansible ~]# ansible -m file -a "name=test1 owner=root group=root mode=1644 state=directory " server2
创建文件
[root@ansible ~]# ansible -m file -a "path=/root/test2 owner=root group=root mode=1644 state=touch" server2
删除文件
[root@ansible ~]# ansible -m file -a "path=/root/test2 owner=root group=root mode=1644 state=absent" server2
创建软链文件
[root@ansible ~]# ansible -m file -a "src=/root/test1 dest=/root/test2 state=link" server2
创建硬链接文件
[root@ansible ~]# ansible -m file -a "src=/root/test.txt dest=/root/test2 state=hard" server2

9) yum

[root@node1 ~]# ansible-doc -s yum
conf_file #设定远程yum安装时所依赖的配置文件。如配置文件没有在默认的位置。
disable_gpg_check #是否禁止GPG checking,只用于`present' or `latest'。
disablerepo #临时禁止使用yum库。 只用于安装或更新时。
enablerepo #临时使用的yum库。只用于安装或更新时。
name= #所安装的包的名称
state #present安装, latest安装新的, absent 卸载软件。
update_cache #强制更新yum的缓存

示例:

ansible -m yum -a "name=httpd state=latest" nodes

10) service

[root@node1 ~]# ansible-doc service
> SERVICE (/usr/lib/python2.7/site-packages/ansible/modules/system/service.py)
	Controls services on remote hosts. Supported init systems include BSD init, OpenRC, SysV, Solaris
	SMF, systemd, upstart. For Windows targets, use the [win_service] module instead.
    * note: This module has a corresponding action plugin.
    arguments #命令行提供额外的参数
    enabled #设置开机启动,可以设置为yes或者no。
    name= #服务名称
    runlevel #开机启动的级别,一般不用指定。
    sleep #在重启服务的过程中,是否等待。如在服务关闭以后等待2秒再启动。
    state #started启动服务, stopped停止服务, restarted重启服务, reloaded重载配置

示例:

  • 设置开机自启动服务
ansible -m service -a "name=httpd state=started" nodes

11)selinux

[root@node1 ~]# ansible-doc -s selinux
# selinux模块针对selinux的修改操作是针对配置文件进行修改的
- name: Change policy and state of SELinux
selinux:
	configfile: # path to the SELinux configuration file, if non-standard
	policy: # name of the SELinux policy to use
	state: # (required) The SELinux mode

12)cron 模块

该模块适用于管理cron计划任务的。
  其使用的语法跟我们的crontab文件中的语法一致,同时,可以指定以下选项:

day= #日应该运行的工作( 1-31, *, */2, )
hour= # 小时 ( 0-23, *, */2, )
minute= #分钟( 0-59, *, */2, )
month= # 月( 1-12, *, /2, )
weekday= # 周 ( 0-6 for Sunday-Saturday, )
job= #指明运行的命令是什么
name= #定时任务描述
reboot # 任务在重启时运行,不建议使用,建议使用special_time
special_time #特殊的时间范围,参数:reboot(重启时),annually(每年),monthly(每月),weekly(每周),daily(每天),hourly(每小时)
state #指定状态,present表示添加定时任务,也是默认设置,absent表示删除定时任务
user # 以哪个用户的身份执行

添加计划任务

[root@ansible ~]# ansible node1 -m cron -a 'name="ntp update every 5min" minute=*/5 job="/sbin/ntpdate 192.168.174.10 &> /dev/null"'
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": [
        "ntp update every 5min"
    ]
}

我们可以去查看一下:

[root@ansible ~]# ansible node1 -m shell -a "crontab -l"
node1 | CHANGED | rc=0 >>
#Ansible: ntp update every 5min
*/5 * * * * /sbin/ntpdate 192.168.174.10 &> /dev/null
set up
ansible -m setup nodes #获取远程主机的详细信息
ansible-doc -l # 可以查询ansible具有的所有模块

https://docs.ansible.com/ansible/latest/index.html # 官方文档

Playbook

简介

playbook是由一个或者多个play组成的列表,可以让这些列表按事先编排的机制执行;所谓task是调用 ansible的具体模块,在模块参数中可以使用变量。模块执行是幂等性的,意味着多次执行结果相同。使 用yaml语言编写playbook,后缀名一般为.yml

特点

  • yaml的可读性好
  • yaml和脚本语言的交互性好
  • yaml使用实现语言的数据类型
  • yaml有一个一致性的信息模型
  • yaml易于实现
  • yaml可以基于流来处理

核心组件

  • hosts:执行的远程主机列表
  • tasks:任务,由模块定义操作列表
  • variables:内置变量或者自定义变量
  • templates:模板,定义模板文件,模板文件一般是由jinja2语言编写的
  • handlers:和notity结合使用,为条件触发操作,满足条件则执行
  • roles:角色

Playbook语法

playbook使用yaml语法格式,后缀可以是yaml,也可以是yml

  • 在单一一个playbook文件中,可以连续三个连子号(---)区分多个play。还有选择性的连续三个点好(...)用来表示play的结尾,也可省略。
  • 次行开始正常写playbook的内容,一般都会写上描述该playbook的功能。
  • 使用#号注释代码。
  • 缩进必须统一,不能空格和tab混用。
  • 缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行实现的。
  • YAML文件内容和Linux系统大小写判断方式保持一致,是区分大小写的,k/v的值均需大小写敏感
  • k/v的值可同行写也可以换行写。同行使用:分隔。
  • v可以是个字符串,也可以是一个列表
  • 一个完整的代码块功能需要最少元素包括 name: task

官方示例

官方文档: http://www.ansible.com.cn/docs/playbooks_intro.html

在线检测工具:http://www.yamllint.com/

---
- hosts: webservers
  vars:
    http_port: 80
    max_clients: 200
  remote_user: root
  tasks:
  - name: ensure apache is at the latest version
    yum: pkg=httpd state=latest
  - name: write the apache config file
    template: src=/srv/httpd.j2 dest=/etc/httpd.conf
    notify:
    - restart apache
  - name: ensure apache is running
    service: name=httpd state=started
  handlers:
    - name: restart apache
      service: name=httpd state=restarted
常见变量
主机名: "{{ ansible_hostname }}"
操作系统版本: "{{ ansible_distribution }}" "{{ ansible_distribution_version
}}"
内核版本: "{{ ansible_kernel }}"
系统位数: "{{ ansible_userspace_bits }}"
网卡:"{{ ansible_eth0["device"] }}"
IP地址: "{{ ansible_eth0["ipv4"]["address"] }}"
子网掩码: "{{ ansible_eth0["ipv4"]["netmask"] }}"
总内存: "{{ ansible_memory_mb["real"]["total"] }}"
内存空闲: "{{ ansible_memfree_mb }}"

自定义剧本

安装httpd

[root@ansible ansible]# cat httpd_install.yml 
- name: Configure Apache HTTP Server
  hosts: node1
  remote_user: root

  tasks:
    - name: Install httpd
      yum:  
        name: httpd
        state: latest

    - name: Start httpd
      service:
        name: httpd
        state: started
  • 检查脚本格式
[root@ansible ansible]# ansible-playbook --syntax-check httpd_install.yml 

playbook: httpd_install.yml
  • 执行脚本
[root@ansible ansible]# ansible-playbook httpd_install.yml 

PLAY [Configure Apache HTTP Server] *******************************************************

TASK [Gathering Facts] ********************************************************************
ok: [node1]

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

TASK [Start httpd] ************************************************************************
changed: [node1]

PLAY RECAP ********************************************************************************
node1                      : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

定义网站内容

[root@ansible ansible]# cat template/index.j2 
<h1>hello siri~</h1>
这是我的博客地址,欢迎大家学习ansible!

This web server is {{ ansible_hostname }}

[root@ansible ansible]# cat index.yml 
- name: Configure Apache index file
  hosts: nodes
  remote_user: root

  tasks: 
    - name: Copy index.j2 to nodes servers 
      template: 
        src: /ansible/template/index.j2
        dest: /var/www/html/index.html
       
  • 执行脚本
[root@ansible ansible]# ansible-playbook httpd_install.yml 

PLAY [Configure Apache HTTP Server] *******************************************************

TASK [Gathering Facts] ********************************************************************
ok: [node2]
ok: [node1]

TASK [Install httpd] **********************************************************************
ok: [node1]
changed: [node2]

TASK [Start httpd] ************************************************************************
ok: [node1]
changed: [node2]

PLAY RECAP ********************************************************************************
node1                      : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
node2                      : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@ansible ansible]# ansible-playbook index.yml 

PLAY [Configure Apache index file] ********************************************************

TASK [Gathering Facts] ********************************************************************
ok: [node1]
ok: [node2]

TASK [Copy index.j2 to nodes servers] *****************************************************
ok: [node1]
changed: [node2]

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

  • 验证
[root@ansible ansible]# curl node1
<h1>hello siri~</h1>
这是我的博客地址,欢迎大家学习ansible!

This web server is node1

[root@ansible ansible]# curl node2
<h1>hello siri~</h1>
这是我的博客地址,欢迎大家学习ansible!

This web server is node2

条件判断

  • 选择性关闭node1的apache服务
[root@ansible ansible]# cat httpd_stop.yml 
- name: Stop httpd
  hosts: nodes
  remote_user: root

  tasks:
  - name: stop httpd
    service:
      name: httpd
      state: stopped

    when: ansible_hostname == "node1"
[root@ansible ansible]# ansible-playbook --syntax-check httpd_stop.yml 

playbook: httpd_stop.yml
[root@ansible ansible]# ansible-playbook httpd_stop.yml 

PLAY [Stop httpd] *************************************************************************

TASK [Gathering Facts] ********************************************************************
ok: [node1]
ok: [node2]

TASK [stop httpd] *************************************************************************
skipping: [node2]
changed: [node1]

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

循环迭代

  • 创建用户
[root@ansible ansible]# cat user_create.yml 
- name: Create User
  hosts: node1
  remote_user: root

  tasks:
    - name: Create server users
      user:
        name: "{{ item.name }}"
        group: "{{ item.group }}"
        state: "present"
      with_items:
        - { name: 'zhangsan', group: 'wheel'}
        - { name: 'lisi', group: 'root'}

[root@ansible ansible]# ansible-playbook user_create.yml 

PLAY [Create User] ************************************************************************

TASK [Gathering Facts] ********************************************************************
ok: [node1]

TASK [Create server users] ****************************************************************
changed: [node1] => (item={u'group': u'wheel', u'name': u'zhangsan'})
changed: [node1] => (item={u'group': u'root', u'name': u'lisi'})

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

# 验证
[root@node1 ~]# id zhangsan
uid=1000(zhangsan) gid=10(wheel) 组=10(wheel)
[root@node1 ~]# id lisi
uid=1001(lisi) gid=0(root) 组=0(root)

安装nginx并且修改配置文件

[root@VM-4-10-centos ~]# cat nginx.yaml 
- name: Update web servers
  hosts: node1
  remote_user: root
 
  tasks: 
  - name: install epel
    yum:
      name: epel-release.noarch
      state: latest
  
  - name: install nginx
    yum:
      name: nginx
      state: present
 
  - name: copy nginx configure file
    copy:
      src: /root/ansible/conf/site1.conf
      dest: /etc/nginx/conf.d/site1.conf

  - name: creat dir
    shell: mkdir -pv /usr/share/nginx/html/{bbs,blog,www}

  - name: creat index1.html
    shell: echo "bbs" > /usr/share/nginx/html/bbs/index.html && echo "www" > /usr/share/nginx/html/www/index.html && echo "blog" > /usr/share/nginx/html//blog/index.html

  - name: start nginx
    service:
      name: nginx
      state: restarted
  • 定义conf文件
[root@VM-4-10-centos ~]# cat site1.conf 
server {
  listen  *:8080;
  server_name bbs.eagle.com;
  location / {
  root /usr/share/nginx/html/bbs;
  index index.html;
}
}
server {
  listen  *:8080;
  server_name blog.eagle.com;
  location / {
  root /usr/share/nginx/html/blog;
  index index.html;
}
}
server {
  listen  *:8080;
  server_name www.eagle.com;
  location / {
  root /usr/share/nginx/html/www;
  index index.html;
}
}
[root@ansible bin]#  ansible-playbook nginx.yaml
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv
to see details

PLAY [Update web servers] ***********************************************************

TASK [Gathering Facts] **************************************************************
ok: [server2]

TASK [install epel] *****************************************************************
ok: [server2]

TASK [install nginx] ****************************************************************
ok: [server2]

TASK [copy nginx configure file] ****************************************************
changed: [server2]

TASK [creat dir] ********************************************************************
[WARNING]: Consider using the file module with state=directory rather than running
'mkdir'.  If you need to use command because file is insufficient you can add 'warn:
false' to this command task or set 'command_warnings=False' in ansible.cfg to get
rid of this message.
changed: [server2]

TASK [creat index1.html] ************************************************************
changed: [server2]

TASK [creat index2.html] ************************************************************
changed: [server2]

TASK [creat index3.html] ************************************************************
changed: [server2]

TASK [start nginx] ******************************************************************
changed: [server2]

PLAY RECAP **************************************************************************
server2                    : ok=9    changed=6    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

  • 验证
[root@ansible bin]# curl bbs.eagle.com:8080
bbs
[root@ansible bin]# curl blog.eagle.com:8080
blog
[root@ansible bin]# curl www.eagle.com:8080
www

roles介绍

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

一个项目的结构如下:

site.yml
webservers.yml
fooservers.yml
roles/
   common/
     files/
     templates/
     tasks/
     handlers/
     vars/
     defaults/
     meta/
   webservers/
     files/
     templates/
     tasks/
     handlers/
     vars/
     defaults/
     meta/

一个 playbook 如下:

---
- hosts: webservers
  roles:
     - common
     - webservers

这个 playbook 为一个角色 ‘x’ 指定了如下的行为:

  • 如果 roles/x/tasks/main.yml 存在, 其中列出的 tasks 将被添加到 play 中
  • 如果 roles/x/handlers/main.yml 存在, 其中列出的 handlers 将被添加到 play 中
  • 如果 roles/x/vars/main.yml 存在, 其中列出的 variables 将被添加到 play 中
  • 如果 roles/x/meta/main.yml 存在, 其中列出的 “角色依赖” 将被添加到 roles 列表中 (1.3 and later)
  • 所有 copy tasks 可以引用 roles/x/files/ 中的文件,不需要指明文件的路径。
  • 所有 script tasks 可以引用 roles/x/files/ 中的脚本,不需要指明文件的路径。
  • 所有 template tasks 可以引用 roles/x/templates/ 中的文件,不需要指明文件的路径。
  • 所有 include tasks 可以引用 roles/x/tasks/ 中的文件,不需要指明文件的路径。

示例:

[root@ansible ansible]# cd /etc/ansible/roles/
[root@ansible roles]# ansible-galaxy init apache
- Role apache was created successfully
[root@ansible roles]# ls
apache
[root@ansible roles]# ll apache/
总用量 4
drwxr-xr-x 2 root root   22 9月  11 21:20 defaults
drwxr-xr-x 2 root root    6 9月  11 21:20 files
drwxr-xr-x 2 root root   22 9月  11 21:20 handlers
drwxr-xr-x 2 root root   22 9月  11 21:20 meta
-rw-r--r-- 1 root root 1328 9月  11 21:20 README.md
drwxr-xr-x 2 root root   22 9月  11 21:20 tasks
drwxr-xr-x 2 root root    6 9月  11 21:20 templates
drwxr-xr-x 2 root root   39 9月  11 21:20 tests
drwxr-xr-x 2 root root   22 9月  11 21:20 vars
[root@ansible roles]# tree /etc/ansible/roles/
/etc/ansible/roles/
└── apache
    ├── defaults
    │   └── main.yml
    ├── files
    ├── handlers
    │   └── main.yml
    ├── meta
    │   └── main.yml
    ├── README.md
    ├── tasks
    │   └── main.yml
    ├── templates
    ├── tests
    │   ├── inventory
    │   └── test.yml
    └── vars
        └── main.yml

* 目录结构:
- tasks:此目录中至少有一个名为main.yaml文件,用于定义各种task,其他文件需要由main.yaml文件进行调用
- handlers:此目录中至少有一个名为main.yaml文件,用于定义各种handler,其他文件需要被main.yaml进行调用
- vars:此目录中至少有一个名为main.yaml文件,用于定义各种变量,其他文件需要被main.yaml进行调用
- templates:存储template模块调用的模板文件
- meta:此目录中至少有一个名为main.yaml文件,定义当前角色的设定及其依赖关系,其他的文件需要被main.yaml文件进行调用
- default:此目录中至少有一个main.yaml文件,用于设定默认的值
- files:此目录存放copy或者script等模块调用的文件

使用角色安装httpd

  • 准备tasks里的main.yml文件
[root@ansible tasks]# cat main.yml 
---
# tasks file for apache
- name: Install httpd
  yum:
    name: httpd
    state: present
- name: Start httpd
  service:
    name: httpd
    state: started
- name: write conf file
  shell: echo "httpd2" > /var/www/html/index.html
[root@ansible tasks]# pwd
/etc/ansible/roles/apache/tasks
  • 准备site.yml文件
[root@ansible roles]# cat site.yml 
- hosts: node2
  remote_user: root
  roles:
    - apache

[root@ansible roles]# pwd
/etc/ansible/roles
  • 验证并执行
[root@ansible roles]# ansible-playbook --syntax-check site.yml 

playbook: site.yml
[root@ansible roles]# ansible-playbook site.yml 
[root@ansible roles]# curl node2
httpd2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值