JenkinsジョブをAWS EC2で実行する

背景

Pythonを含むジョブをAWS EC2インスタンスで実行したくなった。ジョブは頻繁に実行されるわけではないのでEC2インスタンスは常時起動しておく必要はなく、ジョブのたびにEC2インスタンスを立ち上げる仕様とする必要があった。

作業手順

EC2インスタンスの環境構築

UbuntuベースでEC2インスタンスを立ち上げた。そこに必要な環境をインストールした。以下にPython3.8を使うために行ったセットアップを記録しておく。

# Update
sudo apt update -y && sudo apt upgrade -y && sudo apt dist-upgrade -y && sudo apt autoremove -y && sudo apt autoclean -y

# Install Python and venv
sudo apt update && sudo apt-get install python3.8 python3.8-venv python3-pip
python3.8 -m venv project_name

# Install required libraries
# awscli is necessary for Ubuntu, not for Amazon Linux
sudo apt update && apt-get install awscli default-jre

# Install tools
sudo apt update && sudo apt-get emacs

# Change timezone to JST
sudo timedatectl set-timezone Asia/Tokyo

AMIを作成

EC2コンソール画面からAMIを作成する。この際EC2インスタンスは停止する必要はなく起動したままでよい。

Jenkins設定

(初めにおそらくEC2プラグインを入れる必要がある)「Jenkinsの設定」→「ノードの管理」→「Configure clouds」から新しい「Amazon EC2」設定を追加する。重要な設定項目は以下の通り

  • EC2 key Pair's Private Key: EC2にSSHするのに必要な公開鍵を指定する.
  • AMI ID: 作成したAMIのID(ami-******)を記載する.
  • Instance type: 立ち上げたいEC2のインスタンスタイプを指定する.
  • Security group: "ssh-connect"を設定する.
  • Remote FS root: Ubuntu の場合は"/home/ubuntu"、Amazon Linuxなら"/home/ec2-user".
  • Remote user: Ubuntu の場合は"ubuntu"、Amazon Linuxなら"ec2-user"
  • AMI type: "unix".
  • Labels: Jenkinsジョブ側から参照するときの識別ID.

Jenkinsジョブの作成

普段のJenkinsジョブ作成と基本的に同じだが、「General」→「実行するノードを制限」→「ラベル式」のところでは、先ほどのクラウド設定で「Labels」に書いたものと同じ文字列を記載する。

メモ

デフォルトのPyhtonバージョン

Ubuntu18.04ベースでEC2インスタンスを作成したが、デフォルトのPythonバージョンが3.6であった。Python3.8をインストールしてデフォルトバージョンにしようとしたが、以下のようなエラーが出て、作成したAMIからEC2を作成したときにステータスチェックで失敗してしまうので、venvを使いそこに環境を作ることにした。

AMI作成前に環境構築をしておく

Jenkinsジョブに依存しない設定(Pythonのインストールやタイムゾーンの設定など)はAMIを作るまえに設定しておけば、そのAMIをベースに作ったEC2インスタンスにもその設定が反映される。

Ubuntuタイムゾーン設定

デフォルトのEC2インスタンスUTCタイムゾーンになっていた。現在のタイムゾーンがどこであるかを確認するには

timedatectl

コマンドで確認できる。タイムゾーンを東京に変更するには

sudo timedatectl set-timezone Asia/Tokyo

とすれば良い。

EC2の起動時間

Jenkinsでジョブを実行してから実際にビルドが始まるまでは10-20分ほど時間がかかることがある。これはAMIからEC2インスタンスを起動するのに時間がかかっているため。

JenkinsジョブからEC2インスタンスへのSSH接続が失敗する

EC2インスタンスコネクトというのをセットアップしないとJenkinsからEC2へSSH接続できないらしい。Ubuntuの場合はドキュメントにあるようにawscliをインスタンスにインストールする必要があるらしい。Amazon Linuxの場合は不要らしく、この原因調査に時間がかかった。 参考:

docs.aws.amazon.com

Jenkisジョブに対して常にEC2を起動しておく場合

「Jenkinsの設定」→「ノードの管理」→「新規ノード作成」で「Permanent Agent」を追加すれば良いはず(未トライ)。