【VSCode/Cloud9】少し不便に感じていた点の回避策があった件について

記事タイトルとURLをコピーする

こんにちは。AWS CLIが好きな福島です。

はじめに

今回は、VSCode/Cloud9の構成で少し不便に感じていたことがあったのですが、 その回避策が2021年のAWS Blogで既に紹介されていたため、その方法をブログにまとめます。

この回避策により、マネコンを開かずにVSCodeだけ開くことで開発環境にアクセスできるため、より開発が捗りそうです。

参考情報

https://aws.amazon.com/jp/blogs/architecture/field-notes-use-aws-cloud9-to-power-your-visual-studio-code-ide/

不便に感じていた点

不便に感じていたのは、以下の2点となり、これによりVSCode/Cloud9の構成でも、 Cloud9のマネジメントコンソールへのアクセスやAWS CLIを使うなど1手間必要でした。

①Cloud9の起動が手間な点

Cloud9は停止している場合でも、マネジメントコンソールからアクセスすれば、 自動で起動されるのが嬉しいポイントです。

ただ、VSCode/Cloud9の場合、VSCodeからCloud9への接続を試みても、停止しているCloud9は自動起動されません。

そのため、Cloud9を起動するために、マネジメントコンソールへのアクセスやAWS CLIを使うなど1アクション必要でした。 (当たり前ではあるのですが、②と相まってめんどくさく感じていました。)

②VSCodeから接続しているのにも関わらず、Cloud9が自動停止される点

Cloud9はタイムアウト値を分単位で指定でき、非アクティブになった状態がその値に達するとインスタンスが自動的に停止されます。

これはコスト削減の観点から嬉しい機能ではあるのですが、この仕組みは、マネジメントコンソールからアクセスしている場合に正常に機能します。

つまり、VSCodeからCloud9に接続していても、Cloud9はアクティブな接続があると認識しないため、 タイムアウト値の値に達するとインスタンスが自動的に停止されます。

ちなみに、タイムアウト値を伸ばす選択肢もあったのですが、コストの観点からあまり伸ばしたくもないなと思い、デフォルト値のままにしていました。

回避策

ざっくり回避策を記載します。

Cloud9の起動が手間な点に対する回避策

~/.ssh/configのProxyCommandにお手製のスクリプトを実装します。

お手製のスクリプトは、AWS Blogで紹介されているものを流用します。

https://github.com/aws-samples/cloud9-to-power-vscode-blog/blob/main/scripts/ssm-proxy.sh

処理としては単純でCloud9が起動していない場合に、起動した上で接続を行います。

# ~/.ssh/configの設定イメージ

## 変更前

host cloud9
    HostName i-xxxx
    ★ ProxyCommand sh -c "aws ssm start-session --target i-xxxx --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"
    User ec2-user
    IdentityFile "キーペアのパス"

## 変更後

host cloud9
    HostName i-xxxx
    ★ ProxyCommand sh -c "~/.ssh/ssm-proxy.sh %h %p"
    User ec2-user
    IdentityFile "キーペアのパス"

VSCodeから接続しているのにも関わらず、Cloud9が自動停止される点に対する回避策

Cloud9の自動停止機能は、~/.c9/stop-if-inactive.shによって実装されています。 そのため、このスクリプトを修正します。

ただし、逆にVSCodeを開きっぱなしの場合、Cloud9がずっと起動されてしまうため、 VSCodeを閉じるのを忘れないようにする注意が必要です。

構成図

以降から実際に設定方法を記載するのですが、その際の構成図は以下の通りです。

設定方法

Cloud9関連のデプロイ

  • git clone
git clone git@github.com:kazuya9831/blog-sample.git
  • ディレクトリの移動
cd blog-sample/cloud9
  • スタック名の変数設定
STACK_NAME=dev-env-cloud9
  • Cloud9関連のデプロイ

以下のリソースをデプロイします。 VPC / Public Subet / IGW / Route Table / Cloud9

aws cloudformation deploy \
--stack-name ${STACK_NAME} \
--template-file cloud9-template.yml \
--capabilities CAPABILITY_NAMED_IAM

Cloud9のインスタンスIDを取得

  • スタックのアウトプットからCloud9の環境IDを取得
CLOUD9_ENV_ID=$(
    aws cloudformation describe-stacks \
        --stack-name "${STACK_NAME}" \
        --query "Stacks[].Outputs[?OutputKey=='DEVENVCloud9'].[OutputValue]" \
        --output text
)
  • Cloud9の環境IDを基にEC2のインスタンスIDを取得
