Translate

2013年2月27日水曜日

Google App Engine(1.7.4SDK)上のmemcacheは全部取得する系メソッドが使用できない




Google App Engine SDK 1.7.4の
memcache実装はjsr101cache-1.1.jarが使用されているのだけど
どうもこのライブラリのCache実装net.sf.jsr107cache.Cacheには
keySet(): キャッシュ上の全部のキーを取得する
とか
values(): キャッシュ上のすべての値を取得する
などの
全部ごっそり取る系のメソッドを使うと
App EngineのコンソールでLogを見ると
#以下はvalues()の場合

jp.freeex.fourtypes.server.m.StatisticsManager saveResults: exception occured
java.lang.UnsupportedOperationException
 at com.google.appengine.api.memcache.jsr107cache.GCache.values(Unknown Source)

という UnsupportedOperationException が出て使用できないことがわかった..

普段JCacheなんて使い慣れてないから
よく知らなかった..

ってことはメモリへ溜め込んだDB格納レコードを
cronでごっそり保存とかできないんだ..

TaskQueueにしても毎回キュー処理実行されちゃうからなあ..

それか1つのキャッシュにCollection載せてaddしてくか..



にしても..Google App Engine
実行環境に依存する問題多すぎだ..

それなりに慣れてないと使えないなんて
いちげんさんに厳しすぎ..



2013年2月21日木曜日

Google App Engineでcronを使う場合、0.1.0.1からのアクセスを禁止してはいけない




DDoS攻撃を受けていたApp Engine上のサービス
に日本国内IP以外を除外するサーブレットフィルタを
実装稼働させてから数日..


インスタンス起動時にBigTableから読み込み
memcache上に保存してこれをアプリで使うようにし、
cronでmemcache上データを定期的にBigTableへ保管する
ように作り替えたのだけど..

あれ?cronでDB更新ができてない..

で調べてみると..

Scheduled Tasks With Cron for Go
https://developers.google.com/appengine/docs/go/config/cron?hl=ja
の最後の方に

Google App Engine issues Cron requests from the IP address 0.1.0.1.

という記述が..
#Javaの方にも書いてくれよ..

0.1.0.1はもちろん日本国内のIPではないので
フィルタでロックアウトしてた..


ブラックリストを作成しようとする人で
cronを使ってる人は0.1.0.1を通すように
注意して下さい。


p.s.
Google App Engineの記事..
全然人気なくて他の記事と比べ参照数がすごく少ない..

ま、まさかもう..オワコンなのだろうか...

2013年2月15日金曜日

Google App EngineのDDoS対策としてServletFilterを作ってみる

私が昔作ったGoogle App Engine for Javaベース、
それもばりばりServletゴリ書きしたサイトが
分散DoS攻撃を受けていることは
まえの記事に書いた。

作りがDDoS攻撃なんか受けることを想定していなかったので
1リクエスト=1DB更新
というとんでもないプログラムになっていて
それを直すには時間がかかりそうなので
てっとり早く何とかしないといけない...


で、考えたのが、とりあえず対処療法。

Servletを呼び出すリクエストすべてをフックする
分散DDoS対策フィルタをかませることにした。

いろんなIPアドレスからたくさんのリクエストを送ってくるので
・IPアドレスごとにアクセス数をカウントする
・所定の時間カウントを保持するが、その後自動的にクリアする
・BigTableは使用しないでmemcacheのみで実装する
ということにして作ってみた。

参考にされる方はat your own riskでお願いします。



まずフィルタクラスAntiDDoSFilter.java

package harahara-dev;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import harahara-dev.FrequencyManager;
/**
 * <p>対DDoS攻撃用ServletFilter</p>
 * <p>リクエスト送信元のIPアドレス別にアクセス回数をmemcacheで管理し、
 * 一定ルールを超えた場合、所定のページヘfowardする。</p>
 * @author harahara-development
 */
public class AntiDDoSFilter implements Filter{
 
 /**
  * ロガー
  */
 private static Logger log =
   Logger.getLogger(AntiDDoSFilter.class.getName());
 
