こんにちは!現場で毎日コードと向き合っていると、ふとこんな絶望感を味わったことはありませんか?
- 「夜間バッチで走らせたテスト、あと少しで終わるはずだったのに、最後の最後で外部APIが数秒だけ応答しなくてジョブが丸ごと失敗した……」
- 「デプロイ先のサーバーが一時的な高負荷でフリーズし、Jenkinsのビルドが永遠に終わらなくなって、朝出社したら地獄絵図になっていた……」
分かります。本当に心が折れますよね。
でも、安心してください。Jenkinsの「Declarative Pipeline」が持つ強力なエラーハンドリング機能、具体的には `retry` と `timeout` を正しく使いこなせるようになると、こうしたインフラの気まぐれに泣かされることはもうなくなります。
今回は、これからJenkinsを触る初心者の方にもスッと理解してもらえるよう、ツールの基礎から、現場で即戦力になる堅牢なジョブ設計の極意まで、優しく丁寧にお伝えしていきますね。これをマスターすれば、あなたのパイプラインは見違えるほどタフになりますよ!
—
そもそも、Jenkinsってなにをするツールなの?
一言で言うと、Jenkinsは「あなたの代わりに、面倒くさい作業を24時間文句言わずに完璧にこなしてくれる優秀な自動化ロボット」です。
私たちが書いたプログラムをGitHubなどのリポジトリから自動で引っ張ってきて、テストを動かし、ビルドし、本番サーバーへデプロイする――この一連の流れ(CI/CDパイプライン)を自動化するためのデファクトスタンダードツールがJenkinsです。
最速で始める!Jenkinsのインストールと基礎セットアップ
まずはJenkinsを動かす環境を手に入れましょう。一番手軽で安全なのは、Dockerを使う方法です。以下のコマンドをターミナルに叩いてみてください。
docker run -d \
–name jenkins-master \
-p 8080:8080 -p 50000:50000 \
-v jenkins_home:/var/jenkins_home \
jenkins/jenkins:lts-jdk11
たったこれだけで、あなたのローカル環境にJenkinsが立ち上がります!
1. ブラウザで `http://localhost:8080` にアクセスします。
2. 初回アクセス時に「初期パスワード」を求められます。Dockerのログから取得するか、以下のコマンドでコンテナ内から直接確認しましょう。
docker exec jenkins-master cat /var/jenkins_home/secrets/initialAdminPassword
3. 画面に従って「Install suggested plugins(推奨プラグインのインストール)」を選び、管理者ユーザーを作成すればセットアップは完了です。拍子抜けするほど簡単ですよね。
—
はじめての「HelloWorld」:Pipelineの世界へようこそ
Jenkinsの真骨頂は、コードとしてビルド手順を記述できる「Pipeline」にあります。特に現在の主流である「Declarative Pipeline(宣言的パイプライン)」は、人間にとって読みやすく、メンテナンスがしやすいのが特徴です。
まずは、本当にシンプルな「HelloWorld」を動かしてみましょう。
Jenkinsのダッシュボードから [新規ジョブ作成] > [パイプライン] を選び、以下のスクリプトを「Pipeline」の入力欄に貼り付けて保存し、「ビルド実行」を押してみてください。
pipeline {
agent any // 実行するエージェント(環境)を指定します。どこでもOKという意味です。
stages {
stage(‘Hello’) {
steps {
echo ‘こんにちは!Jenkinsの世界へようこそ!’
}
}
}
}
コンソール出力に「こんにちは!Jenkinsの世界へようこそ!」と表示されましたか?おめでとうございます。これであなたも立派なパイプライン・エンジニアの仲間入りです!
—
ここからが本番!`retry` と `timeout` でジョブを「不死身」にする
さて、基本を押さえたところで、今回のメインテーマである「堅牢なジョブ設計」に進みましょう。
実際の開発現場では、ネットワークは「必ず不安定になるもの」、外部APIは「たまに機嫌を損ねるもの」として設計しなければなりません。ここで登場するのが、`retry` と `timeout` です。
それぞれの役割と使い分けの基準を整理しましょう。
- `retry(回数)`:失敗したら、決めた回数だけ「即座にやり直す」。
- `timeout(時間: 単位)`:指定した時間を過ぎたら、処理を強制的に「打ち切る」。
この2つをどう組み合わせるかが、プロの腕の見せ所です。具体的なコードを見てみましょう。
堅牢なパイプラインの模範解答
pipeline {
agent any
stages {
// 1. 外部APIの呼び出しなど、一時的な瞬断に備えるステージ
stage(‘Deploy to Staging API’) {
steps {
script {
// 【retryの極意】
// ネットワークの瞬断は3回までリトライして救う。
// ただし、無限ループは厳禁なので必ず回数を絞ること。
retry(3) {
echo ‘外部APIサーバーへデプロイリクエストを送信中…’
// ここでエラーが起きても、3回までは自動で再実行されます
sh ‘curl -X POST https://api.example.com/v1/deploy’
}
}
}
}
// 2. 処理の無限フリーズを防ぐステージ
stage(‘Run E2E Tests’) {
steps {
script {
// 【timeoutの極意】
// 通常なら5分で終わるはずのテストが、
// デッドロックやリソース枯渇でハングアップした時を救う。
// 10分(TIME: 10, UNIT: ‘MINUTES’)を超えたら容赦なく殺す。
timeout(time: 10, unit: ‘MINUTES’) {
echo ‘重いE2Eテストを実行中…’
// この処理が10分以内に終わらなければ、Jenkinsが自動でジョブを中断します
sh ‘./run-heavy-tests.sh’
}
}
}
}
}
// 【おまけのベストプラクティス】万が一失敗した時の後始末
post {
failure {
echo ‘唉…残念ながらどこかのステップで力尽きました。Slackに通知を送ります!’
}
}
}
—
先輩エンジニアからの設計アドバイス
このスクリプトを見て、「なるほど、全部のステップに `retry` と `timeout` をつければ完璧だな!」と思った方、ちょっと待ってください。ここに大きな罠があります。
1. 「何でもかんでもリトライ」は罪
データベースへのレコード挿入など、「2回実行するとデータが二重に登録されてしまう(冪等性がない)処理」に対して `retry` を使ってはいけません。リトライして安全なのは、「データの取得」「ヘルスチェック」「べき等性が担保されたAPIリクエスト」などに限られます。
2. タイムアウト値は「通常の2倍」を目安に設定する
普段3分かかるテストに、カツカツの「3分1秒」でタイムアウトを設定すると、サーバーのわずかな負荷の揺らぎで正常なビルドまで落としてしまいます。「通常かかる時間の2倍」を目安に、余裕を持った、かつ無限に待たない絶妙なラインを見極めましょう。
—
まとめ
今回は、Jenkins Pipelineにおけるエラーハンドリングの極意として、`retry` と `timeout` を使った堅牢なジョブ設計について解説しました。
- `retry` でネットワークの機嫌不良(瞬断)を華麗にスルーする。
- `timeout` で無限フリーズの呪縛からパイプラインを守り抜く。
この2つを適切に配置するだけで、あなたの作るCI/CDパイプラインは、夜中に勝手に止まることのない、頼もしい相棒へと進化します。
これをマスターすれば、毎日のデプロイ作業やテスト実行が劇的に安心で楽になりますよ。ぜひ、今日のプロジェクトから取り入れてみてくださいね。応援しています!