クラウド

免責事項

  • このページを書いているのは、グーグル・クラウド・ジャパン合同会社に所属するTechnical Solution Engineerの若田部 亮です(2019 4月-)。
  • 本ページに書かれていることは個人的なメモであり、Alphabet傘下の会社の意見とは異なりますので、ご了承ください。

概要

  • GCPの使い方

目次

疑問

  • KVS
  • 可用性と可用性の指標
  • ハイパーバイザー

基本構成

  • 物理的には、リージョン->ゾーン->物理サーバとなっている
  • プロジェクトはリージョンに対して割り当てられている。
    • リージョン内ではゾーンで冗長化されている
  • プロジェクト
    • 唯一の課金アカウントと結び付けられている
    • プロジェクトには一般アカウントが複数ログインできる
    • 逆に、それぞれの一般アカウントは、複数のプロジェクトにログインできる
    • プロジェクトの権限管理はIAMとかいうものでなされる(なんの略?)
    • 複数のインスタンス=サービス=VMみたいなものが、一つのプロジェクトの中で、ネットワークを構成して動いている。インスタンスそのものが別のリージョンで動いていたとしても、内部ネットワークとして利用できる
  • プロジェクトのネットワーク
    • Legacy Network = リージョンにまたがったsubnet
    • Subnet Network = 単一のリージョンでのsubnet
  • Cloud Shell
    • f1-microクラス/debianのめちゃくちゃ弱いGCEの一時インスタンスの上で実行されるシェル
    • 課金なし・永続5GB, ユーザごとに割り当てられていて、プロジェクトにまたがって共有される

用語

  • Cloud Launcher
    • 150個以上の事前ソフトパッケージをGCEにデプロイできる
  • CAPの定理
    • NoSQLで3つの性質を同時に満たすことが極めて難しいという定理
  • デプロイ

一般的なクラウドサービスの知識

  • 仮想化技術
    • ホスト型仮想化: 要するにVM, 手軽だがオーバーヘッドが高い
    • ハイパーバイザー型仮想化: GCEではLinuxKVMが使用されている (GCEはこれが使われている)
    • コンテナ型仮想化: 動作環境(ライブラリなど)を閉じ込めて、見た目独立したサーバのように動作するサービス
  • ライフマイグレーション技術
    • ハードウェアメンテンナンスのときに、「あるVM in サーバAを、in サーバBに無停止で移動する」
  • プリエンティティブVM
    • いつ切られてもおかしくないVMだが、80%割引
  • ディスク
    • 永続ディスク: ネットを介して接続されたNASみたいなもの。
    • ローカルSSD: めちゃくちゃ早い(IOPSが高いという)
  • Web三層アーキテクチャ
    • Webフロントサーバ: HTTP reqを受け取って、HTTP resを返すためのサーバ
    • Webアプリケーションサーバ: 本体の実行
    • データベースサーバ: データの管理をする、ボトルネックになりがち
    • 小規模システムでは上記をすべて兼ねることもできるし、WebフロントとWebアプリケーションを兼ねることもある(p55-58参照)

サービス

L7リバースプロキシ

dispatch.yaml や dispatch.xml はGoogle App Engine(以下GAE)のFrontendでルールベースでL7 HTTP Reverse Proxyしてくれるものです。 これはMicroservicesをやる上では大変便利なものになっています。 L7リバースプロキシなので、全てのサービスが立ち上がっている状態じゃないとデプロイできない(してもいいけどない)

Google App Engine

  • Standardはmem,cpuなどいろいろ見るが、FlexはCPUのみ。

Task Queue

Task QueueはCloud TasksとPub/Subの中間みたいなもの。PushQueue?PullQueue?という2種類のキューがあって、使い分ける感じ。 To use the push Task Queue service outside of the first generation standard environment, you can use Cloud Tasks. In many cases where you might use pull queues, such as queuing up tasks or messages that will be pulled and processed by separate workers, Cloud Pub/Sub can be a good alternative as it offers similar functionality and delivery guarantees. デフォでdefaultのqueueがあるらしい。これは5/s rateのPush queue。Push quueeとかでも、最大レートやリトライ回数などを細かく指定し、名前を浸かるためのものがquuee.yaml(GAE Standardのみ)

Memstore