 /**
  * FilterConfigをインスタンス
  */
 private FilterConfig config = null;

 /**
  * 初期処理。FilterConfigインスタンスをインスタンス変数へ格納する。
  * @param FilterConfig FilterConfigインスタンス
  */
 @Override
 public void init(FilterConfig config) throws ServletException {
  this.config = config;
 }

 /**
  * フィルタ処理。
  * memcache上のIPアドレスアクセス数を比較し違反した場合、
  * 所定のページヘフォワーディングする。
  * @param ServletRequest req リクエスト
  * @param ServletResponse resp レスポンス
  * @param FilterChain フィルタチェーン
  */
 @Override
 public void doFilter(ServletRequest req, ServletResponse resp,
   FilterChain chain) throws IOException, ServletException {
  String ip = req.getRemoteAddr();
  FrequencyManager freqManager = FrequencyManager.getInstance();
  boolean result = freqManager.isHeavyAccess(ip);
  if(result){
   log.log(Level.INFO, "[doFilter] ip=" + ip +" is heavy user");
   ServletContext context = config.getServletContext();
   RequestDispatcher rd = context.getRequestDispatcher("/toomanyaccess.html");
   try {
    rd.forward(req, resp);
    log.info("[doFilter] fowarding done");
   } catch (Exception e) {
    log.log(Level.INFO,
      "[doFilter] exception during forwarding", e);
   }
  }
  // 処理が終わったので、後続のフィルタ/サーブレットへ
  chain.doFilter(req,  resp);
 }

 /**
  * 終了処理。
  * インスタンス変数をクリアする。
  */
 @Override
 public void destroy() {
  config = null;
 }
}

つぎにmemcacheを使った頻度管理マネージャFrequencyManager.java

package harahara-dev;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.google.appengine.api.memcache.jsr107cache.GCacheFactory;
import net.sf.jsr107cache.Cache;
import net.sf.jsr107cache.CacheException;
import net.sf.jsr107cache.CacheFactory;
import net.sf.jsr107cache.CacheManager;

/**
 * 頻度管理マネージャ
 * @author harahara-development
 */
public class FrequencyManager implements Serializable {

 /**
  * シリアルバージョンUID
  */
 private static final long serialVersionUID = -1111111111111111111111L;
 
 /**
  * キャッシュクリアされるデフォルトのタイムアウト時間(秒)
  */
 public static final int DEF_TIMEOUT = 3600;
 
 /**
  * アクセス回数上限(リクエスト数)
  */
 public static final int DEF_MAXCOUNTS = 200;
 
 /**
  * appengine-web.xml上に定義するプロパティキー:タイムアウト時間(秒)
  */
 public static final String PROPKEY_TIMEOUT = "cache.timeout";
 
 /**
  * appengine-web.xml上に定義するプロパティキー:リクエスト上限回数
  */
 public static final String PROPKEY_MAXCOUNTS = "cache.maxcounts";
 
 /**
  * キャッシュ名
  */
 public static final String CACHE_NAME = "frequnecy";
 
 /**
  * ロガー(App Engine)
  */
 private static final Logger log =
   Logger.getLogger(FrequencyManager.class.getName());
 
 /**
  * 唯一のFrequencyManagerインスタンス
  */
 private static final FrequencyManager freqManager = new FrequencyManager();

 private int maxCounts = 200;
 private int timeout = DEF_TIMEOUT;

