20200811記錄:ansible sudo提權,劇本,變數資訊
---------
1 案例1:配置sudo許可權
1.1 問題
本案例要求使用sudo提升普通使用者的許可權,要求如下:
- 給所有被管理主機建立系統賬戶
- 賬戶名稱為alice,密碼為123456
- 修改sudo配置,讓alice可以執行任何管理命令
1.2 方案
sudo(superuser or another do)讓普通使用者可以以超級管理員或其他人的身份執行命令。
sudo基本流程如下:
- 管理員需要先授權(修改/etc/sudoers檔案)
- 普通使用者以sudo的形式執行命令
修改/etc/sudoers的方法如下:
- visudo(帶語法檢查,預設沒有顏色提示)
- vim /etc/sudoers(不帶語法檢查,預設有顏色提示)
授權格式如下:
使用者或組 主機列表=(提權身份) [NOPASSWD]:命令列表
注意事項:命令需要寫絕對路徑,對組授權需要在組名稱前面加%。
[root@control ~]# cat /etc/sudoers #不要改,下面僅僅是語法格式的示例(例子) … … root ALL=(ALL) ALL tom ALL=(root) /usr/bin/systemctl %wheel ALL=(ALL) ALL
1.3 步驟
實現此案例需要按照如下步驟進行。
步驟一:配置sudo提權
1)遠端所有被管理主機批量建立系統賬戶,賬戶名稱為alice,密碼為123456。
[root@control ansible]# ansible all -m user -a "name=alice \ password={{'123456' | password_hash('sha512')}}"
2)配置alice賬戶可以提權執行所有命令(control批量授權,node1主機驗證)。
使用lineinfile模組修改遠端被管理端主機的/etc/sudoers檔案,line=後面的內容是需要新增到檔案最後的具體內容。
等於是在/etc/sudoers檔案末尾新增一行:alice ALL=(ALL) NOPASSWD:ALL
[root@control ansible]# ansible all -m lineinfile \ -a "path=/etc/sudoers line='alice ALL=(ALL) NOPASSWD:ALL'" [root@control ~]# ssh alice@node1
如何驗證?可以在node1電腦上面使用alice使用者執行sudo重啟服務的命令看看是否成功。
[alice@node1 ~]$ sudo systemctl restart sshd #不需要輸入密碼
2 案例2:修改Ansible配置
2.1 問題
沿用練習一,修改ansible配置實現使用普通使用者遠端被控制端主機,具體要求如下:
- 修改主配置檔案
- 設定ansible遠端被管理端主機賬戶為alice
- 設定ansible遠端管理提權的方式為sudo
- 修改主機清單檔案
- 修改主機清單配置檔案,新增SSH引數
2.2 步驟
實現此案例需要按照如下步驟進行。
步驟一:配置普通使用者遠端管理其他主機
1)修改主配置檔案,配置檔案檔案的內容可以參考/etc/ansible/ansible.cfg。
[root@control ~]# vim ~/ansible/ansible.cfg [defaults] inventory = ~/ansible/inventory remote_user = alice #以什麼使用者遠端被管理主機(被管理端主機的使用者名稱) [privilege_escalation] become = true #alice沒有特權,是否需要切換使用者提升許可權 become_method = sudo #如何切換使用者(比如用su就可以切換使用者,這裡是sudo) become_user = root #切換成什麼使用者(把alice提權為root賬戶) become_ask_pass = no #執行sudo命令提權時是否需要輸入密碼
思考:
如果A主機ssh遠端訪問B主機,應該輸入哪個主機的使用者名稱和對應的密碼?
如果張三要去李四家,應該使用誰家的鑰匙,開啟誰家的門?
2)遠端被管理端主機的alice使用者,需要提前配置SSH金鑰。
[root@control ~]# for i in node1 node2 node3 node4 node5 do ssh-copy-id alice@$i done
驗證效果:
[root@control ~]# ssh alice@node1 #依次遠端所有主機看看是否需要密碼 #注意:是遠端登入node1,應該輸入的是node1電腦上面alice賬戶的密碼,control沒有alice使用者 [root@control ~]# ansible all -m command -a "who" #測試效果 [root@control ~]# ansible all -m command -a "touch /test" #測試效果
常見報錯(有問題可以參考,沒問題可以忽略):
node1 | UNREACHABLE! => { "changed": false, "msg": "Failed to connect to the host via ssh: alice@node1: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).", "unreachable": true } 問題分析: 英語詞彙:Failed(失敗),connect(連線),to(到),host(主機),via(通過) permission(許可權),denied(被拒絕) Failed to connect to host via ssh alice@node1(通過ssh使用alice遠端連線到主機失敗) Permission denied(因為無法連線,所以報錯說許可權被拒絕) 解決辦法:手動ssh alice@主機名(如node1),看看是否可以實現免密碼登入。 Ansible的原理是基於ssh遠端管理,如果無法實現alice免密碼登入,則實驗會失敗! 如何實現免密碼登入,可以參考案例上面的命令,或者第一階段相關知識。
3)修改inventory主機清單配置檔案(參考即可,不需要操作)。
如果個別主機的賬戶不同,該如何處理呢?
如果有些主機需要使用密碼遠端呢?如果有些主機的SSH埠不是22呢?
[root@control ~]# cat ~/ansible/inventory [test] node1 ansible_ssh_port=220 #自定義遠端SSH埠 [proxy] node2 ansible_ssh_user=alice #自定義遠端連線的賬戶名 [webserver] node[3:4] ansible_ssh_pass=密碼 #自定義遠端連線的密碼 [database] node5 [cluster:children] webserver database
3 案例3:Playbook應用案例
3.1 問題
沿用練習二,編寫Ansible Playbook劇本,使用Playbook完成自動化操作,具體要求如下:
- 熟悉Playbook語法格式
- 編寫Playbook管理系統賬戶
- 編寫Playbook管理邏輯卷
- 編寫Playbook管理軟體包
3.2 方案
Ansible ad-hoc可以通過命令列形式遠端管理其他主機,適合執行一些臨時性簡單任務。另外還有一種遠端管理的方式叫Playbook,Ansible Playbook中文名稱叫劇本,它將經常需要執行的任務寫入一個檔案,這個檔案就叫劇本。
- 劇本中可以包含多個任務
- 劇本寫後,我們隨時根據劇本,執行相關的任務命令
- Playbook劇本要求按照YAML格式編寫
- 適合執行週期性經常執行的複雜任務
YAML是什麼?
- YAML是一個可讀性高、用來表達資料序列的格式語言
- YAML:YAML Ain't a Markup Language
- YAML以資料為中心,重點描述資料的關係和結構
YAML的格式要求如下:
- "#"代表註釋,一般第一行為三個橫槓(---)
- 鍵值(key/value)對使用":"表示,陣列使用"-"表示
- key和value之間使用":"分隔
- ":"後面必須有空格
- 一般縮排由兩個或以上空格組成
- 相同層級的縮排必須對齊,縮排代表層級關係
- 全文不可以使用tab鍵
- 區分大小寫
- 副檔名為yml或者yaml
- 跨行資料需要使用>或者|,其中|會保留換行符
YAML示例展示:
1)demo1
--- "詩仙": "李白" 或者 "詩仙": "李白"
2)demo2
#陣列的例子 --- - "李白" - "杜甫" - "白居易" - "唐僧"
3)demo3
#使用一行表示陣列的例子 --- "詩人": ["李白","杜甫","白居易"]
4)demo4
#鍵值對和陣列符合例子: --- "詩人": - "李白" - "杜甫" - "白居易"
5)demo5
1 #複雜案例 2 --- 3 - "詩人": 4 - 唐代: 5 - "李白" 6 - "杜甫" 7 - 宋代: 8 - "蘇軾" 9 - "李清照"
6)demo6
1 #喜歡的電影 2 --- 3 - 芳華 4 - 戰狼 5 - 霸王別姬
7)demo7
1 #人物描述 2 --- 3 - 姓名: 李白 4 年齡: 61 5 作品: 蜀道難 6 好友: 汪倫
8)demo8
#跨行文字(計算機理解為一行) --- 自我介紹: > 字太白,號青蓮居士, 唐代詩人,祖籍隴西郡, 今甘肅省平涼市
9)demo9
#跨行文字(計算機理解為多行) --- 自我介紹: | 字太白,號青蓮居士, 唐代詩人,祖籍隴西郡, 今甘肅省平涼市
10)demo10
注意-和:後面必須有空格。
1 #一張發票 2 --- 3 發票編號: 34843 4 日期: 2028-12-12 5 商品: 6 - 商品編號: BL394D 7 描述: 足球 8 價格: 100 9 - 商品編號: BL4438H 10 描述: 棒球 11 價格: 200 12 稅費: 10.00 13 總價: 310.00 14 備註: > 15 本次採購商品均 16 屬於球類運動商品.
11)demo11
#錯誤日誌 --- 時間: 2028-10-01 15:01:42 使用者: ed 錯誤資訊: - 檔案: nginx.conf 行號: 23 錯誤編碼: "0x3D5FF1" - 檔案: test.php 行號: 12 錯誤程式碼: "0xA4C51E" 警告資訊: | 你有兩個錯誤資訊需要檢視, 一條是配置檔案錯誤, 一條是指令碼語法錯誤, 具體內容參考錯誤資訊.
Playbook語法格式要求如下:
- playbook採用YAML格式編寫
- playbook檔案中由一個或多個play組成
- 每個play中可以包含:
- hosts(主機)、tasks(任務)、vars(變數)等元素組成
- 使用ansible-playbook命令執行playbook劇本
步驟一:測試Playbook語法格式
1)編寫第一個Playbook(劇本)
hosts、tasks、name是關鍵詞(不可修改),ping是模組,呼叫不同模組完成不同任務。
1 [root@control ansible]# vim ~/ansible/test.yml 2 --- 3 - hosts: all #hosts定義要遠端誰? 4 tasks: #tasks定義遠端後要執行的任務有哪些? 5 - name: This is my first playbook #name後面的具體內容可以任意 6 ping: 7 [root@control ansible]# ansible-playbook ~/ansible/test.yml
執行效果如圖-1所示
2)定義多個主機和任務的劇本
hosts由一個或多個組或主機組成,逗號分隔,tasks由一個或多個任務組成,多個任務按順序執行,執行ansible-playbook命令可以使用-f選項自定義併發量。
1 [root@control ansible]# vim ~/ansible/test.yml 2 - hosts: test,webserver 3 tasks: 4 - name: This is my first playbook #name後面的內容可以任意 5 ping: 6 - name: Run a shell command 7 shell: touch ~/shell.txt 8 #hosts定義需要遠端哪些被管理主機,hosts是關鍵詞 9 #tasks定義需要執行哪些任務,tasks是關鍵詞 10 #第一個任務呼叫ping模組,該模組沒有引數 11 #第二個任務呼叫shell模組在被管理主機建立一個空檔案~/shell.txt 12 [root@control ansible]# ansible-playbook ~/ansible/test.yml -f 5 13 ## 驗證:到node1、node3、node4主機分別執行命令ls /root/shell.txt檢視是否有該檔案
3)多個play的Playbook檔案
1 [root@control ansible]# vim ~/ansible/test.yml 2 #第一個play劇目 3 --- 4 - hosts: test 5 tasks: 6 - name: This is first play 7 ping: 8 #第二個play劇目 9 - hosts: webserver 10 tasks: 11 - name: This is second play 12 ping:
步驟二:Playbook應用案例
1)使用者管理,建立系統賬戶、賬戶屬性、設定密碼(ansible-doc user)。
[root@control ansible]# vim ~/ansible/test_john.yml --- - hosts: webserver tasks: - name: Add the user 'johnd' user: name: johnd uid: 1040 group: daemon password: "{{ '123' | password_hash('sha512') }}" #hosts定義需要遠端的物件是webserver組,hosts是關鍵詞 #tasks定義需要執行的任務,tasks是關鍵詞 # name是第一個任務的描述資訊,描述資訊可以任意 # user是第一個任務需要呼叫的模組,user下面的縮排內容是給user模組的引數 # name是需要建立的使用者名稱,uid是使用者ID號 # group是使用者屬於哪個基本組 # password是使用者的密碼,密碼是123,密碼經過sha512演算法加密 [root@control ansible]# vim ~/ansible/user_james.yml --- - hosts: webserver tasks: - name: Add 'james' with a bash shell user: name: james shell: /bin/bash groups: bin,adm password: "{{ '123' | password_hash('sha512') }}" #與上一個案例類似,groups指定使用者屬於哪些附加組. [root@control ansible]# vim ~/ansible/user_johnd.yml --- - hosts: webserver tasks: - name: Remove the user 'johnd' user: name: johnd state: absent #刪除系統賬戶johnd,state的值設定為absent是刪除使用者
2)使用playbook管理邏輯卷
準備工作:給node2主機再新增一塊磁碟(以下實驗磁碟名稱僅為參考,不要照抄)。
(ansible-doc parted,ansible-doc lvg,ansible-doc lvol)
[root@control ansible]# vim ~/ansible/lvm.yml --- - hosts: node2 #遠端node2主機 tasks: - name: Create a new primary partition with a size of 1GiB #任務的描述資訊 parted: #呼叫parted模組進行分割槽 device: /dev/sdb #對/dev/sdb磁碟進行分割槽(磁碟名稱不要照抄) label: gpt #分割槽表型別為gpt,或msdos number: 1 #分割槽編號(建立第幾個分割槽) state: present #present是建立分割槽,absent是刪除分割槽 part_start: 1MiB #分割槽的開始位置(預設從最開始位置分割槽) part_end: 1GiB #分割槽的結束位置(不寫就分到磁碟最後位置) - name: Create a volume group on top of /dev/sdb1 #第二個任務的描述資訊 lvg: #呼叫lvg模組,建立VG卷組 vg: my_vg #要建立的卷組名稱 pvs: /dev/sdb1 #使用哪個分割槽建立PV - name: Create a logical volume of 512m #第三個任務的描述資訊 lvol: #呼叫lvol模組建立LV vg: my_vg #使用哪個VG建立LV lv: my_lv #需要建立的LV名稱 size: 512m #要建立的LV大小,可以不指定單位,預設單位m
3)使用playbook管理軟體(ansible-doc yum)
RHEL或CentOS系統中的軟體有組包的概念,使用yum grouplist或者dnf grouplist可以檢視組包的名稱。
[root@control ansible]# vim ~/ansible/package.yml --- - hosts: webserver #需要遠端的主機是誰 tasks: #定義劇本需要執行的任務 - name: Install a list of packages #第一個任務的描述資訊 yum: #呼叫yum模組安裝軟體 name: #安裝軟體的名字,它的值有多個,使用陣列- - httpd #安裝httpd軟體 - mariadb #安裝mariadb軟體 - mariadb-server #安裝mariadb-server - name: install the 'RPM Development Tools' package group #第二個任務的描述資訊 yum: #呼叫yum模組安裝軟體組包 name: "@RPM Development Tools" #安裝哪個組包,@是關鍵詞 - name: update software #第三個任務的描述資訊 yum: #呼叫yum模組升級軟體 name: '*' #需要升級哪些軟體 state: latest #latest代表升級軟體 #備註:state的值可以是(present|absent|latest) #present代表安裝軟體(預設是present);absent代表解除安裝軟體 #latest代表升級軟體
----
4 案例4:Playbook應用案例
4.1 問題
沿用練習三,繼續練習Ansible 特殊模組並掌握自定義變數的方式,具體要求如下:
- 熟悉setup與debug模組
- 熟悉各種常見的變數定義方式
步驟一:Ansible特殊模組
1)setup模組
ansible_facts用於採集被管理裝置的系統資訊,所有收集的資訊都被儲存在變數中,每次執行playbook預設第一個任務就是Gathering Facts,使用setup模組可以檢視收集到的facts資訊。
[root@control ansible]# ansible test -m setup 192.168.4.10 | SUCCESS => { "ansible_facts": { "ansible_all_ipv4_addresses": [ … 省略部分內容…
試試自己找出下列變數:
- ansible_all_ipv4_addresses #IP地址
- ansible_bios_version #主機板BIOS版本
- ansible_memtotal_mb #總記憶體
- ansible_hostname #主機名
- ansible_fqdn #主機的域名
- ansible_devices.sda.partitions.sda1.size #某個磁碟分割槽的大小
2)debug模組
debug模組可以顯示變數的值,可以輔助排錯,通過msg可以顯示變數的值,變數需要使用{{}}擴起來。
[root@control ansible]# vim ~/ansible/debug.yml --- - hosts: test tasks: - debug: msg: "主機名是:{{ ansible_hostname }}" - debug: msg: "總記憶體大小:{{ ansible_memtotal_mb }}" #備註呼叫debug模組顯示某些具體的變數值 #debug模組可以顯示變數的值,可以輔助排錯
步驟二:定義變數的方法
Ansible支援十幾種定義變數的方式,這裡我們僅介紹其中一部分變數。
下面是根據優先順序排序的定義方式:
- Inventory變數
- Host Facts變數
- Playbook變數
- Playbook提示變數
- 變數檔案
- 命令列變數
1)Inventory變數(在主機清單配置檔案中定義變數)。
[root@control ansible]# vim ~/ansible/inventory [test] node1 iname="nb" [proxy] node2 [webserver] node[3:4] [webserver:vars] iname="dachui" #備註,在node1主機後面給該主機新增變數iname,值為nb. #給webserver組定義變數,vars是關鍵詞不可以改變,webserver是上面定義的組 #給這個組定義變數iname="dachui"
下面編寫劇本呼叫剛才的變數:(在劇本中需要呼叫變數是要使用{{}})
[root@control ansible]# vim ~/ansible/inventory_var.yml --- - hosts: node1,webserver #定義需要遠端管理的主機是誰 tasks: #劇目要完成哪些任務 - name: create a user with var. #劇目中的第一個任務描述資訊 user: #呼叫user模組建立使用者 name: "{{ iname }}" #需要建立的使用者名稱是iname這個變數 #注意事項: #在ansible劇本中當呼叫變數時,開始位置就呼叫變數,就需要在{{}}外面加雙引號 #如果是在後面或者中間位置呼叫變數{{}}外面可以不加雙引號 #如: # "{{ iname }}" # nihao {{ iname }}
2)Host Facts變數(可以直接呼叫ansible收集的系統資訊)
[root@control ansible]# vim ~/ansible/facts_var.yml --- - hosts: test tasks: - name: create user. user: name: "{{ansible_hostname}}" #定義劇本,遠端所有被管理主機,呼叫user模組,建立使用者 #需要建立的使用者名稱ansible_hostname是一個ansible_facts變數 #驗證: 到node1主機檢視是否有一個與主機名同名的使用者
3)Playbook變數(使用vars關鍵詞可以在playbook內定義變數)。
[root@control ansible]# vim ~/ansible/playbook_var.yml --- - hosts: test vars: #vars是關鍵詞,用來定義變數用的 iname: heal #具體變數名是iname,值是heal ipass: '123456' #再定義一個變數名是ipass,值是123456 #注意密碼必須是字串,需要引號 tasks: #tasks定義需要執行的任務 - name: Use variables create user. #給任務寫個描述資訊 user: #呼叫user模組建立使用者 name: "{{ iname }}" #使用者名稱的是前面定義的變數 password: "{{ ipass | password_hash('sha512') }}" #密碼是前面定義好的ipass,管道給password_hash把密碼加密.
4)Playbook提示變數(根據提示輸入變數的值)。
[root@control ansible]# vim ~/ansible/prompt_var.yml --- - hosts: test vars_prompt: #vars_prompt是關鍵詞,定義提示變數 - name: iname #通過name定義變數名為iname prompt: "請輸入使用者名稱" #執行劇本時提示資訊 private: no #是否是隱私資料,no代表不是(螢幕可以顯示) - name: ipasswd #通過name再定義變數,變數名為ipasswd prompt: "請輸入密碼" #執行劇本時提示資訊 private: yes #是否是隱私資料,yes代表是(隱私資料螢幕不顯示) tasks: #定義劇本需要執行的任務 - name: Create a user. #定義第一個任務的描述資訊 user: #呼叫user模組建立使用者,設定使用者密碼 name: "{{ iname }}" #使用者名稱是前面建立的變數iname password: "{{ ipasswd | password_hash('sha512') }}" #密碼是前面定義的變數ipasswd,密碼管道給password_hash加密.
5)單獨定義個變數檔案,在playbook中用vars_files呼叫該檔案。
[root@control ansible]# vim ~/ansible/file_var.yml --- - hosts: test vars_files: variables.yml #當變數比較多時,專門定義一個檔案用來存變數 tasks: - name: create user. user: name: "{{ iname }}" password: "{{ ipass | password_hash('sha512') }}" #呼叫user模組建立使用者 #使用者名稱是變數檔案variables.yml中定義的變數iname,密碼也是變數檔案中定義的變數 [root@control ansible]# vim ~/ansible/variables.yml --- iname: cloud ipass: '123456'
6)執行ansible-playbook命令時使用-e引數定義變數
[root@control ansible]# vim ~/ansible/command_var.yml --- - hosts: test tasks: - name: create user user: name: "{{ iname }}" password: "{{ ipass | password_hash('sha512') }}" [root@control ansible]# ansible-playbook command_var.yml \ -e iname="beth" -e ipass="123456"
附加思維導圖,如圖-2所示: