NRIネットコム Blog

NRIネットコム社員が様々な視点で、日々の気づきやナレッジを発信するメディアです

設計書がないJenkinsを別サーバへ移行する

本記事は  マイグレーションウィーク  2日目の記事です。
💻🖥  1日目  ▶▶ 本記事 ▶▶  3日目  🖥💻

はじめに

ドーモ、ウキタです。 皆さん、Jenkins使っていますか? 今回は、EC2を使っている上で避けては通れないOSのEOLによるJenkins移行の話しをしていきます。

移行した背景

CI/CDを実現するのにEC2(CentOS 7)でJenkinsを利用しています。 CentOS 7のサポート終了(2024年6月30日)*1に伴い、CentOS 7でのJenkinsの実行が2023年11月16日にサポートされなくなりました。 そのため、CentOS 7で動いていたJenkinsを別サーバへ移行しました。

After Nov 16, 2023, the Jenkins project will no longer support running Jenkins on Red Hat Enterprise Linux 7 or any of its derivatives.

引用)https://www.jenkins.io/blog/2023/05/30/operating-system-end-of-life/

事前調査

現行構成の把握

ALB + EC2のシンプルな構成で、EC2が1台のみ起動しています。 ACMで発行された証明書をALBに設定しており、特定の開発者のみがアクセスできるようにALBのセキュリティグループでアクセス制御をしています。

開発者がhttps:// hogehogeを叩くと、ALBを経由しEC2にあるJenkinsへアクセスします。

現行の構成

現行設定の確認

2017年頃ChefでJenkinsサーバーが構築されて以来、ほとんどコードによる管理がされていませんでした。 また、Jenkinsに関する資料も存在しなかったので、EC2へログインし地道に内容を確認していきます。

OS周り

一般的にLinuxに設定するであろう項目を確認します。

確認項目 コマンド
ホスト名 hostname
ユーザ cat /etc/passwd
グループ cat /etc/group
SELinux getenforce もしくは sestatus
タイムゾーン timedatectl
ロケーション、キーボードキーレイアウト localectl status
bashrcやbash_profileを確認 cat /etc/bashrc
cat /etc/profile
cat /path/to/.bashrc
cat /path/to/.bash_profile
サービス周り

使っているサービスを洗い出します。 ChefのコードやJenkinsジョブで叩かれているコマンド、cloud-initの設定ファイルの確認を忘れないようにしましょう。

確認項目 コマンド
インストールされたパッケージ yum list installed
稼働しているサービス systemctl list-units --type=service
自動起動するサービス systemctl list-unit-files -t service | grep enabled
稼働しているプロセス ps axf
Jenkinsや監視・運用で使っているパッケージのconfを確認 cat /path/to/xxx.conf

Jenkinsデータの移行方法を調査

Jenkinsジョブやプラグイン、クレデンシャルをどのように移行するか迷っていましたが、別プロジェクトでJenkinsのホームディレクトリを丸々コピーしてデータを移行していたので、同じ方法を採用しました。

移行先OSの調査

Red Hat Enterprise LinuxのABI(Application Binay Interface)互換を目指すAlmaLinux*2やRocky Linux*3, AWSが提供しているAmazon Linux 2023*4が移行先の主な候補でした。 AlmaLinuxとRocky Linuxは、他プロジェクトでの利用経験がないため候補から除外しました。 最終的に、Amazon Linuxの方がAWSの継続的なサポートを見込めるということで、Amazon Linux 2023を移行先に選びました。

AlmaLinuxやRocky Linuxだと移行ツールあるのになぁ

CentOS 7とAmazon Linux 2023の比較
CentOS 7 Amazon Linux 2023
ベースOS Red Hat Enterprise Linux Fedora
サポート期限 2024年6月30日 2028年3月15日
デフォルトユーザ centos ec2-user
パッケージ管理ツール yum dnf
SELinux Enforcing(移行元ではDisabledモードを使用) Permissive*5
ロギング journald(移行元ではrsyslogを使用) journald
スケジューリング systemd timer(移行元ではcronを使用) systemd timer

