「秘伝化したJenkinsと共に動いているレガシーなDockerをバージョンアップする」をやった

仕事でレガシーなEC2インスタンス上にあるレガシーなJenkinsと共に動いているDockerエンジンをアップデートする対応を行った。その際の備忘録を書いておく。

tl;dr

状況としては以下の通り

  • Jenkinsでのデプロイに使用しているDockerのバージョンが古すぎる
  • Jenkinsが動いているEC2インスタンスを複製してJenkins Agentとして起動した
  • master側のDockerをアップデートし、古いDockerと新しいDockerそれぞれを好きに使い分けられる状態にした

くわしく

Jenkinsの上で動いているDockerのバージョンが古すぎるため、新し目のalpineを使用したイメージを扱えない問題が発生していた。詳細は以下を参照してほしいが、ようは musl が扱う新しい命令を runc が対応しきれていない、という問題だった。

インターフェイスが大きく変わるわけでもないし、エイヤでDockerをアップデートしてしまっても良い気がしたが、このJenkinsが場当たり的に管理されてきた経緯もあり、自分自身が全てのJobについて「責任を持って管理できている」と言えるではなかった。そのため、もし問題が発生しても良いようにする方法を考える必要があった。以下のようなものが浮かび、以下のような懸念が浮かんだ。

  • AMIのバックアップを取ってからDockerをバージョンアップして、問題があったらバックアップからリストアする
    • 別の対応でJobを新しく定義などしており、巻き戻すと新たなコストが発生しかねない
  • インスタンスでDockerを起動して、 DOCKER_HOST をそちらに向け変えることでいつでも切り替えられるようにする
    • たしか別ホスト上のDockerにボリュームってマウントできないよね、既存のJobの要件によっては動かない
  • AMIのバックアップ経由でEC2インスタンスを複製し、Jenkins Agentを起動できる環境を用意した上でそちらだけDockerをバージョンアップする
    • これまでのJobがこれまで通りに動くことが期待できる
    • Job単位でmaster/Agentを切り替えることも可能

というわけで新たにJenkins Agentを建てることになった。といってもとても簡単で、masterのJenkinsからAgentの環境にSSHできるようにするだけで良い。一点、ログイン対象のユーザーのログインシェルが指定されていることが必要なので、 jenkins ユーザーを使いまわしたい場合はこれに気をつける必要がある。 $ chsh jenkins -s /bin/bash

その上で、Job実行時のパラメーターとして実行対象のAgentを切り替える対応も行いたい。Pipelineで作成されていればJenkinsfileに手を入れてもらうだけで良いが、そうでない場合についてはJobの設定でどうにかする必要がある。単一のAgentに縛ることは素のJenkinsで既に達成可能だが、切り替えられるようにする場合は以下のプラグインを使用する。

このパラメーターを各Jobに仕込むことで、新しいDockerではJobが失敗してしまった場合に古いDockerが存在するAgentに切り替えて実行する、という対応が可能になる。

あとは経過観察。すべてが新しいDockerでも問題なく動作して「ほら、エイヤで上げてもよかったじゃん」と笑いながら言えるようになることを期待している。


本当はこのあたりの杜撰とも言えるJenkinsの状態を見直したいが、それにしてはあまりにも巨大なので、CasCプラグインなどを使ったコード化が充分に行われているJenkinsの作成を進めている。job-dslやDocker下での管理はまずますうまくいきそうなので、個人的にも期待している。