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

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

Yosuke
September 21, 2016

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

Yosuke

September 21, 2016
Tweet

More Decks by Yosuke

Other Decks in Technology

Transcript

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

    View full-size slide

  2. About me
    Engineer at Nikkei Inc.
    2
    Yosuke Suzuki @yosukep
    Python, Golang, JavaScript
    ウェブの運用とか編集者とか記者の仕事歴も長い

    View full-size slide

  3. スポンサーしてます!
    3

    View full-size slide

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

    View full-size slide

  5. 日経電子版の開発チーム
    5
    ● API開発
    ● モバイルアプリ
    ● ブラウザー向け
    ● インフラ
    ● データ分析
    内製での開発体制を強化、エンジニアを絶賛採用中

    View full-size slide

  6. FinancialTimesとの連携
    6
    ● 2015年12月買収
    ● 開発ノウハウの共有
    ● 英語力++
    英語をコミュニケーションの主言語として使うチームもある

    View full-size slide

  7. Microservicesとは
    8
    ● サイズが小さい✔
    ● 自律的に開発が可能✔
    ● 独立してデプロイが可能✔
    ● デプロイやビルドプロセスの自動化✔
    ● 分散化する、中央集権化しない
    O’Reilly: Microservice Architectureより

    View full-size slide

  8. 日経電子版では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が中央集権的ではある

    View full-size slide

  9. Gateway方式
    10
    ● 認証、認可も担当
    ○ 認可は結局サービス側のレイヤーでやる
    ことも多い
    ● 概念上はGateway方式でも画像の配信
    サービスなどは直接通信
    ● 旧APIのラッパー的役割も

    View full-size slide

  10. サイズが小さい✔
    11
    ● PythonはDjangoベース
    ○ 基本的には2−3個のアプリケーションフォ
    ルダがあるだけ
    ○ Gatewayだけはフォルダ多い
    ● NodeJSはexpressベース
    ○ 数百行レベルのコード

    View full-size slide

  11. 自律的に開発が可能✔
    12
    ● DBなどリソースのシェアはしない
    ○ S3を経由してシェアとかはある
    ● サービス間はAPI経由でのやり取り
    ● 基本的にステートレス
    ● 自律的にできるが、各自バラバラに作ると
    非生産的
    ● 雛形からベースのサービスを作成

    View full-size slide

  12. 雛形からサービスを作成
    13

    View full-size slide

  13. 雛形に含まれているもの
    14
    ● requirements.txt
    ● tox.ini
    ○ テスト実行とflake8による静的解析
    ● Djangoアプリケーション
    ● Dockerfile
    ● ElasticBeanstalkの設定ファイル
    ● CircleCIの設定ファイル など

    View full-size slide

  14. cookiecutterで対話的に作成
    15
    pip install cookiecutter
    cookiecutter gh:Nikkei/django-project-template
    対話形式でいくつか値を入力
    ● repo_name: GitHub用のリポジトリ名
    ● project_name: Djangoプロジェクトの名前
    ● subdomin: サーバーのサブドメインに使用する文字列
    ● short_description: リポジトリの一行での説明

    View full-size slide

  15. 雛形への追随
    16
    pip install git+https://github.com/hirokiky/cookiepatcher
    cookiepatcher
    ● レガシー化させない
    ● KYさん作
    ● 最新のテンプレートに追随
    ○ Djangoなどのライブラリのアップデート
    ● cookiepatcher.jsonで差分を管理

    View full-size slide

  16. Private PyPI
    17
    ● 各サービスで使う固有の処理を共通化
    ○ 記事のIDの変換
    ○ CMS独自の専用タグの置き換え処理
    requirements.txt:
    --extra-index-url https://xxx.x/xxxxx/packages/simple/
    nikkei-utils==0.6
    PyPIの自社専用版、各リポジトリでのコードの重複を避ける

    View full-size slide

  17. Private PyPI (2)
    18
    1. python setup.py sdist を実行
    2. dist/ 以下にできた xx.0.1.tar.gz のようなファイルを
    packages リポジトリの 指定ディレクトリにコピー
    3. ファイルを add してpushするとCircleCIから自動でアッ
    プロードされる
    通常のPyPIへの登録とやることはあまり変わらない

    View full-size slide

  18. 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)

    View full-size slide

  19. 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サーバーから社内専用の共通ライブラリを取得できる

    View full-size slide

  20. ローカル開発環境
    21
    ● API開発なら特に問題なし
    ○ python manage.py runserver
    ○ Dockerも使わなくていい
    ○ 単独で動作確認しやすい
    ● フロントエンド開発の時はややこしい
    ○ ルーティングの際に一部のドメインをロー
    カルに振り向ける

    View full-size slide

  21. みんな大好きRest Framework
    22
    ● Django Rest Framework
    ● Django Rest Framework Swagger
    Python/DjangoでAPI作るなら圧倒的な生産性

    View full-size slide

  22. 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)})

    View full-size slide

  23. 独立してデプロイが可能✔
    24
    ● サービスごとにインフラは
    完全分離
    ● ElasticBeanstalk+Docker
    のアプリとして稼働
    ● スケールアウトも容易

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  26. そこで ebi コマンド
    27
    pip install ebi
    ebi deploy
    ● KYさん作
    ● Dockerrun.aws.jsonを環境(本番・開発)に
    合わせて分けられる
    ● Blue/Greenデプロイが可能

    View full-size slide

  27. 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

    View full-size slide

  28. バッチ処理
    29
    Docker
    アプリコンテナ
    Docker
    アプリコンテナ
    Rundeckでのバッチ処理は
    ElasticBeanstalkにデプロイ
    しているものがそのまま使え

    Spotインスタンス
    Docker
    アプリコンテナ

    View full-size slide

  29. Rundeck
    30
    Dockerコンテナを定期タスクで実行

    View full-size slide

  30. 監視、エラーログ
    31
    ● アプリとは別コンテナーのfluentdでログを
    収集
    ○ github.com/bungoume/log-sender
    ● Sentryでエラーログを収集
    ● New Relicでメトリクスデータを収集
    ● CloudWatch
    すべて同じパターンに共通化

    View full-size slide

  31. ログの集約
    32
    各サービス
    Docker
    アプリコンテナ
    Docker
    fluentd コンテナ
    ログ集約サービス

    View full-size slide

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

    View full-size slide

  33. かなり幅広く適用可能なインフラ
    34
    ● Djangoアプリ
    ● NodeJS(express)アプリ
    ● WordPress
    ● Rundeck
    ● Jenkins
    ● Kibana
    ● Nginx+プラグイン
    日経電子版でこれまで実績のあるパターン

    View full-size slide

  34. クラウドの乗り換えもしやすい(はず
    35
    FinancialTimes社のNodeJSのアプリはHeroku上で運用
    同じものがアプリの変更なく、ElasticBeanstalk環境で動かせた

    View full-size slide

  35. 課題
    36
    ● スケールアウトは起動的ではない
    ○ 想定以上のスパイクが来ると間に合わない
    ○ 予測可能場合はスケジューリングして増やす
    ● マメにメンテは必要
    ○ Djangoは1.7 → 1.10に順次更新
    ○ 定期的にrequirements.txtを更新していく
    ● AWS側のバグと付き合う

    View full-size slide

  36. Thanks
    37
    だいたいはこの2人が作ってくれた

    View full-size slide

  37. Thank you!
    38

    View full-size slide

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

    View full-size slide