ラベル Storage の投稿を表示しています。 すべての投稿を表示
ラベル Storage の投稿を表示しています。 すべての投稿を表示

[Storage] ブロックボリュームの複数インスタンスアタッチ機能を使ったOCI上での共有ストレージの作成/Using the Multiple-Instance Attach Block Volume Feature to Create a Shared File System on Oracle Cloud Infrastructure

原文はこちら

共有ファイルシステムを使いたいというのはとてもよくあるご要望です。共有ファイルシステムは複数アプリケーションが同一のデータにアクセスできるようにしてくれます。また、たとえば複数ユーザーが同時に同一の情報にアクセスする、といったことも可能になります。オンプレミスでは、複数コネクションをサポートするNASやSANデバイスがあれば共有ファイルシステムを使うことができますが、クラウドではどうしたらいいのでしょうか?

iSCSI、NFS、SMBやDRBDといったテクノロジーを用いることで、ブロックデバイスをふたつあるいはそれ以上のクラウドインスタンスで共有することができます。こうしたサービスで複数ユーザーがRead/Writeオペレーションを同時に行うことができるようにするには、Oracle Cluster File System Version 2(OCFS2)やGlusterFSといったクラスターファイルシステムサービスをセットアップする前にいくつか追加の設定をしておくことが必要になります。
Oracle Cloud Infrastructure Block Volumeに新たに追加された複数インスタンスアタッチの共有ボリュームオプションでは、こうした共有サービスのセットアップは必要ありません。このオプションを用いると単一のブロックボリュームを複数のコンピュートインスタンスにアタッチでき、それらのインスタンスから同一のデータに並列でRead/Writeアクセスをできるようになります。
ブロックボリュームをすべてのインスタンスにアタッチしたら、次のステップはクラスターアウェアな(共有)ファイルシステムを使うことです。このポストではOCSF2を新しい複数インスタンスアタッチのオプションで用いる手順を説明していきます。

アーキテクチャ

以下の図で示しているのが、複数インスタンスにアタッチして共有されたRead/Writeのブロックボリュームのアーキテクチャです。
Diagram that shows the architecture for attaching a sharable, read/write block volume to multiple instances.

なんでOCFS2?

OCFS2はクラスター内でストレージのパフォーマンスおよび可用性を向上するために使用することを想定された、汎用用途の共有ディスク・ファイルシステムです。OCFS2はローカルファイルシステム・セマンティクスを提供しているため、ほとんどすべてのアプリケーションで使うことができます。クラスターアウェアなアプリケーションでは、複数クラスターノードからのキャッシュ・コヒーレントなパラレルI/Oを使用してクラスター内のアクティビティを調整することができます。あるいは、あるノードがダウンしたときに、アベイラブル・ファイルシステム機能を使って別のノードにフェイルオーバすることもできます。
OCFS2にはエンタープライズレベルの処理環境でのデプロイメントに適した、多くの機能が備わっています:
  • 順序付けされたWrite-Backデータジャーナルログにより、電源障害やシステムクラッシュなどの障害時にファイルシステムの整合性を保護
  • 512 byteから4KBまでのブロックサイズに対応し、ファイルシステムのクラスターサイズは4KBから1MBに対応。クラスターサイズが4KBのときにサポートされる最大ボリュームサイズは16TB。クラスターサイズが1MBのときには理論上はボリュームサイズは4PBが可能ですが、テストされていません。
  • 非常に大きなファイルの効率的な格納のためのExtent-basedアロケーション
  • 疎なファイル、インラインデータ、未書き込み領域、ホールパンチング、reflink、アロケーション予約といった高性能、高効率なストレージのためのアロケーション最適化のサポート
  • 非常に多数のオブジェクトが格納されていたとしてもディレクトリに効率的にアクセス可能にするためのディレクトリ・インデックシング
  • 破損したinodeとディレクトリを検知するためのメタデータ・チェックサム
  • 通常ファイル、ディレクトリ、シンボリックリンクなどのファイルシステムオブジェクトに数の制限なしにname/valueペアを付与するための拡張アトリビュート
  • トラディショナルなファイルーアクセスパーミッションモデルに加え、POSIX ACLおよびSELinuxへの拡張されたセキュリティサポート
  • ユーザーおよびグループQuotaのサポート
  • 32bitと64bit、リトルエンディアン(x86,x86_64,ia64)とビッグエンディアン(ppc64)アーキテクチャの異種混合ノードから成るクラスターのサポート
  • クラスターノードからの並列アクセスを管理する分散ロックマネージャ(DLM)を備えた容易に設定できるin-kernelのクラスタースタック(O2CB)
  • バッファ、ダイレクト、非同期、スプライスおよびmemory-mapped I/Oのサポート
  • ext3ファイルシステムと同様のパラメータを用いるツールセット

はじめてみよう

前述のアーキテクチャのために、大枠では以下の設定ステップが必要になります:
  1. Oracle Cloud Infrastructure Block Volumeを複数インスタンスにアタッチ
  2. OCFS2/O2CBクラスターノードをセットアップ
  3. OCFS2ファイルシステムとマウントポイントの作成

ポート

