深夜の怠惰な技術ブログ

日々の技術的な話題などを徒然なるままに

GitLab CI/CDにおけるTerraform Moduleについて

はじめに

本投稿ではTerraform Moduleにおいて別GitLabリポジトリを参照する場合におけるTipsを記載していきたいと思います。 また、今回はTerraform Moduleの詳細については割愛させていただきますので、あらかじめご容赦下さい。

Terraform Moduleの設定

Terraform ModuleのsourceにてGitLabレポジトリを指定する必要がありますがサンプルは以下となります。 今回は例としてAWSリソースのVPCを作成するTerraform ResourceコードがGItLabリポジトリsample-terraform-vpc-moduleに格納されているとします。 また、該当リポジトリのcommitにはtagがふられており、refによって該当tagのcommitを参照するようになっています。

module "network" {
  source = "git::ssh://git@gitlab.com/<your_group>/sample-terraform-vpc-modules.git//terraform?ref=v0.0.1"
}

詳細は以下の公式ドキュメントをご覧ください。

www.terraform.io

対象リポジトリへのアクセス方法

GitLab CIにてTerraform Moduleを適用する際には、その参照先のリポジトリsample-terraform-vpc-moduleへのアクセスが必要となります(ダウンロードするために)。 そのため、権限が必要になるのですが、ここではその設定方法について説明していきたいと思います。 Terraform Moduleの設定では、対象sourceをsshによってアクセスするようにしています。しかしながら、GitLab CIではこれをhttpによるアクセスに変更してあげることで、GitLab CI上に定義された環境変数CI_JOB_TOKENを利用して権限の問題を解消することができます。GitLab CI/CDにおける定義済み環境変数については以下をご覧下さい。

gitlab-docs.creationline.com

以下が.gitlab-ci.ymlにおける該当部分のサンプルコードです。

before_script:
  - git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/<your_group>/sample-terraform-vpc-module.git".insteadOf ssh://git@gitlab.com/<your_group>/sample-terraform-vpc-module.git

今回はbefore_scriptにて設定を記述しているのですべてのJobで適用される形になりますが、ユースケースにより必要なJob内で個別に実行していただいても構わないと思います。

さいごに

いかがだったでしょうか。分かってしまえば簡単かもしれませんが、個人的には大変学びになりました。 誰かのお役に立てれば幸いです。

GitLab CI/CD PipelineにおけるAWS IAM Roleでのクレデンシャル取得の方法とJobでの継承について

はじめに

以前のブログでGitHub ActionsにてAWSリソースをIaC(Terraform、AWS CDK等々)によって構築する際のIAM Roleにおける権限付与の話を書きました。 詳しくは以下をご覧ください。 ymmryt.hatenablog.com

今回はGitLab CI/CD Pipelineにおいて、同様の観点からブログを記載していこうと思います。また、各Jobにおいて取得したクレデンシャルを継承していくことで都度取得する手間からも解放していきたいと思います。

Terraformによる必要リソースの作成

GItHub Actionsの時と同様に、IAM Roleに対するAssume Roleを可能にするためには大きく3つのコンポーネントが必要となります。

  • IAM OIDC Provider
  • IAM Role
  • IAM Policy

今回はIAM OICD ProviderとIAM Roleについて記載していきたいと思います。なぜならば、IAM Policyについては読者の方々が適切な権限を選定していただくことになります。また、IAM Policyの作成に関するTerraformの知見はインターネットに無数に転がっているため、ここでは割愛させていただきます。

IAM OIDC Providerの作成

ますは、ID Providerを作成します。

data "http" "gitlab_openid_configuration" {
  url = "https://gitlab.com/.well-known/openid-configuration"
}

data "tls_certificate" "gitlab" {
  url = jsondecode(data.http.gitlab_openid_configuration.body).jwks_uri
}

resource "aws_iam_openid_connect_provider" "gitlab" {
  client_id_list  = ["https://gitlab.com"]
  thumbprint_list = [data.tls_certificate.gitlab.certificates[0].sha1_fingerprint]
  url             = "https://gitlab.com"
}

まずは、OICD Providernいおけるサムプリントの取得を実施する必要があります。詳細については以下をご覧いただければと思いますが、Terraformコードにおける重要な部分はdata resourceで記述されている部分です。 基本的に、OIDCの規格は同じなので、上記のようにすればGitHub ActionsやCircle-ciでも同様の記述を行うことができるはずです。

