当管理的服务器很多时,假设有1000台,如果想要在1000台服务器上做一个简单的操作:
&
符放到后台执行,则会产生1000个进程自动化运维:将日常IT运维中大量的重复性工作,小到简单的日常检查、配置变更和软件安装,大到整个变更流程的组织调度,由过去的手工执行转为自动化操作,从而减少乃至消除运维中的延迟,实现“零延时”的IT运维
管理多台服务器,自动化运维需要关注以下几个方面
管理机与被管理机的连接(管理机如何将管理指令发送给被管理机)
服务器信息收集 (如果被管理的服务器有centos7.5外还有其它linux发行版,如suse,ubuntu等。当你要做的事情在不同OS上有所不同,你需要收集信息,并将其分开处理)
服务器分组(因为有些时候我要做的事情不是针对所有服务器,可能只针对某一个分组)
管理内容的主要分类
常见自动化运维工具
puppet
基于ruby语言,成熟稳定。适合于大型架构,相对于ansible和saltstack会复杂些。
saltstack
基于python语言,相对简单,大并发能力比ansible要好, 但需要维护被管理端的服务。如果服务断开,连接就会出问题。
ansible
基于python语言,简单快捷,被管理端不需要启服务。直接走ssh协议,需要验证所以机器多的话速度会较慢。
ansible是一种由Python开发的自动化运维工具,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能
ansible是基于模块工作的,本身没有批量部署的能力,真正具有批量部署能力的是ansible运行的模块,ansible只是提供一个框架。
特点
执行过程
核心组件
虚拟机 | IP地址 | 作用 |
---|---|---|
server1 | 192.168.139.10 | 管理节点 |
server2 | 192.168.139.20 | 被管理节点 |
server3 | 192.168.139.30 | 被管理节点 |
域名解析
cat >> /etc/hosts <.168.139.10 server1
192.168.139.20 server2
192.168.139.30 server3
EOF
关闭防火墙,selinux
systemctl stop firewalld
systemctl disable firewalld
iptables -F
setenforce 0
sed -i 's/SELINUX=enforced/SELINUX=disabled/' /etc/selinux/config
时间同步
ntpdate cn.ntp.org.cn
yum源配置
yum install -y epel-release.noarch
[root@server1 ~]# yum install ansible -y
[root@server1 ~]# ansible --version
ansible 2.9.25
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, Nov 16 2020, 22:23:17) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
[root@server1 ~]# ssh-keygen
[root@server1 ~]# ssh-copy-id 192.168.139.20
[root@server1 ~]# ssh-copy-id 192.168.139.30
[root@server1 ~]# vim /etc/ansible/hosts
[root@server1 ~]# cat /etc/ansible/hosts |grep -Ev '^#|^$'
[mygroup]
192.168.139.20
192.168.139.30
[root@server1 ~]# ansible -m ping all
192.168.139.20 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.139.30 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
[root@server1 ~]# ansible -m ping mygroup
192.168.139.20 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.139.30 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
多台合写
apache[1:10].aaa.com 表示apache1.aaa.com到apache10.aaa.com这10台机器
nginx[a:z].aaa.com 表示nginxa.aaa.com到nginxz.aaa.com共26台机器
10.1.1.[11:15] 表示10.1.1.11到10.1.1.15这5台机器
定义端口
10.1.1.13:2222
定义别名(定义10.1.1.12:2222这台服务器的别名为nginx1)
nginx1 ansible_ssh_host=10.1.1.13 ansible_ssh_port=2222
指定用户名和密码
nginx1 ansible_ssh_host=10.1.1.13 ansible_ssh_port=2222 ansible_ssh_user=root ansible_ssh_pass="123456"
利用别名分组
ginx1 ansible_ssh_host=10.1.1.13 ansible_ssh_port=2222 ansible_ssh_user=root ansible_ssh_pass="123456"
nginx2 ansible_ssh_host=10.1.1.12
[nginx]
nginx1
nginx2
官网模块文档地址: https://docs.ansible.com/ansible/latest/modules/list_of_all_modules.html
ansible的执行状态
- 绿色:执行成功并且不需要做改变的操作
- 黄色:执行成功并且对目标主机做变更
- 红色:执行失败
- 粉色:警告信息
- 蓝色:显示ansible命令执行的过程
查看模块用法
ansible-doc 模块名
使用模块的基本格式
ansible 操作对象(域名|IP地址|组名) -m 模块名 -a "参数1=值1 参数2=值2"
[root@server1 ~]# ansible -m ping mygroup
192.168.139.30 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.139.20 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
[root@server1 ~]# ansible 192.168.139.20 -m hostname -a 'name=server2'
192.168.139.20 | CHANGED => {
"ansible_facts": {
"ansible_domain": "",
"ansible_fqdn": "server2",
"ansible_hostname": "server2",
"ansible_nodename": "server2",
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"name": "server2"
}
官网:https://docs.ansible.com/ansible/latest/modules/file_module.html#file-module
操作文件(创建, 删除, 软硬链接等)
创建目录
[root@server1 ~]# ansible mygroup -m file -a 'path=/test state=directory'
创建文件
[root@server1 ~]# ansible mygroup -m file -a 'path=/test/file1 state=touch'
创建软连接
[root@server1 ~]# ansible mygroup -m file -a 'src=/etc/fstab path=/tmp/fstab state=link'
创建硬链接
[root@server1 ~]# ansible mygroup -m file -a 'src=/etc/fstab path=/tmp/fstab1 state=hard'
递归修改owner,group,mode
[root@server1 ~]# ansible mygroup -m file -a 'path=/test recurse=yes owner=bin group=daemon mode=1777'
删除文件
[root@server1 ~]# ansible mygroup -m file -a 'path=/test/file1 state=absent'
拷贝
[root@server1 ~]# ansible mygroup -m copy -a 'src=/etc/fstab dest=/tmp/fstab'
如果文件存在,不覆盖
[root@server1 ~]# ansible mygroup -m copy -a 'src=/etc/fstab dest=/tmp/fstab force=no'
如果文件存在,先备份,后覆盖
[root@server1 ~]# ansible mygroup -m copy -a 'src=/etc/fstab dest=/tmp/fstab backup=yes'
拷贝目录要注意/
/etc/表示拷贝etc目录里的所有文件
/etc表示拷贝整个etc目录
如果想要目录内的内容完全一致,copy模块不能做到
因为copy模块默认不会删除目标目录内的多余文件
可以先删除目标文件|目录,再使用copy模块实现
[root@server1 ~]# ansible mygroup -m file -a 'path=/etc/yum.repos.d/ state=absent'
[root@server1 ~]# ansible mygroup -m copy -a 'src=/etc/yum.repos.d dest=/etc/'
[root@server1 ~]# ansible 192.168.139.20 -m fetch -a 'src=/tmp/fstab dest=/tmp/'
创建普通用户
[root@server1 ~]# ansible mygroup -m user -a 'name=zhangsan state=present'
创建系统用户
[root@server1 ~]# ansible mygroup -m user -a 'name=aaa state=present system=yes shell="/sbin/nologin"'
创建用户,指定uid,指定密码
[root@server1 ~]# echo 123456 |openssl passwd -1 -stdin
$1$K32qQQ5j$mS.9Ecez2jbROYL6auz7N0
[root@server1 ~]# ansible mygroup -m user -a 'name=lisi state=present uid=2000 password="$1$K32qQQ5j$mS.9Ecez2jbROYL6auz7N0"'
用户添加到组中
[root@server1 ~]# ansible mygroup -m user -a 'name=zhangsan state=present group=1500'
删除用户
[root@server1 ~]# ansible mygroup -m user -a 'name=zhangsan state=absent'
删除用户的同时删除家目录
[root@server1 ~]# ansible mygroup -m user -a 'name=aaa state=absent remove=yes'
创建
[root@server1 ~]# ansible mygroup -m group -a 'name=group_test state=present gid=1500'
删除组(先删组中用户)
[root@server1 ~]# ansible mygroup -m user -a 'name=zhangsan state=absent'
[root@server1 ~]# ansible mygroup -m group -a 'name=group_test state=absent'
创建
[root@server1 ~]# ansible mygroup -m cron -a 'name=cron1 user=root job="touch /tmp/111" minute=*/2 hour=1'
删除
[root@server1 ~]# ansible mygroup -m cron -a 'name=cron1 state=absent'
安装
[root@server1 ~]# ansible mygroup -m yum -a 'name=vsftpd state=present'
安装最新版
[root@server1 ~]# ansible mygroup -m yum -a 'name=httpd,httpd-devel state=latest'
卸载
[root@server1 ~]# ansible mygroup -m cron -a 'name=cron1 state=absent'
启动服务,并设置为开机自启
[root@server1 ~]# ansible mygroup -m service -a 'name=vsftpd state=started enabled=on'
关闭服务,并设为开机不自动启动
[root@server1 ~]# ansible mygroup -m service -a 'name=vsftpd state=stopped enabled=false'
准备脚本
[root@server1 ~]# vim /tmp/1.sh
[root@server1 ~]# cat /tmp/1.sh
#!/bin/bash
yum install -y mariadb-server &> /dev/null
systemctl start mariadb
systemctl enable mariadb
mysql << EOF
create database abc;
quit
EOF
远程执行脚本
[root@server1 ~]# ansible mygroup -m script -a '/tmp/1.sh'
[root@server1 ~]# ansible mygroup -m shell -a 'useradd xiaoming'
192.168.139.20 | CHANGED | rc=0 >>
192.168.139.30 | CHANGED | rc=0 >>
[root@server1 ~]# ansible mygroup -m shell -a 'id xiaoming'
192.168.139.20 | CHANGED | rc=0 >>
uid=2002(xiaoming) gid=2002(xiaoming) 组=2002(xiaoming)
192.168.139.30 | CHANGED | rc=0 >>
uid=2002(xiaoming) gid=2002(xiaoming) 组=2002(xiaoming)
[root@server1 ~]# ansible mygroup -m shell -a 'tail -1 /etc/passwd'
192.168.139.20 | CHANGED | rc=0 >>
xiaoming:x:2002:2002::/home/xiaoming:/bin/bash
192.168.139.30 | CHANGED | rc=0 >>
xiaoming:x:2002:2002::/home/xiaoming:/bin/bash
playbook(剧本): 是ansible用于配置,部署,和管理被控节点的剧本。用于ansible操作的编排
playbook是由一个或者多个play组成的列表,可以让这些列表按事先编排的机制执行;所谓task是调用ansible的具体模块,在模块参数中可以使用变量。模块执行是幂等性的,意味着多次执行结果相同。
使用yaml语言编写playbook,后缀名一般为.yml(saltstack,elk,docker,docker-compose,kubernetes等也都会用到yaml格式)
https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html
.yaml
或.yml
结尾"---"
开始,表明YMAL文件(或段落)的开始,可不写"- "
作为开头(一个横杠和一个空格)键: 值
的形式组成**(这个冒号后面必须是一个空格)**https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html#yaml-syntax
官方示例
---
- 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
准备配置文件并修改
[root@server1 playbook]# yum install -y vsftpd
[root@server1 playbook]# vim /etc/vsftpd/vsftpd.conf
剧本编写
[root@server1 ~]# cd /etc/ansible/
[root@server1 ansible]# mkdir playbook
[root@server1 ansible]# cd playbook/
[root@server1 playbook]# vim vsftpd.yml
[root@server1 playbook]# cat vsftpd.yml
---
- hosts: mygroup
remote_user: root
tasks:
- name: 安装vstfpd
yum: name=vsftpd state=present
- name: 同步vsftpd.conf配置文件
copy: src=/etc/vsftpd/vsftpd.conf dest=/etc/vsftpd/vsftpd.conf
notify: restart vsftpd
- name: 启动vsftpd服务,并设置开机自启
service: name=vsftpd state=started enabled=on
handlers:
- name: restart vsftpd
service: name=vsftpd state=restarted
执行剧本
[root@server1 playbook]# ansible-playbook vsftpd.yml
PLAY [mygroup] **********************************************************************************
TASK [Gathering Facts] **************************************************************************
ok: [192.168.139.20]
ok: [192.168.139.30]
TASK [安装vstfpd] *********************************************************************************
ok: [192.168.139.30]
ok: [192.168.139.20]
TASK [同步vsftpd.conf配置文件] ************************************************************************
changed: [192.168.139.20]
changed: [192.168.139.30]
TASK [启动vsftpd服务,并设置开机自启] ***********************************************************************
changed: [192.168.139.30]
changed: [192.168.139.20]
RUNNING HANDLER [restart vsftpd] ****************************************************************
changed: [192.168.139.20]
changed: [192.168.139.30]
PLAY RECAP **************************************************************************************
192.168.139.20 : ok=5 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.139.30 : ok=5 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
准备nfs配置文件
[root@server1 playbook]# vim /etc/exports
[root@server1 playbook]# cat /etc/exports
/share *(ro)
编写剧本
[root@server1 playbook]# vim nfs.yml
[root@server1 playbook]# cat nfs.yml
---
- hosts: mygroup
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: 192.168.139.20
remote_user: root
tasks:
- name: 安装nfs客户端软件包
yum: name=nfs-utils state=latest
- name: 挂载nfs服务器的共享
shell: mount 192.168.139.30:/share /mnt
执行剧本
[root@server1 playbook]# ansible-playbook nfs.yml
验证
[root@server2 ~]# df -Th
文件系统 类型 容量 已用 可用 已用% 挂载点
devtmpfs devtmpfs 899M 0 899M 0% /dev
tmpfs tmpfs 910M 0 910M 0% /dev/shm
tmpfs tmpfs 910M 18M 893M 2% /run
tmpfs tmpfs 910M 0 910M 0% /sys/fs/cgroup
/dev/mapper/centos-root xfs 17G 2.1G 15G 12% /
/dev/sda1 xfs 1014M 194M 821M 20% /boot
tmpfs tmpfs 182M 0 182M 0% /run/user/0
192.168.139.30:/share nfs4 17G 2.1G 15G 12% /mnt
[root@server1 playbook]# cd /etc/ansible/roles/
[root@server1 roles]# mkdir -p {httpd,mysql,php}/{files,tasks,handlers,templates,vars,meta}
[root@server1 roles]# touch {httpd,mysql,php}/{tasks,handlers,vars,meta}/main.yaml
[root@server1 roles]# tree -a /etc/ansible/roles/
/etc/ansible/roles/
├── httpd
│ ├── files
│ ├── handlers
│ │ └── main.yaml
│ ├── meta
│ │ └── main.yaml
│ ├── tasks
│ │ └── main.yaml
│ ├── templates
│ └── vars
│ └── main.yaml
├── mysql
│ ├── files
│ ├── handlers
│ │ └── main.yaml
│ ├── meta
│ │ └── main.yaml
│ ├── tasks
│ │ └── main.yaml
│ ├── templates
│ └── vars
│ └── main.yaml
└── php
├── files
├── handlers
│ └── main.yaml
├── meta
│ └── main.yaml
├── tasks
│ └── main.yaml
├── templates
└── vars
└── main.yaml
准备http主页文件
[root@server1 roles]# echo 'test main page' > /etc/ansible/roles/httpd/files/index.html
准备php测试文件
[root@server1 roles]# echo -e "" > /etc/ansible/roles/httpd/files/test.php
将http主页文件和php测试文件移动同一目录下,便于拷贝
[root@server1 roles]# cd httpd/files/
[root@server1 files]# mkdir httpd_doc
[root@server1 files]# mv index.html httpd_doc/
[root@server1 files]# mv test.php httpd_doc/
准备并修改httpd的配置文件
[root@server1 roles]# yum install -y httpd
[root@server1 roles]# vim /etc/httpd/conf/httpd.conf
[root@server1 roles]# cp /etc/httpd/conf/httpd.conf /etc/ansible/roles/httpd/files/
编写tasks/main.yaml文件
[root@server1 roles]# vim httpd/tasks/main.yaml
[root@server1 roles]# cat httpd/tasks/main.yaml
- name: 安装httpd
yum: name=httpd state=latest
- name: 同步httpd.conf配置文件
copy: src=/etc/ansible/roles/httpd/files/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify: restart httpd
- name: 同步数据文件
copy: src=/etc/ansible/roles/httpd/files/httpd_doc/ dest=/var/www/html
- name: 启动httpd,设置为开机自启
service: name=httpd state=started enabled=on
编写handlers/main.yaml文件
[root@server1 roles]# vim httpd/handlers/main.yaml
[root@server1 roles]# cat httpd/handlers/main.yaml
- name: restart httpd
service: name=httpd state=restarted
编写tasks/main.yaml文件
[root@server1 roles]# cd mysql/
[root@server1 mysql]# vim tasks/main.yaml
[root@server1 mysql]# cat tasks/main.yaml
- name: 安装mariadb
yum: name=mariadb-server state=latest
- name: 启动mariadb服务,并设置为开机自启
service: name=mariadb state=started enabled=on
编写tasks/main.yaml文件
[root@server1 mysql]# cd ../php/
[root@server1 php]# vim tasks/main.yaml
[root@server1 php]# cat tasks/main.yaml
- name: 安装php
yum: name=php,php-gd,php-ldap,php-odbc,php-pear,php-xml,php-xmlrpc,php-mbstring,php-snmp,php-soap,curl,curl-devel,php-bcmath,php-mysql state=present
notify: restart httpd
[root@server1 php]# cd ../../
[root@server1 ansible]# cd playbook/
[root@server1 playbook]# vim lamp.yml
[root@server1 playbook]# cat lamp.yml
---
- hosts: mygroup
remote_user: root
roles:
- httpd
- mysql
- php
[root@server1 php]# ansible-playbook /etc/ansible/playbook/lamp.yml
PLAY [mygroup] **********************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************
ok: [192.168.139.30]
ok: [192.168.139.20]
TASK [安装httpd] **********************************************************************************************************
ok: [192.168.139.30]
ok: [192.168.139.20]
TASK [同步httpd.conf配置文件] *************************************************************************************************
ok: [192.168.139.20]
ok: [192.168.139.30]
TASK [httpd : 同步数据文件] ***************************************************************************************************
changed: [192.168.139.30]
changed: [192.168.139.20]
TASK [启动httpd,设置为开机自启] **************************************************************************************************
changed: [192.168.139.30]
changed: [192.168.139.20]
TASK [mysql : 安装mariadb] ************************************************************************************************
ok: [192.168.139.20]
ok: [192.168.139.30]
TASK [mysql : 启动mariadb服务,并设置为开机自启] *************************************************************************************
ok: [192.168.139.20]
ok: [192.168.139.30]
TASK [安装php] ************************************************************************************************************
changed: [192.168.139.20]
changed: [192.168.139.30]
RUNNING HANDLER [restart httpd] *****************************************************************************************
changed: [192.168.139.20]
changed: [192.168.139.30]
PLAY RECAP **************************************************************************************************************
192.168.139.20 : ok=9 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.139.30 : ok=9 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
在搭建完lamp的基础上,搭建discuz论坛
[root@server1 playbook]# cd /etc/ansible/roles/
[root@server1 roles]# mkdir -p {httpd,mysql,php}/{files,tasks,handlers,templates,vars,meta}
[root@server1 roles]# touch {httpd,mysql,php}/{tasks,handlers,vars,meta}/main.yaml
准备discuz软件包
[root@server1 ~]# yum install -y lrzsz
[root@server1 ~]# rz
[root@server1 ~]# mv discuz.zip /etc/ansible/roles/httpd/files/
[root@server1 files]# ls
discuz.zip httpd.conf httpd_doc
修改tasks/main.yaml
[root@server1 httpd]# vim tasks/main.yaml
[root@server1 httpd]# cat tasks/main.yaml
- name: 安装httpd
yum: name=httpd state=latest
- name: 同步httpd.conf配置文件
copy: src=/etc/ansible/roles/httpd/files/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify: restart httpd
- name: 拷贝discuz的压缩包
copy: src=/etc/ansible/roles/httpd/files/discuz.zip dest=/tmp
- name: 删除/var/www/html/discuz,再次同步会快捷
file: path=/var/www/html/discuz state=absent
- name: 解压至https数据目录,并修改数据目录的权限
shell: unzip /tmp/discuz.zip -d /var/www/html/ &> /dev/null && chown -R apache.apache /var/www/html/
- name: 启动httpd,设置为开机自启
service: name=httpd state=started enabled=on
编写脚本,用于建库,授权
[root@server1 mysql]# vim files/create.sh
[root@server1 mysql]# cat files/create.sh
#!/bin/bash
mysql << EOF
create database if not exists discuz default charset=utf8;
grant all on discuz.* to 'discuz'@'localhost' identified by '123456';
flush privileges;
EOF
修改tasks/main.yaml
[root@server1 mysql]# cat tasks/main.yaml
- name: 安装mariadb
yum: name=mariadb-server state=latest
- name: 启动mariadb服务,并设置为开机自启
service: name=mariadb state=started enabled=on
- name: 执行脚本,用于建库,授权
script: /etc/ansible/roles/mysql/files/create.sh
编写tasks/main.yaml文件
[root@server1 mysql]# cd ../php/
[root@server1 php]# vim tasks/main.yaml
[root@server1 php]# cat tasks/main.yaml
- name: 安装php
yum: name=php,php-gd,php-ldap,php-odbc,php-pear,php-xml,php-xmlrpc,php-mbstring,php-snmp,php-soap,curl,curl-devel,php-bcmath,php-mysql state=present
notify: restart httpd
[root@server1 php]# cd ../../
[root@server1 ansible]# cd playbook/
[root@server1 playbook]# vim lamp.yml
[root@server1 playbook]# cat lamp.yml
---
- hosts: mygroup
remote_user: root
roles:
- httpd
- mysql
- php
[root@server1 mysql]# ansible-playbook /etc/ansible/playbook/lamp.y