Redis an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker. 基本的なデータ構造を扱えるNoSQL データベース セッション管理・カウント・ランキングなどの実装に使うのがよい。RedisはI/Oの速さが長所で、消失してもダメージが少ないが、大量アクセスが見込まれるような、ゲームコンテンツなどで使用すると、高い効果を発揮できると思います。 あと、パブサブ・メッセージキュー・ロックとしても使うことができるらしい。すごい メモリ上に全部データを乗せるかなりドラスティックなデータベース スナップショットというものがあって、これを使うと非同期でRDBダンプによってディスクに書き込まれる 2秒おきにデータをファイルシステムに書き込むようになっているので、必要であれば安全なオプションを利用可能。 何がmemcachedと違うのかというと、データを2通りの方法でディスクに書き出せるというところ。 SQLと違ってシングルスレッドに限定されているので自動的に排他的(memcachedはマルチスレッドで処理可能) メモリを使い果たしたら、LRUなどのルールから削除していく。注意点としては、Radisの設定を「データ削除しない」にしておくと、メモリが足りなくなったときに削除せずに、書き込みエラーになる Radisで落ちてほしくないならばちゃんとメモリ増設をする。本当にmaxmemoryもttlも設定していないと、OOMで殺されるので注意 古いVerは爆弾を抱えていることもあるので、理由もなく使い続けるのはやめよう。 ログとかも、新しいVerの方が色々吐いてくれたりするので、 問題発生時の原因特定がしやすい。 maxmemoryと書いてあるけど、これはevictする閾値なので、これ以上のメモリを消費することもある。なので、メモリ性費用を厳密に制限することはできない。2~3倍メモリを消費することくらい全然ありえる。 イメージバックアップは10000回keyの書き換えが会ったら60秒後にディスクに保存するみたいなやつ まずoutput-bufferってなんやねん、という話から。 output-bufferはRedisがメモリ上に確保するバッファの一種。 レプリケーション環境で運用してる際、slaveはmasterのコピーであるので、 keyの削除時には「このkey消しといてー」とslaveに通知する必要がある。 その情報はoutput bufferにため込んで、まとめて送信される。 あまりに削除するkeyが多かったり、masterが抱えるslaveがたくさんあったりすると、 output bufferの分だけ、メモリを大量に消費してしまう。 そうすると、通信がいつまで経っても終わらなくなって、しかし削除要求は増え続け、 slaveの更新ができないまま、メモリ消費量だけ肥大化する。 こうなると非常に危険で、色々な問題を誘発することがある。 空きメモリが無くなって、HTTPが死んだり、前述のBGSAVEプロセス作成に失敗して スナップショットが長期間保存されない状況になったりする。 Radisはバージョンを上げるのはマジで大切。あとRadisは一つに丸投げするのではなく、インスタンスを風数に分ける必要がある。 appendfsync everysecというのがあって、これをonにしておくと書き込み操作のたびにfsyncする。ちなみにeverysecではなくalwaysというのがあり、これが一番安全

client-output-buffer-limitは所定の容量をbufferが超えたら、 クライアントとの通信を強制的に切断するという設定。 これはこれで問題があるけど、メモリが枯渇するよりはマシかもしれない。 masterから見たクライアントというのは、slaveのことなので、 仮にbufferのピーク容量が500MBで、slaveが4台繋がってたら、 最大で2GBぐらい消費することになる。 実際は詰まり始めたらどんどん消費してしまうので、「最大で」とか「最悪でも」なんて 想定をしても、あまり意味はないかもしれない。 ただ、output-bufferの危険性を認識しておくのは非常に大事。 最終的にはサーバ内のディスクにデータが保存されますが、保存直後はメモリに一時保存されるため、データ揮発の可能性はゼロではありません。 バックグラウンド書き込み用のメモリをどれくらい確保すればよいかと言うと、2.8.22 以降の場合は 25 (25 パーセント) に設定、それ以前なら50%にする必要がある active deflagという機能が4.0から提供されていてこれを使うと効率的にメモリを使えるようになる(が完全な解決ではない)

Dialogflow

言語解析エンジン 音声入力で問題となりやすい自然言語の解析を簡単にやってくれる機能。 これを挟むことで言語解析のややこしいところを大幅に削減できる。

Google Compute Engine (GCE)

GCEのホストマシンが死んだりメンテに入った場合(プリエンプティぶも含む) gcloud compute instances set-schedulingによって他のマシンに移したり、終了したりする。普通にサービす稼働させたいものをterminateでデプロイしない!(リファレンスのアドレス好き) https://cloud.google.com/sdk/gcloud/reference/compute/instances/set-scheduling

managed instance-groupにはautohealingという機能がある。 文字通り、ヘルスチェックの結果によってインスタンスを自動修復(再作成)する機能だ。 負荷分散におけるヘルスチェックは、ロードバランサの振り先がHEALTHYかどうかを見るだけで、インスタンスの再作成は行わないが、マネージドインスタンスグループに適用されるヘルスチェックはインスタンスがUNHEALTHYになったら、削除して再作成する。

GCF

  • GCFは、イベントドリブンな処理
    • HTTPリクエストで超マイクロサービスを作るとき(素数判定とか)
    • GCSがアップロードされたら検知して何か作業するとき
    • pubsubに何かがパブリッシュされたとき
    • GCFを使ってGoogle Cloud Storage (GCS)のファイルを自動で圧縮するみたいなやつ。BUD(マイクラ用語)だね

