1. 程式人生 > >Linux進階:自動化運維之ANSIBLE(一)

Linux進階:自動化運維之ANSIBLE(一)

運維自動化發展歷程

1、本地部署(On-Premiss) 部署硬體+軟體+作業系統+環境+服務
2、基礎設施即服務(Iaas) 相當於只准備硬體
3、平臺即服務(Paas) 相當於只准備服務
4、軟體即服務(SaaS) 直接使用

企業實際應用場景分析

1、Dev開發環境

使用者:程式設計師
功能:程式設計師開發軟體,測試BUG的環境
管理者:程式設計師

測試環境
使用者:QA測試工程師
功能:測試經過Dev環境測試通過的軟體的功能
管理者:運維
說明:測試環境往往有多套,測試環境滿足測試功能即可,不宜過多
1、測試人員希望測試環境有多套,公司的產品多產品線併發,即多個版本,意味著多個版本同步測試
2、通常測試環境有多少套和產品線數量保持一樣

2、釋出環境:程式碼釋出機,有些公司為堡壘機(安全屏障)

使用者:運維
功能:釋出程式碼至生產環境
管理者:運維(有經驗)
釋出機:往往需要有2臺(主備)

3、生產環境

使用者:運維,少數情況開放許可權給核心開發人員,極少數公司將許可權完全開放給開發人員並其維護
功能:對使用者提供公司產品的服務
管理者:只能是運維
生產環境伺服器數量:一般比較多,且應用非常重要。往往需要自動工具協助部署配置應用

4、灰度環境(生產環境的一部分)

使用者:運維
功能:在全量釋出程式碼前將程式碼的功能面向少量精準使用者釋出的環境,可基於主機或使用者執行灰度釋出
案例:共100臺生產伺服器,先發布其中的10臺伺服器,這10臺伺服器就是灰度伺服器
管理者:運維
灰度環境:往往該版本功能變更較大,為保險起見特意先讓一部分使用者優化體驗該功能,待這部分使用者使用沒有重大問題的時候,再全量釋出至所有伺服器

程式釋出

1、程式釋出要求:

不能導致系統故障或造成系統完全不可用
不能影響使用者體驗

2、預釋出驗證:

新版本的程式碼先發布到伺服器(跟線上環境配置完全相同,只是未接入到排程器)

3、灰度釋出:

基於主機,使用者,業務

4、釋出路徑:放在同一個目錄,通常用軟連線直接指向新版本

/webapp/tuangou
/webapp/tuangou-1.1
/webapp/tuangou-1.2

5、釋出過程:

在排程器上下線一批主機(標記為maintanance狀態) -->
關閉服務 --> 
部署新版本的應用程式 -->
啟動服務 -->
在排程器上啟用這一批伺服器

自動化灰度釋出:指令碼、釋出平臺

自動化運維應用場景

檔案傳輸
應用部署
配置管理
任務流編排

常用的自動化運維工具

Ansible:python,Agentless,中小型應用環境
分為控制端,客戶端。藉助於ssh協議,可基於key,無代理,管理中小型

Saltstack:python,一般需部署agent,執行效率更高
被管理端需安裝軟體,需代理程式

ansible

創始人,Michael DeHaan( Cobbler 與 Func 的作者)
2012-03-09,釋出0.0.1版,紅帽收購
2015-10-17,Red Hat宣佈收購 1.5億美金

特性

模組化:呼叫特定的模組,完成特定任務
有Paramiko,PyYAML,Jinja2(模板語言)三個關鍵模組
支援自定義模組
基於Python語言實現
部署簡單,基於python和SSH(預設已安裝),agentless
安全,基於OpenSSH
支援playbook編排任務
冪等性:一個任務執行1遍和執行n遍效果一樣,不因重複執行帶來意外情況
無需代理不依賴PKI(無需ssl)
可使用任何程式語言寫模組
YAML格式,編排任務,支援豐富的資料結構
較強大的多層解決方案

利用ansible實現管理的方式:
Ad-Hoc :ansible命令,主要用於臨時命令使用場景
Ansible-playbook : 主要用於長期規劃好的,大型專案的場景,需要有前提的規劃

注意事項

執行ansible的主機一般稱為主控端,中控,master或堡壘機
主控端Python版本需要2.6或以上
被控端Python版本小於2.4需要安裝python-simplejson
被控端如開啟SELinux需要安裝libselinux-python
windows不能做為主控端

配置檔案

1./etc/ansible/ansible.cfg 主配置檔案,  
如下可變動,其他不用變動
#log_path = /var/log/ansible.log  生成日誌檔案
#host_key_checking = False        忽略登入yes no

