ansible简介

2018-06-05  本文已影响0人  小尛酒窝

一、简介

在Linux自动化运维中,常见的自动化运维工具可分为需要安装终端的puppet、func和不需要安装终端的ansible,fabric。而ansible就是其中一个模块化的自动运维管理工具,其基于Python语言实现,由Paramiko,PYYAML和Jinjia2三个关键模块组成。Ansible无需再控制终端安装客户端,因此部署起来十分简单。Ansible的主要特点包括以下几点:

二、Ansible的架构

ansible的架构图

Ansible的架构由以下几个核心组件构成:

ansible:ansible的核心程序,提供一个命令行接口给用户对ansible进行管理操作;
Host Inventory:为Ansible定义了管理主机的策略。一般小型环境下我们只需要在host文件中写入主机的IP地址即可,但是到了中大型环境我们有可能需要使用静态inventory或者动态主机清单来生成我们所需要执行的目标主机。
Core Modules:用于执行管理任务的核心模块,在Ansible管理主机之前,先调用core Modules中的模块,然后指明管理Host Lnventory中的主机,就可以完成管理主机。
Custom Modules:自定义模块,如何ansible自带的模块无法满足我么你的需求,用户可自定义相应的模块来满足自己的需求。
Connection Plugins:Ansible默认是基于SSH连接到目标机器上执行操作的,但是其也支持其他不同的连接方法,此时就需要连接插件帮助我们进行连接。
Playbook:定义需要给远程主机执行的一系列任务。

三、ansible的安装和配置

[root@localhost ~]# yum install -y epel-release
[root@localhost ~]# yum install -y ansible
(1)[defaults]
    #inventory      = /etc/ansible/hosts  # 主机列表配置文件
    #library        = /usr/share/my_modules/ # 库文件存放目录 
    #remote_tmp     = $HOME/.ansible/tmp  # 生成的临时py命令文件存放在远程主机的目录
    #local_tmp      = $HOME/.ansible/tmp # 本机的临时命令执行目录
    #forks          = 5   # 默认并发数
    #poll_interval  = 15   # 默认的线程池
    #sudo_user      = root  # 默认sudo 用户
    #ask_sudo_pass = True
    #ask_pass      = True
    #transport      = smart
    #remote_port    = 22
    #module_lang    = C
    #module_set_locale = False

    host_key_checking = False  ### 检查对应服务器的host_key


(2)[privilege_escalation]
(3)[paramiko_connection]
(4)[ssh_connection]
(5)[accelerate]
(6)[selinux]
(7)[colors]

直接指明主机地址或主机名

node1
10.10.10.11

或者定义一个主机组,把主机地址或者主机名写进去,然后通过组名来调用主机组:

[webservers]
10.10.10.11
10.10.10.12
[dbservers]
db1
10.10.10.13

/etc/ansible/hosts文件支持使用以下变量设置相关的远程主机信息:

ansible_ssh_host     #用于指定被管理的主机的真实IP
ansible_ssh_port     #用于指定连接到被管理主机的ssh端口号,默认是22
ansible_ssh_user     #ssh连接时默认使用的用户名
ansible_ssh_pass     #ssh连接时的密码
ansible_sudo_pass     #使用sudo连接用户时的密码
ansible_sudo_exec     #如果sudo命令不在默认路径,需要指定sudo命令路径
ansible_ssh_private_key_file     #秘钥文件路径,秘钥文件如果不想使用ssh-agent管理时可以使用此选项
ansible_shell_type     #目标系统的shell的类型,默认sh
ansible_connection     #SSH 连接的类型: local , ssh , paramiko,在 ansible 1.2 之前默认是 paramiko ,后来智能选择,优先使用基于 ControlPersist 的 ssh (支持的前提)
ansible_python_interpreter     #用来指定python解释器的路径,默认为/usr/bin/python 同样可以指定ruby 、perl 的路径
ansible_*_interpreter     #其他解释器路径,用法与ansible_python_interpreter类似,这里"*"可以是ruby或才perl等其他语言