INSTANCE_ID=$(
    aws ec2 describe-instances \
        --query "Reservations[].Instances[?Tags[?Value=='${CLOUD9_ENV_ID}']].[InstanceId]" \
        --output text
)

VSCodeからCloud9へSSH接続するための準備

  • 秘密鍵/公開鍵の作成
mkdir ~/.ssh/cloud9
ssh-keygen -b 4096 -C 'VS Code Remote SSH user' -t rsa -f ~/.ssh/cloud9/cloud9_id_rsa -N ""
  • 公開鍵の中身を確認およびコピー

以降の手順でこのファイルの中身のデータを利用するため、コピーしておきます。

cat ~/.ssh/cloud9/cloud9_id_rsa.pub
  • ssm-proxy.shのダウンロード

ポイントになるssm-proxy.shをダウンロードします。 このスクリプトにより、VSCodeからCloud9へ接続する際に、Cloud9が停止している場合、自動で起動を行ってくれます。

curl https://raw.githubusercontent.com/aws-samples/cloud9-to-power-vscode-blog/main/scripts/ssm-proxy.sh -o ~/.ssh/ssm-proxy.sh
chmod +x ~/.ssh/ssm-proxy.sh
  • ssm-proxy.shの修正
vi ~/.ssh/ssm-proxy.sh

7,8行目の以下の設定を環境に合わせて修正します。

AWS_PROFILE='dev'
AWS_REGION='ap-northeast-1'
  • Cloud9へのssh(~/.ssh/config)設定

~/.ssh/configの設定を行います。

以下のコマンド(全行)をコピペで実行することで、~/.ssh/configに設定が追記されます。

cat << EOF >> ~/.ssh/config

host cloud9
    HostName "${INSTANCE_ID}"
    ProxyCommand sh -c "~/.ssh/ssm-proxy.sh %h %p"
    User ec2-user
    IdentityFile ~/.ssh/cloud9/cloud9_id_rsa
EOF

Cloud9上での設定

  • Cloud9へ接続
aws ssm start-session \
    --target "${INSTANCE_ID}"
  • 自動停止スクリプトの差し替え

これにより、VSCodeからCloud9へ接続されている場合に自動停止されることを防げます。

sh-5.2$ sudo su - ec2-user
:~ $ sudo mv ~/.c9/stop-if-inactive.sh ~/.c9/stop-if-inactive.sh-SAVE
:~ $ curl https://raw.githubusercontent.com/aws-samples/cloud9-to-power-vscode-blog/main/scripts/stop-if-inactive.sh -o ~/.c9/stop-if-inactive.sh
:~ $ sudo chown root:root ~/.c9/stop-if-inactive.sh
:~ $ sudo chmod 755 ~/.c9/stop-if-inactive.sh

具体的な変更点としては、Cloud9上でVSCode関連のプロセスが起動しているかをチェックする関数が追加されており、 この関数が自動停止を判断するif文に追加されています。

https://github.com/aws-samples/cloud9-to-power-vscode-blog/blob/main/scripts/stop-if-inactive.sh#L59-L61

  • 公開鍵の登録

~/.ssh/authorized_keysにコピーしておいたデータを貼り付けます。

:~ $ vi ~/.ssh/authorized_keys

これでCloud9上の操作は終わりのため、抜けます。

:~ $ exit
sh-5.2$ exit

動作確認前の事前準備

  • VSCodeにRemote-SSHの拡張機能を導入します。

  • Remote-SSHの「"remote.SSH.connectTimeout"」設定を30秒に変更します。
    デフォルトは15秒になっているのですが、EC2が停止している場合、起動処理が行われるため、 タイムアウトする可能性があるので、タイムアウト値を伸ばしておきます。

動作確認

VSCodeからCloud9へ接続する際にCloud9が自動起動するかの確認

Cloud9が停止していることを確認します。

$ aws ec2 describe-instances \
        --instance-ids ${INSTANCE_ID} \
        --query "Reservations[].Instances[].[InstanceId,State.Name]" \
        --output text
i-00819582a94c0a9a9     stopped
$

左下の緑色のボタンを押してから、ホストに接続するを押下します。

~/.ssh/config設定のhost一覧が出力されるため、その中から先ほど設定したcloud9を選択します。

選択後、新しいウィンドウが開かれ、右下にトーストが表示されます。 トーストのdetailsを押下し、ログを確認することもできます。