docs.aws.amazon.com

IAM Roleの作成

次は、IAM Roleを作成します。

resource "aws_iam_role" "gitlab_assume_role" {
  name = "gitlab-assume-role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = ["sts:AssumeRoleWithWebIdentity"]
        Principal = {
          Federated = aws_iam_openid_connect_provider.gitlab.arn
        }
        Condition = {
          StringLike = {
            "gitlab.com:sub" = "project_path:<my_group>/<my_project>:*"
          }
        }
      }
    ]
  })
}

GitHub Actionsの時とあまり変わらないのですが、念の為説明をしていきたいと思います。 まず、PrincipalにおけるFederatedの値は前セクションで作成したOICD ProviderのARNを指定しています。 これにより、該当OICD Providerが本IAM RoleへのAssume Roleを許可していることになります。 ただし、これだけですと他のGitLab CI/CD PipelineからもAssume Roleが許可されている状況となってしまうため、Conditionによる制限が必要になってきます。具体的には以下の部分です。

Condition = {
  StringLike = {
    "gitlab.com:sub" = "project_path:<my_group>/<my_project>:*"
  }
}

<my_group>と__<my_project>については各自の値になります。 これらのTerraformコードを記述してapplyを実施することにより、必要なリソースが作成されます。

.gitlab-ci.ymlの記述について

上記で必要なリソースが作成されたので、次はgitlab-ci.ymlについて書いていきたいと思います。 サンプルは以下のコードとなります。

image:
  name: hashicorp/terraform:1.1.9
  entrypoint: [""]

stages:
  - assume_role
  - plan

before_script:
  - apk update --no-cache && apk add --no-cache aws-cli jq

assume_role:
  stage: assume_role
  script:
    - >
      credentials=`aws sts assume-role-with-web-identity
      --role-arn ${ROLE_ARN}
      --role-session-name "GitLabRunner-${CI_PROJECT_ID}-${CI_PIPELINE_ID}"
      --web-identity-token $CI_JOB_JWT_V2
      --duration-seconds 3600 | jq .Credentials`
    - export AWS_ACCESS_KEY_ID=`echo ${credentials} | jq -r .AccessKeyId`
    - export AWS_SECRET_ACCESS_KEY=`echo ${credentials} | jq -r .SecretAccessKey`
    - export AWS_SESSION_TOKEN=`echo ${credentials} | jq -r .SessionToken`
    - echo COMMON_AWS_ACCESS_KEY_ID=`echo ${credentials} | jq -r .AccessKeyId` >> assume_role.env
    - echo COMMON_AWS_SECRET_ACCESS_KEY=`echo ${credentials} | jq -r .SecretAccessKey` >> assume_role.env
    - echo COMMON_AWS_SESSION_TOKEN=`echo ${credentials} | jq -r .SessionToken` >> assume_role.env
    - aws sts get-caller-identity
  artifacts:
    reports:
      dotenv: assume_role.env

plan:
  stage: plan
  script:
    - export AWS_ACCESS_KEY_ID=`echo ${COMMON_AWS_ACCESS_KEY_ID}`
    - export AWS_SECRET_ACCESS_KEY=`echo ${COMMON_AWS_SECRET_ACCESS_KEY}`
    - export AWS_SESSION_TOKEN=`echo ${COMMON_AWS_SESSION_TOKEN}`
    - aws sts get-caller-identity
  dependencies:
    - assume_role

クレデンシャルの取得について

作成したIAM RoleにAssume Roleを実施して、クレデンシャルを取得し、環境変数へ格納する部分だけを抜粋すると以下の部分になります。${ROLE_ARN}はGitLab CI/CDのValiablesにて管理されている変数となります。その他の変数については予めGitLab側で用意されているものですので、特段気をつける必要はありません。 結局のところ、AWS CLIで必要な情報を取得しているだけですね。

script:
    - >
      credentials=`aws sts assume-role-with-web-identity
      --role-arn ${ROLE_ARN}
      --role-session-name "GitLabRunner-${CI_PROJECT_ID}-${CI_PIPELINE_ID}"
      --web-identity-token $CI_JOB_JWT_V2
      --duration-seconds 3600 | jq .Credentials`
    - export AWS_ACCESS_KEY_ID=`echo ${credentials} | jq -r .AccessKeyId`
    - export AWS_SECRET_ACCESS_KEY=`echo ${credentials} | jq -r .SecretAccessKey`
    - export AWS_SESSION_TOKEN=`echo ${credentials} | jq -r .SessionToken`

