CI/CD:分岐ベースの地形展開


私のプロジェクトでは、TerraFormを使用して、アプリケーションのインフラストラクチャをAmazon Web Service(AWS)に提供することを選択しました.これは、Terraformが既に私によく知られており、より複雑なモジュラー構成をコーディングする練習をしたかったからです.この決定はいくつかの課題とたくさんの良い学習につながった!

地形モジュール


リソースの非常に簡単なセットで、terraform構成を1つのディレクトリと通常のセットに制限するのは適切かもしれませんmain.tf , providers.tf , variables.tf , など).しかしながら、このプロジェクトはいくつかの異なる種類のリソースを必要とするでしょう.ECSクラスタ、サービス、およびタスク定義;いくつかのIAMロールとパーミッションそして、負荷平衡器.
以下のようなディレクトリ構造に分割しました.
terraform/
  - containers/
      - task-definitions/
      - main.tf
      - ...
  - iam/
      - main.tf
      - ...
  - loadbalancing/
      - main.tf
      - ...
  - vpc/
      - main.tf
      - ...
  - main.tf
  - providers.tf
  - ...
ここで... 各モジュール内で必要な他のファイルを表します(variables.tf //outputs.tf , など.
私の構成が大きくなったので、私が混乱しすぎているのを防ぐために、私はすべてのterraformファイルのトップでコメントを加えましたloadbalancing/main.tf , パスとファイル名を指定します.
VPCとIAMモジュールは簡単で、多くの入力または変数を必要としませんでした.私がロードバランサとECS資源をセットアップし始めたので、ものはより面白くなりました.これらのモジュールは、他のモジュールからの情報の特定の部分を必要としました.例えば、ロードバランサはVPCサブネットについて知っていなければなりません、そして、ECSタスク定義はそのIAMタスクと実行役割のARNを探します.
VPCモジュールのサブネットIDの出力を設定するoutputs.tf ファイル
output "lb_subnets" {
  value = [for subnet in aws_subnet.skyboy_public_subnet : subnet.id]
}
サブネットIDのリストがルートのコンテナモジュールに渡されるのを許しますmain.tf ファイル
module "containers" {
  service_subnets = module.vpc.lb_subnets
}
そうすると、コンテナのモジュール内のECSサービスに渡されますmain.tf ファイル
resource "aws_ecs_service" "skyboy_service" {
  network_configuration {
    subnets = var.service_subnets
  }
}
追加の要件var.service_subnetsvariables.tf コンテナモジュールのファイルも同様です.それは少しトリッキーなファイルに定義されているかを追跡することができますありがたいことに、このプロジェクトの選択のための私のIDEは、ファイルとモジュールの間の変数定義の有無を検出する大きな地形のプラグインを持っています.

展開問題


プロジェクトを展開する準備をしていたので、開発アカウントと生産アカウントを監督するAWS組織を作成しました.これは、私がどのように適切なアカウントにterraform構成を展開するかを理解する必要があることを意味します、一度私が生産において固定されたインフラを持っていたならば、私は変更をテストするために新しいスタックを回転させて、アプリケーションを降りるかもしれないどんな衝突についても心配しませんでした.
問題を解決するには:
  • devとprod状態ファイルを別の場所に保存する
  • 正しいAWSアカウント資格情報を使用する
  • 簡単にプロビジョニングされたインフラストラクチャを分解する方法を持つ
  • terraformに正しいdocker画像URIを渡す
  • 正しいロードバランサリスナーを作成します.
  • (devアカウントはDNSルーティング用のDNSルーティング用の登録ドメインをロードバランサに接続していないので、ポート80上でリスナーを必要としません.ロードバランサエンドポイントにHTTPリクエストを作成するのは十分です.そして、ロード・バランサ・ターゲット・グループにHTTPSトラフィックを進めるために別の.アプリケーションのドメインへの要求は、ドメインの証明書が有効であることを確認し、アプリケーションを起動するように指示します.
    最後の考慮は、私はできるだけ小さなコード繰り返しとしてこれをすべてやりたいということでした.
    私はすでにアプリケーションイメージを構築して、押すために再利用可能なGithubアクションワークフローを準備していたので、私は一貫していて、terraformのために同じことをするのを選びました.

    ブランチベースアクション


    私は倉庫の3つのYAMLファイルを作成しました.github/workflows ディレクトリ
    apply_terraform.yml
    dev_apply_tf.yml
    main_apply_tf.yml
    
    最初のファイルapply_terraform.yml , 再利用可能なワークフローです.にon: セクションでは、ワークフローのトリガを定義しますworkflow_call , これは、このワークフローを別のワークフローで呼び出すことができることを示します.中workflow_call , 定義inputs and secrets これは、呼び出し時間でこのワークフローに渡されます.
    The jobs: セクションは他のGithubアクションのワークフローのように見えます.一つの例外では、リポジトリ秘密が呼ばれるかもしれませんが、代わりにコードはworkflow_call . ある時点で、私は、再利用可能なワークフローに直接terraform雲トークンを通過しようとしたが、エラーを取得し、ワークフローの流れを中断し続けたとして、いくつかのフラストレーションにつながった.このソリューションは、ブランチベースのワークフローでリポジトリ秘密を呼び出し、再利用可能なワークフローに渡すことでした.
    2つのブランチベースのワークフローは同じ構造であり、どちらも非常に短いです.
    name: Call apply-terrafom from dev branch
    
    on:
      push:
        branches:
          - dev
        paths:
          - 'terraform/**'
    
    jobs:
      apply-tf:
        uses: ./.github/workflows/apply_terraform.yml
        with:
          workspace_name: 'skyboy-dev'
          listeners: 'devlisteners'
        secrets:
          image_uri: ${{ secrets.DEV_IMAGE_URI }}
          tf_token: ${{ secrets.TERRAFORM_TOKEN }}
    
    ワークフローはプッシュによって引き起こされますdev ブランチ-また、terraform/ 倉庫のディレクトリ;私は、同じ倉庫にあるアプリケーション自体への変更を望みません.(これについてもっと考えてみてください.
    単一のワークフロージョブは再利用可能なワークフローを使用し、GitHub Webコンソールで定義された特定の入力とリポジトリの秘密を渡します.

    問題解決


    それで、どのように、私が私のマルチ口座配備問題を解決するのを助けるすべて?
    リポジトリのコードをチェックした後、再利用可能なワークフローの次のステップは短いbashスクリプトを実行することです.
    - name: Run tf_files script
      env:
       WORKSPACE: ${{ inputs.workspace_name }}
       IMAGE: ${{ secrets.image_uri }}
       LISTENERS: ${{ inputs.listeners }}
      run: ../.github/scripts/tf_files.sh
    
    スクリプトは、このステップが設定される環境変数に簡単にアクセスでき、テンプレートを使用していくつかの基本的なファイル操作を行います.
  • Torraformクラウドのワークスペース名をbackends.tf , devと主ブランチの状態は別々に格納される.あらゆるterraform apply Traformフォーム上でリモートで発生し、各ワークスペース内に資格情報を格納する機会を与え、配備されたインフラストラクチャを簡単に分解する
  • 適切な弾性コンテナリポジトリからタスク定義に正しいDockerイメージURIを挿入します
  • そして、ロードバランシングモジュールの` mainに正しいリスナーを追加します.tf 'ファイル.
  • スクリプトがGithubランナーで完了したあと、ワークフローはterraform雲、ランニングにログインしますterraform init , fmt , and validate , そしてついにapply .

    包む


    経路ベースのプッシュトリガへの対処:アプリケーションとインフラストラクチャを別々のリポジトリに分離する理由は?答え:それはあまりにも簡単ですので!私は、同じリポジトリの2つを持っていることが最高の実行でないかもしれないと認めます、そして、アプリケーションが成長するならば、私は彼らを分離するかもしれません.現在のセットアップでは、私は1つのIDEウィンドウでプロジェクト全体を維持することができますし、誰もがスカイボーイのアプリを起動に行っているすべての作品を見て興味を持って簡単になります.
    私は私のアプリのためのモジュールの地形形態を設定することができたことがうれしい.回想的で単純であるにもかかわらず、スクリプトを加えて、GiTub Acaction Workflowの間、ファイル操作を実行することはもう一つの良い複雑さ挑戦を克服しました、そして、私が別々の倉庫に基盤を壊すならば、まだ適用可能です.
    この書き込みは、私の思考プロセスと私のソリューションの概要を伝えることを意図しており、ガイドされたチュートリアルとして機能するのに十分な詳細を提示しません.あなたが何か似ているし、私がしたことについての明確化を希望している場合タッチを取得してください.私は助けるために最善を尽くします!
    関連記事