設定作業を開始する前に、利用するVirtual Cloud Network(VCN)のセキュリティリストの7777番と3260番のポートを開放しておく必要があります。Oracle Cloud Infrastructureのコンソールで、VCNセキュリティリストを編集して以下のステップのうちいずれかひとつを実行してください。
  • インターナルサブネットCIDR(172.0.0.0/16 - 非パブリックネットワーク)のすべてのプロトコルをオープン:
    Source: 172.0.0.0/16
    IP Protocol: All Protocols
    Allows: all traffic for all ports
  • 必要なポートだけをオープン。7777と3260:
    Source: 172.0.0.0/16
    IP Protocol: TCP
    Source Port Range: All
    Destination Port Range: 7777
    Allows: TCP traffic for ports: 7777
    Source: 172.0.0.0/16
    IP Protocol: TCP
    Source Port Range: All
    Destination Port Range: 3260
    Allows: TCP traffic for ports: 3260
注意:ポート7777と3260はローカルOSファイアウォールでもオープンしておく必要があります。Oracle Linx 7.xでの必要なコマンドは以下の通りです。別のOSを利用している場合はドキュメントを参照して実施してください。
  • sudo firewall-cmd --zone=public --permanent --add-port=7777/tcp
  • sudo firewall-cmd --zone=public --permanent --add-port=3260/tcp
  • sudo firewall-cmd --complete-reload

DNS

さらに、DNSが適切に動作していること、当該コンピュートインスタンスがテナンシーのAvailability Domainをまたいで通信できていることを確認しください。以下は/etc/resolv.conf ファイルの例です。
$ cat /etc/resolv.conf
; generated by /usr/sbin/dhclient-script
search baremetal.oraclevcn.com publicsubnetad1.baremetal.oraclevcn.com publicsubnetad2.baremetal.oraclevcn.com publicsubnetad3.baremetal.oraclevcn.com
nameserver 169.254.169.254
resolv.conf ファイルの中にAvailability Domain DNSエントリすべてが記載されている必要があります。

環境

この環境には以下のコンピュートインスタンスがあります:
RoleInstanceIP AddressOS
OCFS2 Node1node1.publicsubnetad1.baremetal.oraclevcn.com172.0.0.41Oracle Linux 7.x x86_64
OCFS2 Node2node2.publicsubnetad2.baremetal.oraclevcn.com172.0.1.42Oracle Linux 7.x x86_64


OCFS2の構成

Cluster Stackの設定ファイルの作成

  1. 必要なOCFS2パッケージのインストール:
    $ sudo yum install ocfs2-tools-devel ocfs2-tools -y
  2.  o2cb コマンドまたはテキストエディタで設定ファイルを作成します。ここでは以下のコマンドでクラスター定義を作成しましょう。このコマンドは /etc/ocfs2/cluster.conf のクラスター設定ファイルを新たに作成します。
    $ sudo o2cb add-cluster ociocfs2
  3. それぞれのノードについて、以下のコマンドでノードを定義します:
    $ sudo o2cb add-node ociocfs2 node1 --ip 172.0.0.41
    $ sudo o2cb add-node ociocfs2 node2 --ip 172.0.1.42
    注意:ノード名は/etc/sysconfig/networkで設定されるシステムのHOSTNAMEと同一の値である必要があります。また、IPアドレスはクラスター内でのプライベート通信でそのノードが使うものになります。/etc/ocfs2/cluster.confのクラスター設定ファイルをコピーし、クラスター内のそれぞれのノードに配置しましょう。なお、クラスター設定ファイルに行った更新は、クラスタースタックの再起動まで反映されません。
    以下の/etc/ocfs2/cluster.confの設定ファイルでは、2つのノードからなるociocfs2という名前のクラスターを、ローカルハートビート付きで定義しています。このブログポスト内で使っている設定はこれです。
    $ sudo cat /etc/ocfs2/cluster.conf
    cluster:
            heartbeat_mode = local
            node_count = 2
            name = ociocfs2
     
    node:
            number = 0
            cluster = ociocfs2
            ip_port = 7777
            ip_address = 172.0.0.41
            name = node1
     
    node:
            number = 1
            cluster = ociocfs2
            ip_port = 7777
            ip_address = 172.0.1.42
            name = node2