ansible可以通过以下两种方式完成ssh认证:
1、通过在主机清单中配置对应主机的ssh账号及密码来完成认证:

[root@Monitor ansible]# vim /etc/ansible/hosts             
[webserver]
#192.168.180.4
192.168.180.5 ansible_ssh_port=10022 ansible_ssh_user=root ansible_ssh_pass='123456'
192.168.180.6 ansible_ssh_user=root ansible_ssh_pass='123456'
192.168.180.23 ansible_ssh_user=appuser ansible_ssh_pass='123456'

但是这种方式在管理大量的远程主机的配置会显得特别麻烦,而且容易泄露账号密码信息,因此通常只作为测试使用。
2、使用ssh的免密钥登录方式来远程管理主机。
首先需要在ansible主机上生成ssh的公钥和私钥文件:

[root@ansible ~]# ssh-keygen -t rsa -N ''
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
/root/.ssh/id_rsa already exists.
Overwrite (y/n)? y
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:
eb:74:58:83:93:11:3a:fa:9b:8f:3f:88:4a:94:16:a0 root@ansible
The key's randomart image is:
+--[ RSA 2048]----+
|.       .        |
|..     . .       |
|E .   o .        |
|   o . . +       |
|  + .   S o      |
| o   .   = .     |
|  .  ...+ .      |
| .  . .*..       |
|  ..  +o+.       |
+-----------------+
[root@ansible ~]# ll /root/.ssh/
总用量 12
-rw-------. 1 root root 1675 6月   4 17:44 id_rsa  #生成的私钥文件
-rw-r--r--. 1 root root  394 6月   4 17:44 id_rsa.pub  #生成的公钥文件
-rw-r--r--. 1 root root  348 6月   4 17:12 known_hosts

接着将生成的公钥文件送往远程主机:

[root@ansible ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.0.83
/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.0.83's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@192.168.0.83'"
and check to make sure that only the key(s) you wanted were added.
[root@ansible ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.0.84
/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.0.84's password: 

Number of key(s) added: 1

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

分发之后默认会在远程主机的/root/.ssh下生成authorized_keys这个文件。随后即可使用ansible对远程主机进行管理操作:

[root@ansible ~]# ansible webservers -m ping
192.168.0.83 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
192.168.0.84 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

四、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-doc和/usr/bin/ansible-playbook了。ansible和playbook分别对应着ansible的两种任务的执行方式:AD-Hoc和playbook,而ansible-doc则可以方便于管理员查询指定的模块功能的使用方式。

ansible <host-pattern> [options]

其中options常见的参数有:

-C,--check:测试模式,只显示测试的结果而不做出实际的改变。
-m module_name:用于指定要执行的模块的名字,如:ansible all -m ping;
-a MODULE_ARGS:用于指定要执行的模块的参数,参数格式类似于key=value,如:ansible all -m group -a "gid=3000 name=mygrp state=absent system=no";

使用示例:

[root@ansible ~]# ansible all -m shell  -a "echo magedu"
192.168.0.83 | SUCCESS | rc=0 >>
magedu

192.168.0.84 | SUCCESS | rc=0 >>
magedu

ansible-doc [-l|-F|-s] [options] [-t <plugin type> ] [plugin]

其中常用的参数的解释为:

-l:列出所有可用的模块;
-s:显示指定的模块的片段参数;
-F:列出模块名字及其对应的python脚本文件;

使用示例:

[root@ansible ~]# ansible-doc -s copy
- name: Copies files to remote locations
  copy:
      attributes:            # Attributes the file or directory should have. To get supported flags look at the man page for `chattr' on the target system.
                               This string should contain the attributes in the same order as the one displayed by `lsattr'.
      backup:                # Create a backup file including the timestamp information so you can get the original file back if you somehow clobbered it
                               incorrectly.
      checksum:              # SHA1 checksum of the file being transferred. Used to valdiate that the copy of the file was successful. If this is not
                               provided, ansible will use the local calculated checksum of the src file.
      content:               # When used instead of `src', sets the contents of a file directly to the specified value. For anything advanced or with
                               formatting also look at the template module.
......

ansible-playbook [options] [playbooks]

其中playbooks为以.yaml结尾的文本文件,里面包含着以yaml语言所编写的执行内容。
而常用的options包括:

--check:测试模式,检查playbook的执行结果,不是真正的执行操作;ansible-syntax-check也可以用于检查指定playbook的语法是否有错;
--list-hosts:列出运行指定playbook的主机;
-t tags_name:执行yaml文件中的指定的tags配置;
-e VARS=value:自定义在playbook中使用到的变量;

使用示例:

ansible-playbook -e pkgname=memcached -C fourth.yaml

chdir=path :切换路径到指定的目录下,然后执行指定的命令

使用示例:

ansible all -m command -a "ifconfig"
ansible all -m command -a "chdir=/var/tmp mkdir hi.dir"

2)shell模块
因为command模块不支持管道符号等shell的特性,因此当需要指定的命令需要利用到管道等shell特性时,需要调用shell模块,这样即可在远程主机的shell进程下运行命令。
使用示例:

ansible all -m shell  -a "echo magedu | passwd --stdin testuser"

3)file模块
file模块用于在远程主机上创建或设置文件属性。
其常用的模块参数有:

group=GROUPNAME:用于指定创建文件的属组;
mode=value:用于指定文件的权限;
owner=USERNAME:用于指定文件的属主;
path=PATH:用于指定目标文件的路径;
src=PATH:指定要被链接的源文件路径,只应用于state=link的情况;
dest=PATH:指定创建链接文件的路径,只应用于state=link的情况;
state=ATTIBUTES:用于指定文件属性状态,常见的属性状态有:
    directory:指定文件类型为目录,如果目录不存在则创建目录;
    file:指定文件类型为file,即使文件不存在,也不会创建文件;
    hard:创建硬链接
    link:创建软链接
    touch:如果文件不存在,则会常见一个新的文件,如果文件或目录已存在,则更新其最后修改的时间
    absent:删除文件、目录或取消链接文件;
    present:新增文件、目录或链接文件

使用示例;

#在远程主机的指定目录下创建目录
ansible all -m file -a  "path=/var/tmp/hello.dir state=directory"

4)copy模块
copy模块用于将本地文件复制到远程主机的指定路径下。
其模块参数有:

src:指定复制文件的来源,注意路径最后是否带有/会影响复制的是目录,还是目录下的文件。
content:将指定的内容复制保存为指定路径的文件内容;
dest:指定复制文件的存放目录;
mode:指定复制目标文件的文件权限;
owner:指定复制目标文件的属主;
group:指定复制目标文件的属组;

使用示例:

#将源文件复制到远程主机的指定路径,并设置文件权限为600
ansible all -m copy -a "src=/etc/fstab dest=/tmp/fstab.ansible mode=600"
#将指定的content内容,复制保存为远程主机指定路径下的文件
ansible all -m copy -a "content='hi there\n' dest=/tmp/hi.txt"
minute:定义cron任务每几分钟运行一次;
hour:定义cron任务每几个小时运行一次;
day:定义cron任务每几天运行一次;
month:定义cron任务每几个月运行一次;
weekday:定义cron任务每星期几运行;
name:定义cron任务的名字;
job:定义cron任务的工作内容;
state:通常为present或absent,新增或删除cron任务;

使用示例:

#在远程主机创建时间同步的cron任务
ansible all -m cron -a "minute=*/3 job='/usr/sbin/update ntp1.aliyun.com &> /dev/null' name=dateupdate
#在远程主机上删除时间同步的cron任务
ansible all -m cron -a "minute=*/3 job='/usr/sbin/update ntp1.aliyun.com &> /dev/null' name=dateupdate state=absent "
name:指定用户的名称;
system:指定用户是否为系统用户,yes or no;
uid:指定用户的uid;
shell:指定用户的默认shell;
group:指定用户的属组;
groups:指定用户的附加组;
home:指定用户的家目录;
state:指定是否在远程主机上创建或删除指定的用户,present为创建,absent为删除;

