CI/CDはじめの一歩 IaC編

    CI/CDはじめの一歩 IaC編

    目次

       

       

      はじめに

      アジアクエスト クラウドインテグレーション部の田中雄也です。
      この記事では、CI/CDを知るためのはじめの一歩として、インフラ環境をコード化するIaCについてご紹介していきます。
      この記事を読むことで、インフラ環境をコード化するIaCという仕組みを知ることができます。この手法の具体的な活用例の紹介を通じて、より効率的な環境構築を知るきっかけとなれば幸いです。

       

      記事の目的(または狙い)

      • 今後、CI/CDやIaCに触れてみたい方のきっかけづくりに
      • IaCの情報収集をする方向けの参考情報に
      • インフラ構築の手段を学べる

      そもそもCI/CDとは

      「Continuous Integration」・「Continuous Delivery」の略称で、日本語に訳すと「継続的インテグレーション・継続的デリバリー」といった意味になります。

      ソフトウェアのリリーススピードの向上を目的とした開発手法で、 ソフトウェアをリリースさせた段階で満足するのではなく、リリース後においても継続的なアップデートの提供をすることで、絶えず変化するビジネス環境に適応したソフトウェアの提供を目指すための手法です。

      コードの変更が行われる都度のテストやデプロイを自動化することで、ソフトウェアのリリーススピードの向上を通して、市場が求めるアプリケーションを維持し、競争力を保ち続けることが目的となっています。現在ではソフトウェアだけでなく、クラウドインフラにもこの仕組みが応用されるなど幅広い開発現場で用いられる手法となっています。

      IaCとは

      さて、今回扱うIaCとはどのようなものなんでしょう。
      ずばり、「Infrastructure as Code」の略称で、簡潔にいうと、インフラストラクチャ構築をコード化することです。
      ネットワークの構成やサーバーの設定など、インフラを構成する要素をコード化し、その構築や管理を専用のソフトウェアによって自動化する手法です。

      インフラをコード化することで得られるメリットとしては、

      • 実施内容を記録できること
      • 人的なミスを軽減できること
      • 同一環境を簡単に複製できること

      が挙げられます。

      担当者が手動でインフラ環境をデプロイすることを考えると、どうしても手順書と設計書を見比べながら作業することになり、時間もかかりますし、ミスの可能性も考えられます。
      そのため、インフラ構築をコード化することで、構築の自動化や標準化を通して、ミスや作業時間の削減をすることが求められているのです。

       

      CI/CDとIaCの関連

      これらの関係性はCI/CDの説明の際に、クラウドインフラにも応用されていると記載をしている。まさに、その部分になります!
      CI/CDとIaCは、自動化と効率化の部分で結びついています。IaCでコードとして記述したインフラ環境の設計図をCI/CDによる自動的なテストとデプロイによって、開発者による手動での介入なしに、リソースのプロビジョニングまでのステップを完了させることができます。
      開発者はCI/CDとIaCを連携して運用することで、開発にかかるリスクを低減しながらも、環境構築に掛かるスピード向上を達成することが可能になるのです。

      各クラウドでのサービス

      というわけで、ここからは実際にIaCがどのような形で提供されているのかを把握するために、各クラウドサービスにおける
      IaCサービスについて見ていきます。

       

      AWS CloudFormation(CFn)

      AWSのIaCサービスで、サービスの開始が2011年と歴の長いIaCの火付け役。

      記述はJSON/YAML形式で比較的シンプルに扱える。最小単位は「スタック」であり、スタックの集まりであるスタックセットを利用することで、複数のアカウントや複数のリージョンに対して同様の構築を展開することが可能。

      例として、CFnに用いられるYAMLでは、以下のような形式でコードを記述します。
      (全体を記載すると長くなってしまうので、EC2の定義部分のみ。実際に構築するためには、この他にもパラメータの定義やテンプレートのバージョンの定義などが必要になってきます。)


      Instance:
      Type: AWS::EC2::Instance
      Properties:
      ImageId: !Ref HogeImage
      KeyName: hogehoge-key
      InstanceType: !Ref InstanceType
      SecurityGroups:
      - !Ref HogeSG
      BlockDeviceMappings:
      - DeviceName: /dev/sda1
      Ebs:
      VolumeSize: 50

       

      Azure Resource Manager

      Azureのサービスで、リソースのデプロイに限らず、全般的な管理などを行う包括的な機能を備えている。

      JSONをもとにしたARMや独自の形式であるBicepなどを活用して記述する。変数を扱いやすいという点でJSONより扱いやすいという意見もある。
      最小単位は「リソースグループ」で、それぞれデプロイに用いられるARMは腕、Bicepは上腕二頭筋が由来だったりとユーモアが利いたネーミングセンスをしている。

      例として、Bicepでは、以下のような形式で記述します。(VM定義部のみ抜粋)


      resource vm 'Microsoft.Compute/virtualMachines@2021-03-01' = {
      name: vmName
      location: location
      properties: {
      hardwareProfile: {
      vmSize: vmSize
      }
      storageProfile: {
      imageReference: {
      publisher: 'MicrosoftWindowsServer'
      offer: 'WindowsServer'
      }
      dataDisks: [
      {
      diskSizeGB: 1023
      }

       

      Cloud Deployment Manager

      GCPのサービス。GCP全体としてGUIよりもAPIが充実/推奨される傾向にあり、CDMも同様。

      JSONとYAML、PythonとJinjaなどでコードを記述できる。それぞれの使い分けとしては、JSONとYAMLは静的でシンプルな構成に適しているため、規模の小さい環境向け。PythonとJinjaはより動的で複雑な環境に適しており、記述したコードの内容を変数化し、モジュールとして再利用することに向いている。
      最小単位は「デプロイメント」で、GCPではTerraformの活用も推進されているため、CDMの開発優先度は低いようにも思える。

      例として、CDMのPythonは、以下のような形式で記述します。(VM定義部のみ抜粋)


      COMPUTE_URL_BASE = 'https://www.googleapis.com/compute/v1/'

      def GenerateConfig(context):
      datadisk = 'datadisk-'+ context.env['deployment']
      resources = [{
      'type': 'compute.v1.instance',
      'name': 'vm-' + context.env['deployment'],
      'properties': {
      'zone': context.properties['zone'],
      'machineType': ''.join([COMPUTE_URL_BASE, 'projects/', context.env['project'], '/zones/',
      context.properties['zone'], '/machineTypes/f1-micro']),
      'disks': [{
      'deviceName': 'boot',
      'type': 'PERSISTENT',
      'boot': True,
      'autoDelete': True,
      'initializeParams': {
      'sourceImage': ''.join([COMPUTE_URL_BASE, 'projects/debian-cloud/global/images/family/debian-11'])}
      }
      }
      }]
      return {'resources': resources}

       

      各サービスの比較

      各サービスを簡単に比較すると以下のようになります。

        AWS CFn Azure RM GCP CDM
      料金 無料 無料 無料
      リソースのデプロイ先 スタック展開先に依存 テンプレート内に記述 テンプレート内に記述
      記述言語 JSON/YAML ARM(JSON)/Bicep JSON/YAML/Python/Jinja
      リソースの権限管理
      学習のしやすさ
       
      各項目に対する補足

      料金面:各サービスが無料となっているのでその点を気にする必要はなさそうです。

      リソースのデプロイ先:AWS以外はテンプレート内にどのリージョンに対してリソースを構築するかについて明示的に記述する必要があります。それに対しAWSでは、リソースのデプロイ先がCFn展開時に用いたリージョンに依存するため、コードを展開したリージョンにそのままリソースが構築される仕組みになっています。

      記述言語:AWSのCFnは複雑な処理には直接対応をしていないため、ループや複雑な処理を用いたい場合には別の手段との連携をする必要があります。

      リソースの権限管理:AWSのIAMのような形で、各IaCサービスがどこまでのサービスを作成可能かについて権限を定められるかどうかという観点です。全てのサービスにおいて、IaCを活用して作成できるリソースについて権限設定で制限をかけることが可能です。

      学習のしやすさ:AWSは、広く使われているため学習に利用できるドキュメントが多いため〇としています。Azureは有志の情報こそAWSには及ばないものの、公式ドキュメントが充実しているため、学習のしやすさを〇としています。
      GCPは他のサービスと比較して情報ソースがそろっておらず、比較的学習がしづらいと言えるため△としています。

       

      Terraform

      ここまでは、各クラウドサービスに根付いているIaCサービスについてご紹介してきました。
      しかし、IaCツールには、今まで紹介してきたクラウドサービスを横断して、IaCを実現できるツールも存在しています。その1つがTerraformです。

      Terraformは、HashiCorp社によって開発されたオープンソースのツールであり、今までご紹介をしてきたAWS/GCP/Azure/Kubernetes等に対応した無料のIaCツールであることから、エンジニアにとても人気のあるツールです。
      その特徴として、インフラの定義をコードとして記述することで、作成の過程を自動で行ってくれる宣言型といった仕組みや管理対象のインフラの現状を追跡するために用いられるstateファイルの存在が挙げられます。

      ちなみに、stateファイルとは、Terraformの特徴的な機能であり、管理対象のインフラの現状を追跡するものです。
      このファイルの存在によりTerraformはリソースの変更が必要・不必要の判断やリソース間の依存関係の追跡をすることでリソースが正しい順序で作成、更新、削除されることを保証しています。

      逆に言うと、Terraformでの開発時にはstateファイルが必須となるため、共同開発時にはファイルの共有が必要となってきます。
      また、先ほどまで紹介してきたサービスと違って、個々のクラウドサービスに根ざしたツールではないため、コード外での変更を取り込むために、変更をファイルに反映させる必要があるという点に欠点があります。いずれにせよ取り扱い注意なファイルだと言えます。

      最後に、そのほかTerraformの惜しいポイントを挙げるとすると以下の点があります。

      • ドキュメントが不親切なこと
        • 変数の型がドキュメント上で明記されていないため、変数にどういった項目を入れればよいのか分かりづらい
      • 対応していないリソースがあること
        • とくに、リリース直後だったり、用途が限定的なリソースについては対応していない場合が多いため、別のデプロイ手段を考慮する必要がある

       

      CDK

      次にIaCの仕組みの1つであるCDKと関連するサービスについてご紹介をしていきます。


      そもそもCDKとは?

      Cloud Development Kitの略で
      JavaScript、Python、Java、C#、Goと言ったプログラミング言語でクラウドインフラやクラウドアプリケーションを定義・開発するプロセスのことで、インフラ環境をコードで構築する概念であるIaCの一種です。


      AWS CDK

      AWS CDKは最新のプログラミング言語でAWSのインフラをコードとして定義し、それをAWS CloudFormationを通じてデプロイするための開発フレームワークです。

      その特徴として

      • AWSにおけるすべてのパブリックリージョンで利用可能なこと
      • 開発の過程でCFnを利用するため、CFnと同じ制限が課せられること
      • AWS CDK Command Line Interface (CLI)を使用して、開発・操作が可能なこと

      が挙げられます。

      結論としてAWS CDKの働きは、使い慣れた言語で開発したコードを、CFNでデプロイをできる形に合成することにあります。
      実際に、CDKを使用した場合の開発フローは以下の図のようになります。202404-firststeps-to-cicd-iac-01

      なぜAWS CDKを使うのか

      AWSにはIaCのツールとして、CloudFormationが存在するにもかかわらず、なぜあえてAWS CDKが利用されるのでしょう。その理由は以下のようなものです。

      • 既存のスキル(プログラミング言語・テスト)やツール(VSCode・IDE・Git)が利活用できるため新たな学習コストをかけなくて済む
      • ループ処理や複雑な分岐処理が記述できる分、同一アーキテクチャの設計時にはCFNより短い記述で済むことが多いため
        • (例:CFNの場合500行、CDKの場合は30行だけで済むこともある)
      • アプリコードとインフラコードを一箇所にまとめることができるため、コードの管理がしやすくなる
      • 開発者にやさしいCLIがある
      • 利用料金がかからない

       

      上記のような理由から、AWS CDKを使うことで、開発者は新たな開発コストを気にすることなくより簡単にインフラ構築ができるようになるのです。
      そして、それがAWS CDKが今日においても選ばれ続ける理由となっています。

      例として、AWS CDKのテンプレートは以下のような形式になります。


      class TestStack(core.Stack):
      def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
      super().__init__(scope, id, **kwargs)

      aws_ec2.CfnInstance(
      self,
      id=‘ec2',
      availability_zone="ap-northeast-1a",
      image_id=image_id,
      instance_type="t2.micro",
      key_name=‘cdk-ssh-key',
      security_group_ids=sg_ids,
      subnet_id=subnet_id,
      )


       

      CDK for Terraform

      CDK for Terraform (CDKTF)とはTerraformと同じく、HashiCorp社によって提供されているCDKツールであり、JavaScript(Typescript)、Python、Java、C#、Goに対応しています。
      記述した言語の最終的なアウトプットが最終的のアウトプットはHashiCorp Configuration Language (HCL)という独自の形式で出力されることや特定のクラウドサービスに依存するものではなく、AWSだけでなくAzure、GCPといったマルチクラウドに対応していることが特徴になります。
      専用のCLIもあり、比較的に使いやすいツールだと言えます。

      そんなCDKTFが選ばれる理由も以下に集約されます。

      • HCLを学習せずに、Terraformの恩恵を受けることができる
      • 使い慣れている「プログラミング言語」と「ツール」をそのまま使用できる
      • 開発者にやさしいCLIがある
      • オープンソースなため利用料金がかからず、その上でコミュニティのサポートが手厚い

      総じて、開発者はCDKツールを使うことによって、新たな学習コストを削減し、使い慣れた環境で効率的な開発ができるようになります。
      その上で、CDKツールを用いることで基本的なIaCツールには備わっていないような機能やサポートといった恩恵を受けることもできるので、IaCツール検討の際には、ぜひCDKツールも候補に入れて頂くとよいかなと思います。

      ちなみに例として、CDK for Terraformのテンプレートは以下のような形式になります。


      class TestStack(TerraformStack):
      def __init__(self, scope: Construct, ns: str):
      super().__init__(scope, ns)

      AwsProvider(self, "AWS", region="us-west-1")

      instance = Instance(self, "compute",
      ami=hoge-ami,
      instance_type="t2.micro",
      key_name=‘cdktf-ssh-key’,
      security_group_ids=sg_id,
      subnet_id=subnet_id
      )


       

      結局どのツールを選ぶべきなのか

      ここまで、多様なIaCツールをご紹介してきました。とはいえ、結局どのツールを選択するのがいいんでしょうか?
      結論からいうと、リソースをデプロイする先のクラウドサービスが決まっているならそこから逆算して考える。それでも絞りこめなければ、最後は好みです。

      参考までに、ツールを選定する際に考えるべき点としては以下のような項目が挙げられます。

      1. 使おうと思っている(使っている)クラウドは既に決まっているか?
      2. IaCに関する知識を既に所有しているエンジニアはいるか?
      3. エンジニアはTS, Python, Goなどの知見を活用できるか?
      4. 将来的にマルチクラウドなどの設計の計画がありうるか?

      これらの観点を通しても利用するツールを絞り込むことができない場合には、時間軸という点から考えてみてもいいかもしれません。
      期限が迫っている開発に対して学習コストの高く、使い慣れていないツールを導入してしまうと、それだけ構築の工程は長引いてしまいますよね。要するに、ツールの選定はその場にあったツールを選定することが重要にはなってくるのです。
      ただ、やはり最終的には好みであって、自分が興味を持って始められることが肝心です。

      きっかけの1つとして、IaCツールに触ることのできるワークショップのURLをまとめていますので、興味があればご確認ください。

       

      これらの観点を通しても利用するツールを絞り込むことができない場合には、時間軸という点から考えてみてもいいかもしれません。
      期限が迫っている開発に対して学習コストの高く、使い慣れていないツールを導入してしまうと、それだけ構築の工程は長引いてしまいますよね。要するに、ツールの選定はその場にあったツールを選定することが重要にはなってくるのです。
      ただ、やはり最終的には好みであって、自分が興味を持って始められることが肝心です。

      きっかけの1つとして、IaCツールに触ることのできるワークショップのURLをまとめていますので、興味があればご確認ください。

      URLはこちら

      AWS CloudFormation

      Azure Resource Manager

      Terraform

      AWS CDK

       

      まとめ

      というわけで、この記事では「CI/CDはじめの一歩 IaC編」として、CI/CDとIaC。そこに用いられるツールについて触れさせていただきました。

      CI/CDとは、継続的インテグレーション・継続的デリバリーを指す言葉でソフトウェアのリリーススピードの向上を目的として、コードの変更が行われる都度のテストやデプロイを自動化するものとして現在では、ソフトウェアだけでなくクラウドインフラを含めた幅広い開発現場で用いられている開発手法であること。
      IaCとは、インフラ構築をコード化することで、構築の自動化や標準化を通して、ミスや作業時間を削減できる仕組みであること。
      そんなCI/CDとIaCは、自動化と効率化の部分で結びついていて、IaCでコードとして記述したインフラ環境の設計図をCI/CDによる自動的なテストとデプロイによって、開発者による手動での介入なしにプロビジョニングまでの工程を完了させる。それによって開発にかかるリスクを低減しながらも、環境構築に掛かるスピード向上を達成できること。

      が、ご理解いただけたでしょうか?

      この記事が皆様のCI/CDやIaCに踏み出す一歩として寄与することを願っています。
      最後までお読みいただき、ありがとうございました。

      また、この記事は
      以前に投稿したCI/CDはじめの一歩シリーズの一部となっています。

      以前の記事をご覧になりたい方は下記のリンクより参照できますので、よければご覧ください。

      CI/CDはじめの一歩 ソースコード管理(Git)編

      CI/CDはじめの一歩 CIツール編

      CI/CDはじめの一歩 構成管理ツール編

      参考記事

      5分で分かるTerraform(Infrastructure as Code) | LAC WATCH