Cluster Stackの設定

  1. クラスターの各ノードで以下のコマンドを実行します。オプションについてはドキュメントに記載があります。
    $ sudo /sbin/o2cb.init configure
    Configuring the O2CB driver.
     
    This will configure the on-boot properties of the O2CB driver.
    The following questions will determine whether the driver is loaded on
    boot. The current values will be shown in brackets ('[]'). Hitting
    <ENTER> without typing an answer will keep that current value. Ctrl-C
    will abort.
     
    Load O2CB driver on boot (y/n) [y]:
    Cluster stack backing O2CB [o2cb]:
    Cluster to start on boot (Enter "none" to clear) [ocfs2]: ociocfs2
    Specify heartbeat dead threshold (>=7) [31]:
    Specify network idle timeout in ms (>=5000) [30000]:
    Specify network keepalive delay in ms (>=1000) [2000]:
    Specify network reconnect delay in ms (>=2000) [2000]:
    Writing O2CB configuration: OK
    checking debugfs...
    Setting cluster stack "o2cb": OK
    Registering O2CB cluster "ociocfs2": OK
    Setting O2CB cluster timeouts : OK
    Starting global heartbeat for cluster "ociocfs2": OK
  2. Cluster Stackの設定を確認するには、/sbin/o2cb.init status コマンドを実行します:
    $ sudo /sbin/o2cb.init status
    Driver for "configfs": Loaded
    Filesystem "configfs": Mounted
    Stack glue driver: Loaded
    Stack plugin "o2cb": Loaded
    Driver for "ocfs2_dlmfs": Loaded
    Filesystem "ocfs2_dlmfs": Mounted
    Checking O2CB cluster "ociocfs2": Online
      Heartbeat dead threshold: 31
      Network idle timeout: 30000
      Network keepalive delay: 2000
      Network reconnect delay: 2000
      Heartbeat mode: Local
    Checking O2CB heartbeat: Active
    Debug file system at /sys/kernel/debug: mounted
    この例では、クラスターはオンラインになっており、ローカルハートビートモードを使用しています。ボリュームが設定されていない場合、O2CBハートビートはActiveではなくNot Activeと表示されます。
  3. o2cbとocfs2のサービスを設定し、ネットワークが有効化されたあとに起動時に開始されるようにしておきます:
    $ sudo systemctl enable o2cb
    $ sudo systemctl enable ocfs2
    これらの設定により、ノードはOCFS2ボリュームをシステム開始時に自動的にマウントできるようになります。

クラスターオペレーション用のカーネルの設定

クラスターの適正なオペレーションのために、以下の表に示すカーネル設定を行っておきます:
Kernel SettingDescription
panic
パニックが何秒間続いたらシステムが自動的に自身をリセットするかを定義する値
値が0の場合、システムは応答をやめ、トラブルシューティングのためにパニックの詳細な情報を収集することができる。これがデフォルトの値である。
自動リセットを有効にするには非ゼロの値をセットする。メモリイメージ(vmcore)が必要な場合には、Kdumpがこのイメージを生成するのに十分な時間を与える。推奨値は30秒だが、大規模なシステムではより長い時間が必要。
panic_on_oopskernel oopsが起きたときにシステムが必ずパニックするようにするかの定義。クラスターオペレーションに必要なカーネルスレッドがクラッシュした場合、システムは自身をリセットする必要がある。でなければ、別のノードにはあるノードが応答が遅い、あるいは応答できないことがわからないかもしれず、クラスターオペレーションが停止してしまう。

  1. 各ノードで以下のコマンドを実行し、panicとpanic-on-oopsに推奨値をセットします:
    $ sudo sysctl kernel.panic=30
    $ sudo sysctl kernel.panic_on_oops=1
  2. /etc/sysctl.conf ファイルに以下のエントリーを追加し、変更を再起動後も永続するようにする:
    # Define panic and panic_on_oops for cluster operation
    kernel.panic=30
    kernel.panic_on_oops=1

Cluster Stackの起動と停止

以下の表にはCluster stackに関するオペレーションを実行するためのコマンドを示しています:
CommandDescription
/sbin/o2cb.init statusCheck the status of the cluster stack.
/sbin/o2cb.init onlineStart the cluster stack.
/sbin/o2cb.init offlineStop the cluster stack.
/sbin/o2cb.init unloadUnload the cluster stack.


ボリュームの作成とマウント

OCFS2ボリュームの作成

 mkfs.ocfs2 コマンドを使用してdevice.mkfs上にOCFS2ボリュームを作成します:
$ sudo mkfs.ocfs2 -L "ocfs2" /dev/sdb
mkfs.ocfs2 1.8.6
Cluster stack: classic o2cb
Label: ocfs2
Features: sparse extended-slotmap backup-super unwritten inline-data strict-journal-super xattr indexed-dirs refcount discontig-bg
Block size: 4096 (12 bits)
Cluster size: 4096 (12 bits)
Volume size: 12455405158400 (3040870400 clusters) (3040870400 blocks)
Cluster groups: 94274 (tail covers 512 clusters, rest cover 32256 clusters)
Extent allocator size: 780140544 (186 groups)
Journal size: 268435456
Node slots: 16
Creating bitmaps: done
Initializing superblock: done
Writing system files: done
Writing superblock: done
Writing backup superblock: 6 block(s)
Formatting Journals: done
Growing extent allocator: done
Formatting slot map: done
Formatting quota files: done
Writing lost+found: done
mkfs.ocfs2 successful

OCFS2ボリュームのマウント

  1. 以下の例で示されているように、システムが起動時にネットワーキングが開始されてからOCFS2をマントできるように、また、ネットワーキングが停止した際にはアンマウントするように、/etc/fstab内にnetdevオプションを指定してください。
    $ sudo mkdir /ocfs2
    $ sudo vi /etc/fstab
    #include the below line to mount your ocfs2 after a restart
    /dev/sdb /ocfs2 ocfs2     _netdev,defaults   0 0 
  2. mount -a を実行してOCFS2パーティションをfstabのエントリーをベースにマウントします。
