Ansible 批量部署平臺
Ansible 介紹以及基本命令
Ansible 簡介:
Ansible 和目前市面上一些其他的專案管理工具有很大的不同,它的設計初衷就是為了更方便、快捷的進行配置管理。它易於安裝和實用,語法也非常簡單易學。可以使用 Ansible 將平常複雜的配置工作變得簡單、更加標準化和更容易控制。
Ansible 只需要在一臺普通的伺服器上執行即可,不需要在被管控的伺服器上安裝客戶端,因為它是基於 SSH 的。Linux 伺服器離不開 SSH,所以 Ansible 不需要為配置工作新增額外的支援,可通過命令列來使用 Ansible,執行 Ansible 的伺服器俗稱 “管理節點”,通過 Ansible 進行管理的伺服器俗稱 “受控節點”。
Ansible 是一款極為靈活的開源工具套件,能夠大大簡化 Unix 管理員的自動化配置管理與流程控制方式。它利用推送方式對客戶系統加以配置,這樣所有的工作都可以在主伺服器完成。其命令列機制同樣非常強大,允許利用商業許可 Web UI 實現授權管理與配置。
Ansible 的優點:
① 輕量級,不需要去客戶端安裝 agent,更新時只需要在操作機上進行一次更新即可,採用 SSH 協議。
② 批量任務執行可以寫成指令碼,而且不用分發到遠端就可以執行。
③ 使用 Python 編寫的,維護更簡單。
④ 支援 sudo 普通使用者命令。
Ansible 安裝配置:
Ansible 能夠安裝到 Linux、BSD、Mac OS 等平臺,Python 最低版本要求為 2.6。
安裝 Ansible 之前要先安裝第三方 epel 源:
[[email protected] ~]# cat /etc/redhat-release # 檢視系統核心。
CentOS Linux release 7.3.1611 (Core)
[ [email protected] ~]# python -V # 檢視 Python 版本(Python 版本最低為 2.6)。
Python 2.7.5
[[email protected] ~]# yum install epel-release -y # 安裝 EPEL 源
通過 Yum 安裝 Ansible 軟體:
[[email protected] ~]# yum install ansible -y
[[email protected] ~]# cd /etc/ansible/ # 配置檔案預設的路徑。
[[email protected] ansible]# ll
-rw-r--r-- 1 root root 19549 8月 17 17:06 ansible.cfg
-rw-r--r-- 1 root root 1016 8月 17 17:06 hosts
drwxr-xr-x 2 root root 6 8月 17 17:06 roles
配置之前需要通過 SSH 讓多臺伺服器建立互信:(機器多的話可以用 expect 非互動式指令碼實現)
非互動式建立一對金鑰對:
[[email protected] ansible]# ssh-keygen -t dsa -P "" -f ~/.ssh/id_dsa
Generating public/private dsa key pair.
Created directory '/root/.ssh'.
Your identification has been saved in /root/.ssh/id_dsa.
Your public key has been saved in /root/.ssh/id_dsa.pub.
The key fingerprint is:
ee:18:eb:be:bc:1e:4c:98:aa:98:e0:63:0a:2b:24:a3 [email protected]
The key's randomart image is:
+--[ DSA 1024]----+
| |
| |
| |
| o |
| o . S |
|o. . o . |
|*.. + . |
|E* . * |
|X.. +Xo. |
+-----------------+
[[email protected] ansible]# cd ~
[[email protected] ~]# ls -l .ssh/
總用量 8
-rw------- 1 root root 668 8月 28 21:16 id_dsa
-rw-r--r-- 1 root root 602 8月 28 21:16 id_dsa.pub
分別給受控節點分發公鑰:
[[email protected] ~]# ssh-copy-id -i .ssh/id_dsa.pub [email protected]
[[email protected] ~]# ssh-copy-id -i .ssh/id_dsa.pub [email protected]
[[email protected] ~]# ssh-copy-id -i .ssh/id_dsa.pub [email protected]
測試互信是否成功:【成功】
[[email protected] ~]# ssh -p 22 [email protected] "cat /etc/redhat-release"
CentOS Linux release 7.3.1611 (Core)
[[email protected] ~]# ssh -p 22 [email protected] "cat /etc/redhat-release"
CentOS Linux release 7.3.1611 (Core)
開始配置並通過 Ansible 管理其他節點:
[[email protected] ~]# cd /etc/ansible/
[[email protected] ansible]# ll
總用量 24
-rw-r--r-- 1 root root 19549 8月 17 17:06 ansible.cfg
-rw-r--r-- 1 root root 1016 8月 17 17:06 hosts
drwxr-xr-x 2 root root 6 8月 17 17:06 roles
[[email protected] ansible]# cp hosts hosts.bak
[[email protected] ansible]# vim hosts
[[email protected] ansible]# cat hosts # 預設 hosts 內容可以分組甚至分檔案。
[local]
localhost # 本機。
[webservers]
192.168.193.132 # 受控節點一。
[dbservers]
192.168.193.133 # 受控節點二。
通過命令使用 Ansible:
[[email protected] ~]# ansible -i /etc/ansible/hosts all -a "date"
192.168.136.183 | SUCCESS | rc=0 >>
2018年 08月 28日 星期二 21:41:46 EDT
192.168.136.182 | SUCCESS | rc=0 >>
2018年 08月 28日 星期二 21:41:46 EDT
localhost | SUCCESS | rc=0 >>
2018年 08月 28日 星期二 21:41:47 EDT
[[email protected] ~]# ansible all -a "ping baidu.com -c 1"
192.168.136.183 | SUCCESS | rc=0 >>
192.168.136.182 | SUCCESS | rc=0 >>
localhost | SUCCESS | rc=0 >>
[[email protected] ~]# ansible all -m ping
192.168.136.182 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.136.183 | SUCCESS => {
"changed": false,
"ping": "pong"
}
localhost | SUCCESS => {
"changed": false,
"ping": "pong"
}
Ansible 主要引數:
Ansible 正則表示式的使用:
[[email protected] ~]# ansible 192.168.* -m command -a "df -h"
192.168.193.132 | SUCCESS | rc=0 >>
檔案系統 容量 已用 可用 已用% 掛載點
/dev/sda2 16G 1.7G 15G 11% /
devtmpfs 483M 0 483M 0% /dev
tmpfs 493M 0 493M 0% /dev/shm
tmpfs 493M 6.8M 486M 2% /run
tmpfs 493M 0 493M 0% /sys/fs/cgroup
tmpfs 99M 0 99M 0% /run/user/0
192.168.193.133 | SUCCESS | rc=0 >>
檔案系統 容量 已用 可用 已用% 掛載點
/dev/sda2 16G 1.6G 15G 10% /
devtmpfs 483M 0 483M 0% /dev
tmpfs 493M 0 493M 0% /dev/shm
tmpfs 493M 13M 480M 3% /run
tmpfs 493M 0 493M 0% /sys/fs/cgroup
tmpfs 99M 0 99M 0% /run/user/0
[[email protected] ~]# ansible 192.168.136.* -m shell -a "df -h" # 此處換成 shell 同上 command。
Ansible 遠端批量拷貝檔案或目錄:
[[email protected] ~]# ansible all -m copy -a 'src=/etc/hosts dest=/home/ mode=755 owner=root'
# 拷貝檔案到所有受控節點的 /home/ 目錄下。
192.168.193.132 | SUCCESS => {
"changed": true,
"checksum": "7335999eb54c15c67566186bdfc46f64e0d5a1aa",
"dest": "/home/hosts",
"gid": 0,
"group": "root",
"md5sum": "54fb6627dbaa37721048e4549db3224d",
"mode": "0755",
"owner": "root",
"size": 158,
"src": "/root/.ansible/tmp/ansible-tmp-1538574556.34-237168714952191/source",
"state": "file",
"uid": 0
}
localhost | SUCCESS => {
"changed": true,
"checksum": "7335999eb54c15c67566186bdfc46f64e0d5a1aa",
"dest": "/home/hosts",
"gid": 0,
"group": "root",
"md5sum": "54fb6627dbaa37721048e4549db3224d",
"mode": "0755",
"owner": "root",
"size": 158,
"src": "/root/.ansible/tmp/ansible-tmp-1538574556.32-40315963626608/source",
"state": "file",
"uid": 0
}
192.168.193.133 | SUCCESS => {
"changed": true,
"checksum": "7335999eb54c15c67566186bdfc46f64e0d5a1aa",
"dest": "/home/hosts",
"gid": 0,
"group": "root",
"md5sum": "54fb6627dbaa37721048e4549db3224d",
"mode": "0755",
"owner": "root",
"size": 158,
"src": "/root/.ansible/tmp/ansible-tmp-1538574556.29-213260987463029/source",
"state": "file",
"uid": 0
}
[[email protected] ~]# mkdir /root/hehe
[[email protected] ~]# cd /root/hehe/
[[email protected] hehe]# touch {1..5}
[[email protected] ~]# ansible all -m copy -a 'src=/root/hehe dest=/tmp/ mode=755 owner=root’
# 將 /root/hehe 目錄拷貝到所有受控節點的 /tmp 目錄下(目錄後面加 / 則會拷貝目錄下檔案)。
192.168.136.182 | SUCCESS => {
"changed": true,
"dest": "/tmp/",
"src": "/root/hehe"
}
192.168.136.183 | SUCCESS => {
"changed": true,
"dest": "/tmp/",
"src": "/root/hehe"
}
localhost | SUCCESS => {
"changed": true,
"dest": "/tmp/",
"src": "/root/hehe"
}
Ansible YUM 遠端批量安裝:
[[email protected] ~]# ansible 192.168.* -m yum -a "name=sysstat,screen,ntpdate state=installed"
# 通過 yum 為 IP 以 192.168.* 開頭的受控節點安裝命令,輸出省略若干。
192.168.136.182 | SUCCESS => {
192.168.136.183 | SUCCESS => {
Playbook 配置管理:
我們使用如上這些命令可以快速利用 Ansible 的工具編寫指令碼,從而以非常簡便的方式實現任務處理的自動化與流程化。除此之外我們還可以建立 Ansible Playbook 以收集命令與任務集,這樣能夠大大降低管理工作的複雜程度。
Playbook 採用 YAML 語法結構,因此它們一般比較易於閱讀並加以配置。
案例一:使用 Playbook 實現在客戶端安裝 screen 軟體:
[[email protected]_drew tmp]# rpm -qa|grep screen
screen-4.1.0-0.25.20120314git3c2946.el7.x86_64
[[email protected]_drew ~]# yum remove screen # 先把 182 上面的 screen 軟體解除安裝掉。
[[email protected]_drew tmp]# rpm -qa|grep screen # 此時該伺服器上面的 screen 沒有了。
[[email protected] ansible]# cd /etc/ansible/
# 在 /etc/ansible/ 目錄下,新建 screen.yaml 檔案,內容如下:
[[email protected] ansible]# vim screen.yaml
[[email protected] ansible]# cat screen.yaml # 提示:每個冒號後面都要有空格。
- hosts: 192.168.136.182 # 定義主機。
remote_user: root # 遠端使用者名稱。
tasks:
- name: +++++++++yum install screen+++++++++ # 顯示的任務名稱。
shell: yum install screen -y
# 指定需要在遠端客戶端執行的命令(可多個命令,中間用分號隔開)。
[[email protected] ansible]# ansible-playbook screen.yaml # 執行這個 Playbook 的命令。
# 以下內容表示執行完畢(忽略警告)。
PLAY [192.168.136.182] ***************************
TASK [Gathering Facts] ****************************
ok: [192.168.136.182]
TASK [+++++++++yum install screen+++++++++] **
[WARNING]: Consider using the yum module rather than running yum. If you need to use command
because yum 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: [192.168.136.182]
PLAY RECAP **************************
192.168.136.182 : ok=2 changed=1 unreachable=0 failed=0
[[email protected]_drew ~]# rpm -qa|grep screen # 到 IP 182 的客戶端即可看到安裝的 screen。
screen-4.1.0-0.25.20120314git3c2946.el7.x86_64
案例二:定義原始碼安裝 Nginx 軟體:
[[email protected] ansible]# cd /etc/ansible/
[[email protected] ansible]# vim nginx.yaml
[[email protected] ansible]# cat nginx.yaml
- hosts: 192.168.136.182
remote_user: root
tasks:
- name: +++++++++Install nginx web version 1.6.1++++++++++
shell: wget http://nginx.org/download/nginx-1.6.1.tar.gz ;tar zxf nginx-1.6.1.tar.gz ;cd nginx-1.6.1 ;./configure --prefix=/usr/local/nginx ;make ;make install
[[email protected] ansible]# ansible-playbook nginx.yaml # 執行該 Playbook。
Ansible 批量部署 tomcat 專案
1、專案需求
公司有4臺機器,需要將 jdk8 和 tomcat8 兩個包同時上傳到四臺機器的 /opt/ 目錄下,並進行安裝 。安裝成功後讓四臺機器通過郵件的方式通知運維人員,郵件格式為:IP+hostname+servername。
2、專案計劃
通過 Ansible 批量部署
3、部署方案
3.1、四臺機器的基本資訊
3.2、在 ansible 的主機清單中定義一個主機組,指定需要部署的機器的 IP
[[email protected] ~]# cat /etc/ansible/hosts
[websrvs]
192.168.24.129
192.168.24.130
192.168.24.131
192.168.24.132
3.3、目錄結構
[[email protected] ~]# tree /etc/ansible/
├── files
│ ├── apache-tomcat-8.0.27.tar.gz # tomcat 包
│ ├── jdk-8u60-linux-x64.tar.gz # jdk 包
│ ├── notice.txt # 腳本里的檔案
│ ├── tomcat_ini.sh # tomcat 服務的配置檔案
│ └── tomcat_mail.sh # 發郵件指令碼
├── hosts # 主機清單
├── tomcat.yml # 批量部署 tomcat 服務的 ansible-palybook 指令碼
3.4、檔案詳細內容
[[email protected] ~]# cd /etc/ansible/files/
[[email protected] ansible]# ll
總用量 185912
-rw-r--r-- 1 root root 9128610 11月 6 07:47 apache-tomcat-8.0.27.tar.gz
-rw-r--r-- 1 root root 181238643 7月 23 03:49 jdk-8u60-linux-x64.tar.gz
-rw-r--r-- 1 root root 1465 11月 10 08:02 tomcat_ini.sh
[[email protected] files]# cat tomcat_ini.sh # 指令碼詳細內容
#!/bin/sh
# chkconfig: 345 99 10
# description: Auto-starts tomcat
# /etc/init.d/tomcatd
# Tomcat auto-start
# Source function library.
#. /etc/init.d/functions
# source networking configuration.
#. /etc/sysconfig/network
RETVAL=0
export JAVA_HOME=/application/jdk
export JAVA_HOME
export CATALINA_HOME=/application/tomcat
export CATALINA_BASE=/application/tomcat
start()
{
if [ -f $CATALINA_HOME/bin/startup.sh ];
then
echo $"Starting tomcat"
$CATALINA_HOME/bin/startup.sh
RETVAL=$?
echo " OK"
return $RETVAL
fi
}
stop()
{
if [ -f $CATALINA_HOME/bin/shutdown.sh ];
then
echo $"Stopping tomcat"
$CATALINA_HOME/bin/shutdown.sh
RETVAL=$?
sleep 1
ps -fwwu root | grep tomcat|grep -v grep | grep -v PID | awk '{print $2}'|xargs kill -9
echo " OK"
# [ $RETVAL -eq 0 ] && rm -f /var/lock/...
return $RETVAL
fi
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
echo $"Restaring tomcat"
$0 stop
sleep 1
$0 start
;;
*)
echo $"Usage: $0 {start|stop|restart}"
exit 1
;;
esac
exit $RETVAL
[[email protected] ansible]# cat files/tomcat_mail.sh # 郵件指令碼詳細內容
#!/bin/bash
File=/etc/ansible/files/notice.txt
if [ ! -f $File ]
then
touch $File
fi
> $File
for n in `seq 129 131`
do
number=`ansible -m shell 192.168.24.$n -a 'netstat -lntup|grep 8080|wc -l'|sed -n '2p'`
if [ $number -eq 1 ]
then
ansible 192.168.24.$n -a 'hostname -I' >> $File
ansible 192.168.24.$n -a 'hostname' >> $File
echo "tomcat success" >> $File
else
ansible 192.168.24.$n -a 'hostname -I' >> $File
ansible 192.168.24.$n -a 'hostname' >> $File
echo "tomcat failed" >> $File
fi
done
grep -v "192.168.24.* | SUCCESS | rc=0 >>" $File|mail -s "tomcat state" [email protected]
[[email protected] ansible]# cat tomcat.yml # 批量部署 tomcat 服務 ansible-playbook 指令碼詳細內容
---
- hosts: websrvs
remote_user: root
tasks:
############Install JDK################
- name: copy jdk-8u60-linux-x64.tar.gz
copy: src=files/jdk-8u60-linux-x64.tar.gz dest=/opt/jdk-8u60-linux-x64.tar.gz
- name: tar jdk
command: /bin/tar xf /opt/jdk-8u60-linux-x64.tar.gz -C /application
- name: rename jdk
shell: mv /application/jdk1.8.0_60 /application/jdk
- name: add /etc/profile
shell: sed -i.ori '$a export JAVA_HOME=/application/jdk\nexport PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH\nexport CLASSPATH=.$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar' /etc/profile
- name: add /etc/profile
shell: echo 'export TOMCAT_HOME=/application/tomcat'>>/etc/profile
- name: source profile
shell: source /etc/profile
############Install Tomcat################
- name: copy apache-tomcat-8.0.27.tar.gz
copy: src=files/apache-tomcat-8.0.27.tar.gz dest=/opt/apache-tomcat-8.0.27.tar.gz
- name: tar tomcat
command: /bin/tar xf /opt/apache-tomcat-8.0.27.tar.gz -C /application
- name: softlink tomcat
file: src=/application/apache-tomcat-8.0.27/ dest=/application/tomcat state=link
- name: create group
group: name=tomcat
- name: create user
user: name=tomcat group=tomcat system=yes shell=/sbin/nologin
- name: push conf file
template: src=/application/tomcat/conf/tomcat-users.xml dest=/application/tomcat/conf/
notify: restart tomcat
- name: copy startup.sh
copy: src=files/tomcat_ini.sh dest=/etc/init.d/tomcat mode=0755
- name: start tomcat
shell: /etc/init.d/tomcat start
handlers:
- name: restart tomcat
shell: /etc/init.d/tomcat restart
3.5、執行過程
[[email protected] ansible]# ansible-playbook tomcat.yml
PLAY [websrvs] ********************************************************************
TASK [Gathering Facts] ************************************************************
ok: [192.168.24.131]
ok: [192.168.24.130]
ok: [192.168.24.129]
TASK [copy jdk-8u60-linux-x64.tar.gz] *********************************************
changed: [192.168.24.129]
changed: [192.168.24.130]
changed: [192.168.24.131]
TASK [tar jdk] ********************************************************************
[WARNING]: Consider using the unarchive module rather than running tar. If you
need to use command because unarchive 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: [192.168.24.130]
changed: [192.168.24.129]
changed: [192.168.24.131]
TASK [rename jdk] *****************************************************************
changed: [192.168.24.129]
changed: [192.168.24.130]
changed: [192.168.24.131]
TASK [add /etc/profile] ***********************************************************
[WARNING]: Consider using the replace, lineinfile or template module rather than
running sed. If you need to use command because replace, lineinfile or template
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: [192.168.24.129]
changed: [192.168.24.131]
changed: [192.168.24.130]
TASK [add /etc/profile] ***********************************************************
changed: [192.168.24.129]
changed: [192.168.24.130]
changed: [192.168.24.131]
TASK [source profile] *************************************************************
changed: [192.168.24.130]
changed: [192.168.24.131]
changed: [192.168.24.129]
TASK [copy apache-tomcat-8.0.27.tar.gz] *******************************************
changed: [192.168.24.129]
changed: [192.168.24.131]
changed: [192.168.24.130]
TASK [tar tomcat] *****************************************************************
changed: [192.168.24.129]
changed: [192.168.24.130]
changed: [192.168.24.131]
TASK [softlink tomcat] ************************************************************
changed: [192.168.24.130]
changed: [192.168.24.131]
changed: [192.168.24.129]
TASK [create group] ***************************************************************
ok: [192.168.24.129]
ok: [192.168.24.131]
ok: [192.168.24.130]
TASK [create user] ****************************************************************
ok: [192.168.24.130]
ok: [192.168.24.129]
ok: [192.168.24.131]
TASK [push conf file] *************************************************************
ok: [192.168.24.129]
ok: [192.168.24.131]
ok: [192.168.24.130]
TASK [copy startup.sh] ************************************************************
changed: [192.168.24.129]
changed: [192.168.24.131]
changed: [192.168.24.130]
TASK [start tomcat] ***************************************************************
changed: [192.168.24.129]
changed: [192.168.24.130]
changed: [192.168.24.131]
PLAY RECAP ************************************************************************
192.168.24.129 : ok=15 changed=11 unreachable=0 failed=0
192.168.24.130 : ok=15 changed=11 unreachable=0 failed=0
192.168.24.131 : ok=15 changed=11 unreachable=0 failed=0
[[email protected] ansible]# sh files/tomcat_mail.sh # 執行發郵件的指令碼
3.6、檢視結果
[[email protected] ansible]# ansible all -m shell -a 'netstat -lntup|grep java'
192.168.24.131 | SUCCESS | rc=0 >>
tcp6 0 0 :::8080 :::* LISTEN 4092/java
tcp6 0 0 127.0.0.1:8005 :::* LISTEN 4092/java
tcp6 0 0 :::8009 :::* LISTEN 4092/java
192.168.24.129 | SUCCESS | rc=0 >>
tcp6 0 0 :::8080 :::* LISTEN 38742/java
tcp6 0 0 127.0.0.1:8005 :::* LISTEN 38742/java
tcp6 0 0 :::8009 :::* LISTEN 38742/java
192.168.24.130 | SUCCESS | rc=0 >>
tcp6 0 0 :::8080 :::* LISTEN 31653/java
tcp6 0 0 127.0.0.1:8005 :::* LISTEN 31653/java
tcp6 0 0 :::8009 :::* LISTEN 31653/java