Upgrade to Pro — share decks privately, control downloads, hide ads and more …

OpenStackをAnsibleで操る! - Ansible Night in Tokyo 2017.12

OpenStackをAnsibleで操る! - Ansible Night in Tokyo 2017.12

Ansible Night in Tokyo 2017.12
https://ansible-users.connpass.com/event/71613

Noboru Iwamatsu

December 21, 2017
Tweet

More Decks by Noboru Iwamatsu

Other Decks in Technology

Transcript

  1. 自己紹介  FUJITSU Cloud Service K5の開発チームメンバー サービス・運用・構築の設計から実装までを担当 1 Copyright 2017

    FUJITSU LIMITED 岩松 昇 下國 治 本田 亮弘  OS・仮想化・クラウドの研究からIaaS事業部門へ  Xen, OpenStackなどOSSと10年以上の付き合い  最近はOpenStack kolla/kolla-ansibleに貢献  並列分散処理・クラウドの研究から事業部門へ  扱うマシンの量は、20年前の1000倍  10年前はexpectを使ってた。つらかった  ここ7年ほどはクラウド周辺技術が主な業務  Chefからの移行組  下の子が深夜に徘徊するのが最近の悩み
  2. 本日のAgenda FUJITSU Cloud Service K5 とリリース業務 Ansible Tips & Examples

    適用版数を厳密に守る 手順を間違えない 適用対象を間違えない 履歴をのこす まとめ 2 Copyright 2017 FUJITSU LIMITED
  3.  世界9リージョンで提供中のIaaS  OpenStack がベース  月間数百件のリリース業務をこなす FUJITSU Cloud Service

    K5 5 Copyright 2017 FUJITSU LIMITED JP-east-1 JP-east-2 UK Nordic Germany Spain US Australia Singapore Available Region New Region (planning) JP-west-2 JP-west-1
  4. 典型的なリリース業務  OpenStack CLIを駆使して、状態・正常性を確認 しながら手順書通りに行う高度な作業 6 Copyright 2017 FUJITSU LIMITED

    新機能提供・機能修正のため、サービス全体を 停止せず、ソフトウェアを更新する LB nova nova 切り離す LB nova nova LB nova nova 更新 復帰 LB nova nova 繰り返し
  5. リリース業務: Before Ansible 8 Copyright 2017 FUJITSU LIMITED ※写真はイメージです 適用版数

    指さし確認 手順書  行確認、指さし確認 適用対象 指さし確認 作業履歴  ターミナルログ
  6. 例: Ansibleをインストールする場合 12 Copyright 2017 FUJITSU LIMITED Dependencies Resolved ===============================================================================

    Package Arch Version Repository Size =============================================================================== Installing: ansible noarch 2.4.1.0-1.el7 extras 7.6 M Installing for dependencies: python-cffi x86_64 1.6.0-5.el7 base 218 k python-enum34 noarch 1.0.4-1.el7 base 52 k python-httplib2 noarch 0.9.2-1.el7 extras 115 k python-idna noarch 2.4-1.el7 base 94 k python-ipaddress noarch 1.0.16-2.el7 base 34 k python-paramiko noarch 2.1.1-2.el7 extras 267 k python-passlib noarch 1.6.5-2.el7 extras 488 k python-ply noarch 3.4-11.el7 base 123 k python-pycparser noarch 2.14-1.el7 base 104 k python2-cryptography x86_64 1.7.2-1.el7_4.1 updates 502 k python2-jmespath noarch 0.9.0-3.el7 extras 39 k python2-pyasn1 noarch 0.1.9-7.el7 base 100 k sshpass x86_64 1.06-2.el7 extras 21 k Transaction Summary =============================================================================== Install 1 Package (+13 Dependent packages)  依存関係で色々インストールされる
  7. パッケージ版数を厳密に管理する Copyright 2017 FUJITSU LIMITED 世代1 B C A 13

    世代2 B C A’ D 世代3 B’ C A’ D Aをアップデート Dをインストール Bをアップデート
  8. ダメな例(1) Copyright 2017 FUJITSU LIMITED 世代1 B C A 14

    世代2 B C A’ D Aをアップデート Dをインストール 世代2 B C A’ D E ダメなやつ
  9. ダメな例(2) Copyright 2017 FUJITSU LIMITED 世代1 B C A 15

    世代2 B C A’ D Aをアップデート Dをインストール 世代2 B’ C A’ D ダメなやつ
  10. 我々のやり方  意図しないパッケージの混入を把握・対応する 1. パッケージとバージョンのリストを用意 2. インストール前後のパッケージ一覧を取得 3. 比較 16

    Copyright 2017 FUJITSU LIMITED rpm_packages: - name: curl version: 7.29.0-42.el7 - name: dhcp-common version: 4.2.5-58.el7.centos - … # rpm -qa {{ list1 | difference(list2) }}
  11. パッケージリストの比較例 17 Copyright 2017 FUJITSU LIMITED - name: Difference from

    before to after set_fact: _diff_rpms: >- {{ after_rpms.stdout_lines | difference(before_rpms.stdout_lines) }} - name: Remove arch name from package list set_fact: diff_rpms: "{{ diff_rpms|default([]) + [item.rsplit('.', 1)[0]] }}" with_items: "{{ _diff_rpms }}" - name: Find unspecified packages set_fact: unexp_rpms: "{{ diff_rpms | difference(install_targets) }}" - name: Ensure Unexpected modules are not installed assert: that: unexp_rpms == [] msg: "Unexpected packages are found: {{ unexp_rpms }}" 適用前後での rpm-qaの差分 意図しないパッケージが存 在した場合にエラーとし、是 非を判断する 適用前後の差分リスト からarchを除外 意図したパッケージと適用 前後の差分を比較
  12. 複雑なデータをパースする  ダメな例(手順書) Grep, Awk, Shellでパース  我々の戦略 すべてJSONにし、json_queryフィルタで扱う 19

    Copyright 2017 FUJITSU LIMITED 以下のコマンドを実行します。出力が1であることを確認します。 # AVERAGE=`zgrep "neutron.wsgi" /var/log/neutron/server.log{.1.gz,} | grep -v accepted | tail -n 100 | sed -e "s/ None//" | awk '{x+=$NF}END{print x/NR}'` # echo "$AVERAGE 5.0" | awk '{if($1 < $2) print 1 ;else print 0}'
  13. Json_queryフィルタでの処理  OpenStackのデータ抽出を簡潔に実現 pythonならこう書けるのに… json_queryなら書けます 22 Copyright 2017 FUJITSU LIMITED

    - name: json query example debug: msg: "{{cli_res.stdout |from_json |json_query(qstr)}}" vars: qstr: "[?Status=='ACTIVE']" [ { "ID": "6d905280-9174-4343-88ba-b8f030447575", "Name": "night", "Networks": "private-net=172.29.6.37", "Status": "ACTIVE" } ] 実行結果 [x for x in server_list if x.Status == “ACTIVE” ]
  14. json_queryでの抽出  フィルタロジックは、論理式が書ける  フィルタを適用した後、メンバを抽出  メンバは複数個抽出し、リストやdictにできる  もっと詳しくはjmespathのwebで! 23

    Copyright 2017 FUJITSU LIMITED "[? alive==':-)' && admin_state_up==‘true’]" "[? agent_type==‘DHCP agent'].host" "[?agent_type=='DHCP agent'].{id: id, host: host}"
  15. JSON化の基本戦略  可能な限り全てJSONで出力 API, Ansible Module, CLI 24 Copyright 2017

    FUJITSU LIMITED $ openstack server list -f json [ { "Status": "ACTIVE", "Networks": "private-net=172.29.6.37", "ID": "6d905280-9174-4343-88ba-b8f030447575", "Name": "night" }, { "Status": "SHUTOFF", "Networks": "private-net=172.29.6.36, 10.25.177.56", "ID": "fa3be49e-33aa-4ffa-aa50-13dca8f2b226", "Name": "ansible" } ] 最近のOpenStackは JSONで出力可!
  16. 王道パターン データ取得 • Ansible module • API • CLI (-f

    jsonオプション) 加工 • json_query • jinja2 使用 • モジュール 25 Copyright 2017 FUJITSU LIMITED register set_fact
  17. Prettytable出力  旧来のCLIはprettytableで出力した 人間には見やすい? ansibleには扱いにくい  互換性のため、旧来のCLIが必要な事態も多い 26 Copyright 2017

    FUJITSU LIMITED $ openstack server list +--------------------------------------+---------+---------+----------------------- ----------------+ | ID | Name | Status | Networks | +--------------------------------------+---------+---------+----------------------- ----------------+ | 6d905280-9174-4343-88ba-b8f030447575 | night | ACTIVE | private- net=172.29.6.37 | | fa3be49e-33aa-4ffa-aa50-13dca8f2b226 | ansible | SHUTOFF | private- net=172.29.6.38, 10.25.177.56 | +--------------------------------------+---------+---------+----------------------- ----------------+
  18. Prettytableデータの加工  モノの本には、awkやsedを駆使したplaybookが 紹介されている shellスクリプトを持ってきただけ。つらい。 27 Copyright 2017 FUJITSU LIMITED

    - name: Collect post-migration instance details shell: nova --os-username={{ OS_USERNAME }} --os-password={{ OS_ PASSWORD }} --os-tenant- name={{ OS_TENANT_NAME }} --os-auth- url={{ OS_AUTH_URL }} list --name {{ instance }} -- fields OS-EXT-SRV-ATTR:host,status | awk 'NR > 3' | awk '{ print $4 " and has a status of " $6 }' | awk 'NR == 1' register: postinststat
  19. Prettytable to dictフィルタ 28 Copyright 2017 FUJITSU LIMITED +--------+--------+--------+-------+ |

    key_a | key_b | key_c | ... | +--------+--------+--------+-------+ | val_1a | val_1b | val_1c | ... | | val_2a | val_2b | val_2c | ... | | val_3a | val_3b | val_3c | ... | | ... | ... | ... | ... | +--------+--------+--------+-------+ [ {'key_a': 'val_1a', 'key_b': 'val_1b', 'key_c': 'val_1c', ...}, {'key_a': 'val_2a', 'key_b': 'val_2b', 'key_c': 'val_2c', ...}, {'key_a': 'val_3a', 'key_b': 'val_3b', 'key_c': 'val_3c', ...}, {...}, ] prettytableをJSON (dict) に変換 公開予定
  20. Prettytable例: ホストのVM一覧取得  Nova コマンド出力からIDのリストを取り出す 29 Copyright 2017 FUJITSU LIMITED

    - name: list instances belonging to the migration source host command: >- nova --os-username={{ OS_USERNAME }} --os-password={{ OS_PASSWORD }} --os-tenant-name={{ OS_TENANT_NAME }} --os-auth-url={{ OS_AUTH_URL }} hypervisor-servers {{ inventory_hostname }} register: nova_hypervisor_servers - name: set pre-migration instance list as fact set_fact: instances: "{{ nova_hypervisor_servers.stdout | table_to_list | json_query('[].ID') }}" +--------------------------------------+-------------------+---------------+---------------------+ | ID | Name | Hypervisor ID | Hypervisor Hostname | +--------------------------------------+-------------------+---------------+---------------------+ | 49c70075-bac0-41fd-bb98-159c1779356e | instance-00000012 | 1 | <compute node name> | | 65957279-4871-4168-aea0-f0d9be48ed81 | instance-00000013 | 1 | <compute node name> | +--------------------------------------+-------------------+---------------+---------------------+ このListが得られる
  21. XML出力  Libvirtや特定機器など様々な出力で使用。 高度な構造を扱えるが、Ansibleでは扱いにくい。 コマンドと出力例 30 Copyright 2017 FUJITSU LIMITED

    # virsh dumpxml 49c70075-bac0-41fd-bb98-159c1779356e <domain type='qemu' id='1'> <name>instance-00000012</name> <uuid>49c70075-bac0-41fd-bb98-159c1779356e</uuid> <metadata> <nova:instance xmlns:nova=¥"http://openstack.org/xmlns/libvirt/nova/1.0¥"> .... </metadata> <memory unit='KiB'>524288</memory> <currentMemory unit='KiB'>524288</currentMemory> <vcpu placement='static'>1</vcpu> .... <interface type='bridge'> <mac address='fa:16:3e:20:42:1b'/> .... </interface> .... </domain> MAC addressをNova/Neutronの 結果と比較したい場合がある
  22. XML to JSON フィルタ  XMLからJSONへの変換フィルタを実装 “Converting Between XML and

    JSON”仕様に準拠 • http://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html 31 Copyright 2017 FUJITSU LIMITED 公開予定
  23. XML to JSON例: virsh/nova/neutronのMAC値比較 32 Copyright 2017 FUJITSU LIMITED -

    name: get instance dumpxml from libvirt command: > virsh dumpxml {{ inventory_hostname }} register: virsh_dumpxml - name: set kvm_dumpxml fact set_fact: kvm_dumpxml: "{{ virsh_dumpxml.stdout | fromxml }}" - name: set interfaces' integrity to true set_fact: intf_integrity: yes when: - nova_details_network | symmetric_difference(neutron_net_show|json_query('[].name')) == [] - kvm_dumpxml | json_query(dumpxml_mac_query) | symmetric_difference(nova_intf_list | json_query(nova_intf_mac_query)) == [] vars: id_to_mac_query: "[?¥"Net ID¥"=='{{ item.id }}'].¥"MAC Addr¥" | [0]" dumpxml_mac_query: "domain.devices.interface[].mac.¥"@address¥"" nova_intf_mac_query: "[].¥"MAC Addr¥""
  24. さらなるデータ加工  map, reduceのような加工をしたい時 jinja2やjson_queryにもmap関数はある。 しかし、関数定義できないので使いづらい  [f_x() for x

    in source_list]を ansibleのタスクで実現 33 Copyright 2017 FUJITSU LIMITED - name: template of map process set_fact: ls: “{{ ls |default([]) + [f_x] }}” with_items: "{{ source_list }} vars: f_x: “{{ some_process_of(item) }}” lsの初期値 リスト同士の結合
  25. リスト処理の例  prettytable to dictくらいは書ける 34 Copyright 2017 FUJITSU LIMITED

    # table :input:, odcit :output: - name: get token from table set_fact: tokens: "{{ tokens | default([]) + [ln_token] }}" vars: ln_token: "{{ (item[1:-1].split('|'))| map('trim')|list }}" with_items: "{{ table.splitlines() }}" when: item.startswith('|') and item.endswith('|') - name: define keys set_fact: keys: "{{ tokens[0] }}" - name: make output dict set_fact: odict: "{{ odict|default([]) + [dict(keys |zip(item) |list)] }}" with_items: - "{{ tokens[1:]}}"
  26.  Ansibleだけでは、Playbook・適用対象を管理しきれない  Jenkins + gitによるpipelineによるPlaybook管理  Foreman DBをもとにしたDynamic Inventory

     Jenkinsのログを使う Ansible Tips & Examples 「適用対象を間違えない」 「作業履歴を残す」 35 Copyright 2017 FUJITSU LIMITED
  27. Excel から YAMLへ  リージョン単位にインベントリを管理する 40 Copyright 2017 FUJITSU LIMITED

    inventory/ ├── g2pstg-1 │ ├── group_vars │ │ └── all │ │ ├── common.yml │ │ └── node_config.yml │ └── hosts.yml ├── g2pstg-2 │ ├── group_vars │ │ └── all │ │ ├── common.yml │ │ └── haproxy_conf.yml │ └── hosts.yml └── ops ├── group_vars │ └── all │ ├── common.yml │ └── node_config.yml └── hosts.yml
  28. ExcelからYAMLへ  リージョン単位にインベントリを管理する 41 Copyright 2017 FUJITSU LIMITED inventory/ ├──

    g2pstg-1 │ ├── group_vars │ │ └── all │ │ ├── common.yml │ │ └── node_config.yml │ └── hosts.yml ├── g2pstg-2 │ ├── group_vars │ │ └── all │ │ ├── common.yml │ │ └── haproxy_conf.yml │ └── hosts.yml └── ops ├── group_vars │ └── all │ ├── common.yml │ └── node_config.yml └── hosts.yml
  29.  リージョン単位にインベントリを管理する 手動の管理はそもそも無理 42 Copyright 2017 FUJITSU LIMITED inventory/ ├──

    g2pstg-1 │ ├── group_vars │ │ └── all │ │ ├── common.yml │ │ └── node_config.yml │ └── hosts.yml ├── g2pstg-2 │ ├── group_vars │ │ └── all │ │ ├── common.yml │ │ └── haproxy_conf.yml │ └── hosts.yml └── ops ├── group_vars │ └── all │ ├── common.yml │ └── node_config.yml └── hosts.yml
  30. Foreman概要  OSSのサーバープロビジョニングツール https://theforeman.org/, 2009年開始 ライセンス: GPL v3  特徴

    DHCP/DNS/TFTP/PXEを統合管理 プラグインによるGUIを含む機能拡張 REST APIによる操作が可能 Dynamic Inventory対応 RedHat Satellite 6で採用 44 Copyright 2017 FUJITSU LIMITED
  31. Foreman Dynamic Inventory 出力例  $ python foreman.py --list (抜粋)

    46 Copyright 2017 FUJITSU LIMITED { "_meta": { "hostvars": { "foreman1.ops.flab.fujitsu.co.jp": { "foreman": { ... "foreman_hostgroup_kt122": [ "k1-c28-14-sv.v122.local", "k1-c28-15-sv.v122.local", "k1-c28-16-sv.v122.local", "k1-c28-17-sv.v122.local", "k1-c28-18-sv.v122.local" ], ... }