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

layerx-invoice-practical-devops-20211029

shnjtk
October 30, 2021
14k

 layerx-invoice-practical-devops-20211029

shnjtk

October 30, 2021
Tweet

Transcript

  1. © LayerX Inc.
    実践 DevOps
    チーム全員でインフラを管理する
    @shnjtk
    2021/10/29
    JAWS-UG コンテナ支部 #20

    View Slide

  2. © LayerX Inc.
    自己紹介
    高江 信次 (Shinji Takae)
    株式会社LayerX
    CTO室 リードエンジニア
    LayerX インボイスの開発メンバーとして主にインフラを担当
    コーポレートエンジニア的な業務も一部兼任
    好きなAWSサービス
    2
    AWS Fargate Amazon Aurora
    Lambda

    View Slide

  3. © LayerX Inc.
    今日話すこと
    スピードを落とさず効率的にサービスを開発するために
    LayerX インボイスの開発チームが一体となって取り組んでいる
    インフラの管理方法
    3

    View Slide

  4. © LayerX Inc.
    アジェンダ
    ● 開発チーム構成と普段の開発の様子
    ● チームとして達成したいこと
    ● 実践していること
    ● まとめ
    4

    View Slide

  5. © LayerX Inc.
    開発チーム構成
    5
    LayerX インボイス LayerX ワークフロー
    インフラ開発・デザイン・ QA
    AI-OCR

    View Slide

  6. © LayerX Inc.
    普段の開発の様子
    ● インフラの全体的な設計や開発など大掛かりな作業は基本的に
    インフラ担当が行う
    ● 軽微な変更はアプリ担当が自分で対応することもある
    ● IaC化する前に、テスト的に管理画面から手動でリソースを作ることもある
    ● 手動で作って不要になったリソースの削除やIaC化はインフラ担当が行う
    ● 結果的に、チーム全員が自然とインフラに関わっている
    6

    View Slide

  7. © LayerX Inc.
    達成したいこと
    ● インフラ開発がボトルネックになって開発スピードが落ちるのを防ぐ
    ● 最終的に必要となるリソースはIaCで管理する
    7

    View Slide

  8. © LayerX Inc.
    実践していること
    ● IaCリポジトリのディレクトリ構成とファイルの命名規則
    ● タグ付けによるIaCリポジトリの明確化
    ● 再利用性を意識したリソース定義
    ● CI/CDの自動化とtfstateのバージョン管理
    ● plan実行時の差分を減らす工夫
    ● ツールの使い分け
    8

    View Slide

  9. © LayerX Inc.
    IaCリポジトリのディレクトリ構成
    9
    invoice-infra
    ├── aws_cloudwatch_logs.tf
    ├── aws_ecs.tf
    ├── aws_iam_ecs.tf
    ├── aws_iam_lambda.tf
    ├── aws_kms.tf
    ├── aws_rds.tf
    ├── aws_route53.tf
    ├── aws_s3.tf
    ├── aws_secrets.tf
    ├── buildspec.yml
    ├── data.tf
    ├── datadog_dashboard_ecs.tf
    ├── datadog_integration.tf
    ├── datadog_monitor_ecs.tf
    ├── datadog_monitor_rds.tf
    ├── datadog_synthetics_test.tf
    ├── env
    │ ├── dev.tfvars
    │ ├── prd.tfvars
    │ └── stg.tfvars
    ├── locals.tf
    ├── provider.tf
    └── variables.tf
    (一部抜粋)
    ● リポジトリ直下に.tfファイルをフラットに配置
    ● 環境変数は.tfvarsファイルで定義して
    envディレクトリに配置
    ○ terraformコマンド実行時に引数で指定
    ● プロジェクト固有の定数はlocals.tfで定義

    View Slide

  10. © LayerX Inc.
    Terraformファイルの命名規則
    ● (provider)_(resource)_(target).tf
    ○ 例: aws_iam_ecs.tf、aws_iam_lambda.tf
    ● targetがなかったり、自明な場合は省略
    ○ 例: aws_rds.tf、aws_kms.tf
    ● 目的
    ○ インフラのコードに普段はあまり関わらないメンバーであっても、コードを変更する際にどのファイル
    を編集すればいいか一目で分かる
    ● 上記はあくまで一例
    ○ チーム内で一貫性があって、変更したい目的のファイルをすぐに特定できればよい
    10

    View Slide

  11. © LayerX Inc.
    タグ付けによるIaCリポジトリの明確化
    ● default_tagsを利用して、各リソースを管理してい
    るIaCリポジトリがどれであるかを示すタグを付与
    する
    ● 目的
    ○ アプリ担当がリソースに変更を加えたい場合に
    IaCリポジトリがすぐに分かる
    ○ これが付与されていないものは手動で作ったテスト用リ
    ソースであると判断できる
    → リソース棚卸し時の削除対象
    11
    locals {
    service_id = "invoice"
    managed_by = "invoice-infra"
    }
    provider "aws" {
    region = “ap-northeast-1”
    default_tags {
    tags = {
    service_id = local.service_id
    managed_by = local.managed_by
    env = var.env
    }
    }
    }
    locals.tf
    provider.tf

    View Slide

  12. © LayerX Inc.
    再利用性を意識したリソース定義
    ● アプリ開発メンバーがインフラに変更
    を加えるケースの例
    ○ S3 bucketを追加したい
    ○ IAM policyを変更したい
    ○ DynamoDB tableを追加したい
    ● なるべくコピペしやすいようにlocals
    やvarを使って共通部分は
    そのまま使えるようにする
    ● 暗号化設定や非公開設定など、守っ
    てほしい部分も漏れなく
    カバーされるようにリソース定義を隣
    接させておく
    12
    resource "aws_s3_bucket" "csv_files" {
    bucket = "${local.service_id}-${var.env}-csv-files"
    acl = "private"
    versioning {
    enabled = true
    }
    server_side_encryption_configuration {
    rule {
    apply_server_side_encryption_by_default {
    kms_master_key_id = aws_kms_key.main.arn
    sse_algorithm = "aws:kms"
    }
    }
    }
    }
    resource "aws_s3_bucket_public_access_block" "csv_files" {
    bucket = aws_s3_bucket.csv_files.id
    block_public_acls = true
    block_public_policy = true
    ignore_public_acls = true
    restrict_public_buckets = true
    }

    View Slide

  13. © LayerX Inc.
    CI/CDの自動化とtfstateのバージョン管理
    ● plan/applyの実行は自動化する
    ○ planやapplyの結果をチームで共有することにより
    レビューしやすくなる
    ● tfstateファイルは必ずリモートバックエンドで保管しバージョ
    ン管理を有効にする
    ○ バージョン管理することで、もし何かあった場合でも tfstateをロール
    バックすることができる
    ○ 「何かあってもすぐに元に戻せる」という安心感があることで
    失敗を恐れずにインフラを変更できる
    13
    PR
    plan apply
    tfstate

    View Slide

  14. © LayerX Inc.
    plan実行時に差分を減らす工夫
    14
    例: data sourceが参照しているリソースを変更した場合
    resource "aws_s3_bucket" "csv_files" {
    bucket = "csv-files"
    tags = {
    foo = “bar” # -> “baz” に変更すると...
    }
    }
    data “aws_iam_policy_document” “csv_reader” {
    statement {
    effect = “Allow”
    actions = [“s3:GetObject”]
    resources = [“${aws_s3_bucket.csv_files.arn}/*”]
    }
    }
    resource “aws_iam_policy” “csv_reader” {
    name = “csv-reader”
    policy = data.aws_iam_policy_document.csv_reader.json
    }
    # aws_s3_bucket.sample will be updated in-place
    ~ resource "aws_s3_bucket" "csv_files" {
    ~ tags = {
    ~ "foo" = "bar" -> "baz"
    }
    # (config refers to values not yet known)
    <= data "aws_iam_policy_document" "csv_reader" {
    ~ id = "232721XXXX" -> (known after apply)
    ~ json = jsonencode(
    {
    - Statement = [
    - {
    - Action = "s3:GetObject"
    - Effect = "Allow"
    - Resource = "arn:aws:s3:::csv-files/*"
    - Sid = ""
    },
    ]
    - Version = "2012-10-17"
    }
    ) -> (known after apply)
    - version = "2012-10-17" -> null
    }
    # aws_iam_policy.sample will be updated in-place
    ~ resource "aws_iam_policy" "csv_reader" {
    id = "arn:aws:iam::XXX:policy/csv-reader"
    name = "csv-reader"
    ~ policy = jsonencode(
    {
    - Statement = [
    - {
    - Action = "s3:GetObject"
    - Effect = "Allow"
    - Resource = "arn:aws:s3:::csv-files/*"
    - Sid = ""
    },
    ]
    - Version = "2012-10-17"
    }
    ) -> (known after apply)
    }
    Plan: 0 to add, 2 to change
    , 0 to destroy.

    View Slide

  15. © LayerX Inc.
    plan実行時に差分を減らす工夫
    15
    resource "aws_s3_bucket" "csv_files" {
    bucket = "csv-files"
    tags = {
    foo = “bar” # -> “baz” に変更すると...
    }
    }
    resource "aws_iam_policy" "csv_reader" {
    name = "csv-reader"
    policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
    Effect = "Allow"
    Action = ["s3:GetObject"]
    Resource = ["${aws_s3_bucket.csv_files.arn}/*"]
    }]
    })
    }
    Terraform will perform the following actions:
    # aws_s3_bucket.sample will be updated in-place
    ~ resource "aws_s3_bucket" "csv_files" {
    id = “csv-files"
    ~ tags = {
    ~ "foo" = "bar" -> "baz"
    }
    ~ tags_all = {
    ~ "foo" = "bar" -> "baz"
    }
    # (9 unchanged attributes hidden)
    # (1 unchanged block hidden)
    }
    Plan: 0 to add, 1 to change, 0 to destroy.
    対策: jsonencodeでインライン化する

    View Slide

  16. © LayerX Inc.
    ツールの使い分け
    ● 基本的にはTerraformを使用してリソースを管理する
    ● Lambda関数はケース・バイ・ケースで使い分ける
    ○ jsファイル1つで済む程度の軽いものであればTerraform
    ○ パッケージインストールや複雑なビルドが必要なものは AWS CDK
    ● AWS CDKを使う場合は対象をLambda関数だけにする
    ○ 厳密には、Lambda関数とそれをデプロイするためのCloudFormation stack
    ○ Lambda関数に付与するIAM role/policyや、その他必要なリソースはTerraformで管理
    ● 目的
    ○ Lambda関数はアプリ担当が変更を加えることが多く、デプロイの際に関数以外のことを意識しなくても
    済むように
    ○ リソースはそれぞれ関連(参照)している場合が多く、生成や変更の順序に依存性があったりするので、
    そういった点はTerraformで解決する
    16

    View Slide

  17. © LayerX Inc.
    まとめ
    ● 誰でもインフラ開発ができるように、一貫性のあるルールを設けて
    シンプルなファイル構成、再利用性の高いリソース定義にしよう
    ● タグを活用してリソースの管理状況を可視化しよう
    ● CI/CD環境を構築して処理を自動化し、チームメンバーがレビューできる
    ようにしよう
    ● plan実行時の差分を減らすためにコードをリファクタしよう
    ● ツールは1つに絞らず適材低所で採用しよう
    17
    開発スピードを落とさず、IaCもきちんと行うために:

    View Slide