Ansible 配置檔案/etc/ansible/ansible.cfg (一般保持預設)
[defaults]
#inventory = /etc/ansible/hosts # 主機列表配置檔案
#library = /usr/share/my_modules/ # 庫檔案存放目錄
#remote_tmp = $HOME/.ansible/tmp #臨時py命令檔案存放在遠端主機目錄
#local_tmp = $HOME/.ansible/tmp # 本機的臨時命令執行目錄
#forks = 5 # 預設併發數
#sudo_user = root # 預設sudo 使用者
#ask_sudo_pass = True #每次執行ansible命令是否詢問ssh密碼
#ask_pass = True
#remote_port = 22
#host_key_checking = False # 檢查對應伺服器的host_key,建議取消註釋
#log_path=/var/log/ansible.log #日誌檔案

2./etc/ansible/hosts 主機清單
3./etc/ansible/roles/ 存放角色的目錄

程式
/usr/bin/ansible 主程式,臨時命令執行工具
/usr/bin/ansible-doc 檢視配置文件,模組功能檢視工具
/usr/bin/ansible-galaxy 下載/上傳優秀程式碼或Roles模組的官網平臺
/usr/bin/ansible-playbook 定製自動化任務,編排劇本工具/usr/bin/ansible-pull 遠端執行命令的工具
/usr/bin/ansible-vault 檔案加密工具
/usr/bin/ansible-console 基於Console介面與使用者互動的執行工具

ansible-doc: 顯示模組幫助

ansible-doc 
-a 顯示所有模組的文件
-l, --list 列出可用模組
-s, --snippet顯示指定模組的playbook片段
示例:
ansible-doc –l 列出所有模組
ansible-doc ping 檢視指定模組幫助用法
ansible-doc –s ping 檢視指定模組幫助用法

ansible命令執行過程

1. 載入自己的配置檔案 預設/etc/ansible/ansible.cfg
2. 載入自己對應的模組檔案,如command
3. 通過ansible將模組或命令生成對應的臨時py檔案,並將該 檔案傳輸至遠端伺服器的對應執行使用者$HOME/.ansible/tmp/ansible-tmp-數字/XXX.PY檔案
4. 給檔案+x執行
5. 執行並返回結果
6. 刪除臨時py檔案,sleep 0退出

執行狀態:
綠色:執行成功並且不需要做改變的操作
黃色:執行成功並且對目標主機做變更
紅色:執行失敗

如何使用ansible

1、安裝ansible---基於epel源

[[email protected] yum.repos.d]#yum install ansible

2、配置主機清單 (非預設ssh協議,後面跟埠號)

[[email protected] ~]#vim /etc/ansible/hosts
# Ex 2: A collection of hosts belonging to the 'webservers' group

## [webservers]
## alpha.example.org
## beta.example.org
## 192.168.1.100
## 192.168.1.110

# If you have multiple hosts following a pattern you can specify
# them like this:

## www[001:006].example.com

# Ex 3: A collection of database servers in the 'dbservers' group

## [dbservers]
## 
## db01.intranet.mydomain.net
## db02.intranet.mydomain.net
## 10.25.1.56
## 10.25.1.57

# Here's another example of host ranges, this time there are no
# leading 0s:

## db-[99:101]-node.example.com               
[websrv]                                
192.168.32.17
192.168.32.6
[appsrv]
192.168.32.[1:2]7

3、基本用法
ansible [-m module_name] [-a args]
跟主機ip或分組名(支援萬用字元)+模組名+模組引數 +-a+需要執行的命令

--version 顯示版本
-m module 指定模組,預設為command
-v 詳細過程 –vv -vvv更詳細
--list-hosts 顯示主機列表,可簡寫 --list
-k, --ask-pass 提示輸入ssh連線密碼,預設Key驗證
-K, --ask-become-pass 提示輸入sudo時的口令
-C, --check 檢查,並不執行
-T, --timeout=TIMEOUT 執行命令的超時時間,預設10s
-u, --user=REMOTE_USER 執行遠端執行的使用者
-b, --become 代替舊版的sudo 切換


直接輸入ip地址     基於密碼驗證
[[email protected] ~]#ansible 192.168.32.6 -m ping -k
SSH password: 
192.168.32.6 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
直接輸入組名       基於密碼驗證
[[email protected] ~]#ansible websrv -m ping -k            
SSH password: 
192.168.32.6 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
192.168.32.17 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
萬用字元
ansible "*" -m ping
ansible 192.168.1.* -m ping
ansible "*srv" -m ping

邏輯或
ansible "websrvs:appsrvs" -m ping
ansible "192.168.1.10:192.168.1.20" -m ping