環境変数の継承について

Job間では基本的には環境変数は共通化されていません。そのため、Job1で設定した環境変数はJob2では利用できなくなっています。今回のクレデンシャルの場合、各Jobで都度取得してもいいのですが、せっかくなら継承していきたいと思いまして調べました。 まずは、環境変数を別のJobでも利用できるようにするめの格納からですが、該当コードは以下の部分となります。

    - echo COMMON_AWS_ACCESS_KEY_ID=`echo ${credentials} | jq -r .AccessKeyId` >> assume_role.env
    - echo COMMON_AWS_SECRET_ACCESS_KEY=`echo ${credentials} | jq -r .SecretAccessKey` >> assume_role.env
    - echo COMMON_AWS_SESSION_TOKEN=`echo ${credentials} | jq -r .SessionToken` >> assume_role.env
  artifacts:
    reports:
      dotenv: assume_role.env

artifacts以下の記述によって、envファイルが他のJobでも参照できるようになります。 そして、環境変数を参照する場合、その処理を記述しているのは以下のコードとなります。

  script:
    - export AWS_ACCESS_KEY_ID=`echo ${COMMON_AWS_ACCESS_KEY_ID}`
    - export AWS_SECRET_ACCESS_KEY=`echo ${COMMON_AWS_SECRET_ACCESS_KEY}`
    - export AWS_SESSION_TOKEN=`echo ${COMMON_AWS_SESSION_TOKEN}`
 dependencies:
    - assume_role

継承にはdependenciesキーワードを利用する方法とneedsキーワードを利用する方法の2パターンがあるようですが、今回は前者を利用しました。 詳細については以下の公式ドキュメントを参考にしてください。

gitlab-docs.creationline.com

さいごに

いかがでしたでしょうか。GitLab CI/CDを利用している方も多いのではないでしょうか。そういった方々へAWSリソースの構築の一助になれば幸いです。

GitHub Actionsの実行に向けたTerraformによるAWS IAM Roleの作成について

はじめに

GitHub ActionsにてAWSリソースをIaC(Terraform、AWS CDK等々)によって構築する際、従来はGitHub Actions用のIAM Userを作成して、権限を付与する方法が一般的であったかと思います。 しかしながら、現在はIAM Roleによる権限付与の方法が確立されました。このIAM Roleの作成をTerraformによってどのように記述するのかをポイントに本投稿を記載します。

TerraformによるIAM Roleの作成

GitHub Actions用のIAM Roleを作成する際に必要となるコンポーネントは以下の3つとなります。

  • IAM ID Provider
  • IAM Role
  • IAM Policy

    IAM ID Provider

    まずは、ID Providerを作成します。これにより、AWSの外部ユーザIDにアカウント内のAWSリソースに対するアクセス許可を与えることができます。

resource "aws_iam_openid_connect_provider" "github" {
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = ["a031c46782e6e6c662c2c87c76da9aa62ccabd8e"]
  url             = "https://token.actions.githubusercontent.com"
}

client_id_list は対象者もしくはaudienceとも呼ばれるものを指定します。 ここでは、sts.amazonaws.com と記述しています。 これは、GitHub Actionsで利用する actions/configure-aws-credentials@v1 の要求からくるものです。

thumprint_listOpenID Connect Providerがキーを利用できるようにするドメインで使用されるX.509証明書の16進エンコードされたSHA-1ハッシュ値です。 AWSマネジメントコンソールからID Providerを作成する際には、ProviderのURLを入力すると動的に設定してくれますが、今回はTerraformによる設定のため記述が必要になります。

IAM Role

先にID ProviderのTerraformコードができたので、次にIAM Roleを作成します。 このIAM Roleの信頼関係では、先のID ProviderからのAssume Roleを許可する必要があります。 また、特定のGitHubリポジトリからのGitHub Actionsのみを許可するための設定も必要となります。 これらの設定を反映したTerraformコードが以下となります。

resource "aws_iam_role" "github" {
  name = "GithubActionRole"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = ["sts:AssumeRoleWithWebIdentity"]
        Principal = {
          Federated = aws_iam_openid_connect_provider.github.arn
        }
        Condition = {
          StringLike = {
            "token.actions.githubusercontent.com:sub" = "repo:<GitHub Organization>/<Repository Name>:*"
          }
        }
      }
    ]
  })
}