Datastore

  • Keyにはidもしくはnameがつけられている。idはLongでnameはString
  • Datastore の特徴
    • スケールする & 遅くない & そこそこ柔軟な検索ができる
    • バランスがいいので、逆にハマる 非自明な制約 1 回の commit に同じエンティティ(キーが同一のエンティティ)を複数回含めないでください。1 回の commit に同じエンティティを複数回含めると、Cloud Datastore のレイテンシに影響する場合があります。 クエリ結果のキーだけにアクセスする場合は、キーのみのクエリを使用します。キーのみのクエリでは、エンティティ全体を取得する場合よりも低いレイテンシとコストで結果が返されます。

射影クエリ 要するにSQLのselectで一部だけ撮ってくるみたいなやつ エンティティの特定のプロパティだけにアクセスする場合は、射影クエリを使用します。射影クエリでは、エンティティ全体を取得する場合よりも低いレイテンシとコストで結果が返されます。 多くの場合、アプリケーションが必要とするのはエンティティのプロパティの一部分だけです。 射影クエリを使用すると、エンティティのプロパティの中で本当に必要なものだけをクエリできるため、エンティティ全体を取得する場合よりもレイテンシとコストを低く抑えられます。 射影クエリで指定するプロパティには、インデックスが必要です。

カーソル、制限、オフセット クエリに対して制限を指定することで、1 バッチで返される結果の最大数を制御できます。次の例では、最大で 5 つの Task エンティティを取得します。 これによって、100万人のうち200000-2000100人を撮ってくる、みたいな処理をオーバヘッドなしでおこなえる。課金もされない。 同じような機能をオフセットで行うことができるが、計算量的に悪いし遅いし課金される。Datastore モードのデータベースでは整数のオフセットをサポートしていますが、使用は避けてください。その代わりにカーソルを使用します。オフセットを使用するとスキップされたエンティティがアプリケーションに返されなくなりますが、そのようなエンティティも内部的には引き続き取得されています。スキップされたエンティティはクエリのレイテンシに影響するだけでなく、そのようなエンティティの取得に必要な読み取りオペレーションに対してアプリケーションが課金されます。このようなコストは、オフセットの代わりにカーソルを使用することですべて回避できます。

この記事がめちゃくちゃ面白い https://cloud.google.com/datastore/docs/articles/fast-and-reliable-ranking-in-datastore/#olog-n-

これがめちゃくちゃよいエンティティグループの解説。結局のところ、やっぱり連結されていれば全部強整合性を保つため、1op/sの制限がかかってかなりヤバい。組織全体で木にするというよりは、本当に強性合成が必要だと思ったところだけを木にして連結させるという発想のほうが良い。安心(強整合性)は高いということを知れ。 https://cloud.google.com/datastore/docs/articles/balancing-strong-and-eventual-consistency-with-google-cloud-datastore/ 重要な問題の 1 つは、各エンティティ グループに更新(またはトランザクション)の回数を保管するようにシステムを設計する必要があることです。エンティティ グループごとに 1 秒間に 1 回の更新に制限されます[2]。 更新の回数がこの制限を超える必要がある場合、そのエンティティ グループはパフォーマンスのボトルネックとなるおそれがあります。 上記の例では、各組織内のどの人のレコードも更新が必要になる可能性があります。「ateam」内に 1,000 人含まれていて、それぞれの人物のいずれかのプロパティを 1 秒間に 1 回更新する可能性があるとします。その結果、このエンティティ グループでは 1 秒間に最大 1,000 回の更新がありえますが、これは更新の制限により実現できません。これにより、パフォーマンス要件を考慮した適切なエンティティ グループの設計の選択が重要であることがわかります。これは、結果整合性と強整合性の最適なバランスを求める際の課題の 1 つです。

読み取り、書き込み、削除には、単一のオペレーションではなくバッチ オペレーションを使用します。バッチ オペレーションでは、単一オペレーションと同じオーバーヘッドで複数のオペレーションが実行されるため効率的です。 トランザクションが失敗した場合はロールバックを試行してください。ロールバックを使用すると、トランザクション内で同じリソースを使用する別のリクエストの再試行レイテンシが最小限に抑えられます。ロールバック自体が失敗する可能性もあるため、ロールバックはベスト エフォート型の試行である点に注意してください。 可能な場合は、同期呼び出しではなく非同期呼び出しを使用します。非同期呼び出しでは、レイテンシの影響が最小限に抑えられます。たとえば、同期 lookup() の結果とクエリの結果に従ってレスポンスをレンダリングするアプリケーションについて考えてみましょう。lookup() とクエリにデータの依存関係がない場合、lookup() が完了するまでクエリの開始を同期的に待機する必要はありません。

Datastoreのデータ構造。森がある。全ての頂点には必ず、キーと呼ばれる数字もしくは文字列が書き込まれおり、何らかの色が塗られている。各頂点には、数字もしくは文字列の任意長のタプルが書かれている。以下のクエリを高速に行え。 (1) 色を一つ選んで、同じ色のものを全列挙する (2) 頂点を一つ選んで、その頂点を根とする部分木に含まれる頂点を全列挙する

