【TECH BLOG #62】Jenkins運用での工夫について

こんにちは
グリーエンターテインメント株式会社のエンジニアマネージャーのYSです。
今回は、私が担当しているタイトルのJenkinsの構成について紹介させていただきます。
Jenkinsについて
まず、運用しているJenkinsについては、GCPのGKE上で動作しています。
ミドルウェアのアップデート作業等を実施する際に、ゲーム本体のAPIに影響を出したくないために、ゲーム本体のAPIが動作しているクラスタとは別のクラスタ上に構築しています。構築自体はhelmfileで実施しています。
プラグイン
Jenkinを運用している際に、一番問題になりそうなのがプラグインのバージョン問題かと思います。何かの拍子でJenkinsが再起動かかった際に意図せずプラグインのバージョンが上がってしまい、依存性の問題で起動しなくなってしまう事があると思います。
そのため、使用したいプラグインをインストールして正常に動作したタイミングで下記のコマンドをJenkinsの管理画面から実行して、インストールしているプラグインのバージョン一覧を取得しておき、helmfileに記載しておいています。
p-> println (“\”${p.getLongName()}\”:${p.getShortName()}:${p.getVersion()}”)
}
# helmfile抜粋
– apache-httpcomponents-client-4-api:4.5.14-208.v438351942757
– authentication-tokens:1.53.v1c90fd9191a_b_
– bootstrap5-api:5.3.2-2
– bouncycastle-api:2.29
….
認証
Jenkinsの認証にはGithubでの認証を採用しています。そのために「Github Authentication plugin」を使用しています。弊社はすべての職種のメンバーがgitを使用しており、基本的に職種毎(PL/DE/EN)にteamを作って運用しているので、Github認証を利用することで一元管理しています。使用するためにGithubのOAuthAppを作成しておき、設定値をhelmfileに記載しています。
# helmfile抜粋securityRealm: |-
github:
githubWebUri: “https://github.com”
githubApiUri: “https://api.github.com”
clientID: {Githubで作成したOAuthAppのclientID}
clientSecret: {Githubで作成したOAuthAppのclientSecret}
oauthScopes: “read:org,user:email”
authorizationStrategy: |-
globalMatrix:
permissions:
– “GROUP:Overall/Administer:{Githubのorg名}*{Githubのteam名}”
….
Jobの管理
各種Jobはパイプラインの形式となっており、groovyスクリプトで記載しています。
基本的には、1Job / 1スクリプトで管理していて、Jenkinsの各Jobの設定画面でスクリプトを指定しています。

共通処理
groovyスクリプトで使用する共通の処理は、各Jobのスクリプトのリポジトリとは別のリポジトリ(libraryリポジトリ)で管理しています。そして、このlibraryリポジトリをJenkins全体の「Global Pipeline Libraries」として読み込んでいます。libraryリポジトリは他のタイトルでも利用できるように、固有の定義等(config.json)はタイトル側のスクリプトのリポジトリから参照させるようになっています。

スケジューリングされたJob
例えば、毎日1時にJob-A → Job-B → Job-Cと順番で実行させていきたいということはあると思います。
このような処理においては、毎日1時に実行されるJobを定義しておき、このJobで順次実行したいJob達を上述のconfig.jsonに定義しています。
{
“name” : “Pipeline_Web_Image_Deploy”,
“params” : [
{“name” : “namespace”, “type” : “string”, “value” : “dev1”},
{“name” : “web_branch”, “type” : “string”, “value” : “develop”},
{“name” : “k8s_branch”, “type” : “string”, “value” : “main”},
{“name” : “role”, “type” : “string”, “value” : “app”},
{“name” : “all_role”, “type” : “booleanParam”, “value” : true},
{“name” : “composer_install”, “type” : “booleanParam”, “value” : false}
]
},
{
“name” : “Server_Unittest_Exec”,
“params” : [
{“name” : “namespace”, “type” : “string”, “value” : “dev1”},
{“name” : “role”, “type” : “string”, “value” : “admin”}
]
}
….
]
そして、Jobの中でこの設定を読み込み各Jobを順次実行させています。
# Job-Scriptsteps {
script {
// 上述のconfig.jsonの「nightly_jobs」の値
nightlyJobs.each { job ->
build(
job: job.name,
parameters: job.params.collect { “${it.type}”(name: it.name, value: it.value) },
propagate: false,
wait: true
)
}
}
}
}
Jobの順次実行であれば、各Job内で後続処理として設定してもいいかもしれませんが、各Jobの再利用性を考えると、設定ファイルで定義できるようにしておくのがいいと思います。
これからの展望
グリーエンターテインメント株式会社は、過去は運営移管が主だったためJenkinsについても、移管元の構成をそのまま引き継ぐことが基本でした。しかし、現在は新規開発に注力しているので、ゲームエンジンだけではなく、Jenkins等の周辺ツールにおいても、今までの経験を活かして自分たちで構築していっています。
本日紹介した構成は、まだ1つのタイトルでしか運用されていませんが、運用しつつナレッジをため、今後のタイトルでも活用できるようにどんどん改善していきたいと考えています。
最後まで読んでいただきありがとうございました。
本件に関するお問い合わせ先
グリーエンターテインメント株式会社 広報担当
東京都港区六本木6-11-1 六本木ヒルズゲートタワー
E-mail:info-ent@ml.gree.net