特定のGitHubリポジトリからのGitHub Actionsのみを許可する設定は、以下の部分に該当します。

Condition = {
  StringLike = {
    "token.actions.githubusercontent.com:sub" = "repo:<GitHub Organization>/<Repository Name>:*"
  }
}

ただし、これだと特定の単一GitHubリポジトリのみが対象となります。 そのため、例えば複数のGitHubリポジトリを指定したい場合には配列による指定が可能です。

Condition = {
  StringLike = {
    "token.actions.githubusercontent.com:sub" = [
      "repo:<GitHub Organization>/<Repository Name A>:*",
      "repo:<GitHub Organization>/<Repository Name B>:*",
    ]
  }
}

また、特定のGitHub Organizationの任意のリポジトリを指定することも可能となります。

Condition = {
  StringLike = {
    "token.actions.githubusercontent.com:sub" = "repo:<GitHub Organization>/*:*"
  }
}

いずれにせよ、上記のような Condition句 の記載がない場合にはどのようなリポジトリからのGitHub Actionsも対象となってしまうのでご注意ください。

IAM Policy

先に作成したIAM Roleに付与するIAM Policyを作成します。つまり、GitHub Actionsに許可するPolicyを設定するということです。 IAM Policyを作成するためのTerraformコードについてはTerraformのドキュメントや他ブログなどでも詳細な記述があると思いますので、ここでは割愛します。

GitHub Actionsの実行について

最後に、GitHub Actionsにて先に作成したIAM RoleへどのようにAssume Roleするのかをyamlファイルで記載します。

name: 'Sample'
on:
  push:
    branches:
      - main
env:
  AWS_REGION: 'ap-northeast-1'
jobs:
  cdk:
    name: 'Sample Action'
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    defaults:
      run:
        shell: bash
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          role-to-assume: ${{ secrets.ROLE_ARN }}
          aws-region: ${{ env.AWS_REGION }}
      - name: AWS STS Get Caller Identity
        run: aws sts get-caller-identity

今回のようにID Providerを利用する場合には、permission: 以下の内容がまずは必要となります。 そして、要の部分は aws-actions/configure-aws-credentials@v1 です。 このモジュールの引数として role-to-assumeaws-region が必要となります。 この role-to-assume は先に作成したIAM RoleのARNを指定します。 ここでは、GitHubのSecretsに該当ARNを設定しているため、それを呼び出す記述になっています。

さいごに

いかがだったでしょうか。最近ではこれらの内容を紹介するブログが増えているように感じますが、それぞれの設定などを理解するのに少々時間が掛かりました。 また、IAM Role関連の作成はCloudFormationでの紹介が多く、Terraformユーザに少しでも役に立てれば幸いです。

CloudWatch AlarmをAWS ChatbotによりSlackに通知する方法

はじめに

今回は表題通り、CloudWatch AlarmSNSAWS Chatbotを利用したSlack通知の実現方法を記載していきます。 私自身はIaC(Infrastructure as Code)としてはTerraformを利用します。ただし、現在TerraformはAWS Chatbotに対応しておりません。 そのため、AWS ChatbotだけはAWS マネジメントコンソールで作成していきます。また、通知先となるSlack Channelについてはすでに作成済みであることとします。

アーキテクチャ

f:id:ymyuta:20211204145251p:plain
CloudWatch AlarmからSlack ChannelへのAWS Chatbotを利用した通知

CloudWatch Alarmの作成

まずは、CloudWatch Alarmの作成となります。 ここでは、ALB(Application Loadbalancer)TargetgroupにおけるHealthyHostCountに対して、しきい値を設けていきます。 なお、Targetgroupでは1つのHost(ECSにおけるTask)が実行されている状況が正常とします。

resource "aws_cloudwatch_metric_alarm" "sample" {
  alarm_name          = "SampleAlarm"
  alarm_description   = "Sample Alarm Verify For Slack Notification"
  comparison_operator = "LessThanThreshold"
  evaluation_periods  = 1
  datapoints_to_alarm = 1
  metric_name         = "HealthyHostCount"
  namespace           = "AWS/ApplicationELB"
  dimensions = {
    "LoadBalancer" = "app/<alb_name>/exmaple8e4b2d09"
    "TargetGroup"  = "targetgroup/<targetgroup_name>/exampled7739b8e7"
  }
  period        = 60
  statistic     = "Average"
  threshold     = 1
  alarm_actions = [var.cloudwatch_alarm_sns_topic_arn] // 後ほど作成するSNS Topicに対するARNとなります。 
  ok_actions    = [var.cloudwatch_alarm_sns_topic_arn] // 後ほど作成するSNS Topicに対するARNとなります。 
}

