ENGINEER BLOG ENGINEER BLOG
  • 公開日
  • 最終更新日

【CloudFormation 】ALBとEC2構成で作る「Hello World!」 ~CloudFormation編~

この記事を共有する

目次

はじめに

こんにちは、サービスGの羽生です。

突然ですが、CloudFormationというサービスをご存じでしょうか?
CloudFormationとは、AWSが提供しているIaC(Infrastructure as Code)サービスです。
有名なIaCツールとしてはオープンソースのTerraformがありますが、CloudFormationはAWSのサービスとして利用できるという特徴があります。

前回の記事では、Terraformで「Hello World!」を表示させる環境を構築しましたが、
新たにCloudFormationに触れる機会があったので、今回は CloudFormation を使って、「Hello World!」 を表示できる環境を作っていきたいと思います!

併せて前回の記事もぜひご覧ください! 【Terraform】Terraformで作るAWSインフラ!ALBとEC2構成で「Hello World!」表示 persol-serverworks.co.jp

こんな方におすすめ

  • CloudFormationを使ったインフラ構築に興味がある方
  • Terraformは触ったことあるけど、CloudFormationは触ったことない方
  • とりあえず何でもいいからIaCでインフラを構築したい!な方

前提

事前に以下の準備が整っていることをご確認ください。
  • AWSマネジメントコンソールにアクセス可能であること
  • CloudFormationのスタックを操作できる権限があること
  • その他構築リソース(ALBやEC2等)を操作できる権限があること

概要

構築

以下の環境を構築します。(前回の記事と同じです)

  • Amazon VPC(以下、VPC):パブリック+プライベートサブネット
  • Amazon EC2(以下、EC2):プライベートサブネットに2台、Webサーバー(Apache)を起動
  • Application Load Balancer(以下、ALB):パブリックサブネットに配置、EC2 をターゲットにHTTPを転送
  • NAT ゲートウェイ:プライベートサブネットからの外部通信用
  • インターネットゲートウェイ:ALBのインターネットアクセス

動作確認

構築後、以下の動作確認を行います。(前回の記事と同じです)

  • Webブラウザからのアクセス:ブラウザからALB のDNS名にアクセスし、「Hello World! <Hostname>」 が表示されること
  • AWS Systems Manager(以下、SSM)によるEC2への接続:管理コンソールから接続可能なこと
  • EC2から外部への通信:EC2へ接続後、外部へ通信が可能であること

構成図

  • 実線:HTTPによるアクセス経路(Hello World!表示)
  • 点線:SSMによるEC2への接続経路(EC2→SSM)

構成図①_sh.png

手順

1. CloudFormationのテンプレートファイルを作成

ローカル環境でyamlファイルを作成し、以下の内容を記述して保存します。
ファイル名はなんでも構いません。

ここを押すと展開します

AWSTemplateFormatVersion: '2010-09-09'
Description: 'ALB + EC2 Hello World Stack with VPC, NAT Gateway, and SSM'
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: "Environment Configuration"
        Parameters:
          - Environment
      - Label:
          default: "Network Configuration"
        Parameters:
          - VpcCIDR
          - PublicSubnet1CIDR
          - PublicSubnet2CIDR
          - PrivateSubnet1CIDR
          - PrivateSubnet2CIDR
      - Label:
          default: "EC2 Configuration"
        Parameters:
          - LatestAmiId
          - InstanceType
    ParameterLabels:
      Environment:
        default: "Environment Name"
      VpcCIDR:
        default: "VPC CIDR"
      PublicSubnet1CIDR:
        default: "Public Subnet 1 CIDR (AZ-1a)"
      PublicSubnet2CIDR:
        default: "Public Subnet 2 CIDR (AZ-1c)"
      PrivateSubnet1CIDR:
        default: "Private Subnet 1 CIDR (AZ-1a)"
      PrivateSubnet2CIDR:
        default: "Private Subnet 2 CIDR (AZ-1c)"
      LatestAmiId:
        default: "Amazon Linux 2023 AMI ID"
      InstanceType:
        default: "EC2 Instance Type"
