どうも、大曲です。
Oct-passというサービスやってます。
今回は、定期処理をcrondからJenkins2に置き換えた話に関して書きます。
定期処理をJenkins2でやることになった経緯
Oct-passのサービス開始してから、1年以上が過ぎました。
それに伴って扱うデータ量も増えていき、定期処理の時間が長くなり
重複して実行されるようになってきました。
そして、重複されてから調べることが多くなってきたので
ある程度事前に分かるようにしたいと言うことでJenkins2でやることにしました。
crondからの移行に関して満たしたかった点
- Slackへの通知ができるようにしたい(メールよりもSlackの方が気付くため)
- タイムアウトなどを設定できるようにしたい
- 処理の重複が走らないようにしたい
- 処理をAnsible化して、手動でサーバをいじることを避けたい(Jenkinsおじさん撲滅)
Jenkins2にした理由
- JenkinsをCIサーバとして使っていたため、慣れている
- jenkinsfileを使えば、GUIやXMLを弄ることが減って楽
- jenkinsfileを利用すればshellやAnsibleの実行だったり、処理の流れが把握できる
主に、jenkinsfileがあることが大きいです。
セットアップの方法
https://github.com/oomatomo/ansible-jenkins2
今回は、サンプルとして上記のリポジトリを用意しました。
実際の処理の流れを体験できればいいなと思います。
JenkinsセットアップのAnsibleを実行
# dockerのビルド docker-compose build dev # passwordは test です ssh -p 2222 test@127.0.0.1 # ansibleの実行 ansible-playbook ansible-jenkins2/ansible/jenkins.yml
Jenkinsの初期設定
上記の内容でJenkins2が立ち上がったのでアクセスすると、
Jenkins2の初期設定の画面が出てくるので、設定していきます。
docker内のパスワードを取得して入力します。
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
プラグインのインストールです。
install suggested plugins
を選んでください。
プラグインのインストール中の画面です。
次に、adminユーザーの作成に入ります。
今回は、テストのなのでユーザー名とパスワードを共にtest
でお願いします。
これで初期設定は完了して、Jenkinsのトップ画面が表示されます。
Adminユーザーの設定
Admin用の鍵を作成する
sudo -u jenkins ssh-keygen -t rsa -C jenkins
GUIでAdminユーザーの公開鍵を設定します。
http://127.0.0.1/user/test/configure
SSH Public Keysの項目
鍵は、上で作った公開鍵で大丈夫です。
この鍵は、jenkins-cliでジョブを更新するときに必要なので作っておきます。
cat /var/lib/jenkins/.ssh/id_rsa.pub
Ansibleでジョブの作成
ansible-playbook ansible-jenkins2/ansible/jenkins-job.yml
これで、ジョブが二つ登録されています。
jobを実行
masterが更新されると、どのジョブから変更が反映されたか分かります。
はまった点
jenkins-cliでcreate-jobは、鍵認証は必要無いがupdate-jobでは必要だったこと
cliを使ったジョブの作成のコマンドは以下の通りです。
認証は、usernameとpasswordで行っています。
java -jar jenkins-cli.jar -s http://localhost:8080 create-job --username test --password test test1 < job_config_test1.xml
XMLの更新などで、ジョブの設定変更があった場合にjenkins-cliのupdate-job
を利用します。
この時の認証は、秘密鍵を指定して公開鍵認証を行っています。
java -jar jenkins-cli.jar -s http://localhost:8080 -i /var/lib/jenkins/.ssh/id_rsa update-job test1 < job_config_test1.xml
update-job
で公開鍵認証しなければいけないときに、毎回 No such job
と出ていたいので詰まりました。
良かった点
- 定期処理にどれくらい時間がかかっているか分かる
- Slackへの通知はやっぱり便利
- Ansibleでジョブの登録が完結できる
Ansibleでジョブの登録が完結できる
全てのジョブ登録をAnsibleにしたので出来るようにしたので
本番を直接触ることがなくなったので、オペレーションミスが減るのでよかったと思っています。
悪かった点
- ジョブの追加のために、色々とやらないといけない
- 失敗した場合のリカバリー処理がない
ジョブの追加のために、色々とやらないといけない
crondを使っていた時は、crontab -e
でいじっていたり
Ansibleのcronモジュールを使ったりとサクッと追加できるのですが。
Ansibleにjob用のxmlファイルの追加したり、jenkinsfileの追加など・・・
逆にこれが手間だと感じることもあります。
失敗した場合のリカバリー処理がない
現状は、手動でビルド実行ボタンをGUIでポチッと押している。
もっといい感じのリカバリー処理無いかなと探しています。
一度失敗したら、一定期間は定期実行をしないとかできたらいいなと考えています。。
これからやりたいこと
- 失敗した場合の処理、リカバリーの処理の追加
- Jenkins自体のバッグアップ等々
- jenkinsfileで利用できるプラグインの更新
jenkinsfileで利用できるプラグインの更新
上のサンプルのリポジトリのjenkinsfileでは、Slackへの通知をcurlを使っていましたが
ちゃんとSlackのプラグインが簡単に書けるように対応しているみたいです。
https://jenkins.io/blog/2016/07/18/pipline-notifications/
このように、jenkinsfileで書けるように各プラグインが対応してきているので
もっとできることが増えると思うので定期的にリプレースできればいいなと考えています。
crondからの移行に関して満たしたかった点の振り返り
とりあえず、満たしたいことは全部出来たのでよかったなと思っています。
Slackへの通知ができるようにしたい(メールよりもSlackの方が気付くため)
jenkinsfileで対応できました。
// Slackへの通知 def notifySlack(text, channel) { def slackURL = '' def jenkinsIcon = 'https://wiki.jenkins-ci.org/download/attachments/327683/JENKINS?version=1&modificationDate=1302750804000' def payload = JsonOutput.toJson([text : text, channel : channel, username : "jenkins", icon_url : jenkinsIcon]) sh "curl -X POST --data-urlencode \'payload=${payload}\' ${slackURL}" } // 使い方 notifySlack("build failed ${env.JOB_NAME} <!channel>", "#test")
タイムアウトなどを設定できるようにしたい
jenkinsfileで対応できました。
// 分単位の設定が出来る。1分以上処理にかかったらエラーとなる timeout(1) { 処理.... }
処理の重複が走らないようにしたい
Jenkinsのジョブの設定でビルドの並列ができないように設定しました。
処理をAnsible化して、手動でサーバをいじることを避けたい(Jenkinsおじさん撲滅)
ジョブの登録を全てAnsibleで出来るようになりました。
サービスでの現状
Jenkins2は、6,7月から利用しています。
ただ、全ての定期処理をJenkins2に移行したわけではありません。
Oct-passの改善の週
があるのでその週で既存のものを移行したり、
新規の定期処理をJenkins2で行っていたりしてます。
あと、本番ではテスト用で簡単にjenkinsfileを設定できるジョブを登録して
このjenkinsfileの書き方はあっているか?正常に動くのかチェックしています。
最後に
現状だと、Jenkins2にした良かったと思っています。
あとciサーバは、自分がJenkinsおじさんとなっているので
テストのジョブもjenkinsfileにしてJenkinsおじさんを撲滅したいです。