『Ansible 上手指南』

Ansible 上手指南

前言

最近在重構一款命令行工具,使用 golang 從新開發,但須要繼續維持原有的命令,同時增長新命令。node

在重構的過程當中,須要對現命令行工具和原命令行工具的命令輸出結果進行比對,確保徹底一致(項目要求),命令行工具須要在部署完成系統以後進行使用,每一個系統完成時的部署組件又稍微有點差別。因此其實須要在多套服務主機上進行測試。python

須要作這些動做:golang

  • 拷貝一些配置文件到主機上:用戶配置、IP和端口文件
  • 安裝命令行工具,確保使其在服務主機上可使用
  • 執行一堆測試命令

按理說,我不斷把須要的配置和二進制文件拷貝到主機上進行測試也能完成。web

但在使用的過程當中存在下面幾個問題:正則表達式

  • 測試發現,結果不對時須要及時修改代碼,再次拷貝二進制文件到主機上
  • 主機環境須要屢次推倒,從新部署,驗證版本更新問題
  • 須要手動一個一個命令的執行
  • 測試有幾套主機

看上去手動的方法,有點費勁。shell

目前我從事的工做就是 PaaS 部署相關的,部署層面的腳本的運行、組件的安裝、服務的啓動等都是使用 Ansible 來操做。具體的腳本編寫由其餘同事,我只知道這個東西是幹嗎的。沒實質性的學習。因而想借這個機會主動學習下 Ansible.編程

學習之處,差點犯了老問題,即:從頭開始看官方文檔,而不注重當前須要解決的問題。api

由於其實整個 Ansible 的內容體系不少。不注重當前須要解決的問題,會致使你抓不住重點。數組

意識到後專一在當前須要解決的問題上:安全

  • 拷貝配置文件和安裝腳本到多個主機上
  • 在多個主機上測試命令行工具

Ansible

看了上面的事件背景,你大概知道這個 Ansible 究竟是個什麼東西。

Ansible 是一個配置管理和應用部署工具,即在管理主機上操做一些命令就能在節點主機上進行相應的動做。由 Python 編寫,由模塊化組成,即執行動做的實體,在 ansible 上都是靠着相應的模塊執行動做,好比拷貝 copy 模塊、執行 command 模塊、shell 模塊、文件 file 模塊等。

Ansible 的目標有以下:

  • 自動化部署應用
  • 自動化管理配置
  • 自動化的持續交付
  • 自動化的(AWS)雲服務管理。

原理

管理主機從 hosts 裏讀取主機清單,經過 playbook 按順序同時對管理的主機進行相應的操做。

如圖:

示意圖.png

示意圖.png

管理主機主要是對主機的定義和配置、編寫 playbook(即節點主機的執行動做)。

運行:

1. 命令行

ansible all -m ping 
複製代碼

2. playbook

ansible-playbook example.yml

複製代碼

主機清單

編輯文件:/etc/ansible/hosts

即:定義主機名稱,變量等

主機的變量包括什麼: 主機的執行用戶、鏈接端口、密碼等

相似於 ini 格式的文件

[test-new-cli]
10.62.60.72

[test-old-cli]
10.62.62.88

複製代碼

上面的例子:將兩個主機的分爲兩組:test-new-clitest-old-cli

主機的變量有這麼些:

  • ansible_ssh_host 將要鏈接的遠程主機名.與你想要設定的主機的別名不一樣的話,可經過此變量設置.

  • ansible_ssh_port ssh端口號.若是不是默認的端口號,經過此變量設置.

  • ansible_ssh_user 默認的 ssh 用戶名

  • ansible_ssh_pass ssh 密碼(這種方式並不安全,咱們強烈建議使用 --ask-pass 或 SSH 密鑰)

  • ansible_sudo_pass sudo 密碼(這種方式並不安全,咱們強烈建議使用 --ask-sudo-pass)

  • ansible_sudo_exe (new in version 1.8) sudo 命令路徑(適用於1.8及以上版本)

  • ansible_connection 與主機的鏈接類型.好比:local, ssh 或者 paramiko.

  • ansible_ssh_private_key_file ssh 使用的私鑰文件.適用於有多個密鑰,而你不想使用 SSH 代理的狀況.

  • ansible_shell_type 目標系統的shell類型.默認狀況下,命令的執行使用 'sh' 語法,可設置爲 'csh' 或 'fish'.

  • ansible_python_interpreter 目標主機的 python 路徑.