Parameters:
  Environment:
    Type: String
    Default: cloudformation-dev
    Description: Environment name prefix for all resources
    AllowedPattern: ^[a-zA-Z0-9-]+$
    ConstraintDescription: Must contain only alphanumeric characters and hyphens
  VpcCIDR:
    Type: String
    Default: 10.0.0.0/16
    Description: CIDR block for VPC
    AllowedPattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$'
    ConstraintDescription: Must be a valid CIDR block (e.g., 10.0.0.0/16)
  PublicSubnet1CIDR:
    Type: String
    Default: 10.0.1.0/24
    Description: CIDR block for Public Subnet 1 in AZ-1a
    AllowedPattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$'
    ConstraintDescription: Must be a valid CIDR block (e.g., 10.0.1.0/24)
  PublicSubnet2CIDR:
    Type: String
    Default: 10.0.2.0/24
    Description: CIDR block for Public Subnet 2 in AZ-1c
    AllowedPattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$'
    ConstraintDescription: Must be a valid CIDR block (e.g., 10.0.2.0/24)
  PrivateSubnet1CIDR:
    Type: String
    Default: 10.0.10.0/24
    Description: CIDR block for Private Subnet 1 in AZ-1a
    AllowedPattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$'
    ConstraintDescription: Must be a valid CIDR block (e.g., 10.0.10.0/24)
  PrivateSubnet2CIDR:
    Type: String
    Default: 10.0.20.0/24
    Description: CIDR block for Private Subnet 2 in AZ-1c
    AllowedPattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$'
    ConstraintDescription: Must be a valid CIDR block (e.g., 10.0.20.0/24)
  LatestAmiId:
    Type: AWS::SSM::Parameter::Value
    Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64
    Description: Amazon Linux 2023 latest AMI ID
  InstanceType:
    Type: String
    Default: t2.micro
    AllowedValues:
      - t2.micro
      - t2.small
      - t2.medium
    Description: EC2 instance type for web servers (t2.micro is Free Tier eligible)