 /**
  * 外部から呼び出し不可のコンストラクタ。
  * プロパティ値が設定されていればその値でタイムアウト、上限アクセス数を変更し、
  * キャッシュを生成する。
  * キャッシュ生成時の例外は無視される(App Engineログへ出力)。
  */
 @SuppressWarnings("unchecked")
 private FrequencyManager(){
  // タイムアウト値の確定
  String propTimeout = System.getProperty(PROPKEY_TIMEOUT);
  if(propTimeout!=null){
   try{
    timeout = Integer.parseInt(propTimeout);
   }catch(RuntimeException e){
    log.log(Level.INFO, "Not numeric prop timeout=" +
      propTimeout, e);
   }
  }
  
  // 最大アクセス回数の確定
  String propMaxCounts = System.getProperty(PROPKEY_MAXCOUNTS);
  if(propMaxCounts!=null){
   try{
    maxCounts = Integer.parseInt(propMaxCounts);
   }catch(RuntimeException e){
    log.log(Level.INFO, "Not numeric prop max counts" +
      propMaxCounts, e);
   }
  }
  
  // キャッシュの生成
  try {
   @SuppressWarnings("rawtypes")
   // キャッシュ設定用Map生成
   Map props = new HashMap();
   // タイムアウト値を設定
   props.put(GCacheFactory.EXPIRATION_DELTA, timeout);
   // キャッシュ名を設定
   props.put("name", CACHE_NAME);
   // キャッシュマネージャを取得
   CacheManager manager = CacheManager.getInstance();
   // キャッシュファクトリを取得
   CacheFactory factory = manager.getCacheFactory();
   // キャッシュを生成
   Cache cache = factory.createCache(props);
   // 生成したキャッシュをキャッシュ名をつけて登録
   manager.registerCache(CACHE_NAME, cache);
  } catch (CacheException e) {
   // 例外は再スローしない
   log.log(Level.WARNING, "Exception in constructor", e);
  }
 }
 
 /**
  * FrequencyManagerインスタンスを取得する。
  * @return FrequencyManager インスタンス
  */
 public static final FrequencyManager getInstance(){
  return freqManager;
 }
 
 /**
  * 指定したipアドレスの利用回数が上限に達しているかを確認する。
  * @param ip IPアドレス
  * @return boolean 真:超過している、偽:範囲内
  */
 public boolean isHeavyAccess(String ip){
  log.log(Level.INFO, "isHeavyAccess() arrived ip=[" + ip +"]");
  Frequency freq = null;
  Cache cache = CacheManager.getInstance().getCache(CACHE_NAME);
  freq = (Frequency) cache.get(ip);
  if(freq==null){
   freq = new Frequency(timeout, maxCounts);
   cache.put(ip, freq);
   log.log(Level.INFO, "create Frequency ip=" + ip);
  }
  boolean result = freq.isHeavyAccess();
  log.log(Level.INFO, "isHeavyAccess() returns " + result);
  return result;
 }

 /**
  * 頻度クラス(インナークラス)。
  * キャッシュに格納される唯一のオブジェクト。
  * @author harahara-development
  */
 class Frequency implements Serializable{
  /**
   * シリアルバージョンUID
   */
  private static final long serialVersionUID = -2222222222222222222L;
  /**
   * デフォルトの最大アクセス回数
   */
  private int maxCounts = DEF_MAXCOUNTS;
  /**
   * デフォルトのタイムアウト値(ミリ秒)
   */
  private long timeoutMills = DEF_TIMEOUT*1000L;
  /**
   * インスタンス生成時刻
   */
  private long createdAtMills = System.currentTimeMillis();
  /**
   * アクセス回数
   */
  private int count = 0;
  /**
   * インスタンスを生成する。
   * @param timeout タイムアウト時間(秒)
   * @param maxCounts 最大アクセス回数
   */
  Frequency(int timeout, int maxCounts){
   this.timeoutMills = timeout*1000L;
   this.maxCounts = maxCounts;
  }
  /**
   * 利用回数が上限に達しているかを確認する。
   * 判断とともにカウンタを1回加算する。
   * @return boolean 真:超過している、偽:範囲内
   */
  public boolean isHeavyAccess(){
   // 有効期限を超えた場合、カウンタをリセットする
   if(System.currentTimeMillis()>(createdAtMills+timeoutMills)){
    count = 0;
    createdAtMills = System.currentTimeMillis();
    log.log(Level.INFO, "Frequency reseted");
    return true;
   }
   // カウンタを1加算し最大カウント回数を超過したかどうかbooleanを返却する
   return ((++count)>maxCounts);
  }
  
  @Override
  public String toString(){
   return "Count(" + count + "/" + maxCounts + ")";
  }
 }
}


