May 22, 2021
GCP Hands Off
データの種類でアーキテクチャを決める?
コンテナはオーバヘッドが少なくVM/GCEに比べ軽量高速、スケールアップ/ダウンに優れている
■制約が重要そうでまとめて記載したい
IAPとCDNの両立はできない
LBのbackendにgcsを設定したときはIAPが使えない
GKEのingressのLBに他のアプリのバックエンドを同居できない(GKEが上書き自動更新するから、ドメイン別になる)
IAPでGCEにOSログインする場合はAPI有効やIAPの設定、OSlogin系の権限が必要(Owner付与が楽)
ネットにでるのがapt updateのみでもNAT/Routerが要る
■VPCネットワーク
default VPCネットワークを削除(セキュリティが緩いため)
vpcネットワーク作成 サブネットIPレンジ 10.27.0.0/16-192.168.27.0/24 等で
private google accessはオンでいいのか?on
FWはひとまずなしで、だが大体ポートは22,80,443,8080?
別途firewallで下記を設定(ちなみにリクエスト側を許可すればよく、レスポンス側は自動)
bangboo-fw-allow-iap-ssh IAPからのSSHを許可 35.235.240.0/20 tcp:22
レンジはマニュアル https://cloud.google.com/iap/docs/using-tcp-forwarding#create-firewall-rule
bangboo-fw-allow-lb GFE(Google Front End)からのHTTPを許可 35.191.0.0/16,130.211.0.0/22 tcp:qll
レンジはマニュアル https://cloud.google.com/load-balancing/docs/health-checks#fw-rule
Cloud NAT(Router)を設定
https://cloud-ace.jp/column/detail260/
https://www.topgate.co.jp/google-cloud-network-security
■ハンズオン(GAE:php+FW+IAP)→GAEよりCloud runが良い
IAPはGAEが簡単そう(アクセスするのにGoogleの認証プロンプトを出す)
自前DNSにTXTレコードを設定>確認>IPが表示されAレコードやCnameも登録でき、SSL証明書も使えるようだ
しかし無くてもgoogle提供のドメインが使え不要
DNS(TXTレコード)による所有権の確認 - Google Search Consoleの使い方 (howtonote.jp) WinローカルにGCP SDKインスコし下記にapp.yamlとindex.phpを置いてcmd→ gcloud app deploy
C:\Users\おまはんのユッザー名\AppData\Local\Google\Cloud SDK\php
IAPを有効にしIAM secured userの権限とIAMでGAE viewer権限付与で@gmail.comユーザ等は見れる
外部ドメインを使うときはIdentityPlatform設定が必要そう
止めるにはinstanceを削除する(再度アクセスでinstanceが自動作成される)、IngressをInternal onlyにすると一応止まるか、楽だ
■ハンズオン(Marketplace: GCE+FW->Wordpress)
デフォルト:エフェメラル+インターネット公開なし(LB/IAP/NAT/Armor付けてから公開しようかと)
VMインスタンス ネットワークタグwordpress-1-deployment
FW:wordpress-allow-external ターゲットタグwordpress-1-deployment、ソース0.0.0.0/0 tcp0-65535
スナップショットのラベルはKVSで app : wordpress とか env : testとか
DBはステートフルMIG-永続ボリュームにできる?
■ハンズオン(GCE+nginx+FW+LB+IAP+Cloud NAT+Cloud armor)
●cloud shell terminal
gcloud compute instances list インスタンス一覧
●コンソール
デフォルトVPC NWを削除 > VPC NW作成 > サブネットIPレンジ 10.27.0.0/16-192.168.27.0/24等で
GCE VMを作成(Instance scheduleで起動-停止時間が入れられる、テンプレやグループに使えない?)
インスタンスを作って設定しスナップショットからOSイメージを作り量産すればいいが
instance template作成してinstance group作成してもいい。IGが中々できないならIGを開きエラーメッセージを見ること
OSはubuntu、API access scopeには"Allow full access to all Cloud APis"で
外部からアクセスさせずLB経由だけにしたい→外部IPがephemeralで止められない→作成時にnetwork>external ipをnoneで作成すること→
外へでれなくなるのでgcloudコマンドが通らない→CloudNAT(Router)も設定
インスタンステンプレートのメタデータ
起動スクリプトをファイル化できる
キーstartup-script or shutdown-script、値にパス
キーstartup-script-url or shutdown-script-url、値にGCSのURL
OSLoginをIAPにしてVM上の独自ID管理PW管理不要に
便利機能「OS Login」を使ってIAMでインスタンスへのSSH接続制限をする | apps-gcp.com キーenable-oslogin、値にTRUE、IAMで権限(compute OSLogin/IAP tunnel/gce系)、IAP API有効
権限もIAMで管理されるのでLINUX上の755等も不要なようだ(computeinstanceAdmin.v1を付けとく)
MIGとLBと同じヘルスチェックを使うことは非推奨
LBはより短い低い閾値にせよ
SSHの項目からview gcloud commandで好きなSSHターミナルからアクセスできるcmd出る
gcloud beta compute ssh --zone "asia-northeaset1-b" "instance-3" --tunnel -through-iap --project "bangboo-sandbox"
●SSHターミナル
gcloud init インスコ
sudo apt-get install nginx Webサーバインスコ、ブラウザで内部IPでアクセスしたかったが不可だった
sudo service nginx stop 止める、動かすのは sudo service nginx start
ps プロセス見る
curl http://10.117.0.19 nginxが動いているか確認
cat /var/log/nginx/access.log ログ確認
●nginx
/etc/nginxにあるconf系が設定ファイル
sites-enabled/default だけがあり cat default しdocument rootは/var/www/htmlと判明
ここへ移動 cd /var/www/html
sudo cp index.nginx-debian.html index.html コピー
sudo nano index.html で編集
設定変更後は sudo service nginx restart
使うときfw-bangboo-all-ingress-allow ingress - "all instances" - 192.168.1.255/32 に設定?
外部IP(普通LBとなるか)への制御はCloud armorのでdeny allowしてFWではあんまり考慮しない
armor-bangboo-all-ingress-deny ingress - "all instances" - 0.0.0.0/0 で設定完了まで止めとく
LB作成
VMインスタンスグループ(子インスタンス)作成(上で作ってなければ)
インスタンステンプレート作成
LBヘルスチェック(閾値)が要る
httpLBだと内部か外部か選択できる
httpLBならIPレンジが要る>VPC networkで同resionで使われていないものを設定
例10.55.20.0/22なら10.55.23.255まで使われているので10.55.25から使うとか
IAP(https)を見るとFWで開けてくれの指定がある
fw-bangboo-lb-gce-allow Source IP range:072.72.1.19/22, 69.11.8.0/16 tcp:80
IAPを見るとLBを設定するとFWはLBに対するものだけになるので不要との指示がある
fw-bangboo-http-ingress-allow 0.0.0.0/0(削除)
下記はインスタンス作成時の許可設定分で不要
default-allow-internal 69.11.0.0/9(削除) default-allow-http 0.0.0.0/0(削除)
これも不要?default-allow-http 0.0.0.0/0 tcp:443(削除)default-allow-icmp 0.0.0.0/0(削除)
default-allow-rdp 0.0.0.0/0 tcp:3389(削除)default-allow-ssh 0.0.0.0/0 tcp:22(削除)
IAP(ssh/tcp)を見るとFWで開けてくれの指定があるが開けるとhttpsに穴ができると出るし止め
fw-bangboo-lb-iap-tcp-allow Source IP range:072.72.2.0/20 tcp:all(sshターミナルを使う時だけFW開ける、通常priority9000)
IAPをONだけでは駄目で、FWで調整してGCEに直接アクセスじゃなくLBでやっとIAPが動くみたい
事前にgce.bangoo.com -> 117.072.19.255 (LBのIPはephemeralをstaticに変更)を自前のDNSに設定
(DNSのTTLを前日に3600から300に変更しておいたり、DNS反映期間があったり)
LBのフロントエンドでマネージド証明書を設定(ssl-policyを緩めで設定したが必要?)
オレオレ証明書は?
LBフロントエンドはhttpsでもバックエンドはhttpで
IAP-secured web app userロールを@gmail.comユーザに付与
IAPとCDNの両立はできない
LBのbackendにgcsを設定したときはIAPが使えない→ネット公開にしてVPN SCで制御?(元々ネットに面しているが権限がないだけ)、GCEにGCSをマウント?
FW調整
0.0.0.0/0 all deny priority2000>LB関連 tcp80 allow 1000/IAP関連 tcp allow 1000>(使用拠点のソースIP allow 500)
使用拠点のIPはLBを使うならArmorで設定すればFWへの設定不要
GCEの外部IPを止める:インスタンステンプレート作成時に外部IPnoneで設定(StaticIPを買って削除でもnoneにできなさそう)
必要なもの以外を止める:0-442, 444-65535で443のみ許可は駄目か?
Connectivity testでテストがIPアドレス等でできる(設定変更から実際の反映に時間が掛かるものがあるような気が)
apache benchでスケールするかテスト
Apache Bench を使って初めてのベンチマークテスト - Qiita sudo apt install apache2 abはapachに含まれるのでどれかのVMにインスコ
ab -n 1000 -c 100 https://gcp.bangboo.com/ でインスタンスが増えることが確認できる
Cloud armor設定
DDoS等を防ぐのでOnでいいのでは、adaptive protectionで優先度低いdeny設定
外部IPのdeny allowはこれでやる(web app firewallなのでな)、log4J対策等もここで弾く
一時止めるときは0.0.0.0/0 bad gateway等分かり易いエラーで止めるのが良いかも
IAPが前、Cloud armorが後ろ、そしてLBとか
Access context manager設定(+VPC service control)
Organizationの設定が必要(≒Cloud identityでドメイン必要?)IPアドレスやOS等でアクセスを制限できる
CloudSQL
APIライブラリからCloud SQL API、Cloud SQL Admin APIを有効に
平文通信→暗号化CloudSQL proxyバイナリをVMインスコ、ディレクトリ切る
proxyとアプリ設定を合わせる、proxyサービス起動
SQL用にsvac作成 lemp-gce-sql-01@
ログインユーザをこのsvacにowner設定
ロール付与 Cloud SQL Client、Compute Engine Service Agent、Compute Instance Admin (v1)、Compute Viewer
このsvacをGCEインスタンスのデフォルトsvacに設定
ユーザやdatabeseを作成、charaset: uft8mb4, collation: utf8mb4_bin
GCEでSQL proxyの設定(SSH開く)
gcloud auth list ログインユーザがsvacか確認
mkdir $HOME/download
cd $HOME/download
wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64
sudo mv cloud_sql_proxy.linux.amd64 /usr/local/bin/cloud_sql_proxy 変名
sudo chmod +x cloud_sql_proxy 実行権限設定
sudo mkdir /cloudsqlproxy ソケットになるディレクトリ作成
sudo chmod 777 /cloudsqlproxy パーミッション設定
sudo /usr/local/bin/cloud_sql_proxy -dir=/cloudsqlproxy -instances=bangboo-sql:asia-northeast1:mysql-01
↑Readyになってからコマンドが返るのに何分か掛かる
もう一つSSHを開くと下記コマンドが通る
mysql -u root -p -S /cloudsqlproxy/bangboo-sql:asia-northeast1:mysql-01
mysql> connect test;
mysql> show tables;
mysql> create table test.test (id int, name varchar(10));
mysql> insert into test (id, name) values (1, 'baka');
mysql> select * from test;
SQL proxyサービス化
Cloud SQL Proxy (TCP Socket)を systemd で起動させる - Qiita sudo vi /etc/systemd/system/cloud_sql_proxy.service
=====
[Unit]
Description = Cloud SQL Proxy Daemon
After = network.target
[Service]
ExecStart = /usr/local/bin/cloud_sql_proxy -dir=/cloudsqlproxy -instances=bangboo-sql:asia-northeast1:mysql-01
ExecStop = /bin/kill ${MAINPID}
ExecReload = /bin/kill -HUP ${MAINPID}
Restart = always
Type = simple
LimitNOFILE=65536
[Install]
WantedBy = multi-user.target
=====
sudo systemctl start cloud_sql_proxy 起動だが自動設定してリブートだけでいい
sudo systemctl enable cloud_sql_proxy サービス自動起動
sudo reboot now
Authenticating as: Ubuntu (ubuntu)でPWを求められる場合
systemctl list-units --type=service サービスの一覧確認
systemctl list-units --all --type=service 全サービスの一覧確認
service サービス名 status
service サービス名 start
FW/ArmorでIngress全止め or VMインスタンス停止、LB停止
■GCE MIGローリング更新
dev-stg環境でinstance templateを作ってprodでテンプレ置き置き換える感じ?
シングルVMでstg > OSイメージ > テンプレ化 > prod用MIGローリングアップデート設定
MIGは徐々に更新をいい塩梅で行う必要があるためローリング更新する
ロールバックはテンプレートを元に戻す設定をする、コミットは新しいテンプレートを設定するだけ
カナリアは2nd テンプレート追加項目でターゲットサイズで3台とか10%とか設定するだけ
ローリング更新(Update VMS)
インスタンスグループを開いてUpdate VMSに進む
a)Proactiveは最大サージ(一時追加のインスタンス数)、とオフライン上限を指定
b)日和見Opportunisticはオートスケールの増減時に新インスタンステンプレートに切替る(どうでもいいパッチ等)
サージ:追加台数、オフライン:停止台数、
オフライン台数を大きくすると一気に反映できる
それに合わせて見積もりサージを大きくする(料金は掛かる)
最大サージを 1、オフライン上限を 1 とすると、新しい VM が 1 ずつ発起動して、古い VM が 1 台ずつ落とされて行きます。
最大サージを 3、オフライン上限を 2とすると、新しい VM が 3 発起動して、古い VM が 2 台落とされ、1台落とされる。
インスタンスの再起動/置換(Restart/Replace VMS)
インスタンスグループを開いてRestart/Replace VMSに進むとローリングでインスタンスの再起動と置換ができる
a)再起動:オフライン上限のみを指定して VM のテンプレートを切り替え
b)置換:最大サージを指定することができるようになるだけ
■インスタンススケジュール
元来のサービスアカウントにcompute.instanceAdmin.v1が必要(コンソールでの設定時にエラーが出るので参考にして権限付与)
VMは一つのインスタンススケジュールにしか所属できないため、テスト後に本番スケジュールに入れなおす等の考慮が必要
インスタンススケジュールを削除するには、所属のVMを外す必要がある
最大15分遅れる場合がある。起動時間もその上加算する必要があるかも
■Monitoring
VMにOpsエージェント入れる
gcloud components update これ時間掛かるし不要では
https://cloud.google.com/stackdriver/docs/set-permissions.sh?hl=ja をダウンロード
terminalにアップロードし実行 bash set-permissions.sh --project=bangboo-ome
インスタンス ラベルで設定する GCEにラベルenv=test,app=omeを設定
gcloud beta compute instances \
ops-agents policies create ops-agents-policy-safe-rollout \
--agent-rules="type=logging,version=current-major,package-state=installed,enable-autoupgrade=true;type=metrics,version=current-major,package-state=installed,enable-autoupgrade=true" \
--os-types=short-name=centos,version=7 \
--group-labels=env=test,app=ome \
--project=bangboo-ome
起動しているVMにOS Config エージェントがインストールされているかを確認
gcloud compute ssh instance-1 \
--project bangboo-ome \
-- sudo systemctl status google-osconfig-agent
下記が返る
Enter passphrase for key '/home/sute3/.ssh/google_compute_engine':
google-osconfig-agent.service - Google OSConfig Agent
Loaded: loaded (/lib/systemd/system/google-osconfig-agent.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2022-04-11 18:34:26 UTC; 8min ago
Main PID: 1279 (google_osconfig)
Tasks: 11 (limit: 1116)
CGroup: /system.slice/google-osconfig-agent.service
└─1279 /usr/bin/google_osconfig_agent
Numpyが要る場合は下記でインスコ
sudo apt-get install python-numpy python-scipy python-matplotlib ipython ipython-notebook python-pandas python-sympy python-nose
ダッシュボード作成
Yaml設定を新規で作ればオーバーライドされる
sudo vim /etc/google-cloud-ops-agent/config.yaml
------------------
logging:
receivers:
laravel_log:
type: files
include_paths:
- /var/www/html/laravel/storage/logs/*.log
service:
pipelines:
custom_pipeline:
receivers: [laravel_log]
-----------------
# 反映
sudo service google-cloud-ops-agent restart
↑
sute16 asia-northeast1-b 2021/7/24(91日で33000yen-10/20位まで)
sute3 asia-northeast1-b 2022/2/20(91日で34500yen-5/20位まで)
nginx+PHP appサーバ+BigQuery+BigTable+CloudSQL(MySQL)+GCS+α?
[PHP]BigQueryのデータを取得する | yyuuiikk blog$ composer require google/cloud でインスコ
<?php
require 'vendor/autoload.php';
use Google\Cloud\BigQuery\BigQueryClient;
$keyfile = './credential.json'; //svacのkey
$bigquery = new BigQueryClient([
'keyFile' => json_decode(file_get_contents($keyfile), true),
]);
$dataset = $bigquery->dataset('dataset-name');
$table = $dataset->table('table-name');
$queryJobConfig = $bigquery->query(
"SELECT * FROM `project-id.data-set-name.table-name` LIMIT 100"
);
$queryResults = $bigquery->runQuery($queryJobConfig);
foreach ($queryResults as $row) {
print_r($row);
}
Google Cloud Storage にPHPを使ってファイルをアップロードする | カバの樹 (kabanoki.net)$composer require google/cloud-storage でインスコ
<?php
require __DIR__ . '/vendor/autoload.php';
use Google\Cloud\Storage\StorageClient;
$projectId = 'bangboo-prj';
$auth_key = './iam/credential.json';
$bucket_name = 'gcs-bangboo';
$path = 'img.png';
$storage = new StorageClient([
'projectId' => $projectId,
'keyFile' => json_decode(file_get_contents($auth_key, TRUE), true)
]);
$bucket = $storage->bucket($bucket_name);
$options = [
'name' => $path
];
$object = $bucket->upload(
fopen("{$path}", 'r'),
$options
);
<img src="https://storage.googleapis.com/gcs-bangboo/img.png">
SSLに対応したNGINXリバースプロキシを構築する手順 - Qiita nginxは静的コンテンツを高速に配信するように設計されている。 また、 リバースプロキシ の機能を持つため、背後にWebアプリケーションサーバを配置して動的なコンテンツを配信したり、ソフトウェア ロードバランサやHTTPキャッシュとしても使うこともできる。
Posted by funa : 12:00 AM
| Web
| Comment (0)
| Trackback (0)
May 22, 2021
GCP ログ・アセット調査 Logging/Bigquery information schema/Asset inventory
■Cloud Loggingで調べる
ログ エクスプローラを使用したサンプルクエリ | Cloud Logging | Google CloudLogging のクエリ言語 | Google Cloudとりあえず何かを出して、クリックして不要な要素をHideしていくといい
/// 誰が権限を変更したか
protoPayload.request.policy.bindings.role="organizations/123456/roles/unco"
protoPayload.methodName : "Setlam"
--操作者
--protoPayload.authenticationInfo.principalEmail="kuso@dayo.com"
変更の詳細は下記当たりに出る(デルタは変量の意味と思われる)
protoPayload.metadata.datasetChange.bidingDeltas
protoPayload.serviceData.policybindingDeltas
/// BQテーブル、ビュー作成
protoPayload.methodName="google.cloud.bigquery.v2.TableServiceInsertTable"
/// GCEのPyhon等のロギングを見る
resource.labels.instance_id="12234567898"
severity=WARNING
/// IAPのアクセスログ
監査ログからidentity-で探しログを有効化する(似たような名前があるので注意)
下記でLog exploreで検索するが、大体のアクセス時刻からリソースを類推して右クリックで絞る
logName="project/prjxxxxxx/logs/cloudaudit.googleapis.com%2Fdata_access"
resource.type="gce_backend_service"
/// BQの利用先
protoPayload.resourceName="projects/prjxxxxxxxx/datasets/dsxxxxxxxxx/tables/tblxxxxx
/// Scheduled queryの利用状況
resource.type="bigquery_dts_config"
/// コネクティッドシートでBQアクセスするスプシを調べるLoggingのクエリ
connected_sheets
bigquery.Jobs.create
bigquery.googleapis.com
docId
--データセット名
dataset ni_access_sarerudayo
--除外するにはマイナスを頭に付ける
-protoPayload.authenticationInfo.principal Email="washi@jyaroga.com"
■組織のログを一つのプロジェクトにまとめておく
組織のLog routerで全Syncを設定しておく、BQに吐き出す
select * from prj-log.org_audit_log.activity
where protopayload_auditlog.methodName='google.iam.admin.v1.SetIAMPolicy' or protopayload_auditlog.methodName='google.iam.IAMPolicy.SetIAMPolicy'
# Log exploreと少し違う
■BQインフォメーションスキーマ information schemaで調べる
//// DOL:
SELECT * FROM prj.ds.INFORMATION SCHEMA.TABLES
/// 組織のジョブ:
SELECT DISTINCT
creation_time,
information_schema.project_id,
user_email,
job_id,
cache_hit,
FROM
`region-us`.INFORMATION SCHEMA.JOBS BY ORGANIZATION AS Information schema,
UNNEST (referenced_tables) AS referenced_table
WHERE
--データコネクタからジョブ実行だと sheets_dataconnector が Prefix
job_id like "%sheets_%"
--参照先+
AND referenced table.project_id = "pri_xxx"
AND referenced table.dataset_Id = "ds_xxx"
AND referenced table.table_id LIKE "tbl_xxx%"
AND DATE (creation_time) BETWEEN "2022-06-01" AND "2023-01-30"
AND error_result IS NULL
/// プロジェクトのジョブ:
SELECT * FROM `pri_xxx.region-us.INFORMATION SCHEMA.JOBS`
,UNNEST (referenced_tables) AS referenced table
WHERE creation_time BETWEEN TIMESTAMP_SUB (CURRENT_TIMESTAMP(). INTERVAL 1 DAY)
AND referenced_table.dataset_id = 'ds_xxx'
--データコネクタからジョブを実行している場合 prefixにsheets_dataconnector、他にはscheduled_query等
AND job_id like "%sheets_%"
/// ラベル:
SELECT * FROM pri xxx.region-us. INFORMATION SCHEMA.JOBS
,UNNEST (referenced_tables) AS referenced_table
,UNNEST (labels) AS label
WHERE creation_time BETWEEN TIMESTAMP_SUB (CURRENT_TIMESTAMP(), INTERVAL 1 DAY) AND CURRENT_TIMESTAMP()
AND referenced_table.dataset_id = 'ds xxx
--データコネクタからジョブを実行している場合 labels connected_sheetsが含まれる
AND label.value = 'connected_sheets'
/// ジョブBYユーザ
SELECT * FROM `pri_xxx-region-us.INFORMATION SCHEMA.JOBS_BY_USER`
,UNNEST (referenced_tables) AS referenced_table
,UNNEST (labels) AS label
WHERE creation_time BETWEEN TIMESTAMP_SUB (CURRENT_TIMESTAMP(). INTERVAL 1 DAY) AND CURRENT_TIMESTAMP()
AND referenced_table.dataset_id = 'ds_xxx'
AND label.value = 'connected_sheets'
■Asset inventoryでアセット情報を調べる
コンソールでもGUIでAsset inventoryが見れるがコマンドでも情報取得できる
gcloud asset | Google Cloud CLI Documentationリソースの検索のサンプル | Cloud Asset Inventory のドキュメント | Google Cloudサポートされているアセットタイプ | Cloud Asset Inventory のドキュメント | Google Cloud例えばGKE使用しているアセット情報(GKE cluster)
gcloud asset search-all-resources \
--scope=organizations/組織の数字ID \
--asset-types=container.googleapis.com/Cluster
■監査ログのメソッド種類
⚫SetIAMPolicy (これはプロジェクトレベルのIAM設定が含まれ重要、GAS用Project用等も含まれていて基本となる)
⚫google.iam.admin.v1.SetIAMPolicy (リソースレベルのIAM設定、BQデータセットやテーブルやPubsubトピックやサブスク等が対象)
⚫google.iam.v1.IAMPolicy.Setlam Policy (これはリソースに対するSAの権限調整ではなく、SAに対する処理でimpersonate系等のSetIamが含まれる)
例えばBQの検知だとプロジェクトレベルIAM (SetIAMPolicy:各種権限付与) とリソースレベルの IAM (google.iam.admin.v1.SetIAMPolicy: BQdataset/tablet pubsub Topic/Subsc等への権限付与が含まれる)が必須となる
/// メソッドからの調査方法
目ぼしいメソッドでしばりログをBQ抽出
ローカルにJSONをDL、開いてクリップボードにコピー
スプシにコピペ、条件付き書式でnullや先頭行に色をつけて目検する
/// Set Iam系のメソッド(監査ログによる検知ではSet iamが誰がどこに行ったか見ればいいのでは)
メソッドの種類は1000以上あるが、SetIam系は下記の20辺りから
SetIAMPolicy, google.iam.admin.v1.SetIAMPolicy,
google.iam.v1.IAMPolicy.SetIamPolicy, beta.compute.instances.setIamPolicy beta.compute.subnetworks.setIamPolicy, google.cloud.functions.v1.CloudFunctionsService.SetIamPolicy, google.cloud.iap.v1.IdentityAwareProxyAdminService.SetIamPolicy, google.cloud.orgpolicy.v2.OrgPolicy.CreatePolicy, google.cloud.orgpolicy.v2.OrgPolicy.DeletePolicy, google.cloud.run.v1.Services.SetIamPolicy, google.cloud.run.v2.Services.SetIamPolicy, google.cloud.secretmanager.v1.SecretManagerService.SetIamPolicy, google.iam.admin.v1.CreateServiceAccountKey, google.iam.v1.WorkloadIdentityPools.CreateWorkloadIdentityPool, google.iam.v1.WorkloadIdentityPools.CreateWorkloadIdentity PoolProvider, google.iam.v1.WorkloadIdentityPools. UpdateWorkloadIdentityPoolProvider, storage.setIamPermissions
Posted by funa : 12:00 AM
| Web
| Comment (0)
| Trackback (0)
May 21, 2021
GCP part2
■Artifact registry
Artifact registryt APIの有効化
Cloud buildのサービスアカウントに付与(cloud build > setting)
操作をしようとするとエラーがでるなら下記のように付与
gcloud projects add-iam-policy-binding prj-xxx -member='serviceAccount:service-123456@gcp-sa-artifactregistry.iam.gservice.com' --role='roles/storage.objectViewer'
※事前にgcloud auth loginが必要
gcloud config configurations activate gcp-profile
gcloud auth login
gcloud auth configure-docker asia-northeast1-docker.pkg.dev
gcloud builds submit --tag asia-northeast1-docker.pkg.dev/chimpo-prj/kuso/image001
gcloud builds submit --tag LOCATION-docker.pkg.dev/PROJECT-ID/REPOSITORY/IMAGE
リポジトリ単位で権限管理ができる、リージョン選択できレイテンシー有利、CRコストはGCS計上だがAR計上で分かりやすい、新機能はARに実装される
リポジトリ名はハイフンOKだがアンスコNG、CRはイメージ名にアプリ名称を付ける感じであったがARはリポジトリ名にアプリ名称/イメージ名に版名を付ける感じに付与名が増えた
■ARホスト名(マルチリージョン)
us-docker.pkg.dev
europe-docker.pkg.dev
asia-docker.pkg.dev
■ARホスト名(リージョナル)
asia-northeast1-docker.pkg.dev
等々
Container registry は下記であった
gcloud builds submit --tag gcr.io/PROJECT-ID/IMAGE
CRで使用しているgcr.ioは元々米国のホスト、asia.gcr.io等が派生した
■CRホスト名(マルチリージョン)
gcr.io
us.gcr.io
eu.gcr.io
asia.gcr.io
※CRからARの移行でROUTEボタンで有効にすれば、CRへのコマンドはARに転送、コンテナもARにsubmitできる
※ARにコンテナを最初に置いておきたい場合は gcraneコマンドでコピーできる
■GCPディスク容量
コンソールからディスクに入り編集で容量追加
公開イメージのブートは自動変更される
カスタムイメージや非ブートディスクは手動変更が必要
手動方法は下記参照
/// BANGBOO BLOG /// - Linux cmd■GCPでsudo apt-get updateができないとき
wget https://packages.cloud.google.com/apt/doc/apt-key.gpg
apt-key add apt-key.gpg
■GCEでの通信(GCEのサービスアカウントとホスト上のOSLoginユーザの違い)
Google APIはSAで行く(SAに各権限を付けておく)
ただgcloud compute start-iap-tunel はSAで行くが
サービスアカウントユーザロールで実行者とSAを紐づけて行く?
(サービスアカウントに操作するユーザのserviceAccountUserの権限が必要)
その他のhttpsアクセスやls等コマンドはホスト上の実行者で行く
■IAPトンネルで内部IPでも外部に出る設定
#権限
ユーザ利用のGCEのSAのIAPトンネル権限を踏み台IAPにつける
SAに利用ユーザに対するserviceAccountUserの権限を付ける
#GCEインスタンスにSSHをし下記を実行
#自分に通信するプロキシ
export http_proxy=http://localhost:3128
export https_proxy=http://localhost:3128
#それを転送する
gcloud compute start-iap-tunnel --zone asia-northeast1-a gce-host-proxy001 3128 --local-host-port=localhost:3128 --project=bangboo-kuso-proxy &
#外部通信
git clone xxx
#止める(止め方が分からん)
ps からの kill -kill <iap ps> でできそうにない
gcloud auth revoke からの gcloud auth login の再ログイン?
export -n http_proxy
export -n http_proxy
■踏み台経由して他のインスタンスに接続
#踏み台に接続
gcloud compute ssh step-fumidai001 --project=bangboo-unco --zone=asia-notrheast2-a --tunnel-through-iap
#リストを出し該当ホストを見つける
gcloud compute instances list
#踏み台から他のへ接続
instance=bangboo-kami
gcloud compute ssh $instance --internal-ip --zone=asia-northeast2-a
#もしGKEなら接続前にstep-fumidai001でクレデンシャルが必要だったり、、、
gcloud container clusters get-credentials main -zone asia-northeast2-a --project bangboo-k8s
■curlで認証を受けながらのURLアクセス
●gcloud auth loginしていると、、
curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" https://宛先
●SAキーをアップロードなら、、
export GOOGLE_APPLICATION_CREDENTIALS="/home/aho/sa-key.json"
この環境変数はgcloudライブラリ/SDK等が認証情報として参照するようになっている
access_token=$(gcloud auth application-default print-access-token)
curl -H "Authorization: Bearer $access_token" https://kuso.com/api/endpoint
■Workload identity federation
使うサービスがIdPを持ってWIF対応していればSAキー無く使用できる(GCPの
SAは要る)
●GCP<-AWS,Github,EKS等OpenID connect/SAML2.0
事前設定)GCP SAを作成し権限付与
GCPにWIプールを作成
GCP WIプールで該当IdPを認証、外部アカウントを紐づける
1)UserがIdPにリクエスト
2)IdPがUserを割り当てたIDトークン(JWT)発行
3)IdPがIDトークンをGCPに検証
組織を限定するGCP設定
リポジトリを限定するGCP設定
4)GCPがWIF一時トークンを発行しUserがGCPリソースを使用
Workload Identity Federationを図で理解する - Carpe Diem (hatenablog.com)●GCP<-GKEクラスタは他の方法もある
●●GKEのSA設定(WIF以外)
1)ノードに紐付いたサービスアカウントを使用する
GKEクラスタ作成時にIAM SAを指定かGCEデフォSAが設定されるのでこれでGCP使用
GKEノードのワークロード全てで同一のSAが使用されPod毎に権限を分けられない
GKEの中身はGCEなのでGCEインスタンスのSAを見る?GCEが無いかも
GKEがAutopilotならWIFが有効でノードSAがGoogleAPI用には使えない?
2)SAのキーを Kubernetes SecretリソースとしてGKEクラスタに登録
IAM SA キーの有効期限が長く、手動でログローテーションが必要な点が懸念
エクスポートした IAM SA の流出リスクがある
GCP SAとキーを作成しキーをマニフェストに設定
●●GKEのためのWIF利用(推奨)
GKE node SA @project.iam.serviceaccount.com を
pool name - namespace の WIプールで
GOP SA の pool-namespace@project.iam.serviceaccount.contに紐づける
コマンドやマニフェストで詳しくはLink先で
ブールを有効化するとノードSAが使えなくなるので注意
■ZOZOの新米Google cloud管理者
新米Google Cloud管理者の奮闘記のその後 〜Organizationの秩序を維持する試み〜 - ZOZO TECH BLOG■データ
次世代データ基盤:データレイクハウスを Google Cloud で実現する (zenn.dev)- BigQuery Data Transfer Service:
Cloud Storage や Amazon S3、Azure Blob Storage など格納されているデータを BigQuery に転送するマネージド サービスです。主に構造化データや半構造化データをバッチ処理にて BigQuery へ直接転送したい場合に使用します。 - Storage Transfer Service:
Cloud Storage、Amazon S3、Azure Storage、オンプレミス データなどに格納されているオブジェクトやファイルを Cloud Storage へ転送するマネージド サービスです。主にオブジェクトやファイルをバッチ処理にて Cloud Storage へ直接転送したい場合に使用します。 - Datastream:
Oracle、MySQL、PostgreSQL といったデータベースのから BigQuery に対してシームレスにデータを複製できるサーバーレスな変更データ キャプチャ(CDC)サービスです。データベースの内容をリアルタイムに BigQuery へ反映したい場合に使用します。 - Cloud Data Fusion:
フルマネージドのデータ パイプライン構築サービスであり、ノーコード・ローコードで ETL を実装できます。データ転送のみの用途でも使用可能であり、特に プラグイン を使用することで、多種多様なデータソースに対応することが可能です。また、Datastream と同様に Oracle、MySQL、PostgreSQL から BigQuery への CDC 機能も提供されています。 - Dataflow:
Apache Beam のプログラミングモデルを使用して、大規模なデータを処理できるフルマネージドでサーバーレスなデータ処理サービスです。データ転送のみの用途でも使用可能であり、Google 提供テンプレート を使用することで、簡単にデータ転送の仕組みを構築することができます。 - Pub/Sub:
フルマネージドなメッセージキューイングサービスです。Cloud Storage サブスクリプション を使用すると、Pub/Sub メッセージを Cloud Storage に対して書き込むことが可能です。また BigQuery サブスクリプション を使用すると、Pub/Sub メッセージを BigQuery テーブルに直接書き込むことができ、 さらに BigQuery CDC を使用するとテーブルの行単位で UPSERT(UPDATE, INSERT)、DELETE が可能です。 - Database Migration Service:
MySQL や PostgreSQL から Cloud SQL や AlloyDB に対して、マネージド サービスへのリフト アンド シフト移行やマルチクラウドの継続的レプリケーションを行います。オンプレミスや他クラウドからのデータベース移行が必要な場合に使用します。
↓
- BigQuery:
SQL によってデータ変換を行います。ルーティンとして、ストアド プロシージャ や ユーザー定義関数、テーブル関数 、Apache Spark 用ストアド プロシージャ が使用できます。また、リモート関数 を使用すると、Cloud Functions と Cloud Run にデプロイされた関数をクエリから呼び出すことができます。 - Dataflow:
前述の通り、フルマネージドでサーバーレスなデータ処理サービスです。同一コードでバッチとストリーミングの両方に対応できるという特徴があります。また、通常の Dataflow だと水平方向のみの自動スケーリングとなりますが、Dataflow Prime を使用することで、垂直方向へも自動スケーリングが可能です。 - Dataproc:
Hadoop と Spark などのデータ処理ワークロードを実行するためのマネージド サービスです。既存の Hadoop / Spark を移行する場合やプリエンプティブル VM または Spot VM によってコストを抑えたい場合に適しています。 - Dataprep:
分析、レポートなどに使用するデータを視覚的に探索、データクレンジングできるデータサービスです。特にUI操作でデータ探索やデータクレンジングが可能なことが特徴です。 - Cloud Data Fusion:
前述の通り、ノーコード・ローコードで ETL を実装できるフルマネージドのデータ パイプライン構築サービスです。データのコネクションだけでなく、ETL に関する様々な プラグイン が用意されていることが特徴です。
GKEやRunに信頼できるコンテナイメージのみをデプロイするための管理
ポリシーや承認者を設定してOKのもののみ許可する
コンテナ脆弱性スキャン強弱の設定等
■reCaptcha
v1はゆがんだ文字を入力するもの、v2は画像を選択し私はロボットではありませんとチェック、v3はWeb行動履歴等をスコア化して自動的に判定を行う操作不要のもの(GCPコンソールで結果分析もできる)
■BQ DuetAI
BQ studio内にnotebookがありpythonが使える(現在プレビュー
MLモデルを作成し使用できる
Posted by funa : 12:00 AM
| Web
| Comment (0)
| Trackback (0)
May 20, 2021
GCP
■GCP(Google Cloud Platform)
https://console.developers.google.com/
GCPを活用するスキルを問われる「Associate Cloud Engineer」
インフラストラクチャの知識を問われる「Professional Cloud Architect」
データと機械学習の知識を問われる「Professional Data Engineer」
マシーンラーニング:教師ありをベースにパターンを線形として認識し相似のパターンを見つける
ディープラーニング:人間が把握できる次元のデータ構造ではない多次元でパターンを見つける
線形検索みたいなもんか
■GCP
https://techblog.gmo-ap.jp/category/gcp/https://tech.zeals.co.jp/entry/2019/01/08/094054https://techblog.gmo-ap.jp/category/tensorflow/情報源
Solution Design Pattern (gc-solution-design-pattern.jp)google-cloud-jp – Mediumサポートを付けるとGoogleに聞き放題になったりする
サポートのケースは組織レベルでみると全プロジェクトのケースが見れる
3か月間300 ドル分だけ無料
https://console.cloud.google.com無料枠
GCE:プリエンプティブル以外の1つの以下のe2-micro VMインスタンスと30GB/月の標準永続ディスク
オレゴン: us-west1
アイオワ: us-central1
サウスカロライナ: us-east1
GCS: 5GB/月のRegional Storage(米国リージョンのみ)
無料だとBigQueryのDML(insert)ができないらしい
予算とアラートを1円で設定(通知チャネルにSMSとメール設定)
月額のプロダクトを日割レポートで見ると2月の日割りは高く見え、3月は安く見える
為替の影響は月初から適応されるので円安だと高いよ
辞めるときはプロジェクトをシャットダウン&請求先アカウントの閉鎖
1)プロジェクトの閉鎖
Google Cloud Console > IAMと管理 > 設定 > シャットダウン
2)請求先アカウントの閉鎖(原因不明だが下記画面が出るときと出ないときがった)
Google Cloud Console > お支払い > (左ナビ)アカウント管理 > 請求先アカウントの閉鎖
※お支払い>マイプロジェクト>アクション>無効や請求先変更ができる
セキュリティは使用GoogleアカウントのSMSによる2段階認証、信用するデバイスの設定があるようだ
GKE, Cloud SQL, Dataflow等
【GCP入門編・第3回】難しくない! Google Compute Engine (GCE) でのインスタンス起動方法! | 株式会社トップゲート (topgate.co.jp)【GCP入門編・第12回】 BigQuery を使って気軽にビッグデータの解析を行ってみよう! | 株式会社トップゲート (topgate.co.jp)【GCP入門編・第25回】 Cloud SQL for MySQL で Master-Slave 構成を組もう! | 株式会社トップゲート (topgate.co.jp)【GCP入門編・第29回】Cloud Load Balancing で Web アプリケーションにロードバランサーを設定する | 株式会社トップゲート (topgate.co.jp)【初心者】GCP Identity-Aware Proxy (IAP), Access Context Managerを使ってみる (WEBサーバへのアクセス制限) - Qiita■IAM(Identity and Access Management)
https://cloud.google.com/iam/docs/overview?hl=ja
https://cloud.google.com/iam?hl=ja
IAMベストプラクティス https://cloud.google.com/iam/docs/using-iam-securely
操作方法 https://cloud.google.com/iam/docs/how-to?hl=ja
ロール https://cloud.google.com/iam/docs/understanding-roles?hl=ja
https://www.isoroot.jp/blog/1244/
https://medium.com/google-cloud-jp/gcp-iam-beginner-b2e1ef7ad9c2
//IAMの機能(RBAC認可:role based access control)
機械学習を使ったスマート アクセス制御の最適化
デバイスのセキュリティ、IP アドレス、リソースタイプ、日時などの属性に基づいて、リソースに対するきめ細かいアクセス制御ポリシー
権限の認可、解除、委任に関するすべての監査証跡の履歴
ユーザーとグループのプロビジョニングや管理、シングル サインオンの設定、2 要素認証プロセス(2FA)
//IAMポリシー
IDをGroup(●●部)にアサイン
Members(Group等)にRoles(●●役)をアサイン
MembersとはグループやドメインやID(Googleユーザアカウント、サービスアカウント)
Roles(●●役)にPermissions(権限)を付与
ロールは作成ができ●●世話役みたいな感じか
permissionsは権限で「resourcemanager.projects.get」等でロールに紐づける
個人や無料アカだと組織がない?→フォルダが作成できない?
組織がないとグループが作成できない→グループがないとIDにRoleを付与するしか
フォルダは組織ツリー状でリソース管理、組織改編が多いならプロジェクトフォルダでも
各フォルダに対してそれぞれメールグループを定型(folder-admin/dev/lead/member/parttime/etc)で持たせ
メールグループへのユーザ出し入れで権限の管理をするのが良さそう
IAMやServceAccountの一覧には出てこないが存在するIDがある、実際に権限を付与できるかで存在確認する(TFで作成の場合?)
ポリシーはMSのGPOみたいものも組み込みで存在する
サービスアカウントはAPI用、人が使うことは基本想定されていない(impersonate等できるが
ユーザが削除になっても権限やリソースは残る?30日位はdeleted:になって消えるのでは
プリンシパルには@gmail.comのGoogleアカウントやWorkspace契約のある組織ドメインのGWSアカウント等があり、独自ドメインでもGWS契約がない場合は@gmailのように登録しGoogleアカウントにして使用する
GCPはGWS gmailメールの変名に追従して権限も付与状態も変化がなく問題がない
しかしterraformは追従しないためtfファイルでメールを使っている場合は変更する
外部ドメインのユーザの場合はメールグループ単位でのロール付与が効かず個別アカウントで付与する必要がある?あるいは組織ポリシーを開けっ放し?
APIを有効化せんと何もできないが、するロール roles/serviceusage.serviceUsageAdmin
メールグループの権限関係の確認方法
仕組み:祖->親->子、上の権限は下も持つ
権限から確認する、所属から確認するの両面で確認
1)権限を持っている全ての子をリストアップ
2)所属しているメールグループの全ての親をリストアップ
//画面上部のプルダウンからプロジェクトを選択できない場合
(BQのデータセットにのみ権限がある等)
1)BQの左ペーンでデータセット名を検索し(すべてのプロジェクトを検索するため2回必要)スターを付けて代替とする
2)データセットレベル権限でもURLパラメータ付きだと選択ができる
http://console.cloud.googl.com/bigquery?project=bangboo-kuso-project
3)IAMの画面で何かしらresourcemanager.projects.listを含むロール、つまりBQ data viewerでOKだがプロジェクトレベルの権限を付与しておく(権限付与後にログインしなおしが必要)
※jobuserがないとBQコンソールでプルダウンできない訳ではない(jobuserなしでOK)
※グループメールの深い階層で付与されていても影響はしない
//リソース
階層:Organization > Folders > Project > Resource(Google Cloud services)
割り当て:日や分に対してのデータ量の上限等を設定
必要以上に権限を付与しない
組み込みロールが多い、改変してロールを作るか
権限はサービス名.リソース.動詞という命名規則
プロジェクト名はGCPグローバルで名前空間を共有しており、企業名等でprefixするのがいい
プロジェクト毎にメールグループを設け、権限はメールグループの参加で管理したい
//リージョンとゾーン
リージョン:データセンターの存在場所、ゾーンをいくつか持つ
ゾーン:障害ドメイン区画(単一障害点を避ける形で環境設計したい)
Google Cloud SDKをインストールすればコマンドラインが使える
BQは同一リージョンでないとJoinができない、ゾーンはマルチで良い
APAC: asia-east(台湾、香港)、asia-northeast(日本、韓国)、asia-south(インド)、asia-southeast(シンガポール、インドネシア)、australia-shoutheast(オーストラリア)
NA: northamerica-northeast(モントリオール、トロント)、us-central(アイオワ等)、us-east(バージニア等)、us-west(ネバダ等)
リージョンとゾーン | Compute Engine ドキュメント | Google Cloud//サブネット、Shared VPC
Shared VPCホストプロジェクトに対しサービスプロジェクトを設定しプロジェクト間を共有
サブネットは通常リージョン内?レガシーだと完全に仮想で自由なサブネット?
//Cloud Shell
Google Cloud Shell の 10 の知っておくと便利な Tips | Google Cloud Blogファイルのアップロードやダウンロードが可、コードエディタもありブラウザで完結
Webアプリのプレビューも可
f1-microのGCE一時インスタンスがプロジェクトをまたいだ永続ディスク5GBで起動されている
gcludやdocker,bash,sh,vim,nano,pip,git,mysql等がプリインスコされている
5GBあるのでインスコもできる sudo apt-get install gawk
Cloud Shell VM の Zoneを知る:curl metadata/computeMetadata/v1/instance/zone
Ctrl + b キーを押してから % キーを押すとtmux により ウィンドウが左と右のペインに分割
Cloud shellのグローバルIPを取得できる
curl http://ifconfig.me/
リスト一覧を出すgcloud cmd
gcloud projects list --filter='bangboo-' --format=json | grep -oP '(?<="name": ")[^"]*'
どのgcloud cmdにも使えるワイルドフラグ
--access-token-file, --account, --billing-project, --configuration, --flags-file, --flatten, --format, --help, --impersonate-service-account(人がcmdを打つ場合でも成りすませる、その人にprjレベルの権限が必要), --log-http(cmdでエラーがでるならコレを、詳細が出る), --project, --quiet, --trace-token, --user-output-enabled, --verbosity
各言語でのSDKを使ったプログラムを実行する際の認証を得るために使います
gcloud auth application-default login
ローカルで以下のようなGCP系CLIを実行する際の認証を得るために使います
gcloud config configurations list
gcloud config configurations create unko-profile
gcloud config set account unko@dot.com
gcloud config set project onara-project
gcloud config configurations activate unko-profile
gcloud auth login
■GCE
Marketplaceを使えばアプリを数クリックでデプロイできる
永続ディスク…NWストレージ、SSD永続ディスクも選択できる
ローカルSSD…高性能、永続ではなく一時的
非マネージドインスタンスグループ インスタンスをIGに紐づけるだけ
ステートレスMIG 自動スケーリング(Webフロントエンド等)
スケジュールでもスケーリングできる(cronや予測も)
ステートフルMIG 設定を保持可(DBやデータ保持必要なstatefulなアプリ等)
インスタンス名やIPやディスクやメタを維持する、部分的に外部化ステートレスにして自動化等も
ゾーンMIG=シングルゾーン、リージョンMIG=マルチゾーン(最大3ゾーン)
プリエンプティブは24時間までだが20%課金だけで安い
インスタンスにサービスアカウントを改めて設定するとGoogleAPIはこれで実行される
改めて設定しないとデフォルトSA
操作自体はSSHで入るユーザで操作をする
設定はsudoして行うことが多く例えばcronはroot実行になっている
SSHで入ったユーザで設定するなら所有者/グループ/他のパーミッションを設定した上で
■マネージドクラウドDB各種
ホワイトペーパーPDF■Bigquery
/// BANGBOO BLOG /// - BigQuery/// BANGBOO BLOG /// - GCP ログ調査 Logging/Bigquery information schema■GCS
http(s)で公開可(そもそも公開しているがAllUsersやAllAuthenticatedUsersや各ユーザに権限がついていないだけ)
Nearline…3カ月でアクセス等(全ファイルを1度閲覧)
Coldline…1.5年でアクセス等長期アーカイブ
(standard以外は最低保存期間の縛りがあり早期削除でもお金が掛かる)
5GBまで無料、リージョンで値段が違う、保存/NW/取得/操作で課金
nearlineの保存は半額で取得と併せstandardと同じ金額になるが操作費高い
coldline/archive storageでも長期保存はせずできれば削除する、できないならポリシーでcold/archiveへ移動
最低保存期間の縛り(90/365)があり早期削除でも請求、その期間は置いておく
autoclassだとニア→コールド→アーカイブといい感じにしてくれるが1000ファイルにつき0.0025追加料金
※128kb以下は適応されずstdで追加料金もかからない
Autoclassが安全便利でファーストチョイス?単価から370kb程度以下で損する
バケット作成時に設計をしておく(バケット編集でAutoClassが変更できるようになった)
ライフサイクルを決めて削除条件も決めておく
バケットを細かく分けた方がよいかも(バケット内でフォルダを作るとコマンドが遅く管理が面倒)
ファイルサイズが大きいもの=AutoClassが良いかも
ファイルサイズが小さいもの=OLMでライフサイクル設定(クラスと削除)
ログ保存用途ならColdline/Archive設定+OLMでの削除設定
gsutil ls -lR gs://aaaa バケット内の各ファイルのサイズと、最終行でオブジェクト数と合計サイズが分かる(オブジェクト数はフォルダも一つとカウントされる、フォルダはサイズが0)
※GCSの注意点
早期削除料金の発生がリスク
ストレージクラスはファイルごとに設定がある、バケットはデフォルト設定だけ、AutoClassはバケット
オブジェクトライフサイクルマネージメントOLMでストレージクラスの変更すること
早期削除料金は削除、置換、移動、クラス移動でかかるが、OLMのクラス移動ではかからない
OLMの変更はファイル単位で変わりバケット設定をみてもクラスが分からない
手動(gsutilやAPIという意味)で変更するとStd以外は早期削除料金で高額化の恐れ
ただしOLMは若返りの方向へのストレージクラス変更はできない
gsutilやAPIでなら若返りストレージの変更ができる
Std以外は保存と閲覧の使用としたい、なぜなら、置換はファイル編集が該当するためファイルサーバとできないから
費用は保存費、オペレーション費、NW費、Std以外は取得費等からなり、費用は利用サイズの影響が大きく、通常は保存より利用の費用が高くなる
早期削除料金はStd以外で削除されたり更新がかかればファイル単位でかかる
早期削除料金は最低保存期間分がかかるがファイル作成日を元に計算されどのストレージであっても日数としてカウントされる
LoggingをBQに吐き出しておけば、利用者やバケット作成者が分かる protopayload_auditlog.methodName = 'storage.bucket.create' とかの条件
■GCP Cloud asset inventory
5週間分の履歴が保管される
CAI exportにより任意のタイムスタンプでBQあるいはGCSに履歴情報を吐き出す
コマンドやライブラリでダンプが可能
gcloud CLIのgcould asset search-all-resourseコマンドにより設定
BQに吐き出し各種状況のチェックやポリシーのチェックに活用
権限の確認もコマンドでできる
gcloud asset analyze-iam-policy --organization=123456 --identity="user:fack@unko.com"
■Cloud logging
毎月取込50GBまで無料、取込0.5$/GB+保存0.01$/GB、2種類ありAuditLogで有効無効化
管理アクティビティログ 13ヵ月400日デフォ有効(_requiredログバケットは取込もデフォ期間保存も完全無料)
データアクセスログ デフォ無効(有効にしてもデフォ保存期間30日は無料、50GBを超える取込が有料)
※つまり50GBを超えた取込、あるいは保存期間を伸ばした分が有料
BQ streaming insert0.05$/GB+BQ保存(10G無料)0.02/GB=0.07$/GBでBQ化し保存が得
長期保存が必要なものだけエクスポート
集約エクスポート
ログ取集前にログシンク(取込費がかからない)
サンプル1%等で絞る等
400日の_requiredに入らないものが30日の_defaultに入る
Logルータのシンクでフィルタ、サンプリングしLogバケット/GCS/BQ/Pubsubに転送
requiredでなくdefaultに入る時にLogルータを設定しフィルタを掛ければ減る
自動でSAが作られるので作成や権限付与は不要
包含フィルタが空なら全ログ
クエリsample(insertId, 0.10)で10%のサンプル
Logバケットのdefault30日は変更できる
全ログをBigqueryに入れるには組織プロジェクトで転送を設定すればいい
クエリ:Loggingをクエリで見る、Logルータのシンクをフィルタ(サンプル)する
■Monitoring
ダッシュボードはサンプルから作ると楽
MQLで改変、クエリを実行するとエラーメッセが出るんで
fetch gae_instance::appengine.googleapis.com/flex/cpu/utilization | { top1, max(val()); bottom 1, min(val()) } | UNION
■APIキー
APIキーを発行することで、外部アプリから利用できるようになる。各種使えるが強力なためAPIを絞る等制限を入れた方がよい、アクセス元のIPアドレスやリファラーで縛る等も
API キーを使用して認証する | Google Cloud【要確認】Google Maps Platform APIキーの取得方法と注意点 | ワードプレステーマTCD (tcd-theme.com)■サービスアカウント
デフォルトでは上限100個
svacキーはPWと同じ、できるだけ発行せず慎重に管理、gitにUP厳禁
svac名や役割を広くしない、強すぎる権限は付与せず最小限の権限で
GCEデフォのsvacは使用しない(Editorを持つから)
サービスアカウントはサービスを有効化したときに動作用に自動作成されたり、別途手動でも作れる
所属のプロジェクトが削除されると:
サービスアカウントは削除できなくなり、権限が残るため権限は個別削除が必要になる
サービスアカウントの権限が残るが、他のプロジェクトで使用できる
一定期間が経つとサービスアカウントの権限も自動削除される
>プロジェクト削除前にサービスアカウントの無効にするのが望ましい
IAMでsvacにロールを付与、IAM>svacでユーザにsvacに対する管理ロールを付与できる
組織ポリシーでsvacキーの使用を特定のプロジェクトに制限した方が良い
できればキーを作成せず他の方法を
workload identity(gke)、workload identity federation(serverless)
SAMLみたいなものでGKE、OpenID、AWS、Azure、ActiveDirectory、GoogleCloudAPIは対応している
一発使用ならimpersonateで成り済ませば一連のgcloud cmdは実行できる(下記参照)
SAキーの管理方法
キーの削除、あるいはIAMコンディションにより権限側の変更、あるいはVPCサービスコントロールで制限位しかない
有効期限の設定は無い、キーローテート機能もなくコマンドで自作するしか(削除と作成をするだけ)
キーローテートを要求するため、キーは各々で発行してもらう
手前でキーを発行した方が、キー削除や追跡ができるがローテートの手間がある、手前だと権限付与も少なくできるが、、
svacキーはRSA鍵ペア、秘密鍵でJWT署名なしトークンを作成(JWT=json web token)
GCP内ではキーが自動rotateされている
外部の場合は手動や仕組みでローテーションしたい
開発環境ではクライアントライブラリとgoogle application credentials環境変数を使い隠匿する
サービス アカウント キーを管理するためのベスト プラクティス | IAM のドキュメント | Google CloudGoogle Cloud SDKのインストールと認証の設定について - TASK NOTES (task-notes.com)概要 / アジェンダ - Infra OnAir (cloudonair.withgoogle.com)秘密鍵さえあれば成り済ませ追跡が困難で誰が利用したか等が分からないのでsvacキーは使いたくない
svacキーは10個作成できる
/// svacキー使用方法
サービスアカウントのキーを作成しローカルに保存
SSHでGCEのVMに内容をコピペしてキーファイルを作成
下記でSAとしてログイン
gcloud auth activate-service-account ketsu@un.com --key-file /home/ketsu/sakey.json
cloud shell terminalでもファイルをアップロードできるのでup後下記でOK
gcloud auth activate-service-account ketsu@un.com --key-file sakey.json
ログオン切替
終わるとき rm sakey.json
shellセッションごとに環境変数でkeyを設定する方法も
認証のスタートガイド | Google Cloud/// サービスアカウントキーを発行せずにサービスアカウント権限を使う
IAM and Resource Manager API を有効化
サービスアカウントに使いたいロールを付与(roles/accesscontextmanager.policyAdminとか)
自身にroles/iam.serviceAccountTokenCreatorを付与
叩くgcloud info --impersonate-service-account=chinko-compute@developer.gserviceaccount.com
※tfだとproviderにimpersonate_service_accountを追加する形
設定するにはこれらしい
gcloud config set auth/impersonate_service_account chinko-compute@developer.gserviceaccount.com
svacを指定するならこれでもいいがKeyがいる
gcloud auth activate-service-account chinko-compute@developer.gserviceaccount.com --key-file=/himitsu/dame_key.json --project=bangboo-kuso
ログインユーザ確認で要確認
gcloud auth list
gcloudコマンドのリファレンス
■セック
Google workspace googleアカウント(特定の経路:IP以外は無効)
組織ポリシー(GCP)
Google Cloud 組織ポリシー - Qiita serviceuser.services deny compute.googleapis.com デフォルトcomputeなし
compute.skipDefaultNetworkCreation enforced=true デフォルトcompute nwなし
compute.vmExternalIpAccess inherit_from_parent=true
iam.allowedPolicyMemberDomains inherit_from_parent=true 対象組織 外部ユーザ禁止
→allusers/allauthuserも影響する(このためGCSもallusersが設定できず公開にはならない)
iam.allowedPolicyMemberDomains inherit_from_parent=false 対象prj 外部ユーザ許可
storage.uniformBucketLevelAccess enforced=true GCSアクセス制御を均一
storage.publicAccessPrevention=true 公開しない(allusersも消える、逆にoffってもallusersも要る)
sql.restrictAutherizedNetwork enforced=true CloudSQLのネットワーク制限
compute.restrictLoadBalancerCreationForTypes allow=in:INTERNAL LBは内部だけ許可
compute.restrictLoadBalancerCreationForTypes allow=all=true 対象prj LB許可
compute.disableSerialortAccess enforced=true シリアルポートアクセスの制限
compute.disableSerialortAccess enforced=false 対象prj シリアルポートアクセスの許可
BeyondCorp Enterprise(VPNレス、なお下の各要素はこの為だけということではない)
┣ IAP
┣ IAM
┣ Access Context Manager(VPC Service Controls:IPとかメールドメインとか)
┗ Endpoint Verification(Chrome機能拡張)
Cloud armor(WAF)、FW
危険な設定はアラートを出したい:security command center、cloud asset inventoryをBQに出し定期スキャン
BigQueryの高額クエリはアラートを出したい
セキュアなBigQueryの運用方法 - Speaker Deck IAM condition: 20時以降はアクセスできない等時間やリソースで権限制御
VPC-ServiceControls: VPC+FWで制限を掛けられなかったIPやIDで制限を掛ける(クレデンシャル漏洩防御)
LBのバックエンドをGCSにするとIAPが使えない時も
TF)perimeterで境界を設定してaccess leveで超えれるものを定義
危険で user explicit dry run spec = trueでテストしながら falseで本番化
statusが本番用、specがドライラン用で一旦statusを消してテスト
restricted_services = storage.googleapis.com ならGCS
resource
access_level
GCPでセキュリティガードレールを作るための方法と推しテク - Speaker Deck サブネット作成の際はセキュリティの観点からフローログを15分で取る
監査ログを有効に
ContainerResistryの脆弱性スキャンを有効に
ログ:データアクセス/ポリシー拒否は30日、管理アクティビティは400日
BQにバックアップしたい
SecurityCommandCenterで脆弱性を検知
■タグとラベル
組織ポリシーはタグでconditionを指定した上で設定できる
タグは権限管理のための機能
タグは事前に組織レベルでタグを作成する、その後にリソースに対しタグ付け
FWで使うのはネットワークタグで種類が違うと思われる
ラベルはリソース整理や課金整理のための機能
■ネットワーク
外部IP
External IP addressで取得、300円/月位、通常一つは自動で割り当てられる
PoP(Point of presence)
世界70か所でGCPとエッジ(ネット)接続
NWトポロジーで通信が可視化でき通信コストが分かる
詳細開くのは片側だけにすると使用帯域が表示される
■課金
BillingのBilling ExportからBigQueryにダンプができる
■サービスイン、導入、廃止
どういうステップかよくわからんが
GA(Generally available)
サービスに関する重要なお知らせ:MSA(Mandatory service announcement)
Deprecated
Decommission
■他
///gcloudをプロキシで使う環境設定とか
https://qiita.com/tora470/items/bc00bef8cba9f9acecc7
///Loadbalancer
IAPはhttp LB/GCE/AppEngineに
Internal LBにExternal IPは無理
ついでにIAP tunnel userの権限で踏み台が作れる+OS Loginで認証強化
OS LoginはIAPの認証機能でSSH上でGCEインスタンスにログインできる代物
GCPがSSH keyとIAMをGCEに準備してくれる
ついでにリバースプロキシ(nginxとかで作る)
LBみたいなもんだがプロキシでキャッシュを返す
代理代表サーバとなりWEBサーバ界のFWみたいな役割もできる
///NoSQL
=not only sql、分散kvsだったりの非構造化データ、下記2つのみ提供
キーを指定してCRUD(追加、取得、更新、削除)
キーの範囲かキーの前方一致でのスキャン
///bigtable
高スループット低レイテンシー読み書き速く膨大なユーザや数千万件テラ以上で
gmail、GA、マップ等々で使われている
///cloud functions
サーバレスでRESTみたいな形でURLでサーバアプリを実行、Node.js/PHP/Python等のコードが直接コンソールに掛ける
curl https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME -H "Authorization: bearer $(gcloud auth print-identity-token)"
↑curlでいいなら、コンソールで[未認証の呼び出しを許可する] 設定 + allusersでも可
///Pub/Sub
パプリッシャーからサブスクライバーにメッセージ転送、順序設定可、大量データを1件ずつとか
publisher -> topic : メッセージ -> push型 subscriber
publisher -> topic : メッセージ -> pull型 subscriber
-> cloud functions/runに連携したり、cloud schedulerから連携をしたり
BQ テーブルにデータをエクスポートする Dataflow ジョブ
GCS でデータをテキスト ファイルまたは Avro ファイルにエクスポートするための Dataflow ジョブ
///シリアルコンソール接続
SSH接続できない!そんな時のシリアルコンソール | apps-gcp.com突然起動しなくなったWordPressサーバーをなんとか復旧した話 | (tipstock.net)///gcloud cmd
gcloud organization list GCP IDやGoogleWorkspace IDが分かる
///Recommender
API の使用 - 推奨事項 | Recommender のドキュメント | Google Cloud///Googleスプレッドシート+GAS+BigQuery
GAS:マクロで記録してそれを使いまわす
GASでBQの制御は難しいかも、更新してもBQのデータが古いままだったりする(appscript.jsonに権限を追記しても)
シート経由せずにGASから直にファイルに書き出すとましかも(下記コード参照)
データを一時でも書込ならスプレッドシートの共有の編集権限とシート保護しない設定が必要と思われ(セキュリティがザルに)
呼び名
connected sheetでBQのデータをスプシに抽出する
federated queryはBQに外部ソース(スプシ等)をインポートする
スプシの保護(シートはコピーできザルなのでセキュリティ対策でなくデータ保護)
シートを保護する、非表示にする、編集する - パソコン - ドキュメント エディタ ヘルプ (google.com)スプシの閲覧共有だけでBQコネクテッドシートのプレビュー/抽出は可能だが、それをvlookup系で他のセルに移せない
組織でコネクテッド シートを使用する - Google Workspace 管理者 ヘルプ↓
■アプリ
公開資料 - App Modernization OnAir 〜 モダンなアプリケーション開発とは 〜 (cloudonair.withgoogle.com)cloud runの設定だけでCDCIできる(第10回
End
Posted by funa : 09:00 PM
| Web
| Comment (0)
| Trackback (0)
May 2, 2021
Terrafirma
公式
https://www.terraform.io/docs/index.html
導入
https://www.terraform.io/guides/core-workflow.html
推奨方法
https://www.terraform.io/docs/cloud/guides/recommended-practices/index.html
https://www.terraform.io/docs/cloud/guides/recommended-practices/part1.html
https://www.terraform.io/docs/cloud/guides/recommended-practices/part2.html
https://www.terraform.io/docs/cloud/guides/recommended-practices/part3.html
https://www.terraform.io/docs/cloud/guides/recommended-practices/part3.1.html
https://www.terraform.io/docs/cloud/guides/recommended-practices/part3.2.html
https://www.terraform.io/docs/cloud/guides/recommended-practices/part3.3.html
https://www.terraform.io/docs/cloud/guides/recommended-practices/part3.4.html
チュートリアル
https://learn.hashicorp.com/collections/terraform/gcp-get-started
HCL
https://www.terraform.io/docs/language/index.html
CLI aka cmd(アルファベットリストから使う)
https://www.terraform.io/docs/cli/auth/index.html
GCP用リファレンス
https://registry.terraform.io/providers/hashicorp/google/latest/docs
お便強
https://qiita.com/minamijoyo/items/1f57c62bed781ab8f4d7
https://qiita.com/donko_/items/6289bb31fecfce2cda79
https://www.apps-gcp.com/infra-automation-01/
https://colsis.jp/blog/gcpterraform/
Infra as codeとしてインフラの構築や設定をコード化できる
特にクラウドだと構築の自動化や構成管理等でのレバレッジが強力
■段階
Terraformとは?基本知識とTerraformのメリット4つを紹介 | テックマガジン from FEnetインフラ必要なリソースをTerraform化>workspaceの活用>main.tfの共通部分をmodule化
moduleは構成に合わないようなリファクタリングが必要になった時にterraform state mv が必要になってとたんにつらい、moduleを細分化しすぎるとvariable と output が大量に必要になって書きづらい、moduleは再利用できる複数のリソースの単位(プログラミング言語でいうところの関数みたいなもの)で作るのがしっくり
リソースの差分を無視するlifecycleブロックを使う
resource "aws_autoscaling_group" "app_1" {
name = "app-asg-1"
lifecycle {
ignore_changes = ["load_balancers"]
create_before_destroy = true//新しいのを作ってから古いのを削除
}
}
外部ファイルを文字列として読み込む
resource "aws_iam_role" "ec2_role" {
name = "ec2-role"
assume_role_policy = "${file("./ec2_assume_role_policy.json")}"
}
1つのディレクトリで複数のStateを扱うWorkspaceという機能もあるのですが、
個人的には普通にディレクトリを分けて管理する方が楽
production/stagingが完全に同じリソース構成で、設定のパラメータの差分がちょっとだけあるという理想的な世界ではWorkspaceでも運用できるかもしれませんが、現実的にはstagingだけリリース前の検証用の一時的なリソースが立ってたりとか、完全に同じ構成にならないことも多いので、モジュールの読み込みの有無や一部の環境だけ存在するリソースなどの差分を吸収できる場所があったほうが都合がよい
Terraform職人再入門2020 - Qiitaモジュールが公式から提供されている
Browse Modules | Terraform RegistryTerraform の terraform.tfvars とは | 30歳未経験からのITエンジニア (se-from30.com)環境情報は外部ファイルが基本
prd/stg/dev環境はprd.tfvars, stg.tfvars, dev.tfvarsを用意
.tfvars 各環境の設定
aws_access_key = "XXXXXXXXXXXXXXXXXXXX"
aws_secret_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
aws_region = "eu-west-1"
main.tf
terraform {
required_version = "= 0.12.26"
}
provider "aws" {
version = "2.66.0"
access_key = var.aws_access_key
secret_key = var.aws_secret_key
region = var.aws_region
}
var.tf 空の受け皿
variable aws_access_key {}
variable aws_secret_key {}
variable aws_region {}
Terraform で変数を使う - Qiita実行時に-var-fileで値ファイルを指定して環境などを切り替えると良いかもしれない
terrafrom plan -var-file=dev.tfvars
terrafrom plan -var-file=prod.tfvars
変数ファイル指定がないときは変数でdefaultに入れておく、descriptionで変数の説明もかける
variable "foo" {
type = "string"
default = "default-var"
description = "Sample Variable"
}
変数ファイルを異なるバックエンド(フォルダ構成)で共有したいときはシンボリックリンクを貼る
ln -s ../common/shared_var.tf shared_var.tf
credentials等の秘匿したい変数を外部のファイルやコマンドライン引数から読み込む
variable "credentials_file" {} @var.tf 変数を定義し空にしておく
credentials = file(var.credentials_file) @main.tf ファイルを読むがファイル名は変数
terraform plan -var 'project=
' -var 'credentials_file=.json' @cmd プロジェクトとクレデンをコマンド時に指定
他にもvars.tfvars設定ファイル(行頭variableが不要)、TF_VAR_環境変数による指定-var-fileで変数ファイルを明示してcmd、ファイル名は.tfvars/.tfvars.json
-varで変数を明示してcmd
順序があり後の読込でオーバーライド
↓
HCLの変数は基本2種類のlocalとvariable
variableはグローバル変数、ファイル外やコマンドラインから使える
その他の変数参照方法としては(上から優先に適応)
コマンド引数 一時的に使用
変数ファイル terraform.tfvars git管理等で外部ファイルで?
環境変数 TF_VAR_ 実行ログに残らない鍵情報等
workspaceは使わない、moduleを限定的に使う
設定をコード化>Gitレポジトリに置く>設定内容、作業履歴の明確化、チームでの運用性向上
■特性
TFの影響を反映するのはterraform applyの時だけ、tfファイルとtfstateの差分を実際にリソース作成する
tfファイルで変更した場合、TFはリソースの再作成を行うので一度消えることになる(大体は単位が権限だったりで影響がないだけでplanで要注意)
terraform planはtfとtfstateと実体の差なので、実体があってもtfstateになければwill be createdでplan時は表示される
terraform importはtfファイルからtfstateへ記載だけを行う(実体からも情報を取得しtfstateに入れる)
カレントdirの全.tfファイルor.tf.jsonを評価するのでtfファイルの名は何でもいい
各リソースに対してTF化するかは選択ができるが、TFする場合はそのリソースに必要な全記載をTFファイルに行う
terraform import tfResourceID.yourResourceName gcpIdentifier のコマンド
terrafrom import google_bigquery_dataset.tf-1 bangboo-prj/test-dataset
tfResourceID(リソースIDというようタイプ:リソース種別)はTF指定のもの、yourResourceName (リソース名)は任意のもの
構成ファイル.tfはローカルのものが使われる、importするとtfstateに反映
GCP identifierはTF公式サイトの各サービスの一番下import項目を見ると指定内容が分かるのでGCPを見て拾ってくる
terraform state list TF化されているリソースを見る
terrarorm apply時にもtfstateは更新される(オプション-refresh=falseで無効可)
またapply時に-target=xxxでデプロイするリソースを特定できる(TFファイルだけでなくTFステートもターゲットになる)
resource "google_sql_database_instance" "instance" {
provider = google-beta
name = "my-database-instance"
}
resource "google_sql_database" "db" {
instance = google_sql_database_instance.instance.name
name = "db"
}
ToSetは値設定をするが順不同で重複を省く
resource "xxx" "aaa" {
for_each = toset(["foo", "bar", "bar"]) でbar, foo
name = each.key
}
for_each/eachのループ
locals {
sg = {
foo = "FOO"
bar = "BAR"
}
}
resource "xxx" "aaa" {
for_each = local.sg
name = each.key
description = each.value
}
mapをリストしたものをfor_each
locals {
images = [
{ name = "foo", image = "alpine" },
{ name = "bar", image = "debian" },
]
}
resource "docker_container" "this" {
for_each = { for i in local.images : i.name => i } # こう書くのが正しい
name = each.value.name
image = each.value.image
}
terraform importはリソース単位、更新はできず削除してから追加 terraform state rm google_bigquery_dataset.tf-1
実設定とimportの内容が違う場合は実設定の情報でtfstate化されるようだ(importは項目を入れ込む感じ?)
なので実環境に変更を加えるにはterrafrom apply、tfstate化もされtfファイル/tfstate/実設定の3者で同じになる
apply時にtfstateと実設定が違う場合、例えば既存設定がある場合は重複エラーになりapplyできず、importしtfstateと実設定を同じにしてから、tfファイルの内容をapplyすることが必要
terraform importで対象プロジェクトを間違えるとハマる
通常のterraform applyではproviderの情報を使用してプロジェクトを決めるが、importはハードコードするのでimportを間違えばなぜ変な変更がでるのかわからなくなる(プロジェクトが変なものはstateを調べ、terraform state rmするしか)
■セットアップ
作業ディレクトリの作成(プロジェクトに対するローカルのフォルダ)
プロバイダを指定したtfファイルの作成(gcsにstateを置く設定が良い
provider "google" {
project = "bangboo-kuso"
}
terraform {
backend "gcs" {
bucket = "bangboo-kuso-terraform"
}
}
terraform init ローカルに対して初期化
プロジェクトレベルownerのサービスアカウントを持っておく
セットアップする際にtfsateのbackend保存場所のbucket部分をコメントアウト
bucketを作るterraformを実施しbucketを作成しつつlocalにtfstateファイルを作成
再度terraformをするとtfstateファイルがbucketにコピーされる
bucket部分のコメントアウトを外すと次回tfからはバケットにtfstate更新する
このときローカルtfstateの内容をバケットに写すか聞かれるが写す
(写さないと差分しかバケットに行かないのでimport等が必要になる)
■既存リソースのTF化のおおよその作業
リソースタイプと名前を定義したtfファイルを作成する(任意のリソース名、基本ユニーク、纏められるものは重複してもいい)
resource "google_cloudfunctions_function" "fuckin" { ... をtfファイルに記載
tfResourceID(リソースIDというようタイプ:リソース種別)とyourResourceName (リソース名) だけで
リソースタイプや個別パラメータは公式ドキュメントを参照しながら定義
https://registry.terraform.io/providers/hashicorp/google/latest/docs
(簡単)tfファイル内で1行目以外は空で、terraform planをするとエラーで必要なものが分かるので、それを埋める
planが通ると自動的に値をサーバから拾ってくる(importすればtfstate.tfに入っている or コピーしてTFに入れる)
planでダメならterraform state show tfResourceID.yourResourceName でstateを見てtfファイルにパラメータを定義していく
暫定に空でリソースをTFファイルに記載しterraform import、次にtfstateを調査する
terraform state list tfstateファイルにあるアセットを一覧
terraform import google_bigquery_table.xxx project/dataset/table インポート
terraform state show google_bigquery_table.xxx tfstateの該当部を表示
terraform state rm google_bigquery_table.xxx インポート取り消し
TF定義は複数の方法がある、最終GCP公式のRestAPIで確認するしか
terraform importする(公式ドキュメントの一番下にimportコマンドの指定がある)
terraform planして差分がなくなるまでtfファイルを修正する
import(tfstate)の修正は一度stateから削除する terraform state rm google_bigquery_dataset.tf-1
(既存リソースがあってもあくまでtfファイルとtfstateの差分なのでinitした状態でplanしてもup-to-dateと表示されるだけ)
tfstateファイルにおかしなものが無いか確認、keyとか含まれないか
■個別
リファレンスでoptionalとなっていてもtfファイルでは必要な場合もある
tfstateファイルからは必要ないとして自動的に削除されるが
スプシをBQでみれるFederatedQueryはテーブルだけ定義しimportしstate show調査
urlをTFファイルに記載する
シャーディング(日付別)テーブルは定義できないのでは
生成するクエリの方をTF化したい
Authorized viewはモジュールがあるがconflictがあり全消えする場合がありTF化にまだ向かない
google_bigquery_dataset_iam_memberでもAuthorized viewをはがしてしまう。
Authorized viewを使っている個所は google_bigquery_dataset_access あるいは google_bigquery_dataset の access フィールドを使う。
google_bigquer_dataset_iam_policy と google_bigquery_iam_binding は Authoritative で権限追加でなく権限強制設定でコンソール付与分を引き剝がすので、使わない方が安全。
なお、Authorized view と Routines はTerraform化できない事が分かっている(2022/4時点)
ScheduledQuery は Terraform化できるが実行者の設定ができない(Terraform実行者がSQ実行者?誰?)
BQ関連ではデータセット定義、テーブル定義、ビュー定義、フェデレテッドクエリ定義、ScheduledQuery定義をTerraformで行い
BQ権限定義、AuthorizedView定義、Routines定義は行わない
BQ権限を定義するならデータセットレベルはgoogle_bigquery_dataset_access
プロジェクトレベルはgoogle_project_iam_memberで実施すると別なので安全らしい?
■TF公式ドキュメント
google_organization_iam_custom_role | Resources | hashicorp/google | Terraform Registrygoogle_organization_iam | Resources | hashicorp/google | Terraform Registryカスタムロールを設定して、組織レベルのIAMでそれを使いたい
TFのorg_iamページのArgument referenceのrole項目を見ると
Note that custom roles must be of the format organizations/{{org_id}}/roles/{{role_id}}
TFのorg_iam_custom_roleページのAttributes referenceのrole項目を見ると
id - an identifier for the resource with the format organizations/{{org_id}}/roles/{{role_id}}
で下記と分かる、使用側と被使用側のTFマニュアルを両方確認する
resource "google_organization_iam_custom_role" "my-custom-role" {
role_id = "myCustomRole"
org_id = "123456789"
title = "My Custom Role"
description = "A description"
permissions = ["iam.roles.list", "iam.roles.create", "iam.roles.delete"]
}
resource "google_organization_iam_member" "my-organization" {
org_id = "123456789"
role = google_organization_iam_custom_role.my-custom-role.id
#あるいは通常"roles/bigquery.dataEditor"のようにいれるがorganizations/0123456789/roles/chinkoといれる
member = "user:jane@example.com"
}
↑
resourceの2番目リソース名を定義しますが任意の名前を指定します
ここが同じ項目はユニーク制限がない場合は追加としてまとめられます
通常はユニークにしterraformで管理するリソース名(yourResourceName)を宣言します
※1番目のリソースタイプ内でユニークにするのが基本(全体でもユニークの方が分かり易い)
TFファイルに定義をしたい →定義したいリソースのArgument referenceの項目を設定
TFファイルに定義した内容を変数で使いたい →使いたいリソースのAttributes referenceを見る
terraform importしたい →インポしたいリソースのページ一番下のimportコマンドの指定を見る
■他に一般的なTF(既存がimportされると以下で変更をapplyして運用)
terraform -v 稼働確認
terraform fmt ファイルの記述フォーマットを整える
terraform validate ファイルの検証
terraform plan アクションを計画
terraform apply 最後に変更を適応
terraform show ステータスを確認、一覧
terraform destroy で簡単にインフラの吐き、initができないとき必要そう
■特定のリソースだけ適応したい
terraform plan -target="tfResourceID.yourResourceName"
terraform apply -target="tfResourceID.yourResourceName"
TFファイルだけでなくTFステートもターゲットに含まれる
これでTFファイルにコードがなくTFステートだけにあるものを指定して削除等もできる
■tfenvを使う場合
tfenv install 1.0.0
tfenv list
tfenv use 1.0.0
terraform init
terraform workspace list
terraform workspace select ore_space
main.tf作成し記載
terraform fmt tfファイルのフォーマット(書式は適当で書けばいい)
gcloud auth login ローカル操作のための認証
gcloud auth application-default login SDKを実行のための認証
API&Servicesでクレデンシャルは取得できそう、key=xxxx
既存のリソースを調査
terrafrom import google_storage_bucket.pri-bucket project-abc123/asia-northeast1/pri-bucket でimportとか
terraform refresh tfstateの最新化、どのタイミングで使う?
■既存のリソースを調査
terraformer import google --resources=instances,forwardingRules --regions=us-west1 --projects=xxxx-123 とか
既存リソースimport
https://www.apps-gcp.com/terraformit-gcp/
ダメなら terraform state rm で不要分を削る
新環境用にtfファイルを準備
新環境で下記を実行
terraform init
terraform state push xxx.tfstate
terraform planで差分がないことを確認
■GCP権限(メールの変名時)
GCPはGWS gmailメールの変名に追従して権限も付与状態も変化がない
しかしterraformは追従しないためtfファイルで使っている場合は変更する
■gcloud cmd
https://www.devsamurai.com/ja/gcp-terraform-101/
gcloud projects list 権限あるプロジェクトを表示
gcloud config set project [prjID] ワーキングプロジェクトの設定
gcloud services enable iam.googleapis.com サービスの有効化
gcloud iam service-accounts create terraform-serviceaccount \
--display-name "Account for Terraform" サービスアカウント作成
gcloud projects add-iam-policy-binding [PROJECT_ID]
--member serviceAccount:terraform-serviceaccount@[PROJECT_ID].iam.gserviceaccount.com --role roles/editor 権限付与
gcloud iam service-accounts keys create path_to_save/account.json
--iam-account terraform-serviceaccount@[PROJECT_ID].iam.gserviceaccount.com クレデン発行
Posted by funa : 10:14 PM
| Web
| Comment (0)
| Trackback (0)
April 2, 2021
Linux cmd
■Linux terminal
tabで入力補完
↑↓で入力履歴呼び出し
^qはCtrl+qを押すという意味
半角/全角キー 日本語を切り替える(画面右上にもIMEがある、win+spaceの場合も)
ls -la ディレクトリ内を表示
ls -a 隠しファイルを含み表示
(GUI)ctl+h 隠しファイルを表示(メニューでもチェックで可)
pwd 現ワーク中のディレクトリを表示
cd ../ 上に上がる
clear 表示内容を消す
mv beforeName.text afterName.txt ファイル名変更
rm -R ディレクトリ名 削除、ファイルはrm a.txt
ls -l > hoge.txt >結果を上書き
ls -l >> hoge.txt >>結果を追記
printenv 環境変数表示 printenv xで特定表示
grep aaa -rl ./ カレントディレクトリ以下からファイル内にaaaが含まれるファイルを検索
grep -R $keyword *.py .pyファイルからkeywordを検索
sudo - 一般ユーザが特権操作する sudo省略
sudo -i rootに切り替える
sudo -iu <username> 特権ユーザ切り替え
テキスト選択
Shift↑or↓ で行全体
home(+fn)で行頭、end(+fn)で行末移動
nano text.txt 作成あるいは開く、nano簡単かも、画面下コマンドでctrl+?すればいい
コマンドM-UはEsc+u
ctrl+k で1行削除
■viエディタ
sudo apt install vim
vi text.txt ファイル作成あるいは開く
viは2つ+αのモード
┣コマンドモード
┃┗コロンモード(exモード:祖先のラインエディタ)
Escでコマンドへ抜ける
┗挿入 i (入力モード)
ファイル名を指定し保存 :w new_file_name.txt
強制保存のコマンド :w!
保存せず終了 :q 強制終了 :q!
:10 10行目に移動
:set number 行数を表示
:num 現在のカーソル位置行数を表示
クリップボードをペースト iで挿入モードに入り Shift+Insert
vi内でコピペ:yコマンドのコピー、pコマンドのペーストなので下記の様にする
2yw ならカーソルから2単語コピーされます
3yl ならカーソルから3文字コピーされます
y$ ならカーソルから行末までコピーされます
p ならカーソルの後ろにペーストされます
$ カーソルを行末へ
G カーソルを最終行行頭へ
- 前行の行頭へ
Enter 次行の行頭へ
w カーソルを1語進める
b カーソルを1語戻す
Ctrl-d 1/2画面下へ(down)
Ctrl-u 1/2画面上へ(up)
Ctrl-f 1画面下へ(foward)
Ctrl-b 1画面上へ(back)
/文字列(Enter要) 文字列検索(スラッシュ)
┣n 次の検索文字列へ
┗N 前の検索文字列へ 保存して終了 :wq 保存して強制終了 :wq!
■環境変数は下記の順で探す、なので必要なら下位のものを上にコピー
~/.bash_profile
~/.bash_login
~/.profile
source ~/.bash_profile 編集したbashrcをbash_profileに反映させる
bashrcはbash起動毎、bash_profileはログイン毎
■SSHの設定
Linuxコマンド【 ssh-keygen 】認証用の鍵を生成 - Linux入門 - Webkaru$ ssh-keygen
パスフレーズは空でも設定上は問題ないが塩っ気が足らん気が
秘密鍵(id_rsa)と公開鍵(id_rsa.pub)が生成され、ホームディレクトリに作成される
/home/yourID/.ssh/id_rsa
/home/yourID/.ssh/id_rsa.pub.
公開鍵をSSHサーバや外部サービスに登録する等して使う、秘密鍵は明かさないこと
$ vi ~/.ssh/config
Host oketsu
HostName 1.XXX.XXX.XXX
User hoge
IdentityFile ~/.ssh/id_rsa.pub
LocalForward 5912 localhost:5902
ProxyCommand connect-proxy -H proxy.syanai.in:8022 %h %p
Host github.com
HostName ssh.github.com
Port 443
IdentityFile ~/.ssh/id_rsa.pub
ProxyCommand connect-proxy -H proxy.syanai.in:3128 %h %p
User githoge
$ chmod 600 .ssh/config
下記のように実行すると、ログイン/GITできます。
$ ssh oketsu
$ git clone githoge@github.com:kusogitry.git
$ id 所属グループ等を表示
$ uname -n;id;date
■NW設定
/etc/resolve.conf
nameserver 88.88.88.88
~/.profile とか .bashrc とか
export http_proxy=http://proxy/3128
/etc/apt/apt.conf
ip addr
■スクリプト実行
nohup python3 main.py & ユーザディレクトリにnohup.outログが実行完了時に一度に保存される(重いと思われる)
nohup python3 main.py > /dev/null 2>&1 & ログなし
nohupはバックグラウンド実行、ログアウトしても実行続ける
jobs ジョブリストを出す
fg ジョブ番号 フォアグラウンド実行に変える
bg ジョブ番号 バックグラウンド実行に変える
ctrl c キャンセル
ctrl z 中断(再開できる)
crontab -e 編集
crontab -l 確認
sudo service cron restart 再起動
systemctl status cron 稼働の確認
30 12 * * 0 python3 /home/app_hoge/main.py
cronはバックグラウンド実行でnohup &を含めると実行されない、多分
top プロセス/CPU/メモリ等の情報、こちらで動いていればpsのstatがsでも問題ない、多分
ps aux
ps f -A プロセスをツリーで表示し便利
kill -l
kill -SIGCONT プロセス番号
sudo less /var/log/cron.log
sudo tail -f /var/log/cron.log
sudo less /var/log/syslog
sudo tail -f /var/log/syslog
■ディスク系
ext4 一般的なデスクトップやファイルサーバ向け、16TBまで、ファイルシステムチェックで遅い
xfs 高負荷IOで大容量データ処理向け、ジャーナルなし、ファイルシステムチェックを短縮
論理ディスク=パーティション
/dev/sda1, /dev/sda2, /dev/sdb, /dev/sdf等、数字はパーティション番号、数字がないとパーティション1つだけ
ディスク拡張
lsblk
df -Th
du -sk * | sort -nr
#xfsの場合
pvdisplay
pvresize /dev/nvm
vgdisplay
lvdisplay
lvextend -l +100%FREE /dev/vg001/lv001
xfs_growfs /opt
#ext4の場合
apt autoclean キャッシュあるがインストールされていないdebファイル削除
apt autoremove 必要なくなったパッケージ削除
disk -l /dev/nvm パーティション情報
growpart /dev/nvm 1 指定パーティションの容量拡張
resize2fs /dev/nvm ファイルシステム拡張
容量調整
/var/cache はapt-get clean, yum cleanで消す程度で
■swapをrootからvarに移動
free
swapon -a
swapを無効化
swapoff -v /swap.extended
swapをvarに移動
mv /swap.extended /var
/etc/fstabからswapのエントリを/varに書き換え
cat /etc/fstab
swapを有効化
swapon -a
確認
free -h
■ライブラリアップデート
sudo apt update
apt list --upgradable | grep mysql
sudo apt install mysql-client=6.6.6-0ubuntu2.1~99.99.9
sudo apt install mysql-client-core=6.6.6-0ubuntu2.1~99.99.9
…
dpkg-l | grep mysql
■SPF
spfレコードはメールを送信する際、送信元サーバとDNS上のIPアドレスを比較
自社から取引先に送信したメールにSPFレコードを設定していなければ、相手側のメールサーバで迷惑メールとされ届かない場合も
送信元のDNSに送信元IPをSPFレコードに登録する(ドメインをSMTPのIPに変える?
ドメイン IN TXT v=spf1 ip4:172.16.0.1 -all
(+が省略されているがIP許可、allを認証しないという意味)
送信側SMTPサーバではSPFをチェックせず何でも送信
受信側MTAにて設定され(SMTPにはトランスファのMTA、デリバリのMDA
spfを使えば先方がspfレコードを登録していなければメールが受け取れない
postfixやeximのSPFをonにする設定がある
spfレコードが設定されているかを確認
nsookup -type=TXT 調べたいドメイン
=============
■VS code
マルチカーソル:ctrl+shift+↓
[Alt]+クリック | カーソルを追加 |
[Ctrl]+[Alt]+[↑]/[↓] | カーソルを上下に追加 |
[Ctrl]+[U] | カーソル操作を元に戻す |
[Shift]+[Alt]+[I] | カーソルを行末に追加 |
[Ctrl]+[L] | 行を選択 |
[Ctrl]+[Shift]+[L] | 選択中の文字列と同じものをすべて選択 |
[Ctrl]+[F2] | カーソル位置の単語と同じものををすべて選択 |
[Shift]+[Alt]+[→] | 選択範囲の拡大 |
[Shift]+[Alt]+[←] | 選択範囲の縮小 |
[Shift]+[Alt]+ドラッグ | 矩形選択 |
[Ctrl]+[Alt]+[Shift]+[カーソル] | 矩形選択 |
[Ctrl]+[Alt]+[Shift]+[PgUp]/[PgDn] | 矩形選択 ページ上下 |
VSCodeのマルチカーソル練習帳 - Qiitaマルチカーソルを使わないVSCodeはただのVSCodeだ!〜解説編〜 - memo_md (hateblo.jp)
Posted by funa : 12:00 AM
| Web
| Comment (0)
| Trackback (0)
February 21, 2021
BigQuery
■Big queryリファレンス
BigQuery解説:https://beyondjapan.com/blog/2016/03/what-is-bigquery/
クエリ処理のツリーアーキテクチャによる分散並列処理
複数のサーバーに対してツリー状に拡がっていき、並列にサーバー上で同時に分散処理
ルートサーバ>intermediateサーバ>leafサーバ
BigQuery MLという機能を利用すると、機械学習モデルをCloud AI PlatformのTensorFlowなどに連携させ、クエリ結果を素早くAIと連携
Lookerというデータ分析プラットフォームとの連携よりクエリ結果を、データ統合、変換、分析、可視化、レポーティングすることができ、非常に強力なBI
列指向型・カラム型データベース・カラムナストレージ(一般的なRDBMSでは行単位でデータが保存)
必要なカラムのデータを取得するだけでよく、またデータは圧縮できる
https://dev.classmethod.jp/articles/google-bigquery-debut/
GCPプロジェクト>データセット>テーブル(行row列columnで普通のテーブル、ネイティブbigqueryテーブル/Googleドライブのような外部テーブル、SQLクエリによるビュー)
ジョブは非同期で実行され、ステータスをポーリング(データの読み込み、データのエクスポート、データのクエリ、データのコピーなど)
クエリ(ウェブ UI、bq コマンド、BigQuery REST APIの方法がある、SQLと同じ?
SELECT title, answer_count, view_count
FROM `bigquery-public-data.stackoverflow.posts_questions`
ORDER BY view_count DESC LIMIT 10
BigQueryはSELECT tag, time FROM [dataset_name.table_name_20151206]のように必要な列だけを選択した場合にはスキャンの幅を狭めることは可能ですが、LIMITやWHERE句には何を書いてもテーブルをフルスキャンしてしまう
節約 Amaのs3に入れRedshift内でテーブルを分割した後にBigQuery
Hadoopでも使われていたGoogle開発のエンジンであるMapReduceは、非構造化データをプログラミングモデルを通して扱うが、巨大なテーブルの結合や巨大な出力結果のエクスポートも可能である半面、処理時間は数分間から数日に及んだ、だが、BigQueryは、あらかじめデータを構造化してBigQueryのテーブルに格納しておかねばならないが、ほとんどのクエリは数秒で完了する
サードパーティ ツール(データの読み込みや視覚化を行うツールなど)を使用して BigQuery のデータにアクセス可
Google Cloud SDKをインストールすればコマンドラインが使える
BQは同一リージョンでないとJoinができない、ゾーンはマルチで良い
BQでは us と eu がマルチリージョン
22/4現在のリージョンリスト:asia-east1-2、asia-northeast1-3、asia-south1-2、asia-southeast1-2、australia-southeast1-2、europe-central1-2、europe-north1、europe-west1-6、northamerica-norhteast1-2、southamerica-east1、sourthamerica-west1、us-central1、us-east1-4、us-west1-4
`other-prj`.dataset.table あるいは `other-prj.dataset.table`
■標準SQL
先頭行でレガシーか宣言 #standardSQL あるいは #legacySQL
バッククォートでエスケープ、プロジェクト区切りも.(ドット)、From句のカンマはCross joinで全組合せかと思われ通常通りjoinやunionを使う事
配列が使える、カラム一つに配列を入れて多元的に扱える
withで一時テーブルを作れる
exceptでカラムを除外、replaceでカラムの置き換え
select * except(kuso) from a
分析関数over()とwindowで計算ができる
rank() over (order by x)は下記moreのRFMに使用している
ROW_NUMBER() over (order by timestamp) as id,で採番できる
地理関数とかJSON関数とか色々関数もありそう
■レガシーSQL(標準SQLを使うのが由)
予約語は角かっこを使ってエスケープ、プロジェクト区切りは:
集計関数で WITHIN キーワードを使用すると、レコード内の繰り返しの値が集計?
FROM句のカンマは標準SQLのCross joinとは異なりUNION ALL 演算子
通常のSQL処理システムとは異なり、BigQueryは繰り返しデータの処理を前提として設計。繰り返しレコードの構造を操作するクエリを記述。その方法の1つが、FLATTEN 演算子?
JOINは、INNER、[FULL|RIGHT|LEFT] OUTER、および CROSS JOIN 演算子をサポート、デフォルトINNER
除外できる select + from A OMIT RECORD IF COUNT(payload.pages.page_name) <= 80;
TOP を使用するには、SELECT 句に COUNT(*) を含める
分析関数over()とwindowで計算ができる?(標準SQLと同様?)
functionを作って使える(標準SQLと同様?)
JSON等のネストをフラット化
■DDL
データ定義言語ステートメントの使用 | BigQuery | Google Cloudhttps://www.isoroot.jp/blog/1651/
auto_incrementもdefaultもprimary keyもindexもshow create tableないのでは?
CREATE TABLE IF NOT EXISTS bangboo_data.x_xxx (
`no` INT64 NOT NULL,
`user_no` INT64 NOT NULL,
`name` STRING,
`date` DATETIME,
)
同じスキーマで作ることもできる
CREATE TABLE ore_ds.test003
LIKE prj.ds.test001
PARTITION BY _PATITIONDATE
■bqコマンドはコンソールで実行できる
ブラウザで該当プロジェクトに入りコンソールボタン、下記ではスキーマをJSONで取得できる
bq show --schema --format=prettyjson myProject:myDataset.tbl001
bq ls -n 3000 dataset_aho (データセット内のリスト3000件、デフォ50件?)
bq cp --force prj:ds.tbl prj:ds.tbl2
上書きコピー(削除しコピー)コンソールだと同名コピーや下記ができない
bq cp ds.tbl1,ds.tbl2 ds.newtbl
2つのテーブルをnewtable にまとめコピー
bq cp -a ds.tbl2 ds.tbl1
tbl2をtbl1に追加コピー --append_table でも同じ
bq load (csvとかgcsのファイルを読み込む)
bq extract (gcsに抽出)
■データアップロード時のスキーマ指定
自動検出はFirestore、Datastore、Avro、Parquet、ORCだけ?ほぼ手動のutf-8のcsvかjsonlかを使う形
コンソールで手動スキーマ指定可(jsonスキーマを張付ける)、modeは省略可でデフォはnullable、
JSONスキーマファイルupはaqコマンドのみ可、ローカルからup時のコマンドとスキーマ例↓
bq load --source_format=CSV mydataset.mytable ./myfile.csv ./myschema.json
[
{
"description": "quarter",
"mode": "REQUIRED",
"name": "qtr",
"type": "STRING"
},
{
"description": "total sales",
"mode": "NULLABLE",
"name": "sales",
"type": "FLOAT"
}
]
COUNT DISTINCTだが、BigQueryでは概算値が返ってくる??。正確な値が必要な場合は、GROUP EACH BYとCOUNT(*)を組み合わせる
///Saved query
プロジェクトに対して保存をして使いまわす等ができる
URLでクエリを共有できる
///Federated Query
スプレッドシートやGCSの外部ソースをBigQueryで
範囲の書き方:シート1!A1:B100
Auto detectにするとHeader skipを1にして1行目をカラム名として使うといい
注意)
シートで構成を変えると滅茶苦茶になる
空欄のセルはnullになる
使う人はBQへもスプレッドシートへも両方権限が必要
///パラメータ(変数)を使う
--parameter=min_count:INT64:250
SELECT word FROM `prj.ds.t` WHERE AND count >= @min_count
パラメータ化されたクエリの実行 | BigQuery | Google Cloudこういう感じでも使えるのでは
WITH params AS (
SELECT @sheetInput AS p
),
tmp_pre_processed_src AS (
SELECT * FROM src
)
SELECT * FROM tmp_pre_processed_src
,params
WHERE
tmp_pre_processed_src.a = p
///*を受ける_TABLE_SUFFIXを使う(複数テーブルだとunion allになる)
SELECT year FROM `bigquery-public-data.ds.gsod19*`
WHERE _TABLE_SUFFIX BETWEEN '29' and '35'
ワイルドカード テーブルを使用した複数テーブルに対するクエリ | BigQuery | Google Cloud BTWで絞らないと全結合で課金が厳しいかも
※ワイルドカード注意
dataset.product_*と書くとdataset.product_20190425だけでなくdataset.product_special_20190425にもヒットしてしまう
betweenは小さいから大きいで、パーティションのないシャーディングテーブル日付きつきテーブルでも行ける(From句のテーブルに動的な名前を使うにはこれか、EXE IMEDIATEくらいか?)
SELECT year FROM `bigquery-public-data.ds.gsod20*`
where _TABLE_FUFFIX between format_date('%y%m%d', date_sub(current_date("Asia/Tokyo"), interval 3 day))
and format_date('%y%m%d', current_date("Asia/Tokyo"))
///時間のパラメータを使う
select * from mytable_{run_time-1h|"%Y%m%d"}
実行時間run_time(UTC)から1時間引いた日→mytable_20180214
クエリのスケジューリング | BigQuery | Google Cloud///動的にテーブル名を指定してcreate table
パラメータや変数や_TABLE_FUFFIXだけでは難しい。変数はテーブル名とは解釈されない、_table_fuffixはselect分のfrom句に入れwhere句で内容を指定するがcreate分は無理、execute immediateを用いる
DECLARE t STRING;
SET t = (SELECT CONCAT('x_emp_at', FORMAT_DATE("%Y%m%d", DATE_ADD(CURRENT_DATE(), INTERVAL 1 DAY))));
EXECUTE IMMEDIATE format('CREATE OR REPLACE TABLE `%s` AS SELECT * FROM `prj.bangboo_data.x_employee`', t);
ScheduledQueryでは出力テーブルの指定が可能でテーブル指定例:table001_{run_time-1h|"%Y%m%d"}でOK、なおSQL内にはrun_timeが使用できない
///既存のテーブルをコピー(CREATE OR REPLACE TABLEもあり)
CREATE TABLE IF NOT EXISTS bangboo_data.x_employee_copy (
`no` INT64 NOT NULL,
`name` STRING,
) as
select * from `prj.bangboo_data.x_employee`
データ定義言語ステートメントの使用 | BigQuery | Google Cloud///timestampとdatetime
datetime型カラムにはCURRENT_DATETIME()、timestamp型カラムにはCURRENT_TIMESTAMP()を使う
timestampはUTC、datetimeはローカル的で地域指定ができる
直近3分
SELECT * FROM `aaa.ds.tbl111`
WHERE `date` > DATETIME_SUB(CURRENT_DATETIME(), INTERVAL 3 MINUTE)
//stringとdate
func_approved_routine_a('2021-10-31') 引数がstring型
func_approved_routine_a("2021-10-31") 引数がdate型
///日付のキャスト
CAST(date AS STRING)
TIMESTAMP(DATE_SUB(CURRENT_DATE(), INTERVAL 1 month))
BigQueryのStandardSQLで日付(date, datetime, timestamp)を変換する方法 - 寝ても覚めてもこんぴうた (hatenablog.com)Bigqueryの日時に関係する関数全部試してみた ①Date編 - Qiita///timeで入っているものを日でサマるSQL
select
count(table_id),
sum(size_bytes),
date(record_time) as record_day
from bq_metadata
where record_time > TIMESTAMP(DATE_SUB(CURRENT_DATE(), INTERVAL 3 month))
group by record_day
order by record_day DESC
///有効期限 table expiration
データセットに対して何日間かにするか設定できる
テーブルに対し特定の日付を設定できる
何が起こる?>データセット自体は残るが中のテーブルが無くなる
///パーティション
パーティション分割テーブルの概要 | BigQuery | Google CloudBigQueryのStandardSQLで日付(date, datetime, timestamp)を変換する方法 - 寝ても覚めてもこんぴうた (hatenablog.com)パーティション分割テーブルは2種類:パーティショニングとシャーディング
1)パーティショニング
BigQueryでパーティション分割テーブルを作成する - goodbyegangsterのブログ (hatenablog.com) を見よ
パーティショニングは事前に作っておくこと
上限が4000のため最大日単位で11年、時間単位で5か月くらいでpartition_expiration_daysも指定しておく事
CREATE TABLE sample.n225 (
trading_day DATE NOT NULL OPTIONS(description="取引日"),
closing_quotation NUMERIC NOT NULL OPTIONS(description="終値"),
opening_quotation NUMERIC NOT NULL OPTIONS(description="始値"),
high NUMERIC NOT NULL OPTIONS(description="高値"),
low NUMERIC NOT NULL OPTIONS(description="低値")
)
PARTITION BY
DATE_TRUNC(trading_day, MONTH)
OPTIONS (
partition_expiration_days=1825,
require_partition_filter=true,
friendly_name="日経225時系列データ",
description="月別パーティションされた、201901から202107までの日経225時系列データ",
labels=[("environ", "dev")]
)
クエリはpartitioned byのヤツで絞れば良い
select * from aaa_history wehre
#ParticionIDで絞る(つーかpartitioned byのヤツで日付をキャストしてUTCをJST日付に
date(rec_time) = date(datetime_add(datetime "2000-10-10 00:00:00" interval -9 hour))
AND
#実際の時間で絞る、パーティションが日付区切りなので時間検索だけなら全件検索になる
datetime(rec_time) between datetime_add(datetime "2000-10-10 00:00:00" interval -9 hour)
and datetime_add(datetime "2000-10-10 00:59:59" interval -9 hour)
2)シャーディング
検討中… 上のパーティションも
シャーディングは_TABLE_SUFFIXを使ったり、テーブル名にハードコーディングする。
日付のキャスト select * from `task_*` where _TABLE_SUFFIX = REPLACE(CAST(date AS STRING), '-', '')
DROP TABLE `task_*`のようにワイルドカードは削除時は使えない
大量削除は下記のようにbq cmdリストを作りBashで。(Terminal貼りつけでも可)
シャーディングはデータセット別にしてデータセットごと消すようにしたいが
Delete BigQuery tables with wildcard - Stack Overflowselect concat("bq rm -f -t ",table_schema,".", table_name, ";" )
from INSERT_YOUR_DATASET_NAME.INFORMATION_SCHEMA.TABLES
where table_name like "INSERT_YOUR_TABLE_NAME_%"
order by table_name desc
削除されたテーブルは7日以内なら復元することも可能
テーブルの管理 | BigQuery | Google CloudBQタイムトラベルで2-7日前のデータを見れる
タイムトラベルを使用した履歴データへのアクセス | BigQuery | Google Cloud ///UNNEST
UNNESTを知らないとBigQueryを使えない? | 4番は司令塔 (pep4.net)ARRAY を一組の行にフラット化するには、UNNEST 演算子を使用
SELECT id, title FROM games, UNNEST(titles) AS title
id | titles |
1 | [skyrim, fortnite] |
2 | [atvvsmx, mario] |
↓フラット化
id | title |
1 | skyrim |
1 | fortnite |
2 | atvvsmx |
2 | mario |
ただしUNNESTで指定したカラムが空の配列やNULLの場合、該当行は無くなってしまうので注意
id=3 titles=[]やid=4 titles=NULLの時はid=3,4は引っ張れないということ
select * from unnest(['aaa', 'bbb']) as baka -> rowとして2行出る
select ['aaa', 'bbb'] as baka -> 1行目に配列として全て含まれ出る
sql - How to query multiple nested fields in Bigquery? - Stack OverflowUnnestでもflattenができず空欄ができる場合、結局left join
空を含むカラムはSelectに残し、repeatedのカラムはleft joinでくっつける
VariantsをunnestしてるがPricesもrepeatedなのでleft joinのものを出している
repeatedもarrayと同じらしいが、、、cross joinやarray_to_stringもやったが駄目だった
なおrepeated以外はunnestが効かない
それでも駄目ならselect句の指定方法やwhere句で絞ると空欄が抜けたよ
select Productid,Variants.SKU,Variants.Size
,Prices.Currency,Prices.Country
from `ga-export-0000.feed.feed_dev`
,UNNEST (Variants) AS Variants
LEFT JOIN UNNEST(Variants.Prices) as Prices
///ARRAY型とSTRUCT型
Arrayは上のUnnestを参照。
Structは構造体型。順序付きで親子の構造を持つ。各フィールドはデータ型(必須)とフィールド名(オプション)を持つ。
array型 unnestできる、[]なのでarray_length()で数が取れる
struct型 unnestできる、ネストを含みスキーマでrecord型と表記される、struct型の子へは.ドットで指定す
stringでJSONはjson_extractを使う
配列との絡みでjson_query_arrayを使う、2段階くらいは関数で対処できるがそれ以上はwith句がいい
BigQueryでの複雑なJSON文字列の扱い方と注意点 - Qiita JSON functions | BigQuery | Google CloudCREATE TABLE IF NOT EXISTS `bangboo-prj.ds.x_list` (
`record_time` TIMESTAMP,
`name` ARRAY
)
INSERT INTO `bangboo-prj.ds.x_list` (`record_time`,`name`) VALUES (CURRENT_TIMESTAMP(),['a','b'])
struct型(record型)は子や孫でヒットすれば親を含めて表示されてしまう
見やすくするため*ではなく、カラムを特定すると空欄が表示されなくなり
親が出なくなり理解しやすくなる(必ずカラム指定したい)
Array=String Repeatedつまりリスト(配列)に値を入れる書式(下記で2つしか入らない)
insert into aaa (aaa) value ("['aaa','bbb']") value has STRING
insert into aaa (aaa) value (`['aaa','bbb']`) Unrecognized name: `['aaa','bbb']`
insert into aaa (aaa) value (['aaa','bbb']) OK
insert into aaa (aaa) value ('["aaa","bbb"]') value has STRING
insert into aaa (aaa) value (`["aaa","bbb"]`) Unecognized name
insert into aaa (aaa) value (["aaa","bbb"]) OK
insert into aaa (aaa) value ([`aaa`,`bbb`]) Unrecognized name
insert into aaa (aaa) value ([aaa,bbb]) Unrecognized name: aaa
insert into aaa (aaa) value ([123,456]) Value has type ARRAY
例)権限が変わっていないかの確認する等
降順で最新の日付のアイテムを見る、そして最終ページの古い日付のアイテムを見る
そしてそれらを比較する
select record_time, name, asset_type, m, b.role
from cai_iam_policy_history
,unnest(iam_policy.bindings) b
,unnest(b.members) m
where record_time between timestamp('2021-05-01') and timestamp('2021-06-30')
and b.role in ("roles/bigquery.dataViewer", "roles/bigquery/jobUser")
and m like '%ketsu@bangboo.com%'
and ancestor_path like '%ketsuproject%'
order by record_time desc
SQL解説)struct型が沢山入っていても全部unnestしfromに入れればいい
from a, unnest(iam_policy.bindings) b, unnest(b.members) m
unnest(iam_policy)はできないので2階層目から
一つ階層上ではunnest時に別名を付けて下の階層はその別名でunnest
struct型の子へは.ドットで指定すればいい、フラットでなくてもbでも取得ができる
↑
通常SQLは「表.カラム」だが「親カラム.子カラム」なので、出元がどこかテーブルを探すかスキーマ内を探すかで迷う
///json_extract, json_extract_scalar
2番目の引数はパス
BigQueryでの複雑なJSON文字列の扱い方と注意点 - Qiita標準 SQL の JSON 関数 | BigQuery | Google Cloudwith t as (
SELECT unco_data AS col_1 FROM `kuso`
WHERE date = "2021-08-04"
)
SELECT
json_extract(col_1, '$.color') as unco_color,
json_extract(col_1, '$.temperature') as temperature,
json_extract(col_1, '$.fart.times[0].stink') as first_stink,
FROM t
)
PIVOT(
MAX( IF (active IS NOT NULL, 1, 0))
FOR user IN ("a", "b")
)
↓
tool a b
------------
axe 1 0
sword 0 1
※参考にピボットテーブル
集計して行を列に変換、生ログをある単位でまとめる
生ログが「日 店 金額」の場合
↓
ピボットで「日 金額 (店1 店2 店3)」にする等で、各項目を行と列と値に配置し直す
BigQueryでPreviewになったPIVOTとUNPIVOTを試す | DevelopersIO (classmethod.jp)PIVOTの中は定数でないとだめだが、
Execute Immediate なら動的にイケる、
がGoogleSheetのConnectedSheetではサポートされておらず無理という罠
///縦持ち横持ち
pivotは集計関数を用いる、単純の入れ替えならSQLならこちら
[SQL]データの縦持ち、横持ちを入れ替える | DevelopersIO (classmethod.jp)///新旧の差分
比較したいデータの共通してい部分で外部結合をしてnull部分を探す
WITH
old_e AS (
SELECT * FROM status WHERE user IN ('a@old.com')
),
new_e AS (
SELECT * FROM status WHERE user IN ('a@new.com')
)
SELECT * FROM old_e o
FULL OUTER JOIN new_e n ON o.id = n.id AND o.date = n.date
WHERE o.id is null OR n.id is null
ORDER BY o.id, o.date
unionにexcept distinctをSQLを付けると差分になる
https://qiita.com/tatsuhiko_kawabe/items/2537c562c6d99f83e37b
SELECT * FROM item.item_table
EXCEPT DISTINCT
SELECT * FROM item.item_table WHERE user_id = 'A'
1つ目の結果から2つ目を引いたものを出す
///REGEXP_REPLACE 正規表現で文字を削除
WITH markdown AS
(SELECT "# Heading" as heading
UNION ALL
SELECT "# Another Heading" as heading)
SELECT
REGEXP_REPLACE(heading, r"^# He", "") AS html
FROM markdown;
標準 SQL の文字列関数 | BigQuery | Google Cloud///スラッシュで分割するとarrayになるのでオフセットで取得
select SPLIT(path, "/")[OFFSET(3)] from www
スラッシュの最後を取る
ARRAY_REVERSE(SPLIT(aaa, "/"))[SAFE_OFFSET(0)]
///Job kill
CALL BQ.JOBS.CANCEL('job_id')
CALL BQ.JOBS.CANCEL('project_id.job_id')
job idでエラー詳細を確認
bq show -j
bq show --project_id bangboo_sandbox --format json -j bqjobidxxxxxxxxxx | jp .
job idはコンソールのBQのジョブ詳細やスクリプトキックならロギングから見つけてもいい
クエリならjob/query historyでわかるがbq cmdでもエラーが返る
bq query --nouse_legacy_sql 'select ketsu from `prj`.oshi.ri'
unrecognized name: 'kusofuke@ketsu.com' at [1:149]
select * from prj.`region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECT
where job_id ="aaaaa" and creation_time > "2022-01-01"
ジョブIDの取得
SELECT
project_id,
job_id,
user_email,
creation_time,
start_time,
--query,
total_slot_ms
FROM `region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECT
--`region-us`.INFORMATION_SCHEMA.JOBS_BY_USER
--`region-us`.INFORMATION_SCHEMA.JOBS_BY_FOLDER
--`region-us`.INFORMATION_SCHEMA.JOBS_BY_ORGANIZATION
WHERE state != "DONE"
--state = "RUNNING"
--state = "PENDING"
AND user_email = 'my@email.com'
AND project_id = 'paa'
AND start_time < TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 3 MINUTE)
AND total_slot_ms > (1000 * 30)
AND PARTITIONDATE BETWEEN '2021-01-01' AND '2021-01-02'
--PARTITIONTIME BETWEEN TIMESTAMP('2021-01-01') AND TIMESTAMP('2021-01-02')
///upsert(アップデートか新規インサート
https://swfz.hatenablog.com/entry/2021/02/08/195024
MERGE aaa target USING tmptbl src
ON target.time = src.time
WHEN MATCHED AND src.satus = 'rejected' THEN
DELETE
WHEN MATCHED THEN
UPDATE SET ...
WHEN NOT MATCHED THEN
INSERT ROW
///window関数
集約関数(GROUP BY)だと個別データは出力されず集計データだけでるが
window関数だと集計データが個別データにouter joinされた形で出力される
SELECT
deptname,
id,
salary,
AVG(salary) OVER (PARTITION BY deptname)
FROM emp;
deptname | id | salary | avg_salary
-----------+-------+--------+-------------
dev | 11 | 5200 | 5020
dev | 7 | 4200 | 5020
dev | 9 | 4500 | 5020
dev | 8 | 6000 | 5020
dev | 10 | 5200 | 5020
hr | 5 | 3500 | 3700
hr | 2 | 3900 | 3700
sales | 3 | 4800 | 4866
sales | 1 | 5000 | 4866
sales | 4 | 4800 | 4866
deptnameでグループしそのsalaryの集計のAVGが出ている
下のようにover()が空でも良い、4900は大体
SELECT
deptname,
id,
salary,
AVG(salary) OVER () AS avg
FROM emp;
deptname | id | salary | avg
-----------+-------+--------+-------------
dev | 11 | 5200 | 4900
dev | 7 | 4200 | 4900
dev | 9 | 4500 | 4900
dev | 8 | 6000 | 4900
dev | 10 | 5200 | 4900
hr | 5 | 3500 | 4900
hr | 2 | 3900 | 4900
sales | 3 | 4800 | 4900
sales | 1 | 5000 | 4900
sales | 4 | 4800 | 4900
関数としては集計関数がそのまま使えるようだ
OVERはwindow関数を使う宣言、OVERの後にどのようにwindowを作るのかを定義
PARTITIONでwindowでつまりどの範囲でグループを作るか指定
AVG(salary) OVER (PARTITION BY deptname, sub_deptname) でサブデプト単位での平均となる
///誰が実行しているかをセッションユーザで出す
標準 SQL のセキュリティ関数 | BigQuery | Google CloudSELECT SESSION_USER() as user;
+----------------------+
| user |
+----------------------+
| jdoe@example.com |
+----------------------+
///エラーハンドリング
BQのクエリ内の条件によりerror()でエラーが吐ける
///プログラムで使う
from google.cloud import bigquery
client = bigquery.Client()
QUERY = ('SELECT name FROM `bigquery-public-data.usa_names.usa_1910_2013`')
query_job = client.query(QUERY)
rows = query_job.result()
for row in rows:
print(row.name)
///Pythonも含めトランザクション
/// BANGBOO BLOG /// - GCP script///承認済みビュー authorized view
authorized viewを設定するとそのviewを対象とする権限だけ必要で権限をさかのぼり付与しなくていい(通常のviewは参照元の権限も必要)
この権限移譲は閲覧権限のみで編集権限等は含まない
被参照の元テーブル側に許可するview名を設定する
authorized viewがないと参照先のviewの更に先の参照先に権限が必要でエラーがでる
問題のないユーザと問題のあるユーザの権限の差分を見ると分析ができる
authorized viewを付与すると玄関となったビューはdataEditorではビュー更新ができなくなる
対象のauthorized viewは管理者を立て一元管理するのが良さそう
→ビューにも、ソーステーブルにもEditor権限が必要、ソーステーブルにはテーブルレベルで付与すればいい
基本はauthorized view設定を外す>ビュー変更>再設定
■saturationの場合、詰まっている、サチっている
対象にクエリを発行 select 1
同プロジェクトの他のテーブルにクエリを発行 select 1
別プロジェクトから対象にクエリを発行 select 1
reservationsのoverviewを見る
対象のSQLを発行
別のプロジェクトで同SQLを発行
時間を比べる
Google側の問題と思われるときはGoogleのサポートへGo
Google Could Status
Google Cloud Status DashboardINFORMATION_SCHEMA < Audit log で調査
メタデータ(データに対するデータ)
システムメタデータ(作成更新日時、サイズ、誰いつ参照
ビジネスメタデータ(オーナ、更新頻度、カラムの意味
select * from prj.ds.INFORMATON_SCHEMA.TABLES
select * from prj.ds.INFORMATON_SCHEMA.PARTITIONS
longterm storageでサイズが100000b以上で、更新日が1か月以上とか出せる
select * from prj.ds.INFORMATON_SCHEMA.COLUMNS where column_name like '%kuso%'
select * from prj.ds.INFORMATON_SCHEMA.VIEWS where view_definition like '%kuso_table%'
view_definitionはSQL文が入っている
select * from prj.ds.INFORMATON_SCHEMA.JOBS_BY_(USER / PROJECT / ORGANIZATION)
誰アクセス/誰作った/何Job等も分かる、180日しか出せないが
roles.bigquery.resourceViewerが必要
カラム例:user_email、query、referenced_tables
Auditlogは プロジェクト間で使用されるBQでも情報が取れる
info_schemaのjobs_byとほぼ同じ内容が取れるがよりリッチ
利用ユーザ数、旧データを見ている人、権限変更操作ログ等
SELECT `b-sandbox`.test_ds.count_row(1); で実行できる
UDFやテーブル関数のルーティンを承認しておくと誰からでも使える(ビューと違い権限管理できずセキュリティがズブズブになると思われ)
target_prj.trg_dsに受け入れる関数を共有指定する形
UDFは戻り値がある、テーブル関数は副問い合わせとして使う形か
///ScheduledQueryの実行者
コンソールの場合:コンソール操作者
Terraformの場合:Terraform実行者
bqコマンドの場合:任意に設定ができる
サービスアカウントをbqコマンドでSQ実行者として登録する場合、通常は問題がないがスプレッドシートを使用するなら@プロジェクト名.iam.gserviceaccount.com等でアクセス権が必要なため、会社のポリシーによってはうまく行かない。batch@unco.comのような共通メールを作成し使用したい。(GWS側でOUを使いTrusted ruleによりSAにGoogleDriveへアクセス許可すると問題回避できるが:OUをつくりそのOU内で専用共有ドライブを作成し設定する)
サービスアカウントにScheduleQueryを実行させる設定に必要な権限
https://cloud.google.com/bigquery/docs/scheduling-queries?hl=ja
操作者
BQ job user
BQ transfers.get/update
BQ data viewer/editor
●iam ServiceAccountUser
サービスアカウント
BQ job user
BQ transfer
BQ data viewer/editor
Scheduled queryからの保存先
コンソールだと同じプロジェクト内だが、create文を自由記載ならどこでもOK
設定者一覧を出したい場合
bq --format=json --project_id=bangboo-oketsu ls --transfer_config --transfer_location=us | jq.[].name
bq --format=json show --transfer_config project/1111111/locations/us/tranferConfigs/111111 | jq .ownerInfo.email
■BQ transfer(クエリが不要なBQ連携、3rd partyもあり)
データセットコピー、GCSファイル
Ama S3, Azure storage, Oracle, Salesforce, Ads系等々
■Cloud SQLにBQからクエリ
SELECT * FROM EXTERNAL_QUERY("connection_name", "SELECT * FROM db.tbl")
https://zenn.dev/ykdev/articles/4a4d2fbc6b4fe1
■BQ DMLクォータ超過
割とSQLだとすぐに壁にあたる
上限がテーブル単位のためテーブル名を分けると回避できるらしい
BQ streaming insert->BQ storage read/write APIの上限はDMLと別で、閾値が大きい
APIだとProtocol buffersが必要で、Date/Timestampが対応しておらず
Unixエポックからの日数/秒数への変換が必要、、、
■SQLはカラム数の増加数で構成考える?
left outer joinはカラム数がカラム数の合計から共通のjoin onのカラム数を引いた数(行数はleftに同じ)
full outer join はカラム数がカラム数の合計から共通のjoin onのカラム数を引いた数(行数はleftの要素数にrightの要素数を合計したもの)
unionは重複を除外し表を足し合わせるため行数が両表の合計行数(カラム数は合致必要でカラム数は変わらない)
unian allは重複を除外せず表を足し合わせるため行数が両表の合計行数(カラム数は合致必要でカラム数は変わらない)
cross joinはカラム数が両表のカラム数の合計、行数は両表の行数の掛け算
再帰的にSQL処理はcross joinし条件を付けるか?
■課金
クエリ課金:使用しているプロジェクトで課金される、データの置き場所ではない
定額フラット:$2000/100slot/m(全プロジェクトでスロットを共有)、オンデマンド:$5/T=2Gスキャンで1円位
flat rateでもflex slotsとして時間帯によりスロットを増やす等ができる
課金を減らすには:カラムを減らす、パーティショニング
プレビューを活用:しかしビューだとプレビュー機能はない。列が501列以上あったら501列以降はプレビュー出ない
データ保管課金:データ量
$1/50G/m
active storageからlong term storageへの移行は自動(90日変更がない、50%off)
6,000スロットを使うBigQueryのリソース配分最適化への挑戦 (plaid.co.jp)■権限
事前定義ロールと権限 | BigQuery | Google Cloudjob user:select文クエリ実行だけでもジョブでjob userとdata viewerが要る(data viewerだけでは不足)
課金プロジェクトでjob userを持ち、参照先プロジェクトでdata viewerを持つという権限構成だから
例えばjob userがなくdata ownerだけの場合はデータセットやテーブルやビューの削除作成ができるが、データロードやselect文発行はできない
IAMかデータセット/tblに必要な権限を付与する
data editorでも自分で作成したものは自分がOwnerになり削除や変更権限がある
meta data viewerならDSとテーブル一覧、テーブルのスキーマや容量等の情報が見れデータは見れない
これを広く付けておくとデータ管理が楽
■サービスアカウントに対するBQ job user
コンソールであれば画面左上の請求先プロジェクトで切り替えができるが
スクリプトであればgcloud auth login時に切り替える
gceならインスタンスにSA設定するが
請求先プロジェクトのデフォルトはインスタンスの置いている/SAが作成されたPrj
※同プロジェクトからしか選択ができない
コード上で切り替えができる
bq --project_id=xxx query 'select count(*) from ds.tbl'
■IAM(Identity and Access Management)
https://www.bangboo.com/cms/blog/page_347.html
Posted by funa : 01:00 AM
| Web
| Comment (0)
| Trackback (0)
February 11, 2021
Python Python
$ python
>>> import sys
>>> sys.path
でパス一覧が出るので探すと分かる >>> exit()でpythonコマンド終了
例えば Cloud functionsなら requrements.txtに google-api-python-client==3.3.2と記載し
PyPI · The Python Package Index でバージョンを探す
コードに from google.cloud import bigqueryと宣言する
requirementがpipインスコ
import フォルダ.ファイル名
from フォルダ.ファイル名 import *
上下同じだが、fromは一部を指定し直接使うという意、*は非推奨
つまり
import hello なら下記とする必要があるが
print(hello.hello)
from hello import hello なら省略ができ下記で良い
print(hello)
from フォルダ名 の場合
そのフォルダ名の中に __init__.pyがあれば其れ
from .xxx import aaa の.の意味は?
mainに対するモジュールから見て相対で隣
モジュール検索パスを出す
from pprint import pprint
import sys
pprint(sys.path)
■pipインスコ
PyPIでサードパーティライブラリを管理していてインスコ可
setup.pyが含まれたローカルディレクトリも指定しインスコ可
eオプションで編集可能な状態でインスコ
--userで~/.local下の管理権限不要なユーザディレクトリ以下でシステムが汚れない
--userなしで/usr下にインスコ
pip install --user -e unko
pip3 install pipenv
pyenv install --list インストールできるもの
pyenv install 3.8.8 指定verをインスコ
pyenv global 3.8.8 デフォルトに指定
pipenv PIP管理としてインスコ
pipenvはPipfileとPipfile.lockを利用しpipでrequrements.txtを用いるよりも強力
pipenv --python 3.8.8 など環境をpipfileに記載
pipenv sync Pipfileの最新を取得し環境更新
pipenv shell 仮想環境を起動
■個別
import dataclasses
import datetime
pip install pyyaml > import yaml
pip install requests > import requests
SlackのwebhookにPostするとか
↓本家
/// BANGBOO BLOG /// - Python
Posted by funa : 12:00 AM
| Web
| Comment (0)
| Trackback (0)
February 10, 2021
Python
おッPythonやるのか?
ファイル拡張子oppython.py デフォUTF-8、全部オブジェクト(list,dict,set等のミュータブルなら参照になる点に注意、必要ならcopy())
#コメント、ドキュメントストリング(三連引用符):"""そのまま表示""" print mymod.__doc__で見れる
変数型不要:p = 500 * num、でもキャストは必要、定数はない
文字繰り返し、キャスト:"文字列" * 4 + str(p) + "Hi\nお元気ですか?\nSee u"
raw文字列でescしない:print(r"インストール先は c:\\code\python\bin です")
正規表現のrも同意 re_result = re.match('hel', r'hellow python, 123, end.' )
if re_result: #None以外という意味で、Noneはいわゆるnull、Pythonにnullはない
文字数:len("東京都")→3
文字列[開始:終了]→→ str = "Flower" print(str[1:4]) → low
文字列 % (値1, 値2, ...)→→ num= "10進数では %d 、16進数では %x " % (num, num)
"xxxx{index:書式指定子}xxxx".format(値)→→ "名は{:<8s}で年は{:>3d}で".format(name, age)
f"xxxx{値:書式指定子}xxxx"→→ f"名は{name:<8s}で年は{age:>3d}で"
0/空の文字列''/値なしはfalse、Noneは? x = None x is None→→true?
//→除算切り捨てし整数、**→べき乗
関数宣言はdef kansu(): で中で宣言する変数はローカル変数
関数外で宣言された変数はグローバル変数でどの関数の中でも扱えるようになる
なお関数内でもglobal henでグローバル変数を宣言できる
Pythonでのグローバル(global)変数の宣言方法 | UX MILK返り値複数はcsvでタプルになる、リストが楽か? return a,b → (a, b) あるいは return [a, b] → [a, b]
def func(a, b):
return a, b
result = func()
result[0]がa、result[1]がb
try/exceptを関数内で設定することも、逆に関数呼び出し時にも使用ができる、else, finally, raiseも使う、エラーが出ても止めたくない場合は try-except Exceptions as e、逆にexceptを入れなければ止まるので安全
try:
get_all_transfer(project_id)
excerpt Exception as e:
print(e)
置換は左辺が要る? a = a.replace('x','')
とほほのPython入門 - リスト・タプル・辞書 - とほほのWWW入門 (tohoho-web.com)Pythonの辞書とリストとクラス 複数情報の受け渡し|みはみ|noteリストa=[1,2,3]はmap(), filter(), reduce()等が使える
a=a.append()とかa=a.extend()は値がないんで駄目、単純にappend(b)やextend(b)で左辺不要
取得:a[0]、for v in a:
リストの合体:list_a += list_b
セット型set={1,2,3}は重複や順序や添字の無いリスト、set(list)でキャストし重複を無くせる、ミュータブルは格納できない
取得 for v in a:
tuple→タプルは定数リスト、更新無しならリストより速い a = 1,2,3 a = (1, 2, 3)
取得:a[0]、for num in a:
dict→辞書は連想配列みたいな{a:1,b:2}はitems(), keys(), valus(), iteritems(), get()を使える
Python | 辞書に含まれるすべてのキーと値を取得する (javadrive.jp) 取得:dict_a['key1']、for k in dict_a.keys(): for v in dict_a.values(): for k, v in dict_a.items():
dictの合体:dict_a.update(dict_b)
クラス→例えば●●クラスを宣言しsampleインスタンスを生成し、getter/setterで変数に入れて置く
取得:sample.key
BigQuery→別名を付ければ名前で取得できるが、インデックスでも取得できる(これ何?)
取得:for row in query_job: →row[0], row["t"]
lambdaは無名関数?
str_w = input('何か入力してください-->') #入力させた値を取れるが数字もstr
__iter__()はnext()を持つオブジェクトを返し、next()は次の要素を返し、最後に達するとStopIteration例外を返す?
yield はイテレータを返すジェネレータを定義?
@デコレータは関数を実行する前後に特殊な処理を実行したい場合?
withで終了処理を指定できる、ファイル読込とその後の処理とか
assertや__debug__はテストで機体通りかを確認する?
passは中身の無い関数やクラスを作成しkara.p=1で粋なり属性追加等ができる
execは引数の文字列をPythonとして実行 exec "print 'Hello'"
delはオブジェクトを削除 del x, y, z
継承やオーバーライド class MyClass2(MyClass):
多重継承class MyClassC(MyClassA, MyClassB): で纏めて使えるようになる
class MyClass:
"""A simple example class""" # 三重クォートによるコメント
def __init__(self): # コンストラクタ
self.name = ""
def __del__(self): #インスタンスが消滅する際に呼出でコンストラクタ
print "DEL!"
def __str__(self): #文字列化
return "My name is " + self.name
def getName(self): # getName()メソッド
return self.name
def setName(self, name): # setName()メソッド
self.name = name
class MyClass2(MyClass):
def world(self):
print "World"
class MyClass3(MyClass):
def hello(self): # 親クラスのhello()メソッドをオーバーライド
print "HELLO"
a = MyClass() # クラスのインスタンスを生成
a.setName("Tanaka") # setName()メソッドをコール
print a.getName() # getName()メソッドをコール
print a #=> My name is Tanaka 文字列化
b = MyClass2() #継承
b.hello() #=> Hello
b.world() #=> World
c = MyClass3() #オーバーライド
c.hello() #=> HELLO
super()を使ってオーバーライドする
super()は基底クラスのメソッドを継承した上で処理を拡張
super().__init__(x、y)が使える
with構文で処理の前後で__enter__、__exit__を使う
__enter__メソッドで事前処理
__exit__メソッドで事後処理
if __name__ == "__main__":
モジュール時の勝手実行を抑える
import helloの時hello.py 内部での __name__ は "hello"
python hello.pyのような実行時hello.py の内部の __name__ は "__main__"
from math import pi, radians→mathモジュールから特定のオブジェクト(関数/変数/クラス)をimpo(math.piみたいに書かず省略できる)
import urllib.error→urllibパッケージからerrorモジュールをimpo、パッケージはフォルダ
import numpy as np→別名でしか使えなくなるnp.array()とかで
モジュール=ファイル名.pyでファイルをimpoしている
from {another_file} import {ClassName}
another_file.pyがファイル名
class ClassNameがクラス名
from {パッケージ:ディレクトリ} import {モジュール:ファイル}
ちゅー書き方もできるらしいが、どっち?
impo順:標準ライブラリ>サードパーティライブラリ>ローカルライブラリ(自作のライブラリ)
関数や変数:小文字スネークケース(sample_func)
クラス名、例外、型変数:キャピタルパスカルケース(SampleClass)
定数名:大文字アンダースコア区切り(SAMPLE_CONST)
モジュール名:小文字(samplemodule, sample_module)
パッケージ(フォルダ)名:小文字。アンダースコア非推奨(samplepackage)
インデントは半角スペース4つ
1行半角で79文字以内
トップレベルの関数やクラスは2行開ける
デバッグの方法案
print(type(v)) でどんなメソッドを持っているか等を探る
print(v) をコマンド前後や流れで沢山仕込みでどこでエラーが出ているか探す
is not subscriptableのエラー 添字不可エラーでリストでないのにリストとして入れようとしている
※参照になりコピーされない、必要ならコピー(値を入れた時点で参照が外れるので実際問題少ない?)
a = []
b = a
b.append(1)
print(a) #[1]
https://qiita.com/ponnhide/items/cda0f3f7ac88262eb31e
https://nishiohirokazu.hatenadiary.org/entry/20120125/1327461670
環境変数を扱う
import os
print(os.environ["HOME"]) ホームディレクトリ、LANGでja_JP.UTF-8とか
os.environ["PHASE"] = "staging" 環境変数に代入できるのは文字列だけ
del os.environ["PHASE"] 削除
コマンドラインの引数を扱う
python3 sys_arg_test.py a 100
dst_prj = sys.argv[1] (aが入っている)
sys.argv (['sys_arg_test.py','a','100']
i = 0
v = "["
for s in list_v:
i += 1
if i > 1:
v += ","
v += "'" + s + "'"
v += "]"
SQL = "insert into aaa (aaa) value ({v})"
※テキスト選択
Shift↑or↓ で行全体
home(+fn)で行頭、end(+fn)で行末移動
【基礎一覧】Pythonの基本文法を全て解説してみた!【初心者】 (suwaru.tokyo)Python基本文法まとめ - QiitaとほほのPython入門 - とほほのWWW入門 (tohoho-web.com) Python入門 ~Pythonのインストール方法やPythonを使ったプログラミングの方法について解説します~ | Let'sプログラミング (javadrive.jp)Welcome to Python.orgHTMLの中に少し埋め込めず、基本的にプログラムの中にHTMLを埋め込む:CGI(Perl然)
さくらインターネットでPython CGI (mwsoft.jp)WSGI
Python で WSGI (Web Server Gateway Interface) に従ったシンプルな Web サーバで Hello World - QiitaPython用Webサイト用途フレームワーク:Flask(軽量)、Django
WSGI について — Webアプリケーションフレームワークの作り方 in Python (c-bata.link) GCPでどう使うかは不明だがホスティングは↓
ウェブ ホスティング | Google Cloud 静的ウェブサイトのホスティング | Cloud Storage | Google Cloudstr.split() 区切り文字で分割しリスト等に入れる
Pythonで文字列を分割(区切り文字、改行、正規表現、文字数) | note.nkmk.meprint('Sam' in 'I am Sam') # True 任意の文字列を含むか判定: in演算子
Pythonで文字列を検索(〜を含むか判定、位置取得、カウント) | note.nkmk.me==============
ここで動かせるgoogle colaboratory→
Colaboratory へようこそ - Colaboratory (google.com)半角スペース2個で改行
#の数で見出し
*で箇条書き
数字と.で番号を振る、- でリスト
* or - or _ を3つ以上で水平線
[ ]でチェックボックス、[x]でチェック
| td | td | td |でテーブル
**aaa**で太字、*aaa*で斜体
~~aaa~~で打消し線
[タイトル](URL)でリンク
```でコードの挿入、`でインライン挿入
> or >> で引用
[^1]で注釈
\バックスラッシュでマークダウンのエスケープ
==============
宗教論争(事実は同じでも他人の認知は違うので意味なし
if self.flag_ok == 1 and self.mode == '1'
↓一見で分からんなら変数名を工夫してこうやんな
if self.file_verify_completed and self.mode == GRANT_PERMISSION:
マジックナンバーを使わない(数字の方が曖昧性が無い場合も)
STATUS_ERROR = -1
STATUS_SUCCESS = 0
self.status_error = STATUS_SUCCESS
初期値をエラー値にし、業務判定エラーでステータスを設定したらreturnで抜ける
def exFunction(self):
self.status_error = STATUS_ERROR
try:
if XX = AAA:
self.status_error = STATUS_XX_ERROR
retrun
self.status_error = STATUS_SUCCESS
retrun
except:
~エラー処理、ステータスは変更しない
エラーメッセのハードコーディングを避ける方法(ハードが場所と内容が分かり易いかも)
MSG_ERROR_OLD_EMAIL = "Error: 旧メール%sです\n"
e_message_list.append(MSG_ERROR_OLD_EMAIL % (old_email))
self.error_message = '\n'.join(e_message_list)
ケチって分厚い本1冊にしたが全然進まぬ、薄い奴星e、?チッPython、誰がJSONじゃ~い、チェーンソー魔わすっぞ
続編、、モジュールとかmportとか、
/// BANGBOO BLOG /// - Python Python
Posted by funa : 07:30 PM
| Web
| Comment (0)
| Trackback (0)
December 25, 2020
Promise
https://rightcode.co.jp/blog/information-technology/javascript-promise
https://rightcode.co.jp/blog/information-technology/javascript-async-await
http://www.tohoho-web.com/ex/promise.html
https://sbfl.net/blog/2016/07/13/simplifying-async-code-with-promise-and-async-await/
https://qiita.com/niusounds/items/37c1f9b021b62194e077
https://qiita.com/soarflat/items/1a9613e023200bbebcb3
非同期関数は処理の順序を制御できない問題があった、そこでPromise
↓
Promise オブジェクトは then(ok_callback, ng_callback) というメソッドを持ちます。
then() はPromise が成功または失敗になるまで処理を受け流し、
処理を.then()で繋げ順番を確保することが可能
成功時に ok_callback を、失敗時に ng_callback をコールバック関数として呼び出します
.then() は第一引数に成功時のコールバック関数、第二引数に失敗時のコールバック関数
.catch(ng_callback) は、.then(undefined, ng_callback) と同じ意味
.catch() は処理中に発生した throw をキャッチできる
ES2018(ES9) では、.finally() がサポートされました
function aFunc3(data) {
return new Promise(function(okCallback, ngCallback) {
setTimeout(function() {
if (Math.random() < 0.30) {
ngCallback(new Error('ERROR!'));
} else {
okCallback(data * 2);
}
}, Math.random() * 1000);
});
}
function sample_finally2() {
aFunc3(100).then((data) => {
console.log(data);
return aFunc3(data);
})
.then((data) => {
console.log(data);
return aFunc3(data);
})
.then((data) => {
console.log(data);
throw new Error('ERROR!!!');
})
.catch((e) => {
console.log("catch");
console.log(e);
})
.finally(() => {
console.log('*** Finally ***');
});
}
//200 400 800 catch Error:ERRROR!!! *** Finally ***
Promise.all() は配列で指定された全てのPromiseタスクを待ち全てが完了した時点で .then()を呼ぶ
Promise.race()ならいずれかのPromise
function sample_all() {
p1 = taskA();
p2 = taskB();
Promise.all([p1, p2]).then(() => {
console.log("taskA and taskB are finished.");
});
}
↓
ES2017 では、async/await がサポートされました
async と await を用いることで、Promise に対応した非同期関数を、同期関数の様にシンプルに呼び出すことが可能となります
同期関数の様に呼び出したい非同期関数を呼び出す際に await をつけます。await を呼び出す関数に async をつけます
async function sample_async_await_with_catch() {
var val = 100;
try {
val = await aFunc3(val);
console.log(val);
val = await aFunc3(val);
console.log(val);
val = await aFunc3(val);
console.log(val);
} catch (e) {
console.log(e);
}
}
■コールバック関数
広い定義でいうと「高階関数に渡すための関数」
「関数を受け取る関数」は「高階関数」、つまりhello()がコールバック関数
// 関数を2回実行する関数!!
function doTwice(func) {
func(); // 1回目Hello!
func(); // 2回目Hello!
}
// あいさつするだけの関数
function hello() {
console.log('Hello!');
}
// あいさつを2回実行する
doTwice(hello);
========================================
もっと詳しく、もっと分かり易く、どう使うか↓
https://knowledge.sakura.ad.jp/24890/
https://jsprimer.net/basic/async/
https://dev.classmethod.jp/articles/javascript-asynchronous-processing/
■処理の繋がり
1)コールバック関数
ある関数の処理が終われば次のコールバック関数を呼ぶという指定がそれ
歴史的にはエラーファーストコールバック(のルール)
処理が失敗した場合は、コールバック関数の1番目の引数にエラーオブジェクトを渡して呼び出す
処理が成功した場合は、コールバック関数の1番目の引数にはnullを渡し、2番目以降の引数に成功時の結果を渡して呼び出す
fs.readFile("./example.txt", (error, data) => {
2)Promise(非同期処理に対するPromise→順番を合わせる意味では同期処理ではと思う?JSはシングルスレッドかつ非同期という糞?仕様)
ある関数の処理が終わればPromiseオブジェクトを返す
JSがシングルスレッドだが 処理を一定の単位ごとに分け処理を切り替えながら実行する並行処理(concurrent)の仕様のため 順序を考慮する必要がある
非同期処理の実行中にとても重たい処理があると非同期処理の切り替えが遅れる
Promiseオブジェクトは3つの内部状態を持ちます。
pending(保留): まだ非同期処理は終わっていない(成功も失敗もしていない)
fulfilled(成功): 非同期処理が正常に終了した
rejected(拒否): 非同期処理が失敗した
初期状態はpendingで、一度fulfilledまたはrejectedになったらそれ以降は状態は変わらず、非同期処理の終了時に返す値もそれ以降は変わらない
Promiseのコンストラクターは関数を引数に取って、その関数がさらに2つの関数を引数に取る
1番目の関数(resolve)に引数を渡して実行すると状態がfulfilledになり、引数の値はPromiseオブジェクトが保持する値になる
2番目の関数(reject)に引数を渡して実行すると状態がrejectedになり、引数の値はPromiseオブジェクトが保持する値になる
関数が例外を投げた場合も状態がrejectedになり、投げた値がPromiseオブジェクトが保持する値になる、throwする値をrejectedに渡して実行した時と同じ
then()は2つの関数を引数に取り、Promiseの状態がfulfilledになったら1番目の関数が、rejectedになったら2番目の関数が実行されます。
then()の1番目の引数が関数でなければidentity function(入力値をそのまま返す関数)が代わりに使われます
2番目の引数が関数でなければthrower function(入力値を例外として投げる関数)が代わりに使われます
catch()は1番目の引数にidentity functionを指定したthen()と同じ
上の挙動をオレオレPromiseをYakusokuで作っているので分かり易い https://knowledge.sakura.ad.jp/24890/
なお、本質としてはコレ、下記ソースが決まりの流れ、ひな形としてヤリ慣れるしか
1)時間が掛かる処理をPromise化して順序立てよう
2)成功と失敗のコールバックを指定しよう
//処理にコールバック関数を入れて成功と失敗時の型で終える
function dummyFetch(cmt, callBack) {
setTimeout(() => {
if (cmt.startsWith("/success")) {
callBack(null, { body: `Response body of ${cmt}` });
} else {
callBack(new Error("Bad"));
}
}, 1000 * Math.random());
}
//プロミスを入れるためラッパーを関数にかます
function aaaFilePromise(cmt) {
return new Promise((resolve, reject) => {
dummyFetch(cmt, (err, data) => {
if (err) {
reject(err); // 失敗: 内部状態をrejectedにする
}
else {
resolve(data); // 成功: 内部状態をfulfilledにする
}
});
});
}
//プロミスチェーンでのフロー
aaaFilePromise("/success/passwd")
.then((data) => { // 読み出しに成功したらresolve()に渡した値が引数として渡される
console.log("1", data);
//return 'next';//テキストがあってもなくても次のthenに行く、省略でもテキストでも第一引数関数に行く成功側
return aaaFilePromise("/etc/text");//エラーで次のthenの失敗側の第二引数関数にきっちり行く
})
.then((data) => {
console.log("2", data);
return aaaFilePromise("/success/shadow1");
}, (data) => {
console.log("2e", data);
return aaaFilePromise("/success/shadow2");
})
.then((data) => {
console.log("3", data);
return aaaFilePromise("/etc/shadow");
})
.catch((err) => { // reject()に渡した値が引数として渡される
console.log("error", err);
});
then()/ catch()は、引数で渡された関数の戻り値から新たにPromiseオブェクトを作り、そのオブジェクトを返します。そのためメソッドチェーンが可能
引数に渡した関数の戻り値がPromiseオブジェクトの場合はそのオブジェクトをそのまま返す、そうでなければ戻り値をPromiseで包んで返す
エラーでキャッチに飛ぶ訳ではなく次のthen第2引数関数に飛んでいる、省略でcatchに行っているように見えるだけ
dexieやPWAでの提供があり使う(処理を順序立てて使うようプログラムを組む時に
dexie: db.schedule.where('site').equals('sche').first().then(function(records) {
pwa: caches.keys().then(function(keyList){
return Promise.all(keyList.map(function(key){
3)async / await
promiseは順番決めができたがasync/awaitは順番を扱う処理もできるsetTimeout/setIntevalがプロミスチェーンだけでは時間を止められない
シングルスレッドから似非スレッドで分離し非同期になるから、awaitを入れると同期する↓
const wait = (sec) => {
return new Promise((resolve, reject) => { setTimeout(resolve, sec*1000); });
};
async function arrKick_async(arr) {
for(let i=1; i<=num_arr; i++){
arr = await kickPromise(arr);
await wait(2);
}
}
arrKick_async(arr);
========================================
JSネイティブとPromiseとasyncが混ざった場合は同期しない、then()すら超えてくる↓
4)コールバック地獄
結局コールバック地獄が扱いやすい(スレッドの切り替えがなければ同期ができる)、最近のJSフレームワークは全部Promise化しているらしいが
例)キャッシュを保存し、そのステータスを取るようにAsyncやPromiseで保存待ちの順番をにしても、待たない
//隙間がないと1度エラーだとエラーになりっぱなし
let num_cache;
num_cache = getCacheStatus();
if(num_cache == 0 || !num_cache){
num_cache = getCacheStatus();
if(num_cache == 0 || !num_cache){
num_cache = getCacheStatus();
if(num_cache == 0 || !num_cache){
num_cache = getCacheStatus();
if(num_cache == 0 || !num_cache){
//setTimeoutで隙間があっても関数スレッドの返り値を代入するスレッド切替時に、返り値を待つスレッドの方は次の処理に進んでしまいIF判定ができない
let s = setTimeout(function(){
let num_cache1 = getCacheStatus();
if(num_cache1 == 0 || !num_cache1){
s = setTimeout(function(){
let num_cache2 = getCacheStatus();
if(num_cache2 == 0 || !num_cache2){
s = setTimeout(function(){
let num_cache3 = getCacheStatus();
if(num_cache3 == 0 || !num_cache3){
s = setTimeout(function(){
let num_cache4 = getCacheStatus();
if(num_cache4 == 0 || !num_cache4){
//Func返り値やPromiseやAsyncでのスレッドの切り替えがないDOMの判定であれば上手くいく
let s = setTimeout(function(){
getCacheStatus();
if(document.getElementById('mes_filenames').innerHTML == 'none'){
s = setTimeout(function(){
getCacheStatus();
if(document.getElementById('mes_filenames').innerHTML == 'none'){
s = setTimeout(function(){
getCacheStatus();
if(document.getElementById('mes_filenames').innerHTML == 'none'){
s = setTimeout(function(){
getCacheStatus();
if(document.getElementById('mes_filenames').innerHTML == 'none'){
s = setTimeout(function(){
getCacheStatus();
if(document.getElementById('mes_filenames').innerHTML == '<?php echo $lang_page->install_none; ?>'){
function getCacheStatus(){
let num_caches = 0;
let num_success = 0;
caches.keys().then(function(keyList){
return Promise.all(keyList.map(function(key){
caches.open(key).then(function(cache) {
cache.matchAll().then(function(response) {
document.getElementById('mes_filenames').innerHTML = '';
let s;
let o;
for(const value of response){
s = value.status;
o = value.ok;
document.getElementById('mes_filenames').insertAdjacentHTML('afterbegin', value.url + '<br>');
if(s == '200' && o){
num_success++;
}
num_caches++;
}
if(num_caches > 0){
document.getElementById('mes_progress_rate').innerHTML = 'Progress: ' + num_success / num_caches * 100 + '%';
}else{
document.getElementById('mes_filenames').innerHTML = 'None';
}
});
});
}));
});
return num_caches;
}
===============
thenの入れ子だと親の部分だけ先に進んでしまう、入れ子ダメで親子を作れば親→子の一方方向で子で終わるトーナメント構造で(上がらない)
test1().then((result) => {
test2().then((result) => { //fuok });
})then(function() これは入れ子
↓
test1().then((result) => {
test2().then((result) => {
//fuok
})then(function(){ //fuok2 }); これでトーナメント構造
})catch(function(e)
promiseチェーンでthen毎にに欲しい引数を出すが、複数であればそれらの引数をthenに渡せない、下記1は駄目
1)thenで一つの引数になるようにロジックを組む(thenのトーナメント構造、一階層上で変数に入れる等)
}).then(function(response){
return [response.json(), arr_del];
}).then(function(v) {
json = v[0]; arr = v[1];
2)callbackとresolveに配列を使うとOK、オブジェクトでもいいかも
function dummyFetch(cmt, callBack) {
if(Array.isArray(cmt){
var p = cmt[0];
var s = cmt[1];
}else{
var p = cmt;
var s = 1;
}
setTimeout(() => {
if (p.startsWith("/success")) {
var r = [p, ++s];//これ不可[p, s++]
callBack(null, r);
} else {
callBack(new Error("Bad"));
}
}, 1000 * Math.random());
}
function aaaFilePromise(cmt) {
return new Promise((resolve, reject) => {
dummyFetch(cmt, (err, data) => {
if (err) {
reject(err);
}
else {
if(Array.isArray(data){
var p = data[0];
var s = data[1];
}else{
var p = data;
var s = 1;
}
resolve([p, s]); // 成功: 内部状態をfulfilledにする
}
});
});
}
===============
Promise化していない関数を使いたいが、そのまま使うかthen化できるようにするか?
1)次thenに進みたい元Funcの処理としてresolveの返り値に入れる、ダメなら省略可だがreject()に渡しcatchする
2)次thenには適当でもいいのでreturnで進む
function test1 () {
return new Promise((resolve, reject) => {
const a = 1;
const b = 2;
resolve([a, b]);
})
}
test1().then((result) => {
console.log(result[0]); // 1
console.log(result[1]); // 2
return 'go next';
}).then(function(){
エラーハンドリングしたい、よくわからんが下記で動作に違いがでた、rejectはJSがエラーを吐いた
1)catchさせるにはthrow new Errorし、alertを出す
2)catchはしないが次のthenには移動させないためreturn false
}).then(function(json){
if(json.init == 'Not appropriate access'){
throw new Error('Server warning');
}else if(json.init == 'No data'){
//reject("initiate!");
return false;
}else{
resolve(json);
}
}).catch(function(error){
alert('Ooops: ' + error);
});
Promise.allを使って、3つのpromiseを同時に実行、allはすべての非同期処理がresolveされたタイミングで結果を返
Promise.all([test1, test2, test3]).then(function() {
console.log("Fourth");
もっと簡単に async, await, Promise - Qiita■Javascript
https://www.bangboo.com/cms/blog/page_325.html
Posted by funa : 01:06 AM
| Web
| Comment (0)
| Trackback (0)