上記は、該当のCloudWatch Alarmを作成する上でのTerraformコードになります。ここで重要なポイントにしぼって説明します。

対象となるCloudWatch Metricsの指定方法

今回は先述の通り、対象のCloudWatch MetricsはALB(Application Loadbalancer)TargetgroupにおけるHealthyHostCountとなります。 これらを指定するのに必要な設定値としては、namespacedimensionsmetric_nameです。

しきい値の指定方法

しきい値を指定する設定はthresholdcomparison_operatorになります。 正常なHost数は1であるため、Host数が1未満となったら異常状態とするために、comparison_operatorはLEssThanThresholdとしています。

SNSとの連携

CloudWatch Alarmが取り得る状態としては、異常(Alarm)正常(OK)No Dataの3種類です。 それぞれの状態に遷移した際に、SNSへトピックを発行することができます。 状態ごとに発行先のSNSを指定することができますが、今回はすべて同じSNSを指定しています。 Terraformコードでは対象SNSのARNを記述することになります。

SNSの作成

CloudWatch Alarmがトピックを発行するためのSNSを作成します。

resource "aws_sns_topic" "sample" {
  name = "cloudwatch-alarm-topic"
}

resource "aws_sns_topic_policy" "sample" {
  arn = aws_sns_topic.sample.arn
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = ["sns:Publish"]
        Principal = {
          Service = "cloudwatch.amazonaws.com"
        }
        Resource = aws_sns_topic.sample.arn
        Condition = {
          ArnLike = {
            "aws:SourceArn" = "arn:aws:cloudwatch:<region>:<account_id>:alarm:<alarm_name>"
          }
        }
      }
    ]
  })
}

AWS Chatbotの作成

AWS Chatbotの設定については先述の通りAWS マネジメントコンソールにて実施していきます。 まずは、チャットクライアントの設定にてSlackを指定します。

SlackのPrivate Channelにおける対応について

ひとつだけ、対象のSlack ChannelがPublicの場合には設定はAWS Chatbotのみで完結します。 ただし、Private Channelの場合には対象のChannelに対してAWSユーザをInviteする必要があります。

f:id:ymyuta:20211205144847p:plain
AWS Chatbotにおけるチャットクライアントの設定
f:id:ymyuta:20211205144929p:plain
チャットクライントにおけるSlackの指定
設定を実施すると、Slackへのアクセス許可を求められるので、問題なければ承認を実施します。 問題無く連携が完了したら、新たなChannelを追加することで連携することができます。

さいごに

いかがだったでしょうか。シンプルな内容で学びもそれほど多くはないかもしれませんが、備忘のために記載しました。 引き続き、よろしくお願い致します。

This is Leanを読んで~その2~

はじめに

前回の投稿では、This is Leanを読んで~その1~と題して、リソース効率とフロー効率の概要をScrumの文脈で書いていきました。 今回はリソース効率におけるパフォーマンスへの影響を挙げ、フロー効率との完全なる両立が困難な理由を書いていければと思います。

リソース効率におけるパフォーマンスへの影響

まずは前回の投稿でのリソース効率について簡単に振り返ります。 Scrumを例にとった場合に、リソース効率を高めようとすると以下の図のような状態が予想されます。

f:id:ymyuta:20210923144016p:plain
リソース効率による状態
つまり、開始から完了までの時間が徐々に長くなる、また複数Itemに対するタスクが並列で処理されていくなどの事象が発生します。 これらの事象がパフォーマンスにどのように影響していくかを書いていきます。

長いスループット時間の影響

今までは開始から完了までの時間と書いていましたが、これをスループット時間と言います。 スループット時間とは、フローユニットに対する処理が開始してから完了するまでの時間を指します。 Scrumにおいては、ひとつのPBIをフローユニットといい、そのPBIへの処理が開始されてから完了するまでをスループット時間と呼ぶこととなると思います。 完了が何を指すのかは、Scrumチームにおける完了の定義(Definition of Done)によると思いますが、今回の投稿ではプロダクトを利用しているユーザに対して、PBIによる機能がリリースされたこととします。