最後にフィルタの設定をWEB-INF/web.xmlのなかへ記述する。

 ...
 <filter>
  <filter-name>antiDDoS</filter-name>
  <filter-class>harahara-dev.AntiDDoSFilter</filter-class>
  <init-param>
   <!-- cache values timeout (sec) -->
   <param-name>cache.timeout</param-name>
   <param-value>3600</param-value>
  </init-param>
  <init-param>
   <!-- cache values max request counts -->
   <param-name>cache.maxcounts</param-name>
   <param-value>200</param-value>
  </init-param>
 </filter>
 
 <filter-mapping>
  <filter-name>antiDDoS</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>
 ...

一応言っておくとこのurl-patternでは管理系サーブレットも
頻度管理されるので、気をつけること。




..で、これをセットしてしばらくたつが、
結局BigTableアクセスの頻度は多少おとすことができた。


ただ、
もっとDDoS送信元偽装が浅く広くされてしまうと
当然こんな対処方法ではすぐ手に負えなくなる。


1リクエスト→1DB更新
ではなく、
遅延書き込みというかまとめ書きをしないと
対処できん..

いよいよ全書き換えかなあ..

2013年2月13日水曜日

個人で作ったGoogle App EngineサイトがDDoS攻撃を受ける

2017年10月24日追記:
この記事書いたのが2013年2月13日なので4年以上経過して
ワタシ的には今更なのですが..

ようやくGoogleが対策乗り出してくれました。

Google Cloud Platform Japan Blog
AppleEngineファイアウォールをサポート
https://cloudplatform-jp.googleblog.com/2017/10/App-Engine-firewall-now-generally-available.html

DDoS 対策はコレ使えば、良いと思いますよ。




具体的な日時やサイトURLの記述は避けるが
私が構築運用しているApp Engineで作ったサイトが
DDoS攻撃を受けた。

2010年の夏に構築したサイトで
画面数5のすごく小さなアプリだったのだけど..

Google APIの使用は、
Bigtableへアクセスと
アンケート結果をメール送信する
この2つだけ、
無課金で運用していた。

ある日、
ユーザからアクセス出来ないという

真っ白な画面に
Error: Server Error
The server encountered an error and could not complete your request.

If the problem persists, please report your problem and mention this error message and the query that caused it.
というメッセージのみの状態が続く障害が発生。

大した処理もしていないので、
運用し始めた頃から
ソース自体は変更していなかった。
#リンク先の変更などの静的変更は数度のみ

しかもたまにトップページが出たり、
内部でExceptionが出た時表示する画面へ
すすんだりして動作が安定していない。

なので環境面をまず疑った。
MasterSlaveからHigh Replicationへ移行しろという
コンソールメッセージがでていて
面倒臭がってこれまでやっていなかった。

なので
ははあ、Google M/S型アプリへのリソース配分変えたな
と誤解して
HRD環境へアプリを移行させた。

移行したのでアプリIDがかわり(URLはかわらない)
制約も一旦クリアされるので
その日は快適に動作していたのだけど..

今度は制約クリア時刻(午後5時)から深夜までは動作するが
その後エラーページしかでなくなった。
1日のうち1/3も動作しない時間が..

で、ログを見たらたくさんアクセスしていて
DBアクセスのCPU時間を超過している事がわかった。

もしやとおもいコンソールの
Blacklistを見ると..
でるわでるわ1000アクセスしたIPアドレスが
ちょろちょろと。
#このページ1時間でフルクリアする









しかも別の時間見た時全然別のIPアドレスでアクセスしている。
課金してたら恐ろしいことになってたかも..






自慢じゃないが1ヶ月でやっと1000アクセスするくらいのアプリだ。
キャンペーンもしていない。

ログをジーっとみつづけていたら
法則がわかってきた。
・IPアドレスはランダム、クラスA~Dまでふんだんに使用している
・1つのアドレスからのリクエストは1000件まで
・ブラウザもAndroidからWindows、MacのSafaliやMozilla、Firefoxさまざま
・GET/POSTパラメータを駆使
・GETパラメータのパラメータ値がいつも一緒
・3分で1つのIPアドレスからのアクセス1000件を達成している
・6パラでアクセスしている風を装っている

