Ansibleを結構使ってみた/ansible-nikkei-2015

D405f3b9dc9fa223f6fa507717f41372?s=47 bungoume
September 14, 2015

 Ansibleを結構使ってみた/ansible-nikkei-2015

D405f3b9dc9fa223f6fa507717f41372?s=128

bungoume

September 14, 2015
Tweet

Transcript

  1. Ansibleを結構使ってみた 2015/9/14 日本経済新聞社 デジタル編成局 梅崎裕利 1

  2. 自己紹介 • 2014年入社(2年目) • 社内では基盤チーム • サーバ管理からアプリ開発まで • PythonとElasticsearchで検索API開発 2

  3. Ansibleを使った目的 • ドキュメントと実サーバの状態を合わせたい • これまではExcelでミドルウェア管理(更新されない) • なるべくイミュータブルに • インスタンス起動から設定変更・デプロイまで •

    同じサーバをポコポコ増やしたい • 環境ごとに若干設定が違うのでAMIコピーは面倒 3
  4. Ansibleを選んだ理由 • 社内にPython開発者が多いから • djangoやflaskを使っているためJinja2も慣れてる • Agentを入れなくていい • Chefは社内で何人かが挫折した •

    Windowsにも対応しているらしい • @r_rudiさんにサポートをお願いできた(重要) • 困ったときに相談できる人がいると安心 4
  5. Ansibleを使った場所 • 電子版のWebサーバ群 • 約300台、30種類以上 • データセンターからAWSへ基盤移行のタイミング 5

  6. サーバ構成 6 HAProxy Varnish Varnish HAProxy ELB NAS LogServer StaticFiles

    App1 App2 DB Elasticsearch Zabbix Batch 青い部分を環境数分 (production, staging, dev1, dev2…) Ansible 構築・デプロイ 基盤サーバ (Zabbix,HAProxy, Varnishなど) 配信サーバ (appやDB)
  7. 運用までの流れ • 体制(時期別) • 実験フェーズ • 設計 • 決定内容(すること・しないこと) •

    ディレクトリ構造 • クラウド向けへ構成変更 • 構築 • フロー • RolesのCI方法 • 運用 7
  8. 体制 • 2014/9~12月 実験的にAnsible利用 • 構成を決める(自分+@r_rudiさんサポート) • 2015/1~4月 クラウドベンダーと設計・開発 •

    ベンダーがRole作成、日経でレビュー • 2015/5~7月 リファクタリング・Ansibleを広める • ServerSpecを用意・テスト • 環境毎に使いまわせるよう変数化 • 社員や常駐SEにAnsibleの使い方を伝える • 2015/8月~ 社員と常駐SEで運用 • 常駐SEや社員がプルリクエスト、基盤チームでレビュー 8
  9. 実験期間(2014/9~12月) • 新規開発のAPI群構築にAnsibleを利用 • 実際に使ってみて気になった点を @r_rudiさんに教えてもらった • 一般的なディレクトリ構成 • よくあるAnsible.cfgの設定

    • xxxするモジュールはあるか、作り方 • 再起動チェックの方法 • xxxはバグか仕様か • 環境変数の読み込み方 • … 9
  10. 設計時に決めたこと • アプリケーションとAnsibleどこで分けるか • 理想はアプリをDockerなどでHerokuライクに分ける • 今回は変更頻度(高いのはアプリ)と 環境依存(本番・開発で違うのはAnsible)で分けた • HAProxyなど設定がシンプルなものはすべてAnsibleで

    • ディレクトリ構造 • リポジトリをCommonと配信サーバ群・基盤サーバ群に 分けcommonをsubmoduleで読み込み • 環境変数の切り替えはhostsでやる • Rolesの分割単位 • ミドルウェア単位 • role内での条件分岐はなるべく避ける 10
  11. ディレクトリ構造例 (Zabbix-server) 基盤Playbooks/ |--zabbix-server.yml |--roles/ | └─zabbix-server/ | └─ (defaults,

    handlers, meta, tasks, teplates...) |--spec/ | └─zabbix-server/ | └─main_spec.rb | |--ansible-common-repository/ | |--filter_plugins/ | |-- development/ | |--production/ | |--roles/ | | |--common/ | | └─zabbix-agent/ | └─spec/ | └─zabbix-agent/ 11
  12. 構成をクラウド向けに • サーバ相乗りをやめる • 1機能1サーバにすることで設定を変数化しやすくする • 立て直しできるようにする • ログを別サーバに転送するようにして状態を持たない •

    サーバのrole名を統一する • 同じサーバなのに呼び名いろいろ NASサーバ、シェアサーバ、ファイルサーバ、etc… 12
  13. Ansibleでしないこと • 複数ディストリビュージョン対応 • ソフトウェアバージョンの固定 • 自前のリポジトリを立てる必要が出てくる • 最新のものでも動くように随時対応する •

    Dynamic Inventryの活用 • サーバを固定IPで運用することにした • hostsをもとにサーバを起動・構築する • Ansibleでオートスケーリング • hostsとの相性が悪い • AMIイメージをAnsibleで作成 13
  14. Playbook作成(2015/1~7) • クラウドベンダー(cloudpack)にPlaybookを作成してもら う • 期間が短かったため1ヶ月ほどは直接masterで作業 • 日経側でCI環境を用意 • ある程度できたところでPull-requestフロー開始

    • ベンダーがプルリクエスト、日経でレビュー • Masterマージ後に反映 • レビューが遅れると開発も遅延するのでなるべく早く確認 • cloudpackにServerspecを書いてもらう • リファクタリング • 日経側で運用しやすいように変更 14
  15. CI環境(CircleCI) • 初期はAnsible-lintで簡単な構文チェック • Typoなどのあからさまなバグは発見できる。 • Ansibleに慣れていない人がshell使いまくるのを防げた • CircleCI上にDockerコンテナを用意してコンテナに Ansibleを流す

    • 設定ファイルのバグなどが大幅に減った • Template展開後の値確認が出来るようになった • Serverspecでコンテナをテスト • 期待どおり設定されているかまでわかるようになった 15
  16. CircleCIの内容 • テスト箇所 • コンテナを作成して自身にPlaybookを流しイメージ化 • イメージにServerspecを流す 16 test: override:

    - ansible-lint *.yml - docker run -t -v `pwd`:/data -w=/data/tests/ nikkei/ansible_centos6 ansible-playbook -i hosts haproxy.yml && docker commit `docker ps --latest --quiet` haproxy - docker run -t -v `pwd`:/data -w=/data/ haproxy rake -f tests/Rakefile spec:haproxy SPEC_BACKEND=CI
  17. CIの課題 • どこまでテストするかが悩み • 実機かDockerか。Serverspecでどこまで確認するか • テスト時間とのトレードオフ • AMIイメージとDockerコンテナがそもそも違う •

    LXC上のDockerなのでテスト出来ないものがちょっとある • カーネルパラメータ変更やsystemdでサービス起動 • 流すとエラーになるのは変数でスキップ • Dockerは早いと言われるけど、それでも遅い • Roles数のテストがあるため開発につれて増加(30分かかる) • CircleCIの契約コンテナ数不足(2時間待ち…) • 並列化やキャッシュで少しだけ短縮(20分) • サーバ間連携のテストが出来ない • ロードバランサの振り分けテスト 17
  18. CIでは実施しないことに • 冪等性のテスト • 何度も流して破綻しないか • Tasksを目視で確認、開発環境でテスト • 実機テスト •

    LXCやDockerの制約でテストできない箇所 • masterマージ後に開発環境へ流してテスト • 失敗したら開発環境ごと作りなおす • 連携テスト • HAProxyの振り分けルールが正しいか • 開発環境で手動確認 • テスト用アプリサーバを建てて自動化予定 (https://github.com/bungoume/debug-server) 18
  19. 運用期間(2015/8~) • Ansibleの使い方を常駐SEやアプリベンダーに伝える • 常駐SEはAnsibleを使ってデプロイ出来るようになった • 基盤チームでPlaybook作成・レビューできる人が増えた • アプリベンダーへの普及はこれから •

    Jenkinsで自動デプロイ • 開発には自動でmasterブランチを流すように • 本番デプロイは確認しながら • Productionブランチを用意してデプロイ前に差分確認 • --diff --checkをつけてデプロイ時にも差分確認 19
  20. 運用してみて • 「やらないこと」の範囲であれば破綻していない • CIが動いているので設定ファイルのミスがわかる • ApacheやVarnishの設定ミスも検出できる • Pull-requestフローの体制 •

    破綻する変更がないか確認できる • 複雑度が増す前にプラグイン作成で対応 20
  21. よかったこと • 全台への設定変更が楽 • カーネルパラメータの変更をあとから変えたくなった等 • コスト削減につながった • インスタンスに状態を持たなくなったので AMIバックアップの必要性がなくなった

    • 開発環境の追加が簡単 • 「dev3,dev4が欲しいんだけど…」にもすぐ対応できた 21
  22. 共同開発で困ったこと・事故 • 冪等性のないコード • 初期構築のみAnsibleを利用し、何度も流さない認識だった • Task化されていない変更 • 従来の作業にそって実サーバにログインして設定される •

    とはいえ、ログインを禁止すると作業スピードが落ちる • 設定ファイルだけ違うコピペroles • Windowsのtemplateモジュールがなかった • みんなGitに慣れてない • サーバの秘密鍵をコミット • push -fで1週間戻った… • この半年でかなり使えるようになった 22
  23. 解決方法 • 変更はすべてAnsibleコードでという認識合わせ • 最初に • なるべくカバー出来るようにCIを用意する • 初期作成時にCI用意が間に合わなかった •

    Vagrantを利用する • GithubのProtected branchesを使う • 今月からGithubに実装された機能 • 構築が落ち着いてからリファクタリング • コードが複雑化しそうなものはfilter_pluginを書く 23
  24. Windowsつらい • templateモジュールが使えない • 1.7から待ち焦がれていたのに • copyすら使えなかった(1.9.2) • S3にあげてダウンロードする仕組みを作成 •

    完成した頃にwin_templateモジュール入った(1.9.2) • useraddにも冪等性がなかった • Playbook流すとパスワードが初期化される(1.9まで) • Playbook流すとパスワードが平文表示される • no_log: Trueを付けると動作しないバグあり(2.0で解決予定?) • 最近やっと対応されてきた 24
  25. よかったこと • @r_rudiさんがサポートしてくれた • ちょっとした困りごとが大きくなる前に解決できた • 記述が複雑化しそうなときに相談 • プラグイン作成について相談 •

    バグか仕様か相談 • 変数に日本語つかえる?など • バグにはAnsibleへプルリクもしてもらえた 25
  26. その他やっていること 26

  27. サーバの自動起動・停止 • AnsibleとJenkinsで実行 • 開発環境の夜間停止 • 負荷予測に応じた起動・停止 • EC2モジュールを利用 27

  28. HAProxy(LB)の振り先を自動生成 • Pluginでhostsから振り先を自動生成 28 [webserver] 10.0.4.1 name=webserver01a zone=a 10.0.5.1 name=webserver01c

    zone=c webservers: - {ip: 10.0.4.1, name: webserver01a, zone: a} - {ip: 10.0.5.1, name: webserver01c, zone: c} webservers: "{{ hostvars | get_group(‘webserver') }}" backend webserver {% for host in webservers -%} server {{host.name}} {{host.ip}}:80 check{% if host.zone != zone %} backup{% endif %} {% endfor %} hosts vars 展開後 変数 backend webserver server webserver01a 10.0.4.1:80 check server webserver01c 10.0.5.1:80 check backup HAProxy- template 展開後
  29. • 前述のget_groupはこのようなプラグイン 簡単なプラグインを用意 29

  30. 監視の方法 • Zabbix-agentをAnsibleでインストール • Ansibleでの自動登録はしなかった • Zabbixの通知をSlackに飛ばして確認 • FluentdでログをSentryに飛ばして確認 •

    アクセスログをElasticsearchで可視化 30
  31. 最後に • 日経電子版ではエンジニア採用中です • 見学はウェルカムなので連絡ください! • dg_lab@nex.nikkei.co.jp 31