おめでとうございます!クラスターファイルシステムはOracle Linx 7.xノード1とノード2の両方のサーバで/ocfs2でマウントされました!
クラスターが有効化されたアプリケーションでは、OCFS2ストレージを任意のネットワークアタッチされたストレージと同様に使うことができるようになりました。環境はよくよく考えて計画し、Availability DomainやOCFSなどの機能を活かしてOracle Cloud Infrastructure上に構築したソリューションの性能と可用性を向上していきましょう。

[Functions] Oracle FunctionsとObject Storageの組み合わせ入門/Getting Started with Oracle Functions and Object Storage

原文はこちら

Oracle Cloud InfrastructureのFunction-as-a-Service(FaaS)プラットフォームであるOracle Functionsがすべての商用リージョンでGAになりました。

このポストではOracle Functionsを用いてOracle Cloud Infrastructure Object Storage上のバケットにあるオブジェクトの一覧を、セキュアで細かくアクセス制御されたやり方で取得するサーバレスJavaファンクションを構築、デプロイする方法をご紹介します。ここでは以下をご説明します:
  • コードとコンセプト――背景とコードの概要
  • ファンクションの設定とデプロイ
このファンクションはOracle Cloud Infrastructure Java SDKにあるObject Storage APIを利用してObject Storageバケットにアクセスします。
始める前に、ここで使うことになるOracle Cloud Infrastructureプラットフォームの特長を見ておきましょう。

Oracle Functions

Oracle Functionsはフルマネージドで高いスケーラビリティを備えたオンデマンドのFaaSプラットフォームです。それはサーバレスサービスであり、下回りのインフラを気にすることなくビジネス上の要求を満たすためのコードの開発に集中することができ、また、実行時に消費されたリソースの分だけが課金されます。
Oracle Functionsはどのクラウドでもオンプレミスでも稼働することができるオープンソースのコンテナネイティブ、サーバレスプラットフォームであるFn Projectをベースとしています。あなたはFn Projectのオープンソースディストリビューションをローカルにダウンロード、インストールして、ファンクションを開発してテストすることができます。そしてそれと同じツールをOracle Functionsへのデプロイに利用することができるのです。

Object Storage

Object Storageサービスはインターネットスケールのハイパフォーマンスなストレージプラットフォームであり信頼性が高くコストパフォーマンスの良いデータ永続化を提供します。Object Storageは分析データから画像や動画などのリッチなコンテンツまで、内容の種類を問わず非構造化データを容量無制限で格納します。

コード・ウォークスルー

では、ファンクションの設定とデプロイを行う前に、イメージをつけるために前述したことを行うコードを見ていきましょう。

認証

Oracle Cloud Infrastructure SDKに含まれるResource Principal認証プロバイダがObject Storageサービスへのファンクションのアクセス許可に使われています。ResourcePrincipalAuthenticationDetailsProvider オブジェクトがObject Storageを呼び出すために使われることになるObjectStorageClientのインスタンスを作成するのに使われます。

private ObjectStorage objStoreClient = null;

final ResourcePrincipalAuthenticationDetailsProvider provider
            = ResourcePrincipalAuthenticationDetailsProvider.builder().build();

    public ObjectStoreListFunction() {
        try {
        
            objStoreClient = new ObjectStorageClient(provider);

        } catch (Throwable ex) {
            System.err.println("Failed to instantiate ObjectStorage client - " + ex.getMessage());
        }
    }
これを動かすためには、Oracle Cloud Infrastructureのダイナミックグループにそのファンクションを含めてやる必要があります。その後、Identity and Access Management(IAM)ポリシーでそのダイナミックグループのObject Storageへのアクセスを許可しておきます。このステップは後のセクションで説明します。詳細はドキュメントをご覧ください。

Listファンクション

The handle method for the list objects function needs just the bucket name as the input. Then, it uses the API handle (listObjects method) to get all the bucket object names.
オブジェクトの一覧を取得するhandleメソッドに必要なのはバケット名の引数だけです。そして、このメソッドはAPI(listObjects メソッド)を使ってバケットの全オブジェクト名を取得します。

    public List<String> handle(String bucketName) {
        if (objStoreClient == null) {
            System.err.println("There was a problem creating the ObjectStorageClient object. Please check logs");
            return Collections.emptyList();
        }
        List<String> objNames = null;
        try {
            String nameSpace = System.getenv().get("NAMESPACE");
            ListObjectsRequest lor = ListObjectsRequest.builder()
                    .namespaceName(nameSpace)
                    .bucketName(bucketName)
                    .build();

            System.err.println("Listing objects from bucket " + bucketName);
            
            ListObjectsResponse response = objStoreClient.listObjects(lor);
            objNames = response.getListObjects().getObjects().stream()
                    .map((objSummary) -> objSummary.getName())
                    .collect(Collectors.toList());

            System.err.println("Got list of objects in bucket " + bucketName);
        } catch (Throwable e) {
            System.err.println("Error fetching object list from bucket " + e.getMessage());
        }
        return objNames;
    }

前提

ファンクションを設定、デプロイする前に、以下の準備をしておいてください。

Object Storage

Create an Object Storage bucket. For details, see the documentation. Then, upload a few objects to the bucket (documentation).
ドキュメントを参照して、Object Storageのバケットを作成してください。そのあとさらに、いくつかのオブジェクトをそのバケットにアップロードしておきましょう(ドキュメント)。