IPアドレスを1つづつnslookupしていたが、
ランダムだということがわかってきて諦めた。


最後のパラメータ値が一緒だというところから
ツールなりサーバなりで自動でリクエスト投げてきている
可能性が高い。


..人生初、DDoS攻撃。
また、大人の階段を登ってしまった..

Blacklistがきっちり1000件アクセスでならんでいるのは
GAE環境が同一IPを1000件でロックアウトさせるのか、
ツールのループが1000件で次のアドレスを使い出すロジックになっているのか..

DoS攻撃の場合、アクセスを禁止するIPアドレスを設定できる
dos.xmlというファイルがあるが、
(同一サーバ経由の擬似かもしれないが)DDoS攻撃だと使えない。

アプリで制約にかかりそうなロジックを退避させる。
Cookieで排除してやろうかとも思ったが
ツールならCookieを仕込まないで直接Socketしてるかもしれない。
もうべたな方法で治すしか無い..

やったことは
ダイレクトにURLエントリポイントにGET/POSTしても
Google APIを消費しない
ようにロジックを変更した。
あと、とあるPOSTパラメータをチェックして
これがないとエラーページ(静的)へ飛ばすようにした。

今のアプリ、男らしくServletを使っているけど、
Google App Engineの構造上、
Google Web Toolkitとの親和性がいいはず。
粗方の処理はロジックをJavaでかきJavaScript変換して
ほとんどをクライアント側でやってしまい、
DB保存やDB照会を非同期で処理させてAjaxで画面表示する..


..そろそろ書きなおそうかな..
げっGWTもう2.5.0だって..
こりは時間がかかるかも..

2013年2月6日水曜日

Scalrのインストール手順ドキュメントを翻訳してみる

書籍「CloudStack徹底入門」を読んでいてふと
Scalrというオープンソースがある事を知った。
p340の最後たった5行だけ..

どうもポータル機能をもつWebアプリで、
CloudStackだけでなくOpenStackも扱えるらしい..

もしかしたら..
Cloud Portalを買わずに課金とかできるかもしれない..

しかもオープンソースならプライベートクラウドとして
CloudStackを入れて部署へ使用料を付け替えとかも
できるかもしれない(できないかもしれない)..

これは試してみる必要がありそうだ...


..ということで、Scalrのインストール手順を
まず翻訳して見ることにした。

Dashboard>Documentation>Home>Getting Started>Open-Source Installation
http://wiki.scalr.net/display/docs/Open-Source+Installation#Open-SourceInstallation-SystemRequirements

をとりあえず訳してみたのが以下の文章である。
他の記事と同じく、本文書も at your own risk でお願いします。

以下、開始

オープンソース版インストール手順


新規追加Robin Piedeleu、最終更新Paul Chapotet(2012/07/17)

このページは、自分のインスタンス上でオープンソース Scalr をインストールしたいユーザによって提供されました。

システム要件

免責事項

連続的に更新されるコードをもとにしているため、独自にホストされた環境からScalr管理下の環境への移動はとても難しいです。もしあなたが自分自身でScalr構築を検討しているのであれば、自分で構築したScalrがアップデートやアップグレードできない事を了承しなくてはなりません。


最小サーバ構成

個人でScalrをホストするには、下記の最小構成スペックのサーバが必要となります。

  • m1.large 1台 mysql用
  • m1.large 1台 app用
  • c1.medium 1台 cronジョブ用


2012第2クオータの最新版では以下のサーバが必要になる予定です:

  • m1.large 1台 redis(NoSQL)用
  • m1.small 1台 rabbitmq(MQM)用


パッケージ

パッケージ名及びインストール手順変更箇所です。


オープンソースScalrは以下の機能を持つWebサーバが必要です。

  • URL rewriting (mod_rewriteのような機能)
  • POSIX互換OS(Linux, BSD)
  • PHP5.3.5もしくは以降の5.3.xブランチ
  • MySQL5.1.X


更に以下の様な依存関係のあるパッケージのインストールが必要です。


  •     libssh2
  •     OpenSSL
  •     net-snmp-utils
  •     bind9