移行元のCentOS 7ではrsyslogを使っていましたが、ログを転送する要件がないことやログのサイズが小さいこと、頻繁にログを確認しないことからjournaldを採用しました。 journaldのログはデフォルトで揮発しますが、/var/log/journalディレクトリが存在する場合、ログは永続化します。 ログのサイズはデフォルトでファイルシステム容量の10%(4GBが上限)に制限され、これを超えると古いログが削除されるので注意が必要です。 Amazon Linux 2023ではjournalディレクトリが存在する*6ので、ログは永続化されます。

また、Amazon Linux 2023では、リポジトリバージョンによりパッケージが特定のバージョンに固定されています。 そのため、今までのようにdnf updateを叩いてもインストール済みパッケージをアップデートすることはできません。 アップデートしたい場合は、dnf upgrade --releasever=<リポジトリバージョン>を叩きます。

最後に、Amazon Linux は、柔軟で一貫性のある更新メカニズムである、バージョニングされたリポジトリを通じた決定論的更新を提供します。これは、断然私のお気に入りのポリシーです。ディストリビューションは Amazon Linux パッケージリポジトリの特定のバージョンにロックされるため、更新を適用する方法とタイミングを制御できます。

引用)https://aws.amazon.com/jp/blogs/news/amazon-linux-2023-a-cloud-optimized-linux-distribution-with-long-term-support/

方針

データ移行

今回はJenkinsのデータを別サーバへ移行したかっただけなので、ドメインやALBは既存のものを流用します。 移行前後で整合性を保つため、Jenkinsを停止してデータを移行します。

また、移行後に動作確認をするため、EC2(Amazon Linux 2023)用のリスナーとターゲットグループを作成しEC2(Amazon Linux 2023)を登録します。 ALBにアタッチしたセキュリティグループのインバウンドルールでHTTPS:8080を開放し、EC2(Amazon Linux 2023)側のJenkinsへアクセスできるようにします。

データ移行

切り替え

切り替え時にサービス停止しても問題ないので、ターゲットグループのインスタンス登録と解除で切り替えを行います。

EC2へのログイン

今まで踏み台サーバを経由してCentOS 7へログインしていましたが、運用・管理コストがかかっていたので踏み台を廃止して、代わりにSSM Session Managerによるログインへ変更しました。 厳密にはSSM Session Managerはログインしているわけではないのと、デフォルトのシェルはbashではなくshなので、bashrcやbash_profileは読み込まれません。 bashrcやbash_profileで設定した内容が必要な場合は、AWSマネージメントコンソールのセッションマネージャーにあるLinux shell profileに設定を移しましょう。 また、ログインユーザはec2-userではなくssm-userです。

踏み台サーバを廃止

設定を反映

さて、ここから設定をしていきます。

EC2(Amazon Linux 2023)を作成

VPCやサブネット・インスタンスタイプ・IAMロール・キーペアなどEC2(CentOS 7)と同じように設定していき、EC2(Amazon Linux 2023)を作成します。 EC2(CentOS 7)のときはEBSのストレージが暗号化されていなかったので、EC2(Amazon Linux 2023)ではKMSでEBSを暗号化します。

また、SSM Session Managerによるログインをしたいので、EC2(Amazon Linux 2023)にアタッチしたIAMロールにカスタムインラインポリシーを作成します。

以下のドキュメントを参考に作成します。 docs.aws.amazon.com

docs.aws.amazon.com

ポリシーの例)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Action": "ssm:StartSession",
            "Resource": "arn:aws:ec2:<リージョン>:<アカウントID>:instance/*"
        },
        {
            "Sid": "",
            "Effect": "Allow",
            "Action": [
                "ssm:GetConnectionStatus",
                "ssm:DescribeSessions",
                "ssm:DescribeInstanceProperties",
                "ec2:DescribeInstances"
            ],
            "Resource": "*"
        },
        {
            "Sid": "",
            "Effect": "Allow",
            "Action": [
                "ssm:TerminateSession",
                "ssm:ResumeSession"
            ],
            "Resource": "arn:aws:ssm:*:*:session/${aws:userid}-*"
        }
    ]
}

OSの設定を行う

EC2(Amazon Linux 2023)へログインし、ホスト名の変更とSELinuxを無効化します。

aws ssm start-session --target i-xxxx
hostnamectl set-hostname <ホスト名>
grubby --update-kernel ALL --args selinux=0
reboot

パッケージをインストール

