cloud9を活用してM1チップ搭載MBP向けにIntelチップ開発環境を構築した話

この記事は [ハンズラボ AdventCalendar2022](https://qiita.com/advent-calendar/2022/handslab) 1日目の記事です。
ハイ、今年も１番手です。

# はじめに
ここ最近になって入社した開発メンバーには、M1チップを搭載したMacBookProが貸与されます。
しかし、古くから続いているプロジェクトで使用している古めの開発環境はM1チップに対応していない(特に古いDockerコンテナ)ことが多々あります。そのようなシチュエーションに対応するため  cloud9 + VSCode を活用して、Intelチップの開発環境を構築してみました。

# 事前準備
作業端末(M1搭載MacBookPro)に以下のツールを全てインストールしてください。

- [AWS CLI](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html)
    - [Session Managerプラグイン](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html)
- [VSCode](https://azure.microsoft.com/ja-jp/products/visual-studio-code/)
    - [Remote SSHプラグイン](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh)
- [serverless framework](https://www.serverless.com/)

その他、Cloud9を構築するAWSアカウントへのアクセス権限も必要です。[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-quickstart.html)を参照し、事前にプロファイルを設定してください。


# Cloud9環境構築
serverless framework を使用してAWS上にCloud9関連リソースを作成します。
今回はLambdaを作成しませんのでCloudFormationでも良いですが、使い慣れているためserverlessを利用しています。

```serverless.yml
service: {利用者名}-cloud9
frameworkVersion: '>=3.0.0 <4.0.0'

provider:
  name: aws
  runtime: python3.9
  stage: dev
  region: ap-northeast-1

resources:
  Resources:
  # --------------------------------------------------
  # VPC
  # --------------------------------------------------
    VPC:
      Type: AWS::EC2::VPC
      Properties:
        CidrBlock: 10.0.0.0/16
        EnableDnsSupport: true
        EnableDnsHostnames: true
        Tags:
          - Key: Name
            Value: ${self:service}-VPC

  # --------------------------------------------------
  # パブリックサブネット
  # --------------------------------------------------
    PublicSubnet1:
      Type: AWS::EC2::Subnet
      Properties:
        VpcId: !Ref VPC
        CidrBlock: 10.0.10.0/24
        AvailabilityZone: ap-northeast-1c
        MapPublicIpOnLaunch: true
        Tags:
          - Key: Name
            Value: ${self:service}-PublicSubnet1

  # --------------------------------------------------
  # インターネットゲートウェイ
  # --------------------------------------------------
    InternetGateway:
      Type: AWS::EC2::InternetGateway
      Properties:
        Tags:
          - Key: Name
            Value: ${self:service}-IGW

    GatewayToInternet:
      Type: AWS::EC2::VPCGatewayAttachment
      Properties:
        VpcId: !Ref VPC
        InternetGatewayId: !Ref InternetGateway

  # --------------------------------------------------
  # ルートテーブル(パブリック)
  # --------------------------------------------------
    PublicRouteTable:
      Type: AWS::EC2::RouteTable
      Properties:
        VpcId: !Ref VPC
        Tags:
          - Key: Name
            Value: ${self:service}-PublicRouteTable

    PublicSubnet1RTAssoc:
      Type: AWS::EC2::SubnetRouteTableAssociation
      Properties:
        RouteTableId: !Ref PublicRouteTable
        SubnetId: !Ref PublicSubnet1

    PublicRoute:
      Type: AWS::EC2::Route
      Properties:
        DestinationCidrBlock: 0.0.0.0/0
        GatewayId: !Ref InternetGateway
        RouteTableId: !Ref PublicRouteTable

  # --------------------------------------------------
  # Cloud9
  # --------------------------------------------------
    Cloud9:
      Type: AWS::Cloud9::EnvironmentEC2
      Properties: 
        Name: ${self:service}
        AutomaticStopTimeMinutes: 60
        ConnectionType: CONNECT_SSM
        ImageId: resolve:ssm:/aws/service/cloud9/amis/amazonlinux-2-x86_64
        InstanceType: t3.medium	
        SubnetId: !Ref PublicSubnet1
```

上記を `serverless.yml` という名前で保存して、AWS認証情報をセット後にデプロイコマンドを実行します。

```bash
$ sls deploy
```


# 秘密鍵ファイルの作成
Cloud9に接続するためのSSH秘密鍵ファイルを作成します。
`Enter file in which to save the key` と聞かれたら任意の鍵ファイルの名前を、それ以外は空白で大丈夫です。

```bash
$ cd ~/.ssh
$ ssh-keygen -b 4096 -C 'Cloud9' -t rsa

Enter file in which to save the key (/Users/{ユーザー名}/.ssh/id_rsa): cloud9
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
```

# Cloud9の初期設定
環境を構築したアカウントのAWSマネジメントコンソールにログインし、Cloud9のページを開きます。
[https://ap-northeast-1.console.aws.amazon.com/cloud9/home](https://ap-northeast-1.console.aws.amazon.com/cloud9/home)

環境を選択して [Open IDE] をクリックするとブラウザ上でIDEが開きます。
![スクリーンショット 2022-08-17 15.05.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501670/839ce20a-69de-9ace-74fe-a1b5cd3529d8.png)

設定作業を行なっていきます。

## パッケージアップデート
何は無くともアプデしましょう。IDE下部のコマンドラインから操作を行います。
```bash
$ sudo yum update
```

## SSH公開鍵の配置
ブラウザIDEは使いにくいため、VSCで操作できるようにSSHの設定を行います。
c9 をインストールするとブラウザIDEのエディタ上でファイルの編集が可能になります。
Cloud9上の `~/.ssh/authorized_keys` に、前手順作成した公開鍵(拡張子 .pub)の内容(ssh-rsa〜)を12行目にコピペします。

```bash
$ npm install -g c9
$ c9 ~/.ssh/authorized_keys

# エディタでファイルを開けるようになるので編集
```

## デフォルトの自動シャットダウンスクリプトを置き換える
Cloud9は未使用時間で自動シャットダウンするようになっていますが、使用しているとみなされるのはあくまでもブラウザ接続に限るので、そのままだと利用中にシャットダウンされてしまうため、スクリプトの書き換えを行います。

```bash
# Save a copy of the script first
$ 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
```

## EC2インスタンスIDの確認
AWSマネジメントコンソールに戻り、EC2管理画面を開きます。
`aws-cloud9-` から始まるEC2が起動しているはずですので、自分の名前が含まれたEC2のインスタンスID(i-xxxxxxxxxxxxxxxx)を控えます。


# M1端末側の初期設定
端末側の設定を行なっていきます。

## Session Manager設定
Cloud9への接続はSession Managerを経由して行います。そのためのスクリプトを設定します。スクリプトのベースはAWSから提供されていますので、それをダウンロードします。

```bash
$ 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
$ vi ~/.ssh/ssm-proxy.sh
```

ダウンロードしたスクリプトをエディタで開き、以下の通り修正します。

```bash
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0

#!/bin/bash
# Configuration
# Change these values to reflect your environment
AWS_PROFILE=$3
AWS_REGION=$4
MAX_ITERATION=5
SLEEP_DURATION=5
```

## SSHの設定を追記
端末側の `~/.ssh/config` に以下の設定を追加します。

```
Host cloud9
  IdentityFile ~/.ssh/{秘密鍵のファイル名}
  User ec2-user
  HostName {i-XXXXXXXXXXXXXXXXX(インスタンスID）}
  ProxyCommand sh -c "~/.ssh/ssm-proxy.sh %h %p {AWSプロファイル名} ap-northeast-1"
```

これで準備完了です。


# 接続確認
VSCode左下の `><` のマークをクリックし、ホストに接続する > `~/.ssh/config` に登録したホスト名を選択　で接続されます。
新しくウインドウが開き、左下に **SSH:ホスト名** が表示されていれば接続成功です。

![スクリーンショット 2022-08-17 15.33.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501670/02ba5195-69f8-f7f5-83c8-081ee4694943.png)

ここまで完了すれば通常の開発環境と同様に利用できますので、必要に応じて開発ツールのインストールやディスクの拡張などを実施してください。


# おわりに
他のメンバーが今まで普通に使えていた開発環境で、新メンバーだけ構築エラーとなり頭を抱えた時の救世主がcloud9でした。理想を言えばIntel,M1両対応の開発環境を構築するべきなのですが、長く運用しているプロダクトではなかなか難しいものです。何かのご参考になればと思います。



# 参考リンク
- [Field Notes: Use AWS Cloud9 to Power Your Visual Studio Code IDE
](https://aws.amazon.com/jp/blogs/architecture/field-notes-use-aws-cloud9-to-power-your-visual-studio-code-ide/)