マルチユーザ対応したVSCode稼働開発用AMIを自動構築する

本記事は TechHarmony Advent Calendar 2025 12/23付の記事です

どうも。四国の高知県に来ている寺内です。このブログを書くために、わざわざHHKBを出張に持ってきました。

さて。どこにいても、PCが変わっても、自分の慣れ親しんだ環境を使いたいものですよね。それが作業効率のみならず心地よさに大きく影響するからです。
VSCode周りやブラウザは長い時間を育ててきている設定ファイルを複数PC間で同期できるのでよいですが、OS周りの設定同期や共有は面倒なものがあります。ブラウザで環境が完結していたCloud 9は重宝する面が多々ありました。残念ながらサ終に向かっていることもあり、代替を検討するチームも多いでしょう。
当社のAWS Ambassadors 広野さんが2025年9月に投稿した以下のブログ記事では、Ubuntuが稼働するEC2のデスクトップコンソールをブラウザで操作するサーバを構築できます。

VSCode 導入済みで Web GUI アクセス可能な Amazon EC2 Ubuntu インスタンスを一発構築する [AWS CloudFormation]
AWS Cloud9 の代わりとなるクラウド IDE の構築をいろいろ試しています。そのうちの1案です。

大変優れた記事ですが、こちらのCFnテンプレートでは、素のUbuntu稼働のEC2インスタンスを作成し、その後デスクトップ環境の構築を行います。これはEC2インスタンスを作成するタイミングの違いで、インストールされるツール・ライブラリのバージョンが異なることになります。チーム開発をしているケースで、ある程度の環境の統制を効かせたい場合、メンバー毎にバージョンの違いが生じるのは塩梅がよくありません。
そこで本記事では、このCFnテンプレートを個人利用スコープからチーム開発スコープに拡張します。広野さんのCloudFormationテンプレートを参考にしつつ、新たに開発サーバ構築ツール「vsimage」として再構成します。

vsimageツールのアーキテクチャの考え方はCloud 9 のアーキテクチャを踏襲します。つまり、チームとしてのAMIを一つ作っておき、メンバーはそのAMIからマイ環境のEC2インスタンスを起動するという使い方です。環境をビルドしAMIを作成するフェーズと、EC2インスタンス化するフェーズを分離することで、EC2作成時にデスクトップソフトウェアのインストール時間を待つ必要がなくなります。

登場人物の役割と利用方法概略

vsimageは、以下の二種類の役割の人間を想定しています。

  • AMI管理者: Ubuntu OSおよび導入ツールの管理を行い、AMIをチームメンバーへ提供する責任を持つ役割です。
  • 開発者: AMI管理者によって提供されるAMIを用いて、自分専用のUbuntu EC2インスタンスを作成し、VSCodeを利用する役割です。

vsimageは、以下3つのCFnテンプレートからなります。

  1. Image Builder構築テンプレート: imagebuilder-pipeline.yaml
  2. AMI作成テンプレート: ami-creation-execution.yaml
  3. EC2インスタンス構築テンプレート: ec2-launch-from-ami.yaml

1と2のCFnテンプレートは、AMI管理者が使用します。3は開発者が使用します。

アーキテクチャ概要

Ubuntu ServerにGUI環境をインストールしUbuntu Desktopにします。その後、DCVやVSCodeなどの必要なツール群をインストールします。これらの一連の作業は、EC2 Image Builderを使用します。

Image Builder とは - EC2 イメージビルダー
Image Builder は、安全なカスタム Amazon マシンイメージ (AMI) またはコンテナイメージを作成し、 AWS内の宛先のアカウントとリージョンで使用できるように配布するためのフルマネージドサービスです。

AMI管理者は、Image Builderのコンポーネント定義とレシピ定義を行いUbuntuにインストールするソフトウェアを定義します。その設定をパイプラインとして定義します。
パイプラインを実行し、Image Builderで作成されたAMIをチームに公開します。
開発者はそのAMIを使用して、自らのVPC環境にEC2インスタンスを起動します。
ブラウザからスムーズにアクセスできるように、EC2起動と同時にRoute 53へFQDNと新規取得したElastic IPの組み合わせをAレコードで登録します。またSSL接続を行うためのオレオレサーバ証明書を内部で作り出します。