必要となるPHP設定オプション

  • safe_modeはOff
  • register_globalsはOff


必要となるPHPエクステンション

  •     mysqli
  •     cURL
  •     Sockets (--enable-sockets) SSL をサポートする場合 (--with-openssl)
  •     GetText
  •     SimpleXML
  •     mcrypt
  •     mhash
  •     pcntl
  •     posix
  •     ssh2
  •     DOM
  •     SOAP
  •     SNMP
  •     pecl_http
  •     rrdtool


特定のバージョンのrrdtoolエクステンション(PECLからのデフォルト版ではない)が必要であることに注意して下さい。ビルドするためには、Webサイト http://oss.oetiker.ch/rrdtool/pub/contrib/ から'php_rrdtool.tar.gz'をダウンロードして下さい。解凍し、phpize、設定、makeを実行して下さい。
rrdtoolパッケージ同様librrdもまたバージョン1.3.xのものが必要です。
特定バージョンのダウンロードは http://oss.oetiker.ch/rrdtool/pub/?M=D から行えます。


また、apache mod_rewrite は必須です。
scalr virtualhostに"AllowOverride All"を設定して下さい。



インストール手順

最新コードを http://scalr.net/pricing/open-source/ からダウンロードして、unizpを実行して下さい。

フォルダ app/ のコンテンツをWebサーバへコピーして下さい。
フォルダ app/www のみWebサーバ経由で参照可能にしてください; その他すべてのフォルダは web root の最下部においてください。Scolrはドキュメントルートのサブフォルダ(例:domain.com/something)では動作しません。サブドメインを作成し、そのドキュメントルートに Scalr の app/www フォルダを指すようにして下さい。
以降、文中の /scalr_home_dir/ は Webサーバの app/ フォルダのロケーションをさします。

AllowOverride (Apache) か、もしくは /scalr_home_dir/etc/.htaccess 内で発見されたScalrドメインがrewriteルールを実現のための他の妥当なディレクティブを設定して下さい。もしApache以外のWebサーバ(lighttpdなど)を使用しているのであれば、.htaccessルールを該当サーバに適応するフォームにコンバートする必要があります。



パーミッション設定


以下のフォルダ(およびそのサブフォルダ)やファイルはWebサーバからの書き込みが可能な設定にして下さい。オーナシップをWebサーバユーザに変更し、パーミッションを700に設定するか、(セキュリティがより緩い)777(全員書き込み可能)にしてください:

  • cache


データベースの構築及び設定


新規にMySQLデータベースを構築し、Scalr用のデータベースユーザを作成して下さい。
ファイル sql/scalr.sql からデータベースへインポートして下さい。
Webサーバ上ファイル /scalr_home_dir/etc/config.ini へデータベースの設定を編集して下さい。


cronジョブの設定


正しくシステムを動作させるために、定期的にいくつかのタスクを実行する必要があります。Scalrは様々なコマンドラインスィッチによって実行される単一のファイル cron/cron.php を保有しています。以下のタスクをスケジュール設定して下さい:


*/2 * * * * /usr/bin/php -q /scalr_home_dir/cron-ng/cron.php --Poller
* * * * * /usr/bin/php -q /scalr_home_dir/cron/cron.php --Scheduler2
*/10 * * * * /usr/bin/php -q /scalr_home_dir/cron/cron.php --MySQLMaintenance
* * * * * /usr/bin/php -q /scalr_home_dir/cron/cron.php --DNSManagerPoll
17 5 * * * /usr/bin/php -q /scalr_home_dir/cron/cron.php --RotateLogs
*/2 * * * * /usr/bin/php -q /scalr_home_dir/cron/cron.php --EBSManager
*/20 * * * * /usr/bin/php -q /scalr_home_dir/cron/cron.php --RolesQueue
*/5 * * * * /usr/bin/php -q /scalr_home_dir/cron-ng/cron.php --DbMsrMaintenance
*/2 * * * * /usr/bin/php -q /scalr_home_dir/cron-ng/cron.php --Scaling
*/5 * * * * /usr/bin/php -q /scalr_home_dir/cron/cron.php --DBQueueEvent
*/2 * * * * /usr/bin/php -q /scalr_home_dir/cron/cron.php --SzrMessaging
*/4 * * * * /usr/bin/php -q /scalr_home_dir/cron/cron.php --RDSMaintenance
*/2 * * * * /usr/bin/php -q /scalr_home_dir/cron/cron.php --BundleTasksManager
* * * * * /usr/bin/php -q /scalr_home_dir/cron-ng/cron.php --ScalarizrMessaging
* * * * * /usr/bin/php -q /scalr_home_dir/cron-ng/cron.php --MessagingQueue
*/2 * * * * /usr/bin/php -q /scalr_home_dir/cron-ng/cron.php --DeployManager
*/2 * * * * /usr/bin/php -q /scalr_home_dir/cron/cron.php --UsageStatsPoller