邏輯與
ansible "websrv:&dbsrv" –m ping
在websrvs組並且在dbsrvs組中的主機

邏輯非
ansible 'websrv:!dbsrv' –m ping
在websrvs組,但不在dbsrvs組中的主機
注意:此處為單引號

綜合邏輯
ansible 'websrv:dbsrv:&appsrv:!ftpsrv' –m ping

正則表示式
ansible "websrv.dadda.com:&dbsrv.dadda.com" –m ping
轉換:~ 代表後面要跟的正則表示式
ansible "~(web|db).*\.dadda\.com" –m ping

注:多臺機器管理基於key驗證
如何基於key驗證:

[[email protected] ~]#ssh-keygen
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: 
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:nIQnThJNBzY0pm14bxLNDjaKvnY2CU9NYYkdFjocVgI [email protected]
The key's randomart image is:
+---[RSA 2048]----+
|  E.=B&=.        |
|   o.%*B         |
|    B.%.=        |
|   . [email protected] .       |
|  . .oo S        |
| .. . .o         |
|  .+ .           |
|  ..*            |
| ..o .           |
+----[SHA256]-----+
[[email protected] ~]#cd .ssh
[[email protected] .ssh]#ls
id_rsa  id_rsa.pub  known_hosts
[[email protected] .ssh]#ssh-copy-id 192.168.32.6    多臺可利用指令碼
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/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
[email protected]'s password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh '192.168.32.6'"
and check to make sure that only the key(s) you wanted were added.
[[email protected] .ssh]#ssh 192.168.32.6
Last login: Sat Sep 22 22:17:40 2018 from 192.168.32.27
[[email protected] .ssh]#ansible all -m ping
192.168.32.17 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
192.168.32.6 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
192.168.32.27 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

使用舉例

1、以本機shine使用者執行ping存活檢測
注意:不是基於key的驗證了需輸入shine的密碼,需帶選項-k

[[email protected] ~]#ansible all -m ping -u shine -k
SSH password:
192.168.32.17 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.32.27 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.32.6 | UNREACHABLE! => {
"changed": false,
"msg": "Authentication failure.",
"unreachable": true
}

2、以shine sudo至root執行ping存活檢測
注意:sudo需帶選項-b -K ,sudo免口令可不加-K

[[email protected] ~]#ansible 192.168.32.17 -m ping -u shine -b -K -k
SUDO password:
192.168.32.17 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).\r\n",
"unreachable": true
}
失敗是因為未做sudo授權