使用示例:

ansible all -m user -a "uid=5000 name=testuser state=present group=mygrp shell=/bin/tcsh"
gid:用于指定用户组的id;
name:用于指定用户组的名称;
state:是否在远程主机上创建或删除指定的组,present为创建,absent为删除;
system:用于指定用户组是否为系统组;

使用示例:

ansible all -m group -a "gid=3000 name=mygrp state=present system=no"
name:指明要安装的程序包的名字;
state:指明安装或卸载的方式,包括present、installed、latest、absent、removed;

使用示例:

ansible all -m yum -a "name=epel-release state=installed"
name:指定要管理的服务的名称;
enabled:指定管理的服务是否开机自启动;
state:设置服务的状态为started、stopped或者restarted、reloaded;

使用示例:

ansible all -m service -a "name=nginx state=started"
chdir:指定脚本执行的目录路径;

使用示例:

ansible all -m script -a "chdir=/etc/ /root/ehco.sh"
src:本地Jinjia2模版的template文件位置;
dest:远程节点上的绝对路径,用于放置template文件;
group:设置远程节点上的的template文件的所属用户组;
owner:设置远程节点上的的template文件的所属用户组;
mode:设置远程节点上的template文件权限;

使用示例:

#模板文件
[root@ansible playbooks]# vim mylisten.conf 
Listen {{ http_port }}
#ansible主机变量:
[root@ansible playbooks]# vim /etc/ansible/hosts
[webservers]
192.168.0.83 http_port=8080
192.168.0.84 http_port=10080
#yaml配置:
[root@ansible ~]# vim first.yaml
- hosts: webservers
  remote_user: root
  tasks:
  - name: install httpd
    yum: name=httpd state=latest
  - name: install config file
    template: src=/root/playbooks/mylisten.conf dest=/etc/httpd/conf.d/mylisten.conf
  - name: start httpd
    service: name=httpd state=started
#ansible-playbook执行调用
[root@ansible ~]# ansible-playbook all first.yaml

五、Ansible-playbook

playbook应该说是ansible的核心模块了,一个playbook相当于是一堆task任务的合集。执行一个playbook,相当于执行了一堆task任务,而且这个playbook还是可复用的,这样就能大大减少了重复性的工作量。Playbook是使用一种叫YAML语言来编写的,其本身就是一种可读性高,用于表达数据序列的格式的语言。一个playbook文件应以.yaml结尾。
playbook由以下几个核心元素组成:

1、Hosts:指远程控制的主机;
2、Tasks:指在远程控制主机上执行的任务;
3、Variables:执行Tasks任务时调用的变量;
4、Templates:包含了模板语法的文本文件;
5、Handlers:根据特殊的触发条件而判断执行某个具体的Task任务;
6、Roles:Playbook的角色,将经常调用的Task任务定义成一个角色,方便日后进行复用;

下面我们来看每个元素在playbook里面的实现。

#调用全部主机
- hosts: all  
#调用指定的主机组
- hosts: webservers

1)action:module arguments;
2)module:arguments

注意,shell和command模块后面只需直接添加命令,而不是使用key=value类似的参数列表。另外某任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers;任务可以通过“tags"打标签,而后可在ansible-playbook命令上使用-t指定进行调用。

Tasks在playbook中的实现:

- hosts: all    #定义远程主机
  remote_user: root  #定于远程主机上执行任务的用户
  tasks:
  - name: install redis  #定义第一个task任务
    yum: name=redis state=latest  #定义task任务的内容
  - name: install nginx  #定义第二个task任务
    yum: name=nginx state=latest
    notify: restart nginx    #调用名为restart nginx的handlers
    tags: installngx  #添加installngx的tags标签