https://cloud.google.com/appengine/docs/standard/python/datastore/transactions Databaseでキーをランダムではなく文字列で管理している場合、同じ文字列 ID を持つエンティティを別のユーザーが作成または更新しようとする状況を処理するには、前の例と同様、ここでもトランザクションが必要です。トランザクションを使用しない場合は、エンティティがまだ存在していない時点で 2 人のユーザーが同時にこれを作成しようとすると、1 人目のユーザーが知らないうちに 2 人目のユーザーが作成したエンティティが 1 人目のエンティティを上書きしてしまいます。 トランザクションのもう 1 つの一般的な用法は、名前付きキーによってエンティティを取得することです。名前付きキーがまだ存在しない場合は、新規に作成します。 実はキーに対応する実態がなくても大丈夫(Noteに人のIDを突っ込んでputしていないし、実際にconsoleでみるとそれはないみたいな)

HTTPリクエストから来ているやつらは基本的に文字列だから注意!!!Keyはnameだったりidだったりするので、とくにidの場合キャストせずに突っ込むとまずい。

ndbのkeyを作るときは、kindを文字列としても渡しても良いし、ndbのEntityのクラスを渡してもよいらしい。 sandy_key = ndb.Key(Account, 'sandy@example.com') ndb.Key('Account', 'sandy@example.com', 'Message', 123, 'Revision', '1') Keyを得るためには、これは本当に(S, S cup N)+の配列なので、自分で構築してしまったほうが早い。Keyはちゃんと設計して自分で作るもの。Entityから得るものというよりは。なのでfrom_pathを使っている時点でなんかおかしいと思ったほうが良さそう。

Dialogflow

Dialogflow 言語解析エンジン 音声入力で問題となりやすい自然言語の解析を簡単にやってくれる機能。 これを挟むことで言語解析のややこしいところを大幅に削減できる。

Cloud Storage

  • GAE, GCE, BQ, CDのBackend Storageとして使える
  • 特徴
    • オブジェクトストレージ
    • エッジキャッシュ
  • ストレージタイプ
    • Multi-Regional: 複数のリージョンにデータを分散
    • Regional: 単一のリージョンの複数のゾーンにデータを分散
    • Necling: 月一回程度のアクセス
    • Cold Line: 年一回程度のアクセス
  • GCP全体->バケット->オブジェクトの順に階層がある
    • オブジェクトはたとえば画像イメージみたいなもの
    • オブジェクトに対してそれを取得するためのHTTPリクエストを投げることができる
    • オブジェクト自体にはディレクトリのような階層構造はないが、名前にスラッシュを入れることで擬似的にそう扱うことはできる

Object split / compose splitコマンドで分解したファイルをあとでcomposeするのは非常によくやられる方法。GCS上ではgcloud compose part-* resultの形で行うことができるらしい。

catした結果をパイプで繋いでgsutilに渡す。 cat files.txt | gsutil -m cp -I gs://my_bucket →リストに書いてあるファイルが全てコピーされる

gsutil -mでマルチスレッドコピーができる。他にも並列化されるものはある?

gsutilにはトップレベルオプションとそうでないオプションがある gsutil -DD cp src dstのようにすると、-DDはトップレベルオプションでコマンドの詳細情報が得られる。

Google Cloud SQL

  • GAE, GCEからアクセス可能
  • Cloud SQL Proxyで通信経路の暗号化もできる
    • SQLプロキシ
    • 要するに安全にオンプレとクラウドをつなぎたいんだけど、静的IPを用意するのはアホらしいからGCPの認証で安全にアクセスするようにしましょうということ。
    • GCEからのアクセスを考えるときでも、SQLにPrivate IPを設定するという手もあるが、それもいやだねという話。
    • ちなみにV2ではprivate, public, SQL Proxy, Proxy Docker imageのどれかが使えるが、V1だとパブリックしか使うことができない。
    • じゃあPrivate IPを使えばいいじゃん、という話になるのだけど、Private IPのSQLは鬼門なのでProxyをしたいねという気分になる

gcloud sql instances create myinstance2-replica2 --master-instance-name=myinstance2 を走らせた後にctrl-Cを押してもインスタンス作成はキャンセルされずに作られる。

SQLはstart timeというコンフィグが会って、 start of a 4-hour backup windowでバックアップが取られる。そのためコネクションが4時間に一回増える。

リードレプリカは全然削除を気軽にしても大丈夫。なぜならリードレプリカだから。最悪管理コマンドで消しても作り直せばよいし、再起動くらいなら全然やってよい。

MySQLの MySQL 5.6以降ではデフォルトでONに設定されるようになったパフォーマンススキーマですが、MySQL 5.5時代をご存知の方は明示的にOFFにしているかも知れません(MySQL 5.5のパフォーマンススキーマはパフォーマンスへのオーバーヘッドが非常に大きかった上に、大量にメモリーを利用した)。最近のパフォーマンススキーマはON/OFFに再起動が必要な点こそ変わりませんが、パフォーマンスオーバーヘッド、メモリー使用量ともに大幅に改善されています。また、取得できる情報も「ステートメント(ダイジェスト)単位での各種待ち状態の統計」、「各ステージでの経過時間」、「トランザクション単位での統計」などが追加され、さらに「スキーマ単位、テーブル単位で記録するか否か」、「ユーザー単位、ホスト単位で記録するか否か」を設定できるようになっています。

