はじめに
前回、oneAPIをEC2で使うことを記事にしました。
これをCloudFormationでやってみました。
概要
以下のような手順で作成します。
- キーペア作成
- これはコンソールから作成
- 基盤作成:VPCなど
- EC2作成
- 作成後に自動でoneAPIをインストールするスクリプトを実行
- 基板上に複数台作る想定
作ってみた
キーペア作成
まずはEC2インスタンスに設定するキーペアを作っておきます。これはコンソールから作っておきます。
作成と同時に、pemファイルをダウンロードしますので保存しておいてください。
VPC等、共通リソース作成
基盤として以下のリソースを作ります。
- VPC
- パブリックサブネット (AZ-a / AZ-c)
- インターネットゲートウェイ
- ルートテーブル: 外界への通信経路の定義
- S3用VPCエンドポイント
- 共通セキュリティグループ
- 引数でマイIPを指定して、SSH接続(ポート22)のみを許可
- IAMロール / インスタンスプロフィール
- SSMを使用するための専用のロール
コードは以下になります。
AWSTemplateFormatVersion: '2010-09-09'
Description: 'VPC infrastructure with SG, IAM Role, and Subnet Exports'
# --- 1. 変数定義 ---
Parameters:
ProjectName:
Type: String
Default: for-oneapi2
Description: 'Prefix for all resource names'
MyIpAddress:
Type: String
Description: 'Your public IP address in CIDR notation (e.g., xxx.xxx.xxx.xxx/32)'
VpcCidr:
Type: String
Default: 10.3.0.0/16
Description: 'CIDR block for the VPC'
PublicSubnetACidr:
Type: String
Default: 10.3.0.0/20
Description: 'CIDR block for Public Subnet A'
PublicSubnetCCidr:
Type: String
Default: 10.3.16.0/20
Description: 'CIDR block for Public Subnet C'
# --- 2. コンソール表示の制御 (Metadata) ---
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: "Project Settings"
Parameters:
- ProjectName
- Label:
default: "Security Configuration"
Parameters:
- MyIpAddress
- Label:
default: "Network Configuration"
Parameters:
- VpcCidr
- PublicSubnetACidr
- PublicSubnetCCidr
# --- 3. リソース定義 ---
Resources:
# VPC
VPC:
Type: 'AWS::EC2::VPC'
Properties:
CidrBlock: !Ref VpcCidr
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub '${ProjectName}-vpc'
# セキュリティグループ(マイIPからのSSHを許可)
CommonSecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: !Sub 'SSH access for ${ProjectName} from MyIP'
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref MyIpAddress
Tags:
- Key: Name
Value: !Sub '${ProjectName}-common-sg'
# IAMロール (SSMログイン用)
EC2Role:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: ec2.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
RoleName: !Sub '${ProjectName}-ec2-ssm-role'
# インスタンスプロフィール
EC2InstanceProfile:
Type: 'AWS::IAM::InstanceProfile'
Properties:
Path: "/"
Roles:
- !Ref EC2Role
# ネットワークリソース
VPCEndpointS3:
Type: 'AWS::EC2::VPCEndpoint'
Properties:
ServiceName: !Sub 'com.amazonaws.${AWS::Region}.s3'
VpcId: !Ref VPC
VpcEndpointType: Gateway
RouteTableIds: [!Ref PublicRouteTable]
Tags:
- Key: Name
Value: !Sub '${ProjectName}-vpce-s3'
PublicSubnetA:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Sub '${AWS::Region}a'
CidrBlock: !Ref PublicSubnetACidr
MapPublicIpOnLaunch: true
Tags: [{Key: Name, Value: !Sub '${ProjectName}-subnet-public-a'}]
PublicSubnetC:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Sub '${AWS::Region}c'
CidrBlock: !Ref PublicSubnetCCidr
MapPublicIpOnLaunch: true
Tags: [{Key: Name, Value: !Sub '${ProjectName}-subnet-public-c'}]
InternetGateway:
Type: 'AWS::EC2::InternetGateway'
Properties:
Tags: [{Key: Name, Value: !Sub '${ProjectName}-igw'}]
InternetGatewayAttachment:
Type: 'AWS::EC2::VPCGatewayAttachment'
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
PublicRouteTable:
Type: 'AWS::EC2::RouteTable'
Properties:
VpcId: !Ref VPC
Tags: [{Key: Name, Value: !Sub '${ProjectName}-rtb-public'}]
PublicRoute:
Type: 'AWS::EC2::Route'
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: '0.0.0.0/0'
GatewayId: !Ref InternetGateway
PublicSubnetARouteTableAssociation:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref PublicSubnetA
RouteTableId: !Ref PublicRouteTable
PublicSubnetCRouteTableAssociation:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref PublicSubnetC
RouteTableId: !Ref PublicRouteTable
# --- 4. 外部参照用(アウトプット) ---
Outputs:
VPCId:
Value: !Ref VPC
Export:
Name: !Sub '${ProjectName}-VPC'
CommonSecurityGroup:
Value: !Ref CommonSecurityGroup
Export:
Name: !Sub '${ProjectName}-CommonSG'
EC2InstanceProfile:
Value: !Ref EC2InstanceProfile
Export:
Name: !Sub '${ProjectName}-EC2InstanceProfile'
PublicSubnetA:
Value: !Ref PublicSubnetA
Export:
Name: !Sub '${ProjectName}-PublicSubnetA'
PublicSubnetC:
Value: !Ref PublicSubnetC
Export:
Name: !Sub '${ProjectName}-PublicSubnetC'
CloudFormationの使い方は他の記事を参照ください。
引数は以下です。
- ProjectName
- プロジェクトの識別子
- この名前が、後で作成するEC2と紐付く
- MyIpAddress
- 現在の接続元IPアドレスを指定し、SSH接続できないように制限
- VpcCidr
- VPC全体のプライベートIPアドレス範囲
- PublicSubnetACidr / CCidr
- 各アベイラビリティゾーンに割り当てるIPアドレス範囲
EC2作成
次のコードで、先ほど作成したVPC内にEC2を作っていきます。
極力ProjectNameで、紐づけるようにしています。
UserDataで、oneAPIも自動でインストールするようにしています。
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Step 2: Ubuntu 24.04 Instance with Custom Name and oneAPI'
# --- 1. 変数定義 ---
Parameters:
ProjectName:
Type: String
Default: for-oneapi2
Description: 'Project name prefix for importing values'
InstanceName:
Type: String
Default: oneapi-server-01
Description: 'Custom name for this EC2 instance (Name Tag)'
KeyName:
Type: 'AWS::EC2::KeyPair::KeyName'
Description: 'Name of an existing EC2 KeyPair'
InstanceType:
Type: String
Default: 'm6i.large'
Description: 'Intel-based instance type'
LatestAmiId:
Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
Default: '/aws/service/canonical/ubuntu/server/24.04/stable/current/amd64/hvm/ebs-gp3/ami-id'
VolumeSize:
Type: Number
Default: 50
# --- 2. コンソール表示の制御 ---
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: "Instance Identification"
Parameters:
- ProjectName
- InstanceName
- Label:
default: "Access Configuration"
Parameters:
- KeyName
- Label:
default: "Instance Specification"
Parameters:
- InstanceType
- VolumeSize
- LatestAmiId
# --- 3. リソース定義 ---
Resources:
OneApiInstance:
Type: 'AWS::EC2::Instance'
Properties:
KeyName: !Ref KeyName
ImageId: !Ref LatestAmiId
InstanceType: !Ref InstanceType
SubnetId: !ImportValue
Fn::Sub: '${ProjectName}-PublicSubnetA'
SecurityGroupIds:
- !ImportValue
Fn::Sub: '${ProjectName}-CommonSG'
IamInstanceProfile: !ImportValue
Fn::Sub: '${ProjectName}-EC2InstanceProfile'
BlockDeviceMappings:
- DeviceName: /dev/sda1
Ebs:
VolumeSize: !Ref VolumeSize
VolumeType: gp3
UserData:
Fn::Base64: !Sub |
#!/bin/bash
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
echo "Starting oneAPI Installation for Ubuntu..."
export DEBIAN_FRONTEND=noninteractive
apt update && apt upgrade -y
# 1. 前提パッケージのインストール
apt install -y gpg-agent wget build-essential cmake pkg-config
# 2. Intelリポジトリキーの登録
wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB \
| gpg --dearmor | tee /usr/share/keyrings/oneapi-archive-keyring.gpg > /dev/null
# 3. リポジトリの追加
echo "deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main" | tee /etc/apt/sources.list.d/oneAPI.list
# 4. インストール
apt update
apt install -y intel-oneapi-base-toolkit
# 5. 環境変数の自動設定 (全ユーザー)
# oneapi-vars.sh ではなく、最新推奨の setvars.sh を使用
echo "source /opt/intel/oneapi/setvars.sh" >> /etc/profile.d/oneapi.sh
echo "Installation Complete."
Tags:
- Key: Name
Value: !Ref InstanceName
# --- 4. アウトプット ---
Outputs:
InstanceId:
Value: !Ref OneApiInstance
PublicIp:
Description: 'Public IP address (Login as "ubuntu")'
Value: !GetAtt OneApiInstance.PublicIp
引数は以下になります。
- ProjectName
- 基盤スタックで指定した名前と揃えることで、土台で作ったVPCやセキュリティグループを自動的に紐づける
- InstanceName
- EC2の名前を指定
- 複数台作る場合はここを変えて区別します
- KeyName:
- 事前に作成した「EC2キーペア」をプルダウンから選択
- InstanceType
- Intel製CPUのインスタンスタイプを指定
- LatestAmiId:
- UbuntuOSのイメージIDが前提
- デフォルト値
/aws/service/canonical/ubuntu/server/24.04/stable/current/amd64/hvm/ebs-gp3/ami-idで、自動的に最新のIDを取得
- VolumeSize
- サーバーのストレージ容量(GB)
- oneAPIはツール一式でかなりのサイズを使用するため、デフォルト値で50GBを指定
インストールの状況を出力しているファイルは、tail -f /var/log/user-data.logで確認できます。
インストールが完了したら、再度アクセスしなおして、使用できるか確認します。
icpx --version
oneapi-cli
先ほどと同じCFnテンプレートで、もう一つ作れることも確認してみます。

削除
作成した逆順でCloudFormationスタックを削除するだけで、作成したリソースはすべて消えます。
おわりに
今回は、記事にした環境をCFnで作れるようにしました。
IaC化することで複製が容易になったかと思います。
この記事がどなたかのお役に立てれば幸いです。




