Nebula Graph 的 Ansible 實踐

本文首發於 Nebula Graph 公衆號 NebulaGraphCommunity,Follow & 看大廠圖數據庫技術實踐html

Nebula Graph 的 Ansible 實踐

背景

在 Nebula-Graph 的平常測試中,咱們會常常在服務器上部署 Nebula-Graph。爲了提升效率,咱們須要一種工具,能幫咱們作到快速部署,主要的需求:python

  • 可使用非 root 帳戶部署 Nebula Graph,這樣咱們能夠針對這個用戶設置 cgroup 作資源限制。
  • 能夠在操做機上更改配置文件,而後分發到部署的集羣上,方便咱們作各類調參的測試。
  • 可使用腳本調用,方便之後咱們繼承在測試的平臺或工具上。

工具選擇上,早期有 Fabric 和 Puppet,比較新的工具備 Ansible 和 SaltStack。git

Ansible 在 GitHub 上有 40K+ star, 並且在 2015年被 Red Hat 收購,社區比較活躍。不少開源項目都提供了 Ansible 的部署方式,好比 Kubernetes 中的 kubespray和 TiDB 中的 tidb-ansiblegithub

綜合下來,咱們使用 Ansible 來部署 Nebula Graph。shell

Ansible 介紹

特色

Ansible 是開源的,自動化部署工具(Ansible Tower 是商業的)。具備如下的幾個特色:數據庫

  • 默認協議是基於 SSH,相比於 SaltStack不 須要額外部署 agent。
  • 使用 playbook, role, module 來定義部署過程,比較靈活。
  • 操做行爲冪等。
  • 模塊化開發,模塊比較豐富。

優缺點比較明顯api

  • 使用 SSH 協議,優勢是大多數機器默認只要有帳號密碼就能夠經過 Ansible 完成部署,而缺點性能上會差一些。
  • 使用 playbook 來定義部署過程,Python 的 Jinja2 做爲模板渲染引擎,對於熟悉的人來講會比較方便,而對於沒有使用過的人,會增長學習成本。

綜上,適用於小批量機器的批量部署,不須要關心額外部署 agent 的場景,和咱們的需求比較匹配。安全

部署邏輯

一般爲了離線部署,能夠把機器分爲 3種角色。bash

  • Ansible 執行機:運行 Ansible 的機器,須要能經過 SSH 連到全部機器。
  • 有外網的資源機:運行須要鏈接外網的任務,好比下載 RPM 包。
  • 服務器:即運行服務的服務器,能夠網絡隔離,經過執行機來部署

Nebula Graph 的 Ansible 實踐

任務邏輯

Ansible 中,主要有三種層次的任務:服務器

  • Module
  • Role
  • Playbook

Module 分爲 CoreModule 和 CustomerModule,是 Ansible 任務的基本單元。

在運行任務的時候,首先 Ansible 會根據 module 的代碼,將參數代入,生成一個新的 Python 文件,經過 SSH 放到遠程的 tmp 文件夾,而後經過 SSH 遠程執行 Python 將輸出結果返回,最後把遠程目錄刪除。

Nebula Graph 的 Ansible 實踐

# 設置不刪除 tmp 文件
export ANSIBLE_KEEP_REMOTE_FILES=1
 # -vvv 查看 debug 信息
ansible -m ping all -vvv
<192.168.8.147> SSH: EXEC ssh -o ControlMaster=auto -o ControlPersist=30m -o ConnectionAttempts=100 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="nebula"' -o ConnectTimeout=10 -o ControlPath=/home/vesoft/.ansible/cp/d94660cf0d -tt 192.168.8.147 '/bin/sh -c '"'"'/usr/bin/python /home/nebula/.ansible/tmp/ansible-tmp-1618982672.9659252-5332-61577192045877/AnsiballZ_ping.py && sleep 0'"'"''
複製代碼

能夠看到有這樣的日誌輸出,AnsiballZ_ping.py 就是根據 module 生成的 Python 文件,能夠登陸到那臺機器,執行 Python 語句看一下結果。

python3 AnsiballZ_ping.py

#{"ping": "pong", "invocation": {"module_args": {"data": "pong"}}}
複製代碼

返回了運行 Python 文件的標準輸出,而後 Ansible 再對返回的結果作額外處理。

Role 是串聯 module 的一系列任務,能夠經過 register 來傳遞上下文參數。

典型例子:

  1. 建立目錄
  2. 若是建立目錄成功,繼續安裝,不然退出整個部署工程。

Playbook 是組織部署機器和 role 之間的關聯。

經過在 inventory 對不一樣機器進行分組,對不一樣分組使用不一樣的 role 來部署,完成很是靈活的安裝部署任務。

當 playbook 定義好以後,不一樣的環境,只要變動 inventory 中的機器配置,就能夠完成同樣的部署過程。

模塊定製

自定義 filter

