Terraform 管理下の Code Engine でプライベートレジストリのイメージを使う
はじめに
Code Engine でアプリケーションを動かす際に、何も考えずにプライベートレジストリのコンテナイメージを指定してデプロイしたところ以下のようなエラーになって、ちょっとつまずいたので今後の自分のためにもやったことを書いておく。
ちなみにプライベートレジストリとしては、今回 Container Registry を使用している。
$ terraform apply -var-file=terraform.tfvars -auto-approve
...
(省略)
...
│ Error: Error waiting for resource IbmCodeEngineApp (12345678-8910-xxxx-xxxx-1x1x1x1x1x1x1x/sample-app) to be created: The instance getAppOptions failed: %!s(<nil>)
│ {
│ "StatusCode": 200,
│ "Headers": {
│ "Cache-Control": [
│ "no-cache, no-store"
│ ],
│ "Content-Length": [
│ "1258"
│ ],
│ "Content-Type": [
│ "application/json; charset=UTF-8"
│ ],
│ "Date": [
│ "Mon, 12 Jun 2023 05:54:56 GMT"
│ ],
│ "Etag": [
│ "12345678910"
│ ],
│ "Strict-Transport-Security": [
│ "max-age=31536000; includeSubDomains; preload"
│ ],
│ "X-Content-Type-Options": [
│ "nosniff"
│ ]
│ },
│ "Result": {
│ "created_at": "2023-06-12T05:53:56Z",
(省略)
│
│ with ibm_code_engine_app.main_app,
│ on main.tf line 30, in resource "ibm_code_engine_app" "main_app":
│ 30: resource "ibm_code_engine_app" "main_app" {
HCL ファイルは以下のような感じだった。
resource "ibm_code_engine_secret" "app_secret" {
project_id = var.project_id
name = "${var.project_name}-secret"
format = "generic"
data = {
BASIC_AUTH_NAME = var.basic_auth_name
BASIC_AUTH_PASSWORD = var.basic_auth_password
# omit other variables
}
}
resource "ibm_code_engine_app" "main_app" {
project_id = var.project_id
name = "${var.project_name}-app"
image_reference = var.image
image_port = 3000
managed_domain_mappings = "local_public"
scale_min_instances = 1
run_env_variables {
reference = "${var.project_name}-secret"
type = "secret_full_reference"
}
}
もちろん terraform plan
も問題なく、上記の terraform apply
のログではリソースの作成には成功していそうで、どこでエラーになっているのかぱっと見では分からなかった。
原因
IBM Cloud の Web コンソールを確認すると、すぐに判明した。 Code Engine のアプリケーションの画面を見ると、「リビジョンの準備ができていません」というメッセージが出ていた。
また「構成」タブを見てみると一目で原因に気づけたが、見ての通りプライベートレジストリからのイメージのプルに失敗していた。
プライベートレジストリからのイメージを取得するにはレジストリー・アクセス・シークレットが必要らしい。当然必要になるものを忘れていた。
対処方法
公式のドキュメントを参考にした。
上記リンク先によると、ibm_code_engine_secret
リソースを format registry
、data を username
, password
, server
で作成する。
image_secret - (Optional, String) Optional name of the image registry access secret. The image registry access secret is used to authenticate with a private registry when you download the container image. If the image reference points to a registry that requires authentication, the app will be created but cannot reach the ready status, until this property is provided, too.
また ibm_code_engine_app
リソースについては、作成した ibm_code_engine_secret
のリソース名を image_secret
プロパティに指定するという方法らしい。
上記を踏まえると HCL ファイルは最終的に以下のようになった。
resource "ibm_code_engine_secret" "app_secret" {
project_id = var.project_id
name = "${var.project_name}-secret"
format = "generic"
data = {
BASIC_AUTH_NAME = var.basic_auth_name
BASIC_AUTH_PASSWORD = var.basic_auth_password
# omit other variables
}
}
+ resource "ibm_code_engine_secret" "registry_secret" {
+ project_id = var.project_id
+ name = "${var.project_name}-registry-secret"
+ format = "registry"
+
+ data = {
+ username = var.registry_username
+ password = var.registry_secret
+ server = var.registry_server
+ }
+ }
resource "ibm_code_engine_app" "main_app" {
project_id = var.project_id
name = "${var.project_name}-app"
image_reference = var.image
+ image_secret = "${var.project_name}-registry-secret"
image_port = 3000
managed_domain_mappings = "local_public"
scale_min_instances = 1
run_env_variables {
reference = "${var.project_name}-secret"
type = "secret_full_reference"
}
}
variable "project_name" {}
# 省略
+ variable "registry_username" {
+ type = string
+ default = "iamapikey"
+ description = "The username of registry secret"
+ }
+
+ variable "registry_secret" {
+ type = string
+ description = "The secret value of registry secret"
+ }
+
+ variable "registry_server" {
+ type = string
+ default = "jp.icr.io"
+ description = "The server of registry secret"
+}
registry_secret
は、IBM Cloud の Web コンソールなどから API key を発行し、それを使えば良い。今回は、Container Registry 上にあるイメージを指定するため、それに合わせてデフォルト値を指定している。
まとめ
プライベートレジストリにあるコンテナイメージを指定してデプロイする際は、レジストリ・アクセス・シークレットを指定する必要があることが分かり、Terraform の公式ドキュメントを確認するとすぐに解決できた!
terraform plan
で検知できず、terraform apply
でもそれっぽい原因となるエラーメッセージが表示されずでハマりかけたので、もし同じ現象に出くわした人の参考になればと思う。