看不懂怎麼用:

舉個例子,你想鏈接主機 192.168.100.100 , 切換到 root 用戶下執行相應的操做。

若是你直接ssh username@192.168.100.100 會要求你輸入用戶名和密碼。

假如我編輯主機清單使得本身不須要輸入用戶名密碼,怎麼操做?

[test-new-cli]
example ansible_ssh_host=192.168.100.100 ansible_ssh_user=username ansible_ssh_pass=root

複製代碼

即配置好192.168.100.100 的主機別名爲example, 主機的用戶名和密碼爲:username/root

Yaml

包含三種類型:

  • 鍵值對:key: value
  • 數組
  • 純量:整型、字符串、布爾型

這個很好理解:若是你熟悉Python, 這三種類型就至關於:map, list, 變量

若是你熟悉golang, 這三種類型就至關於: map, 數組, 變量

示例:

---
- name: "execute command nodepool node list {{item.name}}"
  shell: "{{item.cli}} nodepool node list {{item.id}}"
  register: result
- name: show result
  debug:
    msg: "{{result.stdout_lines}}"
  with_items:
    - { name: "new-cli", cli: "new-cli", id: "1" }
    - { name: "old-cli", cli: "old-cli", id: "1" }

複製代碼

模塊

Ad-doc

ansible 命令行式,適合執行單條命令。

# 操做 192.168.100.100 主機,看管理主機是否和192.168.100.100的主機連通

ansible example -m ping

# 操做 192.168.100.100 主機,拷貝管理主機下的/root/opcli/conf 文件至節點主機/etc/opcli/conf 下
ansible test-new-cli -m copy -a="src=/root/opcli/conf dest=/etc/opcli/conf"

複製代碼
  • m: 模塊
  • a: 接參數

能夠看出適合執行單條命令

Patterns

假如你的節點主機分組不少了,Ad-hoc 如何選擇特定特徵的節點主機分組呢?

使用類正則表達式。

好比觸發全部節點主機進行動做:

ansible all -m ping
ansible * -m ping

二者等價,都是選擇全部的節點主機
複製代碼

示例:

1. 主機別名或者IP
one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*

複製代碼
2. 一個或多個groups
webservers
webservers:dbservers

複製代碼
3. 排除一個組
webservers:!phoenix 
# 隸屬 webservers 組但同時不在 phoenix組

複製代碼
4. 兩個組的交集
webservers:&staging
# 同時隸屬於 webservers 和 staging 組
複製代碼
5. 列表
webservers[0]
webservers[0-25]

複製代碼
6. 其餘

有什麼需求,看官方文檔吧。

Playbook

編寫 yaml 文件,適合執行多步操做的複雜操做。能夠當作是Ad-doc 命令的集合。甚至能夠當作是一門編程語言。

執行:ansible-playbook example.yml

按照 example.yml 文件裏的任務集合按步執行任務。

示例

命令示例,僅舉幾例,有帶參數、有沒帶參數的。

咱們最終的目標是:在節點主機上執行這些命令進行比對二者結果。

目錄:

demo-for-ansible:
--- nodepool:
    nodepool-list.yml
    nodepool-node-list.yml
--- node:
    node-list.yml
    node-show.yml
--- task/task-list.yml
--- main.yml



複製代碼

新版本:

命令 說明
command-cli nodepool list 查詢資源池
command-cli nodepool node list 查詢資源池節點
command-cli node list 查詢節點
command-cli node show 查詢某個節點
command-cli task list 查詢部署任務

...

舊版本:

命令 說明
old-cli nodepool list 查詢資源池
old-cli nodepool node list 查詢資源池節點
old-cli node list 查詢節點
old-cli node show 查詢某個節點
old-cli task list 查詢部署任務

...

第一步:編寫主機清單

/etc/ansible/hosts

[test_client]
192.168.100.100 ansible_ssh_user=xiewei ansible_ssh_pass=root ansible_connection=ssh
192.168.100.101 ansible_ssh_user=xiewei ansible_ssh_pass=root ansible_connection=ssh
192.168.100.102 ansible_ssh_user=xiewei ansible_ssh_pass=root ansible_connection=ssh

複製代碼

定義主機鏈接類型、用戶名、密碼

第二步:編寫 yaml 文件

主要動做:

  • 在節點主機上建立兩個文件夾: /etc/client/conf/et/client/commands
  • 拷貝管理主機目錄:/etc/client/conf 文件至節點主機: /etc/client/conf
  • 拷貝管理主機二進制文件:/root/gosrc/src/client/command-cli 至節點主機 /etc/client/commands
  • 軟鏈接節點主機二進制文件:/etc/client/commands/command-cli 至節點主機 /usr/bin/command-cli
  • 執行上表中查詢命令:nodepool, node, task

main.yml

---
- hosts: test_client
  remote_user: root
  become: yes
  become_user: root
  tasks:
    # 在節點主機上建立目錄:/etc/client/conf
    - name: create /etc/client/conf /etc/client/commands
      file:
        path: "/etc/client/{{item}}"
        owner: root
        group: root
        mode: 0755
        state: directory
      with_items:
      - "conf"
      - "commands"
    # 軟鏈接到 /usr/bin/command-cli
    - name: link  /etc/client/commands
      file: src="/ect/client/commands" dest="/usr/bin/command-cli" state=link

    # 拷貝管理主機配置文件/etc/client/conf和二進制文件至 /etc/client/conf, /etc/client/commands
    - name: copy /etc/client/conf
      copy: src="{{ itme.src }}" dest="{{ item.dest }}" owner=root group=root mode=0644
      with_items:
      - { src: "/etc/client/conf", dest: "/etc/client/conf" }
      - { src: "/root/gosrc/src/client/command-cli", dest: "/etc/client/commands"}

    # nodePool list
    - include_tasks: "/nodepool/nodepool-list.yml"
      with_items:
      - { client: "new client", name: "command-cli"}
      - { client: "old client", name: "old-cli"}

    # nodePool node list <id>
    - include_tasks: "/nodepool/nodepool-node-list.yml"
      with_items:
      - { id: "1", client: "new client", name: "command-cli"}
      - { id: "1", client: "old client", name: "old-cli"}

    # node list
    - include_tasks: "node/node-list.yml"
      with_items:
      - { client: "new client", name: "command-cli"}
      - { client: "old client", name: "old-cli"}

    # node show <id>
    - include_tasks: "node/node-show.yml"
      with_items:
      - { client: "new client", name: "command-cli", id: 1}
      - { client: "old client", name: "old-cli", id: 1}

    # task list
    - include_tasks: "task/task-list.yml"
      with_items:
      - { client: "new client", name: "command-cli"}
      - { client: "old client", name: "old-cli"}



複製代碼

task-list.yml

---
- name: "execute command task list by {{ item.client}}"
  shell: "{{item.name}} task list"
  register: result
- name: show result
  debug:
    msg: "{{result.stdout_lines}}"

複製代碼

第三步: 檢查語法

兩種方法

ansible-playbook main.yml --syntax-check

複製代碼

先安裝 pip install ansible-lint

ansible-lint main.yml

複製代碼

第四步: 執行

ansible-playbook main.yml

複製代碼

整個的編寫流程大概是這樣。核心是編寫 yml 文件,調用 ansible 支持的各類模塊完成任務。

下一步

  1. 熟悉 playbook
  2. 熟悉 ansible 模塊
  3. 熟悉 ansible api

關注你當前須要解決的問題,切入學習,事半功倍。

相關文章
相關標籤/搜索