1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OCI Container Instancesで組むマルチコンテナ構成

1
Posted at

概要

Oracle Cloud Infrastructure(OCI)のContainer Instances は、Kubernetes(OKE)のような複雑なオーケストレーションを必要とせず、サーバーレスで手軽にコンテナを実行できる非常に便利なサービスです。

単一のコンテナを動かすだけであれば非常にシンプルなContainer Instancesですが、実運用を見据えたサーバーを構築しようとすると制約や課題に直面します
例えば

  • 永続ディスクとしてNFS(File Storage)を直接マウントできない
    外部ストレージを直接マウントする機能をサポートいないため代替案を検討する必要がある
  • 標準ログだけでは実運用のモニタリングが不十分
    Container Instancesはコンテナの標準出力をコンソール上に表示・集約してくれますが、長期間のログ保存やログ監視基盤連携するためには外部転送する仕組みが不可欠です。

これらの課題を解決するためのマルチコンテナ構成を検証しました

構成

以下の 3コンテナ構成で環境を構築します

  • メインコンテナ(Appl): 今回は検証用としてNginxを使用します

  • サイドカー1(Rclone):
    Object Storageからデータを取得し、Nginxと共有します

  • サイドカー2(Fluent Bit):
    Nginxが出力したログファイルを外部のSyslogサーバーへ転送します

コンテナ間のファイルやログの受け渡しには、Container Instancesがサポートする一時ボリューム EmptyDir(EMPTY_DIR) を使用します

事前準備

Container Instancesを構築する前の事前準備です

  • Terraform環境のセットアップ
    OCI CLI等別の手段でもContainer Instances作成可能です
  • Object Storageにデータをアップロード
    今回はWebコンテンツをデータとしています

OCI環境準備

Container Instances作成/実行のための環境準備です

  • ネットワーク(VCN/Subnet)の作成
    Container Instancesが起動するネットワーク
  • 動的グループおよびIAMポリシーの作成
    Container InstancesがObject Storageからオブジェクトを取得するためのポリシー
## Replace << >> with the appropriate value

Dynamic-group
container-instance-dynamic-group
ALL {resource.type = 'containerinstance', resource.compartment.id = '<<compartment OCID>>'}

Policy
Allow dynamic-group container-instance-dynamic-group to read objects in compartment <<compartment>> where target.bucket.name = '<<Object Storage Bucket>>'

Terraform環境が導入されたインスタンスからContainer Instancesを起動するためのポリシー

## Replace << >> with the appropriate value

Dynamic-group
instance-dynamic-group
instance.compartment.id = '<<compartment OCID>>'

Policy
Allow dynamic-group instance-dynamic-group to manage compute-container-family in compartment <<compartmentt>>
Allow dynamic-group instance-dynamic-group to use virtual-network-family in compartment <<compartment>>
Allow dynamic-group instance-dynamic-group to read repos in compartment <<compartment>>

Container Instancesの作成

ここが本稼働環境のコアとなる部分です。一時ボリューム EMPTY_DIR を定義し、3つのコンテナを紐付けます。

Container InstancesのTerraform定義が以下です

tf-ci_nginx-rclone-fluentbit.tf
## Replace << >> with the appropriate value

terraform {
  required_version = ">= 1.5.0"

  required_providers {
    oci = {
      source  = "oracle/oci"
      version = "~> 8.0"
    }
  }
}

provider "oci" {
  auth = "InstancePrincipal"
  region = var.region
}

variable "region" {
  description = "OCI region used by the provider."
  type        = string
  default     = "ap-tokyo-1"
}

variable "compartment_id" {
  description = "Compartment OCID for the container instance."
  type        = string
  default     = "<<Compartment OCID>>"
}

variable "subnet_id" {
  description = "Subnet OCID for the container instance VNIC."
  type        = string
  default     = "<<Subnet OCID>>"
}