Oracle Functions

Set up and configure Oracle Functions in your tenancy as described in the documentation.
このドキュメントを参照して、Oracle Functionsをあなたのテナンシーでセットアップしておいてください。

ソースコード

ソースコードを格納するためのディレクトリ構造を作りましょう:

mkdir -p function-object-store-example/src/main/java/io/fnproject/example

cd function-object-store-example
以下の内容を持ったfunc.yamlという名前のファイルを作りましょう:

schema_version: 20180708
name: listobjects
version: 0.0.1
runtime: java
build_image: fnproject/fn-java-fdk-build:jdk11-1.0.98
run_image: fnproject/fn-java-fdk:jre11-1.0.98
cmd: io.fnproject.example.ObjectStoreListFunction::handle
timeout: 120
以下の内容を持ったpom.xmlという名前のファイルを作りましょう:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <groupId>io.fnproject.example</groupId>
    <artifactId>list-objects</artifactId>
    <version>1.0.0</version>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.oracle.oci.sdk</groupId>
                <artifactId>oci-java-sdk-bom</artifactId>
                <version>1.5.14</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.oracle.oci.sdk</groupId>
            <artifactId>oci-java-sdk-objectstorage</artifactId>
        </dependency>
    </dependencies> 
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.1</version>
                <configuration>
                    <useSystemClassLoader>false</useSystemClassLoader>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <name>list-objects</name>
</project>
別のディレクトリに移ります:

cd src/main/java/io/fnproject/example/
以下の内容を持ったObjectStoreListFunction.java という名前のファイルを作りましょう:

package io.fnproject.example;

import com.oracle.bmc.auth.ResourcePrincipalAuthenticationDetailsProvider;
import com.oracle.bmc.objectstorage.ObjectStorage;
import com.oracle.bmc.objectstorage.ObjectStorageClient;
import com.oracle.bmc.objectstorage.requests.ListObjectsRequest;
import com.oracle.bmc.objectstorage.responses.ListObjectsResponse;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class ObjectStoreListFunction {

    private ObjectStorage objStoreClient = null;

    final ResourcePrincipalAuthenticationDetailsProvider provider
            = ResourcePrincipalAuthenticationDetailsProvider.builder().build();

    public ObjectStoreListFunction() {
        try {

            //print env vars in Functions container
            System.err.println("OCI_RESOURCE_PRINCIPAL_VERSION " + System.getenv("OCI_RESOURCE_PRINCIPAL_VERSION"));
            System.err.println("OCI_RESOURCE_PRINCIPAL_REGION " + System.getenv("OCI_RESOURCE_PRINCIPAL_REGION"));
            System.err.println("OCI_RESOURCE_PRINCIPAL_RPST " + System.getenv("OCI_RESOURCE_PRINCIPAL_RPST"));
            System.err.println("OCI_RESOURCE_PRINCIPAL_PRIVATE_PEM " + System.getenv("OCI_RESOURCE_PRINCIPAL_PRIVATE_PEM"));

            objStoreClient = new ObjectStorageClient(provider);

        } catch (Throwable ex) {
            System.err.println("Failed to instantiate ObjectStorage client - " + ex.getMessage());
        }
    }

    public List<String> handle(String bucketName) {

        if (objStoreClient == null) {
            System.err.println("There was a problem creating the ObjectStorage Client object. Please check logs");
            return Collections.emptyList();
        }

        List<String> objNames = null;
        try {
            String nameSpace = System.getenv().get("NAMESPACE");

            ListObjectsRequest lor = ListObjectsRequest.builder()
                    .namespaceName(nameSpace)
                    .bucketName(bucketName)
                    .build();

            System.err.println("Listing objects from bucket " + bucketName);

            ListObjectsResponse response = objStoreClient.listObjects(lor);

            objNames = response.getListObjects().getObjects().stream()
                    .map((objSummary) -> objSummary.getName())
                    .collect(Collectors.toList());

            System.err.println("Got " + objNames.size() + " objects in bucket " + bucketName);

        } catch (Throwable e) {
            System.err.println("Error fetching object list from bucket " + e.getMessage());
        }

        return objNames;
    }
}

Oracle Functionsへのデプロイ

ディレクトリのルートに移動します:

cd ../../../../../..

アプリケーションの作成

アプリケーションを作成して必要な設定を行います。あなたの全てのファンクションはこのアプリケーションの一部となります。

fn create app --annotation oracle.com/oci/subnetIds='["<OCI_SUBNET_OCIDs>"] --config NAMESPACE=<NAMESPACE> fn-object-store-app
ここで設定パラメータは以下のように定義します:
  • OCI_SUBNET_OCIDs: Oracle Functions用に設定したコンパートメント内のサブネットをひとつ、あるいは複数指定します。
  • NAMESPACE: Object Storageのネームスペース(ドキュメント)を指定してください。
例:

fn create app --annotation oracle.com/oci/subnetIds='["ocid1.subnet.oc1.phx.exampleuniqueid"]' --config NAMESPACE=foobar fn-object-store-app

ファンクションをデプロイ

