一,ansible是一种由Python开发的自动化运维工具,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能

二,特点

* 部署简单

* **默认使用ssh进行管理,基于python里的==paramiko==模块开发**

* 管理端和被管理端不需要启动服务

* 配置简单,功能强大,扩展性强

* 能过playbook(剧本)进行多个任务的编排

三,ansible搭建

实验准备三台机器,一台管理机 192.168.115.3,两台被管理机 192.168.115.4 192.168.115.5

#所有主机都要配置主机名和 hosts文件

[root@hd1 ~]# hostnamectl set-hostname hd1

[root@hd1 ~]# cat /etc/hosts

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4

::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.1.11 hd1

192.168.1.12 hd2

192.168.1.13 hd3

ansible之user创建用户 ansible创建文件_ansible之user创建用户

#hd2和hd3 同上类似操作

关闭防火墙, selinux

ansible之user创建用户 ansible创建文件_vim_02

ansible之user创建用户 ansible创建文件_d3_03

时间同步

下载更新epel源

yum -y install epel-release
 

ansible之user创建用户 ansible创建文件_vim_04

管理机上安装ansible,被管理节点必须打开ssh服务

 yum install epel-release
yum install ansible
查看版本ansible --version

ansible之user创建用户 ansible创建文件_apache_05

实现master对agent的免密登录,只在master上做。(如果这一步不做,则在后面操作agent时都要加-k参数传密码;或者在主机清单里传密码

ssh-keygen

ansible之user创建用户 ansible创建文件_vim_06

ssh-copy-id   192.168.115.4      192.168.115.5

ansible之user创建用户 ansible创建文件_ansible之user创建用户_07

ansible之user创建用户 ansible创建文件_apache_08

在master上定义主机组,并测试连接性

vim /etc/ansible/hosts 

ansible之user创建用户 ansible创建文件_apache_09

 ansible -m ping group1

ansible之user创建用户 ansible创建文件_ansible之user创建用户_10

查看支持的模块

ansible-doc -l

ansible之user创建用户 ansible创建文件_ansible_11

hostname模块配置

hostname模块用于修改主机名(注意: 它不能修改/etc/hosts文件)

将其中一远程机器主机名修改为agent1

ansible 192.168.115.4 -m hostname -a 'name=agent1'
基本格式为: ansible 操作的机器名或组名 -m 模块名 -a "参数1=值1 参数2=值2" argment

ansible之user创建用户 ansible创建文件_apache_12

ansible之user创建用户 ansible创建文件_ansible_13

测试完改回hd2

file模块

file模块用于对文件相关的操作(创建, 删除, 软硬链接等)

创建一个目录


ansible group1 -m file -a 'path=/test state=directory'


ansible之user创建用户 ansible创建文件_ansible之user创建用户_14

ansible之user创建用户 ansible创建文件_vim_15

创建一个文件


ansible group1 -m file -a 'path=/test/111 state=touch'


ansible之user创建用户 ansible创建文件_ansible之user创建用户_16

ansible之user创建用户 ansible创建文件_apache_17

递归修改owner,group,mode


ansible group1 -m file -a 'path=/test recurse=yes owner=bin group=daemon mode=1777'


ansible之user创建用户 ansible创建文件_d3_18

ansible之user创建用户 ansible创建文件_ansible之user创建用户_19

测试完改回777权限

ansible之user创建用户 ansible创建文件_ansible之user创建用户_20

删除目录 absent 缺席的(连同目录里的所有文件)


ansible group1 -m file -a 'path=/test state=absent'


ansible之user创建用户 ansible创建文件_apache_21

ansible之user创建用户 ansible创建文件_ansible_22

创建文件并指定owner,group,mode等


ansible group1 -m file -a 'path=/tmp/111 state=touch owner=bin group=daemon mode=777'


ansible之user创建用户 ansible创建文件_ansible之user创建用户_23

删除文件


ansible group1 -m file -a 'path=/tmp/111 state=absent'


ansible之user创建用户 ansible创建文件_apache_24

ansible之user创建用户 ansible创建文件_ansible_25

创建软链接文件


ansible group1 -m file -a 'src=/etc/fstab path=/tmp/fstab state=link'


创建硬链接文件


ansible group1 -m file -a 'src=/etc/fstab path=/tmp/fstab2 state=hard'


copy模块

copy模块用于对文件的远程拷贝操作(如把本地的文件拷贝到远程的机器上)

在master上准备一个文件,拷贝此文件到group1的所有机器上


echo master > /tmp/222ansible group1 -m copy -a 'src=/tmp/222 dest=/tmp/333'


ansible之user创建用户 ansible创建文件_d3_26

ansible之user创建用户 ansible创建文件_ansible_27

使用content参数直接往远程文件里写内容(会覆盖原内容)


ansible group1 -m copy -a 'content="ha ha\n" dest=/tmp/333'注意:ansible中-a后面的参数里也有引号时,记得要单引双引交叉使用,如果都为双引会出现问题


使用force参数控制是否强制覆盖

先在hd2 hd3里创建文件  touch /tmp/444

ansible之user创建用户 ansible创建文件_vim_28


如果目标文件已经存在,则不覆盖ansible group1 -m copy -a 'src=/tmp/222 dest=/tmp/444 force=no' 如果目标文件已经存在,则会强制覆盖 ansible group1 -m copy -a 'src=/tmp/222 dest=/tmp/444 force=yes'


ansible之user创建用户 ansible创建文件_apache_29

ansible之user创建用户 ansible创建文件_d3_30

使用backup参数控制是否备份文件


backup=yes表示如果拷贝的文件内容与原内容不一样,则会备份一份group1的机器上会将/tmp/333备份一份(备份文件命名加上时间),再远程拷贝新的文件为/tmp/333 ansible group1 -m copy -a 'src=/etc/fstab dest=/tmp/333 backup=yes owner=daemon group=daemon mode=777'


ansible之user创建用户 ansible创建文件_vim_31

ansible之user创建用户 ansible创建文件_ansible之user创建用户_32

ansible之user创建用户 ansible创建文件_ansible_33

copy模块拷贝时要注意拷贝目录后面是否带"/"符号


/etc/yum.repos.d后面不带/符号,则表示把/etc/yum.repos.d整个目录拷贝到/tmp/目录下ansible group1 -m copy -a 'src=/etc/yum.repos.d dest=/tmp/'/etc/yum.repos.d/后面带/符号,则表示把/etc/yum.repos.d/目录里的所有文件拷贝到/tmp/目录下 ansible group1 -m copy -a 'src=/etc/yum.repos.d/ dest=/tmp/'


ansible之user创建用户 ansible创建文件_d3_34

ansible之user创建用户 ansible创建文件_ansible之user创建用户_35

练习: 在master上配置好所有的yum源,然后拷贝到group1的远程机器上(要求目录内的内容完全一致)

master上配置yum源

ansible之user创建用户 ansible创建文件_vim_36


ansible group1 -m file -a "path=/etc/yum.repos.d/ state=absent" 删除hd2 hd3上的/etc/yum.repos.d目录ansible group1 -m copy -a "src=/etc/yum.repos.d dest=/etc/" 把hd1上的目录拷贝到hd2 hd3


ansible之user创建用户 ansible创建文件_apache_37

hd2 hd3查看

ansible之user创建用户 ansible创建文件_apache_38

练习: 使用hostname模块修改过主机名后.在master上修改/etc/hosts文件,并拷贝到group1的远程机器上


先删除hd2 hd3的hosts文件,在master上修改好/etc/hosts文件,然后使用下面命令拷贝过去覆盖ansible group1 -m copy -a "src=/etc/hosts dest=/etc/hosts"


ansible之user创建用户 ansible创建文件_apache_39

客户端查看

ansible之user创建用户 ansible创建文件_vim_40

user模块

user模块用于管理用户账号和用户属性。

创建aaa用户,默认为普通用户,创建家目录


ansible group1 -m user -a ‘name=aaa state=present’


ansible之user创建用户 ansible创建文件_ansible之user创建用户_41

ansible之user创建用户 ansible创建文件_vim_42

创建bbb系统用户,并且登录shell环境为/sbin/nologin


ansible group1 -m user -a ‘name=bbb state=present system=yes shell="/sbin/nologin"’


ansible之user创建用户 ansible创建文件_apache_43

创建ccc用户, 使用uid参数指定uid, 使用password参数传密码


echo 123456 | openssl passwd -1 -stdin$1$1a.g59z9$kfIxvDIvOq0g20Sd2XMib0下一句命令注意一下格式,密码要用双引号引起来,单引号的话验证时会密码不正确 ansible group1 -m user -a 'name=ccc uid=2000 state=present password="$1$1a.g59z9$kfIxvDIvOq0g20Sd2XMib0"'


ansible之user创建用户 ansible创建文件_ansible_44

ansible之user创建用户 ansible创建文件_ansible之user创建用户_45

创建一个普通用户叫hadoop,并产生空密码 密钥对


ansible group1 -m user -a 'name=hadoop generate_ssh_key=yes'


ansible之user创建用户 ansible创建文件_d3_46

删除aaa用户,但家目录默认没有删除


ansible group1 -m user -a 'name=aaa state=absent'


ansible之user创建用户 ansible创建文件_apache_47

ansible之user创建用户 ansible创建文件_ansible_48

删除bbb用户,使用remove=yes参数让其删除用户的同时也删除家目录


ansible group1 -m user -a 'name=bbb state=absent remove=yes'


ansible之user创建用户 ansible创建文件_ansible之user创建用户_49

ansible之user创建用户 ansible创建文件_ansible_50

group模块

group模块用于管理用户组和用户组属性。

创建组


ansible group1 -m group -a 'name=groupa gid=3000 state=present'


ansible之user创建用户 ansible创建文件_d3_51

删除组(如果有用户的gid为此组,则删除不了)


ansible group1 -m group -a 'name=groupa state=absent'


ansible之user创建用户 ansible创建文件_ansible之user创建用户_52

cron模块

cron模块用于管理周期性时间任务

创建一个cron任务,不指定user的话,默认就是root(因为我这里是用root操作的)。 如果minute,hour,day,month,week不指定的话,默认都为*


ansible group1 -m cron -a 'name="test cron1" user=root job="touch /tmp/111" minute=*/2'


ansible之user创建用户 ansible创建文件_ansible_53

ansible之user创建用户 ansible创建文件_vim_54

删除cron任务


ansible group1 -m cron -a 'name="test cron1" state=absent'


 

ansible之user创建用户 ansible创建文件_vim_55

yum_repository模块

yum_repository模块用于配置yum仓库。

增加一个/etc/yum.repos.d/local.repo配置文件


ansible group1 -m yum_repository -a "name=local description=localyum baseurl=file:///mnt/ enabled=yes gpgcheck=no"


ansible之user创建用户 ansible创建文件_ansible之user创建用户_56

ansible之user创建用户 ansible创建文件_apache_57


注意:此模块只帮助配置yum仓库,但如果仓库里没有软件包,安装一样会失败。所以可以手动去挂载光驱到/mnt目录# mount /dev/cdrom /mnt


删除/etc/yum.repos.d/local.repo配置文件


ansible group1 -m yum_repository -a "name=local state=absent"


ansible之user创建用户 ansible创建文件_apache_58

ansible之user创建用户 ansible创建文件_d3_59

yum模块(重点)

yum模块用于使用yum命令来实现软件包的安装与卸载。

使用yum安装一个软件(前提:group1的机器上的yum配置都已经OK)


ansible group1 -m yum -a 'name=vsftpd state=present'


ansible之user创建用户 ansible创建文件_ansible之user创建用户_60

ansible之user创建用户 ansible创建文件_vim_61

使用yum安装httpd,httpd-devel软件,state=latest表示安装最新版本


ansible group1 -m yum -a 'name=httpd,httpd-devel state=latest'


ansible之user创建用户 ansible创建文件_ansible_62

ansible之user创建用户 ansible创建文件_d3_63

使用yum卸载httpd,httpd-devel软件


ansible group1 -m yum -a 'name=httpd,httpd-devel state=absent'


ansible之user创建用户 ansible创建文件_d3_64

service模块(重点)

service模块用于控制服务的启动,关闭,开机自启动等。

启动vsftpd服务,并设为开机自动启动


ansible group1 -m service -a 'name=vsftpd state=started enabled=on'


关闭vsftpd服务,并设为开机不自动启动


ansible group1 -m service -a 'name=vsftpd state=stopped enabled=false'


练习: 在group1的被管理机里的mariadb里创建一个abc库


mysql -e user=root password=123456 "create database abc ;"


练习:

假设我主机清单里定义的group1里有多台机器,它们现在要做一个集群。此集群要求实现一个名为hadoop的普通用户之间的两两免密登录,如何实现(要求只在master上进行操作)?




script模块

script模块用于在远程机器上执行本地脚本。


在master上准备一个脚本master# vim /tmp/1.sh#!/bin/bash
mkdir /tmp/haha
touch /tmp/haha/{1..10}

在group1的远程机器里都执行master上的/tmp/1.sh脚本(此脚本不用给执行权限)
ansible group1 -m script -a '/tmp/1.sh'


扩展: 使用shell脚本实现在group1的被管理机里的mariadb里创建一个abc库


#!/bin/bashyum install mariadb-server -y  &> /dev/nullsystemctl start mariadb
systemctl enable mariadb

mysql << EOF
create database abc;
quit
EOF

把上面的脚本使用script模块在group1被管理机里执行即可


command与shell模块

两个模块都是用于执行linux命令的,这对于命令熟悉的工程师来说,用起来非常high。

shell模块与command模块差不多(command模块不能执行一些类似$HOME,>,<,|等符号,但shell可以)

ansible.builtin.command module – Execute commands on targets — Ansible Documentation

ansible.builtin.shell module – Execute shell commands on targets — Ansible Documentation


master# ansible -m command group1 -a "useradd user2"master# ansible -m command group1 -a "id user2"master# ansible -m command group1 -a "cat /etc/passwd |wc -l"       --报错
master# ansible -m shell group1 -a "cat /etc/passwd |wc -l"     --成功

master# ansible -m command group1 -a "cd $HOME;pwd"   --报错
master# ansible -m shell  group1 -a "cd $HOME;pwd"    --成功


注意: shell模块并不是百分之百任何命令都可以,比如vim或ll别名就不可以。不建议大家去记忆哪些命令不可以,大家只要养成任何在生产环境里的命令都要先在测试环境里测试一下的习惯就好。

三、playbook

playbook(剧本): 是ansible用于配置,部署,和管理被控节点的剧本。用于ansible操作的编排。

参考:Ansible playbooks — Ansible Documentation

使用的格式为yaml格式(saltstack,elk,docker,docker-compose,kubernetes等也都会用到yaml格式)

YMAL格式

  • 以.yaml或.yml结尾
  • 文件的第一行以 "---"开始,表明YMAL文件的开始(可选的)
  • 以#号开头为注释
  • 列表中的所有成员都开始于相同的缩进级别, 并且使用一个 "- " 作为开头(一个横杠和一个空格)
  • 一个字典是由一个简单的 键: 值 的形式组成(这个冒号后面必须是一个空格)
  • ==注意: 写这种文件不要使用tab键,都使用空格==

参考: YAML Syntax — Ansible Documentation

下面看一个官方的示例感受一下


---# 一位职工记录name: Example Developer
job: Developer
skill: Elite
employed: True
foods:
    - Apple
    - Orange
    - Strawberry
    - Mango
languages:
    ruby: Elite
    python: Elite
    dotnet: Lame


playbook实例

先直接来看一个实例

第1步: 创建一个存放playbook的目录(路径自定义)


master# mkdir /etc/ansible/playbook


第2步: 准备httpd配置文件,并修改成你想要的配置


master# yum install httpd -y按需要修改你想要的配置(为了测试可以随意改动标记一下)master# vim /etc/httpd/conf/httpd.conf


第3步: 写一个playbook文件(后缀为.yml或.yaml)

# vim /etc/ansible/playbook/example.yaml---- hosts: group1
  remote_user: root
  tasks:  
  - name: ensure apache is at the latest version    
    yum: name=httpd,httpd-devel state=latest
    
  - name: write the apache config file      
    copy: src=/etc/httpd/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
    
    notify:
    - restart apache
    
  - name: ensure apache is running (and enable it at boot)
    service: name=httpd state=started enabled=yes
    
  handlers: 
    - name: restart apache
      service: name=httpd state=restarted

第4步: 执行写好的palybook

  • 会显示出执行的过程,并且执行的每一步都有ok,changed,failed等标识
  • 执行如果有错误(failed)会回滚,解决问题后,直接再执行这条命令即可,并会把failed改为changed(幂等性)

# ansible-playbook /etc/ansible/playbook/example.yaml


Playbook常见语法

hosts: 用于指定要执行任务的主机,其可以是一个或多个由冒号分隔主机组.

remote_user: 用于指定远程主机上的执行任务的用户.


- hosts: group1  remote_user: root


tasks: 任务列表, 按顺序执行任务.

  • 如果一个host执行task失败, 整个tasks都会回滚, 修正playbook 中的错误, 然后重新执行即可.

 tasks:  - name: ensure apache is at the latest version    yum: name=httpd,httpd-devel state=latest      - name: write the apache config file    copy: src=/etc/httpd/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf


handlers: 类似task,但需要使用notify通知调用。

  • 不管有多少个通知者进行了notify,等到play中的所有task执行完成之后,handlers也只会被执行一次.
  • handlers最佳的应用场景是用来重启服务,或者触发系统重启操作.除此以外很少用到了.
notify:                   - restart apache    
  - name: ensure apache is running (and enable it at boot)
    service: name=httpd state=started enabled=yes
    
  handlers:
  - name: restart apache
    service: name=httpd state=restarted


练习: 修改httpd的端口为8080,再执行playbook测试

variables: 变量

  • 定义变量可以被多次方便调用
master# vim /etc/ansible/playbook/example2.yaml---- hosts: group1
  remote_user: root
  vars:
  - user: test1
  tasks:
  - name: create user
    user: name={{user}} state=present
~                                          
 
master# ansible-playbook /etc/ansible/playbook/example2.yaml


案例: playbook编排vsftpd

写一个playbook实现

  1. 配置yum
  2. 安装vsftpd包
  3. 修改配置文件(要求拒绝匿名用户登录)
  4. 启动服务并实现vsftpd服务开机自动启动
---- hosts: group1                   remote_user: root                     
  tasks:                                
  - name: rm yum repository      
    file: path=/etc/yum.repos.d/ state=absent
    
  - name: 同步master上的yum源到group1
    copy: src=/etc/yum.repos.d dest=/etc/
    
  - name: ensure vsftpd is at the latest version        
    yum: name=vsftpd state=latest
    
  - name: write the apache config file          
    copy: src=/etc/vsftpd/vsftpd.conf dest=/etc/vsftpd/vsftpd.conf 
    
    notify:                             
    - restart vsftpd
    
  - name: ensure vsftpd is running (and enable it at boot)
    service: name=vsftpd state=started enabled=yes
    
  handlers:                     
    - name: restart vsftpd              
      service: name=vsftpd state=restarted


playbook编排多个hosts任务


--- # ---代表开始(可选项,不写也可以)- hosts: 10.1.1.12  remote_user: root  tasks:  - name: 创建/test1/目录    file: path=/test1/ state=directory # 这里不能用---分隔,会报语法错误(后面课程玩k8s编排也写YAML文件,是可以用---来分隔段落的) - hosts: 10.1.1.13  remote_user: root  tasks:  - name: 创建/test2/目录    file: path=/test2/ state=directory ... # ...代表结束(可选项,不写也可以)


案例: 编排nfs搭建与客户端挂载

1, 在master上准备nfs配置文件


# vim /etc/exports/share  *(ro)


2, 编写yaml编排文件

# vim /etc/ansible/playbook/nfs.yml---- hosts: 10.1.1.12
  remote_user: root
  tasks:
  - name: 安装nfs服务相关软件包
    yum: name=nfs-utils,rpcbind,setup  state=latest

  - name: 创建共享目录
    file: path=/share/ state=directory

  - name: 同步nfs配置文件
    copy: src=/etc/exports dest=/etc/exports

    notify: restart nfs

  - name: 启动rpcbind服务,并设置为开机自启动
    service: name=rpcbind state=started enabled=on

  - name: 启动nfs服务,并设置为开机自启动
    service: name=nfs state=started enabled=on

  handlers:
  - name: restart nfs
    service: name=nfs state=restarted

- hosts: 10.1.1.13
  remote_user: root
  tasks:
  - name: 安装nfs客户端软件包
    yum: name=nfs-utils state=latest

  - name: 挂载nfs服务器的共享
    shell: mount 10.1.1.12:/share /mnt
 
3, 执行playbook
 
# ansible-playbook /etc/ansible/playbook/nfs.yaml