Ubuntuサーバは、安価なGravitonインスタンスタイプで動作します。そのため、AMI作成プロセスにおけるインスタンスタイプも同じくGravitonを指定しています。 AMI作成段階で作るインスタンスタイプは、t4g.large。EC2作成段階ではパラメータで指定可能ですが、デフォルトはt4g.largeです。

パスワード管理の仕組み

vsimageでは、Ubuntuのrootパスワードは以下の二段階で設定します。

AMI作成段階(アーキテクチャ図でいうSTEP 2)で、 ami-creation-execution.yaml にCloudFormationパラメータとして、AMI管理者が設定したパラメータストアキーを与えます。AMI作成中にパラメータストアからパスワード文字列を読み出し、Ubuntu ルートパスワードを設定します。生成された直後のAMIには、AMI管理者が定義した文字列がルートパスワードとなります。

EC2インスタンス作成段階(アーキテクチャ図でいうSTEP 3)では、開発者が実行する ec2-launch-from-ami.yaml にCloudFormationパラメータとして、開発者が設定したパラメータストアキーを与えます。EC2インスタンス作成中にパラメータストアからパスワード文字列を読み出し、Ubuntu ルートパスワードを設定します。もしパラメータストアキーが未設定であったり、パラメータストアの読み出しが失敗した場合は、AMI管理者の設定したルートパスワードのままとなります。

どちらの段階でのルートパスワード設定方法は、 /home/ubuntu/set-password-from-parameter.sh というスクリプトがOS起動時にsystemctrl により実行されることで設定されます。

作成されるAMIの概略

作成されるAMIは以下の内容となります。

  • ベースとなるOSは、ubuntu-24-lts-arm64の最新版
  • EBSボリュームはルート領域の1つで20GBのサイズ
  • ubuntu-desktopパッケージ一式とX windowサーバパッケージを導入
  • 日本語パックパッケージとibus-mozcパッケージを導入
  • nginxパッケージを導入
  • certbotパッケージを導入
  • VSCodeパッケージを導入
  • Amazon管理コンポーネントのDCVサーバを導入
  • Amazon管理コンポーネントのCloudWatchエージェントを導入
  • Amazon管理コンポーネントのAWS CLIを導入

独自にAMI内部に作られるシェルスクリプトは以下3つがあります。いずれもubuntuユーザのホームディレクトリ /home/ubuntu に作られます。ルートパスワード設定とSSLサーバ証明症作成はsystemctlのサービスとして追加され、OS起動直後に一度だけ自動実行されます。

  • 前述したルートパスワード設定ファイル: set-password-from-parameter.sh
  • SSLサーバ証明書作成スクリプト: setup-ssl.sh
  • SSLサーバ証明書更新スクリプト: renew-cert.sh

vsimageツール利用手順

以下では、CloudFormationテンプレートからCloudFormationスタックを作成する手順を示します。この手順に従い、パラメータを適切に設定すれば、Ubuntuサーバが完成します。

CFnテンプレートのダウンロード

ダウンロードリンク

vsimageは、以下3つのCFnテンプレートから成り、zip圧縮してあります。

  1. Image Builder構築テンプレート: imagebuilder-pipeline.yaml
  2. AMI作成テンプレート: ami-creation-execution.yaml
  3. EC2インスタンス構築テンプレート: ec2-launch-from-ami.yaml

こちらのリンクからzipファイルをダウンロードしてください。

vsimage-cfn

 

前提条件

vsimageを使用する前提は以下です。

  • AMI管理者は、EC2インスタンスを起動後のUbuntu ルートパスワードをパラメータストアに保存しておく必要があります。このパスワードは、実質的には開発者のルートパスワードで上書きされますが、開発者によるパスワード定義がされていない場合にこのルートパスワードが有効になるように設計してあります。
  • 開発者は、DNSルートから検索可能な正規のドメインを持ち、Route 53でホストゾーンを定義している必要があります。これは、最終的にブラウザからアクセスするためのURLとして使うことと、SSLサーバ証明書の署名にも利用します。
  • 開発者は、UbuntuのEC2インスタンスを起動するためのVPCおよびパブリックサブネットを用意しておく必要があります。
  • 開発者は、EC2インスタンスを起動後のUbuntu ルートパスワードをパラメータストアに保存しておく必要があります。