Resources:
  # VPC
  MainVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCIDR
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-vpc'
  # InternetGateway
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-igw'
  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref MainVPC
      InternetGatewayId: !Ref InternetGateway
  # Public Subnet
  PublicSubnetAZ1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MainVPC
      CidrBlock: !Ref PublicSubnet1CIDR
      AvailabilityZone: ap-northeast-1a
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-public-subnet-ap-northeast-1a'
  PublicSubnetAZ2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MainVPC
      CidrBlock: !Ref PublicSubnet2CIDR
      AvailabilityZone: ap-northeast-1c
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-public-subnet-ap-northeast-1c'
  # Private Subnet
  PrivateSubnetAZ1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MainVPC
      CidrBlock: !Ref PrivateSubnet1CIDR
      AvailabilityZone: ap-northeast-1a
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-private-subnet-ap-northeast-1a'
  PrivateSubnetAZ2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MainVPC
      CidrBlock: !Ref PrivateSubnet2CIDR
      AvailabilityZone: ap-northeast-1c
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-private-subnet-ap-northeast-1c'
  # Regional NATGateway
  RegionalNATGateway:
    Type: AWS::EC2::NatGateway
    Properties:
      AvailabilityMode: regional
      VpcId: !Ref MainVPC
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-natgw'
  # Public Route Table
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MainVPC
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-public-rt'
  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: AttachGateway
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
  PublicSubnetRouteTableAssociationAZ1:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetAZ1
      RouteTableId: !Ref PublicRouteTable
  PublicSubnetRouteTableAssociationAZ2:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetAZ2
      RouteTableId: !Ref PublicRouteTable
  # Private Route Table
  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MainVPC
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-private-rt'
  PrivateRoute:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref RegionalNATGateway
  PrivateSubnetRouteTableAssociationAZ1:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnetAZ1
      RouteTableId: !Ref PrivateRouteTable
  PrivateSubnetRouteTableAssociationAZ2:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnetAZ2
      RouteTableId: !Ref PrivateRouteTable
  # Security Group for ALB
  ALBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub '${Environment}-alb-sg'
      GroupDescription: Security group for ALB
      VpcId: !Ref MainVPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
      SecurityGroupEgress:
        - IpProtocol: -1
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-alb-sg'
  # Security Group for EC2
  WebSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub '${Environment}-web-sg'
      GroupDescription: Security group for Web servers
      VpcId: !Ref MainVPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          SourceSecurityGroupId: !Ref ALBSecurityGroup
      SecurityGroupEgress:
        - IpProtocol: -1
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-web-sg'
  # IAM Role for SSM
  SSMRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub '${Environment}-ssmrole'
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-ssmrole'
  SSMInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      InstanceProfileName: !Sub '${Environment}-ssmprofile'
      Roles:
        - !Ref SSMRole
  # EC2 Instance 1
  WebInstance1:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref LatestAmiId
      InstanceType: !Ref InstanceType
      SubnetId: !Ref PrivateSubnetAZ1
      SecurityGroupIds:
        - !Ref WebSecurityGroup
      IamInstanceProfile: !Ref SSMInstanceProfile
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash
          yum update -y
          yum install -y httpd
          systemctl enable httpd
          systemctl start httpd
          HOSTNAME=$(hostname)
          echo "Hello World! Hostname: $HOSTNAME" > /var/www/html/index.html
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-web-ec2-1'
  # EC2 Instance 2
  WebInstance2:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref LatestAmiId
      InstanceType: !Ref InstanceType
      SubnetId: !Ref PrivateSubnetAZ2
      SecurityGroupIds:
        - !Ref WebSecurityGroup
      IamInstanceProfile: !Ref SSMInstanceProfile
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash
          yum update -y
          yum install -y httpd
          systemctl enable httpd
          systemctl start httpd
          HOSTNAME=$(hostname)
          echo "Hello World! Hostname: $HOSTNAME" > /var/www/html/index.html
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-web-ec2-2'
  # Application Load Balancer
  ApplicationLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: !Sub '${Environment}-alb'
      Type: application
      Scheme: internet-facing
      SecurityGroups:
        - !Ref ALBSecurityGroup
      Subnets:
        - !Ref PublicSubnetAZ1
        - !Ref PublicSubnetAZ2
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-alb'
  # Target Group
  TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Name: !Sub '${Environment}-tg'
      Port: 80
      Protocol: HTTP
      TargetType: instance
      VpcId: !Ref MainVPC
      HealthCheckPath: /
      HealthCheckIntervalSeconds: 30
      HealthCheckTimeoutSeconds: 5
      HealthyThresholdCount: 3
      UnhealthyThresholdCount: 3
      Targets:
        - Id: !Ref WebInstance1
          Port: 80
        - Id: !Ref WebInstance2
          Port: 80
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-tg'
  # HTTP Listener
  HTTPListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      LoadBalancerArn: !Ref ApplicationLoadBalancer
      Port: 80
      Protocol: HTTP
      DefaultActions:
        - Type: forward
          TargetGroupArn: !Ref TargetGroup
Outputs:
  ALBDNSName:
    Description: DNS name of the Application Load Balancer
    Value: !GetAtt ApplicationLoadBalancer.DNSName
    Export:
      Name: !Sub '${AWS::StackName}-ALB-DNS'
  VPCId:
    Description: VPC ID
    Value: !Ref MainVPC
    Export:
      Name: !Sub '${AWS::StackName}-VPC-ID'

2. テンプレートのアップロードと設定