resource "oci_container_instances_container_instance" "nginx_rclone_fluentbit" {
  compartment_id      = var.compartment_id
  display_name        = "nginx-rclone-fluentbit"
  availability_domain = "<<Availability_domain>>"
  fault_domain        = "FAULT-DOMAIN-1"
  shape               = "CI.Standard.E4.Flex"

  shape_config {
    ocpus         = 1
    memory_in_gbs = 1
  }

  vnics {
    subnet_id            = var.subnet_id
    private_ip           = "<<Private IP address>>"
    is_public_ip_assigned = false
  }

  containers {
    display_name = "nginx"
    image_url    = "docker.io/library/nginx:stable-alpine"
    command      = ["/bin/sh", "-c"]
    arguments = [
      "rm -f /var/log/nginx/access.log && touch /var/log/nginx/access.log; nginx -g 'daemon off;'"
    ]

    environment_variables = {
      MY_POD_NAME = "container-instance-01"
    }

    volume_mounts {
      volume_name = "shared-html"
      mount_path  = "/usr/share/nginx/html"
    }

    volume_mounts {
      volume_name = "shared-logs"
      mount_path  = "/var/log/nginx"
    }
  }

  containers {
    display_name = "rclone"
    image_url    = "docker.io/rclone/rclone:latest"
    command      = ["/bin/sh", "-c"]
    arguments = [
      <<-EOT
      echo '--- START RCLONE COPY---' && mkdir -p /config/rclone && echo -e "[oci]
      type = oracleobjectstorage
      provider = resource_principal_auth
      namespace = <<Namespace>>
      compartment = <<Compartment OCID>>
      region = ap-tokyo-1" > /config/rclone/rclone.conf && rclone copy oci:<<Bucket name>>/index.html /data && echo '---END RCLONE COPY ---'
      EOT
    ]

    volume_mounts {
      volume_name = "shared-html"
      mount_path  = "/data"
    }
  }

  containers {
    display_name = "fluent-bit"
    image_url    = "docker.io/fluent/fluent-bit:3.2"

    environment_variables = {
      MY_POD_NAME = "container-instance-01"
    }

    volume_mounts {
      volume_name = "shared-logs"
      mount_path  = "/var/log/nginx"
    }

    volume_mounts {
      volume_name = "fluent-bit-config-volume"
      mount_path  = "/fluent-bit/etc"
    }
  }

  volumes {
    name          = "shared-logs"
    volume_type   = "EMPTYDIR"
    backing_store = "EPHEMERAL_STORAGE"
  }

  volumes {
    name          = "shared-html"
    volume_type   = "EMPTYDIR"
    backing_store = "EPHEMERAL_STORAGE"
  }

  volumes {
    name        = "fluent-bit-config-volume"
    volume_type = "CONFIGFILE"

    configs {
      file_name = "fluent-bit.conf"
      data      = base64encode(file("${path.module}/fluent-bit.conf"))
    }
  }
}

output "container_instance_id" {
  description = "OCID of the OCI container instance."
  value       = oci_container_instances_container_instance.nginx_rclone_fluentbit.id
}

Fluent Bitの構成ファイルは以下のとおりです

fluent-bit.conf
## Replace << >> with the appropriate value

[SERVICE]
    Flush        1
    Daemon       Off
    Log_Level    info

[INPUT]
    Name         tail
    Path         /var/log/nginx/access.log
    Tag         nginx.access
    Parser       none
[FILTER]
    Name         modify
    Match        *
    Add          pod_name ${MY_POD_NAME}
[OUTPUT]
    Name                    syslog
    Match                   *
    Host                    <<Syslog server IP address>>
    Port                    514
    Mode                    udp
    syslog_format           rfc3164
    syslog_message_key      log
    syslog_facility_preset  1
    syslog_severity_preset  6
    syslog_hostname_key     pod_name
    syslog_appname_preset   nginx-pod

ファイルが準備できたらTerraformを実行します

$ terraform init
Initializing the backend...
Initializing provider plugins...
:

$ terraform plan -out=tfplan

Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
  + create
:

$ terraform apply "tfplan"
oci_container_instances_container_instance.nginx_rclone_fluentbit: Creating...
oci_container_instances_container_instance.nginx_rclone_fluentbit: Still creating... [10s elapsed]
oci_container_instances_container_instance.nginx_rclone_fluentbit: Still creating... [20s elapsed]
oci_container_instances_container_instance.nginx_rclone_fluentbit: Still creating... [30s elapsed]
oci_container_instances_container_instance.nginx_rclone_fluentbit: Still creating... [40s elapsed]
oci_container_instances_container_instance.nginx_rclone_fluentbit: Creation complete after 49s [id=ocid1.computecontainerinstance.***]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:

container_instance_id = "ocid1.computecontainerinstance.***"

動作確認

  • Nginxへのアクセス確認
    Object Storageにアップロードしたデータを表示することができました
  • Syslogサーバーへのログ転送確認
    NginxのログがSyslogサーバーに転送されています
[2026-07-12T22:11:14.632833+09:00] <14>Jul 12 13:11:13 container-instance-01 nginx-pod: 10.**.**.** - - [12/Jul/2026:13:11:13 +0000] "GET /index.html HTTP/1.1" 200 5349 "-" "****" "-"
[2026-07-12T22:11:14.632833+09:00] <14>Jul 12 13:11:14 container-instance-01 nginx-pod: 10.**.**.** - - [12/Jul/2026:13:11:14 +0000] "GET /favicon.ico HTTP/1.1" 404 555 "http://****" "****" "-"

まとめ

OCI Container Instancesの「外部ストレージ直接マウント不可」および「標準ログ機能の不足」という実運用上の制約を、一時共有ボリューム(EMPTY_DIR)と2つのサイドカーコンテナ(Rclone/Fluent Bit)を組み合わせることで、Kubernetesなどの複雑な基盤を使うことなくシンプルに解決できることを検証しました

その他参考リンク

Fluent Bit Official Manual - Outputs
https://docs.fluentbit.io/manual/data-pipeline/outputs

OCIロギングとGrafanaを使用したHPC/GPUクラスタのログ監視方法
https://oracle-japan.github.io/ocitutorials/hpc/tech-knowhow/log-monitoring/

rclone
https://hub.docker.com/r/rclone/rclone

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?