以下のコマンドを実行してファンクションをデプロイします:

fn -v deploy --app fn-object-store-app
プロセスが完了したら、次のコマンドを実行してデプロイが成功したことを確認しましょう:

//to check your app (and its config)
fn inspect app fn-object-store-app

//to check associated function
fn list functions fn-object-store-app

Oracle Functions Resource Principalsの設定

ファンクションがデプロイされたので、Object Storageにアクセスできるようにテナンシーの設定を行っていきましょう。
ファンクションのOCIDを以下のコマンドで取得します:

fn inspect fn fn-object-store-app listobjects id
以下のマッチングルールでfn-obj-store-listという名前のダイナミックグループを作成してください:

resource.id = '<FUNCTION_OCID>'
以下のステートメント文でfn-object-store-list-policyという名前のIAMポリシーを作成してください。<COMPARTMENT_NAME>と<BUCKET_NAME>はご自身のテナンシーの値で置き換えてください:

allow dynamic-group fn-obj-store-list-dg to read objects in compartment <COMPARTMENT_NAME> where all{target.bucket.name=’<BUCKET_NAME>’}

ファンクションのテスト

いよいよデプロイしたばかりのファンクションを試してみる時がきました。
バケット内の全てのオブジェクト名を一覧:

echo -n '<object store bucket name>' | fn invoke fn-object-store-app listobjects
例:

echo -n 'test' | fn invoke fn-object-store-app listobjects
全オブジェクト名の一覧がレスポンスとして返ってくるはずです。以下が例です:

[
 "file1.txt,
 "file2.txt"
]

まとめ

ここまででOracle Cloud Infrastructure Object Storageとやり取りするファンクションをどのように開発するかのイメージを掴んでいただけたかと思います。Java SDKをファンクションの構築、設定、Oracle Functionsへのデプロイの中でどのように使うのかもおわかりになったでしょう。
ここでの例はごくシンプルなものでしたが、このコンセプトはどこでも応用できるものです。

[Cloud] Cloud SyncでStorage Gatewayを最大限活用/Get the Most Out of Storage Gateway with Cloud Sync

原文はこちら。
https://blogs.oracle.com/cloud-infrastructure/get-the-most-out-of-storage-gateway-with-cloud-sync







Oracle Cloud Infrastructure Storage GatewayのCloud Sync機能はふたつのNFSサーバー間でのファイル同期を可能にしてくれます。
以前のわたしのブログポストで、Oracle Cloud Infrastructure上で稼働するよう作られたObject StorageベースのNFSサーバーであるStorage Gatewayをご紹介しました。このソリューションはデータ転送、バックアップおよびアーカイブのユースケースにぴったりです。また、クラウドネイティブではないソフトウェアがObject Storageバケットのオブジェクトをどのように取り出したり書き込んだりするかを意識せずにObject Storageを使えるようにしてくれます。
しかし、あなたのアプリケーションが高頻度で大規模なファイル書き込みを行うようなものだったとしたらどうでしょう?このようなケースでは、Storage Gatewayに直接書き込みを行うやり方はあまり実践的ではありません。外部のクラウドリソースからのファイル読み込み、書き込みには時間がかかりますから、高速なストレージを必要とするアプリケーションをスローダウンさせてしまうでしょう。一方で、あなたはObject Storageを使うことで得られる事実上無限のストレージ容量を欲しています。このような場合に一般的なソリューションには、ふたつのNFSサーバーを稼働させることが含まれています;ひとつは高速なBlock Volumeベースのものにしておいて、アーカイブ用にはObject Storageベースのものを使う、というやつです。そして、もしローカルNFS上のファイルをStorage Gateway上のファイルと同期できたら便利です。これをマニュアルで行うこともできるでしょうが、ヒューマンエラーの可能性が怖いですよね。であればCloud Syncを使うこともできますよ。

Cloud Syncとはなんぞや

Storage GatewayのCloud Sync機能は、Linux標準のrsyncコマンドを用いてローカルのNFSサーバー上のファイルをObject StorageベースのStorage Gateway NFSサーバーへの同期、またその逆の同期を行うものです。さらに、このツールはエラーハンドリングと進捗のモニタリングも行います。この機能はメタ―自動ジョブ(たとえば夜間cronジョブ)を行うもので、スクリプトに加えたりすることなく使えるためとても簡単にできます。接続の問題は自動リトライでシームレスに対処され、Webコンソールとコマンドラインインターフェース(CLI)のどちらで起動してもステータスフィードバックを提供します。高いレベルでの自動化を行うには、出力をCLIでモニタリングしておくことが理想的でしょう。
でもちょっと待ってください…これだけではありません!CLIのパラメータからわかるように、Cloud Syncは人間がほとんどいつも失敗してしまうタスクであるファイルのパラレル同期を行ってくれます:
sudo ocisg cloudsync create [--auto-delete] [--parallel=<number>] [--files-from=<file>] <job_name> <source_path> <target_path>
ジョブを作成し、パラレル処理するプロセスの数(最大10まで)を指定し、実行するだけでいいのです:
sudo ocisg cloudsync run <job_name> 
ローカルNFSサーバーからStorage Gatewayに大きなデータを転送したいような場合に特に、この機能が役立ちます。もしかしたらあなたは数テラバイトのデータをObject Storageに移動しようとしているかもしれません。Cloud Sync機能を使うことで、1日数十テラバイトのデータを扱うこともできるようになります。自動リトライと再開機能により、人による干渉は必要なくなります。
わたしはいつもCLIを使うことをおすすめしていますが、Webコンソールでも高速で直観的、便利にClous Syncジョブを作成し、実行し、参照し、削除することができますよ。
このOracle Cloud Infrastructureの新機能についての記事を楽しんでいただけたなら幸いです。ではまた次回お会いするときまで、クラウドであれ!

