[Oracle Cloud] Object Storage のリージョン間自動コピーを、Oracle Functions で実現

# はじめに

Oracle Cloud Infrastructure(以下OCI) のオブジェクトストレージは、リージョン内に配置されたサービスです。
世界規模の可用性や、世界各地からのダウンロード速度を上げたい場合、複数のリージョンへオブジェクトを配置したいユースケースが考えられます。

現時点で、OCI には手動で複数リージョン間をまたいでコピーする機能はありますが、自動的にコピーをしてくれる機能ではありません。Oracle Functions と Events を活用して自動コピー機能を実現することができます。

今回の記事では、[GitHub](https://github.com/Sugi275/oci-objectstorage-multiregioner/blob/master/func.go) に上げているサンプルコードを使用して、使用する方法を紹介していきます。

**※ サンプルコードなので、エラーハンドリングが考慮されていない箇所があります。**
**本番利用の際は、アルゴリズムの見直しや、指定したリージョンでコピーがされていない状況の検知を考慮する必要があります。ご留意ください。**



# 概要図

![1566998416732.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/8d029c92-455a-97a3-b3b9-395736623623.png)



# Object Storage の設定

まずは、Object Storage の Bucket を、使用したいリージョンで作成をします。
サンプルコードの仕様上、全て同じ名前である必要があるため、`multi_region` という名前で作成します。

この記事の 手順例 では、以下の 3 リージョンを 対象にしています

- 東京 (ap-tokyo-1)
- アッシュバーン (us-ashburn-1)
- フェニックス (us-phenix-1)



コピー先のリージョンは、自由に変更可能なので、好きなリージョンで作成頂いて構いません。



# Function の 設定

## Function Deploy

まず、Functions を動かす準備が出来ていない場合は、以下の Document や Quick Start Guide を参考にして、事前準備をします。
Preparing for Oracle Functions
https://docs.cloud.oracle.com/iaas/Content/Functions/Concepts/functionsprerequisites.htm

Quick Start Guide
https://www.oracle.com/webfolder/technetwork/tutorials/infographics/oci_faas_gettingstarted_quickview/functions_quickview_top/functions_quickview/index.html

Functions を動かす準備が出来たら、GitHub から Sample コードをclone します

```
# 作業用ディレクトリ作成
mkdir ~/fnwork/
cd ~/fnwork/

# GitHub から clone
git clone https://github.com/Sugi275/oci-objectstorage-multiregioner.git
```



Sample コードの中で実行している概要は、以下の通りです

- `generateAction` 関数で、Events から受け取ったパラメータと環境変数をもとに、Object Storage のコピー機能のパラメータを 構造体(struct)として生成します
- Object Storage に格納されたファイルが新規作成(create) と 更新(update) の場合には、tokyo region から、他のリージョンにコピー。他のリージョンでファイルが存在している場合は上書き
- ファイルが削除(delete) された場合は、他リージョンのファイルを削除



clone したディレクトリへ移動します

```
cd ~/fnwork/oci-objectstorage-multiregioner/
```



go.mod を作成します

```
echo "module func" > go.mod
```



Functions へ multiregioner の function を Deploy します。`--app` に渡すアプリケーション名は環境によって書き換えてください

```
fn --verbose deploy --app susugiya
```



次に、Deploy した Functions の OCID をコピーします。
OCI コンソールのメニューから、Developer Services > Functions を選択します。
私の環境で、事前に作成していた Application の名前を選択します。

![1567002098720.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/9b1d7493-d079-b385-f9ef-c24d9b53126f.png)



`objectstorage_multiregioner` の OCID を Copy します

例 : `ocid1.fnfunc.oc1.ap-tokyo-1.aaaaaaaaacbqyf6ps7uxmpz3tevmvkmvbbsqqcgkf3xk62zvjryb4hhgo36a`

![1567002144071.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/599d84fe-3293-f94c-3c18-90e39502bebe.png)



## Function の 環境変数設定

Functions に環境変数を設定します。3種類の環境変数が必要です。

- OCI_BUCKETNAME : Object Storage のバケット名を指定します。今回の例では、`multi_region` としています。
- OCI_SOURCE_REGION : Object Storage のコピー元のリージョン名を指定します。今回の例では、`ap-tokyo-1` としています
- OCI_DESTINATION_REGIONS : Object Storage のコピー先のリージョン名を指定します。複数存在する場合は、カンマで区切りで指定すればOKです。今回の例では、`us-ashburn-1,us-phoenix-1` としています。

```
fn config func susugiya objectstorage_multiregioner OCI_BUCKETNAME "multi_region"
fn config func susugiya objectstorage_multiregioner OCI_SOURCE_REGION "ap-tokyo-1"
fn config func susugiya objectstorage_multiregioner OCI_DESTINATION_REGIONS "us-ashburn-1,us-phoenix-1"
```





## Function の logging

Functions では、logging として現段階は2種類の方式がサポートされています

- Object Storage へ出力
- syslog



開発環境としては、syslog を使用するのが楽で良いです。Object Storage の場合は、出力されるのに約15分ほど待つ必要があるため、すばやい log 確認が出来ません。syslog の場合はすぐに確認できるのでお勧めです。

syslog を受け取るために syslog サーバを用意してもよいのですが、開発する時には 無償で使用可能な SaaS の [Papertrail](https://papertrailapp.com/) が簡単でお勧めです。

Papertrail の設定方法は、[こちら](https://qiita.com/sugimount/items/590796840338170f62d8) の記事を参考にしてください。
なお、OCI コンソール上から Papertrail の送付先を設定・確認することが可能です。

Edit Application を選択
![1567003485810.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/5d63a0a8-8849-b7ee-05d8-ab14e9543668.png)



logging 先を設定変更

![1567003522717.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/3f750c14-3560-19f1-41aa-b4093733135d.png)





# Dynamic Group

次に、Function 内で OCI SDK を使用するための権限を付与するために、Resource Principle を使用するための設定を行います。Resource Principle 自体の説明は [こちら](https://qiita.com/sugimount/items/db84122d787af7208eb5) を参照してください

OCI のメニューから、Identity > Dynamic Groups へ移動し、 Create Dynamic Group を押します
以下のパラメータを入力し、Create を押します

- NAME : susugiya_objectstorage_multiregional_group
- DESCRIPTIN : susugiya_objectstorage_multiregional_group

Rule に以下の文字列を入力します。`resource.id` の部分は、作成した Function の OCID を指定します。

```
ALL {resource.type = 'fnfunc', resource.id = 'ocid1.fnfunc.oc1.ap-tokyo-1.aaaaaaaaacbqyf6ps7uxmpz3tevmvkmvbbsqqcgkf3xk62zvjryb4hhgo36a'}
```



![1566991397719.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/0f336efa-0b14-ee60-f1d2-ec68f4be4f73.png)



# Policy

2種類の Policy を設定する必要があります

- リソースプリンシパル用
- Object Storage のリージョン間コピー機能用



## リソースプリンシパル用

Identity > Policies へ移動し、 Create Policy を押します
以下のパラメータを入力し、Create を押します

- NAME : objectstorage_multiregional_policy
- DESCRIPTION : objectstorage_multiregional_policy
- STATEMENT : 以下の文字列で指定します。 Dynamic Group で作成した名前を指定して、`object-family`(Object Storage サービス) を `manage`(全操作可能) な権限を付与しています

```
Allow dynamic-group susugiya_objectstorage_multiregional_group to manage object-family in compartment susugiya
```



画面例

![1567002392168.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/2ac70123-021f-ffba-fcba-836385672019.png)



## Object Storage のリージョン間コピー機能用

Create Policy を押します
以下のパラメータを入力し、Create を押します

- NAME : objectstorage_multiregional_policy
- DESCRIPTION : objectstorage_multiregional_policy
- STATEMENT : 以下の文字列で指定。使用したいリージョン分を全て指定します。リージョン名は、OCI コンソール上で確認可能です

```
Allow service objectstorage-us-ashburn-1 to manage object-family in tenancy
Allow service objectstorage-ap-tokyo-1 to manage object-family in tenancy
Allow service objectstorage-us-phoenix-1 to manage object-family in tenancy
```



参考 Document : https://docs.cloud.oracle.com/iaas/Content/Object/Tasks/copyingobjects.htm#permissions 

参考 リージョン名

![1567002696298.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/945be18c-a6dd-bf82-c97d-3c58e499cd89.png)





# Events の 設定

次に、Tokyo Region の Object Storage を起点にして Events を動かすために設定を行います。
OCI のメニューから、 Application Integration > Events Service を選択します。

Create Rule を押して、以下のパラメータを指定していきます

- DISPLAY NAME : objectstorage_multiregion
- DESCRIPTION : objectstorage_multiregion
- Events Matching : 下の画像を参考にして設定する
  - EVENT TYPE に Object の Create, Delete, Update の3種類を入力
  - Attribute に、`bucketName` を `multi_region` と手入力することで、特定のバケットに制限
- Actions : Function の 名前を指定

![1566908155243.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/fd1bcfb9-4f92-4bb1-ff45-98f0ffe69b40.png)



# 動作確認

それでは準備完了できたので、さっそく動作確認をしてみます。エラーログや実行時のログは logging 先の Papertrail を確認すると、ほぼリアルタイムにログが表示されるので、これを開きながら動作確認すると良いです。

では、Tokyo Region の Object Storage にある バケット`multi_region`にファイル(Object) を格納します。

Upload Objects を押します

![1567003672939.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/b244e07f-2ffd-c164-1af9-61d049157529.png)



Upload Objects を選択すると、ファイルがアップロードされます

![1567003712157.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/440da56d-e3dc-194a-4842-4962d78e3b77.png)



Work Requests の画面では、Object Storage へのリクエストされたコピー機能の状況が示されています。
Resource Name に、アップロードしたファイル名が表示され、Status が Completed となっています

![1567003845277.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/70c117e7-bb63-d6de-13e7-74294d6487cb.png)



ashburn と phoenix Region でファイルがコピーされていることが確認できます

ashburn

![1567003975338.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/4253daf4-d68e-4a46-035d-4bf854d5ffc7.png)



phoenix 

![1567004008677.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/daf8ecde-dcbf-43ef-3329-2c4f3fc07864.png)



Papertrail では実行時のログが出力されています

![1567004122452.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/a8f4a83d-67e0-c5fc-59a8-9a30bd2d61eb.png)



# 参考URL

https://docs.cloud.oracle.com/iaas/Content/Object/Tasks/copyingobjects.htm