A cascading failure is a failure that grows over time as a result of positive feedback. It can occur when a portion of an overall system fails, increasing the probability that other portions of the system fail. For example, a single replica for a service can fail due to overload, increasing load on remaining replicas and thereby increasing their probability of failing, causing a domino effect until all the replicas for a service are down.

Dataflow

裏でオープンソースのものを使っているので難しい

HiveやPigでTezを使うのはすごく簡単です。 Hiveの場合、 set hive.execution.engine=tez; など、hive.execution.engine変数にtezという値を入れてやります。 Pigの場合も起動時に $ pig -x tez set exectype=tez;

HiveはSQLっぽくHadoopのmap reduceパイプラインを作るためのツール。もともとはFacebookが作った。 他の言語としては以下がある Cloudera Impala -- allows you to query Hadoop data using SQL, but does not utilize Mapreduce under the hood so can run faster. i.e. more similar to Dremel in architecture. See https://vision.cloudera.com/impala-v-hive/. IBM BigSQL HAWQ Hadapt

Apache Pig -- new language for specifying a Mapreduce against Hadoop data. Simpler than writing Java code. Originally created by Yahoo.

HBaseはこのHDFS上に構築するデータベースです。HBaseとHadoop(HDFS)の関係を図4に示します。なお、HBaseの構築にYARNとMapReduce?は必須ではありませんが、MapReduce?を使用するとHBaseのデータ格納/参照を高速に行えるため、YARNとMapReduce?も同時にインストールすることを推奨します。 NoSQL

RDDとは、以前にも書きましたが「不変(イミュータブル)で並列実行可能な(分割された)コレクション」 RDD(A Resilient Distributed Dataset (RDD),)に保持したデータを操作するメソッドは大きく分けて2つに分類されます。「Transformations」と「Actions」です。「Transformations」はRDDを操作し、結果を新しいRDDとして返します。「Transformations」の代表的なメソッドは、mapやfilterです。「Actions」はRDDのデータを操作し、結果をRDD以外の形式で返すか保存を行います。大雑把に言えば、RDDを返すのが「Transformations」、そうではないものが「Actions」であると言えると思います。 得意 Hadoopで加工したのちのドリルダウン分析 TB級までのデータを扱うシステム サンプリングが有効でないロングテールのデータ分析 数秒~数分程度のHadoopよりも短いレスポンスが必要な処理 不得意 クラスタ全体のメモリに乗りきらない巨大なデータ処理(TB以上) 大きなデータセットを少しずつ更新する処理 秒以下の時に短いレスポンスが必要な処理 Hadoopの欠点と言われていたのが主に以下の三つ 個々のメモリを活用できる設計でなかった(タスクごとにデータをディスク読み込み&書き込みしなきゃいけないのがボトルネック) 同じ処理を複数行う際に、その都度データアクセスが発生 同じデータでもなんども使うものは使う際に無駄にアクセスがいっぱい発生 この課題を解決するのがRDD(Resilient Distributed Datasets)というSparkの分散共有メモリの仕組みです。 すごくざっくり言うと、Hadoopでは毎回ストレージにアクセスしたりしていたのがインメモリで実行できるのでいいこといっぱいあるよねって感じだと解釈しました。 YARNとHDFSって何 (*1)HDFS:MapReduce?で処理するデータを扱う、分散ストレージとして複数のマシンを一つのストレージとして扱うことができる。 HDFSは管理するファイルのI/Oを高速化するため大きなファイルを一定の大きさ(初期設定では64MB)のブロックに分割して、複数の記憶装置に分散して保存、I/Oを記憶装置の台数だけ並列に実行できるようにしている。 HDFSは並列でよめるファイルシステム。Hadoop Distributed File System Sparkはインメモリにすると早いよねなので、クラスタのメモリがなくなると当然弱い(遅延評価しているとはいえ)。 データをインメモリにロードする部分はSparkContext?と呼ばれるtextFileのようなファイルシステムからダウンロードしてくるような関数が提供されている。一方で、parallelizeという関数があってこれはプリミティブなデータ構造(配列とか)をRDDにするための関数。 RDDはデータそのものではなく、「RDDsを構築するためにデータに対して行った変換」を記録することで効率的な耐障害性を実現している。 もしRDDの中の一部分がロストした場合、RDDはそのデータが他のRDDからどのように変換されて生じたデータかを保持しているため、コストの大きなレプリケーション(*5)なしに迅速に再計算/復旧させることができる。 . 系譜のステージへの分割 DAGSchedulerが、系譜をスケジュールに分割する ステージは系譜中で狭い依存関係が連続して発生する範囲(依存関係の種類は変換の種類できまる) 系譜中で広い依存関係が発生する変換関数を処理する場合はエグゼキュータ間でシャッフルと呼ばれる多数対多数の通信が発生する。 この分割は、パーティションごとに一つのエグゼキュータがまとめて計算できる変換の範囲を決めるため なので、sparkの実装にdataflowを使いたくなるのはすごく気持ちがわかるねという感じ RDDは静的なので静的なデータの変換を行うために、関数型で物体そのものを定義するというのは妥当な感じがする YARN は、以下の図に示す次世代の Hadoop 計算プラットフォームです。イメージクラスタのマスターがYARN masterでworkerがYARN slaveと呼ばれるっぽい。YARN slaveはMapreduce マスタ・スレーブをコンテナとして起動する感じになる。 プログラマブルでやれることがちょっと限られているdataflowみたいな感じかな Cloud Dataproc service – receives job requests from the user and submits the request to the dataproc agent dataproc agent – runs on the VM, receives job requests from the Cloud Dataproc service, and spawns driver driver – runs customer-supplied code, such as Hadoop jar, spark-submit, beeline, and pig applications Dataprocではselectorというのがあって、これはクラスタを冗長化してジョブをランダムにクラスタアサインする Jobが失敗したら全てのジョブがキャンセルされて今後のものもキャンセルされる。