スループット時間が長くなるとはどのようなことを意味するのでしょうか。 例えば、開発開始からリリースまでの時間が長くなります。すると、リリース対象の実装がどのようなものだったのかを思い出すことが必要になってくるかもしれません。 この思い出す作業が発生することにより、副次的なタスクとして、リリース対象の実装を別途ドキュメントとして書き出しておいたりといったものが追加される可能性もあります。 このような本来必要のないニーズ(上記の例でいえば、思い出す作業をスムーズにする)といったものを、本書では二次ニーズと呼び、スループット時間が長くなることで二次ニーズが発生しやすくなると書いてあります。 そして、このような二次ニーズにより不要なタスクが発生することも示唆しています。

不要なタスクが発生することで、本来注力すべきタスクに割く時間が減少してしまうのは、Scrumチームのパフォーマンス低下に結びつくのではないでしょうか。

多すぎるフローユニットの影響

リソース効率を高めようとした際には、上図からもわかるように、各engineerに対してフローユニットに関連するタスクに連続的に取り組んでいかなければなりません。つまり、フローユニットが多くなるのが常です。 そのため、Scrumチーム内で様々フローユニットに対するタスクが並列で実施されている状態となります。このような状態において発生する事象はどのようなものがあるでしょうか。

例えば、各engineerが並列するタスクにおいて、ひとつのGit Repositoryの各々のブランチで作業を実施していたとします。そのような場合にはコンフリクトやリベース作業などが発生しやすくなります。 コンフリクトの解消やリベース作業は本来不要なタスクだったかもしれません。並列するタスクを実施することにより、ムダなタスクが発生する可能性が高まることになります。 また、あるengineerが別のengineerが実施したタスクに対して質問したとします。しかし、質問されたengineerは現在はまた別のタスクを実施しており、その質問を答えるために頭の切り替えをしなければならなくなります。 このように、スイッチングコストが高まる可能性もでてきてしまいます。

つまり、フローユニットが多くなると、長いスループット時間の影響と同様にムダなタスクが発生することに加えて、スイッチングコストが高まることによるパフォーマンス低下が生まれてしまうかもしれません。

リソース効率とフロー効率の両立は困難

上記ではリソース効率を高めることで発生し得るパフォーマンスの低下について書きました。 これらの原因としては、長いスループット多すぎるフローユニットなどが挙げられます。 この原因を解消するためのアプローチがフロー効率を高めることとなります。 そのため、フロー効率を高めようとすると必然的にリソース効率は低くなるのです。

f:id:ymyuta:20211004090947p:plain
リソース効率とフロー効率のマトリックス
上図のように、理想はリソース効率とフロー効率がお互いに高い星印の部分にチームの効率を近づけようとする。しかしながら、それぞれの効率における両立は理論上困難なため、現実的には点線で記載してある部分を目指します。

さいごに

いかがでしたでしょうか。リソース効率を高めた際の影響については、読んでいただいた皆さまにも覚えがあることだったではないでしょうか。 また、リソース効率を高めた際のパフォーマンス低下を避けるための方法としてのフロー効率についても書きました。これによって、リソース効率とフロー効率の両立が困難なことも記載しました。

This is Leanを読んで~その1~

はじめに

先日This is Leanを読了しました。この本を読むきっかけとしては、アジャイル開発やScrumという文脈で度々耳にすることもあるLeanという言葉について、改めて自分の認識を固めておきたかったためです。 本ブログではこの本を通して語られる内容に対して、ソフトウェア開発、アジャイル、Scrumでの経験に落とし込んで、僕なりの整理をしていきたいと思います。

アジェンダ

This is Leanを読んでは以下のアジェンダについて、複数の投稿に分けていこうと考えてます。

  1. リソース効率とフロー効率について
  2. 両効率を同時に満たすことはできない
  3. Leanとは

今回は、1. リソース効率とフロー効率についてをまとめていきます。

リソース効率とフロー効率について

リソース効率

リソース効率とは、従来効率と呼ばれる多くの場合に意味しているものとなります。具体的には、ある業務を担当している担当者に対して稼働率が100%に近づくように担当業務を割り振るための効率化を指します。 つまり、ある価値を生じさせる機能(人、機械など)にスポットを当てた効率性となります。 多くの企業において、セールス部門、エンジニアリング部門、企画部門など、機能ごとに組織化してこのリソース効率を高めるための構造を構築しています。