コードを使用する上での注意点

  • このサンプルコードではツール名称を「ytera-vsimage」と仮称します。ファイル名やパイプライン名などの随所で使用されているので、実際に使用されるときは grep などで検索して置き換えてください。
  • このツールが作成するリソースは、Costタグが付与するようにハードコーディングされています。 Key: Cost Value: y.terauchi の部分も適宜置き換えてください。

ImageBuilderの構築手順

まずImage Builder構築テンプレート imagebuilder-pipeline.yaml を用いて、Image Builderのパイプライン構築を行います。このスタック実行にはおおよそ5分ほどかかります。

パラメータ一覧

CloudFormationへ与えるパラメータは以下のとおりです。

PasswordParameterName AMI作成段階で指定するUbuntuルートパスワードを収納しているパラメータストアキー名を指定します。
LoggingBucket Image Builderの動作ログを保管するS3バケットを新規作成ときのバケット名を指定します。このパラメータが有効になるのは、 CreateNewBucketをtrueとしたときです。 
CreateNewBucket 上記名前で新規作成するときにtrueを指定します。二回目以降のスタック実行の場合はS3バケットは存在しているのでfalseを指定します。
ExistingBucketName S3バケットを新規作成しない場合に既存バケット名を指定します。新規作成する場合はパラメータ指定をしません。

コマンド例

AWS CLIで実行するときのコマンド例を以下に示します。

【一回目の実行であり、S3バケットを新規作成する場合】

aws cloudformation create-stack \
  --stack-name ytera-vsimage-pipeline \
  --template-body file://imagebuilder-pipeline.yaml \
  --parameters \
    ParameterKey=PasswordParameterName,ParameterValue=/ytera-vsimage/ubuntu-password \
    ParameterKey=CreateNewBucket,ParameterValue=true \
    ParameterKey=LoggingBucket,ParameterValue=ytera-vsimage-imagebuilder-logs-ap-northeast-1 \
  --capabilities CAPABILITY_NAMED_IAM \
  --region ap-northeast-1

【二回目以降の実行であり、既存のS3バケットを使用する場合】

aws cloudformation create-stack \
  --stack-name ytera-vsimage-pipeline \
  --template-body file://imagebuilder-pipeline.yaml \
  --parameters \
    ParameterKey=PasswordParameterName,ParameterValue=/ytera-vsimage/ubuntu-password \
    ParameterKey=CreateNewBucket,ParameterValue=false \
    ParameterKey=ExistingBucketName,ParameterValue=ytera-vsimage-imagebuilder-logs-ap-northeast-1 \
  --capabilities CAPABILITY_NAMED_IAM \
  --region ap-northeast-1

AMI作成手順

AMI作成テンプレート ami-creation-execution.yaml を実行し、AMI作成を行います。このスタック実行にはおおよそ40分ほどかかります。

パラメータ一覧

PipelineStackName 前工程でパイプラインを作成したスタック名を入力します。
ImageName 作成するAMIの名前を指定します。
EnableImageTests Image Builderは作成したAMIが正常に稼働するかをテストする機能があります。その自動テストを実施するかしないかを選択します。パイプラインではテスト定義をしていないため、falseを指定します。

コマンド例

aws cloudformation create-stack \
  --stack-name ytera-vsimage-ami-creation \
  --template-body file://ami-creation-execution.yaml \
  --parameters \
    ParameterKey=PipelineStackName,ParameterValue=ytera-vsimage-pipeline \
    ParameterKey=ImageName,ParameterValue=ytera-vsimage-ami \
    ParameterKey=EnableImageTests,ParameterValue=false \
  --region ap-northeast-1

EC2インスタンスの作成手順

AMIが正常に作成できたら、EC2インスタンス構築テンプレート ec2-launch-from-ami.yaml を開発者として実行します。これにより個人の環境にEC2インスタンスを起動します。このスタック実行にはおおよそ10分ほどかかります。