Cloud Launcher

https://qiita.com/NagaokaKenichi/items/41ee9d8ba40555eaf2b7 Cloud Launcherというサービスがあって、これをつかうとpredefinedのjenkinsなどをGCE上に立ち上げることができる。

BigTable?

HBase BigTable?のapache版。こっちからBigTable?に移行したい、あるいはベンダーロックを嫌うためにHBaseっぽいクライアントライブラリが提供されている(ちょっとの差はあるけど) com.google.cloud.bigtable.hbase.BigtableConfiguration?が全てのhaddp系と全く同じインターフェースの関数群を提供しており、それから先はほぼhadoop.hbaseと同じように操作できるよ!という感じ。 このナレッジベースがかなりよいので一読の価値がある 数については知らないのでページの機能をいい感じに実装するのは厳しそう Filter filter = new PageFilter?(pageSize); BTでもない

BigTable? Cloud Bigtable は行をアトミックに読み取ります。このため、一回の更新が1行で収まるようにする努力が大切で、1 行に格納するデータ量の合計を制限することは非常に重要です。1 つのセルに格納するデータを 10 MB 以下にし、1 行のデータを 100 MB 以下にするのがベスト プラクティスです。 BigTable?は二次主キーを作ることができないが、列ファミリーをいくつか作ってその中では辞書順ソートされるようにできる。

Java+BigTable? githubのcloud-bigtable-examples/java/hello-worldのgithub上のREADMEに従ったら一瞬でできた。mavenを一から書くにはたいへんだな… put.addColumnみたいなのをやると、Bigtableの各列はector<map<string, multiset<string>>>みたいなものなので、その列ファミリーが指定するsetにappendされる mvn package mvn exec:java -Dbigtable.projectID=wakataberyo-sandbox2 -Dbigtable.instanceID=bigtable-test

BigTable?の列ファミリーって何

BigQuery?

  • Dremel Queryグループで調べる tempでもいいからとりあえず実装してみる persistentで比較 大きいデータセットを作ってベンチマークしてみる NEXT 19のPersistent Queryを調べる The following limits apply to persistent user-defined functions. 気合で先頭を大文字にしている例 BigQuery? で半角全角変換を一応実現しているもの table -> arrayはarray(table) array->tableはUNNEST(array) Persistent functionを定義する場合、関数単体でクエリを投げる必要があります(同時に二つの関数を登録できない)
    CODE_POINTS_TO_STRING(array(select c + 65248 from UNNEST(TO_CODE_POINTS(CAST(x as STRING))) as c)) 
    string, array, tableの全てを行き来する必要がある。string -> arrayはTO_CODE_POINTS, CODEPOINTS_TO_STRING。ArrayとTableは、UNNESTとarray。ちなみにプリミティブシグネチャにかんしては cast(x as INT64)などでOK
# 半角数値 x を全角文字列に変換する関数
CREATE TEMP FUNCTION TO_MULTI_BYTE(x INT64) AS (
  CODE_POINTS_TO_STRING(array(select c + 65248 from UNNEST(TO_CODE_POINTS(CAST(x as STRING))) as c))
);

# 全角文字列 x を半角数値に変換する関数
CREATE TEMP FUNCTION TO_SINGLE_BYTE(x STRING) AS (
  CAST(CODE_POINTS_TO_STRING(array(select c - 65248 from UNNEST(TO_CODE_POINTS(x)) as c)) as INT64)
);

BQの配列アクセスarr[1]は arr[OFFSET(1)]