[Cloud]OKEでFile Storageサービスを利用する/Using File Storage Service with Container Engine for Kubernetes


Oracle Cloud Infrastructure Container Engine foe Kubernetesはコンテナ化されたアプリケーションをクラウド上にデプロイするのに使える、フルマネージドのスケーラブル、高可用性のサービスです。

コンテナ化されたアプリケーションのベストプラクティスのひとつに、ステートレスコンテナの利用があります。しかし、実際には多くのアプリケーションにはコンテナにステートフルな動作が必要です。たとえば、クラシックな3層アプリケーションは以下のような3つのコンテナを持つでしょう:
  • プレゼンテーションレイヤー用にひとつ、ステートレス
  • アプリケーションレイヤー用にひとつ、ステートレス
  • 永続化(データベースなど)レイヤー用にひとつ、ステートフル
Kubernetesでは、各コンテナはそれぞれのファイルシステムを読み書きできます。しかし、コンテナが再起動すると、全てのデータがロストします。したがって、ステートを保持する必要のあるコンテナではデータをNetwork File System(NFS)のような永続化ストレージに保存することになります。NFSに保存済のデータは、ひとつ~複数のコンテナで構成されるポッドが破壊されても削除されません。また、NFSには複数のポッドから同時にアクセスすることが可能なので、ポッドをまたいでデータをシェアするのにもNFSを使うことができます。この性質は、コンテナやアプリケーションが単一の共有ファイルシステムから設定データを読み込む必要があるとき、また、複数のコンテナが単一の共有ファイルシステムのデータを読み書きするときにとても有用です。
Oracle Cloud Infrastructure File Storageは堅牢、スケーラブルで分散したエンタープライズグレードのネットワークファイルシステムを提供しており、NFSバージョン3とNetwork Lock Manager(NLM)をサポートしています。Virtual Cloud Network(VCN)内のどのベアメタルあるいはVM、コンテナインスタンスからもFile Storegeにアクセスすることができます。また、Oracle Cloud Infrastructure FastConnectかInternet Protocol Security(IPSec) Virtual Private Network(VPN)を使えば、VCN外からもファイルシステムにアクセスすることができます。File Storageはフルマネージドサービスなので、ハードウェアの導入と維持、キャパシティプランニングやソフトウェアアップグレード、セキュリティパッチなどは気にしなくて済みます。わずか数キロバイトのデータからファイルシステムを使いだして、ゆくゆくは8エクサバイトのデータまで扱うこともできます。
このポストではFile Storage(しばしばFSSと呼ばれます)をContainer Engine for Kubernetes(OKEと呼ばれます)を組み合わせて使う方法を解説します。ここではふたつのポッドを作成します。ひとつはWorker Node 1上で動き、もうひとつはWorker Node 2上で動いており、File Storageファイルシステムを共有します。
 
ではここから、ポッドの中身と、File Storageと組み合わせる方法を見ていきましょう。

前提条件:

  • 利用するテナンシーのOracle Cloud Infrastructureアカウントの認証情報
  • テナンシー内に作成済のOKEクラスターがあること。Container Engine for Kubernetes documentationに例が載っています。
  • Security lists configured to support File Storage as explained in the File Storage documentationに説明があるように、File Storageをサポートするようにセキュリティリストが構成されていること。以下はセキュリティリスト設定の例です。
  • Announcing File Storage Service UI 2.0の手順にしたがって作成された、ファイルシステムとマウント対象。

手順の概要

  1. Storage Classの作成
  2. Persistent Volume (PV)の作成
  3. Persistent Volume Claim(PVC)の作成
  4. PVCを利用するポッドの作成

Storage Classの作成

作成したファイルシステムのマウントターゲットIDを参照するStorage Classを作成します:
kind: StorageClass
apiVersion: storage.k8s.io/v1beta1
metadata:
  name: oci-fss
provisioner: oracle.com/oci-fss
parameters:
  # Insert mount target from the FSS here
  mntTargetId: ocid1.mounttarget.oc1.iad.aaaaaaaaaaaaaaaaaaaaaaaaaa

Persistent Volume(PV)の作成

apiVersion: v1
kind: PersistentVolume
metadata:
name: oke-fsspv
spec:
storageClassName: oci-fss
capacity:
storage: 100Gi
accessModes:
- ReadWriteMany
mountOptions:
- nosuid
nfs:
# Replace this with the IP of your FSS file system in OCI
server: 10.0.32.8
# Replace this with the Path of your FSS file system in OCI
path: "/okefss"
readOnly: false

