Ansibleを結構使ってみた/ansible-nikkei-2015
by
bungoume
×
Copy
Open
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Slide 1
Slide 1 text
Ansibleを結構使ってみた 2015/9/14 日本経済新聞社 デジタル編成局 梅崎裕利 1
Slide 2
Slide 2 text
自己紹介 • 2014年入社(2年目) • 社内では基盤チーム • サーバ管理からアプリ開発まで • PythonとElasticsearchで検索API開発 2
Slide 3
Slide 3 text
Ansibleを使った目的 • ドキュメントと実サーバの状態を合わせたい • これまではExcelでミドルウェア管理(更新されない) • なるべくイミュータブルに • インスタンス起動から設定変更・デプロイまで • 同じサーバをポコポコ増やしたい • 環境ごとに若干設定が違うのでAMIコピーは面倒 3
Slide 4
Slide 4 text
Ansibleを選んだ理由 • 社内にPython開発者が多いから • djangoやflaskを使っているためJinja2も慣れてる • Agentを入れなくていい • Chefは社内で何人かが挫折した • Windowsにも対応しているらしい • @r_rudiさんにサポートをお願いできた(重要) • 困ったときに相談できる人がいると安心 4
Slide 5
Slide 5 text
Ansibleを使った場所 • 電子版のWebサーバ群 • 約300台、30種類以上 • データセンターからAWSへ基盤移行のタイミング 5
Slide 6
Slide 6 text
サーバ構成 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)
Slide 7
Slide 7 text
運用までの流れ • 体制(時期別) • 実験フェーズ • 設計 • 決定内容(すること・しないこと) • ディレクトリ構造 • クラウド向けへ構成変更 • 構築 • フロー • RolesのCI方法 • 運用 7
Slide 8
Slide 8 text
体制 • 2014/9~12月 実験的にAnsible利用 • 構成を決める(自分+@r_rudiさんサポート) • 2015/1~4月 クラウドベンダーと設計・開発 • ベンダーがRole作成、日経でレビュー • 2015/5~7月 リファクタリング・Ansibleを広める • ServerSpecを用意・テスト • 環境毎に使いまわせるよう変数化 • 社員や常駐SEにAnsibleの使い方を伝える • 2015/8月~ 社員と常駐SEで運用 • 常駐SEや社員がプルリクエスト、基盤チームでレビュー 8
Slide 9
Slide 9 text
実験期間(2014/9~12月) • 新規開発のAPI群構築にAnsibleを利用 • 実際に使ってみて気になった点を @r_rudiさんに教えてもらった • 一般的なディレクトリ構成 • よくあるAnsible.cfgの設定 • xxxするモジュールはあるか、作り方 • 再起動チェックの方法 • xxxはバグか仕様か • 環境変数の読み込み方 • … 9
Slide 10
Slide 10 text
設計時に決めたこと • アプリケーションとAnsibleどこで分けるか • 理想はアプリをDockerなどでHerokuライクに分ける • 今回は変更頻度(高いのはアプリ)と 環境依存(本番・開発で違うのはAnsible)で分けた • HAProxyなど設定がシンプルなものはすべてAnsibleで • ディレクトリ構造 • リポジトリをCommonと配信サーバ群・基盤サーバ群に 分けcommonをsubmoduleで読み込み • 環境変数の切り替えはhostsでやる • Rolesの分割単位 • ミドルウェア単位 • role内での条件分岐はなるべく避ける 10
Slide 11
Slide 11 text
ディレクトリ構造例 (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
Slide 12
Slide 12 text
構成をクラウド向けに • サーバ相乗りをやめる • 1機能1サーバにすることで設定を変数化しやすくする • 立て直しできるようにする • ログを別サーバに転送するようにして状態を持たない • サーバのrole名を統一する • 同じサーバなのに呼び名いろいろ NASサーバ、シェアサーバ、ファイルサーバ、etc… 12
Slide 13
Slide 13 text
Ansibleでしないこと • 複数ディストリビュージョン対応 • ソフトウェアバージョンの固定 • 自前のリポジトリを立てる必要が出てくる • 最新のものでも動くように随時対応する • Dynamic Inventryの活用 • サーバを固定IPで運用することにした • hostsをもとにサーバを起動・構築する • Ansibleでオートスケーリング • hostsとの相性が悪い • AMIイメージをAnsibleで作成 13
Slide 14
Slide 14 text
Playbook作成(2015/1~7) • クラウドベンダー(cloudpack)にPlaybookを作成してもら う • 期間が短かったため1ヶ月ほどは直接masterで作業 • 日経側でCI環境を用意 • ある程度できたところでPull-requestフロー開始 • ベンダーがプルリクエスト、日経でレビュー • Masterマージ後に反映 • レビューが遅れると開発も遅延するのでなるべく早く確認 • cloudpackにServerspecを書いてもらう • リファクタリング • 日経側で運用しやすいように変更 14
Slide 15
Slide 15 text
CI環境(CircleCI) • 初期はAnsible-lintで簡単な構文チェック • Typoなどのあからさまなバグは発見できる。 • Ansibleに慣れていない人がshell使いまくるのを防げた • CircleCI上にDockerコンテナを用意してコンテナに Ansibleを流す • 設定ファイルのバグなどが大幅に減った • Template展開後の値確認が出来るようになった • Serverspecでコンテナをテスト • 期待どおり設定されているかまでわかるようになった 15
Slide 16
Slide 16 text
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
Slide 17
Slide 17 text
CIの課題 • どこまでテストするかが悩み • 実機かDockerか。Serverspecでどこまで確認するか • テスト時間とのトレードオフ • AMIイメージとDockerコンテナがそもそも違う • LXC上のDockerなのでテスト出来ないものがちょっとある • カーネルパラメータ変更やsystemdでサービス起動 • 流すとエラーになるのは変数でスキップ • Dockerは早いと言われるけど、それでも遅い • Roles数のテストがあるため開発につれて増加(30分かかる) • CircleCIの契約コンテナ数不足(2時間待ち…) • 並列化やキャッシュで少しだけ短縮(20分) • サーバ間連携のテストが出来ない • ロードバランサの振り分けテスト 17
Slide 18
Slide 18 text
CIでは実施しないことに • 冪等性のテスト • 何度も流して破綻しないか • Tasksを目視で確認、開発環境でテスト • 実機テスト • LXCやDockerの制約でテストできない箇所 • masterマージ後に開発環境へ流してテスト • 失敗したら開発環境ごと作りなおす • 連携テスト • HAProxyの振り分けルールが正しいか • 開発環境で手動確認 • テスト用アプリサーバを建てて自動化予定 (https://github.com/bungoume/debug-server) 18
Slide 19
Slide 19 text
運用期間(2015/8~) • Ansibleの使い方を常駐SEやアプリベンダーに伝える • 常駐SEはAnsibleを使ってデプロイ出来るようになった • 基盤チームでPlaybook作成・レビューできる人が増えた • アプリベンダーへの普及はこれから • Jenkinsで自動デプロイ • 開発には自動でmasterブランチを流すように • 本番デプロイは確認しながら • Productionブランチを用意してデプロイ前に差分確認 • --diff --checkをつけてデプロイ時にも差分確認 19
Slide 20
Slide 20 text
運用してみて • 「やらないこと」の範囲であれば破綻していない • CIが動いているので設定ファイルのミスがわかる • ApacheやVarnishの設定ミスも検出できる • Pull-requestフローの体制 • 破綻する変更がないか確認できる • 複雑度が増す前にプラグイン作成で対応 20
Slide 21
Slide 21 text
よかったこと • 全台への設定変更が楽 • カーネルパラメータの変更をあとから変えたくなった等 • コスト削減につながった • インスタンスに状態を持たなくなったので AMIバックアップの必要性がなくなった • 開発環境の追加が簡単 • 「dev3,dev4が欲しいんだけど…」にもすぐ対応できた 21
Slide 22
Slide 22 text
共同開発で困ったこと・事故 • 冪等性のないコード • 初期構築のみAnsibleを利用し、何度も流さない認識だった • Task化されていない変更 • 従来の作業にそって実サーバにログインして設定される • とはいえ、ログインを禁止すると作業スピードが落ちる • 設定ファイルだけ違うコピペroles • Windowsのtemplateモジュールがなかった • みんなGitに慣れてない • サーバの秘密鍵をコミット • push -fで1週間戻った… • この半年でかなり使えるようになった 22
Slide 23
Slide 23 text
解決方法 • 変更はすべてAnsibleコードでという認識合わせ • 最初に • なるべくカバー出来るようにCIを用意する • 初期作成時にCI用意が間に合わなかった • Vagrantを利用する • GithubのProtected branchesを使う • 今月からGithubに実装された機能 • 構築が落ち着いてからリファクタリング • コードが複雑化しそうなものはfilter_pluginを書く 23
Slide 24
Slide 24 text
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
Slide 25
Slide 25 text
よかったこと • @r_rudiさんがサポートしてくれた • ちょっとした困りごとが大きくなる前に解決できた • 記述が複雑化しそうなときに相談 • プラグイン作成について相談 • バグか仕様か相談 • 変数に日本語つかえる?など • バグにはAnsibleへプルリクもしてもらえた 25
Slide 26
Slide 26 text
その他やっていること 26
Slide 27
Slide 27 text
サーバの自動起動・停止 • AnsibleとJenkinsで実行 • 開発環境の夜間停止 • 負荷予測に応じた起動・停止 • EC2モジュールを利用 27
Slide 28
Slide 28 text
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 展開後
Slide 29
Slide 29 text
• 前述のget_groupはこのようなプラグイン 簡単なプラグインを用意 29
Slide 30
Slide 30 text
監視の方法 • Zabbix-agentをAnsibleでインストール • Ansibleでの自動登録はしなかった • Zabbixの通知をSlackに飛ばして確認 • FluentdでログをSentryに飛ばして確認 • アクセスログをElasticsearchで可視化 30
Slide 31
Slide 31 text
最後に • 日経電子版ではエンジニア採用中です • 見学はウェルカムなので連絡ください! •
[email protected]
31