しばらくすると、Cloud9の起動が完了し、Cloud9へ接続ができるかと思います。 左下の緑色の部分を見ると、SSH:Cloud9となっていることが分かります。

ローカルで作業前に実行したコマンドを再度実行すると、EC2(Cloud9)のステータスがrunningになっていることが分かります。

$ aws ec2 describe-instances \
        --instance-ids ${INSTANCE_ID} \
        --query "Reservations[].Instances[].[InstanceId,State.Name]" \
        --output text
i-00819582a94c0a9a9     running
$

VSCodeからCloud9へ接続している場合、Cloud9が自動停止されないことを確認

まずは、Cloud9が自動停止されることを確認します。 デフォルトでは、タイムアウト値が30分で長いため、1分に変更します。

AWS Cloud9 > Preferences > Custom Shutdown value

その後、Cloud9へのアクティブな接続がないようブラウザやVSCodeを閉じ、 whileでEC2のステータスを確認します。

while :
do 
   echo "$(date): $(aws ec2 describe-instances --instance-ids ${INSTANCE_ID} --query 'Reservations[].Instances[].[InstanceId,State.Name]' --output text)"
   sleep 3
done

結果は以下の通り、約1.5分で停止されました。

(12時07分47秒に起動し、12時09分13秒に停止)

2024年 3月27日 水曜日 12時07分40秒 JST: i-00819582a94c0a9a9 stopped
2024年 3月27日 水曜日 12時07分42秒 JST: i-00819582a94c0a9a9    pending
2024年 3月27日 水曜日 12時07分43秒 JST: i-00819582a94c0a9a9    pending
2024年 3月27日 水曜日 12時07分45秒 JST: i-00819582a94c0a9a9    running
                       : 中略
2024年 3月27日 水曜日 12時09分17秒 JST: i-00819582a94c0a9a9    stopping
2024年 3月27日 水曜日 12時09分21秒 JST: i-00819582a94c0a9a9    stopped

続いてVSCodeからのみ接続して様子を見てみます。 少し長めに7分程度見てみましたが、想定通り、自動停止されませんでした!

2024年 3月27日 水曜日 12時18分18秒 JST: i-00819582a94c0a9a9 stopped
2024年 3月27日 水曜日 12時18分21秒 JST: i-00819582a94c0a9a9    pending
2024年 3月27日 水曜日 12時18分25秒 JST: i-00819582a94c0a9a9    running
                       : 中略
2024年 3月27日 水曜日 12時19分24秒 JST: i-00819582a94c0a9a9    running
                       : 中略
2024年 3月27日 水曜日 12時20分27秒 JST: i-00819582a94c0a9a9    running
                       : 中略
2024年 3月27日 水曜日 12時21分29秒 JST: i-00819582a94c0a9a9    running
                       : 中略
2024年 3月27日 水曜日 12時22分28秒 JST: i-00819582a94c0a9a9    running
                       : 中略
2024年 3月27日 水曜日 12時23分27秒 JST: i-00819582a94c0a9a9    running
                       : 中略
2024年 3月27日 水曜日 12時24分26秒 JST: i-00819582a94c0a9a9    running
                       : 中略
2024年 3月27日 水曜日 12時25分29秒 JST: i-00819582a94c0a9a9    running

ついでにVSCodeを閉じた後に正しく停止されることも確認しておきます。

約7分後に停止処理が開始しました。 (12時34分03秒くらいにVSCodeの接続を切り、12時41分14秒に停止処理が開始)

2024年 3月27日 水曜日 12時34分03秒 JST: i-00819582a94c0a9a9 running
                       : 中略
2024年 3月27日 水曜日 12時41分11秒 JST: i-00819582a94c0a9a9    running
2024年 3月27日 水曜日 12時41分14秒 JST: i-00819582a94c0a9a9    stopping
                       : 中略
2024年 3月27日 水曜日 12時42分02秒 JST: i-00819582a94c0a9a9    stopping
2024年 3月27日 水曜日 12時42分06秒 JST: i-00819582a94c0a9a9    stopped

1分程度ではなく、7分かかったのかは、おそらくCloud9上で稼働するvscode-serverがクライアントからの接続がなくなってからも、 一定時間( 5分程度?)起動し続けるからではないかなと推測します。

終わりに

今回は、VSCode/Cloud9で不便に感じていた点についての回避策をまとめてみました。 どなたかのお役に立てれば幸いです。

福島 和弥 (記事一覧)

2019/10 入社

AWS CLIが好きです。