Ansible 免密登录与主机清单配置
Ansible 通過 SSH 協議免密登錄遠程主機
安裝好 ansible 后,第一件事當然是連接上遠程主機。
1. 批量掃描主機指紋
ansible 使用 ssh 協議登錄遠程主機進行操作,我想用過 ssh user@host 命令的都知道,首次登錄遠程主機時都會有如下提示:
ryan@RYAN-MI-DESKTOP:~$ ssh user@github.com
The authenticity of host 'github.com (13.250.177.223)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'github.com,13.250.177.223' (RSA) to the list of known hosts.
這里會要求你輸入 yes 將主機指紋保存到本地,是一種安全措施,防止在遇到 DNS 污染或 IP 沖突等異常情況時,目標主機被冒名頂替。
Ansible 默認情況下也會使用這個指紋對主機進行驗證,因此我們希望能夠快速地掃描出所有主機的指紋,這里使用 ssh-keyscan 命令:
echo "
192.168.58.131
192.168.58.132
192.168.58.133
" > my-hosts
ssh-keyscan -f my-hosts >> ~/.ssh/known_hosts
# 或者添加 -H 參數,只保存主機 IP/域名的 hash 值,更安全
ssh-keyscan -H -f my-hosts >> ~/.ssh/known_hosts
2. 設置免密登錄
大量的遠程主機都使用同一個密碼提供 ssh 遠程登錄是很不安全的,一般都建議所有主機都只開啟私鑰登錄,禁用密碼登錄。相關配置在主機的 /etc/ssh/sshd_config 中,詳細配置方法請自行搜索。
首先你需要在本地通過 ssh-keygen 命令生成好公私鑰,默認使用 rsa 算法。
如果你是使用的虛擬機,可以基于同一個 ova 鏡像創建所有虛擬機,一開始就把運維賬號(如 ops)和公鑰打包在 ova 中。
或者你可以在安裝所有主機時,給所有遠程主機都打開密碼登錄,然后通過 ansible 來批量添加 ssh 公鑰到所有主機上,流程如下:
首先編寫一個名叫 add-sshkey.yml 的 playbook(playbook 將在后面詳細介紹):
---
- hosts: all # 使用 inventory 中的所有主機
gather_facts: false
remote_user: root # 使用這個賬號登錄遠程主機
tasks:
- name: install ssh key
authorized_key: # 查看該 module 的文檔:`ansible-doc authorized_key`
user: root # 給遠程主機上的這個用戶添加公鑰。建議不要直接使用 root 賬號(可以用 ops)
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" # 也可以使用 url,這樣公鑰可以直接放 nginx 上掛著,更方便。
state: present
然后用如下命令運行這個 playbook,輸入密碼,就能在所有遠程主機上添加好 ssh 公鑰:
# --inventory 指定主機清單,就用我們之前進行 ssh-keyscan 時用的那個文件就行
# --ask-pass 可以讓我們交互式地輸入主機密碼(所有主機的密碼必須相同)
ansible-playbook --inventory my-hosts --ask-pass ssh-addkey.yml
ansible 使用
/etc/ansible/hosts文件作為它的默認 inventory 主機清單,但是我比較追求「基礎設施即代碼」,
為了將這個 hosts 文檔和相關代碼/文檔放在一起,提交到 git 倉庫保存,我推薦每次都使用-i [hosts_file]的方式指定 inventory 主機清單。
如果各主機的 ssh 端口、密碼等參數不一致,就需要在 my-hosts 中設定更詳細的參數,詳見 Ansible Docs - intro_inventory
3. 開始愉快地玩耍
OK,現在免密登錄就配好了,可以愉快地用 Ansible 玩耍了。
簡單地進行下測試:
# ansible [pattern] -m [module] -u [remote user] -a "[module options]"
# -u root # 使用 root 賬戶登錄遠程主機,這個對應前面 playbook 中的 remote_user
# all # [pattern],all 表示選中 my-hosts 中的所有主機
# -m [module] # 指定使用的 ansible 模塊,默認使用 `command`,即在遠程主機上執行 -a 參數中的命令
# -a "ls -al" # 指定 module 的參數,這里是提供給 `command` 模塊的參數。
ansible -u root -i my-hosts all -a "ls -al"
# 或者使用 ansible-console 交互式執行命令,更適合愉快地游玩hhh
ansible-console -i my-hosts all -u root
4. inventory 主機清單
前面給出的 inventory 只是非常簡單的 IP 地址列表。
可如果我們不同的主機有不同的 ssh 端口號、ssh 密鑰,或者不同的用戶等等,那這樣一個簡單的 IP 列表就不夠用了。
為了解決這個問題,我們需要使用更高級的 inventory 語法,以對主機進行分類,對不同類別的主機配置不同的參數。
ini 格式的配置舉例如下:
# 給服務器分組,組名只能用 [a-zA-Z0-9_]
[databases]
# 指定一個數字范圍
192.168.1.1[01:50]
[k8s_cluster]
# 指定一個字母表范圍
worker[01:30].k8s.local
worker-[a:h].k8s.local
# k8s-cluster 組的公用參數
[k8s_cluster:vars]
ntp_server=ntp.local
proxy=proxy.local
[app]
# 給服務器指定別名(git),通過關鍵字參數指定其他參數
git ansible_host=git.local ansible_port=225 ansible_ssh_private_key_file=<path/to/git-server-ssh>
# 使用指定的賬號密碼(危險!)
tester ansible_host=tester.local ansible_user=root ansible_password=xxx
另外也可以使用 yaml 格式配置 inventory 主機清單,上面的 ini 配置寫成 yaml 格式是這樣的:
---
databases:
hosts: 192.168.1.1[01:50]
k8s_cluster:
hosts: # 沒有別名的服務器
worker[01:30].k8s.local:
worker-[a:h].k8s.local:
vars: # 公共的參數
ntp_server: ntp.local
proxy: proxy.local
app:
hosts:
git: # 服務器別名
ansible_host: git.local # 如果未定義這個,默認以「別名」為 host。(在這里就是 git)
ansible_port: 225
ansible_ssh_private_key_file: <path/to/git-server-ssh>
tester:
ansible_host: tester.local
ansible_user: root
ansible_password: xxx # 危險!盡量不要寫明文密碼
寫好配置后,可以通過如下命令驗證并查看你的配置:
ansible-inventory -i xxx.yml --list --yaml
該命令會提示出你錯誤的配置,并且打印出最終得到的 yaml 配置內容。
批量掃描主機指紋
驗證通過后,就可以通過 ansible/ansible-playbook/ansible-console 愉快地玩耍了么?很遺憾的是——不行。
我們在前面使用不帶任何參數的文檔作為 inventory 時,因為 ssh-keyscan 也能解析它,所以我們很方便地就完成了主機指紋的批量掃描。
但是現在我們的 inventory 變得很復雜了,ssh-keyscan 解析不了它了,該如何去批量掃描主機指紋呢?難道幾十上百臺服務器的指紋,我必須得手動一個個去添加?!
答案是可以批量加,最簡單有效的方法,是使用如下命令:
# 使用環境變量 ANSIBLE_HOST_KEY_CHECKING 臨時關閉主機指紋檢查
ANSIBLE_HOST_KEY_CHECKING=false ansible -i inventory.yaml all -m ping
經測試,不論成功與否,ping 模塊都會自動將所有主機的指紋添加到 known_hosts 中。
但是在 ping 的文檔里沒有講到這個功能,這算是未定義行為。
其他方法:
網上有很多文檔會教你修改 /etc/ansible/ansible.cfg 以關閉指紋的驗證,但是這是很危險的操作!你可能會連接到了黑客偽造的主機!
參考中有個問答,里面有人提供了一個 playbook 批量添加指紋,但是該方法不支持「主機別名」!
該 playbook 會將別名當作 host 解析,根本不理會 ansible_host 參數。
另外測試發現它用到了 ansbile 的 local 連接,而這種用法在 wsl1(ubuntu) 上無法使用,會報權限錯誤。。
自己寫個小腳本讀取 ansible-inventory -i xxx.yml --list 輸出的 json,將它轉換成 ssh-keyscan 可讀的文本。
參考
ansible ssh prompt known_hosts issue
host-key-checking - ansible docs
總結
以上是生活随笔為你收集整理的Ansible 免密登录与主机清单配置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [网络收集]DBHelper 常用数据库
- 下一篇: 如何进入Google工作? Google