PythonでもPythonじゃなくても使える汎用的なMicroservice実行環境 / nikkei microservice

3ceba985a8d8efb44ef9c7d74089efdb?s=47 Yosuke
September 21, 2016

PythonでもPythonじゃなくても使える汎用的なMicroservice実行環境 / nikkei microservice

3ceba985a8d8efb44ef9c7d74089efdb?s=128

Yosuke

September 21, 2016
Tweet

Transcript

  1. 1 PythonでもPythonじゃなくても使える汎用 的なMicroservice実行環境 PyConJP2016 Yosuke Suzuki Nikkei Inc. Development and

    Infrastructure for Microservice Architecture
  2. About me Engineer at Nikkei Inc. 2 Yosuke Suzuki @yosukep

    Python, Golang, JavaScript ウェブの運用とか編集者とか記者の仕事歴も長い
  3. スポンサーしてます! 3

  4. 日経電子版について 4 • 2010年3月に創刊 • 有料会員48万人以上 のニュースサービス • 月間アクセス3億件

  5. 日経電子版の開発チーム 5 • API開発 • モバイルアプリ • ブラウザー向け • インフラ

    • データ分析 内製での開発体制を強化、エンジニアを絶賛採用中
  6. FinancialTimesとの連携 6 • 2015年12月買収 • 開発ノウハウの共有 • 英語力++ 英語をコミュニケーションの主言語として使うチームもある

  7. 本題 7

  8. Microservicesとは 8 • サイズが小さい✔ • 自律的に開発が可能✔ • 独立してデプロイが可能✔ • デプロイやビルドプロセスの自動化✔

    • 分散化する、中央集権化しない O’Reilly: Microservice Architectureより
  9. 日経電子版ではGateway方式を採用 9 Cache/router (Fastly) UI service UI service Internet API

    gateway Search Content Auth DNS (Internal / Route53) API service API service Image API gatewayが中央集権的ではある
  10. Gateway方式 10 • 認証、認可も担当 ◦ 認可は結局サービス側のレイヤーでやる ことも多い • 概念上はGateway方式でも画像の配信 サービスなどは直接通信

    • 旧APIのラッパー的役割も
  11. サイズが小さい✔ 11 • PythonはDjangoベース ◦ 基本的には2−3個のアプリケーションフォ ルダがあるだけ ◦ Gatewayだけはフォルダ多い •

    NodeJSはexpressベース ◦ 数百行レベルのコード
  12. 自律的に開発が可能✔ 12 • DBなどリソースのシェアはしない ◦ S3を経由してシェアとかはある • サービス間はAPI経由でのやり取り • 基本的にステートレス

    • 自律的にできるが、各自バラバラに作ると 非生産的 • 雛形からベースのサービスを作成
  13. 雛形からサービスを作成 13

  14. 雛形に含まれているもの 14 • requirements.txt • tox.ini ◦ テスト実行とflake8による静的解析 • Djangoアプリケーション

    • Dockerfile • ElasticBeanstalkの設定ファイル • CircleCIの設定ファイル など
  15. cookiecutterで対話的に作成 15 pip install cookiecutter cookiecutter gh:Nikkei/django-project-template 対話形式でいくつか値を入力 • repo_name:

    GitHub用のリポジトリ名 • project_name: Djangoプロジェクトの名前 • subdomin: サーバーのサブドメインに使用する文字列 • short_description: リポジトリの一行での説明
  16. 雛形への追随 16 pip install git+https://github.com/hirokiky/cookiepatcher cookiepatcher • レガシー化させない • KYさん作

    • 最新のテンプレートに追随 ◦ Djangoなどのライブラリのアップデート • cookiepatcher.jsonで差分を管理
  17. Private PyPI 17 • 各サービスで使う固有の処理を共通化 ◦ 記事のIDの変換 ◦ CMS独自の専用タグの置き換え処理 requirements.txt:

    --extra-index-url https://xxx.x/xxxxx/packages/simple/ nikkei-utils==0.6 PyPIの自社専用版、各リポジトリでのコードの重複を避ける
  18. Private PyPI (2) 18 1. python setup.py sdist を実行 2.

    dist/ 以下にできた xx.0.1.tar.gz のようなファイルを packages リポジトリの 指定ディレクトリにコピー 3. ファイルを add してpushするとCircleCIから自動でアッ プロードされる 通常のPyPIへの登録とやることはあまり変わらない
  19. Private PyPI (3) 19 各アプリで呼び出し from nikkei_utils.kiji import extract_snippet from

    nikkei_utils.region import region_info def hoge(): snippet = extract_snippet(article.body)
  20. NodeJSアプリの場合はPrivate npm 20 package.json: "dependencies": { "@nikkei/nikkei-ui": "^6.2.0", "@nikkei/rnikkei-express": "^2.32.2",

    "denodeify": "^1.2.1", "dom-delegate": "^2.0.3", "express-validator": "^2.20.8", "open-graph-scraper": "^2.2.2" } privateなnpmサーバーから社内専用の共通ライブラリを取得できる
  21. ローカル開発環境 21 • API開発なら特に問題なし ◦ python manage.py runserver ◦ Dockerも使わなくていい

    ◦ 単独で動作確認しやすい • フロントエンド開発の時はややこしい ◦ ルーティングの際に一部のドメインをロー カルに振り向ける
  22. みんな大好きRest Framework 22 • Django Rest Framework • Django Rest

    Framework Swagger Python/DjangoでAPI作るなら圧倒的な生産性
  23. Rest Framework(2) 23 class FeedAnArticleView(APIView): http_method_names = ['get'] permission_classes =

    (IsAuthenticated,) def get(self, request, kiji_id_raw): """ # 検索エンジン用フィード --- parameters: - name: kiji_id paramType: path description: 対象の記事ID """ article = Article.objects.get(kiji_id_raw=kiji_id_raw, status=Article.POST) return Response(data={'article': feed_article_mapper(article)})
  24. 独立してデプロイが可能✔ 24 • サービスごとにインフラは 完全分離 • ElasticBeanstalk+Docker のアプリとして稼働 • スケールアウトも容易

  25. デプロイやビルドプロセスの自動化✔ 25 masterブランチが開発系に、deployment/productionブランチが本番系に

  26. ElasticBeanstalk(ebコマンド)の課題 26 • 開発系と本番系の設定ファイル (Dockerrun.aws.json)を分けられない • Blue/Greenデプロイメントできない

  27. そこで ebi コマンド 27 pip install ebi ebi deploy <app_name>

    <env_name> • KYさん作 • Dockerrun.aws.jsonを環境(本番・開発)に 合わせて分けられる • Blue/Greenデプロイが可能
  28. CircleCIの設定ファイル 28 - sudo pip install --ignore-installed awsebcli - sudo

    pip install -U ebi - aws configure set aws_access_key_id $PROD_AWS_ACCESS_KEY_ID - aws configure set aws_secret_access_key $PROD_AWS_SECRET_ACCESS_KEY - aws configure set default.region ap-northeast-1 - aws configure set default.output json - ebi bgdeploy app-name env-name-blue env-name-green cname_prefix --profile default --noswap --region ap-northeast-1 --dockerrun Dockerrun.aws.prod.json - sleep 10 - sudo pip install -r e2etests/requirements.txt - py.test e2etests/tests.py - eb swap env-name-blue --profile default --destination_name env-name-green
  29. バッチ処理 29 Docker アプリコンテナ Docker アプリコンテナ Rundeckでのバッチ処理は ElasticBeanstalkにデプロイ しているものがそのまま使え る

    Spotインスタンス Docker アプリコンテナ
  30. Rundeck 30 Dockerコンテナを定期タスクで実行

  31. 監視、エラーログ 31 • アプリとは別コンテナーのfluentdでログを 収集 ◦ github.com/bungoume/log-sender • Sentryでエラーログを収集 •

    New Relicでメトリクスデータを収集 • CloudWatch すべて同じパターンに共通化
  32. ログの集約 32 各サービス Docker アプリコンテナ Docker fluentd コンテナ ログ集約サービス

  33. 障害対応 33 Slackに通知ししつつ、対応が必要な障害はPagerDuty経由で電話呼び出し

  34. かなり幅広く適用可能なインフラ 34 • Djangoアプリ • NodeJS(express)アプリ • WordPress • Rundeck

    • Jenkins • Kibana • Nginx+プラグイン 日経電子版でこれまで実績のあるパターン
  35. クラウドの乗り換えもしやすい(はず 35 FinancialTimes社のNodeJSのアプリはHeroku上で運用 同じものがアプリの変更なく、ElasticBeanstalk環境で動かせた

  36. 課題 36 • スケールアウトは起動的ではない ◦ 想定以上のスパイクが来ると間に合わない ◦ 予測可能場合はスケジューリングして増やす • マメにメンテは必要

    ◦ Djangoは1.7 → 1.10に順次更新 ◦ 定期的にrequirements.txtを更新していく • AWS側のバグと付き合う
  37. Thanks 37 だいたいはこの2人が作ってくれた

  38. Thank you! 38

  39. We're hiring! s.nikkei.com/saiyo Pythonエンジニア (機械学習できるひと歓迎) フロントエンドエンジニア アプリエンジニア デザイナー 39