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

fourkeys基盤を構築した話

uncle
September 12, 2022

 fourkeys基盤を構築した話

uncle

September 12, 2022
Tweet

Other Decks in Technology

Transcript

  1. fourkeys基盤を構築した話
    Kyash TechTalk #4 - Serversideと新しい挑戦
    2022-09-12
    @uncle__ko

    View Slide

  2. 自己紹介
    kohei ouchi(@uncle__ko)
    主にお金周りのシステムを作ってた
    今はTechチームの生産力向上のために頑
    張ってる
    プライベートでは5歳児のパパとして育児に励
    んでる

    View Slide

  3. Agenda
    ● 生産性の可視化
    ● fourkeys基盤の概要
    ● デプロイ頻度の計測
    ● リードタイムの計測
    ● Incident flowの整備
    ● incidents view
    ● merged_pull_requests view
    ● 変更障害率の計測
    ● サービス復元時間の計測
    ● さいごに

    View Slide

  4. 生産性の可視化

    View Slide

  5. そもそもなんで計測するの?
    KyashのTechチームでは生産力を3倍にするという目標を置いてる
    Techチームの価値は、最終的に「世の中=ユーザ」に何を届けたかだと思っている
    技術的負債の解消、Incident件数の含めて生産力を上げていく
    3倍にするにあたり、現状の課題や生産性を可視化する必要があると考えた

    View Slide

  6. そもそもなんで計測するの?
    計測するにあたり指標をどうするかを考えfourkeysを採用した
    理由は下記
    ● 定量的に計測できる
    ○ 定義を明確にすれば計測できる
    ● 世の中の水準で現状を評価できる
    ○ Google Cloudで実行されているDevOps組織の有効性を評価する にもあるように、それぞれの
    KeyごとにElite、High、Medium、Lowの4レベルで評価できる
    ● 自動化できる
    ○ GitHubやSlack、CircleCI等のAPIを使って自動計測が可能

    View Slide

  7. Google Cloud で実行されている DevOps 組織の有効性を評価する より引用

    View Slide

  8. 計測対象
    fourkeysのそれぞれの定義は各社・各Teamで決めてよいとされてるが、Kyashでは
    DORA(DevOps Research and Assessment)に合わせて下記のように定義してる
    指標 概要
    デプロイ頻度 組織による正常な本番へのリリース頻度
    変更のリードタイム commitから本番環境稼働までの所要時間
    変更障害率 デプロイが原因で本番環境で障害が発生する割合 (%)
    サービス復元時間 組織が本番環境での障害から回復するのに掛かる時間

    View Slide

  9. 詳しくはBlogを書いてるので、興味があれば読んでみてください
    https://blog.kyash.co/entry/2022/06/15/170000
    そもそもなんで計測するの?

    View Slide

  10. fourkeys基盤の概要

    View Slide

  11. fourkeysの概要
    Kyashでは https://github.com/GoogleCloudPlatform/fourkeys をforkして使っている
    理由は下記
    ● GCPのfourkeysが普通にイケてる
    ● GitHub,CircleCi,Tekton,Cloud Build,PagerDutyのイベントハンドリング処理がす
    でに用意されている
    ● Terraform管理されてる
    ● あまり工数を掛けずに自分たちで構築できそうであった

    View Slide

  12. アーキテクチャ

    View Slide

  13. Dashboard

    View Slide

  14. あえてイケてないところをあげるなら
    ● 比較的あたらしいRepoなので小さなバグは多い
    ● チームメンバー含めてPRを5つくらい上げてるけど反応が遅い
    ● 今はShell Scriptとterraform二つ使っているが、terraform側に寄せようとしてい
    る?ようで、今後大きな変更が入る可能性が高い

    View Slide

  15. デプロイ頻度の計測

    View Slide

  16. デプロイ頻度の計測
    デプロイ頻度とは本番環境へリリースした回数
    以下の条件に合致するのもをデプロイと判断
    ● branchがmain or master
    ● job名(GitHubActionsの場合はcheck_run.name、CircleCIの場合はjob.name)に
    Deploy or deployが含まれている

    View Slide

  17. deployments View
    スキーマはこんな感じ

    View Slide

  18. Query
    SELECT
    TIMESTAMP_TRUNC(time_created, DAY) AS day,
    COUNT(distinct deploy_id) AS deployments
    FROM
    four_keys.deployments
    GROUP BY day;

    View Slide

  19. 過去分のイベント
    過去分のイベントが取れると生産性が上がりましたと言いやすい
    トランクベース開発はすでに始まっていたりする
    期間を指定すると、その期間内のデプロイをfetchしてBigQueryにinsertするGoの
    Scriptを作ったりもした

    View Slide

  20. リードタイムの計測

    View Slide

  21. リードタイムの計測
    リードタイムとはcommitが本番環境にデプロイされるまでの時間の中央値
    Mergeでのpushイベントに、そのpushに含まれるcommit配列がある。それぞれの commitのpushした時刻との
    差を取ればいい
    pushイベントのcommitsとはなにか?
    ● https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-paylo
    ads#push
    なので、deployments.changesにあるcommitはmainへのmerge用PRに出てくるdiffのcommitと同じ

    View Slide

  22. changes View
    スキーマはこんな感じ

    View Slide

  23. SELECT
    day,
    IFNULL(ANY_VALUE(med_time_to_change)/60, 0) AS median_time_to_change, # Hours
    FROM (
    SELECT
    d.deploy_id,
    TIMESTAMP_TRUNC(d.time_created, DAY) AS day,
    PERCENTILE_CONT(
    # Ignore automated pushes
    IF(TIMESTAMP_DIFF(d.time_created, c.time_created, MINUTE) > 0, TIMESTAMP_DIFF(d.time_created, c.time_created, MINUTE), NULL), 0.5) # Median
    OVER (PARTITION BY TIMESTAMP_TRUNC(d.time_created, DAY)) AS med_time_to_change, # Minutes
    FROM four_keys.deployments d, d.changes
    LEFT JOIN four_keys.changes c ON changes = c.change_id
    )
    GROUP BY day ORDER BY day;
    Query

    View Slide

  24. Incident Flowの整備

    View Slide

  25. KyashではwikiツールとしてKibelaを使っている
    https://kibe.la/
    incidentはもともとKibelaにまとめられていた
    GoogleCloudPlatform/fourkeysはGitHub/GitLab/PagerDutyに対応してる
    Kibelaもparserさえ作れれば対応自体はできる
    が、KibelaのAPIでは更新された場合を考えると少し貧弱であったためGitHubのIssue
    にしたかった
    Incident Flowの整備

    View Slide

  26. なにをしたのか
    有識者を集めてIncidentフローにGitHub Issueをいれたい
    もしくは自動計測しやすいなにかにしたい旨のMTGを開催
    理想はGitHub Issueへの統一だったが、Engineer以外がGitHubのアカウントをもって
    いないこともありKibelaに概要を、詳細はGitHub Issueにまとめる運用になった

    View Slide

  27. 実際に作ったIssue Template
    Kyash/incidentというIncident管理用のRepoを作成

    View Slide

  28. 実際に作ったIssue Template

    View Slide

  29. incidents View

    View Slide

  30. incidents View
    view自体はevents_rowから下記条件で取得
    - sourceがgithub
    - repoがKyash/incident
    - actionがclose
    正規表現で時刻やPRを習得している

    View Slide

  31. incidents View
    一応ReOpenの考慮も入れている
    マイクロサービスごとに集計するためにincident issueにlabelでマイクロサービス名を付
    与してもらう運用
    from句で下記のようなことをしたり
    select句でこんなことしたりしてる

    View Slide

  32. incidents View
    スキーマはこんな感じ

    View Slide

  33. merged_pull_requests View

    View Slide

  34. merged_pull_requests View
    本家ではIssueの中に原因となったcommit hashを含めよ的なノリ
    https://github.com/GoogleCloudPlatform/fourkeys/blob/main/queries/incidents.sql#
    L25
    しかし、IncidentがIssueとKibelaに別れて面倒になってるのにcommit hashまで取って
    くるのはさすがに...
    原因になったPRのリンクだけ貼ってもらいcommit hashは別途たどるために本家には
    ないviewを追加

    View Slide

  35. merged_pull_requests View
    # Merged Pull Request Table
    SELECT
    JSON_EXTRACT_SCALAR(metadata, '$.pull_request.html_url') AS url,
    PARSE_TIMESTAMP('%Y-%m-%dT%H:%M:%SZ',JSON_EXTRACT_SCALAR(metadata, '$.pull_request.created_at')) AS time_created,
    PARSE_TIMESTAMP('%Y-%m-%dT%H:%M:%SZ',JSON_EXTRACT_SCALAR(metadata, '$.pull_request.merged_at')) AS time_merged,
    JSON_EXTRACT_SCALAR(metadata, '$.pull_request.merge_commit_sha') AS commit_sha,
    JSON_EXTRACT_SCALAR(metadata, '$.pull_request.base.repo.name') AS repository
    FROM
    `four_keys.events_raw`
    WHERE
    source = 'github'
    AND event_type = 'pull_request'
    AND json_extract_scalar(metadata, '$.pull_request.merged') = 'true'
    AND json_extract_scalar(metadata, '$.action') = 'closed'
    GROUP BY 1,2,3,4,5

    View Slide

  36. merged_pull_requests View
    スキーマはこんな感じ

    View Slide

  37. 変更障害率の計測

    View Slide

  38. 変更障害率の計測
    本家はcommit単位で計測している
    が、現状のKyashには明確なcommit単位の基準が存在しないので人によってブレる可
    能性がある
    そのためKyashではDeploy単位での集計とした
    (incident数)/(本番へのdeploy数)

    View Slide

  39. Query
    SELECT
    TIMESTAMP_TRUNC(d.time_created, DAY) as day,
    IF(COUNT(DISTINCT d.deploy_id) = 0, 0, SUM(IF(i.incident_id is NULL, 0, 1)) / COUNT(DISTINCT d.deploy_id)) as change_fail_rate,
    d.repository as metric,
    FROM four_keys.deployments d, d.changes
    LEFT JOIN four_keys.merged_pull_requests m ON changes = m.commit_sha and m.repository = d.repository
    LEFT JOIN four_keys.incidents i ON i.cause_pr_url = m.url
    GROUP BY day, d.repository
    ORDER BY day

    View Slide

  40. サービス復元時間の計測

    View Slide

  41. サービス復元時間の計測
    サービス復元時間とは障害の発生時間から収束時間までの中央値
    この発生時間から収束時間というのは機械的に計測できる場合もあるが、パターンに
    よっては難しい場合もある(PRに起因してない障害等)
    そのため、Incidentレポート用のIssueに人の手で記載してもらう
    Incident IssueがCloseしたタイミングでIssueをParseして計測する

    View Slide

  42. Query
    SELECT
    day,
    label as metric,
    daily_med_time_to_restore
    FROM (
    SELECT
    TIMESTAMP_TRUNC(time_created, DAY) AS day,
    label,
    #### Median time to resolve
    PERCENTILE_CONT( TIMESTAMP_DIFF(time_resolved, time_created, HOUR), 0.5) OVER(PARTITION BY TIMESTAMP_TRUNC(time_created, DAY), label ) AS daily_med_time_to_restore,
    FROM
    four_keys.incidents,
    UNNEST(label_names) AS label
    )
    GROUP BY
    day, label, daily_med_time_to_restore
    ORDER BY
    day

    View Slide

  43. さいごに

    View Slide

  44. さいごに
    やっと生産性を推測ではなく、計測できる状態が作れた
    GCPのfourkeysはイケてる部分が多いので、forkして自分たちに合うように微調整すれ
    ば使える
    今後はこのfourkeys基盤をもとに分析していくフェーズ
    TryとしてSprintのはじめに分析する時間を設けるようにしている
    可視化することで改めてわかってくることもある
    推測ではなく計測した結果で生産性向上のための策を打っていく

    View Slide

  45. ご清聴ありがとうございました

    View Slide