[Java] A new (Japanese) era for Java!

原文はこちら。
https://blogs.oracle.com/java-platform-group/a-new-japanese-era-for-java

2016年に今上天皇が皇太子さまに譲位する予定であることを発表されました。今上天皇は2019年4月30日(平成31年4月30日)に退位される予定で、2019年4月1日に日本の内閣が、2019年5月1日から始まる新しい元号を発表することになっています。
この新しい元号に備えるための手順をとってきましたが、新元号の発表までこのアップデートの最終化は待つ必要があります。
特にJDKにおいてはいくつかの変更があります。
  • グレゴリオ暦の日付を和暦に相当する日付に変換してテキストとして表示する場合、正しい元号名を知っておく必要があります。
  • 逆変換、つまり文字列表記の日付を正しい日時に変換する場合には、元号名称を解析し、どの西暦に相当するのかを知っておく必要があります。
  • Unicodeは、新しい元号名称を表現する合字を新たに追加します。
JDK 8以降、Java APIには新しいDate and Time API(JSR 310を参照)のほか、古いjava.util.Calendarクラスに日付を処理するためのメソッドが追加されました。すべての関連APIは、新しい時代を正しく処理するように更新されてきました。
JSR 310: Date and Time API
https://jcp.org/en/jsr/detail?id=310
新元号に備えて、JDK 12では新元号( “NewEra”)のプレースホルダー名を使用します。JDK 12を使用すると、新元号発表後にリリースされるアップデートで、新元号名がどのように処理されるのかがわかります。
新元号の発表後の次のアップデートリリースは2019年4月16日(PDT)を予定しています。すべてのサポート対象のJDKである7、8、11 LTS、そして12が新しい元号を扱えるようにアップデートされます。
これらのすべてのバージョンの中で、java.util.Calendarクラスは正しい値を理解し、返すためにアップデートされます。
import java.util.*;
import java.text.*;

...

  new SimpleDateFormat("GGGGy 年M ⽉d ⽇", 
        Locale.forLanguageTag("ja-JP-u-ca-japanese")).
        format(new Calendar.Builder().
        setDate(2019, Calendar.MAY, 1).build().getTime());

    // before the update: 平成31 年5 ⽉1 ⽇, 
    // after the update: 元号元 年5 ⽉1 ⽇
    // On versions released after new announcement the 元号 will be replaced with the new era name
そしてjava.text.SimpleDateFormatを使った日付のパースは正しく動作します。
import java.text.*;

...

var sdf = new SimpleDateFormat("GGGGy 年M ⽉d ⽇",
            Locale.forLanguageTag("ja-JP-u-ca-japanese"));  
            sdf.setLenient(false);
            new SimpleDateFormat("Y-M-d", Locale.US).format(sdf.parse("元号2 年2 ⽉1 ⽇"));
    // => "2020-2-1"
    // with 元号 replaced with the new era name
JDK 8以後については、JSR 310 Data and Time APIもアップデートします (このAPIはJDK 7には含まれていません)。
import java.time.chrono.*;
import java.time.format.*;
import java.time.temporal.*;

...

    DateTimeFormatter.ofPattern("GGGGy 年M ⽉d ⽇").
          withChronology(JapaneseChronology.INSTANCE).
          withLocale(Locale.JAPAN).
          format(JapaneseDate.of(2020, 2, 1));
    // => “元号2 年2 ⽉1 ⽇”

    DateTimeFormatter.ofPattern("u-M-d").format(
          DateTimeFormatter.ofPattern("GGGGy 年M ⽉d ⽇").
          withChronology(JapaneseChronology.INSTANCE).
          withLocale(Locale.JAPAN).
          withResolverStyle(ResolverStyle.STRICT).
          parse("元号2 年2 ⽉1 ⽇"));
     // => “2020-2-1”


    JapaneseEra.of(3).getDisplayName(TextStyle.FULL,
          Locale.forLanguageTag("ja-JP-u-ca-japanese"));
    // => “元号”
    // with 元号  replaced with the new era name
JDK 8以後では、Unicodeコードポイント U+32FF がjava.util.Calendar クラスに入ります。このコードポイントは新元号の合字用に予約されています。