統計設定のロード


まず最初に、adminアカウントでSetting→Core セッティングを編集して下さい。rrdtoolバイナリファイルへのパス、rrdデータベースへのパスやその他の設定を行う必要があります。


システム要件(Scalrの追加要件)

  • rrdtool ≧1.3.5 (pangoサポートのために必要)
  • rrdtool-php


注意:
CentOSユーザ、最新のrrdtool、perl-rrdtoolはRPMForge repoからインストール出来ます。また同一のrepoからphp-rrdtool のインストールも試すことができます。私のネットワークでは可能でした。ただし、rrdtool-devel を同一repoからインストールした後、php-rrdtoolのコンパイルに成功しました。


Cron

統計データの保管を行うために追加のcronタスクをスケジュール設定して下さい:

* * * * * root /usr/bin/php -q /var/www/scalr/app/cron-ng/cron.php --SNMPStatsPoller


設定

サーバが(ほとんどの)Scalrシステム要件を満たしているかチェックするために、app/wwwフォルダのtestenvironment.php スクリプトを実行して下さい。上記のステップを満たしたとすると、Webサーバからhttp://your.scalr.domain/testenvironment.phpへアクセス可能になっています。この操作によって、幾つか(rewriteルール不足やcronタスクの不足など)は発見出来ませんが、ほとんどの主要な問題を発見することができます。



BIND


サーバ上にBIND設定が必要です:

すべてのファイルパスは絶対パスです。

ファイル named.conf はBINDユーザからは読み書き可能にしてください。

ファイル named.conf へ"/var/named/etc/namedb/client_zones/zones.include"のインクルードを追加して下さい。

ゾーンファイルのために、ディレクトリ '/var/named/etc/namedb/client_zones' を作成して下さい。このディレクトリに中のすべてのファイルも含めてBINDユーザが読み・書き・実行できるパーミッションを設定して下さい。

ゾーン定義のために、ブランクファイル'/var/named/etc/namedb/client_zones/zones.include'を作成して下さい。


セキュリティIPプール


ファイル/path/to/scalr/etc/security.ini内:
[ec2]
; You can set the security group name to
; anything you want. Scalr will add it to
; all instances launched.
security_group_name = 'scalr.ip-pool'

[ip-pool]
; You can add any number and any name to
; the below list.
host1 = '3.1.4.1/28'
host2 = '5.9.2.6/28'
host3 = '5.3.5.8/28'
; This entry is specifically for phpmyadmin
pma = '9.7.9.3/32'
; This entry is specifically for statistics
stats = '2.3.8.4/32'


おめでとうございます!設定完了です。admin/adminでログインして、Settings→Core settingsへ進み設定を編集して下さい。

イベントハンドラURLをチェックして下さい、デフォルトでは'example.com'になっていますので、実際のScalrサーバのURLへ変更して下さい。インスタンスはこのURLを使ってScalrサーバとの接続を確立します。設定変更なしでは、インスタンスはHostInitメッセージ(と、すべてのシーケンシャルメッセージ)の送信先が分かりません。