Jenkinsとその実行に必要なJavaをインストールします。 OSとJenkinsバージョンの変更を同時に行うと問題があったときの切り分けが大変なので、今回はEC2(CentOS 7)と同じJenkinsとJavaのバージョンをインストールしています。 Jenkinsでコンテナイメージのビルドを行うジョブがあるのでdockerとdocker composeをインストールし、jenkinsユーザとssm-userユーザがdockerコマンドを叩けるようにします。 他にも色々とインストールしていますが割愛します。

dnf install java-11-amazon-corretto

// dnfによるJenkinsのインストールも可能だがバージョン管理をしたかったため、以下の方法でインストール
// 必要に応じて設定ファイルを更新する
rpm -ivh https://get.jenkins.io/redhat-stable/jenkins-2.414.1-1.1.noarch.rpm
vim /etc/sysconfig/jenkins
systemctl enable jenkins

dnf install -y docker
usermod -aG docker jenkins
usermod -aG docker ssm-user
systemctl enable docker
mkdir -p /usr/local/lib/docker/cli-plugins
curl -SL https://github.com/docker/compose/releases/download/v2.4.1/docker-compose-linux-x86_64 -o /usr/local/lib/docker/cli-plugins/docker-compose
chmod +x /usr/local/lib/docker/cli-plugins/docker-compose

データ移行

Jenkinsのデータ移行

EC2(Amazon Linux 2023)側の設定が終わったら、EC2(CentOS 7)のJenkinsを停止しデータを移行します。 操作ミスをしても元へ戻せるようにするため、EC2(CentOS 7)のバックアップを取得します。 また、EC2(Amazon Linux 2023)を作成するときに用意したキーペアの秘密鍵をCentOS 7側にコピーします。 必要に応じて秘密鍵の権限を設定してください。

◾️ CentOS 7側での作業
Jenkinsのワークスペースが13GB(デカイ)もあり、移行後に必要ないので削除しました。 今思えば、tarのexcludeオプションを使えばディレクトリを除外できるので、削除しなくてもよかったです。

// ログイン
ssh <IPアドレス>

// Jenkinsを停止させる
systemctl stop jenkins

// 移行しても使わないため、Jenkinsのワークスペースより下を全て削除する
cd /var/lib/jenkins
rm -rf workspace/*

// データを圧縮する
tar -zcvf /home/centos/jenkins.tar.gz .

// データを転送する
scp -i /home/centos/.ssh/xxxx.pem /home/centos/jenkins.tar.gz ssm-user@<EC2(Amazon Linux 2023)のプライベートIPアドレス>:/home/ssm-user

◾️ Amazon Linux 2023側での作業

// ログイン
aws ssm start-session --target i-xxxx

// Jenkinsが起動している場合、停止させる
systemctl stop jenkins

// データ解凍
cd /home/ssm-user
tar xzvf jenkins.tar.gz -C /var/lib/jenkins/

// Jenkins起動
systemctl start jenkins

動作確認

HTTPS:8080でJenkinsのGUIへアクセスし、ログインできるか、ジョブやプラグインが存在するかなどを確認します。 その後、Jenkinsジョブを一通り流して動作確認を行い、エラーが出たら修正します。

動作確認(検証)

CentOS 7からAmazon Linux 2023へ切り替える

EC2(CentOS 7)側のターゲットグループから、EC2(CentOS 7)の登録解除とEC2(Amazon Linux 2023)のインスタンス登録を行います。 ネットワークの経路が変わったので念のため、Jenkinsへログインできるかを確認し簡易なジョブをいくつか流します。 特に問題なければ、切り替え完了です。

切り替え

後片付け

安定して稼働していることを確認し、不要になったリスナーやターゲットグループ・セキュリティグループのHTTPS:8080・キーペア・EC2(CentOS 7)を削除します。

後片付け後の構成

おわりに

設計書がない状態でJenkinsをCentOS 7からAmazon Linux 2023へ移行しました。 今回は、1からOSの設定やconfの設定を確認していくのが一番大変でした。 こうならないように皆さんはドキュメントを作成しましょう。 とはいえ、久しぶりにLinuxの設定を手動で行い、インフラやってる感があり懐かしかったです。

踏み台廃止については、コストが掛からなくなったことに加え、セキュリティグループのインバウンドにSSHを解放しなくて良くなったためセキュリティが向上しました。 個人的には、AWSマネージメントコンソールから気軽にログインできるようになったことが嬉しかったです。

執筆者: 浮田 博揮 クラウドエンジニア