5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

CircleCI × Capistranoでec2にデプロイできなくて困った。

Last updated at Posted at 2020-05-20

CircleCIでCI/CDパイプラインを構築していたところ、どうしてもcapistranoの実行プロセスでSSHエラーが出るので、憤慨。結果から言うと、セキュリティグループのポートがマイIPからしか解放されないように設定していた故のエラーだったのですが、変更がめんどくさそうなのでもっといい方法がないかと模索したところ、半日くらいこのデバックに費やしてしまいました(とほほ)。
ですが、デバッグの過程で各々のツールに関する知識が深まったので、結果オーライかなぁと思うわけです。
以下、備忘録。

ーーーーーーーーーーーーーーーーーーーーーーーーーーー

【原因のエラーメッセージ】

cap aborted!
SSHKit::Runner::ExecuteError: Exception while executing as ユーザー名@IPアドレス: 
Net::SSH::ConnectionTimeout


Caused by:
Net::SSH::ConnectionTimeout: Net::SSH::ConnectionTimeout


Caused by:
Errno::ETIMEDOUT: Connection timed out - connect(2) for IPアドレス

Tasks: TOP => rbenv:validate
(See full trace by running task with --trace)

ムムム、Capistranoの設定の時に散々遭遇した覚えがある。

実際にこの処理が行われているのは、CircleCIのサーバー上に立てられたdockerコンテナなので(合ってますよね?)、どうにかこの中に入って原因を突き止めたい。

該当するワークフローの画面から、Rerun Job with SSH を選択し、
Enable SSH に表示されるIPをコピーする。
スクリーンショット 2020-05-19 23.26.59.png

capistranoのデプロイ先であるEC2インスタンスから、github用の秘密鍵を用いて、circleciのコンテナにSSH接続します。

(ここら辺の動きがまだよくわからん。CiecleCIにはgithubとの連携の際に公開鍵が登録されてるってことですか?)

【EC2インスタンス】
$ ssh -i ~/.ssh/aws_git_rsa -p Enable SSHの値
The authenticity of host 'Enable SSHの値 (Enable SSHの値)' can't be established.
RSA key fingerprint is 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
RSA key fingerprint is 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
Are you sure you want to continue connecting (yes/no)? 

確認されるので、yesと入力。

circleci@~~~~~~~~~ :~$ 

無事入れました。

コンテナ内を回遊してわかったんですが、結局ローカルでやろうとしてることをこのコンテナ内で再現しようとしているだけなんですよね。つまり、EC2に接続できなかったのは、ローカルの~/.sshに置かれている秘密鍵がcircleci@ :~/.sshには存在しないからなのです。思ったより単純でした。

ローカルの~/.sshにあるEC2用の秘密鍵をコピーします。

.ssh % pbcopy < ~/.ssh/himitsu_key_rsa
スクリーンショット 2020-05-20 11.09.50.png

サークルCI->プロジェクトページ->右上設定タブ->project settings

スクリーンショット 2020-05-20 11.12.15.png

サイドバーにあるSSHkeysを選択。

スクリーンショット 2020-05-20 11.13.46.png

Add SSH Keyから、EC2用の秘密鍵を設定します。

スクリーンショット 2020-05-20 11.18.13.png

Hostnameを、EC2のElasticIP。Private Keyに、先ほどコピーした鍵の値をCtrl+Vで貼り付ける。値がinvalidだと怒られる。PEM形式でないと鍵の値を保存できないみたい。

参考:https://amasuda.xyz/post/2019-07-27-ssh-keygen-openssh-to-pem/

上記の記事などを参考に、鍵の形式を変更します。

スクリーンショット 2020-05-20 11.29.52.png

BEGIN OPENSSH PRIVATE KEY が BEGIN RSA PRIVATE KEY
に変わっていれば保存できるはずです。

スクリーンショット 2020-05-20 11.48.36.png

登録を終えたら、上記画像のFingerprintの値をコピーして、.circleci/config.ymlのプロセスに記載します。

      - add_ssh_keys:
          fingerprints:
            - "コピーしたFingerprint"

      - deploy:
          name: Capistrano deploy
          command: |
            if [ "${CIRCLE_BRANCH}" != "master" ]; then
              exit 0
            fi
            bundle exec cap production deploy

ここでひとまず、githubにプッシュ。実行されたプロセスを確認してみると、

スクリーンショット 2020-05-20 12.00.19.png

fingerprintをもとに鍵の値をインストールしてくれています。

一旦コンテナの中に入って、確認してみましょう。

circleci@~~~~~~~~~:~$ ls .ssh
config  id_rsa  id_rsa_11111111111111111111111111111111  known_hosts

【id_rsa + _fingerprintから:を抜いた値】と言う形式で保存されている鍵があります(ここでは例として111...を記載しています)。

このファイルを展開してみましょう。

circleci@~~~~~~~~~:~$ cat .ssh/id_rsa_11111111111111111111111111111111
-----BEGIN RSA PRIVATE KEY-----

   【さっき登録した秘密鍵の値】

なるほど、さっき登録した秘密鍵は、【id_rsa + _fingerprintから:を抜いた値】という名前でCircleCIコンテナの.ssh配下に保存されているわけですね。

ローカルでは、環境変数を用いてこの鍵へのパスを指定していました。

【config/deploy/production.rb】

server 'ElasticIP',
   user: "ユーザー名",
   roles: %w{web db app},
   ssh_options: {
       port: 22,
       keys: ["#{ENV.fetch('PRODUCTION_SSH_KEY')}"],
       forward_agent: true
   }

しかし、ローカルとCircleCIコンテナでは鍵の名前が異なりますし、環境変数は各々のサーバーで設定する必要がありますから、CircleCI側で改めて環境変数を指定し直さなくてはなりません。

先ほどと同じく、ProjectSettingsから
スクリーンショット 2020-05-20 11.09.50.png

サイドバーのEnvironment Variablesを選択。
スクリーンショット 2020-05-20 12.25.25.png

Add Variableから
スクリーンショット 2020-05-20 12.26.02.png

環境変数を指定します。Nameはdeproy/production.rbで使用している変数名と同じものを指定。
valueはCircleCIコンテナにある秘密鍵へのパスを指定します。

スクリーンショット 2020-05-20 12.27.23.png

ここまでくれば大丈夫なはず!再実行をしてみる!!!

cap aborted!
SSHKit::Runner::ExecuteError: Exception while executing as ユーザー名@IPアドレス: 
Net::SSH::ConnectionTimeout


Caused by:
Net::SSH::ConnectionTimeout: Net::SSH::ConnectionTimeout


Caused by:
Errno::ETIMEDOUT: Connection timed out - connect(2) for IPアドレス

Tasks: TOP => rbenv:validate
(See full trace by running task with --trace)

ムカつくな、試しにEC2のインバウンドルールを変更します。22番ポートを完全に解放。

スクリーンショット 2020-05-20 12.38.16.png スクリーンショット 2020-05-20 12.39.21.png

まんまと成功しやがって、畜生、マジで。まあそうだよな。マイIPからのSSHじゃなきゃ開けないって設定したの自分なのに、馬鹿みたいじゃないか。

CircleCIでは毎回新しくコンテナを立ち上げている(?)のでIPアドレスが流動的です。つまり、プロセスを開始するたびに、そのコンテナからの接続を許可し、処理が終わったらそれを破棄しなければならない。

参考:https://qiita.com/rintaro-ishikawa/items/02e6a63dbc90ea67a991

この記事を参考に次の記事で問題を解決してみます。

あぁ、早くReactさわりたい。

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?