Blogaomu

WEBアプリケーション開発とその周辺のメモをゆるふわに書いていきます。

作業用EC2インスタンスを cloud-init で準備する

AWS環境で単発の作業用サーバー(例: 負荷テストツールの実行用)を楽に準備したくて cloud-init を利用する方法を調べました。EC2インスタンスの起動時にユーザーが定義した設定を行ってくれる仕組み(= cloud-init)があり、この設定をユーザーデータという形でEC2インスタンスに渡すことができます。

cloudinit.readthedocs.io

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/user-data.html

要件

  • プライベートサブネットに配置
  • デフォルトの ec2-user ではなくて、特定のユーザーでSSHログインしたい(公開鍵認証)
  • OpenJDK8 と sbt がインストール済み
    • Gatling という負荷テストツールを利用する想定
    • amazon-corretto のインストールで良い方法が見つからなかったので OpenJDK にしています

ユーザー作成

まず、SSHログインするためのユーザーアカウントを作成します。ログインするために公開鍵を登録するというのがポイントになります。cloud-init の users 設定で行います。

#cloud-config
cloud_final_modules:
    - [users-groups, always]
users:
    - name: takagi
      groups: [wheel]
      sudo: ["ALL=(ALL) NOPASSWD:ALL"]
      shell: /bin/bash
      ssh-authorized-keys:
          - ssh-rsa publickey # 公開鍵をセットする

この設定は以下資料を参考にしました。

aws.amazon.com

EC2インスタンス作成時に上記の設定内容をユーザーデータに渡しインスタンスが起動するとSSHログインできるようになります。踏み台サーバー経由でログインするために以下のような設定を行います。鍵は簡易的に踏み台サーバーと同じものを利用しています。諸々の設定が上手くいけば ssh working-server でログイン可能です。

# ~/.ssh/config
Host bastion # 踏み台サーバー
    HostName x.x.x.x # public IPアドレス
    User takagi
    IdentityFile /Users/takayuki_atkwsk/.ssh/id_rsa
Host working-server # 作業用サーバー
    HostName 192.168.2.73 # private IPアドレス
    User takagi
    IdentityFile /Users/takayuki_atkwsk/.ssh/id_rsa
    ProxyCommand ssh -W %h:%p bastion

パッケージのインストール

次に必要なパッケージをインストール済みの状態にします。上記でSSHログインできるようになった段階で yum install コマンドを打っても良いのですが、時間が空いて別の作業用インスタンスを起動したときに再度打つのも面倒くさいので cloud-init に任せてしまいます。今回は OpenJDK と sbt をインストールします。注意点としては、パッケージのインストールはインスタンスのライフサイクルで一度しか行われないため、上記の設定でインスタンスを起動した場合は一度終了(stop ではなく terminate)してパッケージの設定を追加した新しいインスタンスを作り直しましょう。

sbt に関しては以下のインストール方法に記されている方法の内、RPMレポジトリをパッケージマネージャに追加する方法で行います。

curl https://bintray.com/sbt/rpm/rpm | sudo tee /etc/yum.repos.d/bintray-sbt-rpm.repo
sudo yum install sbt

www.scala-sbt.org

cloud-init で対応するには yum_repos という設定を利用します。各設定値には上記の sbt RPM URLから得られるデータに含まれる値を使います。こちらがダウンロードしたデータです。

#bintray--sbt-rpm - packages by  from Bintray
[bintray--sbt-rpm]
name=bintray--sbt-rpm
baseurl=https://sbt.bintray.com/rpm
gpgcheck=0
repo_gpgcheck=0
enabled=1

それぞれの値を yum_repos に当てはめると以下の cloud-init 設定になります。これでパッケージマネージャにレポジトリを追加できます。後は yum install でインストールしたいパッケージ名を packages の値に書き込みます。

yum_repos:
    bintray--sbt-rpm:
        baseurl: https://sbt.bintray.com/rpm
        name: bintray--sbt-rpm
        enabled: true
        gpgcheck: false
packages:
    - java-1.8.0-openjdk-devel
    - sbt

yum_repos: https://cloudinit.readthedocs.io/en/latest/topics/modules.html#yum-add-repo

packages: https://cloudinit.readthedocs.io/en/latest/topics/modules.html#package-update-upgrade-install

この設定をユーザーデータに含めてインスタンスを起動すると、OpenJDK および sbt がインストールされた状態になっています。これで Gatling シミュレーションを含んだソースコードをローカルから scp すれば実行できるようになります。

[takagi@ip-192-168-2-73 ~]$ which java
/usr/bin/java
[takagi@ip-192-168-2-73 ~]$ which sbt
/usr/bin/sbt
[takagi@ip-192-168-2-73 ~]$ java -version
openjdk version "1.8.0_242"
OpenJDK Runtime Environment (build 1.8.0_242-b08)
OpenJDK 64-Bit Server VM (build 25.242-b08, mixed mode)

まとめ

用意した cloud-init 設定全体を以下に示します。今回は単発でEC2インスタンスを利用する(=定常的に稼働しないまたは他の人が利用しない)用途だったのでこのくらいの簡潔さが丁度良いなと感じました。組織でEC2インスタンスの構成管理を行いたい場合になると Chef や Ansible などのツールを使う方が上手く運用できるのかもしれません。

#cloud-config
cloud_final_modules:
    - [users-groups, always]
users:
    - name: takagi
      groups: [wheel]
      sudo: ["ALL=(ALL) NOPASSWD:ALL"]
      shell: /bin/bash
      ssh-authorized-keys:
          - ssh-rsa publickey # 公開鍵をセットする
yum_repos:
    bintray--sbt-rpm:
        baseurl: https://sbt.bintray.com/rpm
        name: bintray--sbt-rpm
        enabled: true
        gpgcheck: false
packages:
    - java-1.8.0-openjdk-devel
    - sbt