BQの一時テーブル作成において、以下のようにすると楽。

 FROM UNNEST([1, 2, 3, 4, 5]) AS numbers;

To convert an ARRAY into a set of rows, also known as "flattening," use the UNNEST operator. UNNEST takes an ARRAY and returns a table

Pub/Sub

  • Kafkaみたいなもの
  • 要するにただの分散キュー

Dataproc

  • Spark

Kubernetes

https://knowledge.sakura.ad.jp/16082/ GKEを理解したい Docker: コンテナとイメージというのがあって、イメージからコンテナを作る感じ。コンテナをイメージにするコマンドもあるし、どのようにそのコンテナを作ったかを記録しておいてそれをスクリプト的に走らせて再現性高くコンテナを作ることもできる(Dockerfile)。DockerではDockerネットワークという仮想的なコンテナ間通信を行うことができる。 複数ホストでコンテナを起動して、コンテナ間通信するには、今回説明したことの他にも必要な設定があります。そこで活躍するのが、KubernetesやDocker Swarmなどのコンテナオーケストレーションツールになります(今はKubernetesがデファクトスタンダードとなっています)。

k8sはこれがわかりやすかった https://news.mynavi.jp/itsearch/article/devsoft/4097 1つ目は高い抽象度です。Dockerコンテナは通常一台のサーバ内に閉じて構築されます。複数台のサーバにまたがるコンテナ環境を構築するためには、ネットワークにおけるNAT設定など、さまざまな設定が必要になります。 こういった問題にアプローチするのがKubernetesです。Kubernetesを使うとコンテナのクラスタ化が容易になります。クラスタはサーバ単位でコンテナを管理するPodと、サーバをまたがるPodを管理するReplicaSet?の組み合わせで構築されます。 2つ目は高い信頼性・回復性です。セルフヒーリングと呼ばれ、障害により設定された台数を下回った場合には、自動的にコンテナが再起動されます。これにより、ゼロダウンタイムを実現します。 3つ目は中立性です。Kubernetesを実現するサービスはGoogle Cloud PlatformやOpenStack?などさまざまに存在します。CNCF(Cloud Native Computing Foundation)により標準化されており、Kubernetesが各クラウドを抽象化する層を担うことで、ベンダーロックインを防ぎます。

ハイパバイザ 従来のホストOS型は、HW->OS->仮想化->ゲストOS ハイパバイ座敷は、HW->ハイパバイザ仮想化->ゲストOSとなっている。 ハイパバイザの一つの例としては、Linux自体をハイパバイザにしたQEMUというのが有名(発表して二週間でLinuxにマージされたので)。これはLinuxだからホスト型じゃない?と思うかも知れないけど、ハイパバイザの上で通常のプロセスを走らせることなく、ゲストOSをのせるという点で少し異なる 技術的な差異は主に3つある。(1) 仮想化支援機能を有するCPUを前提としていること。通常ソフトだけで仮想化してx86の上でarmなどの違うアーキテクチャを動かすとその計算のエミュレートが大変だったのだが、CPUがその機能を提供するようなCPUが販売されるようになったので、パフォーマンスがよくなった(CPUを限定してゲストOS側を最適化・改造が必要な準仮想化に比べると遅いけど)。(2) KVMは独自にハイパバイザを開発するのではなく、Linuixのデバドラを流用できるのでハードウェア対応が容易 (3) KVMでのゲストOSはプロセスとして管理される(!)ので、killとかCtrl-CによるゲストOSの削除が可能になる KVMは完全仮想化に際して仮想化支援機能を有するCPUを要求する(HWに対する制約がある)。使用している機器にCPUの仮想化支援機能があるかどうか分からない場合は、/proc/cpuinfoを見てみるとよいでしょう。Intel VTの場合はvmxが、AMD-Vの場合はsvmがあるか否かが1つの判断基準となります。

apt-get install kvm bridge-utilsみたいなやつをやって、kvm-img create -fとかいうかなりお手軽間を醸し出していることをすることによってkvmがインストールできたりOSがインストールできたりしてすごい

KVMはただでさえ仮想化していて物理的なサーバの位置がよくわからないのに、物理サーバの位置が多くなってくると本当にわけわからなくなってしまう。なので、こういうときに使うためのKVM運用ツールoVirtというものがある。

Cloud tasks

HTTP PUTを定期的に投げるだけのサービス(タスク:このHTTPリクエストをここに投げといてという依頼) 「POSTを積む、POSTを投げる」 投げる先はオンプレでもGCEでもApp Engineでもありえる。Google内部だといろいろ楽なので楽(例としてHTTPリクエストを…と言ったときにターゲットがApp Engineだったらprojectからの相対パスで指定できるので)。 ターゲットはPOSTに対して200台を返す義務がある。返さないとリトライとかされる。 Cloud Tasksからのリクエストには、どのキューからPOSTされたのかなどのヘッダーが書かれている。 こういうタスク系は非常に重くて特殊なものを使いがちだと思うので、GAEではなくGCEがそれを受けるというのが現実的になりそう

