環境準備
ansible:192.168.12.10(主節點)
web01:192.168.121.11
web02:192.168.121.12
db:192.168.121.13
只需在主節點安裝ansible即可,從屬節點不需要安裝
一、Ansible簡介
Ansible是一個自動化統一配置管理工具,自動化主要體現在Ansible整合了豐富模組以及功能元件,可以透過一個命令完成一系列的操作,進而能減少重複性的工作和維護成本,可以提高工作效率。
1.遠端執行
批次執行遠端命令,可以對多臺機器遠端操作2.配置管理
批次配置軟體,可以自動分發配置檔案,服務統一管理啟動或停止3.事件驅動
透過Ansible的模組,對服務進行不同的事件驅動
比如:
1)修改配置後重啟
2)只修改配置檔案,不重啟
3)修改配置檔案後,重新載入
4)遠端啟停服務管理4.管理公有云
透過API介面的方式管理公有云,不過這方面做的不如saltstack
saltstack本身可以透過saltcloud管理各大雲廠商的雲平臺。5.二次開發
因為語法是Python,所以便於運維進行二次開發。6.任務編排
可以透過playbook的方式來統一管理服務,並且可以使用一條命令,實現一套框架的部署7.跨平臺,跨系統
幾乎不受到平臺和系統的限制,比如安裝apache和啟動服務Ansible是epel源提供的,一次在安裝Ansible之前需要安裝epel
# 安裝epel
yum install -y epel-release
# 安裝ansible
yum install -y ansible
二、ansible配置
【1】、配置hosts
修改/etc/hosts檔案
[root@ansible ~]# echo -e "192.168.121.11\tweb01" >> /etc/hosts
[root@ansible ~]# echo -e "192.168.121.12\tweb02" >> /etc/hosts
[root@ansible ~]# echo -e "192.168.121.13\tdb" >> /etc/hosts
[root@ansible ~]# echo -e "192.168.121.10\tansible" >> /etc/hosts
[root@ansible ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.121.11 web01
192.168.121.12 web02
192.168.121.13 db
192.168.121.10 ansible
【2】、ssh免密
[root@ansible ~]# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
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:iF5fPyuXd8VbGOmKpicRTmVdiAFtEf001NMnQdSbh5o root@ansible
The key's randomart image is:
+---[RSA 3072]----+
| .o+B **+.|
| * + +.=|
| + o ==|
| . .o =o.|
| . ooS.. + +.|
| . . .o. .E o +|
| . .. .oo +|
| . = +o...|
| .= o.. . |
+----[SHA256]-----+
ssh-copy-id web01
ssh-copy-id web02
ssh-copy-id db
【3】、配置ansible管理環境
修改主配置檔案
- 主配置檔案
- 參考/etc/ansible/ansible.cfg
- ansible配置檔案查詢順序
- 首先檢測ANSIBLE_CONFIG變數定義的配置檔案
- 其次檢測當前目錄下的./ansible.cfg
- 再次檢查當前使用者家目錄下~/ansible.cfg
- 最後檢查/etc/ansible/ansible.cfg
# 修改主配置檔案(在工作目錄中建立主配置檔案和主機清單檔案)
[root@ansible ansible]# vim ansible.cfg
[defaults]
inventory=inventory # 主機清單要和你自己建立的主機清單名字一致
host_key_checking=false
# 修改主機清單,ansible後面的物件一定要出現在inventory清單檔案中
[root@ansible ansible]# vim inventory
[webservers]
web[01:02]
# 也可以寫成:web01 web02
[dbservers]
db
[cluster:children] # 定義組巢狀的語法
webservers
dbservers
【4】、測試
# 批次執行ping命令,檢測主機存活
[root@ansible ansible]# ansible all -m ping
db | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
web02 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
web01 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
# ansible後面可以跟多個物件,用逗號隔開
[root@ansible:192.168.121.10 ~/ansible]$ansible web01,db -m ping
# 批次新增使用者
[root@ansible ansible]# ansible all -a "useradd zhangsan"
db | CHANGED | rc=0 >>
web02 | CHANGED | rc=0 >>
web01 | CHANGED | rc=0 >>
# 批次建立目錄
[root@ansible ansible]# ansible all -a "mkdir /tmp/demo"
web02 | CHANGED | rc=0 >>
db | CHANGED | rc=0 >>
web01 | CHANGED | rc=0 >>
三、ansible管理
- ansible進行程序管理的兩個方法
- adhoc臨時命令。就是在命令列上執行管理命令
- playbook劇本。把管理任務用特定格式寫到檔案中
- 無論哪種方式都是透過模組載入引數進行管理
【1】、adhoc臨時命令
ansible 主機或組列表 -m 模組 -a "引數" # -a是可選的
1、ping模組
測試能否ping同主機
類似ping但是不完全等於ping
2、ansbile檔案操作模組
- 在ansible中,透過模組完成某一特定任務
- 學習模組,主要知道實現某種功能,需要哪個模組
- 模組的使用方式都一樣。主要是檢視模組有哪些引數
# 檢視ansible可用模組
[root@ansible:192.168.121.10 ~/ansible]$ansible-doc -l | wc -l
8354
# 檢視ansible可用模組數量
[root@ansible:192.168.121.10 ~/ansible]$ansible-doc -l | wc -l
8354
(1)、command模組
這是ansible預設模組,如果執行ansible命令時,沒有加模組,預設是command模組
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -a "ls -lh /etc/hosts"
web01 | CHANGED | rc=0 >>
-rw-r--r--. 1 root root 158 Sep 10 2018 /etc/hosts
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m command -a "ls -lh /etc/hosts"
web01 | CHANGED | rc=0 >>
-rw-r--r--. 1 root root 158 Sep 10 2018 /etc/hosts
### 在command模組中執行命令時不支援shell特性,如管道、重定向等
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -a "ifconfig ens33 | head"
web01 | FAILED | rc=1 >>
|: Unknown host
ifconfig: `--help' gives usage information.non-zero return code
(2)、shell模組
在shell模組中執行命令支援shell特性
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m shell -a "ifconfig ens33 | grep 192"
web01 | CHANGED | rc=0 >>
inet 192.168.121.11 netmask 255.255.255.0 broadcast 192.168.121.255
(3)、script模組
如果要執行復雜的命令,可以寫入指令碼使用script模組可以執行指令碼
在使用script模組執行指令碼時,指令碼可以沒有x許可權
# test指令碼內容
#!/bin/bash
for user in user{6..8}
do
useradd $user
echo "123456" | passwd --stdin $user
done
#
[root@ansible:192.168.121.10 ~/ansible]$ansible all -m script -a "test.sh"
⚠️command、shell、script不建議使用
因為這三個模組沒有冪等性
(4)、file模組
- 可以建立檔案、目錄、連結等,還可以修改許可權屬性等
- 常用的選項
- path:指定檔案路徑
- owner:設定檔案所有者,一定要是提前存在的
- group:設定檔案所屬組,一定要是提前存在的
- state:狀態。touch表示建立檔案,directory表示建立目錄,link表示建立軟連線,absent表示刪除
- mode:設定許可權
- scr:source的縮寫,源
- dest:目的路徑
# 在webservers組中建立檔案
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m file -a "path=/tmp/file.txt state=touch"
# 在webservers組中建立目錄
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m file -a "path=/tmp/demp state=directory"
# 指定許可權和屬組,屬主
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m file -a "path=/tmp/bbb.txt mode='0777' state=touch owner=user1 group=user1"
# 刪除檔案
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m file -a "path=/tmp/bbb.txt mode='0777' state=absent owner=user1 group=user1"
# 刪除目錄
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m file -a "path=/tmp/demp mode='0777' state=absent owner=user1 group=user1"
# 建立連結
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m file -a "src=/etc/passwd dest=/tmp/passwd state=link"
file模組冪等性的體現
在建立目錄時,第一次建立是CHANGED,後面再建立相同的目錄時就是SUCESS,不會報錯
web01 | SUCCESS =>
在建立檔案時不存在冪等性,因為雖然建立的檔案是一樣的,但是每一次touch時,檔案的時間都會改變
web02 | CHANGED =>
(5)、copy模組
- 用於將檔案從控制端複製到被控端
- 常用選項
- scr:源,控制端檔案路徑
- dest:目的,被控端檔案路徑
# 複製檔案
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m copy -a "src=test.sh dest=/tmp/"
# 複製目錄,不能上傳空目錄
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m copy -a "src=/etc/passwd dest=/tmp/"
# 我們可以使用copy模組直接在被控端主機上建立檔案並寫入內容,不需要再控制端建立好後在上傳到被控端
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m copy -a "dest=/tmp/a.txt content='hello world\n'"
(6)、fetch模組
- 與copy相反,copy是上傳,fetch是下載
- 常用選項
- src:源,被控端檔案的路徑,不支援下載目錄
- dest:目標,控制端檔案的路徑
# 將被控端的/etc/hosts檔案下載下來,下載下來之後會在dest_path下自動劃分目錄
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m fetch -a "src=/etc/hosts dest=~/"
[root@ansible:192.168.121.10 ~]$ll|grep web
drwxr-xr-x. 3 root root 17 Jun 25 18:25 web01
drwxr-xr-x. 3 root root 17 Jun 25 18:25 web02
(7)、lineinfile模組
- 用於確保目標檔案中有某一行內容
- 常用選項
- path:待修改的檔案路徑
- line:寫入檔案的一行內容
- regexp:正規表示式,用於查詢檔案中的內容
# 向檔案中寫入一行內容
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m lineinfile -a "path=/etc/issue line='Hello World\n'"
# 使用regexp正則匹配替換,替換匹配到的一行
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m lineinfile -a "path=/etc/issue regexp='Hello' line='chilema\n'"
(8)、replace模組
- lineinfile會替換一行,replace可以替換關鍵詞
- 常用選項
- path:待修改的檔案路徑
- replace:將正規表示式匹配到的內容,替換成replace中的內容
- regexp:正規表示式,用於查詢檔案中的內容
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m replace -a "path=/etc/issue regexp='chi' replace='he'"
[root@web01:192.168.121.11 /tmp]$cat /etc/issue
\S
Kernel \r on an \m
helema
(10)、檔案操作綜合練習
- 所有操作均對webservers組中的主機生效
- 在目標主機上建立/tmp/mydemo目錄,屬主和屬組都是adm,許可權0777
- 將控制端的/etc/hosts檔案上傳到目標主機的/tmp/mydemo目錄中,屬主和屬組都是adm,許可權為0600
- 替換目標主機的/tmp/mydemo/hosts檔案中的db1為database1
- 將目標主機/tmp/mydemo/hosts檔案下載到控制短的當前目錄
# 在目標主機上建立/tmp/mydemo目錄,屬主和屬組都是adm,許可權0777
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m file -a "path=/tmp/mydemo state=directory owner=adm group=adm mode='0777'"
# 將控制端的/etc/hosts檔案上傳到目標主機的/tmp/mydemo目錄中,屬主和屬組都是adm,許可權為0600
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m copy -a "src=/etc/hosts dest=/tmp/mydemo owner=adm group=adm mode=0600"
# 替換目標主機的/tmp/mydemo/hosts檔案中的db1為database1
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m replace -a "path=/tmp/mydemo/hosts regexp="db" replace=database"
# 將目標主機/tmp/mydemo/hosts檔案下載到控制短的當前目錄
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m fetch -a "src=/tmp/mydemo/hosts dest=./"
3、使用者操作模組
(1)、user模組
- 實現Linux的使用者管理
- 常用選項
- name:帶建立使用者名稱
- uid:使用者UID
- group:設定主組
- groups:這隻附加組
- home:設定家目錄
- password:設定使用者密碼
- state:狀態。present表示建立,他是預設選項。absent表示刪除
- remove:刪除家目錄、郵箱等。值為yes或true都行
# 直接建立使用者
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m user -a "name=zhangsan"
# 指定條件建立使用者
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m user -a "name=lisi uid=1011 group=adm groups=adm,root home=/home/lisi "
[root@web01:192.168.121.11 /tmp/mydemo]$id lisi
uid=1011(lisi) gid=4(adm) groups=4(adm),0(root)
# 修改使用者密碼
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m user -a "name=zhangsan password={{'123456'|password_hash('sha512')}}"
# 刪除使用者
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m user -a "name=zhangsan state=absent remove=yes"
(2)、group模組
建立使用者組
- name:帶建立的組名
- gid:組的id號
- stat:present表示建立,他是預設選項。absent表示刪除
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m group -a "name=devops"
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m group -a "name=devops state=absent"
4、軟體包相關模組
(1)、yum_repository模組
- 用於配置yum
- 常用選項
- file:指定檔名
- name:軟體倉庫名
- description:描述名稱
- 其他選項,請與檔案內容對照
# 我們可以使用file模組和copy模組實現yum的repo檔案傳輸
ansible all -m file "path=/etc/yum.repos.d/local.repo state=absent"
ansible all -m copy "src=/etc/yum.repos.d/local.repo dest=/etc/yum.repos.d/local.repo"
# 使用yum_repository模組進行配置
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m yum_repository -a "file=myrepo name=MyApp description='My App' baseurl=file:///mnt/mydvd/AppStream enabled=yes gpgcheck=no "
# 如果在寫一個相同檔名的repo檔案,不會覆蓋原有的repo檔案,而是在原始檔中追加
(2)、yum模組
管理軟體
常用選項
- name:包名
- state:狀態
- present:表示安裝,如果安裝則忽略;latest表示安裝或者升級到最新版本;absent表示解除安裝
# 安裝一個軟體
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m yum -a "name=tar state=present"
# 安裝多個軟體,軟體之間使用逗號隔開
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m yum -a "name=tar,wget state=present"
# 解除安裝軟體
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m yum -a "name=wget state=absent"
# 使用latest更新安裝軟體(軟體版本以軟體倉庫中的為主)
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m yum -a "name=nginx state=latest"
5、服務相關模組
(1)、service模組
- 常用選項
- name:服務名稱
- state:對服務執行的操作。started啟動,stopped停止,restarted重啟服務,reloaded重新載入服務
- enable:是否開機自啟。yes開機自啟,no開機不自啟
# 啟動服務
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m service -a "name=nginx state=started enabled=yes"
# 重啟服務
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m service -a "name=nginx state=reloaded enabled=yes"
6、邏輯卷相關模組
(1)、lvg模組
建立卷組
vg:卷組名字,pvs:組成卷組的物理分割槽
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m lvg -a "vg=myvg pvs=/dev/sdb1"
[root@web01:192.168.121.11 ~]$vgs
VG #PV #LV #SN Attr VSize VFree
myvg 1 0 0 wz--n- <5.00g <5.00g
rl 1 3 0 wz--n- <99.00g 0
# 刪除卷組
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m lvg -a "vg=myvg state=absent"
(2)、lvol模組
建立邏輯卷
vg:邏輯卷名字 lv:邏輯卷名字 size:邏輯卷大小
常用選項
- vg:製作邏輯卷的卷組名字
- lv:邏輯卷的名字
- force:刪除邏輯卷時必須加的,force=yes
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m lvol -a "vg=myvg lv=mylv size=2G"
[root@web01:192.168.121.11 ~]$lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
mylv myvg -wi-a----- 2.00g
home rl -wi-ao---- <31.82g
root rl -wi-ao---- 65.17g
swap rl -wi-ao---- <2.0 1g
# 要對邏輯捲進行擴容時,直接修改size即可,通知檔案系統
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m lvol -a "vg=myvg lv=mylv size=4G resizefs=yes"
[root@web01:192.168.121.11 ~]$lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
mylv myvg -wi-a----- 4.00g
home rl -wi-ao---- <31.82g
root rl -wi-ao---- 65.17g
swap rl -wi-ao---- <2.01g
# 刪除邏輯卷
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m lvol -a "vg=myvg lv=mylv state=absent force=yes"
(3)、filesystem模組
- 用於格式化,也就是建立檔案系統
- 常用選項
- fstype:指定檔案系統型別
- dev:指定要格式化的裝置,可以是分割槽,可以是邏輯卷
Windows:ntfs
Linux:xfs(適合大檔案)、ext4(適合小檔案)
存在冪等性,當我們格式化一次後,再要格式化時就不會執行了
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m filesystem -a "dev=/dev/myvg/mylv fstype=xfs"
[root@web01:192.168.121.11 ~]$blkid /dev/myvg/mylv
/dev/myvg/mylv: UUID="22ef21b3-51b2-4bbf-a546-45c3e83005d8" BLOCK_SIZE="512" TYPE="xfs"
(4)、mount模組
- 用於掛載檔案系統,掛在完成後會自動寫入/etc/fstab檔案中
- 常用選項
- path:掛載點。如果掛載點不存在,自動建立
- src:待掛在裝置,支援透過UUID進行掛載
- fstype:檔案系統型別
- state:unmounted解除安裝,mounted掛載
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m mount -a "src=/dev/myvg/mylv path=/data state=mounted fstype=xfs"
[root@web01:192.168.121.11 ~]$grep data /etc/fstab
/dev/myvg/mylv /data xfs defaults 0 0
# 解除安裝掛載點
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m mount -a "path=/data state=absent"
(5)、parted模組
用於磁碟分割槽管理
常用選項
- device:待分割槽裝置
- number:分割槽編號
- state:present表示建立,absent表示刪除
- part_start:分割槽的起始位置,不屑表示從開頭
- part_end:表示分割槽結束的位置,不寫表示到結尾
---
- name: disk manage
hosts: web01
tasks:
- name: create a partition
parted:
device: /dev/sdc
state: present
number: 1
part_end: 5GiB
- name: create a new partition
parted:
device: /dev/sdc
state: present
number: 2
part_start: 5GiB
part_end: 8GiB
- name: create lvm
hosts: web01
tasks:
- name: create vg
lvg:
vg: my_vg
pvs: /dev/sdc1,/dev/sdc2
- name: create lv
lvol:
vg: my_vg
lv: my_lv
size: 2G
- name: make fs
hosts: web01
tasks:
- name: make xfs
filesystem:
fstype: xfs
dev: /dev/my_vg/my_lv
- name: mount
hosts: web01
tasks:
- name: mount parted
mount:
path: /mnt/xfs_my
src: /dev/my_vg/my_lv
fstype: xfs
state: present
7、防火牆相關模組
(1)、firewalld模組
- 用於配置防火牆模組
- 常用選項
- port:宣告埠
- permanent:永久生效,但不會立即生效
- immediate:立即生效,但不會永久生效
- state:enable放行,disable拒絕
- 防火牆一般預設拒絕,明確寫入允許的服務
- 有一些服務有名字,有些服務沒有名字。但是最終都是基於TCP或UDP的某些埠。比如http服務基於TCP80埠。服務名和埠號對應關係的說明檔案是:/etc/services
- 配置伺服器的防火牆,一般來說只要配置開放哪些服務或者埠即可。沒有明確開放的,都預設拒絕
---
- name: configure webservers
hosts: webservers
tasks:
- name: install nginx and firewalld
yum:
name: nginx,firewalld
state: present
- name: start nginx
service:
name: nginx
state: started
enabled: yes
- name: start firewalld
service:
name: firewalld
state: started
enabled: yes
# 配置防火牆規則
- name: set firewalld
hosts: webservers
tasks:
- name: set firewalld rule
firewalld:
port: 80/tcp
permanent: yes
immediate: yes
state: enabled
8、template模組
- copy模組可以上傳檔案,但是檔案內容固定
- template模組可以上傳具有特定格式的檔案(如檔案中包含變數)
- 當遠端主機接收到檔案之後,檔案中的變數將會變成具體的值
- template模組上傳的檔案,使用的語法叫做Jinja2
- 常用選項:和copy一樣
- src:
- dest:
【2】、playbook劇本
- 常用於複雜任務的管理,以及管理經常要完成的任務
- playbook也是透過模組和它的引數,在特定的主機上執行任務
- playbook是一個檔案,該檔案中需要透過yaml格式書寫
1、yaml
YAML Ain‘t Markup Language
語法規範:
- yaml檔案的檔名,一般以yml或yaml作為副檔名
- 檔案以---作為第一行
- 鍵值對使用:表示,冒號後面必須有空格
- 陣列使用-表示,-後面必須有空格
- 相同層級必須有相同的縮排。如果縮排不對,則有語法錯誤。每一級縮排,建議兩個空格
- 全文不能使用tab,應該使用空格
2、配置vim適應yaml語法
# 檔案位置和名字都是固定的,用於設定 vim的格式
[root@ansible:192.168.121.10 ~]$vim ~/.vimrc
1 set nu # 顯示行號
2 set ai # 換行時自動縮排
3 set et # 讓tab以空格的形式出現
4 set ts=2 # 按一次tab空兩格
3、編寫playbook
- 一個劇本(即playbook),可以包含多個play
- 每個play用於在指定的主機上,透過模組和引數執行相應的任務
- 每個play可以包含多個任務
- 任務由模組和引數構成
# 第一個劇本
1 ---
2 - name: 測試能否管理
3 hosts: all
4 tasks:
5 - name: test
6 ping:
# ansible有專門執行劇本的命令
[root@ansible:192.168.121.10 ~/ansible]$ansible-playbook test.yaml
# 每一個play
PLAY [測試能否管理] *****************************************************************************************************************************************
# ansible會自動執行的任務
TASK [Gathering Facts] **************************************************************************************************************************************
ok: [web01]
ok: [web02]
ok: [db]
# 我們自己定義的任務
TASK [test] *************************************************************************************************************************************************
ok: [db]
ok: [web01]
ok: [web02]
# 回放,執行完成後的總結
PLAY RECAP **************************************************************************************************************************************************
db : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
web01 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
web02 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
1 ---
2 - name: create dir and copy file
3 hosts: db,web01
4 tasks:
5 - name: create dir
6 file:
7 path: /tmp/demo
8 state: directory
9 mode: '0755'
10
11 - name: copy file
12 copy:
13 src: /etc/hosts
14 dest: /tmp/demo
# 在webservers組中的主機上,建立使用者bob,附加組是adm;在db主機上,建立/tmp/hi.txt 其內容為hello world
---
- name: user and file context manage
hosts: webservers
tasks:
- name: create usre
user:
name: bob
groups: adm
- name: context
hosts: db
tasks:
- name: create file
file:
path: /tmp/hi.txt
state: touch
- name: change file context
copy:
dest: /tmp/hi.txt
content: "hello world\n"
# 在一個劇本中可以存在兩個play
4、|和>區別
---
- name: play 1
hosts: db
tasks:
- name: mkfi
copy:
dest: /tmp/1.txt
content: |
Hello
nihao
[root@db:192.168.121.13 /tmp]$cat /tmp/1.txt
Hello
nihao
---
- name: play 2
hosts: db
tasks:
- name: mkfi
copy:
dest: /tmp/2.txt
content: >
Hello
nihao
[root@db:192.168.121.13 /tmp]$cat /tmp/2.txt
Hello nihao
5、引號問題
---
- name: user11
hosts: webservers
tasks:
- name:
user:
name: john
uid: 1040
group: daemon
password: "{{'123456'|password_hash('sha512')}}"
# 如果是大括號開頭必須用引號括起來,數字必須是str不能是int
6、安裝軟體包
# 安裝多個軟體包
寫法1:
---
- name: install packages
hosts: webservers
tasks:
- name: install httpd,php,php-mysqlnd
yum:
name:
- httpd
- php
- php-mysqlnd
state: present
寫法二:
---
- name: install packages
hosts: webservers
tasks:
- name: install httpd,php,php-mysqlnd
yum:
name: [httpd,php,php-mysqlnd]
state: present
寫法三:
---
- name: install packages
hosts: webservers
tasks:
- name: install httpd,php,php-mysqlnd
yum:
name: httpd,php,php-mysqlnd
state: present
Linux將一系列軟體放到一個組中,安裝軟體包,將會把很多軟體一起安裝上,比如gcc、java等都是開發工具,安裝開發工具包組,將會把他們一起安裝
# 列出所有的軟體包組
[root@web01:192.168.121.11 ~]$yum grouplist
Last metadata expiration check: 11:30:08 ago on Wed 26 Jun 2024 05:44:48 AM CST.
Available Environment Groups:
Server with GUI
Server
Workstation
KDE Plasma Workspaces
Virtualization Host
Custom Operating System
Installed Environment Groups:
Minimal Install
Available Groups:
Container Management
.NET Core Development
RPM Development Tools
Development Tools
Graphical Administration Tools
Headless Management
Legacy UNIX Compatibility
Network Servers
Scientific Support
Security Tools
Smart Card Support
System Tools
Fedora Packager
Xfce
# 安裝軟體包組
[root@web01:192.168.121.11 ~]$yum groupinstall "Development Tools"
# 劇本寫法,要將軟體包組加上引號,並且在組名前加@,來告訴yaml要安裝的是一個軟體組
---
- name: install packages
hosts: webservers
tasks:
- name: install group
yum:
name: "@Development Tools"
state: present
系統更新,將yum源換為更高的版本,然後全部更新即可
---
- name: install packages
hosts: webservers
tasks:
- name: update system
yum:
name: "*"
state: latest
四、ansible變數
【1】、facts變數
- facts翻譯過來就是事實
- facts變數是ansible自帶的預定義變數,用於描述被控端軟硬體資訊
- facts變數透過setup模組
# 檢視所有的ansible變數
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m setup
# filter:過濾變數
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m setup -a "filter=ansible_all_ipv4_addresses"
web01 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.121.11"
],
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}
常用的facts變數
- ansible_all_ipv4_addresses----所有的IP地址
- ansible_bios_version----BIOS版本資訊
- ansible_memtotal_mb----總記憶體大小
- ansible_hostname---主機名
【2】、debug模組
用來列印變數
在輸出時需要加上{{變數名}}
---
- name: display host info
hosts: webservers
tasks:
- name: display hostname and memory
debug:
msg: "hostname: {{ansible_hostname}}, mem {{ansible_memtotal_mb}}MB"
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m setup | grep -E "hostname|mem"
"ansible_hostname": "web01",
"ansible_memfree_mb": 211,
"ansible_memory_mb": {
"ansible_memtotal_mb": 1734,
"ansible_hostname": "web02",
"ansible_memfree_mb": 221,
"ansible_memory_mb": {
"ansible_memtotal_mb": 1734,
【3】、執行劇本時的順序
在我們執行劇本時,在執行每一個play時系統會自己執行一個任務
TASK [Gathering Facts] ****************************************************************************************************************************************
ok: [web02]
ok: [web01]這個任務的作用是收集facts,只有透過setup模組收集了事實,才可以使用debug模組去輸出
# 如果我們在adhoc中直接輸出facts,會未定義的錯誤
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m debug -a "msg='{{ansible_ens33.ipv4.address}}'"
web01 | FAILED! => {
"msg": "The task includes an option with an undefined variable. The error was: 'ansible_ens33' is undefined. 'ansible_ens33' is undefined. 'ansible_ens33' is undefined. 'ansible_ens33' is undefined"
}
# 如果我們將facts寫入劇本中,在執行劇本時,劇本會自己生成一個task(透過setup去收集facts),這樣你在後面如果要使用debug去輸出facts就不會再報錯了
【4】、ansible變數格式
ansible變數的格式類似於python中的字典,
我們在查詢變數時,要嚴格遵循層層遞進的關係去寫
父.子的格式,中間使用”.“表示巢狀關係
---
- name: display host info
hosts: web01
tasks:
- name: display hostname and memory
debug:
msg: |
hostname: {{ansible_hostname}}
mem: {{ansible_memtotal_mb}}MB
ens33_ip: {{ansible_ens33.ipv4.address}}
sdb2: {{ansible_devices.sdb.partitions.sdb2.size}}
ok: [web01] => {
"msg": "hostname: web01\nmem: 1734MB\nens33_ip: 192.168.121.11\nsdb2: 15.00 GB\n"
}
【5】、自定義變數
- 引入變數,可以方便playbook重用。比如裝包的playbook,包名使用變數,多次執行playbook,只要改變變數名即可,不用重新編寫playbook
- ansible支援10種以上的變數定義方式。常用變數來源如下:
- inventory變數。變數來自於主機清單
- facts變數。
- playbook變數。變數在playbook中定義。
- 變數檔案。專門建立用於儲存變數的檔案。推薦變數寫入單獨的檔案
# 在webservers組中建立zhaoliu使用者,在db上建立wangwu
---
- name: create user
hosts: webservers
tasks:
- name: create zhaoliu
user:
name: zhaoliu
- name: create wangwu
hosts: db
tasks:
- user:
name: wangwu
# 我們無法使用一個play去實現
因此我們就需要自定義變數
在劇本中使用變數,讓不同的主機建立不同的使用者
# 修改劇本
---
- name: create user
hosts: webservers,db
tasks:
- name: create zhaoliu
user:
name: "{{username}}"
# 在主機清單中建立變數
[webservers]
web[01:02]
# 給整個webservers組定義了一個變數
[webservers:vars]
username=zhaoliu
[dbservers]
# 只給dbservers中的db定義了變數
db username=zhaoliu
[cluster:children]
webservers
dbservers
在劇本中定義變數,使用vars:
在劇本中定義變數如果和invention中定義的變數重名,劇本中的變數的優先順序高於invention中定義的變數
---
- name: create jack
hosts: webservers
vars:
username: jack
password: "123"
tasks:
- user:
name: "{{username}}"
password: "{{password|password_hash('sha512')}}"
定義變數檔案,將變數寫入變數檔案中
# 劇本
---
- name: create user
hosts: webservers
vars_files: vars.yaml # 引用變數檔案
tasks:
- name: create user
user:
name: "{{yonghu}}"
state: present
password: "{{mima|password_hash('sha512')}}"
# 變數檔案
---
yonghu: rose
mima: abc
五、進階語法
【1】、錯誤處理
當playbook中包含很多工時,當某一個任務遇到錯誤,他將崩潰,終止執行
---
- name: my errors
hosts: webservers
tasks:
- name: start mysqld
service:
name: mysqld
state: started
enabled: yes
- name: touch file
file:
path: /tmp/service.txt
state: touch
# 由於主機上沒有mysql,當執行ansible時
# 我們可以加一個ignore_errors.引數來忽略錯誤,繼續向下執行
---
- name: my errors
hosts: webservers
ignore_errors: yes # ignore如果寫在這裡,則表示可以忽略所有的任務中的錯誤
tasks:
- name: start mysqld
service:
name: mysqld
state: started
enabled: yes
ignore_errors: yes # ignore寫在這裡表示忽略這一個任務的錯誤
- name: touch file
file:
path: /tmp/service.txt
state: touch
ASK [start mysqld] *******************************************************************************************************************************************
fatal: [web01]: FAILED! => {"changed": false, "msg": "Could not find the requested service mysqld: host"}
...ignoring
fatal: [web02]: FAILED! => {"changed": false, "msg": "Could not find the requested service mysqld: host"}
...ignoring
【2】、觸發執行任務
- 透過handlers定義觸發執行的任務
- handlers中定義的任務,不是一定會執行的
- 在task中定義的任務,透過notify關鍵通知handlers中的哪個任務要執行
- 只有task中的任務狀態是changed才會進行通知
# 下載nginx配置檔案到當前目錄
---
- name: download file
hosts: web01
tasks:
- name: get nginx.conf
fetch:
src: /etc/nginx/nginx.conf
dest: ./
flat: yes
# flat的作用是:扁平下載,只下載檔案,不會巢狀著目錄
---
- name: configure nginx
hosts: webservers
vars:
http_port: "80"
tasks:
- name: upload file
template:
src: ./nginx.conf
dest: /etc/nginx/nginx.conf
notify: restart nginx # 當這個任務發生修改後,在執行handlers的任務,如果notify的任務沒有執行,那就不會給handlers傳送訊號,handlers的任務也不會去執行
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
【3】、when條件
---
- name: install mysql-server
hosts: db
tasks:
- name: mysql-server
yum:
name: mysql-server
state: present
when: ansible_memtotal_mb > 2048
# when後面的變數不需要加雙大括號
TASK [mysql-server] *******************************************************************************************************************************************
skipping: [db]
# 如果不滿足when的條件,則跳過,不執行
多條件判斷
---
- name: whens
hosts: webservers
tasks:
- name: whens
copy:
src: ./motd
dest: /etc/motd
when: >
ansible_distribution == "Rocky"
and
ansible_distribution_major_version == "8"
【4】、regitster註冊變數
Ansible的”regitster“模組是用於捕獲和儲存任務執行結果的,它允許將其他任務的輸出作為變數使用。register是一個關鍵字,它可以將任務的執行結果賦值給指定的變數名稱。這個變數可以在後續任務中使用。register模組可以捕獲各種型別的輸出,包括stdout、stderr、rc、changed等。他可以與其他模組一起使用,例如”when“條件、”loop“迴圈等。
---
- name: create file
hosts: web01
tasks:
- name: create /tmp/reg1.txt
file:
path: /tmp/reg1.txt
state: touch
register: result
- name: display
debug:
msg: "{{result}}"
TASK [display] ************************************************************************************************************************************************
ok: [web01] => {
"msg": {
"changed": true,
"dest": "/tmp/reg1.txt",
"diff": {
"after": {
"atime": 1719419743.2074833,
"mtime": 1719419743.2074833,
"path": "/tmp/reg1.txt",
"state": "touch"
},
"before": {
"atime": 1719419530.2680113,
"mtime": 1719419517.1950111,
"path": "/tmp/reg1.txt",
"state": "file"
}
},
"failed": false,
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"secontext": "unconfined_u:object_r:user_tmp_t:s0",
"size": 0,
"state": "file",
"uid": 0
}
}
---
- name: create file
hosts: web01
tasks:
- name: create /tmp/reg1.txt
file:
path: /tmp/reg1.txt
state: touch
register: result
- name: display
debug:
msg: "failed:{{result.failed}},owner:{{result.owner}},mode:{{result.mode}}"
TASK [display] ************************************************************************************************************************************************
ok: [web01] => {
"msg": "failed:False,owner:root,mode:0644"
}
register和when結合使用
---
- name: create file
hosts: web01
ignore_errors: yes
tasks:
- name: file
file:
path: /tmp/a
state: touch
register: result
- name: debug
debug:
msg: "create fail"
when: result.failed
# 根據上一個任務執行結束
六、任務塊
【1】、block
可以透過block關鍵字,將多個任務組合到一起
可以將整個block任務組,一起控制是否要執行
---
- name: block
hosts: webservers
tasks:
- name: install nginx
yum:
name: nginx
state: present
when ansible_distribution == "Rocky"
- name: start nginx
service:
name: nginx
state: started
enabled: yes
when ansible_distribution == "Rocky"
# 如果不用block就會進行重複的判斷
# 設定block
---
- name: block
hosts: webservers
tasks:
- name: define a group of tasks
block:
- name: install nginx
yum:
name: nginx
state: present
- name: start nginx
service:
name: nginx
state: started
enabled: yes
when: ansible_distribution == "Rocky"
【2】、rescue和always
block、rescue和anlways是三兄弟分別表示
block:正常執行
rescue:補救,如果block不能正常執行(執行出錯),rescue則執行,如果block可以正常執行(執行沒有出錯),rescue則不執行
always:不論block和rescue執不執行,always永遠執行
---
- name: block
hosts: web01
tasks:
- name: block / rescue / always
block:
- name: create test1
file:
path: /tmp/test1.txt
state: touch
rescue:
- name: create test2
file:
path: /tmp/test2.txt
state: touch
always:
- name: create test3
file:
path: /tmp/test3.txt
state: touch
# block模組可以正確執行,因此rescue模組不執行,always執行。最後的結果就是,會在web01的 /tmp目錄下test1和test3檔案
---
- name: block
hosts: web01
tasks:
- name: block / rescue / always
block:
- name: create test1
file:
path: /tmp/aaa/test1.txt
state: touch
rescue:
- name: create test2
file:
path: /tmp/test2.txt
state: touch
always:
- name: create test3
file:
path: /tmp/test3.txt
state: touch
# block模組不能正確執行,因此rescue模組執行,always執行。最後的結果就是,會在web01的 /tmp目錄下test2和test3檔案
七、loop迴圈
相當於是shell中的for迴圈
ansible中迴圈用到的變數名是固定的,叫item
# 寫法1:
---
- name: use loop
hosts: web01
tasks:
- name: create dir
file:
path: /tmp/{{item}}
state: directory
loop:
- aaa
- bbb
- ccc
- ddd
- eee
# 寫法2
---
- name: use loop
hosts: web01
tasks:
- name: create dir
file:
path: /tmp/{{item}}
state: directory
loop: [aaa,bbb,ccc,ddd,eee]
# 控制多個服務,停止多個服務
---
- name: control server
hosts: webservers
tasks:
- name: stop nginx and firewalld
service:
name: "{{item}}"
state: stopped
enabled: no
loop: [nginx,firewalld]
在使用yum安裝軟體時儘量不要使用loop
1、yum本身就支援安裝多個包
2、如果使用loop去安裝軟體,則表示執行多次yum,效率降低
字典
建立兩個賬號
zhangsan:123
lisi:456
---
- name: create user
hosts: webservers
tasks:
- name: del user
user:
name: "{{item}}"
state: absent
remove: yes
loop: [zhangsan,lisi]
- name: create user
user:
name: "{{item['user']}}"
password: "{{item['pass']|password_hash('sha512')}}"
state: present
loop: [{"user":"zhangsan","pass":"123"},{"user":"lisi","pass":"456"}]
八、role角色
- 為了實現playbook重用,可以使用role角色
- 角色role相當於把任務打散,放到不同的目錄中
- 在把一些固定的值,如使用者名稱、軟體包、服務等,用變數來表示
- role角色定義好後,可以在其他playbook中直接呼叫
【1】、配置角色
# 宣告存放角色的 位置
roles_path = roles
# 建立roles目錄
[root@ansible:192.168.121.10 ~/ansible]$mkdir roles
# 生成具體的某一個角色
[root@ansible:192.168.121.10 ~/ansible]$ansible-galaxy init roles/motd
# 檢視生成的角色motd,如下的所有目錄和檔案不是每一個都必須的,沒有用到的目錄可以刪除,等到後面需要的時候可以再新建
[root@ansible:192.168.121.10 ~/ansible]$ll roles/motd/
total 4
drwxr-xr-x. 2 root root 22 Jun 27 05:36 defaults # 存放變數,優先順序最低
drwxr-xr-x. 2 root root 6 Jun 27 05:36 files # 存放劇本(不包含變數的劇本)
drwxr-xr-x. 2 root root 22 Jun 27 05:36 handlers
drwxr-xr-x. 2 root root 22 Jun 27 05:36 meta #後設資料:role的建立者、建立日期等
-rw-r--r--. 1 root root 1328 Jun 27 05:36 README.md
drwxr-xr-x. 2 root root 22 Jun 27 05:48 tasks # 存放任務
drwxr-xr-x. 2 root root 18 Jun 27 05:46 templates # 存放劇本(有變數的劇本)
drwxr-xr-x. 2 root root 39 Jun 27 05:36 tests # 測試案例
drwxr-xr-x. 2 root root 22 Jun 27 05:49 vars # 存放變數
# 配置角色具體內容
# 將劇本放入template
[root@ansible:192.168.121.10 ~/ansible]$mv motd roles/motd/templates/
# 編寫任務,將原劇本中的tasks複製到roles/motd/tasks/main.yml中
[root@ansible:192.168.121.10 ~/ansible]$vim roles/motd/tasks/main.yml
---
# tasks file for roles/motd
- name: motd
template:
src: motd
dest: /etc/motd
# 定義變數,將劇本中會使用到的變數寫入roles/motd/vars/main.yml中
[root@ansible:192.168.121.10 ~/ansible]$vim roles/motd/vars/main.yml
---
# vars file for roles/motd
admin: xuruizhao00@163.com
# 編寫劇本引用角色
[root@ansible:192.168.121.10 ~/ansible]$vim role_motd.yaml
---
- name: modify motd
hosts: webservers
# 呼叫設定好的角色,首先會去roles/motd/task/中找任務,再去template目錄中找要上傳的檔案,最後去vars目錄中找變數
roles:
- motd
【2】、role練習
1、建立名為pkgs的角色,用於裝包,包名使用變數pkg代表
2、建立inst_nginx.yaml,呼叫pkgs角色,安裝nginx
3、建立inst_mysql.yaml,呼叫pkgs角色,安裝mysql
# 新建角色,我們不使用ansible-galaxy,直接使用mkdir建立所需要的目錄,因為在建立角色的過程中,有很多的目錄不是我們所需要的
[root@ansible:192.168.121.10 ~/ansible]$mkdir -p roles/pkgs/{task,defaults}
# 設定任務
[root@ansible:192.168.121.10 ~/ansible/roles/start_svc]$vim tasks/main.yaml
---
- name: Install the pkgs
yum:
name: "{{pkg}}"
state: present
# 編寫變數,將變數寫入defaults中,因為defaults中的變數的優先順序最低,我們後續可以在劇本中定義新的變數,新的變數的值就可以覆蓋defaults中的值了
[root@ansible:192.168.121.10 ~/ansible/roles/start_svc]$vim defaults/main.yaml
---
pkg: nginx
# 編寫劇本
[root@ansible:192.168.121.10 ~/ansible]$vim inst_nginx.yaml
---
- name: intall nginx
hosts: webservers
roles:
- pkgs
[root@ansible:192.168.121.10 ~/ansible]$vim inst_mysql.yaml
---
- name: intall mysql
hosts: db
vars:
# 此處定義的變數,就會覆蓋defaults中定義的變數
pkg: mysql-server
roles:
- pkgs
定義一個start_svcjuese,控制服務
變數svc
# 編寫任務
[root@ansible:192.168.121.10 ~/ansible]$vim roles/start_svc/tasks/main.yaml
---
- name: control server
service:
name: "{{svc}}"
state: "{{single}}"
enabled: "{{panduan}}"
# 編寫變數
[root@ansible:192.168.121.10 ~/ansible]$vim roles/start_svc/defaults/main.yaml
---
svc: nginx
single: start
panduan: yes
# 編寫劇本
[root@ansible:192.168.121.10 ~/ansible]$vim role_nginx.yaml
---
- name: control serv
hosts: webservers
vars:
pkg: nginx
svc: nginx
single: restarted
roles:
- pkgs
- start_svc
tasks:
- name: create index web page
copy:
dest: /usr/share/nginx/html/test.html
content: "role test"
在劇本中允許role和tasks同時存在
當一個劇本中既有role又有tasks時,不管書寫的順序如何,一定是role先執行,tasks後執行
九、ansible加解密檔案
ansible加解密檔案使用ansible-vault命令
# 檔案加密
[root@ansible:192.168.121.10 ~/ansible]$ansible-vault encrypt hello.txt
New Vault password:
Confirm New Vault password:
Encryption successful
# 檔案解密
[root@ansible:192.168.121.10 ~/ansible]$ansible-vault decrypt hello.txt
Vault password:
Decryption successful
# 在不解密的情況下檢視檔案內容
[root@ansible:192.168.121.10 ~/ansible]$ansible-vault view hello.txt
Vault password:
在嗎
[root@ansible:192.168.121.10 ~/ansible]$ansible-vault view hello.txt > output
Vault password:
# 將密碼寫入檔案中,透過檔案進行加密和解密
[root@ansible:192.168.121.10 ~/ansible]$echo "aaa" > pass.txt#
[root@ansible:192.168.121.10 ~/ansible]$echo 'hello' > data.txt
[root@ansible:192.168.121.10 ~/ansible]$ansible-vault encrypt --vault-id=pass.txt data.txt
Encryption successful
[root@ansible:192.168.121.10 ~/ansible]$ansible-vault decrypt --vault-id=pass.txt data.txt
Decryption successful
# 先將劇本檔案進行加密,在執行的時候輸入密碼
[root@ansible:192.168.121.10 ~/ansible]$ansible-vault encrypt loop2.yaml --vault-id=pass.txt
Encryption successful
[root@ansible:192.168.121.10 ~/ansible]$ansible-playbook loop2.yaml --ask-vault-pass # 互動式輸入密碼
Vault password:
[root@ansible:192.168.121.10 ~/ansible]$ansible-playbook loop2.yaml --vault-id=pass.txt # 非互動式
十、sudo命令
- 一般用於普通使用者需要執行root許可權的命令
- 在web01上配置zhangsan擁有sudo許可權
# 普通使用者的sudo許可權要進行設定才能使用
# 配置檔案/etc/sudoers
# 我們在修改sudoers時,一般使用visudo去修改而不使用,vim。因為visudo具備語法檢查功能,如果你修改sudoers後,有語法錯誤,visudo會自動檢查出來
# 我們可以過濾出除註釋和空行的內容,方便檢視
[root@web01:192.168.121.11 ~]$grep -E -v "^#|^$" /etc/sudoers
Defaults !visiblepw
Defaults always_set_home
Defaults match_group_by_gid
Defaults always_query_group_plugin
Defaults env_reset
Defaults env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS"
Defaults env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
Defaults env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
Defaults env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
Defaults env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"
Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin
root ALL=(ALL) ALL
# 這裡的%代表wheel是一個使用者組,ALL表示可以使用sudo做任何提權操作
%wheel ALL=(ALL) ALL
# 我們可以將zhangsan加到這個組中
[root@web01:192.168.121.11 ~]$usermod -aG wheel zhangsan
[root@web01:192.168.121.11 ~]$id zhangsan
uid=1016(zhangsan) gid=1016(zhangsan) groups=1016(zhangsan),10(wheel)
# 這是zhangsan就具備了sudo提權許可權
# 給lisi設定sudo許可權,NOPASSWD表示在進行sudo時不輸入密碼
lisi ALL=(ALL) NOPASSWD:ALL
# 不給tom使用者ALL許可權
# 設定命令別名,tom只能執行允許的命令
Cmnd_Alias USER = /usr/sbin/useradd,/usr/sbin/usermod,/usr/sbin/userdel,/bin/passwd
tom ALL=(ALL) NOPASSWD:USER
十一、特殊的主機清單變數
- 如果遠端主機沒有使用免密登入,如果遠端主機ssh不是標準22埠,可以設定特殊的主機清單變數
- ansible_ssh_user:指定登入遠端主機的使用者名稱
- ansible_ssh_pass:指定登入遠端主機的密碼
- ansible_ssh_port:指定登入遠端主機的埠號
# 先取消免密登入,刪除遠端主機中的公鑰
[root@ansible:192.168.121.10 ~/ansible]$ansible all -m file -a "path=/root/.ssh/authorized_keys state=absent"
# 修改web01的ssh登入的埠號
vim /etc/ssh/sshd_config # sshd_config:是伺服器端的ssh配置檔案
vim /etc/ssh/ssh_config # ssh_config:是客戶端的ssh配置檔案
# 修改ssh連線埠為220,重啟服務
[root@web01:192.168.121.11 ~/.ssh]$echo 'Port 220' >> /etc/ssh/sshd_config
[root@web01:192.168.121.11 ~]$systemctl restart sshd
# 客戶端測試連結
[root@ansible:192.168.121.10 ~/ansible]$ssh 192.168.121.11
ssh: connect to host 192.168.121.11 port 22: Connection refused
[root@ansible:192.168.121.10 ~/ansible]$ssh 192.168.121.11 -p 220
root@192.168.121.11's password:
Hostname: web01
Date: 2024-06-27
Contact to: xuruizhao00@163.com
Last login: Thu Jun 27 18:36:10 2024 from 192.168.121.10
# 準備一個新的ansible目錄
[root@ansible:192.168.121.10 ~]$mkdir myansible
[root@ansible:192.168.121.10 ~]$cp ansible/ansible.cfg myansible/
[root@ansible:192.168.121.10 ~]$cd myansible/
[root@ansible:192.168.121.10 ~/myansible]$ll
total 4
-rw-r--r--. 1 root root 85 Jun 27 18:43 ansible.cfg
[root@ansible:192.168.121.10 ~/myansible]$vim inventory
[group1]
web01
web02
db
# 此時去使用ansible是不通的
# 設定主機清單變數
[group1]
web01 ansible_ssh_user=root ansible_ssh_pass=123 ansible_ssh_port=220
web02 ansible_ssh_user=root ansible_ssh_pass=123
db ansible_ssh_user=root ansible_ssh_pass=123