2-1.以下の手順でyamlファイルをアップロードします。

  1. AWS管理コンソールにログインし、サービスメニューから「CloudFormation」を選択します

  2. 「スタックの作成」→「新しいリソースを使用(標準)」を選択します スタック作成.png

  3. 設定は画像のように選択し、「ファイルの選択」から先ほど作成した「.yaml」ファイルを選択します。ファイルのアップロードを確認後、「次へ」を選択
    • ※本手順でテンプレートをアップロードすると、S3バケットが自動作成されます。既存バケットを使用する場合は、「Amazon S3 URL」を選択しバケットを指定してください。 YAMLアップ.png

2-2.スタックの詳細設定を行います。

  1. スタック名を入力します。ご自由に命名してください。(例:TechBlog-20260313)

  2. パラメータは下表の通り、デフォルト値のままでOKです。そのまま「次へ」を選択します。
    • ※デフォルトから変更する場合は、CIDRブロック等の重複に注意し適切な値を設定してください。
パラメーター名 デフォルト値 説明
Environment Name cloudformation-dev 環境識別子
VPC CIDR 10.0.0.0/16 VPCのCIDR
Public Subnet 1 CIDR(AZ-1a) 10.0.1.0/24 パブリックサブネット1のCIDR
Public Subnet 2 CIDR(AZ-1c) 10.0.2.0/24 パブリックサブネット2のCIDR
Private Subnet 1 CIDR(AZ-1a) 10.0.10.0/24 プライベートサブネット1のCIDR
Private Subnet 2 CIDR(AZ-1c) 10.0.20.0/24 プライベートサブネット2のCIDR
Amazon Linux 2023 AMI ID /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64 SSMパラメータストアに公開されているAmazon Linux 2023のAMI ID
EC2 Instance Type t2.micro Webサーバーのインスタンスタイプ

2-3.スタックオプションの設定を行います。

  1. 追加のオプション設定はせず、画面下部までスクロールし、「AWS CloudFormationによってIAMリソースがカスタム名で作成される場合があることを承認します。」にチェックを入れて「次へ」を選択します。 スタック設定3.png

3. スタックのデプロイ

  1. 設定内容が一覧で表示されるため、問題なければ「送信」を選択します。
    • ※「送信」を選択すると、リソース構築が開始されます。誤クリックにご注意ください。 スタック送信.png

4. デプロイ完了の確認

  1. スタックステータスが「CREATE_COMPLETE」になるまで待機しましょう(約5分)。
    • ・デプロイ進行中の画面 (ステータスが「CREATE_IN_PROGRESS」) スタック実行中.png
    • ・デプロイ完了の画面 (ステータスが「CREATE_COMPLETE」) スタック実行完了.png

動作確認

デプロイが完了したので、動作確認をしていきましょう!

1. Webページの表示

  1. 対象スタックの「出力」タブを確認し、「ALBDNSName」キーに表示されている値を選択します。 スタック出力.png
  2. ブラウザの別タブが開き「Hello World!Hostname:<EC2 プライベートDNS名>」が表示されたらOKです!何度かリロードしてプライべートDNS名が切り替わることも確認してみましょう! ブラウザ.png

2. EC2インスタンスへの接続確認

  1. AWS管理コンソールに戻り、サービスメニューから「EC2」を選択します

  2. 「インスタンス」から今回デプロイしたインスタンスにチェックをいれ、「接続」を選択します。

  3. 接続画面が表示されるので、「SSM Session Manager」タブに切り替えて「接続」を選択します。 EC2-SSM.png
  4. コマンドラインの画面が表示されれば接続完了です! CLI.png

3. EC2インスタンスから外部への通信確認

  1. インスタンスへの接続が確立できたら、以下コマンドを実行してインターネットへ接続可能であることを確認します。
ping google.com -c 10


以下のような結果であればOKです! CLI.png

これまで確認した以下の結果がすべて想定通りであれば完了です!スタックのデプロイと動作確認まで問題ないことが確認できましたね!

  • Webページの表示
  • インスタンスへの接続確認
  • インスタンスから外部への通信確認

スタックの削除

構築したリソースは利用料金が発生する可能性がありますので、動作確認がすべて完了したらスタックを削除しましょう。

1. スタックの削除実行

以下の手順でスタックを削除していきます。

  1. AWS管理コンソールに戻り、サービスメニューから「CloudFormation」を選択します

  2. スタック一覧画面から、今回扱ったスタックにチェックを入れ、「スタックを削除」を選択します。 スタック削除.png

  3. 確認画面が表示されるので、スタック名を入力し「スタックを削除」を選択します。 スタック削除実行.png

  4. スタック削除が開始されますので、完了まで待機しましょう(約5分)。 スタック削除開始.png

2. スタックの削除確認

待機したらスタック削除を確認していきましょう。

  1. 以下のように「DELETE_COMPLETE」と表示されていれば削除完了です。 スタック削除完了.png

  2. スタックが削除されると一覧に表示されなくなりますが、「ステータスのフィルター」がデフォルトで「アクティブ」になっているためです。 これを「削除済み」に変更してみましょう。 スタック削除済.png

  3. 以下のように対象のスタックが削除済みリストに表示されていますので、こちらから確認可能です!
    • ※スタックを選択すると、過去のデプロイや削除の履歴も確認することができます。 スタック削除済確認.png

3. S3バケットの確認

スタックは削除してしまいましたが、テンプレートであるyamlファイルはちゃんと残っていますのでご安心ください。 いつでも再利用できるぜ!ということでついでにこちらも確認してみましょう。

  1. AWS管理コンソールのサービスメニューから「S3」を選択します。

  2. 「cf-templates-<ランダム文字列>-ap-northeast-1」というバケットがあるはずなので、バケット名を選択します。

  3. オブジェクトの中を確認し、テンプレートファイルが存在していることを確認しましょう。 バケット内に残存しているので、再度スタック作成時に同じようにyamlテンプレートをアップロードする必要はなく、オブジェクトURLを設定することでテンプレートを指定することができます! YAML残存確認.png

スタックのデプロイから動作確認、スタック削除まで終了したので作業はこれにて完了です!

最後に

今回はCloudFormationを使って、簡単なWeb構成を構築しました。 冒頭にTerraformを引き合いに出しましたが、個人的な比較を簡単にまとめます。

項目 CloudFormation Terraform
提供元 AWS公式 HashiCorp社
対応クラウド AWS専用 マルチクラウド対応(AWS、Azure、GCP等)
記法 JSON / YAML HCL(HashiCorp Configuration Language)
インストール 不要 必要
料金 無料(デプロイしたリソース料金のみ) 一部無料 ※
状態管理 AWS側で管理 tfstateファイルで管理
モジュール化 ネストスタック、スタックセット モジュール機能充実(公式レジストリ/コミュニティ多数)
ロールバック あり(更新失敗時に自動ロールバック) 自動ロールバックなし。コードを前バージョンに戻し再適用

※CLIが無料で利用可能。企業向けの有料プランあり。

両者それぞれの強みと弱みがあるので、プロジェクトの要件や環境に応じて適切なIaCツールを選択できるといいですね!

参考文献

本ブログでのYAMLテンプレートは下記公式ドキュメントを参考に記述していますが、あくまで一例です。
情報量がかなり多いですがぜひご確認ください。

CloudFormation テンプレート形式
AWS リソースおよびプロパティタイプのリファレンス

この記事は私が書きました

S.Hanyu

記事一覧

サッカー観戦(プレミア、ラ・リーガ)とコーヒーが好きです。 Terraformが好きでよく触っています。

S.Hanyu

この記事を共有する

クラウドのご相談

CONTACT

クラウド導入や運用でお悩みの方は、お気軽にご相談ください。
専門家がサポートします。

サービス資料ダウンロード

DOWNLOAD

ビジネスをクラウドで加速させる準備はできていますか?
今すぐサービス資料をダウンロードして、詳細をご確認ください。