一. ansible简介
ansible 是一款强大的开源的自动化运维管理工具,底层代码主要用python编写,结合了paramiko jinjia2 yaml 三个模块
ansible:ansible的核心程序
host lnventory:记录了每一个由ansible管理的主机信息,包括:ssh端口,用户及密码,等
playbooks:任务剧本,yaml格式的文件,用来储存多任务,方便统一调用
core modules:ansible执行任何管理任务,都不是ansible自身完成的,而是由ansible的核心模块完成的;ansible在管理主机之前,先调用core modules中的模块,然后指明host lnventory中的主机中的主机,就可以完成管理主机,
custom modules:自定义模块,完成ansible核心模块无法完成的任务,此模块支持任何语言编写;
connection plugins:连接插件,ansible和host之间通信
ansible优点
No client 不需要在被管控主机上安装任何软件
No server 不用单独启用服务,能使用直接运行,使用时直接运行命令
支持sudo
基于ssh工作,安全
幂等性:无改变重复操作自动跳过机制
提供一个功能强大、操作性强的Web管理界面和REST API接口——AWX平台
配置简单、功能强大、扩展性强
支持API及自定义模块,可通过Python轻松扩展
ansible主要生成文件
/etc/ansible/ansible.cfg #主配置文件
/etc/ansible/hosts #管理的主机库
/usr/bin/ansible #主程序
/usr/bin/ansible-doc #文档
/usr/bin/ansible-playbook #剧本
设置管理主机库
控制客户端主机的两种方式:
免密钥:ssh-keygen 可参考:https://www.cnblogs.com/du-z/p/10901774.html
参数形式:ansble_ssh_user=root ansible_ssh_pass=123456 ansible_ssh_port=22
编写host inventory
╭─root@localhost.localdomain ~
╰─➤ vim /etc/ansible/hosts
#参数形式
[testhosts]
192.168.137.4 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass=123456
192.168.137.5 ansible_ssh_user=root ansible_ssh_poet=22 ansible_ssh_pass=123456
…
#免密钥模式
[testhosts]
192.168.137.4
192.168.137.5
ansible常用命令及模块
ansible-doc命令:
ansible-doc -l #查看ansible支持的模块
ansible-doc -s model_name #查看model_name模块的用法
ansible 常用模块
ping 模块 :ping查看客户端能否管理通信
command 模块 :命令
shell 模块 : shell命令(支持正则等)
copy 模块 : 远程复制相当于scp
cron 模块 : 计划任务模块
mail 模块 :邮件模块
ansible命令行模式
ansible [options]
-f forks :启动并发线程数
-m model_name :要使用模块
-a args:特有的参数
ansible all -m ping #查看client端是否正常连通,即可管理
ansible testhosts -m setup #查看客户端信息
ansible testhosts -m copy -a ‘src=/root/test.txt dest=/root/test1.txt’ #copy文件到client端
ansible testhosts -m user -a “name=user1 state=present” #创建user1用户
ansible testhosts -m user -a “name=user1 state=absent” #删除user1用户
ansible testhosts -m yum -a “name=hpptd state=installed” #yum 安装apache
ansible testhosts -m service -a “name=httpd state=stoped encable=no” #停止httpd服务,开机不自起
ansible -m command -a “date” #查看时间
playbook
包括:
tasks :一个tasks相当于一个play
variables :变量,一次定义,多处调用
templates :模板,可以区分不同主机的特点
handlers :触发器,依赖于前一个任务,前一个任务如果执行改变,就会触发handlers
二 . Ansible 部署 及 模块篇实操
2.1 ansible 软件部署
----------ansible环境安装部署----------
管理端:192.168.100.4
被管理端:192.168.100.14
被管理端:192.168.100.15
yum install -y epel-release //安装epel源
yum install ansible -y
ansible --version //查看ansible版本
yum install tree -y
查看版本
[root@ansible ~]# ansible --version
ansible 2.9.13
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, Oct 30 2018, 23:45:53) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]
yum install tree -y
tree /etc/ansible/ //树状结构展示文件夹
/etc/ansible/
├── ansible.cfg #ansible的配置文件
├── hosts #ansible的主仓库,用于存储需要管理的远程主机的相关信息
└── roles #角色
编辑配置文件
[root@ansible ~]# cd /etc/ansible
[root@ansible ansible]# ls
ansible.cfg hosts roles
[root@ansible ansible]# vi hosts
写入数据,配置主机清单
[webserver]
192.168.100.48
[mysql]
192.168.100.20
生成秘钥对
[root@ansible ansible]# ssh-keygen -t rsa
输入密码 abc123
将公钥推送到目标主机
ssh-copy-id root@192.168.100.48
操作显示时间
[root@ansible ~]# ansible 192.168.100.48 -m command -a 'date'
Enter passphrase for key '/root/.ssh/id_rsa': 会提示输入设置密码 abc123
192.168.100.48 | CHANGED | rc=0 >>
2020年 10月 21日 星期三 23:38:51 EDT
[root@ansible ~]# ansible mysql -m command -a 'date'
Enter passphrase for key '/root/.ssh/id_rsa':
192.168.100.20 | CHANGED | rc=0 >>
2020年 10月 22日 星期四 11:40:25 CST
2.2 设置代理登录,免去密码交互
[root@ansible ~]# ssh-agent bash
[root@ansible ~]# ssh-add
Enter passphrase for /root/.ssh/id_rsa: 输入设置的密码 ABC123
Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)
直接访问目标主机,就不需要输入密码了
[root@ansible ~]# ansible mysql -m command -a 'date'
192.168.100.20 | CHANGED | rc=0 >>
2020年 10月 22日 星期四 11:41:48 CST
2.3 各模块详解
------command模块------
命令格式:ansible [主机] [-m 模块] [-a args]
ansible-doc -l //列出所有已安装的模块 注:按q退出
ansible-doc -s yum //-s列出yum模块描述信息和操作动作
[root@localhost .ssh]# ansible webserver -m command -a 'date'
默认来说,不加 -m 就是默认使用 -command模块 ,执行基本命令
操作测试,在所有节点上查看时间
[root@ansible ~]# ansible all -a 'date'
192.168.100.20 | CHANGED | rc=0 >>
2020年 10月 22日 星期四 11:49:08 CST
192.168.100.48 | CHANGED | rc=0 >>
2020年 10月 21日 星期三 23:49:08 EDT
查看目录文件
[root@ansible ~]# ansible all -a 'ls'
192.168.100.48 | CHANGED | rc=0 >>
anaconda-ks.cfg
192.168.100.20 | CHANGED | rc=0 >>
anaconda-ks.cfg
core.18799
original-ks.cfg
公共
模板
-----cron模块------
两种状态(state):present表示添加(可以省略),absent表示移除。
查看 cron 模块信息
[root@ansible ~]# ansible-doc -s cron
- name: Manage cron.d and crontab entries
cron:
backup: # If set, create a backup of the cronta
is modified. The
location of the
backup is
returned in the
`backup_file'
variable by this
module.
cron_file: # If specified, uses this file instead
individual user's
crontab. If this
is a relative
path, it is
interpreted with
respect to
`/etc/cron.d'. If
it is absolute,
it will typically
:
添加计划性任务
[root@ansible ~]# ansible webserver -m cron -a 'minute="*/1" job="/usr/bin/echo heihei >> /opt/info.txt" name="test cron job"'
192.168.100.48 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": [
"test cron job"
]
}
查看计划性任务
[root@ansible ~]# ansible webserver -a 'crontab -l'
192.168.100.48 | CHANGED | rc=0 >>
#Ansible: test cron job
*/1 * * * * /usr/bin/echo heihei >> /opt/info.txt
去节点查看确认
[root@shanan ~]# crontab -l
#Ansible: test cron job
*/1 * * * * /usr/bin/echo heihei >> /opt/info.txt
[root@shanan ~]# cat /opt/info.txt
heihei
[root@shanan ~]#
取消计划性任务
[root@ansible ~]# ansible webserver -m cron -a 'name="test cron job" state=absent'
192.168.100.48 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": []
}
查看确认
[root@ansible ~]# ansible webserver -a 'crontab -l'
192.168.100.48 | CHANGED | rc=0 >>
user 模块
user模块是请求的是useradd, userdel, usermod三个指令
ansible-doc -s user
创建账户
[root@ansible ~]# ansible all -m user -a 'name=test01'
192.168.100.48 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"comment": "",
[root@mysql ~]# id test01
uid=1000(test01) gid=1000(test01) 组=1000(test01)
[root@ansible ~]# ansible webserver -m user -a 'name=test01 state=absent'
192.168.100.48 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"force": false,
"name": "test01",
"remove": false,
"state": "absent"
}
[root@shanan ~]# id test01
id: test01: no such user
此处修改一下主机清单
Vim /etc/ansible/hosts
[local]
127.0.0.1
[test1]
192.168.100.11 ansible_ssh_user=root ansible_ssh_pass=shanan1023
[test2]
192.168.100.12 ansible_ssh_user=root ansible_ssh_pass=shanan1023
[test3]
192.168.100.10 ansible_ssh_user=root ansible_ssh_pass=shanan1023
[test4]
192.168.100.9 ansible_ssh_user=root
[tests:children] //此:children 是必须套用的格式,不能替代
test1
test2
vi /etc/ansible/ansible.cfg
在文件中进行插入一行
host_key_checking = False
group 模块
group模块请求的是groupadd, groupdel, groupmod 三个指令。
ansible-doc -s group
system=yes 意思是创建系统组
创建组 nginx
[root@shanan ~]# ansible test3 -m group -a 'name=nginx gid=306 system=yes'
192.168.100.10 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 306,
"name": "nginx",
"state": "present",
"system": true
}
[root@shanan ~]# ansible test3 -a 'tail /etc/group'
192.168.100.10 | CHANGED | rc=0 >>
saned:x:983:
gdm:x:42:
gnome-initial-setup:x:982:
sshd:x:74:
slocate:x:21:
avahi:x:70:
postdrop:x:90:
postfix:x:89:
tcpdump:x:72:
nginx:x:306:
[root@shanan ~]# ansible test3 -m user -a 'name=lisi uid=306 group=nginx system=yes'
192.168.100.10 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"comment": "",
"create_home": true,
"group": 306,
"home": "/home/lisi",
"name": "lisi",
"shell": "/bin/bash",
"state": "present",
"system": true,
"uid": 306
}
创建用户 lisi加入nginx组
[root@shanan ~]# ansible test3 -a 'tail /etc/passwd'
192.168.100.10 | CHANGED | rc=0 >>
sssd:x:991:985:User for sssd:/:/sbin/nologin
setroubleshoot:x:990:984::/var/lib/setroubleshoot:/sbin/nologin
saned:x:989:983:SANE scanner daemon user:/usr/share/sane:/sbin/nologin
gdm:x:42:42::/var/lib/gdm:/sbin/nologin
gnome-initial-setup:x:988:982::/run/gnome-initial-setup/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
lisi:x:306:306::/home/lisi:/bin/bash
[root@shanan ~]# ansible test3 -a 'id lisi'
192.168.100.10 | CHANGED | rc=0 >>
uid=306(lisi) gid=306(nginx) groups=306(nginx)
—copy模块--------
将本地的挂载文件配置拷贝到 对方的 opt 目录下,并命名为fstab.bk ,设置属主为root ,权限为644
[root@shanan ~]# ansible test1 -m copy -a 'src=/etc/fstab dest=/opt/fstab.bk owner=root mode=644'
192.168.100.11 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "e05ac6c94a941bbdd288edf5b3cf2f255fd4d904",
"dest": "/opt/fstab.bk",
"gid": 0,
"group": "root",
"md5sum": "267e8121fadd28a0bcfd5c0b1339711d",
"mode": "0644",
"owner": "root",
"size": 541,
"src": "/root/.ansible/tmp/ansible-tmp-1609031909.11-11243-277522247686179/source",
"state": "file",
"uid": 0
}
查看确认,操作成功
[root@shanan ~]# ansible test1 -a 'ls -l /opt'
192.168.100.11 | CHANGED | rc=0 >>
total 4
-rw-r--r-- 1 root root 541 Dec 27 09:18 fstab.bk
drwxr-xr-x. 2 root root 6 Oct 31 2018 rh
在目标主机处创建一个123.txt 文档,并写入内容 this is dog
[root@shanan ~]# ansible test1 -m copy -a 'content="this is dog" dest=/opt/123.txt'
192.168.100.11 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "3200a35079e10df998a94365c8b51ff74479b17c",
"dest": "/opt/123.txt",
"gid": 0,
"group": "root",
"md5sum": "341f6c7b04e6aba7b97e9a5b4a074073",
"mode": "0644",
"owner": "root",
"size": 11,
"src": "/root/.ansible/tmp/ansible-tmp-1609032262.54-11362-265646299341074/source",
"state": "file",
"uid": 0
}
查看确认
[root@shanan ~]# ansible test1 -a 'cat /opt/123.txt'
192.168.100.11 | CHANGED | rc=0 >>
this is dog
------file模块--------指定文件属性
查看使用说:
[root@shanan ~]# ansible-doc -s file
- name: Manage files and file properties
file:
access_time: # This parameter indicates the time the file's
access time
should be set to.
Should be
`preserve' when
no modification
is required,
`YYYYMMDDHHMM.SS'
when using
default time
format, or `now'.
Default is `None'
meaning that
`preserve' is the
default for `stat
e=[file,directory
,link,hard]' and
`now' is default
for
`state=touch'.
access_time_format: # When used with `access_time', indicates the time
format that must
be used. Based on
:
[root@shanan ~]# ansible test2 -m copy -a 'content="this is test" dest=/opt/test.txt owner=root mode=644'
192.168.100.12 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "b6794b2000d94d348203d0279c2e7322b922cb16",
"dest": "/opt/test.txt",
"gid": 0,
"group": "root",
"md5sum": "8c6d115258631625b625486f81b09532",
"mode": "0644",
"owner": "root",
"size": 12,
"src": "/root/.ansible/tmp/ansible-tmp-1609033033.06-11565-14145546920083/source",
"state": "file",
"uid": 0
}
192.168.100.12 | CHANGED | rc=0 >>
this is test
[root@shanan ~]# ansible test2 -a 'ls -l /opt/test.txt'
192.168.100.12 | CHANGED | rc=0 >>
-rw-r--r-- 1 root root 12 Dec 27 09:37 /opt/test.txt
修改 文件 test.txt 的属主,以及权限
[root@shanan ~]# ansible test2 -m file -a 'owner=mysql mode=666 path=/opt/test.txt'
192.168.100.12 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0666",
"owner": "mysql",
"path": "/opt/test.txt",
"size": 12,
"state": "file",
"uid": 987
}
[root@shanan ~]# ansible test2 -a 'ls -l /opt/test.txt'
192.168.100.12 | CHANGED | rc=0 >>
修改其属组 为 mysql
[root@shanan ~]# ansible test2 -m file -a 'group=mysql path=/opt/test.txt'
192.168.100.12 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 981,
"group": "mysql",
"mode": "0666",
"owner": "mysql",
"path": "/opt/test.txt",
"size": 12,
"state": "file",
"uid": 987
}
[root@shanan ~]# ansible test2 -a 'ls -l /opt/test.txt'
192.168.100.12 | CHANGED | rc=0 >>
-rw-rw-rw- 1 mysql mysql 12 Dec 27 09:37 /opt/test.txt
-rw-rw-rw- 1 mysql root 12 Dec 27 09:37 /opt/test.txt
建立软连接
将opt 下的 test.txt 创建一个软连接到etc目录下
[root@shanan ~]# ansible test2 -m file -a 'path=/etc/text.txt src=/opt/test.txtstate=link'
192.168.100.12 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dest": "/etc/text.txt",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"size": 13,
"src": "/opt/test.txt",
"state": "link",
"uid": 0
}
查看确认,创建成功
[root@shanan ~]# ansible test2 -a 'ls -l /etc/text.txt '
192.168.100.12 | CHANGED | rc=0 >>
lrwxrwxrwx 1 root root 13 Dec 27 09:49 /etc/text.txt -> /opt/test.txt
创建一个空文件 abc.txt
[root@shanan ~]# ansible test2 -m file -a 'path=/opt/abc.txt state=touch '
192.168.100.12 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dest": "/opt/abc.txt",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"size": 0,
"state": "file",
"uid": 0
}
查看确认
[root@shanan ~]# ansible test2 -a 'ls -l /opt '
192.168.100.12 | CHANGED | rc=0 >>
total 4
-rw-r--r-- 1 root root 0 Dec 27 09:54 abc.txt
-rw-rw-rw- 1 mysql mysql 12 Dec 27 09:37 test.txt
删除文件 abc.txt
[root@shanan ~]# ansible test2 -m file -a 'path=/opt/abc.txt state=absent '
192.168.100.12 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"path": "/opt/abc.txt",
"state": "absent"
}
查看确认
[root@shanan ~]# ansible test2 -a 'ls -l /opt '
192.168.100.12 | CHANGED | rc=0 >>
total 4
-rw-rw-rw- 1 mysql mysql 12 Dec 27 09:37 test.txt
创建目录 usb
[root@shanan ~]# ansible test2 -m file -a 'path=/opt/usb state=directory mode=755 owner=root group=mysql '
192.168.100.12 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 981,
"group": "mysql",
"mode": "0755",
"owner": "root",
"path": "/opt/usb",
"size": 6,
"state": "directory",
"uid": 0
}
[root@shanan ~]# ansible test2 -a 'ls -l /opt '
192.168.100.12 | CHANGED | rc=0 >>
total 4
-rw-rw-rw- 1 mysql mysql 12 Dec 27 09:37 test.txt
drwxr-xr-x 2 root mysql 6 Dec 27 09:57 usb
删除组
[root@shanan ~]# ansible test2 -m file -a 'path=/opt/usb state=absent'
192.168.100.12 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"path": "/opt/usb",
"state": "absent"
}
查看确认
[root@shanan ~]# ansible test2 -a 'ls -l /opt '
192.168.100.12 | CHANGED | rc=0 >>
total 4
-rw-rw-rw- 1 mysql mysql 12 Dec 27 09:37 test.txt
-----ping模块-------
测试被管理主机是否在线
[root@shanan ~]# ansible all -m ping
192.168.100.9 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).",
"unreachable": true
}
127.0.0.1 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: Warning: Permanently added '127.0.0.1' (ECDSA) to the list of known hosts.\r\nPermission denied (publickey,gssapi-keyex,gssapi-with-mic,password).",
"unreachable": true
}
192.168.100.11 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.100.12 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.100.10 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
-----yum模块-----
安装httpd
[root@shanan ~]# ansible test1 -m yum -a 'name=httpd'
192.168.100.11 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"changes": {
"installed": [
"httpd"
]
},
"msg": "warning: /var/cache/yum/x86_64/7/base/packages/mailcap-2.1.41-2.el7.noarch.rpm: Header V3 RSA/SHA256 Signature, key ID f4a80eb5: NOKEY\nImporting GPG key 0xF4A80EB5:\n Userid : \"CentOS-7 Key (CentOS 7 Official Signing Key)<security@centos.org>\"\n Fingerprint: 6341 ab27 53d7 8a78 a7c2 7bb1 24c6 a8a7 f4a8 0eb5\n Package : centos-release-7-6.1810.2.el7.centos.x86_64 (@anaconda)\n From : /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7\n",
"rc": 0,
"results": [
"Loaded plugins: fastestmirror, langpacks\nLoading mirror speeds from cached hostfile\n * base: mirrors.ustc.edu.cn\n * extras: mirrors.bfsu.edu.cn\n *updates: mirrors.ustc.edu.cn\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.4.6-97.el7.centos will be installed\n--> Processing Dependency: httpd-tools = 2.4.6-97.el7.centos for package: httpd-2.4.6-97.el7.centos.x86_64\n--> Processing Dependency: /etc/mime.types for package: httpd-2.4.6-97.el7.centos.x86_64\n--> Running transaction check\n---> Package httpd-tools.x86_64 0:2.4.6-97.el7.centos will be installed\n---> Package mailcap.noarch 0:2.1.41-2.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n httpd x86_64 2.4.6-97.el7.centos updates 2.7 M\nInstalling for dependencies:\n httpd-tools x86_64 2.4.6-97.el7.centos updates 93 k\n mailcap noarch 2.1.41-2.el7 base 31 k\n\nTransaction Summary\n================================================================================\nInstall 1 Package (+2 Dependent packages)\n\nTotal download size: 2.8 M\nInstalled size: 9.6 M\nDownloading packages:\nPublic key for mailcap-2.1.41-2.el7.noarch.rpm is not installed\nPublic key for httpd-tools-2.4.6-97.el7.centos.x86_64.rpm is not installed\n--------------------------------------------------------------------------------\nTotal 2.2 MB/s | 2.8 MB 00:01 \nRetrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Installing : httpd-tools-2.4.6-97.el7.centos.x86_64 1/3 \n Installing : mailcap-2.1.41-2.el7.noarch 2/3 \n Installing : httpd-2.4.6-97.el7.centos.x86_64 3/3 \n Verifying : httpd-2.4.6-97.el7.centos.x86_64 1/3 \n Verifying : mailcap-2.1.41-2.el7.noarch 2/3 \n Verifying : httpd-tools-2.4.6-97.el7.centos.x86_64 3/3 \n\nInstalled:\n httpd.x86_64 0:2.4.6-97.el7.centos \n\nDependency Installed:\n httpd-tools.x86_64 0:2.4.6-97.el7.centos mailcap.noarch 0:2.1.41-2.el7 \n\nComplete!\n"
]
}
查看确认,已安装
Last login: Sat Dec 26 21:48:26 2020 from 192.168.100.48
[root@server 11 ~]# rpm -q httpd
httpd-2.4.6-97.el7.centos.x86_64
[root@server 11 ~]#
卸载软件
[root@shanan ~]# ansible test1 -m yum -a 'name=httpd state=absent'
192.168.100.11 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"changes": {
"removed": [
"httpd"
]
},
"msg": "",
"rc": 0,
"results": [
"Loaded plugins: fastestmirror, langpacks\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.4.6-97.el7.centos will be erased\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nRemoving:\n httpd x86_64 2.4.6-97.el7.centos @updates 9.4 M\n\nTransaction Summary\n================================================================================\nRemove 1 Package\n\nInstalled size: 9.4 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Erasing : httpd-2.4.6-97.el7.centos.x86_64 1/1 \n Verifying : httpd-2.4.6-97.el7.centos.x86_64 1/1 \n\nRemoved:\n httpd.x86_64 0:2.4.6-97.el7.centos \n\nComplete!\n"
]
}
查看确认
[root@server 11 ~]# rpm -q httpd
httpd-2.4.6-97.el7.centos.x86_64
[root@server 11 ~]# rpm -q httpd
未安装软件包 httpd
----service模块--------
将httpd 服务设为开机自启动,并启动
[root@shanan ~]# ansible test1 -m service -a 'name=httpd enabled=true state=started'
192.168.100.11 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},tonic": "0",
"ExecMainStatus": "0",
"ExecReload": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS-k graceful ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }",
"ExecStart": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -DFOREGROUND ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }",
"ExecStop": "{ path=/bin/kill ; argv[]=/bin/kill -WINCH ${MAINPID} ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }",
"FailureAction": "none",
"FileDescriptorStoreMax": "0",
"FragmentPath": "/usr/lib/systemd/system/httpd.service",
"GuessMainPID": "yes",
"IOScheduling": "0",
"Id": "httpd.service",
"IgnoreOnIsolate": "no",
"IgnoreOnSnapshot": "no",
"551615",
"TimeoutStartUSec": "1min 30s",
"TimeoutStopUSec": "1min 30s",
"TimerSlackNSec": "50000",
"Transient": "no",
"Type": "notify",
"UMask": "0022",
"UnitFilePreset": "disabled",
"UnitFileState": "disabled",
"Wants": "system.slice",
"WatchdogTimestampMonotonic": "0",
"WatchdogUSec": "0"
}
}
查看确认
[root@server 11 ~]# systemctl status httpd
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
Active: active (running) since 日 2020-12-27 10:14:05 CST; 24s ago
Docs: man:httpd(8)
man:apachectl(8)
Main PID: 22212 (httpd)
Status: "Total requests: 0; Current requests/sec: 0; Current traffic: 0 B/sec"
Tasks: 6
CGroup: /system.slice/httpd.service
├─22212 /usr/sbin/httpd -DFOREGROUND
├─22215 /usr/sbin/httpd -DFOREGROUND
├─22216 /usr/sbin/httpd -DFOREGROUND
├─22217 /usr/sbin/httpd -DFOREGROUND
├─22218 /usr/sbin/httpd -DFOREGROUND
└─22219 /usr/sbin/httpd -DFOREGROUND
12月 27 10:14:05 server 11 systemd[1]: Starting The Apache HTTP Server...
12月 27 10:14:05 server 11 httpd[22212]: AH00558: httpd: Could not reliably determine th...age
12月 27 10:14:05 server 11 systemd[1]: Started The Apache HTTP Server.
Hint: Some lines were ellipsized, use -l to show in full.
关闭 httpd开启自启动,以及关闭服务
[root@shanan ~]# ansible test1 -m service -a 'name=httpd enabled=false state=stopped'
192.168.100.11 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"enabled": false,
"name": "httpd",
"state": "stopped",
"status": {
"ActiveEnterTimestamp": "Sun 2020-12-27 10:14:05 CST",
"ActiveEnterTimestampMonotonic": "13479505196",
"ActiveExitTimestampMonotonic": "0",
"CanStop": "yes",
"C12-27 10:14:05 CST",
"ExecMainStartTimestampMonotonic": "13479433549",
"ExecMainStatus": "0",
"ExecReload": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS-k graceful ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }",
"ExecStart": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -DFOREGROUND ; ignore_errors=no ; start_time=[Sun 2020-12-27 10:14:05 CST] ; stop_time=[n/a] ; pid=22212 ; code=(null) ; status=0/0 }",
"ExecStop": "{ path=/bin/kill ; argv[]=/bin/kill -WINCH ${MAINPID} ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }",
"FailureAction": "none",
"FileDescriptorStoreMax": "0",
"FragmentPath": "/usr/lib/systemd/system/httpd.service",
"GuessMainPID": "yes",
"IOScheduling": "0",
"Id": "httpd.service",
"IgnoreOnIsolate": "no",
"I5",
"LimitRTPRIO": "0",
"LimitRTTIME": "18446744073709551615",
"LimitSIGPENDING": "7730",
"LimitSTACK": "18446744073709551615",
"LoadState": "loaded",
"MainPID": "22212",
"MemoryAccounting": "no",
"MemoryCurrent": "18446744073709551615",
"MemoryLimit": "18446744073709551615",
"MountFlags": "0",
..................
"WantedBy": "multi-user.target",
"Wants": "system.slice",
"WatchdogTimestamp": "Sun 2020-12-27 10:14:05 CST",
"WatchdogTimestampMonotonic": "13479505172",
"WatchdogUSec": "0"
}
}
查看状态确认
[root@shanan ~]# ansible test1 -a 'systemctl status httpd'
192.168.100.11 | FAILED | rc=3 >>
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
Active: inactive (dead)
Docs: man:httpd(8)
man:apachectl(8)
Dec 27 10:14:05 server 11 systemd[1]: Starting The Apache HTTP Server...
Dec 27 10:14:05 server 11 httpd[22212]: AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using fe80::20c:29ff:fe0e:5518. Set the 'ServerName' directive globally to suppress this message
Dec 27 10:14:05 server 11 systemd[1]: Started The Apache HTTP Server.
Dec 27 10:20:14 server 11 systemd[1]: Stopping The Apache HTTP Server...
Dec 27 10:20:15 server 11 systemd[1]: Stopped The Apache HTTP Server.non-zero return code
Shell 模块
创建用户TOM ,并设置其密码
[root@shanan ~]# ansible test2 -m user -a 'name=tom'
192.168.100.12 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"comment": "",
"create_home": true,
"group": 1000,
"home": "/home/tom",
"name": "tom",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 1000
}
[root@shanan ~]# ansible test2 -m shell -a 'echo abc123 | passwd --stdin tom'
192.168.100.12 | CHANGED | rc=0 >>
Changing password for user tom.
passwd: all authentication tokens updated successfully.
Script 模块
让你在本地设置一个脚本,让下面所有的节点服务器都可以执行这个脚本
首先在本地创建一个脚本
[root@shanan ~]# vim test.sh
#!/bin/bash
echo "hello ansible from script"> /opt/script.txt
chmod 666 /opt/script.txt
[root@shanan ~]# chmod +x test.sh
让目标主机执行此脚本,此时用的相对路径,完整路径也可以
[root@shanan ~]# ansible tests -m script -a 'test.sh'
192.168.100.11 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.100.11 closed.\r\n",
"stderr_lines": [
"Shared connection to 192.168.100.11 closed."
],
"stdout": "",
"stdout_lines": []
}
192.168.100.12 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.100.12 closed.\r\n",
"stderr_lines": [
"Shared connection to 192.168.100.12 closed."
],
"stdout": "",
"stdout_lines": []
}
查看执行情况,执行成功
[root@shanan ~]# ansible tests -a 'cat /opt/script.txt'
192.168.100.12 | CHANGED | rc=0 >>
hello ansible from script
192.168.100.11 | CHANGED | rc=0 >>
hello ansible from script
-----setup模块-------
收集信息的模块
[root@shanan ~]# ansible test1 -m setup
192.168.100.11 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.100.11",
"192.168.122.1"
],
...................................
"gather_subset": [
"all"
],
"module_setup": true
},
"changed": false
}
三. Ansible 的主机清单详解
Inventory文件 默认vim/etc/ansible/hosts,也可以-i ./hosts指定Inventory file,告诉我们连接到哪里
比较简单的管理方法介绍
1. 是将用户名密码写入hosts文件里面:
Vim /etc/ansible/hosts
[remotr]
192.168.100.12 ansible_ssh_user=root ansible_ssh_pass=123456
执行时报错
192.168.100.11 | FAILED | rc=-1 >>
Using a SSH password instead of a key is not possible because Host Key checkingis enabled and sshpass does not support this. Please add this host's fingerprint to your known_hosts file to manage this host.
解决方法两种:第一种:在本地先SSH登录一下对方设备,下次ansible 就可以正常操作了
第二种:
设置参数为不检查
vim /etc/ansible/ansible.cfg
host_key_checking = False
[root@shanan ~]# ansible test3 -a 'ls'
192.168.100.10 | CHANGED | rc=0 >>
anaconda-ks.cfg
original-ks.cfg
下载
公共
图片
2. 为了安全考虑可以进行如下配置尾部加上 --ask-pass
Vim /etc/ansible/hosts
[test4]
192.168.100.9 ansible_ssh_user=root
[root@shanan ~]# ansible test4 -a 'ls' --ask-pass
SSH password: 会提示输入登录密码
192.168.100.9 | CHANGED | rc=0 >>
anaconda-ks.cfg
original-ks.cfg
下载
公共
3. 配置SSH秘钥免交互
vim /etc/ansible/hosts
[test5]
192.168.100.8
生成秘钥对
[root@shanan ~]# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again: 输入 密码 ABC123
Passphrases do not match. Try again.
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:uM6igaMNEXtPqDkCxG0WXYr+sRvR7rcRHJONXxqC+F8 root@shanan
The key's randomart image is:
+---[RSA 2048]----+
| .. .. |
|. . o.o . + |
|.o = o . * o . |
|.o+. o.. = + |
|+ o..o.oSo E |
|.* o. =.. o |
|O . .+.. o |
|o= ..o+ .. |
|. o. oo.... |
+----[SHA256]-----+
[root@shanan ~]#
会生成 公钥和私钥
[root@shanan .ssh]# ls
id_rsa id_rsa.pub known_hosts
[root@shanan .ssh]# pwd
/root/.ssh
把公钥推给被管理端
[root@shanan .ssh]# ssh-copy-id root@192.168.100.8
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '192.168.100.8 (192.168.100.8)' can't be established.
ECDSA key fingerprint is SHA256:3UrnCWbEvpcUONvqSHvPW8QTvG7u/FKTrrkt/rRm7og.
ECDSA key fingerprint is MD5:d3:74:d7:b3:ae:86:6d:ae:d4:07:90:56:99:ca:29:00.
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 filterout 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.100.8's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'root@192.168.100.8'"
and check to make sure that only the key(s) you wanted were added.
在目标主机 查看接受的公钥
[root@master2 ~]# cd .ssh
[root@master2 .ssh]# ls
authorized_keys
[root@master2 .ssh]#
操作指令
[root@shanan .ssh]# ansible test5 -a 'date'
Enter passphrase for key '/root/.ssh/id_rsa': 输入刚才设置的密码 ABC123
Enter passphrase for key '/root/.ssh/id_rsa':
192.168.100.8 | CHANGED | rc=0 >>
Sun Dec 27 11:57:58 CST 2020
这样每次输入比较麻烦,我们设置代理
[root@shanan .ssh]# ssh-agent bash
[root@shanan .ssh]# ssh-add
Enter passphrase for /root/.ssh/id_rsa: 输入密码 ABC123
Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)
再次操作,可以直接执行了
[root@shanan .ssh]# ansible test5 -a 'ls'
192.168.100.8 | CHANGED | rc=0 >>
anaconda-ks.cfg
original-ks.cfg
下载
4. 本机被 ansible 管理的配置
Vim /etc/hosts
[local]
127.0.0.1
[root@shanan ~]# ansible --connection=local local -m ping
127.0.0.1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
参数说明
--connection=local的意思是不需要通过ssh连接,因为我们针对的就是本地,还可以是--connection=ssh意思是需要ssh连接。
-i ./hosts指定Inventory file,告诉我们连接到哪里
remote,local,all指明使用哪个标签下面的服务器清单,all表示针对每个服务器运行
-m ping表示使用ping模块,会返回ping结果
将一个组变成另一个组的成员
Vim /etc/ansible/hosts
[local]
127.0.0.1
[test1]
192.168.100.11 ansible_ssh_user=root ansible_ssh_pass=shanan1023
[test2]
192.168.100.12 ansible_ssh_user=root ansible_ssh_pass=shanan1023
[test3]
192.168.100.10 ansible_ssh_user=root ansible_ssh_pass=shanan1023
[test4]
192.168.100.9 ansible_ssh_user=root
[tests:children] //此:children 是必须套用的格式,不能替代
test1
test2
执行验证成功
[root@shanan ~]# ansible tests -a 'ls'
192.168.100.11 | CHANGED | rc=0 >>
anaconda-ks.cfg
original-ks.cfg
下载
公共
图片
文档
192.168.100.12 | CHANGED | rc=0 >>
anaconda-ks.cfg
original-ks.cfg
下载
公共
图片
文档
下面不再实操,自行操作
对于每一个host可以选择连接类型和连接用户名:
[targets]
localhost ansible_connection=local
39.107.74.200 ansible_connection=ssh ansible_ssh_user=root
给整个组添加变量
上面是给服务器单独配置变量,但是也可以给整个组配置变量:
[remote:vars]
ansible_connection=ssh
[remote]
host1
host2
只要需要配置的组的名字对上了,就可以获取配置
各种参数说明:
其他说明
————主机清单
ansible默认的主机清单是/etc/ansible/hosts文件
主机清单可以手动设置,也可以通过Dynamic Inventory动态生成
一般主机名使用FQDN
vi /etc/ansible/hosts
[webserver] #方括号设置组名
www1.example.org #定义被监控主机,这边可以是主机名也可以是IP地址,主机名需要修改/etc/hosts文件
www2.example.org:2222 #冒号后定义远程连接端口,默认是ssh的22端口
如果是名称类似的主机,可以使用列表的方式标识各个主机
[webserver]
www[01:50].example.org ansible_ssh_user=root ansible_ssh_pass=123456
[dbbservers]
db-[a:f].example.org //支持匹配a b c ... f
下面是Inventory中变量
(1)主机变量
[webserver]
www1.magedu.com http_port=80 WEB端口 maxRequestsChild=808 最大访问进程数
www2.magedu.com http_port=8080 maxRequestsChild=909
(2)组变量
[servers:vars]
ntp_server=ntp.example.org
nfs_server=nfs.example.org
(3)组嵌套
[apache]
http1.example.org
http2.example.org
[nginx]
ngx1.example.org
ngx2.example.org
[webservers:children]
apache
nginx
(4)inventory变量参数
参数 说明
ansible_ssh_host 将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置.
ansible_ssh_port ssh端口号.如果不是默认的端口号,通过此变量设置.
ansible_ssh_user 默认的 ssh 用户名
ansible_ssh_pass ssh 密码(这种方式并不安全,我们强烈建议使用 --ask-pass 或 SSH 密钥)
ansible_sudo_pass sudo 密码,建议使用–ask-sudo-pass
ansible_connection 与远程主机连接类型local ssh
ansible_ssh_private_key_file ssh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的情况.
ansible_ssh_common_args 此设置附加到sftp,scp和ssh的缺省命令行
ansible_sftp_extra_args 此设置附加到默认sftp命令行。
ansible_scp_extra_args 此设置附加到默认scp命令行。
ansible_ssh_extra_args 此设置附加到默认ssh命令行。
ansible_ssh_pipelining 确定是否使用SSH管道。 这可以覆盖ansible.cfg中得设置。
ansible_shell_type 目标系统的shell类型.默认情况下,命令的执行使用 ‘sh’ 语法,可设置为 ‘csh’ 或 ‘fish’.
ansible_python_interpreter 目标主机的 python 路径.适用于的情况: 系统中有多个 Python, 或者命令路径不是"/usr/bin/python",比如 BSD, 或者 /usr/bin/python
ansible__interpreter 这里的"*"可以是ruby 或perl 或其他语言的解释器,作用和ansible_python_interpreter 类似
ansible_shell_executable 这将设置ansible控制器将在目标机器上使用的shell,覆盖ansible.cfg中的配置,默认为/bin/sh。