nkjmkzk.net

powered by Kazuki Nakajima

Archive for the ‘aws’ tag

CORSサポートを利用したAWS S3へのアップロード方法 – Force.comバージョン

昨年秋にAWS S3はCORSをサポートし、クロスドメインでもjavascriptだけでファイルを容易にアップロードできるようになりました。

CORSとは?についてはクラスメソッドさんのブログで決定版的な詳解がありますのでそちらを参考に。
CORS(Cross-Origin Resource Sharing)について整理してみた

Force.comでも非構造化データはS3にお任せする、というシチュエーションはしばしばあります。そういうケースでS3のCORSに対応したファイルアップロードを実現するVisualforceおよびApexのサンプルコードを作成したので共有しておきます。

Step 1. CORS設定

まず、CORSに対応するバケットを作成しておく必要があります。既存のバケットでも構いません。

AWS Management Consoleにアクセスし、CORS対応させるバケットを選択し、「Properties」タブをクリックします。「Permissions」セクションを展開すると「Edit CORS Configuration」ボタンが現れます。

「Edit CORS Configuration」をクリックするとXMLフォームが開きます。このフォームを下記の通りに設定して保存します。

<CORSConfiguration>
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>PUT</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>Origin</AllowedHeader>
        <AllowedHeader>Content-Type</AllowedHeader>
        <AllowedHeader>x-amz-storage-class</AllowedHeader>
        <AllowedHeader>x-amz-acl</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

このXMLではどのような操作が許可されるかを定義しています。必要に応じて後ほどパラメータを編集するとして、とりあえずはこれで十分です。

 

Step 2. パッケージをSalesforce組織にインストール

サンプルコードはApexクラス、Visualforceコンポーネント・ページ、カスタム設定、カスタムオブジェクトで構成されています。これらをパッケージにまとめてAppExchangeにアップしておきましたのでこちらをインストールしてください。

AWS S3 CORS Uploader

パッケージをインストールしたらアプリケーションの設定 > 開発 > カスタム設定を開き、AWS S3のManageリンクをクリックします。

「新規」ボタンをクリックします。

必須項目のアクセスキー、シークレットアクセスキー、バケット名を入力して保存します。これらの情報はAWS Management Consoleで確認できます。

次に右上のアプリケーションプルダウンメニューからAWS S3 CORS Uploaderを選択します。S3 UploaderとS3 Objectの二つのタブが現れるはずです。S3 Uploaderタブを選択するとシンプルなアップロードフォームが表示されます。


「ファイルを選択」ボタンをクリックして適当なファイルを選択し、「upload」ボタンをクリックして実際にファイルをアップロードしてみてください。JavascriptがダイレクトにファイルをS3にアップロードします。ポップアップが2回表示され、それぞれ「Upload Succeeded」と「Insert Succeeded」と表示されるはずです。

S3のManagement Consoleでファイルがアップロードされたかどうか確認してみてください。また、S3 Objectタブをクリックすると、アップロードしたファイルのURLが記載されたレコードが作成されているはずです。

このサンプルコードでは、JavacriptがまずS3にファイルをアップロードし、その後にForce.comのデータベースにそのファイルに関する情報を記録するようになっているので上記のような挙動になっています。実際のシチュエーションでも何らかの形でS3に格納したオブジェクトの情報をForce.comに記録しておく必要がでてくると思いますので、その際の参考にしていただければ幸いです。

Step 3. サンプルコードの確認

サンプルがどのように動作するのか確認したところでその中身、ソースコードを見ておきましょう。

肝になっているのはApexクラス:aws_s3の中のget_url_for_updoad(string file_name, string file_type)というメソッドです。

@remoteAction
global static r get_url_for_upload(string file_name, string file_type){
    r r = new r();
    r.status = false;
    aws_s3__c s3 = aws_s3__c.getOrgDefaults();

    if (s3.access_key__c == null || s3.secret_access_key__c == null || s3.bucket__c == null){
        r.message = 'Custom Settings has not been configured.';
        return r;
    }

    if (String.isBlank(file_name)){
        r.message = 'file_name is not set.';
        return r;
    }

    string url;

    // This means that users have to start uploading in 600 seconds since they have loaded the page by default.
    integer default_expiration = 600;

    string http_method = 'PUT';
    string content_md5 = '';

    string content_type = '';
    if (String.isBlank(file_type)){
        r.message = 'file_type is not set.';
        return r;
    }
    content_type = file_type.toLowerCase();

    string expiration;
    if (s3.expiration__c == null){
        expiration = string.valueOf((DateTime.now().getTime() / 1000).intValue() + default_expiration);
    } else {
        expiration = string.valueOf((DateTime.now().getTime() / 1000).intValue() + s3.expiration__c.intValue());
    }

    string canonicalized_amz_headers = '';
    if (!String.isBlank(s3.acl__c)){
        if (storage_classes.contains(s3.acl__c.toLowerCase())){
            canonicalized_amz_headers += 'x-amz-acl:' + s3.acl__c.toLowerCase() + '\n';
        } else {
            r.message = 'ACL value is incorrect.';
            return r;
        }
    }
    if (s3.reduced_redundancy__c == true){
        canonicalized_amz_headers += 'x-amz-storage-class:REDUCED_REDUNDANCY' + '\n';
    }

    string canonicalized_resource;
    if (s3.folder__c == null){
        canonicalized_resource = '/' + s3.bucket__c + '/' + file_name;
    } else {
        canonicalized_resource = '/' + s3.bucket__c + '/' + s3.folder__c.removeStart('/').removeEnd('/') + '/' + file_name;
    }
    string string_to_sign = 
        http_method + '\n' +
        content_md5 + '\n' +
        content_type + '\n' + 
        expiration + '\n' + 
        canonicalized_amz_headers + canonicalized_resource;
    system.debug('string_to_sign = ' + string_to_sign);
    string signature = EncodingUtil.urlEncode(EncodingUtil.base64Encode(Crypto.generateMac('hmacSHA1', blob.valueOf(string_to_sign), blob.valueOf(s3.secret_access_key__c))), 'UTF-8');
    string path = '/';
    if (s3.folder__c != null){
        path += s3.folder__c.removeStart('/').removeEnd('/') + '/';
    }
    url = 'https://' + s3.bucket__c + '.s3.amazonaws.com' + path + file_name + '?AWSAccessKeyId=' + s3.access_key__c + '&Signature=' + signature + '&Expires=' + expiration;

    r.status = true;
    r.message = url;
    return r;
}