Ansible 使用 Jinja2 做爲模板渲染引擎,能夠用 Jinja2 自帶的 filter ,好比

# 使用 default filter,默認輸出 5

ansible -m debug -a 'msg={{ hello | default(5) }}' all
複製代碼

有時候,咱們會須要自定義的 filter 來操做變量,典型的場景就是 nebula-metad 的 地址 --meta_server_addrs

  • 當只有 1 個 metad 的時候,格式是 metad1:9559
  • 當有 3 個 metad 的時候,格式是 metad1:9559,metad2:9559,metad3:9559

在 ansible playbook 的工程下,新建 filter_plugins 目錄,建立一個 map_fomat.py Python文件,文件內容:

# -*- encoding: utf-8 -*-
from jinja2.utils import soft_unicode

def map_format(value, pattern):
    """ e.g. "{{ groups['metad']|map('map_format', '%s:9559')|join(',') }}" """
    return soft_unicode(pattern) % (value)

class FilterModule(object):
    """ jinja2 filters """
    def filters(self):
        return {
            'map_format': map_format,
        }
複製代碼

{{ groups['metad']|map('map_format', '%s:9559')|join(',') }} 即爲咱們想要的值。

自定義 module

自定義 module 須要符合 Ansible 框架的格式,包括獲取參數,標準返回,錯誤返回等。

寫好的自定義 module,須要在 ansible.cfg 中配置 ANSIBLE_LIBRARY,讓 ansible 可以獲取到。

具體參考官網:ansible-docs.readthedocs.io/zh/stable-2…

Nebula Graph 的 Ansible 實踐

由於 Nebula Graph 自己啓動並不複雜,使用 Ansible 來完成 Nebula-Graph 的部署十分簡單。

  1. 下載 RPM 包。
  2. 複製 RPM 包到部署機,解壓後,放到目的文件夾。
  3. 更新配置文件。
  4. 經過 shell 啓動。

使用通用的 role

Nebula Graph 有三個組件,graphd、metad、storaged,三個組件的命名和啓動使用同樣的格式,可使用通用的 role,graphd、metad、storaged 分別引用通用的 role。

一方面更容易維護,另外一方面部署的服務更有細粒度。好比 A B C 機器部署 storaged, 只有 C 機器部署 graphd,那 A B 機器上,就不會有 graphd 的配置文件。

# 通用的 role, 使用變量 install/task/main.yml
- name: config {{ module }}.conf
  template:
    src: "{{ playbook_dir}}/templates/{{ module }}.conf.j2"
    dest: "{{ deploy_dir }}/etc/{{ module }}.conf"
    
# graphd role,將變量傳進來 nebula-graphd/task/main.yml
- name: install graphd
  include_role:
    name: install
  vars:
    module: nebula-graphd
複製代碼

在 playbook 中,graphd 的機器組來運行 graphd 的 role,若是 A B 不在 graphd 的機器組,就不會將 graphd 的配置文件上傳。

這樣部署後,就不能使用 Nebula-Graph 的 nebula.service start all 來所有啓動,由於有的機器上會沒有 nebula-graphd.conf 的配置文件。相似的,能夠在 playbook 中,經過參數,來指定不一樣的機器組,傳不一樣的參數。

# playbook start.yml
- hosts: metad
  roles:
    - op
  vars:
    - module: metad
    - op: start

- hosts: storaged
  roles:
    - op
  vars:
    - module: storaged
    - op: start

- hosts: graphd
  roles:
    - op
  vars:
    - module: graphd
    - op: start
複製代碼

這樣會至關於屢次 ssh 去執行啓動腳本,雖然執行效率沒有 start all 更好,可是服務的啓停會更爲靈活。

Nebula Graph 的 Ansible 實踐

使用 vars_prompt 結束 playbook

當只想更新二進制,不想刪除數據目錄的時候,

能夠在 remove 的 playbook 中,添加 vars_prompt 二次確認,若是二次確認了,纔會刪除數據,不然會退出 playbook。

# playbook remove.yml
- hosts: all
  vars_prompt:
    - name: confirmed
      prompt: "Are you sure you want to remove the Nebula-Graph? Will delete binary only  (yes/no)"
 
  roles:
    - remove
複製代碼

而在 role 裏,會校驗二次確認的值

# remove/task/main.yml
---
- name: Information
  debug:
    msg: "Must input 'yes', abort the playbook "
  when:
    - confirmed != 'yes'

- meta: end_play
  when:
    - confirmed != 'yes
複製代碼

效果如圖,刪除時能夠二次確認,若是不爲 yes,就會取消執行此次的 playbook,這樣能夠只刪除二進制,而不刪除 nebula 集羣的數據。

Nebula Graph 的 Ansible 實踐

交流圖數據庫技術?加入 Nebula 交流羣請先填寫下你的 Nebulae 名片,Nebula 小助手會拉你進羣~~

推薦閱讀

相關文章
相關標籤/搜索