- hosts: all
  remote_user: root
  tasks:
  - name: install redis
    yum: name=redis state=latest
  - name: copy config file
    copy: src=/root/playbooks/redis.conf dest=/etc/redis.conf owner=redis
    notify: restart redis    #调用指定的handlers
    tags: configfile
  - name: start redis
    service: name=redis state=started enabled=true
  handlers:    
  - name: restart redis    #定义一个handlers
    service: name=redis state=restarted    #定义handlers所触发的任务
ansible_distribution:目标主机系统的社区版本
ansible_os_family:目标主机系统派系
ansible_default_ipv4.address:目标主机的Ip地址

2)用户自定义变量
包括通过ansible-playbook -e VARS=value playbook.yaml命令所指定的变量,以及在playbook中通过下面方式定义的变量:

  - hosts: all
    gather_facts: False
    vars:
        pkgname: nginx
    tasks:
    - name: install nginx
      yum: name={{ pkgname }} state=latest

3)通过roles传递变量;

4)通过在/etc/ansible/hosts文件中定义变量,如:

#向不同的主机传递不同的变量
[root@ansible playbooks]# vim /etc/ansible/hosts
[webservers]
192.168.0.83 http_port=8080
192.168.0.84 http_port=10080

#向组中的主机传递相同的变量
[webservers]
192.168.0.83
192.168.0.84

[webservers:vars]
http_port=8080

files/:存放由copy或script模块等调用的文件;
templates/ : 存放template模块查找所需要模板文件的目录;
tasks/ :至少应该包含一个名为mail.yml的文件,此文件保存着与tasks相关的信息,其它的文件需要在此文件中通过include进行包含;
handlers/ :至少应该包含一个名为mail.yml的文件,此文件保存着与handlers相关的信息,其他的文件需要在此文件中通过include进行包含;
vars/:至少应该包含一个名为mail.yml的文件,此文件保存着与vars相关的信息,其他的文件需要在此文件中通过include进行包含;
meta/:至少应该包含一个名为mail.yml的文件,定义当前角色的特殊设定及其依赖关系;其他的文件需要在此文件中通过include进行包含;
default/:设定默认变量时使用此目录的mail.yml文件;

一个roles的目录架构:

[root@ansible ~]# tree /etc/ansible/roles/nginx/
/etc/ansible/roles/nginx/
├── default
├── files
│   └── index.html
├── handlers
│   └── main.yml
├── meta
├── tasks
│   └── main.yml
├── templates
│   └── vhost1.conf.j2
└── vars
    └── main.yml

在playbook中调用角色的方法:

- hosts: webservers
  remote_user: root
  roles:
  - mysql
  - memcached
  - { role: nginx,username: nginx}  #将username变量传递给nginx角色
tasks:
- hosts: webservers
  remote_user: root
  tasks:
  - name: install nginx
    yum: name=nginx state=installed
    when: ansible_os_family == "RedHat"
  - name: install apahce2
    apt: name=apache2 state=installed
    when: ansible_os_family == "Debian"

也可以根据when条件测试来实现角色的调用:

- hosts: webservers
  remote_user: root
  roles:
  - { role: nginx, when: "ansible_distribution_major_version == '7' " }

另外在playbook中也可以实现循环迭代的操作,其实现需要在tasks引用用固定变量"item",然后在task中使用with_items给定要循环迭代的元素列表,列表支持以字符串或者字典的方式提供,如:

- hosts: webservers
  remote_user: root
  tasks:
  - name: install {{ item }} package    
    yum: name={{ item }} state=latest    #引用固定变量item
    with_items:    
    - tomcat      #列表方式
    - tomcat-webapps
    - tomcat-admin-webapps  
  - name: add some users            
    user: name={{ item.name }} group={{ item.group }} state=present   #引用固定变量作字典
    with_items:
    - { name: 'user11',group: 'group11' }    #字典方式
    - { name: 'user12',group: 'group12' }
    - { name: 'user13',group: 'group13' }
上一篇下一篇

猜你喜欢

热点阅读