S3へのアップロードはS3のREST APIにアクセスしているのですが、当然アクセス先のURLが必要になります。そのURLを生成しているのがこのメソッドです。

URLは下記のような構造になっています。

https://[バケット名].s3.amazonaws.com/[バケットを除くファイルへのパス]?AWSAccessKeyId=[アクセスキー]&Signature=[シグネチャー]&Expires=[シグネチャの有効期限]

他のフォーマットもありますが、話を簡単にするためにそこは省略します。

この中で特に生成が難しいのがシグネチャーです。

シグネチャーは下記のフォーマットの文字列をシークレットアクセスキーを鍵にしてHMAC-SHA1のアルゴリズムでハッシュ化し、それをBase64エンコードし、さらにURL用にエンコードしたものになります。

[HTTP Method]\n
[Content-MD5]\n
[Content-Type]\n
[Expiration]\n
[canonicalized-amz-headers]
[canonicalized-amz-resources]

このフォーマットについてさらに詳しく知りたい方はS3の開発者ガイドのこちらのチャプターを参照ください。
REST リクエストの署名と認証

前述のget_url_for_upload()はこの面倒な作業をおこなっているメソッドです。カスタム設定であらかじめセットしたAWSの鍵情報、バケット名と、ユーザーがアップロード用に選択したファイルからこのURLを生成しています。

このURLさえあればあとは簡単です。Visualforceコンポーネント:S3 Uploaderをみてみましょう。

<apex:component controller="aws_s3">
<script>
function s3_upload_file(){
    var file = document.getElementById('s3_file_for_upload').files[0];

    aws_s3.get_url_for_upload(
        file.name,
        file.type,
        function(result, event){
            console.dir(event);
            console.dir(result);
            if (event.status == false){
                alert(event.message);
                return;
            }
            if (result.status == false){
                alert(result.message);
                return
            }
            url = result.message;
            var xhr = new XMLHttpRequest();
            xhr.onload = function(event){
                // You can replace this code to execute your code on upload success.
                console.dir(event);

                if (event.target.status == '200'){
                    alert("Upload Succeeded");
                } else {
                    alert("Upload Failed: " + event.target.statusText);
                    return;
                }
                aws_s3.insert_s3_object(
                    url,
                    function(result, event){
                        console.dir(event);
                        console.dir(result);
                        if (event.status == false){
                            alert(event.message);
                            return;
                        }
                        if (result.status == false){
                            alert(result.message);
                            return
                        }
                        alert("Insert Succeeded.");
                    },
                    {escape:true}
                );
            }
            xhr.open('PUT', url, true);

            // set Content-Type
            xhr.setRequestHeader('Content-Type', file.type);

            // set ACL
            var acl = "{!JSENCODE(config.acl__c)}";
            if (acl != ""){
                xhr.setRequestHeader('x-amz-acl', acl.toLowerCase());
            }

            // set REDUCED_REDUNDANCY
            if ({!config.reduced_redundancy__c} == true){
                xhr.setRequestHeader('x-amz-storage-class','REDUCED_REDUNDANCY');
            }

            xhr.send(file);
        },
        {escape:false}
    );
}
</script>
<input type="file" id="s3_file_for_upload" />
<button onclick="s3_upload_file();">upload</button>
</apex:component>

このコンポーネントはコントローラーとして、get_url_for_upload()メソッドを含むaws_s3を指定しています。

そしてget_url_for_upload()メソッドはJavascript RemotingによってJavascriptから呼び出せるようになっているので、ユーザーがuploadボタンを押した際にaws_s3.get_url_for_upload(ファイル情報とコールバックメソッド)としてget_url_for_upload()メソッドを実行しています。

そしてURLが取得できた後に実行されるコールバックメソッドの中では一般的なXMLHttpRequestオブジェクトを生成し、生成されたURLをもってS3のREST APIにアクセスしています。その際、Content-Type, x-amz-storage-class, x-amz-storage-class等のリクエストヘッダーを必要に応じて付与しています。

そしてさらにこのAPIアクセスのコールバックとして、Force.comデータベースにオブジェクト情報を記録するためのメソッド、aws_s3.insert_s3_object()を実行しています。こちらもJavascript Remotingのメソッドとして、aws_s3クラスの中に定義されているものです。

このコンポーネントの中で実行しているaler()やinsert_s3_object()を実より現実的な処理に置き換えていけば、自身のアプリの中にうまくアップロード処理を組み込めるのではないかと思います。

また、カスタム設定の中にストレージの冗長性を指定するReduced Redundancyや、フォルダ、そして重要なファイルのパーミッションを指定するアクセス制御等の項目を入れてあります。これらの項目をセットすることでオブジェクト格納時のメタ情報を制御することができます。動作を試していただいて、必要に応じてカスタマイズしてみてください。

グッドラック。

without comments

Written by 中嶋 一樹

5月 8th, 2013 at 6:34 pm

Posted in Uncategorized

Tagged with , , , ,

Transloaditを使ってSalesforceから透過的にファイルをAmazon S3にアップロードする

SalesforceにはAttachmentやFilesといったファイル格納機構があります。ただ、そのファイルを外部公開する(認証不要でアクセス可とする)のは少し厄介です。そういう要件がある場合は素直にAmazon S3等にアップした方がよいケースもあるでしょう。

そんなアーキテクチャーでも、ユーザーにはSalesforceを使いながら意識させずにS3にアップロードするような実装をしたいものです。また、アップロードのコードも出来る限りさぼって書きたいですよね。

アップローダーとして使えそうなツールやサービスをいろいろ見ていると、UploadifyPluploadなどがあるなー、と。結果的に私はTransloaditというサービスを使ってみました。

Transloaditは単なるアップロードツールやWidgetという域にとどまらず、画像や動画のエンコーディングという中間処理を得意とするサービスです。そしてもちろんアップロードのためのUIもjQuery Pluginとして提供してくれています。使用感はこちらの動画で確認してみてください。

実際、クロスブラウザ対応などを含め、ファイルのアップロードというのはなにかと問題が発生する意外に難しい処理です。Transloaditはそのあたりのクライアント側の制御をjQuery Pluginを提供することで開発者から解放しつつ、その後の処理もクライアントとファイル格納先(S3等)の中間に入って動作することでお任せすることができるというサービスです。

S3にファイルをアップロードするときにTransloaditはリバースプロキシのような位置づけで機能します。クライアントはjQuery Pluginを使ってファイルをTransloaditにアップロードし、アップロードされたファイルは事前に定義されたTemplateに従って処理されます。最終格納場所(S3)にファイルが保存された後にクライアントはTransloaditからJSONレスポンスでファイルのメタデータを受け取ります。上のデモ動画では、このメタデータからファイルのURLを取得してSalesforceのフィールドに保存しています。

Transloaditのサイトにもこのアップローダーの構築方法が書かれていますが、ここでも簡単に解説しておきます。

まずアカウントを作成します。Transloaditは従量課金の有料サービスですが、100MB/月までは無料で利用できます。

次にTemplateを作成します。Templateはアップロードするファイルをどの順番で、どんな処理をおこなうかを記述したファイルです。これはTransloaditの管理画面から作成することができます。上のデモ動画で定義しているTemplateは下記の通りです。

{
  "steps": {
    "store": {
      "robot": "/s3/store",
      "key": "あなたのAWS KEY",
      "secret": "あなたのAWS SECRET",
      "bucket": "nkjm-sfdc-tokyo"
    }
  }
}

次にアップロードフォームを作成します。これはVisualforceで作成することになります。

<form id="MyForm" action="http://api2.transloadit.com/assemblies" enctype="multipart/form-data" method="POST">
    <input type="hidden" name="params" value='{"auth":{"key":"あなたのAPI KEY"},"template_id":"あなたのTemplate ID","redirect_url":"{!$CurrentPage.URL}"}'></input>
    <input type="file" name="my_file"></input>
    <input type="submit" value="Upload"></input>
</form>

次に同じVisulaforceページにアップローダーとなるjQuery Pluginを追加します。

<apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" />
<apex:includeScript value="https://assets.transloadit.com/js/jquery.transloadit2.js" />

<script type="text/javascript">
   // We call .transloadit() after the DOM is initialized:
   j$ = jQuery.noConflict();
   j$(document).ready(function() {
     j$('#MyForm').transloadit({
        wait: true
     });
   });
</script>

次にファイルのアップロードが完了した際にJSONレスポンスを解析して必要な情報をデータベースに保存するApexクラスを作成します。

public class transloadit_uploader {
    public final product__c product;

    public transloadit_uploader(ApexPages.StandardController controller){
      product__c p = (product__c)controller.getRecord();
      if (p.id != null){
          this.product = [select id, name, price__c, code__c, discount_rate__c, photo_url__c, url_to_buy__c, description__c from product__c where id = :p.id];
      }
    }

    public void update_photo_url(){
        string s3_url;
        if (ApexPages.currentPage().getParameters().get('transloadit') != null){
            string result_json = ApexPages.currentPage().getParameters().get('transloadit');
            JSONParser parser = JSON.createParser(result_json);
            while (parser.nextToken() != null) {
                if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) && (parser.getText() == 'url')) {
                    parser.nextToken();
                    if (parser.getText().contains('s3.amazonaws.com')){
                        s3_url = parser.getText();
                    }
                }
            }
        }
        if (s3_url != null){
            this.product.photo_url__c = s3_url;
            update this.product;
        }
    }
}

最後に、先ほどのVisualforceページに、上記のApexクラスのupdate_photo_url()を最初にキックするように<apex:page>タグにaction=”{!update_photo_url}”を追加します。

<apex:page standardController="sugoidiscount__product__c" extensions="sugoidiscount.transloadit_uploader" action="{!update_photo_url}">

最終的にデモのVisualforceページは下記のようになります。

<apex:page standardController="sugoidiscount__product__c" extensions="sugoidiscount.transloadit_uploader" action="{!update_photo_url}">
<apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" />
<apex:includeScript value="https://assets.transloadit.com/js/jquery.transloadit2.js" />

<script type="text/javascript">
   // We call .transloadit() after the DOM is initialized:
   j$ = jQuery.noConflict();
   j$(document).ready(function() {
     j$('#MyForm').transloadit({
        wait: true
     });
   });
</script>

<apex:detail />

<apex:pageBlock title="{!$Label.sugoidiscount__upload_photo}" mode="edit">
    <apex:pageBlockSection >
        <form id="MyForm" action="http://api2.transloadit.com/assemblies" enctype="multipart/form-data" method="POST">
            <input type="hidden" name="params" value='{"auth":{"key":"あなたのAPI KEY"},"template_id":"あなたのTemplate ID","redirect_url":"{!$CurrentPage.URL}"}'></input>
            <input type="file" name="my_file"></input>
            <input type="submit" value="Upload"></input>
        </form>
    </apex:pageBlockSection>
    <apex:pageBlockSection >
        <apex:outputpanel id="product_photo" rendered="{! !ISNULL(photo_url)}">
            <img height="200px" src="{!sugoidiscount__product__c.sugoidiscount__photo_url__c}" />
        </apex:outputpanel>
    </apex:pageBlockSection>
</apex:pageBlock>
</apex:page>

エンジョイ。

without comments

Written by 中嶋 一樹

10月 11th, 2012 at 11:58 am

Database.comの魅力に迫る – Salesforce.comとAWSによるECO-SYSTEM

Salesforce.comとAWSの連携といえば、Force.comからS3を拡張ストレージとして使うようなインテグレーションはしばしば用いられてきました。

しかしDatabase.comの登場により、それとはまったく逆の方向で両クラウドサービスをインテグレートする用法が見えてきています。ここではその連携アーキテクチャについてお話します。

Salesforce.comはApex、Visualforceという独自言語を提供しながらも、Open Developmentというエリアを真剣に考えており、その最たるアプローチがDatabase.comです。

Database.comはForce.comのハートであるデータベース機能だけを切り出して単独で提供しているものです。課金体系もForce.comのユーザー単位に加え、データ容量やトランザクション量での従量課金を取り入れています。

Database.comはSalesforce.comが十年以上にもわたって磨き上げてきたデータベースプラットフォームをOpen Developerに開放するものです。Open DeveloperはRuby, PHP, Python, Java, Node.js, Clojure等、各々が得意なプログラミング言語からDatabase.comを利用することができます。

AWSではEC2という仮想マシンサービスが長らく提供されており、ユーザーはクラウド上で即座にOS環境を整え、任意のプログラミング言語の実行環境を自由に構築できます。このような環境で利用するデータベースとして、Database.comというのは魅力的な選択肢となるはずです。

では、Open DeveloperがDatabase.comを利用するメリットとはどのようなものなのか? 僕は次の2点にそのメリットを集約してみます。

メリット1:データベース運用からおさらば

データベースはほぼすべてのアプリケーションに必須のコンポーネントです。Open Developerの中には自身でアプリケーションに必要なデータベースを構築、運用することができる人たちがいるでしょう。あるいはアプリケーション開発会社であればデータベースを担当するインフラ部門があるかもしれません。

ただし、僕が思うにデータベースの独自運用は価値を生みません。

データベースの仕事は、常に十分な速度で安定してアプリケーションからの問い合わせに応答する、というシンプルなものです。しかし、この要件を満たすために必要な労力は一体どれほどのものでしょうか。データベースの設定項目はそれだけで辞書にできるほど多く、スケーラビリティや耐障害性を確保するのに極めて複雑な実装が余儀なくされます。

世の中には様々なスキルレベルのデータベースエンジニアが日々データベースに向き合っています。その中には上記の要件をかなり高いレベルで実装できるエンジニアもいるでしょう。

ただし、上には上がいます。

この「上」の最たる例が「クラウド」だと思います。僕の定義ではクラウドというのはノウハウの共有であり、ノウハウの開放です。

参考:オレ流クラウドの定義

自社サービスを長年に渡り提供し続けてきたサービスプロバイダーは、その歴史が長いほど、ビジネスボリュームが大きいほど、重要な経験、つまりノウハウを蓄積しており、そのインフラに研究と改善を重ねています。

この長年の経験に裏打ちされたインフラのレベルは一朝一夕で到達できるようなものではなく、かつ、大きな投資をおこなってデータベースプラットフォームを独自に構築したとしても、それはアプリケーションから見れば「当たり前の仕事をしている」に過ぎません。いくらこのレイヤーに投資しても決して自社のアプリケーション、サービスに差別化要素をもたらすことはできないでしょう。それより、磨き上げられたデータベースサービスがオンラインでサインアップするだけで使える時代なのです。これを利用しない手はないでしょう。

Database.comは誰でもすぐにサインアップして利用することができます。無料枠があるので、試用するのに費用はかかりません。

今すぐサインップするにはこちらから。

メリット2:REST API

単にマネージド・データベースというくくりであればまだDatabase.comでなければならない理由にはなりません。マネージド・データベースはDatabase.com以外にも存在します。その中でもDatabase.comをユニークにする要素は何なのか。

僕はその要素にREST APIを挙げたい。

データベースはForce.comのハートだと書きました。それは何故か?Force.comまたはDatabase.comではデータモデル(つまりテーブル。Force.com用語ではオブジェクト)を定義するだけでプログラミングの基礎部分が終わってしまうという特徴があります。テーブルを作成するとそのテーブルに対するデータの挿入、更新、削除を行うメソッドは自動的に作成され、開発者がテーブル毎にメソッドをコーディングする必要はありません。それだけでなく、テーブルを作成しただけでそのテーブルに対するREST APIまでもが自動的に生成されます。つまり、テーブルを作成した時点で、そしてまたカラムを追加した時点で、そのデータ構造に対するデータ挿入、更新、削除、検索がREST APIを通じておこなえるのです。

このことは特にHTML5アプリを開発する上で大きなアドバンテージになるでしょう。

HTML5アプリとはHTML5規格にのっとってコーディングされたHTML, CSS, JavaScriptによるユーザーインターフェースを持つアプリを指すアプリの緩い定義。一般的にHTML5アプリはWebサーバーからダウンロードしたHTMLでダイナミックなユーザーインターフェースを表現し、Ajaxによってサーバーと通信を行います。

AjaxはサーバーからダウンロードされたローカルのJavaScriptによってキックされます。JavaScriptはユーザーの操作によって特定のイベントで発火し、バックグラウンドでサーバーへリクエスト・データを送る、またはサーバーからデータを取得します。

このHTML5アプリの構造で必要になるプログラムコンポーネントは一般的なWeb/データベースサーバーのアーキテクチャでは下図のようになるでしょう。

  • HTML – ユーザーインターフェースを構成するのに必要
  • Web API Class – JavaScriptからのAjaxリクエストを受け付けるのに必要
  • DB Class – AjaxリクエストをDBへのリクエストへ変換しSQLを発行するのに必要

一方、Database.comを擁するHTML5アプリに必要なプログラムコンポーネントは下図のようになります。

 

HTMLは依然としてコーディングする必要があるものの、JavaScriptから発行されるAjaxリクエストはDatabase.comが直接受け付けて処理できるため、Web API ClassとDB Classが不要になります。したがって開発者は基本的なメソッドを自身でコーディングする必要がなく、ユーザーの使い勝手を向上させるためのインターフェースやアプリの差別化に直結するコア機能の開発に集中して時間を費やすことができます。

さらにDatabase.comにアクセスするJavaScriptのコードも、いちから書き上げる必要はありません。Salesforce.comではForce.com JavaScript REST Toolkitなるものを提供しています。このJavaScriptライブラリをロードすれば、create(), update(), delete()といったより抽象化された手続きでDatabase.comにアクセスすることができます。

なお、Database.comではデータモデルを作成した際に自動生成されるAPIのほか、より複雑な処理が必要な場合は独自にAPIを拡張することも可能です。

したがってDatabase.comではデータモデルを定義するだけで多くの開発タスクが自動的に完了してしまいます。データモデルを定義するのが数少ない作業ではありますが、実はこのデータモデル定義作業もDatabase.comでは楽しい。

新機能のスキーマビルダーを使えばドラッグ&ドロップでテーブルを作成し、同様にドラッグ&ドロップで適宜カラムを追加することができます。未だPilot扱いの機能なのでページレイアウトが自動更新されない等、まだ至らない点はあるのですが、直感的な操作でデータモデル定義をEnjoyできます。

リレーションを張った場合はそのつながりも視覚的に確認することができ、手作業でER図を作成する必要はもうありません。

このDatabase.com、先日開通した東京データセンターでも稼働しているためAWSの東京リージョンとも極めて低いレイテンシーで通信できます。まさに今すぐ利用できる環境にありますゆえ、一度サインアップして操作画面だけでものぞいてみてみてはどうでしょうか。今回ご紹介したメリット2点以外にも、地味に便利な機能がふんだんに搭載されていますよ。

まとめ

Database.comを利用することで開発者は、

  • 厄介なわりに差別化要素とならないデータベース運用から解放される。
  • REST APIの自動生成により(特に)HTML5アプリ開発が加速する。
  • 美しいUIで作業がなんだか楽しくなってくる。

 

*ちなみに、現在Salesforce.comではDeveloper Communityをすごい勢いでつなげ、技術情報を交換する環境を広げていきたいと考えています。まずはFacebookページをLike! オンラインで、オフラインでつながりましょう。近々オフラインで集会(飲み会)したいと思っています。

http://www.facebook.com/developerforcejapan

without comments

Written by 中嶋 一樹

3月 5th, 2012 at 4:39 pm

Posted in Uncategorized

Tagged with , , , ,

EC2でOracleのバックアップサイトを構築しマルチサイト運用を実現する

言わずもがな日本に大きなインシデントがあり、ITシステムにもシステム構成に変化が起きようとしているのを感じます。マルチサイト運用の必要性です。

  • 例えデータセンターであっても一カ所にデータ・システムを置いておくことへの危機感
  • 地理的な事情によって停電・節電でシステムの継続運用が難しくなっている状況
  • 長期的な影響が見込まれるなかで、サイトの移転を検討(移転先でも一カ所での運用は避けたい)

システムをメインサイトからバックアップサイトへと軽やかに切り替えるような仕組みがあれば、と思います。しかし切り替えたいと思い立ってすぐに切り替えられるものではありません。物理的にどうやってもすぐには移せないのは大量のデータです。100TBのデータを夕方までにアメリカに移したい!と思っても時既に遅し、です。高速ネットワークをもってしも、物流をもってしても不可能です。

なのでサイトを軽やかに切り替えるにはデータはあらかじめコピーしておき、その後継続的に同期し続けることが必要になります。つまりマルチサイト運用に不可欠な要素は「データ同期」と「切り替えの仕組み」だと考えています。

また、不可欠ではないものの、現実的な導入にあたってはコストの壁をクリアする必要があります。災害対策というのは皆必要性は認識しつつも、インシデント発生確率に対してかかる費用があまりに大きいため、多くのプロジェクトでは先送りされる項目でしょう。しかし今実際にインシデントが発生し、脅威はリアルになっています。そんな中、このコストの壁を乗り越えるためのソリューションが仮想サイト、つまりパブリッククラウドだと考えています。

まとめると、僕はマルチサイト運用を実現するには非常に重要な3つの要素があると整理しています。

マルチサイト運用に重要な3つの要素

  • データ同期
  • 切り替え
  • 仮想サイト

僕はすでに起こってしまった被害を復旧するような危機管理ソリューションをOracle製品に見い出すのは難しいと考えていますが、これから起こる事態に備えるリスク管理ソリューションをより現実的な形でパワフルに提案することはできると考えており、それに当面心血を注ごうと考えています。

それがEC2とOracle Databaseのレプリケーション機能(Data Guard)を組み合わせたバックアップサイトの構築です。

データ同期

Data Guardはデータベースをリアルタイムにレプリケートするための機能で、まさに今利用しているメインサイトのデータベースを、リモートのバックアップサイトに同期させるにうってつけの製品です。

切り替え

また、Data Guardは軽やかな切り替え機能を装備しています。不可避な停電に際し意図的にシステムをバックアップサイトに切り替え、そしてまたメインサイトに切り戻すことができます。必要に応じてシステムを稼動させるサイトを選択することができるのです。

仮想サイト

そしてこの構成を現実的にするのが仮想バックアップサイトであるパブリッククラウドです。特にEC2であれば世界中からバックアップサイトをクリック一つで選択し、スタンバイデータベースを作成することができます。しかもこれまでもっとも大きな障壁であったサーバ、ストレージ等をもう1セット購入するという初期設備導入費用「ゼロ」で。これは明らかにブレークスルーです。レプリケーション機能とパブリッククラウドが特に相性が良いことを示すユースケースの一つでしょう。

Data Guardとパブリッククラウドを組み合わせたバックアップサイト構成には下記のようなメリットがあります。

  • なんと言ってもバックアップサイトのH/W設備投資がゼロ。
  • 状況に応じてアクティブなサイトを切り替えられる。バックアップサイトでもすでに全プロセスが起動してスタンバっているため切り替えも高速。
  • 同期には低負荷のREDOログ転送が用いられるが、さらにこれを圧縮転送することが可能なため回線負荷を低減できる。
  • メインサイトでブロック破損が発生してしまった場合、バックアップサイトから正常なブロックが透過的に取得されて自動修復される。
  • 同期の中断/再開が可能なためインスタンスを必要最低限の時間だけ起動するといった鬼節約が可能
  • あくまでもバックアップサイトにパブリッククラウドを適用するため、未だパブリッククラウドを信用できないでいる人にも敷居が低い。(実際には僕は可用性はともかく、データの保全性はローカルサイトにユーザが構築するストレージよりも相当高いと思います。そういう意味でも適した使い方。)

グランドデザイン

しかしサイトごと切り替えるとなると、データベースだけ切り替えても目的は達成できません。関連するアプリケーションサーバも連動して切り替え、システムを利用するクライアントからのトラフィックを適切にルーティングする必要があります。

システム構成は環境によって多岐に渡るため決定版的な構成を提唱するのは難しいですが、データベースとアプリケーションサーバ、そしてユーザからのトラフィックが切り替える対象であると仮定すると次のようなアーキテクチャが考えられます。

  • データベースはData Guardによってレプリケート&切り替え。
  • アプリケーションサーバは同構成をバックアップサイトにあらかじめ用意し、コンテンツの更新が発生する場合はコンテンツをACFS(ASMクラスターファイルシステム)に格納してACFSのレプリケーション機能を擁してバックアップサイトのアプリケーションサーバへ同期する。
  • ユーザからのトラフィックは、社内DNSレコードを更新することによって、該当ドメインをバックアップサイトのIPアドレス体系に書き換える。DNSレコードの更新は、DNSをAWSが提供するRoute 53にしておくことでAPIを通じてデータベースとアプリケーションサーバの切り替えと連動する形で自動実行させることができる。インターネットではDNSレコードは伝播遅延が懸念されるが、社内用DNSであれば階層構造をとらなければクライアントに依らずリアルタイムに切り替えが行われる。

・通常時のトラフィック

 

・メインサイト停止時のトラフィック

可及的速やかにこのような対応を行う必要がある方、ご連絡ください。出来ること、出来ないことがありますが、全力でサポートさせていただきます。

kazuki.nakajima@oracle.com

 

without comments

Written by 中嶋 一樹

4月 7th, 2011 at 4:17 pm

Posted in Uncategorized

Tagged with , ,

EC2上のLinuxでOracleをインストールする時の注意:DHCP対応

EC2は現在固定IPをサポートしていません。

Elastic IPを割り当てればGlobal IPは固定にできますが、そのアドレスはOSに割り当てられてはおらず、NATされてOSにルーティングされてきます。そしてOSに直接割り当てられているのは常にPrivateアドレスであり、DHCPによって動的に割り当てられます。このPrivateアドレスを固定化することは現在できないようです。

ここで注意しなければいけないのはOracle(Grid InfrastructureまたはDatabase)をインストールするときのホスト名です。デフォルトではホスト名は割り当てられたPrivateアドレスを元に生成されます。つまり一旦停止して再度起動した場合にはホスト名が変わってしまいます。Oracleはホスト名をアプリケーションの設定に静的に組み込み、そのホスト名を解決して通信用ソケットを作成します。なのでこれが変わってしまうとそのままでは起動できなくなります。そしてホスト名だけ固定しても一旦インスタンスを停止してしまうと、次回起動時には十中八九同じPrivateアドレスは割り当てられません。したがってホスト名は固定にしながらも、動的に割り当てられるPrivateアドレスに都度正しく解決できるようしてやる必要があります。

僕は下記のような仕組みを作ってみました。

まず/etc/sysconfig/networkにてホスト名を静的に設定。

[root@ec2-nkjm]# vi /etc/sysconfig/network
NETWORKING=yes
NETWORKING_IPV6=no
HOSTNAME=ec2-nkjm

/etc/hostsの元となるファイルを作成。

[root@ec2-nkjm]# vi /etc/sysconfig/hosts.template
127.0.0.1       localhost.localdomain   localhost
::1     localhost6.localdomain6 localhost6

起動時に割り当てられたPrivateアドレスを元に/etc/hostsを都度生成するスクリプトを/etc/rc.localに挿入。

[root@ec2-nkjm]# vi /etc/rc.local
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.

touch /var/lock/subsys/local

PRIV_IP=`curl curl http://169.254.169.254/latest/meta-data/local-ipv4`
cp -f /etc/sysconfig/hosts.template /etc/hosts
echo "$PRIV_IP    $(hostname)" >> /etc/hosts

これでうまく動いています。もっといい方法もありそうですがとりあえずこれでやり過ごせそうです。

*ちなみに一度インスタンスを停止するとElastic IPも割り当てがはずれてしまいますので再度Assosicateする必要があります。

without comments

Written by 中嶋 一樹

3月 22nd, 2011 at 11:56 pm

Posted in Uncategorized

Tagged with , ,

EC2でEBSベースのAMIをRegion間移行する方法

EC2をしばらく使っていると、クラウドといえどRegionというのはかなりハードなパーティションであることがわかります。あるRegionで作成したSnapshot, Volume, AMI, InstanceはそのRegionでしか利用することができませんし、Region間通信にPrivateセグメントは利用できません。

S3ベースのAMIに関してはRegion間移行するためのAPIが用意されているのですが、EBSベースのAMIについてはRegion間移行を行う手段は提供されていません。つまり、例えばUS Eastで作成したAMIをAP North Eastでも使えるようにしたい場合にそれを簡単に実現するためのツールがないということです。Amazonさんの勢いからするとその内ec2-migrate-imageがEBSもサポートしそうな気もしないでもないのですが、まさに今時点でこのEBSベースのAMIをRegion間移行を手動で行う方法を見ていきたいと思います。

*AWS Management Consoleで行える作業でについては詳細な画面操作は割愛します。

移行先Regionでの作業

  • まず移行元AMIのEBSボリュームと同じサイズでボリュームを作成します。
  • なんでもいいのでLinuxインスタンスをLaunchします。ここではAmazon Linux AMI 64bitを使うこととします。
  • 先ほど作成した空のEBSボリュームをインスタンスにattachします。ここでは/dev/sdfとしてattachすることとします。
  • インスタンスにログインし、ec2-userのパスワードを設定します。
  • あと、セキュリティグループでこのインスタンスに対してSSH接続ができるように設定しておきます。

 

移行元Regionでの作業

  • 移行したいAMIのEBSボリュームのSnapshotを作成します。
  • このSnapshotからボリュームを作成します。
  • なんでもいいのでLinuxインスタンスをLaunchします。ここではAmazon Linux AMI 64bitを使うこととします。
  • このインスタンスに先程作成したボリュームをattachします。ここでは/dev/sdfとしてattachすることとします。
  • インスタンスにログインし、下記のddコマンドで/dev/sdfの情報を吸い上げながらそれをSSH経由で移行先インスタンスに送信して同じくddで書き出します。EBSボリュームのサイズにもよりますがそれなりに時間がかかります。僕が実施したときの実績では転送スピードは1.4MB/sくらいでしたのでそれを目安に計算してください。なお、screenで作業する等して、もしセッションが切れても泣かないようにしてのぞみましょう。
[ec2-user@sender]$ sudo dd if=/dev/sdf | ssh [移行先RegionのインスタンスのIP] sudo dd of=/dev/sdf

 

再び移行先Regionでの作業

  • インスタンスを停止します。
  • EBSボリュームをインスタンスからdetachします。
  • EBSボリュームのSnapshotを作成します。
  • ec2-registerコマンドで、作成したSnapshotからAMIを登録・作成します。このとき、–kernelパラメータや–ramdiskパラメータに注意してください。これらのオプションに渡す値はRegionで異なります。これはkernelイメージやramdiskイメージもRegion毎に管理されているため、別Regionのイメージを指定することはできないからです。僕はUser Provided Kernelを使用するため、今回の移行先Region (AP North East)でそれに応じたAKIとなるaki-d409a2d5を指定しました。
[nkjm@mac]$ ec2-register -n 'Oracle Linux 5.6 64bit customized by nkjm' -d 'Oracle Linux optimized for Grid Infrastructure and Oracle Database' --root-device-name /dev/sda1 -b /dev/sda1=snap-215ef049 -a x86_64 --kernel aki-d409a2d5

これでAMIの移行は完了です。

without comments

Written by 中嶋 一樹

3月 20th, 2011 at 10:18 pm

Posted in Uncategorized

Tagged with , ,

EC2のTokyo RegionでOracle Linux AMIを公開しました

先日US East (Virginia)で作成・公開したカスタムOracle Linux AMIですが、AP North East (Tokyo)でも公開しました。モノは全く同じで、Grid InfrastructureやOracle Databaseの検証を行うのに適したミニマムOSです。*2011.04.06 updated

AMI ID: ami-6ac2686b
Name: Oracle Linux 5.6 64bit customized by nkjm
Region: AP North East (Tokyo)

やはり検証作業時、特にターミナルでの作業時にはレイテンシーの影響が大きいので日本で使っていただく際にはTokyo Regionが望ましいでしょう。はっきりと体感速度が違います。また、Tokyo RegionではまだOracleから公式なAMIを提供できていません(今日現在、Communitiy AMIsで「oracle」と検索いただければ今回僕が公開したものしか出てきません)。

なのでご入用の際にはこちらをご利用あそばせ。

with one comment

Written by 中嶋 一樹

3月 20th, 2011 at 12:45 pm

Posted in Uncategorized

Tagged with ,

EC2: Tokyo Region (AP North East)でのUser Provided Kernel用のAKI

先日ポストしたこちらのエントリで紹介しているPDFにはTokyo RegionでUser Provided Kernelを使用するためのAKIがまだ記載されていませんので下記にリストしておきます。

IMAGE aki-d609a2d7 ec2-public-images-ap-northeast-1/pv-grub-hd00-V1.01-i386.gz.manifest.xml
IMAGE aki-d809a2d9 ec2-public-images-ap-northeast-1/pv-grub-hd00-V1.01-x86_64.gz.manifest.xml
IMAGE aki-d209a2d3 ec2-public-images-ap-northeast-1/pv-grub-hd0-V1.01-i386.gz.manifest.xml
IMAGE aki-d409a2d5 ec2-public-images-ap-northeast-1/pv-grub-hd0-V1.01-x86_64.gz.manifest.xml

ちなみにこのリストは下記のコマンドで取得できます。

[nkjm@mac]$ export EC2_URL=https://ec2.ap-northeast-1.amazonaws.com
[nkjm@mac]$ ec2-describe-images -o amazon --filter "image-type=kernel"

without comments

Written by 中嶋 一樹

3月 20th, 2011 at 12:08 pm

Posted in Uncategorized

Tagged with ,

EC2上でカスタムOracle Linux AMIを作成する・その全工程

Oracleが提供しているOracle Linux 5.5 64bit AMIにいくつかカスタマイズを行ってオリジナルAMIを作成しました。このオリジナルAMIは僕が普段から検証でよく使っている構成で、Storage GRIDを構成するためのGrid InfrastructureやOracle Databaseをスポーンとインストールすることができるミニマムな環境になります。今回はその全行程を紹介します。

ベースとなるAMI: ami-09d43a60から新しいインスタンスを作成します。また、同時にボリュームサイズをデフォルトの10Gbyteから26Gbyteに拡張しておきます。

[nkjm@mac]$ ec2-run-instances ami-09d43a60 -t t1.micro -b /dev/sda1=snap-bedb19d6:26 -k nkjmkey --ramdisk ari-25d43a4c --kernel aki-23d43a4a

インスタンスにログインします。

[nkjm@mac]$ ssh -l root -i nkjmkey.pem ec2-50-17-122-234.compute-1.amazonaws.com

ボリュームサイズ(このインスタンスではブロックデバイスのパーティションに相当)に合わせてファイルシステムを拡張します。

[root@rc1]# resize2fs /dev/sda1

タイムゾーンをJSTに合わせます。

[root@rc1]# rm /etc/localtime
[root@rc1]# cp /usr/share/zoneinfo/Japan /etc/localtime

不要なサービスを停止します。

[root@rc1]# for i in ip6tables iptables mcstrans isdn auditd restorecond portmap nfslock mdmonitor rpcidmapd rpcgssd setroubleshoot o2cb bluetooth netfs ocfs2 pcscd acpid hidd autofs oracleasm hplip cups xinetd sendmail gpm xfs rhnsd
do
    chkconfig $i off
done

不要なパッケージグループを削除してミニマム化を図ります。

[root@rc1]# yum groupremove 'Games and Entertainment' 'Graphics' 'Graphical Internet' 'Mail Server' 'Office/Productivity' 'Printing Support' 'Sound and Video'

最新のYumレポジトリ情報をインストールし、OS全体をアップデートします。また、その後恐らく何らかの依存関係でうっかり入ってしまったパッケージグループを削除します。

[root@rc1]# rm /etc/yum.repos.d/public-yum-el5.repo
[root@rc1]# wget http://public-yum.oracle.com/public-yum-el5.repo
[root@rc1]# yum update
[root@rc1]# yum groupremove 'MySQL Database' 'Mail Server'

アップデートしたカーネルを利用するためにGRUBのメニューリストを作成しておきます。

[root@rc1]# vi /boot/grub/menu.lst
default=0
timeout=3
hiddenmenu

title Oracle Linux 5.6 64bit
    root (hd0)
    kernel /boot/vmlinuz-2.6.18-238.el5xen root=/dev/sda1 console=hvc0
    initrd /boot/initrd-2.6.18-238.el5xen.img

スワップ領域用のファイルを作成し、スワップに割り当てます。これは後々Grid InfrastructureやOracle Databaseのインストール時にスワップがないと怒られるためです。(どっちみに容量が足りないといって怒られるのですがもうそれは無視します)

[root@rc1]# dd if=/dev/zero of=/var/tmp/swap.img bs=1M count=2048
[root@rc1]# mkswap /var/tmp/swap.img
[root@rc1]# swapon /var/tmp/swap.img
[root@rc1]# vi /etc/fstab
/dev/sda1                  /                       ext3    defaults        1 1
tmpfs                   /dev/shm                tmpfs   defaults        0 0
devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
sysfs                   /sys                    sysfs   defaults        0 0
proc                    /proc                   proc    defaults        0 0
/var/tmp/swap.img     swap     swap     defaults     0     0

udevのルールを作成します。これは後々ASM(Automatic Storage Management)に追加のEBSボリュームを認識させるためです。

[root@rc1]# vi /etc/udev/rules.d/80-oracle.rules
KERNEL=="sd*",OWNER="oracle",GROUP="oinstall",MODE="660"
KERNEL=="xvd*",OWNER="oracle",GROUP="oinstall",MODE="660"