Persistent Volume Claim (PVC)の作成

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: oke-fsspvc
spec:
storageClassName: oci-fss
- ReadWriteMany
resources:
requests:
 # Although storage is provided here it is not used for FSS file systems
 storage: 100Gi
volumeName: oke-fsspv

PVCがバインドされたことを確認します:

raghpras-Mac:fss raghpras$ kubectl get pvc oke-fsspvc
NAME         STATUS   VOLUME      CAPACITY   ACCESS MODES   STORAGECLASS   AGE
oke-fsspvc   Bound    oke-fsspv   100Gi      RWX            oci-fss        1h
raghpras-Mac:fss raghpras$

Worker Nodeのラベル付け

ふたつのWorker Nodeにラベルを付け、ポッドをアサインできるようにしておきます:
kubectl label node 129.213.110.23 nodeName=node1
kubectl label node 129.213.137.236  nodeName=node2

ポッドでのPVC利用

次のWorker Node 1(node1)上のポッド(oke-fsspod)がファイルシステムPVC(oke-fsspvc)を使用します:
#okefsspod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: oke-fsspod
spec:
  containers:
  - name: web
    image: nginx
    volumeMounts:
     - name: nfs
       mountPath: "/usr/share/nginx/html/"
    ports:
      - containerPort: 80
        name: http
  volumes:
  - name: nfs
    persistentVolumeClaim:
      claimName: oke-fsspvc
      readOnly: false
  nodeSelector:
    nodeName: node1

ポッドを作成します:
kubectl apply -f okefsspod.yaml

テスト

ポッドを作成したら、kubectl execで共有ファイルを書き込むことができるかテストします:
raghpras-Mac:fss raghpras$ kubectl get pods oke-fsspod -o wide
NAME         READY   STATUS    RESTARTS   AGE   IP            NODE             NOMINATED NODE
oke-fsspod   1/1     Running   0          33m   10.244.2.11   129.213.110.23   <none>
raghpras-Mac:fss raghpras$

kubectl execを使用し、ファイルシステムに書き込みます:
raghpras-Mac:fss raghpras$ kubectl exec -it oke-fsspod bash

root@oke-fsspod:/# echo "Hello from POD1" >> /usr/share/nginx/html/hello_world.txt

root@oke-fsspod:/# cat /usr/share/nginx/html/hello_world.txt

Hello from POD1

root@oke-fsspod:/#

もうひとつのポッドでも繰り返し

Worker Node 2 (node2)上のもうひとつのポッド(oke-fsspod2)でもこのファイルシステムがマウントできることを確認します: 
apiVersion: v1
#okefsspod2.yaml
kind: Pod
metadata:
  name: oke-fsspod2
spec:
  containers:
  - name: web
    image: nginx
    volumeMounts:
     - name: nfs
       mountPath: "/usr/share/nginx/html/"
    ports:
      - containerPort: 80
        name: http
  volumes:
  - name: nfs
    persistentVolumeClaim:
      claimName: oke-fsspvc
      readOnly: false
  nodeSelector:
   nodeName: node2

raghpras-Mac:fss raghpras$ kubectl apply -f okefsspod2.yaml 

pod/oke-fsspod2 created

raghpras-Mac:fss raghpras$ kubectl get pods oke-fsspod oke-fsspod2 -o wide
NAME          READY   STATUS    RESTARTS   AGE   IP            NODE              NOMINATED NODE
oke-fsspod    1/1     Running   0          12m   10.244.2.17   129.213.110.23    <none>
NAME          READY   STATUS    RESTARTS   AGE   IP            NODE              NOMINATED NODE
oke-fsspod2   1/1     Running   0          12m   10.244.1.9    129.213.137.236   <none>

raghpras-Mac:fss raghpras$ kubectl exec -it oke-fsspod2 -- cat /usr/share/nginx/html/hello_world.txt

Hello from POD1

raghpras-Mac:fss raghpras$

もういちどテスト

後で作成したポッドでも共有ファイルに書き込めることをテストします:
raghpras-Mac:fss raghpras$ kubectl exec -it oke-fsspod2 bash

root@oke-fsspod2:/# echo "Hello from POD2" >> /usr/share/nginx/html/hello_world.txt

root@oke-fsspod2:/# cat /usr/share/nginx/html/hello_world.txt

Hello from POD1

Hello from POD2

root@oke-fsspod2:/# exit

exit

まとめ

File StorageとOKEは両方ともフルマネージドサービスで、高可用性があり、スケーラブルです。File Storageはさらに、Oracle Cloud Infrastructure上でデータを高度に永続化する、堅牢なストレージです。File Storageは分散アーキテクチャ上に構築され、データとそのアクセスをスケーラブルにします。これらのサービスを利用することで、クラウド上でのワークフローをシンプルにし、柔軟性とコンテナデータをどのように保存するかの選択肢を得ることができます。

What's Next

開発中のFile Storageサービスでの動的なボリュームプロビジョニングでは、Kubernetesクラスターの中からファイルストレージをリクエストし、ファイルシステムの作成とマウントを行います。
Oracle Cloud Infrastructure、OKE、OCI File Storageについてもっと知りたい場合は、まずはクラウドランディングページを見てみるのがいいと思います。

Resources