Scrumにおけるリソース効率

リソース効率という観点から、Scrumを見ていくことにします。以下の図の通り、あるScrumチームにはInfra engineer、Backend engineer、Frontend engineerがいると仮定します(engineerの名称については簡略化のためこのように記載しております、ご容赦ください)。それぞれのPBI(Product Backlog Item)には、各種Infra、Backend、Frontendに関するタスクが存在します。リソース効率を念頭において各PBIに取り組むとすると、担当であるタスクに注力することとなります。

f:id:ymyuta:20210923135942p:plain
Scrumにおけるリソース効率

例えば、Infra engineerにスポットを当ててみると、Sprint内でInfra関連のタスクにリソースを全投入しようとしています。 プロダクトの採算を管理している事業部がPO(Product Owner)の場合には、リソース効率を高めることを要望してくることがありました(engineerにももちろん人件費がかかっているのでわからなくもない話しではありますが)。 具体的にはSprint外のItemにおけるタスクを実施するなどといった要望です。そもそもScrumとしてのルールから逸脱している要望ですが、実際にあった話しです。

リソース効率を高めた際に起こり得ること

では、リソース効率を高めた場合にどのようなことが発生するのでしょうか?ここで簡単な例を挙げます。 以下の図に示す通り、リソース効率を高めようとすると、各engineerはそれぞれのタスクに取り組みます。

f:id:ymyuta:20210923144016p:plain
リソース効率による事象
すると、あるItemに対しての開始から完了までの時間が徐々に長くなっていくのがわかるかと思います。 また、あるタイミングにおいては複数Itemに対するタスクが並列で処理されていることもあります。 これらリソース効率により発生する事象によって、Scrumチームのパフォーマンスにどのような影響が発生するかは、2. 両効率を同時に満たすことはできないでお伝えできればと思います。

フロー効率

上記でリソース効率はある価値を生じさせる機能にスポットを当てた効率性ということを書きました。 一方で、フロー効率とは、あまり耳馴染みのない言葉かもしれませんが、ある価値を付与する対象への効率性ということができます。 また、ある価値を付与する対象のことをフローユニットと呼びます。

Scrumにおけるフローユニットと効率性

リソース効率でも行ったように、Scrumという観点におけるフロー効率を見ていきたいと思います。 フロー効率はフローユニットへの効率性を高めるものです。ScrumにおけるフローユニットはPBIとなることが多いと思います。

f:id:ymyuta:20210923144658p:plain
フロー効率による事象
ご覧のように、リソース効率で発生していた事象である開始から完了までの時間安定し、複数Itemに対するタスクの並列処理解消されたことがわかると思います。 実際にScrumにおいて、このフロー効率を高めるプラクティスは種々ありますが、それは別のブログや書籍にお任せしようと思います。

さいごに

如何だったでしょうか。本投稿では、リソース効率とフロー効率について、Scrumという観点から情報をまとめてみました。 今回の内容に関連して、モブプログラミングなどのプラクティスとの関連性も垣間見えた方がいらっしゃるかと思いますが、This is Leanからは少し蛇足となりそうだったので割愛してます。 ただし、実際にScrumで実践しているプラクティスの背景や動機を考える上のスタートラインとしての意義はあったのかな、と個人的には思ってます。 僕が整理したい部分にフォーカスしてますので、網羅性などはあまりありませんが誰かのお役に立てれば幸いです。

はじめに

お礼

数あるブログの中から、このブログにアクセスしていただき、ありがとうございます。 本投稿では、今後どのような内容を記載していこうかということを簡単ですがお伝えできればな、と思っています。

このブログの目的について

記載内容

基本的には、ソフトウェア開発についての内容を記載していこうかと思ってます。 ただし、そこまで大仰な話しではなく、僕自身が実際に手を動かしていく中で直面した壁などについて、備忘録的に書いていきたいです。 どこかで、僕が体験したことと同じような壁にぶち当たって、困っている方の一助になれれば幸いです。

更新頻度

仕事などの関係から多少前後はするかもしれませんが、1週間に1回は更新したいと思います。

さいごに

継続は力なり、投稿を積み重ねることで、僕自身の知識の深化もできればいいな。 みなさん、よろしくお願い致します。