今天會透過 ShellScript 來部署 SSH Public Key 到各 Host 上
完成後透過 Ansible 來大量處理 Node-Exporter 的安裝
最後用 Prometheus 來檢視一下 Metric 是否成功
待會 ansible 會透過 SSH 來進行操作
所以這邊來生個 SSH Private/Public KeyPair 來簡化驗證流程
ssh-keygen

ssh-copy-id root@<remote-ip>

這樣子就成功把 Bastion 公鑰上傳到另一台 Linux 上了
但如果有上百台 Linux 準備被納管 這不是會輸入到累死嗎?
這時就可以用 shell 來幫助我們來進行大量操作(為避免 A:我要先使用 ansible 來匯入 ssh key 驗證ansible
B:那就用 ansible 匯入 的迴圈所以跑去用 shell
這邊要多安裝 expect 來自動跑交互式命令的輸入密碼給 ssh-copy-id 做驗證
apt-get install -y expect
用 APT 安裝好後就來處理 Shell Code 吧
#!/bin/bash
read -s PWD
hosts=("5" "6" "101" "102" "103") # Host IP need to add ssh key.
for i in "${hosts[@]}"; do
        /usr/bin/expect <<EOT
        set timeout 1
        spawn ssh-copy-id root@10.0.0.$i
        expect "Password will auto fill in"
        send "$PWD\n"
        expect EOF
EOT
done
稍微解釋一下
read -s PWD 是將 ssh-copy-id 要用的密碼輸入進入 shell 存為 PWD 這個變數hosts=("5" "6"...) 是將要存放公鑰的 Server IP 存入 hosts 陣列 待會使用 for 來讀取set timeout 1 是為了減少 expect 運行的等待時間大致上是這個樣子 下方是 shell 執行的結果
root@router:~# bash ssh-copy-id.bash
spawn ssh-copy-id root@10.0.0.5
/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
root@10.0.0.5's password:
Number of key(s) added: 1
Now try logging into the machine, with:   "ssh 'root@10.0.0.5'"
and check to make sure that only the key(s) you wanted were added.
spawn ssh-copy-id root@10.0.0.6
......
先在 Bastion 上裝 Ansible 吧
apt-get install -y ansible
mkdir /etc/ansible
接著要寫 Ansible 腳本(Playbook) 來執行待會安裝 node-exporter 的流程
這邊先來寫 Ansible 的基本設定 透過 /etc/ansible/ansible.cfg 來指定
這邊設定 Ansible 的 Inventory 路徑和 remote_user 為 root
nano /etc/ansible/ansible.cfg
[defaults]
    inventory = ./inventory
    remote_user = root
    ask_pass = false
這邊透過 Inventory 來指定 Group 的成員
prometheus_node_exporter_inst 是正式安裝的對象tester 是專門開來測試用的群組 (雖然可以 --check 來 dry run :Dnano /etc/ansible/inventory
[prometheus_node_exporter_inst]
    lcr.ironman.test
    ipam.ironman.test
    lke-main.ironman.test
    lke-node1.ironman.test
    lke-node2.ironman.test
[tester]
    10.0.0.6
接著就是 Ansible 的 Playbook 本體
透過 hosts 來指定要被操作的群組 / IP 這邊先用 tester 來做測試
這一個 playbook 有兩個 play 會執行
第一個 play 主要是安裝 prometheus-node-exporter 詳細的操作如下
第二個 play 是用來 local 端測試服務正不正常
---
- name: Install_prometheus_node_exporter_to_servers
  hosts: tester
  tasks:
    - name: update apt package list
      ansible.builtin.apt:
        update_cache: yes
    - name: Install prometheus node-exporter
      ansible.builtin.apt:
        name: prometheus-node-exporter
        state: present
    - name: Install curl
      ansible.builtin.apt:
        name: curl
        state: present
    - name: Make sure a service unit is running and startup when booting
      ansible.builtin.systemd_service:
        name: prometheus-node-exporter
        state: started
        enabled: true
- name: check localhost:9100 from localhost
  hosts: tester
  tasks:
    - name: Check if 'Node Exporter' string exists in localhost:9100/metric
      shell: curl -s http://localhost:9100/metric | grep "Node Exporter"
      register: grep_result
      ignore_errors: yes
    - name: Show result
      debug:
        msg: "node-exporter successful"
      when: grep_result.rc == 0
    - name: Show result if string is not found
      debug:
        msg: "node-exporter failure"
      when: grep_result.rc != 0
測試執行結果
最終執行結果
這邊在第一次執行時遇到 ssh host key 衝突導致執行失敗 ==
最後來 Prometheus 伺服端把設定 Key 上去
再到網頁端確認結果就結束了
打開 prometheus 的設定檔
nano /etc/prometheus/prometheus.yml
job_name 設成可辨識的名字targets 設成對象的 IP- job_name: 'router'
  static_configs:
    - targets: [ 'router.ironman.test:9100' ]
- job_name: 'lcr'
  static_configs:
    - targets: [ 'lcr.ironman.test:9100' ]
- job_name: 'ipam'
  static_configs:
    - targets: [ 'ipam.ironman.test:9100' ]
- job_name: 'lke-main'
  static_configs:
    - targets: [ 'lke-main.ironman.test:9100' ]
- job_name: 'lke-node1'
  static_configs:
    - targets: [ 'lke-node1.ironman.test:9100' ]
- job_name: 'lke-node2'
  static_configs:
    - targets: [ 'lke-node2.ironman.test:9100' ]
接著回到 Prometheus 的網頁上
這次使用 node_memory_MemAvailable_bytes 來看看現在哪台 VM 的 RAM 最閒 欠砍RAM Size
非常成功!
其實官方就有自己的 Ansible Role 可以使用
但秉持著 DIY(Destroy It Youself) 的精神這邊還是用自己寫的了