授權:切換到(最簡單的是加到配置檔案組內)
```bash
[[email protected] ~]#vim /etc/sudoers
...
## Allows people in group wheel to run all commands
#%wheel ALL=(ALL)       ALL              需輸口令
## Same thing without a password
 %wheel ALL=(ALL)       NOPASSWD: ALL    此行免輸口令
...

[[email protected] ~]#getent passwd shine
shine:x:1000:1000:Shine:/home/shine:/bin/bash    
[[email protected] ~]#id shine
uid=1000(shine) gid=1000(shine) groups=1000(shine)

[[email protected] ~]#usermod -aG wheel shine
[[email protected] ~]#ansible 192.168.32.17 -m ping -u shine -b -K -k   
SSH password: 
SUDO password[defaults to SSH password]: 
192.168.32.17 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

[[email protected] ~]#ansible 192.168.32.17 -m ping -u shine -b  -k  
SSH password: 
192.168.32.17 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

3、以shine sudo至root使用者執行ls
sudo授權過可以

[[email protected] ~]#ansible 192.168.32.17 -m command -u shine --become-user=root -a 'ls /root' -b -k -K   
SSH password: 
SUDO password[defaults to SSH password]: 
192.168.32.17 | SUCCESS | rc=0 >>
anaconda-ks.cfg
Desktop
Documents
Downloads
initial-setup-ks.cfg
Music
Pictures
Public
Templates
Videos

沒有sudo授權不可以

[[email protected] ~]#usermod -G '' shine
[[email protected] ~]#id shine
uid=1000(shine) gid=1000(shine) groups=1000(shine)

[[email protected] ~]#ansible 192.168.32.17 -m command -u shine --become-user=root -a 'ls /root' -b -k -K
SSH password: 
SUDO password[defaults to SSH password]: 
192.168.32.17 | FAILED! => {
    "changed": false, 
    "module_stderr": "Shared connection to 192.168.32.17 closed.\r\n", 
    "module_stdout": "\r\nshine is not in the sudoers file.  This incident will be reported.\r\n", 
    "msg": "MODULE FAILURE", 
    "rc": 1
}

最好還是用root身份基於key最方便

[[email protected] ~]#ansible 192.168.32.17 -m command -a 'ls /root'
192.168.32.17 | SUCCESS | rc=0 >>
anaconda-ks.cfg
Desktop
Documents
Downloads
initial-setup-ks.cfg
Music
Pictures
Public
Templates
Videos

常用模組

1、Command:在遠端主機執行命令,預設模組,可忽略-m選項

[[email protected] ~]#ansible all -a 'useradd test' 同時建立
192.168.32.17 | SUCCESS | rc=0 >>


192.168.32.27 | SUCCESS | rc=0 >>


192.168.32.6 | SUCCESS | rc=0 >>

[[email protected] ~]#ansible all -a 'getent passwd test' 同時檢視
192.168.32.6 | SUCCESS | rc=0 >>
test:x:502:502::/home/test:/bin/bash

192.168.32.17 | SUCCESS | rc=0 >>
test:x:1001:1001::/home/test:/bin/bash

192.168.32.27 | SUCCESS | rc=0 >>
test:x:1001:1001::/home/test:/bin/bash

[[email protected] ~]#ansible all -a 'userdel -r test' 同時刪除賬戶及家目錄
192.168.32.17 | SUCCESS | rc=0 >>


192.168.32.27 | SUCCESS | rc=0 >>


192.168.32.6 | SUCCESS | rc=0 >>

此命令不支援 $VARNAME < > | ; & 等,用shell模組實現

2、Shell:和command相似,用shell執行命令

用command模組修改密碼:只是輸出內容
[[email protected] ~]#ansible all -a 'echo dadda |passwd --stdin shine'         
192.168.32.6 | SUCCESS | rc=0 >>
dadda |passwd --stdin shine

192.168.32.17 | SUCCESS | rc=0 >>
dadda |passwd --stdin shine

192.168.32.27 | SUCCESS | rc=0 >>
dadda |passwd --stdin shine

用shell模組修改密碼:成功
[[email protected] ~]#ansible all -m shell -a 'echo dadda |passwd --stdin shine'  
192.168.32.17 | SUCCESS | rc=0 >>
Changing password for user shine.
passwd: all authentication tokens updated successfully.

192.168.32.27 | SUCCESS | rc=0 >>
Changing password for user shine.
passwd: all authentication tokens updated successfully.

192.168.32.6 | SUCCESS | rc=0 >>
Changing password for user shine.
passwd: all authentication tokens updated successfully.

更改預設command更換成shell

[[email protected] ~]#vim /etc/ansible/ansible.cfg 
...
# default module name for /usr/bin/ansible
module_name = shell

[[email protected] ~]#ansible all -a 'echo dadda |passwd --stdin shine'         
192.168.32.17 | SUCCESS | rc=0 >>
Changing password for user shine.
passwd: all authentication tokens updated successfully.

192.168.32.27 | SUCCESS | rc=0 >>
Changing password for user shine.
passwd: all authentication tokens updated successfully.

192.168.32.6 | SUCCESS | rc=0 >>
Changing password for user shine.
passwd: all authentication tokens updated successfully.

呼叫bash執行命令 類似 cat /tmp/stanley.md | awk -F‘|’ ‘{print $1,$2}’ &> /tmp/example.txt 這些複雜命令,即使使用shell也可能會失敗,解決辦法:寫到指令碼時,copy到遠端,執行,再把需要的結果拉回執行命令的機器

3、Script:執行指令碼
注意執行的是本機所在的指令碼

[[email protected] ~]#cat >test.sh
echo ansible
[[email protected] ~]#cat test.sh 
echo ansible
[[email protected] ~]#chmod +x test.sh 
[[email protected] ~]#ansible 192.168.32.17 -m script -a '/root/test.sh' 
192.168.32.17 | SUCCESS => {
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to 192.168.32.17 closed.\r\n", 
    "stderr_lines": [
        "Shared connection to 192.168.32.17 closed."
    ], 
    "stdout": "ansible\r\n", 
    "stdout_lines": [
        "ansible"
    ]

常用引數
creates 如檔案存在,則不執行指令碼

[[email protected] ~]#ansible all -m script -a 'creates=/etc/fstab /root/test.sh' 
192.168.32.27 | SKIPPED
192.168.32.17 | SKIPPED
192.168.32.6 | SKIPPED

removes 如檔案存在,則執行指令碼

[[email protected] ~]#ansible 192.168.32.17 -m script -a 'removes=/etc/fstab /root/test.sh' 
192.168.32.17 | SUCCESS => {
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to 192.168.32.17 closed.\r\n", 
    "stderr_lines": [
        "Shared connection to 192.168.32.17 closed."
    ], 
    "stdout": "ansible\r\n", 
    "stdout_lines": [
        "ansible"
    ]
}