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

GCP を活用してスケーラブルな CI サービスを作った話

GCP を活用してスケーラブルな CI サービスを作った話

Yoshiyuki Mineo

September 20, 2018
Tweet

More Decks by Yoshiyuki Mineo

Other Decks in Technology

Transcript

  1. 小早川 知昭 Rocro 株式会社 代表取締役社長 ネットワークエンジニア、経営コンサルタントを経て、各社で事業 開発。モバイル管理サービス立ち上げ、クラウド基盤の再構築、ド ローン向けクラウド事業立ち上げ等。2017 年にソニーのグループ 会社として

    Rocro (株)を設立、ソフトウェア開発者向け SaaS を 提供。日本発のグローバルなインフラを目指す。著書に ”IPsec 徹底入門”、共著に ”インターネットルーティング入門”、”IPv6 実践 ガイド”。 Photo Speaker
  2. Rocro とは • 開発者の定常的・共通的タスクを自動化する CI 分野の SaaS 群 ◦ Inpecode

    : 自動コードレビュー&修正サービス ◦ Docstand : API ドキュメント生成&ホスティングサービス ◦ Loadroid : 自動負荷試験サービス • ソニーのクラウド開発から始まる • 回転させながらモノを作るプロの道具:轆轤(ろくろ)とソフトウェア開発の類 似性から命名
  3. Inspecode : コードレビューを SaaS で手間なく廉価 に利用 • GitHub.com / Bitbucket

    のレポジト リと連携、プッシュごとに自動的に静 的解析を実行 • 実行結果はInspecode によるWeb サーバでホスティング • プルリクエストもレビュー • 検出したIssue を自動修正。修正内 容は Pull Request として発行 → エンジニアの修正作業の時間を大幅 に削減 if err != nil { return err } return nil return err
  4. Docstand : API ドキュメント生成&ホスティングサー ビス – GitBook – GoDoc –

    Javadoc – Jekyll – MkDocs – phpDocumentor – ScalaDoc • チーム開発に欠かせないAPI ドキュメントの 生成・維持・公開を、手間なく廉価にサービ ス提供 • レポジトリと連携して、API ドキュメントを自 動生成 • 主要な言語/ツールに対応 – apiDoc – Asciidoctor – Codox – documentation.js – Docurium – Docusaurus – Doxygen – Spectacle – Sphinx – TypeDoc – YARD – YUIDoc
  5. Loadroid : 負荷試験SaaS。シナリオに沿ってクラウ ド上で負荷を自動発生、自動集計 • YAML で負荷試験シナ リオを記述 • シナリオを実現する負

    荷サーバを GCP 上に 自動構築 • 負荷試験を自動実行、 結果を集計 • 負荷試験を CI 化。IoT 機器群も模擬
  6. GKE を活用したインフラで並列実行されるので待ち 時間が非常に短い • 一般的に CI の待ち時間が 30 分な どということはザラ

    • Inspecode は実行するツール群の 依存関係を自動解析し、パイプライ ンを自動生成、並列実行 • 並列実行には GKE を活用(後述) • 他のサービスで 20 − 30 分かかる ところ 5 分で完了するイメージ
  7. Photo 峯尾 嘉征 Rocro 株式会社 代表取締役 CTO ソニー (株) において

    Web ブラウザ、Web サーバ、Web サー ビス共通基盤などの開発を主導。 2017 年に Rocro (株) を設 立 。Node.js の C++ 実装 libnode のほか、Sonyflake、 gobreaker、v8eval など OSS 作成多数。 Speaker
  8. Rocro サービスの構成 App Engine Kubernetes Engine Cloud Datastore Cloud Storage

    Stackdriver Container Registry Cloud Build ユーザリクエストを処理 ユーザジョブを非同期実行
  9. GAE Standard Environment の特徴 ステートレスな Web API サーバ向けのマネージドサービス • インスタンスが高速に起動し迅速にスケール

    ◦ 特に Go 言語の場合、数百 msec で起動 • 制約 ◦ automatic scaling で request timeout 1 分 (task queue 経由なら 10 分) ◦ local disk アクセス不可 (second generation では /tmp にアクセス可) ◦ 言語 / ライブラリに制限あり
  10. GKE の特徴 Kubernetes のマネージドサービス • Kubernetes:コンテナオーケストレーションのデファクト ◦ 他のクラウドベンダーも採用 ◦ Docker

    for Mac/Windows に統合(Swarm と共存) • 汎用的なサーバプラットフォーム ◦ Web API 処理、バッチジョブ etc. ◦ 基本的に GAE で可能なことは GKE でも可能 ▪ CronJob、ノード自動修正など継続的に機能追加
  11. GAE Standard Environment の優位性① • Web アプリ開発に必要な機能がデフォルトで統合 ◦ 非同期処理(Task Queue)

    ◦ インメモリ・キャッシュ(Memcache) ◦ ユーザ認証 ▪ URL パスに対して login: admin / required ◦ ローカル開発環境
  12. GAE Standard Environment の優位性② • 運用が楽 ◦ バージョンアップが簡単 ▪ 同時に複数のバージョンをデプロイ可能

    ▪ トラフィックの割り当てを変更するだけ (ロールバックも容易) ◦ Task Queue によるインスタンス障害対応 ▪ 成功するまでリトライ可能 ▪ Task Queue を一時的に停止してタスクを保留 ▪ 503 やアクセスできないと push rate を自動で低下
  13. GKE の優位性 • ポータビリティ ◦ Docker / OCI Image +

    Kubernetes ベンダーロックインされにくい • 自由度の高さ ◦ 言語 / ライブラリに制限なし ◦ 自在なコンテナ構成(Pod, Service, Namespace)
  14. GAE/GKE の使い分け GAE Standard GKE 参考: GAE Flexible 用途 Web

    API サーバ 汎用 汎用 開発運用効率 ◯ △ △ ポータビリティ ☓ ◯ △ 自由度 ☓ ◯ △
  15. Resource Quota • 各コンテナへの CPU / メモリ配分を制限可能 • limit は上限、request

    は下限 ◦ limit を超えるリソースは割り当てられない ◦ 空きリソースが request 未満なら配置されない resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"
  16. インスタンスタイプ選択のトレードオフ② • インスタンス数が多い方がインスタンス障害に強い • デフォルトで各インスタンス最大 110 Pod の制限があり、 小さい Pod

    を多数実行する場合は、大きいインスタンスを 使い切れない場合もあるので注意 ◦ 例:n1-standard-64 > cpu: 0.5 × 110 ◦ GKE において現在この制限は変更不可
  17. Namespace • 仮想クラスタ ◦ オブジェクト (Pod, Service, etc.) をグループ化 ◦

    オブジェクト名のスコープを提供 • 同一の物理クラスタの上に複数の Namespace を配置可能 ◦ 動的に生成/削除可能
  18. Namespace の使い所 物理クラスタを共有してリソースの利用効率を改善 • チームや Web アプリごとに Namespace を分ける •

    全体でコストを分担し、大きいインスタンスを多数使用 → 利用効率改善とインスタンス冗長化の両方を狙える
  19. Namespace Resource Quota Namespace にも Resource Quota を設定可能 • 仮想的なリソース空間

    • Namespace 内の全コンテナの request / limit の合計値を制限 ◦ コンテナと違って request で指定された物理リソースは不要 ◦ request / limitを動的に変更可能
  20. Namespace Resource Quota の注意点 • Namespace で request / limit

    を設定 → コンテナでも request / limit の設定が必須になる • 複数の Namespace を共存させて安定的に運用するために Namespace に request / limit を指定 → 各コンテナの必要リソースの見積もりが必須
  21. Namespace のトレードオフ • Pros ◦ クラスタを複数の Namespace で共有して リソースの利用効率を改善 •

    Cons ◦ 安定運用のために Namespace / コンテナに quota を設定 → 安全マージンが積み重なって利用効率が悪化 • シンプルに複数のクラスタを運用するのも選択肢の1つ
  22. Cloud Build の活用 1. Cloud Build を利用する理由 2. 他の CI

    サービスとの比較 3. ビルドの並列実行 4. 各種 TIPS
  23. 2. 他 CIサービスの実行環境比較 Circle CI Travis CI Google Cloud Build

    CPU Xeon 2.3G 2-core Xeon 2.6G 2-core n1-standard-1 (Xeon 2.6G 1-core) n1-highcpu-8 (Xeon 2.3G 8-core) n1-highcpu-32 (32-core) Memory 8GB 4GB / 7.5GB n1-standard-1 (3.75GB) n1-highcpu-8 (7.2GB) n1-highcpu-32 (28.8GB) Storage 10GB 4GB 100GB~ Swap swapon可能 swapon可能 swapon不可 Cost Free - 1x 1500min $150/mo - 4x unlimited $350/mo - 8x unlimited 2x build $69/mo - 1x unlimited $129/mo - 2x unlimited $249/mo - 4x unlimited $0.003/min $0.016/min $0.064/min https://bit.ly/2o6eSj1 https://bit.ly/2o60lUt 120分 / 日の無料枠 出典:
  24. ローカル環境でのデバッグが可能 $ cloud-build-local -config cloudbuild.yaml --no-source 2018/08/27 09:11:54 RUNNER -

    [docker ps -a -q --filter name=step_[0-9]+|cloudbuild_|metadata] 2018/08/27 09:11:54 RUNNER - [docker network ls -q --filter name=cloudbuild] 2018/08/27 09:11:54 RUNNER - [docker volume ls -q --filter name=homevol|cloudbuild_] 2018/08/27 09:11:56 Error merging substitutions and validating build: Error validating build: invalid .steps field: cannot specify more than 100 build steps
  25. Cloud Build Limitations // MaxTimeout is the maximum allowable timeout

    for a build or build step. MaxTimeout = 24 * time.Hour maxNumSteps = 100 // max number of steps. maxNumEnvs = 100 // max number of envs per step. maxNumArgs = 100 // max number of args per step. maxNumImages = 100 // max number of images. maxNumSubstitutions = 100 // max number of user-defined substitutions. maxSubstKeyLength = 100 // max length of a substitution key. maxSecretSize = 2048 // max size of a secret https://bit.ly/2PAoxe6 cloud-build-local のソースコードを参照
  26. Reserved Volume Paths reservedVolumePaths = map[string]struct{}{ "/workspace": struct{}{}, "/builder/home": struct{}{},

    "/var/run/docker.sock": struct{}{}, } https://bit.ly/2Nd7FbD Docker in Dockerの為
  27. 3つのコンテナ並列ビルド steps: - id: fetch-source - id: build-container1 waitFor: [

    'fetch-source' ] - id: build-container2 waitFor: [ 'fetch-source' ] - id: build-container3 waitFor: [ 'fetch-source' ]
  28. steps: - id: fetch-source waitFor: [ '-' ] - id:

    pull-build-container waitFor: [ '-' ] - id: build-container1 waitFor: [ 'fetch-source', 'pull-build-container' ] - id: build-container2 waitFor: [ 'fetch-source', 'pull-build-container' ] - id: build-container3 waitFor: [ 'fetch-source', 'pull-build-container' ] 共通カスタムコンテナ読み込みの並列化
  29. git のコミット時のタイムスタンプ付与 Setting the timestamps of the files to the

    commit timestamp of the commit which last touched them git のコミットログの時刻をファイルに付与するスクリプトを利用 これを利用して生成物をビルド前に読み込むことでキャッシュとして利用 可能 https://bit.ly/2P1bcdz
  30. ビルドステップからビルドをリクエスト steps: - name: ubuntu entrypoint: bash args: - '-c'

    - | cat << EOF > cloudbuild.yaml steps: - name: ubuntu entrypoint: date EOF - name: gcr.io/cloud-builders/gcloud args: - builds - submit - --config - cloudbuild.yaml - --no-source トリガから起動されたビルドから、さらに並列ビルドのリクエス トを発行することが可能
  31. FETCHSOURCE BUILD Starting Step #0 - "step1" Step #0 -

    "step1": Already have image (with digest): ubuntu Finished Step #0 - "step1" Starting Step #1 - "step2" Step #1 - "step2": Already have image (with digest): gcr.io/cloud-builders/gcloud Step #1 - "step2": Created [https://cloudbuild.googleapis.com/v1/projects/codelift-plugins-test/builds/e6f4d3d0-e2ae-4035-9a15-8210dbef7 035]. Step #1 - "step2": Logs are available at [https://console.cloud.google.com/gcr/builds/e6f4d3d0-e2ae-4035-9a15-8210dbef7035?project=407066390234]. Step #1 - "step2": ----------------------------- REMOTE BUILD OUTPUT ------------------------------ Step #1 - "step2": starting build "e6f4d3d0-e2ae-4035-9a15-8210dbef7035" Step #1 - "step2": Step #1 - "step2": FETCHSOURCE Step #1 - "step2": BUILD Step #1 - "step2": Already have image (with digest): ubuntu Step #1 - "step2": Fri Aug 3 01:16:16 UTC 2018 Step #1 - "step2": PUSH Step #1 - "step2": DONE Step #1 - "step2": -------------------------------------------------------------------------------- Step #1 - "step2": Step #1 - "step2": ID CREATE_TIME DURATION SOURCE IMAGES STATUS Step #1 - "step2": e6f4d3d0-e2ae-4035-9a15-8210dbef7035 2018-08-03T01:16:10+00:00 6S - - SUCCESS Finished Step #1 - "step2"