パラメータ一覧

AmiCreationStackName 前工程でAMIを作成したスタック名を入力します。
InstanceType Ubuntuを稼働させるインスタンスタイプを指定します。Gravitonである必要があります。初期値はt4g.large。
VpcId Ubuntuを稼働させるVPC IDを指定します。
SubnetId Ubuntuを稼働させるサブネットIDを指定します。パブリックサブネットである必要あります。
AllowedSubnet Ubuntuへ接続可能なPCのCIDRを指定します。ここで指定したCIDRからUbuntuのTCP 8443ポート、443ポートが許可されます。
DomainName Ubuntuのホスト名を含むFQDNを指定します。これがブラウザからアクセスするときのURLとなります。
Route53HostZoneId FQDNで指定したドメインを定義しているRoute 53のゾーンIDを指定します。このゾーンIDに対してAレコードを追加します。
PasswordParameterName EC2インスタンスのUbuntuルートパスワードとして設定する文字列を収納しているパラメータストアキー名を指定します。
EMAIL SSLサーバ証明書に埋め込むメールアドレスを指定します。何でもかまいません。

コマンド例

aws cloudformation create-stack \
  --stack-name ytera-vsimage-user1-instance \
  --template-body file://ec2-launch-from-ami.yaml \
  --parameters \
    ParameterKey=AmiCreationStackName,ParameterValue=ytera-vsimage-ami-creation \
    ParameterKey=InstanceType,ParameterValue=t4g.large \
    ParameterKey=SubnetId,ParameterValue=subnet-0d29XXXXXXXXXXXXXXd \
    ParameterKey=VpcId,ParameterValue=vpc-0e98dXXXXXXXXXXXXXX \
    ParameterKey=AllowedSubnet,ParameterValue=2XX.2XX.XX.XX/32 \
    ParameterKey=DomainName,ParameterValue=ytera-vsimage-user1-instance.example.com \
    ParameterKey=Route53HostZoneId,ParameterValue=Z09XXXXXXXXXXXXXXXXXXXX \
    ParameterKey=PasswordParameterName,ParameterValue=/ytera-vsimage/user1-password \
    ParameterKey=EMAIL,ParameterValue=ytera@example.com \
  --capabilities CAPABILITY_NAMED_IAM \
  --region ap-northeast-1

Ubuntuへアクセス

EC2インスタンス構築テンプレート ec2-launch-from-ami.yaml が正常終了すると、EC2へアクセスするURLが指定したFQDNを下に出力されます。スタックのOutputページを見ていただき、そのURLにDCVでアクセスしてください。
DCVの認証は、Ubuntuの一般ユーザ(ubuntu)とCFnテンプレートで指定したパラメータストアのパスワードでログイン可能です。その後、Ubuntuのログイン画面が出ますが、同じIDとパスワードでログインします。

本ツールのユースケースと今後の課題

本ツールでは、開発環境となるAMI作成と、実際のインスタンス化の工程を分離しているのが特徴です。常に開発環境のバージョンをセキュアに最新に保ち開発者に提供することが比較的簡単にできます。
毎晩AMI作成を自動で実行するようにスケジュールを組んでおき、開発者は毎朝EC2を作成する運用とすることで実現可能です。EC2作成のスタックでは、AMI作成スタックが出力するAMI IDを参照しているので、開発者はどのAMIが最新であるかを意識する必要がありません。
ただ開発者の個人設定などのホームディレクトリを、インスタンス外に自動退避し、EC2作成時に自動で戻す仕組みがまだできていませんが。

ライトなユースケースでは、Ubuntuの開発者のホームディレクトリをS3マウントしておくだけでもよいかもしれません。 

Mountpoint for Amazon S3 はメチャ便利だよ
Mountpoint for Amazon S3 はS3オブジェクトストレージを、ローカルディスクにマウントしブロックストレージのように扱うことのできる超便利な機能です。その使い方をAmazon Linux 2023 をベースに解説します。

最後に。本記事は、広野さんの秀逸なCloudFormationがあったからこそ実現できました。ありがとうございました。

タイトルとURLをコピーしました