GitLab Runner(jobの中)からデプロイ先にSSHに入ってごにょごにょしたいときに使います。
dockerイメージを使っていますが、今回のジョブではdockerである必要はないです。
秘密鍵を生成する
ssh-keygen -t rsa -b 4096 -f id_rsa_deploy
生成された id_rsa_deploy(秘密鍵) と id_rsa_deploy.pub(公開鍵) は後で使います。
秘密鍵をGitLabの環境情報として設定
グループかプロジェクトのSettings→CI/CD→Variableから設定。TypeはFileにしておき、Valueに秘密鍵の内容をまるっと張り付ける。
GitLab Runnerからの接続先の authorized_keys に書き足す
公開鍵の内容をGitLab Runnerから接続する先(踏み台サーバなど)のauthorized_keysに書き足して、接続できるようにします。keyの大文字小文字は区別するので注意。
ssh-rsa AAAAB3Nza...OA9w== mydeploykey
鍵が漏れたら何されるかわからないので不安、という場合は、command="..."
をつけておくと、その秘密鍵ではcommand以外の操作ができなくなるので気休めになります。以下のようにすると、echoしかできません、多分。
command="echo SSH Test OK $SSH_ORIGINAL_COMMAND" ssh-rsa AAAAB3Nza...OA9w== mydeploykey
$SSH_ORIGINAL_COMMAND
環境変数を使うとsshコマンドの引数を受け取れますが、空白を含む1つの値を引数に与える際は注意する必要があります。そもそもここまでやるなら引数を使って処理するのは避けたほうがよいでしょう。
.gitlab-ci.yml を書く
今回は踏み台経由でほかのサーバも操作したかったのでSSH-Agentを張っていますが、必須ではないです。
SSH Agentを使わない場合は ssh -i "$ID_RSA_DEPLOY" -p22 USER@HOST echo hello world
とでもすればよいでしょう。
ポート(-p22
)とUSER
とHOST
は適宜置き換えてください。
image: docker:19.03.1
services:
- docker:19.03.1-dind
variables:
DOCKER_HOST: tcp://docker:2376
DOCKER_TLS_CERTDIR: "/certs"
deploy_production:
stage: deploy
script:
- apk update && apk add openssh
- chmod 0400 "$ID_RSA_DEPLOY"
- eval "$(ssh-agent)"
- ssh-add "$ID_RSA_DEPLOY"
- mkdir ~/.ssh/ && chmod 0700 ~/.ssh
- ssh-keyscan -p22 -H HOST > ~/.ssh/known_hosts
- ssh -A -p22 USER@HOST echo hello world
一応、known_hostsに追記していますが、この流れ作業ではもはや無視しても同じな気はします。
あとはymlファイルをpushすればciが動き始めるはず。
苦労ポイント
- docker imageはalpine系でsshもgitもないのでapkで導入する必要がある
- 環境設定で作られたファイルの権限が 0666 なので、そのままSSHでは使えなかった(なのでchmod 0400にしている)
- knwon_hostsに登録が必要だし、
~/.ssh/
がないので作る必要があった
.gitlab-ci.yml
を1行足しては再実行を繰り返したことですかね・・・これだけでも10回ぐらい流した気がする。みんなこうやって書いてるんだろうか・・・