まとめると、以下の通りです。
  • 日本の新元号の発表後リリースされるJDKのアップデートで、新元号を正しく取り扱えるようにする
  • 新元号発表までは、JDK 12(そしてJDK 11も)は将来の挙動と同様ではあるものの、元号をプレースホルダー名(*)として使用する。
(*)文字列形式の日付のパースに問題があるため、パースが正しく機能するための4月のアップデートまで待つ必要があります。
[JDK-8217609] New era placeholder not recognized by java.text.SimpleDateFormat
https://bugs.openjdk.java.net/browse/JDK-8217609

[Cloud]Grafana用クラウド監視データを提供/Oracle Delivers Open Source Cloud Monitoring Data with Grafana

原文はこちら。



オープンソース・ソフトウェアが次世代クラウドの適用とポータビリティを加速させています。オープンソースの技術とカルチャーを取り入れることで、分散した環境にまたがるクラウド管理をシンプルにでき、クラウドを相互運用可能でポータブルかつスケーラブルにすることができます。オープンソースなしでは、特定のクラウドモデルにロックインされてしまうでしょう。

Oracle Cloud Infrastructure Data Source for Grafanaのリリースをお伝えできて興奮しています。Grafanaは分析と監視のための先進的なオープンソースプラットフォームで、Oracle Cloud Infrastructureをお使いのお客様からの多くのご要望がありました。以前に行ったOracle Cloud Infrastructure内でのPrometheusの利用に加えてさらに堅牢な監視を可能にする今回のGrafanaの統合に関して、我々はGrafana Labsと緊密に連携してきました。
Cloud nativeのワークロードが求める監視可能性の強化について、Oracle Cloud Infrastructureはネイティブのものとサードパーティのもの両方の様々なツールで実現できるようにしています。Oracle Cloud Infrastructure Data Source for Grafanaにより、データを探索したり、ログを分析したり、Grafana 6.0の持つ様々な機能を利用する新たな方法が提供されます。
2018年12月のKubeCon + CloudNativeConで発表したOracle Cloud Native Frameworkのリリースは今後も続きます。このフレームワークには、いずれもマネージドサービスとして提供するKubernetesOracle Cloud Infrastructure Registry、可視性の拡充やアプリケーション定義、開発とプロビジョニング機能などから成るOracle Cloud Infrastructure cloud native servicesが含まれます。我々はOracle Cloud Infastructureおよびハイブリッドやマルチクラウド環境をお使いのお客様に対して、最良の可視性を提供することに力を入れています。そのために、Oracle Cloudのサービスをオンプレミスで動かせるようCloud at Customerを提供したり、Oracle Autonomous Databaseをはじめとするエンタープライズワークロードのための最も自動化され高性能な環境を提供しています。
Oracleは長年にわたりオープンソースにコミットしてきており、2017年からはCloud Native Computing Foundationのプラチナメンバーになっています。どこでも動かせるスケーラブルなファンクション基盤であるFn Projectへの貢献に示される通り、オープンソースへの注力は継続していきます。マネージドサービスをお求めなら、プロプライエタリなAPIであなたをロックインしたりすることがないオープンなソリューションであるOracle Functions (FaaS)もあります。Oracle Functionsで開発したものは、Fn Projectであればどこでも動かすことができます。
ハイブリッドやマルチクラウドなど環境をまたいだイベントとタスク実行のストリーミングについてのログ出力・分析のためのアーキテクチャそのものはもちろん、そのスケールとパフォーマンスも重要です。このことから、イベント監視、問題の隔離、および確実で堅牢なセキュリティフレームワークの必要性が増すでしょう。
Oracle Cloud Infrastructure Data Source for Grafanaは、オープンソースのソリューションを促進し、エンタープライズのお客様に提供することで、Oracle Cloud Infrastructureとハイブリッド、マルチクラウドのワークロード管理の選択肢と柔軟性を提供していくという我々の姿勢を示しています。

[Cloud]OCI WAFのリリースのご案内/Introducing the Oracle Cloud Infrastructure Web Application Firewall

原文はこちら。


Oracle Cloud Infrastructure上のワークロード、また、マルチクラウドのWebアプリケーション向けのOracle Cloud Infrastructure Web Application Firewall (WAF)をリリースしたことをご案内します。Oracle Cloud Infrastructure WAFは、インターネットに面するWebアプリケーションを悪意のサイバー攻撃やスクレイピング・ボットから防御するための、エンタープライズグレードでクラウドベースのセキュリティソリューションです。2018年のOracleとKPMGによるCloud Threat Reportによれば、回答者の51%が、不正アクセスから組織の機密データを守る方法としてWebアプリケーションファイアウォールが最も優先度が高いと回答しています。

今日では、Webアプリケーションはデジタルビジネスの中核を成していますが、サイトに侵入しようという悪意を持った者によるサイバー攻撃の脅威に恒常的にさらされています。もし侵入を許せば、データを盗まれたり、不正なソフトウェアをサイトを訪れるお客様に広められてしまったり、評判を傷つけられたりしてしまいます。なのでクラウドにワークロードを移行しようとしているすべての企業にとってセキュリティが一番の関心事であること、また、Webアプリケーションファイアウォールが今日のデジタルビジネスにとって絶対必要だとみなされることに不思議はありません。Webアプリケーションファイアウォールなしでは、多くの企業は重要なアプリケーションやデータ、サービスをクラウドに移行しようとも考えないでしょう。Oracle Cloud Infrastructure WAFは、Oracle Cloud Infrastructure、オンプレミス、マルチクラウドのワークロードに安全と安心を提供します。

WAFサービスはサイバー攻撃から多層的なアプローチでWebアプリケーションを守ります。今回のリリースでは、Open Web Access Security Project(OWASP)のものや特定のアプリケーション、特定の規制準拠のためのものなど、250以上の定義済みルールが含まれています。WAFにはまた、Webroot BrightCloud®を含む複数のソースを統合した脅威インテリジェンスも提供します。管理者はアクセス制御を地理、IPアドレスのホワイトリスト/ブラックリスト、HTTP URLやヘッダの特徴にもとづいて行うことができます。ボット対策にはJavaScript受け入れ、CAPTCHAやデバイス認証、ヒューマンインタラクション・アルゴリズムなどのより高度なチャレンジを提供しています。WAFサービスにアプリケーションを登録しておくことで、レイヤー7分散DDoS攻撃から守ります。

WAFの仕組み

Oracle Cloud Infrastructure WAFはリバースプロキシとして動作し、通信フローやリクエストがもとのWebアプリケーションに到達する前に監査をします。また、Webアプリケーションサーバからエンドユーザーへのいずれのリクエストも監査します。
この強力なサービスによって、アプリケーションサーバからのデータ漏えいを制御し、外部の脅威からサーバを守ることができるようになります。

WAFの統合

Oracle Cloud Infrastructure WAFは他のOracle Cloud Infrastructureのアプリケーション、サービスとコンソール上で密に統合されており、セットアップと管理が簡単にできます。たとえば:
  • WAFのポリシーにタグを付け、コストを追跡する
  • Identity and Access Management(IAM)を用いてWAF管理へのアクセス制御を行う
  • 監査サービスにWAFの変更を記録
WAFはEdgeサービス・メニューの配下にあります。パッシブ検知用の定義済みルールを有効にしたり、Webアプリケーションのリバースプロキシ―として個別のルールでWAFにブロックを行わせたりできます。

数百の準備済み防御ルール

WAFを通ったトラフィックのログはコンソール上で分析することもできますし、エンタープライズSIEMに引き入れることもできます。
詳細なアプリケーションログと可視性
コンソール上での統合に加えて、WAFでは堅固なRESTful APIの利用も可能です。これには複数の言語のSDKと、CLIおよびTerraformが含まれます。

主要なユースケース

以下はWebアプリケーションファイアウォールのユースケースの一部です:
  • サイバー攻撃からの防御:Oracle Cloud Infrastructure WAFはクラウドベースで提供され、OWASPのルールセットに加え、250のルールセットをサポートしています。こうしたルールを使い、重要なWebアプリケーションを悪意のサイバー攻撃から守りましょう。インカミングリクエストはこれらのルールにより攻撃ペイロードを含んでいないか評価されます。リクエストが攻撃であると判断された場合、WAFはそのリクエストをブロックするか、またはアラートを挙げます。こうした攻撃は多種多様で、SQLインジェクションやクロスサイトスクリプティング、HTMLインジェクションなどの脅威を含んでいますが、いずれもWAFルールで検知、ブロックが可能です。
  • データプライバシー標準のためのアクセス制御:アクセス制御を用いて重要なWebアプリケーション、データやサービスへのアクセスをコントロールしましょう。例えば、リージョンベースのアクセス制御はEUのGDPRコンプライアンス要件にぴったりです。しばしば、あるサービスの提供をGDPRに則った特定の地域に限る必要があります。リージョンベースのアクセス制御を用いてユーザーアクセスをある地域に限定し、たとえばアメリカにあるサーバーから情報を取得できないようにする、といったことが可能です。あるいは、特定の国からのアプリケーションアクセスを完全にブロックするといったこともできます。たとえば、アジアの国々とのビジネスを行っていない場合に、それらの国々からのアクセスをブロックする、といったように。
  • 既存の管理システムとの統合:RESTful APIは、WAFへの十全なシステム間インターフェースを提供します。すでにバックエンドの管理システムを保持しており、コンソールは不要なので、WAFを直接既存管理システムと統合したいというときにはこれは理想的です。
  • ボット対策:インターネット上では、ボットによるトラフィックは人間によるそれよりも多くなっています。ボットの大半は悪意のないものですが、しかしそれゆえ単にボットを全てブロックしてしまうということもできません。JavaScriptチャレンジ、CAPTCHAチャレンジ、ホワイトリスト機能をWAFルールセットと併せて用いることで、良いボットをとおして悪いボットをブロックすることが可能です。
  • Hybrid and multicloud protection:ハイブリッドおよびマルチクラウドの防御:Many 多くのクラウドプロバイダがWebアプリケーションファイアウォールの防御を自身のクラウド上のアプリケーションのみに制限しています。Oracle Cloud Infrastructure WAFではそのようなことはありません。Oracle Cloud Infrastructure上のワークロードに加え、WAFはオンプレミスとマルチクラウド環境も防御します。Oracle Cloud Infrastructureへの移行にあたり、単一のWebアプリケーションファイアウォールでいずれの環境も防御できるというのは非常に重要なことです。移行のそれぞれのフェーズ―クラウド上でのテスト、移行とカットオーバー―でWAFがあなたの環境を防御します。

まとめ

Oracle Cloud Infrastructure WAFは、もはやVPNや専用線の必要なしにインターネットに接するWebアプリケーションを実現するための鍵となります。Oracle Cloud Infrastructure WAFについての詳細は、こちらのWebサイトまで。

[Cloud]Traffic Managementのリリースのご案内/Announcing the Launch of Traffic Management




本日(2019/2/15)、Oracle Cloud Infrastructure上でのDNS Traffic Managementをリリースしたことをお伝えでき、大変うれしく思います。われわれの業界をリードするDNSは、既に世界で最も信頼性が高く、堅牢なDNSネットワークです。これからはさらに、エンドポイントの可用性やエンドユーザーの所在地に応じてカスタマイズ可能なSteering Policyを使用し、最適なエンドユーザーエクスペリエンスを提供できるようになります。ふたつのクラウドリージョン間でのトラフィック分散のようなトラディショナルなグローバル・ロードバランシング機能に加えて、Oracle Cloud Infrastructure DNSはインカミングクエリとリクエストのルーティングをより細かく制御できるようになりました。
Traffic Management Steering Policiesによって、AからBへのフェイルオーバーといったシンプルなものから非常に複雑なエンタープライズアーキテクチャでのものまで、幅広いユースケースをサポートできます。これにより、サービスの差別化、地理情報に基づいたマーケティング、ディザスターリカバリー対応などの業務上の要求に予測可能なかたちで応えるポリシーを構築しておくことができます。ルールセットにより、管理下にある任意のアセットにグローバルトラフィックを差し向けることができ、ハイブリッドクラウド、マルチクラウドいずれのシナリオでも、ユーザーエクスペリエンスとインフラ効率性を最適化することができます。


Traffic Management Steering Policiesの必要性とは?

DNSの中核コンポーネントであるTraffic Managementにより、DNSクエリに対してインテリジェントなレスポンスを返すためのルーティングポリシーを設定できます。お客様が設定するTraffic Management Policyによっては、同様のクエリに対して動的に違ったレスポンスを返すことも可能で、これによりエンドユーザーを最も最適な地理にあるインフラに誘導することができます。また、Oracle Cloud Infrastructure DNSは、その時点のインターネットの状況に応じて最適なルーティングを行うように最適化されています。

典型的なユースケースとは?

エンタープライズ企業がクラウド、また、ハイブリッドアーキテクチャに移行を進めるに連れ、高可用性とディザスターリカバリの重要性はこれまでにないほどに高まっています。DNSフェイルオーバを使うと、あるエンドポイントが応答しなくなった場合に、トラフィックをそのエンドポイントから別の場所に振り替えることができます。エンドポイントの死活監視はOracle Cloud Infrastructure上で併せて利用可能となったOracle health checkによって行われます。
複数の地理分散したリージョンにまたがるインフラをスケールさせるために、クラウドベースのDNSロードバランシングは理想的です。スケールアウトによる新インフラの追加、クラウドへの移行、新機能の限定的なリリースなどが典型的なユースケースです。オンプレミスとクラウド上にあるあなたの全てのインフラのエンドポイントの「プール」を構築し、割合による重みづけを設定することも簡単にできます。
ソースベースド・ステアリングでは、リクエストがどこから来たのかに応じた自動ルーティングを行うことができます。こうしたソースベースドポリシーを用いることで、最も地理的に近いところにトラフィックを誘導したり、元のクエリのIPプレフィックスに基づいてトラフィックを制御する「スプリットホライズン」を作成したり、プロバイダ選好に基づいた判断を行うことができます。
異なるOracle Cloud Infrastructureリージョンにまたがって、ユーザーを地理的に最も近いところに誘導するようなロードバランシングを行うことができます。Health Checkを併せて使えば、あるリージョンのアセットが応答しない場合に別のリージョンに誘導するといったこともできます。

使い始めるには

 基本的なDNSの設定を終えたあとに、Edge Servicesの配下にあるTraffic Management Steering Policiesを選択すると、自分のステアリングポリシーを作成、カスタマイズすることができます。使い始める方法や自分のユースケースをどう実現できるかについて質問があれば、われわれまでご連絡ください。

[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

[Cloud] Oracle Functions:開発者のためのクイックスタートガイド/Oracle Functions: Serverless On Oracle Cloud - Developer's Guide To Getting Started (Quickly!)

原文はこちら。
https://blogs.oracle.com/developers/oracle-functions%3a-serverless-on-oracle-cloud-developers-guide-to-getting-started-quickly

12月にクラウドネイティブサービスについての大規模な大規模なアナウンスをしましたが、その一部としてOracle Functionsという新しいサービスも発表しました。Oracle Functionsは、Functions as a Service(FaaS)、あるいはDockerコンテナを利用して実行されるホストされたサーバーレスだと考えればよいでしょう。サービスのベースとなっているオープンソースであるFn Project自体は新しいものではありませn。しかし、Oracleのクラウド経由でサーバーレスファンクションを迅速にデプロイし、起動することができるようになったことで、以前よりも実装がとても容易になりました。このサービスは現時点ではLimited Availabilityです(トライしてみたい方はこちらから登録ください)が、開発者のみなさんが簡単にOracle Cloudでサーバーレスを始められるように、情報をまとめてみようと思います。このポストでは、テナンシーを設定し、Oracle Functionsであなたの最初のアプリケーションやファンクションをデプロイし起動するために必要なステップを一通り見ていきます。
まず始める前に、Oracle Cloudテナンシーの設定を行っておく必要があります。Oracle Functionsは現時点ではPhoenixリージョンのみで利用可能となっているため、Limited Availabilityトライアルを行う場合、あなたのテナンシーがPhoenixリージョンに登録してあることを確認しましょう。リージョンのチェック、登録方法は以下のGIFを見てください。
また、OCI CLIをインストールしていない場合、インストールしておきましょう。というかなんでインストールしてないんですか?コンソールにログインせずにテナンシーに関することはほとんどなんでもできるので、すごく便利ですよ!

残っている設定作業はステップが多く時間もかかるものです。誰だって設定作業に時間を取られるのは嫌だし、そんなことするよりも早くコードを書いてファンクションをデプロイしたいですよね……なのでテナンシーでOracle Functionsを使うために必要なステップを全部まとめてシェルスクリプトにしておきました。
ただし、スクリプトに一通り目を通し、何をやっているのかをしっかり理解してからスクリプトを実行するようにしてください。このスクリプトでは、あなたのクラウドテナンシーに以下の変更/追加を加えます:
  1. FaaS専用のコンパートメントを作成
  2. FaaSユーザー用のIAMグループを作成
  3. FaaSユーザーを作成
  4. 後でDockerログインに使うためのユーザー認証トークンを作成
  5. FaaSユーザーをFaaSグループに追加
  6. グループIAMポリシーを作成
  7. VCNを作成
  8. VCN内に3つのサブネットを作成
  9. VCNにインターネットゲートウェイを作成
  10. VCNのルートテーブルをインターネットゲートウェイへのトラフィックを許可するよう更新
  11. VCNのデフォルトトラフィックセキュリティリストを80番ポートのトラフィックを許可するよう更新
  12. 作成した全ての認証情報のサマリを表示
これらのとても多くの作業を通常、コンソールUIから行わなくてはならなくてはなりません。しかしOCI CLIからこのスクリプトを使用することで、30秒で完了することができるのです。スクリプトへのリンクを貼る前に念押ししますが、スクリプトに目を通し、何をしているのか理解してから使ってください。まず最初に、1~20行目に含まれている、作成するオブジェクトの名前と値のところを修正(あるいは少なくとも確認)する必要があります。
ここまでで必要な警告とディスクレイマーは済ませました。スクリプトはここにあります。ダウンロードしたら実行可能かチェックして、実行しましょう。コンパートメントを作成してから他のオブジェクトに利用可能になるまでにはやや時間がかかる関係で、もしかするとVCNを作成するところでいくつか失敗が発生するかもしれません。これは想定されており、そのあたりに自動リトライ処理を入れてあるので問題ないです。スクリプトによってテナンシーでOracle Functionsを使う準備が整い、次のステップに進むことができるようになるでしょう。以下はスクリプトを実行した結果の出力の例です。
Created compartment faas-compartment with ID ocid1.compartment.oc1..[redacted]na
Created group faas-group with ID ocid1.group.oc1..[redacted]vq
Created user faas-user with ID ocid1.user.oc1..[redacted]va
Created Auth Token. Remember this token, it can not be retrieved in the future: ew[redacted]et
Added user faas-user to group faas-group
Action completed. Waiting until the resource has entered state: ACTIVE
Created policy faas-demo-policy. Use the command: 'oci iam policy get --policy-id ocid1.policy.oc1..[redacted]sa' if you want to view the policy.
Creating VCN. This may take a few seconds...
ServiceError:
{
"code": "NotAuthorizedOrNotFound",
"message": "Authorization failed or requested resource not found.",
"opc-request-id": "[redacted]",
"status": 404
}
[create failed, trying again in 10 seconds...]
Created VCN faas-demo-vcn with ID ocid1.vcn.oc1.phx.[redacted]ma
Created subnets: faas-subnet-1, faas-subnet-2, faas-subnet-3
Created internet gateway faas-internet-gateway with ID ocid1.internetgateway.oc1.phx.[redacted]kq
Updated default route table for VCN to allow traffic to internet gateway
Updated default security list to open port 80 for all subnets in VCN
Remember to save the generated auth token:
ew[redacted]et
This token is used for Docker login, with the username [redacted]/faas-user.
Your new compartment ID is ocid1.compartment.oc1..[redacted]na
Your subnet IDs are:
faas-subnet-1: ocid1.subnet.oc1.phx.[redacted]2q
faas-subnet-2: ocid1.subnet.oc1.phx.[redacted]hq
faas-subnet-3:ocid1.subnet.oc1.phx.[redacted]na
Use these subnets for your Fn applications.
Your user ID is: ocid1.user.oc1..[redacted]va
You can use the following profile section to modify your OCI CLI config for use with Fn (you'll need to generate a key and populate the necessary key related items):
[faas]
user=ocid1.user.oc1..[redacted]va
fingerprint=<public-key-fingerprint>
key_file=<private-key-pem-file>
tenancy=[redacted]
region=us-phoenix-1
pass_phrase=<passphrase>
次に、署名鍵を作成しましょう。クイックスタートガイドから引用します:
ここまできてコンソールUIを使うのが面倒だという場合は、以下のようにOCI CLIを使って鍵をアップロードすることもできます:
1
oci iam user api-key upload --user-id ocid1.user.oc1..[redacted]ra --key-file <path-to-key-file> --region <home-region>
次に、OCI CLIの設定ファイル(~/.oci/config)をテキストエディタで開き、上記のスクリプトで生成されたprofileセクションを貼り付け、新しい署名鍵の値で上書きしておきましょう。
ここで、Dockerがあなたのローカル環境にインストール済であることを確認してください。たぶん大丈夫だと思いますが、そうでもなかったらDocker docsを見て自分のプラットフォームに合ったものをインストールしてください。インストールされているかは以下のコマンドで確認しましょう:
1
docker version
では、上記のスクリプトで生成しておいた認証情報でDockerにログインしてみましょう:
1
docker login phx.ocir.io
ユーザー名をスクリプトの出力(<tenency>/<username> の形式)からコピーして使い、生成された認証トークンはDockerログインパスワードとして使用されます。
それではFn CLIをインストールしましょう。GitHubのFn projectに行くとプラットフォームごとのインストール手順が説明されています。うまくいったかどうか確認するには、以下を実行しましょう:
1
fn version
Fn CLIで実行できる全てのコマンドは、command reference docsに説明されています。ブックマークしておくといいでしょうね!
いよいよFnの設定の仕上げにかかりましょう。またFnクイックスタートを参考にします:
Function開発者ユーザーで開発環境にログインして:
以下を入力して新規Fn Project CLIコンテクストを作成します:
1
fn create context <my-context> --provider oracle
以下を入力してFn Project CLIが新しいコンテクストを使用するように指定します:
1
fn use context <my-context>
新しく作ったコンテクストにFunctionsをデプロイしたいコンパートメントのOCIDを設定しましょう:
1
fn update context oracle.compartment-id <compartment-ocid>
新しく作ったコンテクストにFn Project APIを呼ぶ際に使用するapi-urlエンドポイントを設定しましょう:
1
fn update context api-url <api-endpoint>
以下は例です:
1
fn update context api-url https://functions.us-phoenix-1.oraclecloud.com
新しく作ったコンテクストに、DockerレジストリとOracle Functionsと使いたいリポジトリのアドレスを指定しましょう:
1
fn update context registry <region-code>.ocir.io/<tenancy-name>/<repo-name>
以下は例です:
1
fn update context registry phx.ocir.io/acme-dev/acme-repo
新っく作ったコンテクストに、Oracle Functionsを使うために作成しておいたプロファイルを設定しましょう:
1
fn update context oracle.profile <profile-name>
さて、ここまででアプリケーションを作成する準備ができました。Oracle Functionsでは、アプリケーションというのは、共通の設定値のコンテクストを共有しているサーバーレスファンクションのグループのことです。クイックスタートではコンソールUIを使ってアプリケーションを作成する方法が説明されていますが、ここでは引き続きコマンドラインを使って素早く行っていきましょう。以下を実行してアプリケーションを作成します:
1
fn create app faas-demo --annotation oracle.com/oci/subnetIds='["ocid1.subnet.oc1.phx.[redacted]ma"]'
先ほど作成したサブネットIDのうち、少なくともひとつをここのJSON配列に含める必要があります。複数のサブネットを含めておくことで可用性を高められます。アプリケーションを表示するには、以下を実行します:
1
fn list apps
以下を実行してひとつめのファンクションを作成しましょう:
1
fn init --runtime node faas-demo-func-1
この例ではNodeJSを使用していますが、様々なランタイムがサポートされていることは知っておいてください。現時点ではランタイムはGo、Java 8、Java 9、Node、Python 3.6、Python 3.7、Ruby、Kotlinから選ぶことができます。ファンクションが生成されると、以下のような出力が表示されます:
1
2
3
Creating function at: /faas-demo-func-1
Function boilerplate generated.
func.yaml created.
では、新規作成されたディレクトリに行き、生成されたファイルを見てみましょう。func.yamlファイルはFnがプロジェクトやトリガーなどのメタデータ定義のために使用するファイルです。いったんこのYAMLは置いといて、func.jsをテキストエディタで開いてみましょう。以下のようになっているはずです:
1
2
3
4
5
6
7
8
9
const fdk=require('@fnproject/fdk');
fdk.handle(function(input){
  let name = 'World';
  if (input.name) {
    name = input.name;
  }
  return {'message': 'Hello ' + name}
})
シンプルなHello Worldです。しかしあなたは必要に応じてファンクションをパワフルにすることができます。Oracle Cloudの同一サブネット内のDBと接続したりとか、オブジェクトストレージを使用したりとか、様々なことができます。ここではこのファンクションをデプロイして、起動してみましょう。ファンクションのルートディレクトリ(さっきのYAMLファイルがあったところです)で以下のコマンドを実行するとデプロイできます。以下のような出力が表示されるでしょう:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fn deploy --app faas-demo
Deploying faas-demo-func-1 to app: faas-demo
Bumped to version 0.0.2
Building image phx.ocir.io/[redacted]/faas-repo/faas-demo-func-1:0.0.2 .
Parts:  [phx.ocir.io [redacted] faas-repo faas-demo-func-1:0.0.2]
Pushing phx.ocir.io/[redacted]/faas-repo/faas-demo-func-1:0.0.2 to docker registry...The push refers to repository [phx.ocir.io/[redacted]/faas-repo/faas-demo-func-1]
1bf689553076: Pushed
9703c7ab5d87: Pushed
0adc398bfc34: Pushed
0b3e54ee2e85: Pushed
ad77849d4540: Pushed
5bef08742407: Pushed
0.0.2: digest: sha256:94d9590065a319a4bda68e7389b8bab2e8d2eba72bfcbc572baa7ab4bbd858ae size: 1571
Updating function faas-demo-func-1 using image phx.ocir.io/[redacted]/faas-repo/faas-demo-func-1:0.0.2...
Successfully created function: faas-demo-func-1 with phx.ocir.io/[redacted]/faas-repo/faas-demo-func-1:0.0.2
FnによってファンクションがDockerコンテナにコンパイルされ、DockerコンテナがOracle Dockerレジストリにプッシュされ、こうしてファンクションを起動する準備が整いました。では次のコマンドで起動してみましょう(一つ目の引数はアプリケーション名、二つ目はファンクション名です):
1
2
fn invoke faas-demo faas-demo-func-1
{"message":"Hello World"}%
初回の起動はちょっと時間がかかります。というのも、FnがDockerコンテナをpullして立ち上げなければならないからです。なので次からは速くなりますよ。この方法がファンクションを起動する唯一の方法というわけではありません。HTTPエンドポイントに署名を付けてリクエストするなどの方法はありますが、その話題は別のポストにとっておきましょう。
では、アプリケーションの設定変数を追加してみましょう:
1
fn update app faas-demo --config defaultName=Person
前述の通り、設定はアプリケーション内の全てのファンクションで共有されています。あるファンクションから設定変数にアクセスするには、環境変数から取得してきます。例として使っているNodeファンクションを設定変数を使用するように更新し、デプロイして起動してみましょう:
1
2
3
4
5
6
7
8
9
const fdk=require('@fnproject/fdk');
fdk.handle(function(input){
  let name = process.env.defaultName || 'World';
  if (input.name) {
    name = input.name;
  }
  return {'message': 'Hello ' + name}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ fn deploy --app faas-demo
Deploying faas-demo-func-1 to app: faas-demo
Bumped to version 0.0.3
Building image phx.ocir.io/[redacted]/faas-repo/faas-demo-func-1:0.0.3 .
Parts:  [phx.ocir.io [redacted] faas-repo faas-demo-func-1:0.0.3]
Pushing phx.ocir.io/[redacted]/faas-repo/faas-demo-func-1:0.0.3 to docker registry...The push refers to repository [phx.ocir.io/[redacted]/faas-repo/faas-demo-func-1]
7762ea1ed77f: Pushed
1b0d385392d8: Pushed
0adc398bfc34: Layer already exists
0b3e54ee2e85: Layer already exists
ad77849d4540: Layer already exists
5bef08742407: Layer already exists
0.0.3: digest: sha256:c6537183b5b9a7bc2df8a0898fd18e5f73914be115984ea8e102474ccb4126da size: 1571
Updating function faas-demo-func-1 using image phx.ocir.io/[redacted]/faas-repo/faas-demo-func-1:0.0.3...
$ fn invoke faas-demo faas-demo-func-1
{"message":"Hello Person"}%
以上がOracle Functionsでのサーバーレスファンクション開発のスタートガイドの基本的な部分でした。Fnプロジェクトはもっと沢山のガイドを提供しているので、そちらもぜひ読んでみることをおすすめします。もっと深く知りたいという方は、 Limited Availabilityプログラムに登録するのも忘れずに。