クラウド
免責事項 †
- このページを書いているのは、グーグル・クラウド・ジャパン合同会社に所属するTechnical Solution Engineerの若田部 亮です(2019 4月-)。
- 本ページに書かれていることは個人的なメモであり、Alphabet傘下の会社の意見とは異なりますので、ご了承ください。
概要 †
目次 †
強み †
- 10億人が利用するサービスのインフラをそのまま借りれる
- Anthosでマルチクラウドが簡単
- Google!
疑問 †
基本構成 †
- 物理的には、リージョン->ゾーン->物理サーバとなっている
- プロジェクトはリージョンに対して割り当てられている。
- プロジェクト
- 唯一の課金アカウントと結び付けられている
- プロジェクトには一般アカウントが複数ログインできる
- 逆に、それぞれの一般アカウントは、複数のプロジェクトにログインできる
- プロジェクトの権限管理は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に無停止で移動する」
- ディスク
- 永続ディスク: ネットを介して接続された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 †
- Standardはmem,cpuなどいろいろ見るが、FlexはCPUのみ。
- GAEのserviceは、yamlにservice: service_nameというのがあれば、サービスが建てられる。一方で、app.yamlには通常serviceの行が存在しないので、defaultというサービスが建てられる。サービスがworkerの場合https://worker-dot-wakataberyo-sandbox2.appspot.com/のように、[service-name]-dot-[project name].appshot.comの名前でアクセスできるっぽい?
- warmupリクエスト
- オートスケーリングしているので、インスタンスのスタートアップ時にMemcacheはちゃんと整っていないし、インスタンスのメモリ上に必要なデータが揃っていない可能性がある。
- そこで、インスタンスを作ってリクエストが車での間に前処理を済ませておこうというのがこのwarmupリクエスト。
- これをオンにしておくと、リクエストが着終わってからインスタンスを作るのではなく、予測的にインスタンスを作るのですこし高くなるらしい。
GAE Standard, GAE Flex †
- Google App Engine
- .gcloudignoreによってデプロイのときにアップロードするファイルを限定できる。
- deployをするとversionが一つ増える。
- Flexはインスタンスが一つ以上あるので、GAE->Versionが増える。Flexはinstanceが1個以上必要なので、VMインスタンスが一つは残って課金されるので、適宜消していったほうが良いという話が書いてあった。
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のみ)
Firebase †
企業がソーシャルログインを導入するメリット
ソーシャルログインの導入で企業が得られるメリットは、ユーザーが得られるメリットを逆の視点から見たものになります。
会員登録時の離脱率が減る
詳しいユーザー情報を得られる(※SNSプロバイダによる)
再訪率が上がる
パスワード再発行やログインできないという問い合わせが減る
セキュリティ対策へのコストが減らせる
Facebook、Twitter、Instagramが利用するようなOAuth2の仕様は、やや独自仕様になっている傾向があります。このような手間をoauth.ioを使うことで、簡単にSNSを用いた登録ボタンを作成できます。
Firestore †
- Document型データベース
Firebase Realtime Database = Cloud Firestore in Native Mode
Cloud Firestore in Datastore Mode
Datastore
Firestoreには、ネイティブモードとDatastoreモードの二種類があり、どちらか一方しか選ぶことしかできません。
ネイティブモードは、簡単に言うとFirebase Realtime Databaseの機能が使えるモードです。
Datastoreモードは、その名前のとおり、FirestoreのストレージレイヤでDatastoreのシステム動作するモードです。(正確にはDatastoreモードがDatastoreの後継です。)
Firestoreとして一括りにされる傾向が強い印象ですが、DatastoreモードではFirestoreの主な機能であるリアルタイム機能が使えなかったりするなど、Firestoreと言ってもまるで別のサービスと考えた方が良いと思います。
Firestore for realtimeという全然違うものがあるらしい。
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は一つに丸投げするのではなく、インスタンスを風数に分ける必要がある。
- 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から提供されていてこれを使うと効率的にメモリを使えるようになる(が完全な解決ではない)
Memcacheというものは、データがいつか消えてしまうかもしれないhash関数。Storageにアクセスするのに比べたら圧倒的に早いのが特徴。これって各インスタンスごとに定義されると思っていい?それとも全インスタンスで共有?
制限時間を設定することもできる(当然保証はできないけど)
memcache は他の一時的な値にも便利です。ただし、memcache のみに値を保存し、他の永続ストレージを使用しないかどうかを検討する場合、値が突然使用できなくなったときに、アプリケーションが適切に動作するようにしてください。
新しくできたインスタンスのためにmemcacheを用意しようみたいな話があるので、おそらくはmemcacheはインスタンスワイズの話なんだろうなあと思う
Dialogflow †
言語解析エンジン
音声入力で問題となりやすい自然言語の解析を簡単にやってくれる機能。
これを挟むことで言語解析のややこしいところを大幅に削減できる。
Google Compute Engine (GCE) †
- GCEのホストマシンが死んだりメンテに入った場合(プリエンプティぶも含む)
- managed instance-groupにはautohealingという機能がある。
- 文字通り、ヘルスチェックの結果によってインスタンスを自動修復(再作成)する機能だ。
- 負荷分散におけるヘルスチェックは、ロードバランサの振り先がHEALTHYかどうかを見るだけで、インスタンスの再作成は行わないが、マネージドインスタンスグループに適用されるヘルスチェックはインスタンスがUNHEALTHYになったら、削除して再作成する。
- マネージド インスタンス グループ(MIG)
- マネージド インスタンス グループ(MIG)は、ステートレスのサービス提供側のワークロード(ウェブサイト フロントエンドなど)や、高性能または高スループットのバッチ処理用コンピューティング ワークロード(キューからの画像処理など)に適しています。
- まじ!競プロに使えそう
- プリエンプティブインスタンスを一日立てて落とされる確率は結構低い。僕が試したときは2%くらいだった。
- これを使うとCloud FunctionsでGCEをシャットダウンさせるコードが書いてある
GCF †
- GCFは、イベントドリブンな処理
- HTTPリクエストで超マイクロサービスを作るとき(素数判定とか)
- GCSがアップロードされたら検知して何か作業するとき
- pubsubに何かがパブリッシュされたとき
- 例
- GCFを使ってGoogle Cloud Storage (GCS)のファイルを自動で圧縮するみたいなやつ。BUD(マイクラ用語)だね
- pubsubの構成要素
- publisher
- topic
- subscription
- subscriber
- topic 1:many subscription 1:1 subscriber
- 複数のsubscriberがいるならば、それぞれに対してtopicを設定する必要がある。
- subscriptionはデフォルトではpullで、pushにしたければ、自分の有効なエンドポイントをAPIで教えてあげる必要がある。pullの場合、10秒で再送信受け取りをする必要がある。
- APIとしては、たとえばあるtopicに紐付けられたsubscriptionを全列挙するなどもできる
- Subscriber には push か pull があって、pushだと subscription から POST が投げつけられる
- API的には、以下のようにトピックやサブスクリプションを指定できる。トピックはpublisherが知らせるところ、subscriptionは一つのsubscriberがpullするところ。
- projects/project-identifier/[topics/subscriptions]/relative-name
- project-identifier は、Google Cloud Platform Console から取得可能なプロジェクト ID にする必要があります。例: projects/myproject/topics/mytopic
Datastore †
- Keyにはidもしくはnameがつけられている。idはLongでnameはString
- Datastore の特徴
- スケールする & 遅くない & そこそこ柔軟な検索ができる
- バランスがいいので、逆にハマる
- 非自明な制約
- 1 回の commit に同じエンティティ(キーが同一のエンティティ)を複数回含めないでください。1 回の commit に同じエンティティを複数回含めると、Cloud Datastore のレイテンシに影響する場合があります。
- クエリ結果のキーだけにアクセスする場合は、キーのみのクエリを使用します。キーのみのクエリでは、エンティティ全体を取得する場合よりも低いレイテンシとコストで結果が返されます。
- 射影クエリ
- 要するにSQLのselectで一部だけ撮ってくるみたいなやつ
- エンティティの特定のプロパティだけにアクセスする場合は、射影クエリを使用します。射影クエリでは、エンティティ全体を取得する場合よりも低いレイテンシとコストで結果が返されます。
- 多くの場合、アプリケーションが必要とするのはエンティティのプロパティの一部分だけです。 射影クエリを使用すると、エンティティのプロパティの中で本当に必要なものだけをクエリできるため、エンティティ全体を取得する場合よりもレイテンシとコストを低く抑えられます。
- 射影クエリで指定するプロパティには、インデックスが必要です。
- カーソル、制限、オフセット
- クエリに対して制限を指定することで、1 バッチで返される結果の最大数を制御できます。次の例では、最大で 5 つの Task エンティティを取得します。
- これによって、100万人のうち200000-2000100人を撮ってくる、みたいな処理をオーバヘッドなしでおこなえる。課金もされない。
- 同じような機能をオフセットで行うことができるが、計算量的に悪いし遅いし課金される。Datastore モードのデータベースでは整数のオフセットをサポートしていますが、使用は避けてカーソルを使用
- これがめちゃくちゃよいエンティティグループの解説
- 結局のところ、やっぱり連結されていれば全部強整合性を保つため、1op/sの制限がかかってかなりヤバい。組織全体で木にするというよりは、本当に強性合成が必要だと思ったところだけを木にして連結させるという発想のほうが良い。安心(強整合性)は高いということを知れ。
- 重要な問題の 1 つは、各エンティティ グループに更新(またはトランザクション)の回数を保管するようにシステムを設計する必要があること
- エンティティ グループごとに 1 秒間に 1 回の更新に制限されます[2]。 更新の回数がこの制限を超える必要がある場合、そのエンティティ グループはパフォーマンスのボトルネックとなるおそれがあります。
- 上記の例では、各組織内のどの人のレコードも更新が必要になる可能性があります。
- 「ateam」内に 1,000 人含まれていて、それぞれの人物のいずれかのプロパティを 1 秒間に 1 回更新する可能性があるとします。その結果、このエンティティ グループでは 1 秒間に最大 1,000 回の更新がありえますが、これは更新の制限により実現できません。
- これにより、パフォーマンス要件を考慮した適切なエンティティ グループの設計の選択が重要であることがわかります。これは、結果整合性と強整合性の最適なバランスを求める際の課題の 1 つです。
- 読み取り、書き込み、削除には、単一のオペレーションではなくバッチ オペレーションを使用します。
- バッチ オペレーションでは、単一オペレーションと同じオーバーヘッドで複数のオペレーションが実行されるため効率的です。
- トランザクションが失敗した場合はロールバックを試行してください。
- 可能な場合は、同期呼び出しではなく非同期呼び出しを使用
- 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を使っている時点でなんかおかしいと思ったほうが良さそう。
- getとrunQueryの差
- getはバックエンドに直接問い合わせる
- runQueryはindexをつかって問い合わせる
- ds[kind][key]でエンティティが一意に確定する。これを得るためには.key(kind, key)でkey型を得て、.get(key)でEntityを得ることができる(idとプロパティのペア)。
- Entity typeは、ここに説明があるのだけど、.id, .kind, ["propertyname"]でアクセスできるらしい。
Dialogflow †
Dialogflow
言語解析エンジン
音声入力で問題となりやすい自然言語の解析を簡単にやってくれる機能。
これを挟むことで言語解析のややこしいところを大幅に削減できる。
GCS (Cloud Storage) †
- GAE, GCE, BQ, CDのBackend Storageとして使える
- 特徴
- オブジェクトストレージ
- エッジキャッシュ
- データはStrong Consistency, ACLはEventual Consistency
- ストレージタイプ
- Multi-Regional: 複数のリージョンにデータを分散
- Regional: 単一のリージョンの複数のゾーンにデータを分散
- Necling: 月一回程度のアクセス
- Cold Line: 年一回程度のアクセス
- GCP全体->バケット->オブジェクトの順に階層がある
- オブジェクトはたとえば画像イメージみたいなもの
- オブジェクトに対してそれを取得するためのHTTPリクエストを投げることができる
- オブジェクト自体にはディレクトリのような階層構造はないが、名前にスラッシュを入れることで擬似的にそう扱うことはできる
- かなりいっぱいオプションのバリエーションを用意して、どれが一番良かったでしょう?みたいなGCSのコマンドがあると良さそう。
- Object split / compose
- splitコマンドで分解したファイルをあとでcomposeするのは非常によくやられる方法。GCS上ではgcloud compose part-* resultの形で行うことができるらしい。
- GCSのtransferというものでAmazon S3からデータを取ってくるみたいなことができる。
- gsutil -mでマルチスレッドコピーができる。他にも並列化されるものはある?
- gsutilにはトップレベルオプションとそうでないオプションがある
- gsutil -DD cp src dstのようにすると、-DDはトップレベルオプションでコマンドの詳細情報が得られる。
- Copying 300MB files takes 2-4 minutes.
- 1Gのアップロード15病とかそこら(ストレージクラスはリージョナル)
- GCSのnotificationは、REST endpointになげるOCNとPub/Subの普通のやつがある。OCNは推奨されていない。
Google Cloud Repository (GCR) †
- GCRはプライベートなコンテナレジストリを提供してくれるサービス
- 特にGCPのコンテナを扱うサービス(GKEなど)を利用するときに便利
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.
https://miyabi-lab.space/blog/31
ただのバックアップではなくマスターへの変更を即座に反映することができるバックアップなのです。
さらに、災害などでマスターが属しているデータセンターに異常が発生し、マスターの機能が停止してしまった場合にもこのスレーブは働いてくれます。
なぜなら、スレーブが代わりにマスターへ昇格することでデータベースを安定稼働させ続けることができるからです。(これをフェイルオーバーと呼びます。)
リードレプリカとは、マスターからレプリケーションされた読み込み専用のデータベースです。
リードレプリカを使用する設計だとデータ読み込み(SELECTクエリ)を行う場合はリードレプリカが処理します。
そして、その他のデータの削除(DELETEクエリ)、更新(UPDATEクエリ)、追加(INSERTクエリ)に対してはマスターが処理を行います。
データベースでは書き込みよりも読み込み比率の方が高いため、データベースへのアクセス頻度が高くDBサーバのリソースが逼迫している場合などの際に、読み込みを複数の「リードレプリカ(読み込み用のレプリカ)」に分散して処理をさせることで、全体のパフォーマンス向上させることを目的としています
Cloud SQLでフェイルオーバーが発生するとフェイルオーバーレプリカがマスターに昇格します。
この時、フェイルオーバーレプリカのIPアドレスはマスターのIPアドレスに変更されます。
マスター側の復旧は約100秒ほどのようです。
フェイルオーバーレプリカ側の復旧は約390秒ほどのようです。
マスターはデータが増えても、復旧までの時間は変わらないようです。
フェイルオーバーレプリカはデータが増えると、復旧までの時間が増えていくようです。
第 2 世代インスタンスは、フェイルオーバーを持つ場合は高可用性構成になります。フェイルオーバー レプリカは、マスターと呼ばれる元のインスタンスと異なるゾーンにあることが必要です。ユーザー テーブルを含むマスターのすべてのデータ変更は、semisynchronous レプリケーションを使用してフェイルオーバー レプリカに複製されます。
SQLはICMPを返さないのでtelnetが必要
この3つを全部見る
https://cloud.google.com/vpc/docs/private-access-options#private_services_access_and_on-premises_connectivity
https://cloud.google.com/vpc/docs/configure-private-services-access
https://cloud.google.com/vpc/docs/using-vpc-peering#update-peer-connection
プライベートアクセスとか言うのがある。
RFC1918は、要するにプライベートIPアドレスってこと。
限定公開のGoogleアクセス=内部IPのみを持って外部IPを持たないもの→デフォルトのインターネットゲートウェイ経由でパブリックIPに接続。←要するに、外部IPを持たないのにGoogleのAPIにはアクセスできるよ
オンプレホスト限定公開Googleアクセス=内部IPが必要、外部IPは任意。←VPNトンネルを介して、外部IPを持っていなくてもGoogle APIに接続できるよ
プライベートサービスアクセス=内部IPを持ってやる。外部IPを持つこともできる(SQLとかのやつ)。Google, third partyの管理するinstance向け
限定公開のGoogleアクセス→内部IPしかないのにGoogleのAPIにつながる!不思議!(サブネットレベルでオンオフ)
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よりも短いレスポンスが必要な処理
- 不得意なこと
- DataflowではShufflingのときにhotspottingという問題が起きる可能性がある。これはa-m, n-zの辞書順で分けたときに、どっちかがあめっちゃ多くなるコーナーケースがある可能性があるから
- クラスタ全体のメモリに乗りきらない巨大なデータ処理(TB以上)
- 大きなデータセットを少しずつ更新する処理
- 秒以下の時に短いレスポンスが必要な処理
- Hadoopの欠点と言われていたのが主に以下の三つ
- 個々のメモリを活用できる設計でなかった(タスクごとにデータをディスク読み込み&書き込みしなきゃいけないのがボトルネック)
- 同じ処理を複数行う際に、その都度データアクセスが発生
- 同じデータでもなんども使うものは使う際に無駄にアクセスがいっぱい発生
- この課題を解決するのがRDD(Resilient Distributed Datasets)というSparkの分散共有メモリの仕組みです。
- すごくざっくり言うと、Hadoopでは毎回ストレージにアクセスしたりしていたのがインメモリで実行できるのでいいこといっぱいあるよねって感じだと解釈しました。
- 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みたいな感じかな
- Dataflowのスケールは、今後やるべきタスクの数によってスケールする。これはコストの制御のために行われている。つまるところ、レイテンシを固定化するようにスケールしているということ。行うタスクが小さいときにレイテンシがおそいのはWAI
- Dataflowはレイテンシを固定するように動くので、少量のデータだと遅い
- DataflowではShufflingのときにhotspottingという問題が起きる可能性がある。これはa-m, n-zの辞書順で分けたときに、どっちかがあめっちゃ多くなるコーナーケースがある可能性があるから
Composer †
コンポーザーはデータレイク(色んな所の生データ)にあるデータにドメイン知識を反映してデータウェアハウスにして(Hadoop)にして、特定用途向けに加工整理してデータマート(Tableau、Bigquery)にするという感じ。すぐに使える完成品を取り揃えていることからマート(市場)と呼びます。ウェアハウスは複数のデータを統合・蓄積して、意思決定に活用できるように整理したものです。
DAGフィアルはDAGを定義するだけで実際のデータ処理はworkirにやらせる。通信とかはチア変なのでXComというものを使うことによっていい感じにする
AirFlow?のオペレータにはめちゃくちゃいっぱいGCP系のものがある(DataflowとかDataprocとかStorageとかどこからどこにコピーするとか何でもあると言っても過言ではない)
従来の Cloud Dataflow ジョブ
Apache Beam パイプラインの開発とジョブの実行は、すべて開発環境内で行われます。
開発者が開発環境を作成し、パイプラインを開発します。環境には、Apache Beam SDK やその他の依存関係が含まれます。
ユーザーが開発環境からパイプラインを実行します。Apache Beam SDK が Cloud Storage 内のファイルをステージングし、ジョブ リクエスト ファイルを作成し、そのファイルを Cloud Dataflow サービスに送信します。
テンプレート化された Cloud Dataflow ジョブ
Cloud Dataflow テンプレートを使用する場合、ステージングと実行は別のステップです。このように分離されているため、ジョブを実行できるユーザーとジョブの実行元となる場所を柔軟に決定できます。
テンプレート化された Cloud Dataflow ジョブの典型的なワークフロー:
開発者が開発環境を作成し、パイプラインを開発します。環境には、Apache Beam SDK やその他の依存関係が含まれます。
開発者がパイプラインを実行し、テンプレートを作成します。Apache Beam SDK が Cloud Storage 内のファイルをステージングし、テンプレート ファイル(ジョブ リクエストと類似したもの)を作成し、Cloud Storage 内にテンプレート ファイルを保存します。
開発者以外のユーザーは、GCP Console、gcloud コマンドライン ツール、REST API でジョブを簡単に実行し、テンプレート ファイルの実行リクエストを Cloud Dataflow サービスに送信できます。
Spark runnerは分散用
Direct runnerはサーバ一大で開発・デバッグ・テスト用に作られたBeasmに付属した欄な
Cloud Launcher †
https://qiita.com/NagaokaKenichi/items/41ee9d8ba40555eaf2b7
Cloud Launcherというサービスがあって、これをつかうとpredefinedのjenkinsなどをGCE上に立ち上げることができる。
Cloud Build †
GCBはCI/CDとして見るとCircleCIと比べてまだまだ扱いづらいところがあります。一方で、従量課金制のフルマネージドなビルドサービスというCircleCIとは違った使い方もできるところが特徴と言えます。
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?は二次主キーを作ることができないが、列ファミリーをいくつか作ってその中では辞書順ソートされるようにできる。
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? †
clusterというのがある、同じ日のものは同じ場所に置くので料金が安くなったり速度が早くなると期待している。
検索バイト数が増えたり減ったりしている。
# 半角数値 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
bigqueryにはパーティションとクラスターという二つの方法がある
パーティションは基本的には時間分割。自動で一日ごとに分割する方法と、維持分で分割方法を考える方法とがある
クラスタ化とは、あるソート可能な要素を最大4つまで指定できる。クラスタ化ではディスクのランダムIOを減らすという目的になっているので、insertなどに弱い
性別というカラムはmale、femaleの2種類程度であるのでカーディナリティが低いです。
一方、マイナンバーというカラムは被りがないので非常にカーディナリティが高いです。
インデックスはカーディナリティが高いものを設定するとより効果的です。
こんなの当然で、uniqueのものが入っていると矩形クエリにいっぱい入り込む可能性があるので。。
インデックスが設定されているとレコードが挿入された時に平衡二分木なりなんなりのinsertが発生するので、insertは遅くなる。インデックスが二つといったときには、1次元のindexが二個なのか2次元のindexが1個なのかについては考えたほうがいい。多次元拡張するとしても例えばSegment TreeであってもO(log^2 n)になるので、インデックスを多次元にしてWHERE句で多次元indexを実現しようとすると当然insertに時間がかかる。一方で、1次元のindexが二つだという過程にたったとしても、insertを行うのにindexの更新すべき木の数が2倍になっているので時間がかかる。
なので、 索引を増やすとinsertの時間がかかってしまったりするので、readとwriteのパフォーマンスのトレードオフでどんな索引を作成スべきかという話を考えれば良い。
bigqueryは実際に処理されるデータとか金額は違うし、それがいつ決まるかもダイナミックに決まるので、よくわからない
byte billedというのは正確
BQは、project 1:many dataset 1:many tableの構造になっている。
datasetではcreate tableというのがWeb UIからできてファイルを追加できる
table のデータ構造<string, string, integer>などは、Schemaと呼ばれる。
Pub/Sub †
- PubsubはJavaじゃないとやってられない
- Pub/subは必ず2個以上のdeliveryをするものだと認識しなければならない。
Dataproc †
- Spark
- DataprocはHadoop系のサービスで、クラスタと呼ばれている計算機プールの中に、master 1:many worker がいるみたいなやつ。これで何ができるんだろうね?
- 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が失敗したら全てのジョブがキャンセルされて今後のものもキャンセルされる。
GCE †
- GCEからgsutilを使う方法
- gcloud init
- gcloud auth login
- service accountにGCSへのアクセスがあることを確認
- gsutilが使えるようになる
- 今回発表されたsolo-tenant nodesは、1台の物理サーバを複数のユーザーの仮想マシンで共有することを許さず、ある物理サーバには必ず同一ユーザーの仮想マシンしか稼働しないようにするサービスです。
- GCEがHost Hardware -> Hyperbvisorの上にVMが複数経っているが、このVMをそのプロジェクトのインスタンスだけで専有するサービス
- GCE上でOracleを使うのは無理。ライセンスの関係があるから。もちろんサポート自体はしているのだけど、これはかなり特殊なケース
- フリートライアルでは規約で、BitCoin?マイニングは禁止。GCE上でマイニングをしようとするとstockoutを引き起こす可能性があるのでbanされる。windows機でマイニングしようとしても同様。
- managed instance group
- 同じインスタンスを大量につなげる。GAE Flexと同じことをGCEレベルで行える。
- ステートレスアプリならばこういうことが可能だよ。
- Instance templates are global resources. The process of creating an instance template involves selecting a network and a subnet.
- プライマリIPアドレスは実はnetwork (0), default gateway (1), second-to-last (254), broadcast(255)が全て予約済み。second-to-lastが駄目なのは結構トリッキーなので注意
- gsutilでGCEのサービスアカウントにstorage read/writeつけたのにGCE上からstorageにアップロードできなくて謎だなあと思っていたら、
- gce startup-scriptでcronを設定する方法、screenで事前のアプリを立ち上げる方法
(crontab -l | grep -v -F "/home/minecraft/backup.sh" ; echo "*/1 * * * * /home/minecraft/backup.sh")| crontab -
screen -d -m -S mcs java -Xms1G -Xmx3G -d64 -jar server.jar nogui
Kubernetes †
GKE
クラスタ
ノード=マシン
プール=すべてが同じように構成されたノード インスタンスのサブセット(はじめに構成したときのノードはデフォルトノードプール)
ポッド=プロセス=Docker コンテナなどのコンテナが 1 つ以上リソースを共有。ポッド内のコンテナは、ポッド内で localhost を使用して互いに通信します。デフォルトでは、ポッドはクラスタのデフォルト ノードプール内のノードで実行されます。作成されたポッドは、自身のプロセスが完了するか、自身が削除されるか、リソース不足のために自身がノードから強制排除 (evict)されるか、ノードに障害が発生するまで、ノードに存在し続けます。
GKEはCluster生成時にGCEのインスタンスグループを作るので、そのグループに対してオートスケールの設定をすることができる。前述のPodの水平オートスケールと合わせると次のようなシナリオが考えられる。
アクセスが増える
Podに割り当てられたCPUリソース使用量が閾を超える
Podがスケールして増える
Podが増えたことでNodeのCPUリソース使用量が閾を超える
Nodeがスケールして増える
アクセスが減る
PodのCPUリソース使用量が閾以下になる
Podが減る
NodeのCPUリソース使用量が閾以下になった状態でクールダウン期間を経る
Nodeが減る
永久機関感ある。自分は実際にこの構成で運用し始めている。今後問題が生じたらまたエントリにしようと思う。
https://knowledge.sakura.ad.jp/16082/
GKEを理解したい
Docker: コンテナとイメージというのがあって、イメージからコンテナを作る感じ。コンテナをイメージにするコマンドもあるし、どのようにそのコンテナを作ったかを記録しておいてそれをスクリプト的に走らせて再現性高くコンテナを作ることもできる(Dockerfile)。DockerではDockerネットワークという仮想的なコンテナ間通信を行うことができる。
複数ホストでコンテナを起動して、コンテナ間通信するには、今回説明したことの他にも必要な設定があります。そこで活躍するのが、KubernetesやDocker Swarmなどのコンテナオーケストレーションツールになります(今はKubernetesがデファクトスタンダードとなっています)。
GKEでHello worldを言わせるやつ
https://medium.com/@gorlemkun/gke%E3%81%ABhello%E3%81%A8%E3%81%A0%E3%81%91%E8%A8%80%E3%82%8F%E3%81%9B%E3%81%9F%E3%81%84-google-kubernetes-engine%E3%81%AB%E7%84%A1%E3%82%92%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%99%E3%82%8B-7c8feea1921c
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 †
Google Cloud Tasks … GAE 内のサービスである「Task Queue」を、GAE 以外でも利用できるようにしたもの。 Google Cloud Pub/Sub リリース当初は、Task Queue をなくして Pub/Sub に一本化する予定だったそうだが、 Pub/Sub では吸収しきれない要望がたくさんあったため、存続決定とのこと。
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のほうが良くない?)
Spanner †
- Indexを動的に追加することがindex backfills
- これをやっている間は追加のリソースが使われる。
- indexを動的に追加すると、indexに整合しているかを確認するためのverification, refillの処理がバックグラウンドで走る。この間はCPU usageが高くなる
- 分散並列なRDBとしてSpannerは唯一無二 (2020年)
- Spannerにはクエリのパフォーマンスを測るためのビルトインテーブルが提供されている
- ZetaSQLというSQLパーサを内部的に使っている
- クエリオプティマイザ (QO) がバージョニングされている
- これはJOINなどの複雑なクエリの最適化に貢献している(局所的なものは効果がない)
- QOのバージョンは1, 2まであり(2020年)、QOの変更で壊れないようにするためにバージョンを固定化できる
Networking †
Route †
- routesというのは、要するに自分のネットワークルーティングテーブルに存在しなかった場合にどこにそれを聞きに活かせるかという意味。
VPC †
- GCPにマルチリージョンでプライベートネットワークを構成
- オンプレも可能(トンネル)
- 公共のネットワークを使わない
- Serverless VPCでApp Engine Standard, Cloud Runなどとも接続可能
GCEインスタンスとかだと、特に全部のサーバに正しくACL設定できるかとかかなり不安なので、VPCでセキュリティは大丈夫だよという感じにしておいたほうが安心だねとなる
これ読んで理解して。かなり良い記事
Cloud NAT †
Network tags †
- 要するに、CIRDで指定するのは連続を前提としていて辛いから、インスタンスに直接タグをつけて、グループAからグループBのポート80には通信ができますよーみたいな感じにするのが良いという話だと思う。
- 上りファイアウォール ルールを作成するときは、ソースを指定する必要がある
- ソースを定義するには、内部 IP アドレスまたは外部 IP アドレスの範囲を使用するか、特定のインスタンスを指定
- インスタンスを指定する場合は、ソースタグまたはソース サービス アカウントを使用
VPN †
- ネットワークにリージョンがあるというのはどういう意味?
- autoだと予めブロックされているレンジがあって、これがいろんなリージョンに分割されている。
- automatic->customに移すことはできるが、逆は不可能
- typeはautomaticとcustomで結構違う。
ゲートウェイ †
- デフォルトゲートウェイはパケットがパブリックに流れる。
- このネットワークを使って、Compute Engine 仮想マシン(VM)インスタンス、Kubernetes Engine クラスタ、App Engine フレキシブル環境インスタンス、プロジェクト内のその他のリソースを接続できます。
- ということは、VPCはApp Engine Standardをつないでいないということ?
- VPC ネットワークの特性は次のとおりです。
- 関連ルート、ファイアウォール ルールを含む VPC ネットワークはグローバルなリソースです。特定のリージョンやゾーンには関連付けられていません。
- サブネットはリージョン リソースです。サブネットごとに IP アドレスの範囲が定義されます。ネットワークとサブネットの詳細については、ネットワークとサブネットをご覧ください。
- プロジェクトにまたがったVPCは無理で、それをやるためにはVPC peeringを行う必要がある
Debugging †
- 一般論としてクラウドではリトライを前提としたシステムが要求されるし、ERRORは必要となる。
- 特に 503 temporally unavailableはリトライする。
- Googleにはcanonical_codeというのがある。例えば3はINVALID_ARGUMENT, 2はCANCELLED。多い順に番号が振られているかんじ。
Stackdriver Debugger †
- 実行中のアプリケーションを停止・処理速度を下げたりすることなく、コードの任意の場所でアプリケーションの状態を調べることができます。
- Stackdriver Debugger は、ログ ステートメントを追加することなく、アプリケーションの状態を簡単に表示できます。
- Stackdriver Debugger は、テスト環境、開発環境、本番環境などでのアプリケーションのデプロイに際して使用できます。このデバッガは、アプリケーションの状態をキャプチャしているときだけ、10 ミリ秒未満のリクエスト レイテンシが発生します。ほとんどの場合、ユーザーは気付きません。
Monitoring †
Stackdriver Logging †
loggingで
dremdataflot.googleapis.com/worker-startupやkubeletやshuffler0starrrrtupなどの指定をlog typeに指定することができる
KVMとかシステム的なやつの場合にはlogsの指定をそういう感じにすると良い。
back -> front -> cx
-> stackdriver
でcxとstackdriverは並列!backが成功していてcx, stackdriverが落ちている場合、frontがbackのものを渡せていないとかそういうやつだと思う。
言語 †
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を設定して全世界に公開することもできる(!?)
初期設定 †
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分)
課金 †
- GCE ぷりエンタティブ
- 100円で 1PFLOPS
- 1ハンバーガー1PFLOPS(100円で10^15回計算できると思うと胸熱だな、マクドナルドのハンバーガー食ってる場合じゃない)
- この視点を持つと何が面白いかというと、n<10^18をゴリ押し全探索するのは、1ケースあたり100,000円くらい支払う気があるなら現実的であるということですね(並列計算はできるものとします)
「一日何回くらい演算をしますか?」
「2×10^15回くらいですね」
「演算年数は?」
「30年くらいです」
「あそこにベンツが停まってますね」
「はい」
「もし演算やめたらあのベンツが買えるんですよ」
- MySQLがかなり高い StandardでHA構成で1ヶ月55USD, f1-micro 10GB SSD no-HAで10USD
- TranslateはDetectionが50000文字1ドル, Translateが25000文字1ドル。結構高い。
- Speech (音声認識) は1USD/1h
- Compute Engineはf1-microだと4USD/month。逆に、n1-highcpu-96(96コア90GB RAM)だと月1800USDとかになるので設定ミス注意。Preentitiveだと料金が1/5くらいになる。ちなみにf1-microだとapacheとかmysqlを走らせるだけでも厳しくて落ちまくるらしい。と-いうかFLOPS/sがわからないと全然わからないんだけど…f1-microとかってどうなってるの?ちなみにmicroは0.2vCPU, smallは0.5vCPU
逆に、f1-microを1000並列でPreentitiveで1日中動かしたとしても、12USDにしかならない!一方、1000並列n1-standard-1-preemptibleだとUSD 240.00 per 1 dayなので意外と高い
n1-ultramem-160, 160コア3844GBがプリエンプティブだと$5.3244/hで使えて面白そう。
GAE Standardは1時間あたりのインスタンス数が1だと、だいたい30USD/monthくらいになる
GAE Flexは1時間あたりのインスタンス数が1で1ヶ月動かすと、だいたい90USD/monthくらいになる。結構高いな。
Storageは結構やすい。40GB/Monthで1USDくらい。1TB/monthで26USD/month (multiregional). single reagionalとしても20USD/monthにしかならないので、multi-regionalは結構お得。Coldlineとかだと、1TB/monthが5USDだが、データ操作の方が2倍位高い
プリエンプトは一応終了までに30秒の猶予がある
Compute Engine は、プリエンプションの通知を ACPI G2 ソフトオフ信号の形式でインスタンスに送信します。シャットダウン スクリプトを使用して、プリエンプト通知を処理し、インスタンスが停止する前にクリーンアップ操作を完了できます。
SQLのmachine typeははじめstandardなのでちょっと高いよ
アクセスコントロール †
- IAM
- user 1:many role 1:many permission
- userには複数のroleをつけられる。roleはpermissionのセット。
- policy 1:many binding = (role, member^n)みたいな感じ。
- policyはorganization level, the folder level, the project level, or the resource levelのどれにもつけることができる。
各アカウントが得るpermissionは、その人の祖先のpermissionのORになる(上書きされたり消されたりはしない)
- primitive roles
- 実は歴史的なもので、IAMがなかった時代の名残みたいなやつ
- 本当はIAMを適切に使うのが適切
- 例えば、gcloud iam roles describe roles/viewerとすると、あらゆるサービスのread権限が付与されていることがわかる。
- Datastoreなど主要なサービスは、それ自身がread, write, adminのようなpredefined roleを提供している。これを使うとちょっと詳細なIAM設定ができるようになる
言語別比較 †
- Java一択
- Goはバイナリを出力するので、JavaとかPythonとは異なりランタイムとかを乗せる必要がなく、Docker配布が軽くなるので嬉しいという特徴がある