Grid Infrastructure、Databaseをインストールするにあたり必要なパッケージをまとめてインストールしてくれるoracle-validatedをインストールします。

[root@rc1]# yum install oracle-validated

あった方が便利なソフトウェアをいくつかインストールしていきます。
まずscreen。

[root@rc1]# yum install screen

高速に圧縮/解凍を行うためのpbzip2。

[root@rc1]# yum install bzip2-devel
[root@rc1]# wget http://compression.ca/pbzip2/pbzip2-1.1.2.tar.gz
[root@rc1]# tar xvfz pbzip2-1.1.2.tar.gz
[root@rc1]# cd pbzip2-1.1.2
[root@rc1]# make && make install

sqlplusを便利にするrlwrap。

[root@rc1]# yum install readline-devel
[root@rc1]# wget http://utopia.knoware.nl/~hlub/rlwrap/rlwrap-0.37.tar.gz
[root@rc1]# tar xvfz rlwrap-0.37.tar.gz
[root@rc1]# cd rlwrap-0.37
[root@rc1]# ./configure
[root@rc1]# make && make install

viでvimを起動するためのalias設定を行います。

[root@rc1]# vi /root/.bashrc
# .bashrc

# User specific aliases and functions

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias vi='vim'

# Source global definitions
if [ -f /etc/bashrc ]; then
	. /etc/bashrc
fi

ログやキャッシュ、SSH鍵情報をクリーンアップしてAMIとしてリパックするための前処理を行います。

[root@rc1]# oraclevm-template --cleanup
[root@rc1]# oraclevm-template --enable
[root@rc1]# history -c

インスタンスを停止します。

[nkjm@mac]$ ec2-stop-instances i-5409fe3b

インスタンスのボリュームのスナップショットを作成します。

[nkjm@mac]$ ec2-create-snapshot -d 'Oracle Linux 5.6 64bit customized by nkjm' vol-193e7874

スナップショットからAMIを登録します。

[nkjm@mac]$ ec2-register -n 'Oracle Linux 5.6 64bit customized by nkjm' -d 'Oracle Linux optimized for Grid Infrastructure and Oracle Database' --root-device-name /dev/sda1 -b /dev/sda1=snap-cb0e4aa7 -a x86_64 --kernel aki-427d952b

AMIを公開します。(デフォルトでは非公開になっています)

[nkjm@mac]$ ec2-modify-image-attribute ami-dc07f5b5 --launch-permission -a all

そして実際にこのAMIを公開しています。

AMI ID: ami-dc07f5b5
Name:
Oracle Linux 5.6 64bit customized by nkjm
Region:
US East

特に最新のASMやDatabase等のOracleソフトウェアをこれから検証してみたいけどなかなかそういった機材がないという方、AWSのアカウントを作成してこのAMIを試してみたりしてはいかがでしょうか。AMIについてのフィードバックもいただけるとhappyです。

with one comment

Written by 中嶋 一樹

3月 18th, 2011 at 1:03 pm

Posted in Uncategorized

Tagged with , ,

EC2でOracle Linux AMIを使ってカスタムAMIを作る方法

OracleはEC2用のAMIを数多く提供しています。そうしたAMIをそのまま使ってももちろんOKなのですが、やはり自分の環境用にカスタマイズしたくなります。実際EC2ではAMIをカスタマイズして再度それを新しいAMIとして登録することができます。こうして自分だけのAMI作っておけば後々おなじようなセットアップ作業を繰り返しおこなう必要がなくなって便利ですよね。

ときにOracle VMではOracle VM Templateというものを提供していますが、EC2上のOracle AMIはこのVM Templateの実装を取り込んでいます。Oracle VM Templateにはoraclevm-templateというツールがインストールされており、このツールを使うとテンプレートのカスタマイズがちょっぴり楽チンになります。そしてこのoraclervm-templateがOracle Linux AMIにもインストールされているのです。

どういう風に楽チンなのか。

EC2上で新規にAMIを作る際には既存のAMIをベースにカスタマイズを行いそれを新AMIとして再登録する形が最も簡単だと思いますが、その際には一度AMIからホスト固有の情報をはぎとってニュートラルな状態にするためにSSH用の鍵を消したり、ログを消したり、キャッシュを消したり、という面倒な作業が必要になります。

ここでoraclevm-templateの出番です。AMIのカスタマイズが一通り完了して、これからAMI登録するよ、という時点で、下記のコマンドを発行します。

[root@~]# oraclevm-template --cleanup
[root@~]# oraclevm-template --enable

するとAMIから現在のログ等がクリーアップされ、次回起動時には新しい鍵ファイルが生成されるといった具合で最後の一手間をまとめてやってくれます。そしてこのクリーンアップ処理はきちんとEC2対応しており、通常だとoraclevm-template –cleanupしてしまうとネットワーク情報がリセットされるためSSH接続がきれてしまうのですが、EC2ではSSHがライフラインなのでここが切れては困ります。そこでoraclevm-templateはEC2上ではネットワークのリセットは行わないような配慮が加えられています。なので安心してcleranupしてください。

クリーンアップをおこなったらインスタンスを停止し、EBSボリュームのSnapshotを作成します。

[nkjm@mac]$ ec2-create-snapshot -d 'cleaned image' vol-42aaf52a
* -d: 作成されるスナップショットの説明
* vol-42aaf52a: EBSのVolume ID(ec2-describe-instancesで確認)

そしてSnapshotからAMI登録する、とすればオリジナルのAMIが出来上がりです。

ec2-register -n my-new-ami -d 'nakajima template' --root-device-name /dev/sda1 -b /dev/sda1=snap-be86f0d2 -a x86_64 --kernel aki-23d43a4a --ramdisk ari-25d43a4c
* -n: 作成されるAMIの名前
* -d: 作成されるAMIの説明
* --root-device-name: インスタンスからみたルートデバイス
* -b: ルートデバイスとそれに対応するSnapshotのID(ec2-describe-snapshotsで確認)
* -a: アーキテクチャ
* --ramdisk: ramdiskのID(元のインスタンスで確認)
* --kernel: kernelのID(元のインスタンスで確認)

このAMIはMy AMIsとして登録されますので、Lauch Instanceする際にこのAMIをMy AMIsから選択してインスタンスを作成できます。

ちなみに僕はami-09d43a60をベースに自分のAMIを上記手順で作成しています。

without comments

Written by 中嶋 一樹

3月 17th, 2011 at 5:07 pm

Posted in Uncategorized

Tagged with , ,