エラーを含む既知の問題

  • 問題:OperationalErrorが出る:データベースはサーバログやスクリプト実行などいくつかの便利なものがロックされ、データベースバンドルが動作しません
  • 解決法:サーバへSSH接続して以下のコマンドを実行して下さい

    $ rm -f /etc/scalr/private.d/db.sqlite
    $ /etc/init.d/scalarizr restart

  • 問題:Received RebundleFailed event from serverが出る
  • 理由:EBSボリュームvol-XXXXXXXXが時間内にアタッチされずに、_t1.micro_サーバタイプを使っている
  • 解決法:サーバを再起動して再試行してください


4つの子ページ



Scalr 2.5 + Ubuntu 11.10
2.1.* から 2.2.0 への更新
2.2.0 から 2.2.1 への更新
振る舞いの作成方法


以上



なんか最初にやけにオープンソース適用を脅す文言が入ってるなと思ったら、phpファイルじかにWebサーバへ導入するインストレーションだからか..
なんでaptとかyumでやらないんだろう..バージョンも現時点だと3.5とか結構メジャーバージョン進んでるのになあ..


2013年2月5日火曜日

書籍「CloudStack徹底入門」を読む




書店でCloudStack徹底入門(翔泳社)が発刊されていたので早速買う。

CloudStackやOpenStackはGoogle一本釣りで情報をかき集めていたため、知識や情報がパッチワーク状態で「CloudStackの基礎知識」に抜けがあるのかどうか気になっていたのだ。
これを機にちょっと正しく情報を整理しようと購入してみた。


CloudStack徹底入門/翔泳社
¥3,990 Amazon.co.jp

ざーっとななめ読みしてみると、たしかに知らないところが結構ある。

・ゾーンにはパブリック、プライベートがあること
・パブリックゾーンは全ユーザがインスタンスを作れること
・プライベートゾーンは特定のドメイン傘下でないとインスタンスを作れない
・プライマリストレージをローカルで作成するとライブマイグレーション機能が使えない
・ローカルでプライマリストレージを作るにはsystem.vm.lovsl.storage.requiredをtrueにする
・セカンダリストレージにOpenStack Swiftも使える
・基本ネットワーク+NetScaler(製品)でロードバランサ/静的NATが実現可能
・ネットワーク、特にVPNあたりの解説はきちんと読んでおかないと..
・インストレーションはRedHat系中心、yumでインストールする手順
・KVM/XenServer/VMwareごと、基本/拡張ゾーンの導入方法も記載されている
・OpenStack Swift連携の手順も紹介されている
・cloudmonkey(CLI)の導入と簡単な使い方
・CloudStack APIをコールするURLの作り方(Linux上のコマンドを使って)
・AWS互換APIの使い方、たぶんさわりくらい
・お試しCloudStack環境としてVirtualBox上で動くDevCloudというのがあるらしい
・ソースからのビルド方法
・日本語訳ドキュメントのありか
・CloudPortal、enStratus、Chef、RightScaleの概要
・NetScalerやJuniparSRX、MidoNet、Stratosphereのネットワーク系ソフトの概要
・Engine YardとかForgeなどのPaaS系(さすがにVMware系のCloudFoundryは無いか..)
・ストレージ系のCATStorやCloudianの紹介など

インストレーションについては、まあUbuntu派なので(個人的には)不要だったけど、自分がきちんと理解しきれていない拡張ネットワークやらVPNなどのネットワーク系は、整理するのに役に立ちそう。

それにCloudStack自体にふりまわされていて正直周辺の製品やオープンソースやらはよく理解できていなかったが、このへんの基礎知識を収集する手間が省けそうだ。


なお、
Apache CloudStack Docs翻訳プロジェクトのリポジトリは
以下にあります。

https://www.transifex.com/projects/p/ACS_DOCS/language/ja_JP/



既存アプリケーションをK8s上でコンテナ化して動かす場合の設計注意事項メモ

既存アプリをK8sなどのコンテナにして動かすには、どこを注意すればいいか..ちょっと調べたときの注意事項をメモにした。   1. The Twelve Factors (日本語訳からの転記) コードベース   バージョン管理されている1つのコードベースと複数のデプロイ 依存関係 ...