数百万または数十億のような多数のタスクを追加する必要がある場合、二重注入パターンが便利です。1 つのジョブからタスクを作成する代わりに、インジェクタ キューを使用します。

このTask Queueには、キューに追加した処理がGAEにより自動実行されない Pull Queue という種類があり、これを使うとGAEではない外部のプラットフォームからキューに入っている処理を引き出す事ができます。

StandardはTask queue, FlexはCloud tasks/PubSub?を使うべき(本当?StandardもCloud tasksのほうが良くない?)

言語

Java

JavaでLocalをチェックするための方法として、以下のものがある。要するに、環境変数的な感じでSystemからappengine.appid

 private static final String APP_ID = System.getProperty("appengine.appId");
 private static final String APP_VERSION = System.getProperty("appengine.version");
 private static final boolean LOCAL_TEST = null == APP_ID || null == APP_VERSION;

app.yamlにそうとうするものは、javaのばあいsrc/main/webapp/WEB-INF/appengine-web.xmlになっているっぽい。ここの部分でランタイムをxmlとして入力し、

Javaのweb-??.xmlみたいなやつ(app.yamlのJava ver)では、serviceが何故かmoduleという表現になっている あと、appIdって見たらプロジェクトIDのことだと思う必要がある

インスタンス設定

  • インスタンスに"http-server"タグを付記するとHTTPにつなぐための通信許可が得られる

デプロイ

  • 外部IPを設定して全世界に公開することもできる(!?)
    • どうやってるの

初期設定

  • いつhamkoになったのか…?
curl https://sdk.cloud.google.com | bash
exec -l $SHELL
gcloud init # ちゃんとログインページに飛ばしてくれないので、リンクを手でコピペする

ssh

gcloud compute ssh instance-1 --zone us-central1-c

GCPでコマンドが無い時に自動終了するスクリプト

https://twitter.com/imos/status/923551881166602240

月2ドルとかで超安くサーバが使えるように鳴るらしい

Googleクラウド お金がクレジットある状態だと不明瞭なのまじね。試しに使って見て、これくらいかーとなるもんじゃないの

Logging

Stackdriver Logging

  • Advanced Filterをちゃんと使いましょう
  • リクエストログ・アプリケーションログ・アクセスログという3つのログの種類がある。
  • 自分でgroup logを実現できる
    • どのログがどのリクエストから来ているかがわかるので
  • Trace
    • App Engine Standard以外で使おうとすると大変
    • Stackdriver Trace は、App Engine スタンダード環境と統合されています。
    • アプリケーションの実行中、App Engine スタンダード環境は、アプリケーション URI へのリクエストに関するレイテンシ データを Stackdriver Trace に自動的に送信
    • App Engine サービスへのラウンドトリップ RPC 呼び出しに関するレイテンシ データが含まれています。
    • Stackdriver Trace は、Cloud SQL を除いたすべての App Engine Admin API と連携します。

Stackdriver Trace

https://cloudplatform-jp.googleblog.com/2018/05/viewing-trace-spans-and-request-logs-in-multi-project-deployments.html また、トレースの一部となっている全プロジェクトからのリクエストに関するログ エントリの表示も可能です。これには関連するプロジェクト側に “logging.logEntries.list” の権限が必要で、ログを Stackdriver Logging に書き込む際は、“projects/[PROJECT-ID]/traces/[TRACE-ID]” というフォーマットで LogEntry? オブジェクトの trace フィールドを設定する必要があります。LogEntry? の span_id フィールドを、16 文字の 16 進数でエンコードされたスパン ID として設定し、ログを特定のトレース スパンと関連づけることも可能です。詳細はこちらのドキュメントを参照してください。 Fluentd を介して Google Kubernetes Engine もしくは Stackdriver Logging エージェントを利用する場合は、“logging.googleapis.com/trace” や “logging.googleapis.com/span_id” というキーを使って構造化ログを書き込むことで、LogEntry? オブジェクトの trace や span_id フィールドを設定できます。詳細はこちらのドキュメントを参照してください。 トレース スパンに関連づけられたログ エントリを表示するには、“Show logs” をクリックしてください。 ということは、これはStackdriver Traceと同等の機能なのか。

Cloud Activity

パーミッションチェンジみたいなやつは、Cloud Activityで得ることができる。Cloud ActivityはもともとStackdriverのAdmin操作のみを取り出したもので、 Cloud Activity (Home > My Activity) of your "snap-crackle-proxy" project and then filter for resources "GCS bucket".

gcloud

gcloud app logs read
gcloud app logs tail

Appengineのstackdriver logging的なものが得られる。各サービス、HTTPリクエスト、loggingが割と読みやすい形式で撮ってくれる。 結構遅延がある (30分)

言語別比較

  • Java一択
  • Goはバイナリを出力するので、JavaとかPythonとは異なりランタイムとかを乗せる必要がなく、Docker配布が軽くなるので嬉しいという特徴がある

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS