/// BANGBOO BLOG ///

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

May 21, 2021

GCP Hands Off
データの種類でアーキテクチャを決める?
 コンテナはオーバヘッドが少なくVM/GCEに比べ軽量高速、スケールアップ/ダウンに優れている
GCS
 IAPを使うと画像アクセスにも認証が使えそう>LBのバックエンドではIAPが使えない
  GCEにGCSマウントするとGCEのIAPとしてイケる、gcsfuseのOSSでLinux上のドライブになる
   CensOS6.8にgcsfuseをインストールしてGCSをマウント - Qiita
   GCS Fuseを使ってみる - Qiita
 リテンションで保護期間を設定したり、ライフサイクルで削除時期を設定したり
 世代管理ができたり

■制約が重要そうでまとめて記載したい
 IAPとCDNの両立はできない
 LBのbackendにgcsを設定したときはIAPが使えない

■VPCネットワーク
default VPCネットワークを削除(セキュリティが緩いため)
vpcネットワーク作成 サブネットIPレンジ 10.27.0.0/16 等で
 private google accessはオンでいいのかon?
 FWはひとまずなしで
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を設定
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等で
GCE VMを作成(Instance scheduleで起動-停止時間が入れられる、テンプレやグループに使えない?)
 インスタンスを作って設定しスナップショットからOSイメージを作り量産すればいいが
  instance template作成してinstance group作成してもいい。IGが中々できないならIGを開きエラーメッセージを見ること
 OSはubuntu18、API access scopeには"Allow full access to all Cloud APis"で
  外部からアクセスさせずLB経由だけにしたい→外部IPがephemeralで止められない→作成時にnetwork>external ipをnoneで作成すること→
  外へでれなくなるのでgcloudコマンドが通らない→CloudNATも設定
 インスタンステンプレートのメタデータ
  起動スクリプトをファイル化できる
   キー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系)
  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
●コンソール
GCEスナップショット作成→OSイメージ作成→テンプレ作成→Healthcheck作成→MIG設定
 OSイメージはオンプレから作ったものとかHashi corpのPackerで作るとかも
FW作成
 gceに外部IPがあればアクセス試す
 fw-bangboo-http-ingress-allow ingress - "all instances" - 0.0.0.0/0 デフォルトで許可+ingressが必要
  httpsはIPではダメ、ドメイン/証明書が要るか知らんがhttpでは外部IPあればアクセスできる
   GCPのIPを自前のDNSのAレコードに設定しとけば、、
   ウェブとメールを別々のサーバで運営したい?・・・それ、ゾーン設定で出来ます! | さくらのナレッジ (sakura.ad.jp)
   ドメイン所有はDNSにTXTレコード設定ができるようだが、、、
   ウェブマスター セントラル (google.com)
  使うとき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から使うとか
  NW計算 ネットワーク計算ツール・CIDR計算ツール | Softel labs
   VPCのサブネット設定は拡大できるが縮小ができない→小さめにしておきたいが、k8sはIP沢山使うので大きめ
   プライベートサービスコネクト(VPC間を繋ぐ)を使うと疎結合でつなげられるが
 backendはhttpで、healthcheckはtcp80とproxy無し
IAP作成
 外部 HTTPS ロードバランサの設定  |  Identity-Aware Proxy  |  Google Cloud
 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が動くみたい
  IAPの設定でhttp://IPでアクセスするとhttps://に転送されたのだが(IAPがない場合は下記設定をするようだ)
  HTTP(S) 負荷分散用の HTTP から HTTPS へのリダイレクトの設定  |  Google Cloud
事前に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)
 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を求められる場合
    sudo su - でrootに切り替えてからcmd sudo su とかしてる人はだいたいおっさん (zenn.dev)
  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)置換:最大サージを指定することができるようになるだけ

■Monitoring
VMにOpsエージェント入れる
@terminalで
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位まで)
Instance groupはどう止める?>LB削除>LBのバックエンド削除>Instance group削除
 LBはinstance groupがいる、IAPはGCEの場合はLBにSSL証明書要る(ドメインもGlobalIPも要る)
  DNSのAレコードを登録しLB設定すれば証明書入る
   毎回検証終了時につぶして、立てるのが面倒そうだな→FWでdeny allしとく
 【初心者】GCP Identity-Aware Proxy (IAP), Access Context Managerを使ってみる (WEBサーバへのアクセス制限) - Qiita

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キャッシュとしても使うこともできる。
GCPにセキュアな踏み台サーバーを作成する. GCPのIdentity-Aware… | by Taiga Murakami | google-cloud-jp | Medium
 Googleにバックドアを開けてしまっては危険、、、ということはない


End

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/094054
https://techblog.gmo-ap.jp/category/tensorflow/

情報源
google-cloud-jp – Medium

3か月間300 ドル分だけ無料
https://console.cloud.google.com
無料枠
Google Cloud の無料プログラム
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段階認証、信用するデバイスの設定があるようだ

GCP ハンズオンセミナー Google_Cloud_GCPHandson_infra1122.pdf (cloudplatformonline.com)
 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の機能
機械学習を使ったスマート アクセス制御の最適化
デバイスのセキュリティ、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:になって消えるのでは
外部ドメインのユーザの場合はメールグループ単位でのロール付与が効かず個別アカウントで付与する必要がある?あるいは組織ポリシーを開けっ放し?

メールグループの権限関係の確認方法
 仕組み:祖->親->子、上の権限は下も持つ
 権限から確認する、所属から確認するの両面で確認
 1)権限を持っている全ての子をリストアップ
 2)所属しているメールグループの全ての親をリストアップ

//リソース
階層: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 により ウィンドウが左と右のペインに分割

リスト一覧を出す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, --log-http, --project, --quiet, --trace-token, --user-output-enabled, --verbosity

ログイン
gcloud auth application-default login
デフォルト以外のプロファイルを使う
gcloud config configurations list
gcloud config configurations create unko-profile
gcloud config configurations activate unko-profile
gcloud config set account unko@dot.com
gcloud config set project onara-project
gcloud auth login

■GCE
 Marketplaceを使えばアプリを数クリックでデプロイできる
 永続ディスク…NWストレージ、SSD永続ディスクも選択できる
 ローカルSSD…高性能、永続ではなく一時的
 非マネージドインスタンスグループ インスタンスをIGに紐づけるだけ
 ステートレスMIG 自動スケーリング(Webフロントエンド等)
  スケジュールでもスケーリングできる(cronや予測も)
 ステートフルMIG 設定を保持可(DBやデータ保持必要なstatefulなアプリ等)
  インスタンス名やIPやディスクやメタを維持する、部分的に外部化ステートレスにして自動化等も
 ゾーンMIG=シングルゾーン、リージョンMIG=マルチゾーン(最大3ゾーン)
 プリエンプティブは24時間までだが20%課金だけで安い

■マネージドクラウドDB各種
ホワイトペーパーPDF

■Bigquery
/// BANGBOO BLOG /// - BigQuery

///BQ job エラー
bq show -j <job-id>
クエリならjob/query historyでわかるがbq cmdでもエラーが返る
bq query --nouse_legacy_sql 'select ketsu from `prj`.oshi.ri'
 unrecognized name: 'kusofuke@ketsu.com' at [1:149]

■GCS
 http(s)で公開可
 Nearline…月1アクセス等
 Coldline…年1アクセス等長期アーカイブ
 (standard以外は最低保存期間の縛りがあり早期削除でもお金が掛かる)
 Multi-regional 99.95%、Regional 99.9%の可用性
料金  |  Cloud Storage  |  Google Cloud
  5GBまで無料、リージョンで値段が違う、保存/NW/取得/操作で課金
  nearlineの保存は半額で取得と併せstandardと同じ金額になるが操作費高い
   月1未満ならnearline
  coldline/archive storageは年1程度とされているが使うと結構お金が掛かる
   長期保存はせずできれば削除する、できないならポリシーでcold/archiveへ移動
    最低保存期間の縛り(90/365)があり早期削除でも請求、その期間は置いておく

■GCP Cloud asset inventory
 5週間分の履歴が保管される
 CAI exportにより任意のタイムスタンプでBQあるいはGCSに履歴情報を吐き出す
 gcloud CLIのgcould asset search-all-resourseコマンドにより設定
  BQに吐き出し各種状況のチェックやポリシーのチェックに活用

■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日は変更できる
 クエリ:Loggingをクエリで見る、Logルータのシンクをフィルタ(サンプル)する

■Monitoring
ダッシュボードはサンプルから作ると楽
MQLで改変、クエリを実行するとエラーメッセが出るんで
fetch gae_instance::appengine.googleapis.com/flex/cpu/utilization | { top1, max(val()); bottom 1, min(val()) } | UNION

■サービスアカウント
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は実行できる(下記参照)

svacキーはRSA鍵ペア、秘密鍵でJWT署名なしトークンを作成
 GCP内ではキーが自動rotateされている
 外部の場合は手動や仕組みでローテーションしたい
 開発環境ではクライアントライブラリとgoogle application credentials環境変数を使い隠匿する
サービス アカウント キーを管理するためのベスト プラクティス  |  IAM のドキュメント  |  Google Cloud
Google 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

/// サービスアカウントキーを発行せずにサービスアカウント権限を使う
サービスアカウントに直接成り代わって gcloud コマンドを実行する - Qiita
サービス アカウントの権限借用の管理  |  IAM のドキュメント  |  Google Cloud
gceにデフォルトsvacが設定されていれば誰で入ってもauthはsvac?パスはユーザだが
任意のコマンドに--impersonate-service-account=ワイルドフラグを付けるだけ
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
BeyondCorp Enterprise(VPNレス、なお下の各要素はこの為だけということではない)
┣ IAP
┣ IAM
┣ Access Context Manager(VPC Service Controls:IPとかメールドメインとか) 
┗ Endpoint Verification(Chrome機能拡張)
Cloud armor(WAF)

セキュアな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
  https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/access_context_manager_service_perimeter
GCPでセキュリティガードレールを作るための方法と推しテク - Speaker Deck
 サブネット作成の際はセキュリティの観点からフローログを15分で取る
 監査ログを有効に
 ContainerResistryの脆弱性スキャンを有効に
 ログ:データアクセス/ポリシー拒否は30日、管理アクティビティは400日
  BQにバックアップしたい
 SecurityCommandCenterで脆弱性を検知
Cloud Audit Logging 活用のベスト プラクティス | Google Cloud Blog
 集約エクスポート シンクにより監査ログをBQに貯めたい

■他
///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等のコードが直接コンソールに掛ける
 ブラウザでcloud functionsにアクセスしたら下記が出た
Error: Forbidden Your client does not have permission to get URL/kuso-ketsu from this server
呼び出しの認証  |  Google Cloud Functions に関するドキュメント
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 -> cloud scheduler
publisher -> topic : メッセージ -> pull型 subscriber -> cloud functions/run

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に権限を追記しても)
 データを一時でも書込ならスプレッドシートの共有の編集権限とシート保護しない設定が必要と思われ(セキュリティがザルに)
呼び名
 connected sheetでBQのデータをスプシに抽出する
 federated queryはBQに外部ソース(スプシ等)をインポートする

スプシの保護(シートはコピーできザルなのでセキュリティ対策でなくデータ保護)
シートを保護する、非表示にする、編集する - パソコン - ドキュメント エディタ ヘルプ (google.com)
スプシの閲覧共有だけでBQコネクテッドシートのプレビュー/抽出は可能だが、それをvlookup系で他のセルに移せない
組織でコネクテッド シートを使用する - Google Workspace 管理者 ヘルプ
他のブックにすればいいかも
編集共有した別ブックに入力データ(日付やメール)を持たせBQフェデレテッドクエリでBQに準備
閲覧共有した別ブックは参照用にBQコネクテッドシートがある形

GASのGCPプロジェクトは通常はデフォルトがベスト
デフォルトプロジェクトから切り替えると戻せない、利点も少しだけ(サイト参照)
appscript.jsonにoauthのスコープを追加しないと十分に機能しない
 GAS で OAuth のスコープが足りなくてやったこと (zenn.dev)
 GoogleAPIのOAuth2.0スコープ  |  Google Identity Platform  |  Google Developers
※エラーの場合
 BQの場合はBQコンソールでクエリ単体で実行しテスト
 loggingを見るともう少し情報がある
 スプシ等への共有設定とBQの閲覧ロール等が要る、ビューならその先の小孫~最後までのロールまで要る
 oauth自体でこけるとクッキー消去すれば待たずに再確認ができる?
Google Apps Script試行錯誤 Blog: デフォルトのGCPプロジェクトを標準のGCPプロジェクトに切り替えたい (pre-practice.net)
Google Apps ScriptのログをGoogle Cloud Platformで確認する方法 – hidetoshl.com

GASでAdminDirectoryを使う
 gas > サービス > AdminDirectory APIをOn
 gcp該当prj > APIダッシュボード > ライブラリ > Admin SDKを有効
 等でg workspaceのユーザ情報が取れるらしい
  Google Apps Script試行錯誤 Blog: AdminDirectoryでUsers.listを取得したい (pre-practice.net)
  GASでAdmin SDKを利用する(Directory編)その1 - Qiita

■アプリ
公開資料 - App Modernization OnAir 〜 モダンなアプリケーション開発とは 〜 (cloudonair.withgoogle.com)
cloud runの設定だけでCDCIできる(第10回

■ネットワーク
外部IP
 External IP addressで取得、300円/月位、通常一つは自動で割り当てられる
PoP(Point of presence)
 世界70か所でGCPとエッジ(ネット)接続
NWトポロジーで通信が可視化でき通信コストが分かる
 詳細開くのは片側だけにすると使用帯域が表示される

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 Registry

Terraform の 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"
}

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でデプロイするリソースを特定できる

Syntax - Configuration Language - Terraform by HashiCorp コメントは#が基本、//や/**/も使える
Terraform v0.12で変わるHCLの記述について - Qiita localsや変数、リストやマップ等
Terraform職人再入門2020 - Qiita yamldecodeやjsonencode等
Terraformの基本 - Foreverly (hatenablog.com)
変数
 variable(input var)はcmd実行時に変数を上書きできるが、localsはできない
 outputはapply時にterminalで値が確認できる、moduleから値を取得する

google_bigquery_connection | Resources | hashicorp/google | Terraform Registry
ドット繋ぎで値を扱える
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
}

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することが必要

for_eachで書いた.tfをterraform importする | DevelopersIO (classmethod.jp)
 ユーザ指定は user:aaa@xxx.com だったりメールグループなら group:aaa@xxx.com

■セットアップ
 作業ディレクトリの作成(プロジェクトに対するローカルのフォルダ)
 プロバイダを指定した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更新する

■既存リソースの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化にまだ向かない

■TF公式ドキュメント
google_organization_iam_custom_role | Resources | hashicorp/google | Terraform Registry
google_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のcount
数を指定してその個数のリソースを作る。なのだが
 enable_lien = true モジュール側/変数側でこう設定し
 count = var.enable_lien ? 1 : 0 リソース側で3項演算子を使えばIFのように使える
  ※for loopのようなインクリのcount"+="でなく"="の1発実行なので3項演算子でIFになる

■エラー
bigquery access denied:
gcloud auth login --enable-gdrive-access
gcloud auth application-default login --scopes="https://www.googleapis.com/auth/drive","https://www.googleapis.com/auth/cloud-platform"
BigQueryでGoogleドライブデータへのクエリでエラーが出るときの対処 (zenn.dev)

排他処理でロックが残る:
他の作業者がいなければ、terraform apply -lock=false で一時的に無視をして続行
エラーIDに対して terraform force-unlock id_num963103164
Terraform で state のロックを解除する方法、ロックを手動で行う方法 | ゲンゾウ用ポストイット (genzouw.com)
TerraformでState Lockエラーが発生したら | DevelopersIO (classmethod.jp)

■tfenvを使う場合
cd my-repo
get clone https://bitbucket/bangboo-prj.git
cd bangboo-prj
tfenv use 0.14.7
 terraform workspace list
 terraform workspace select default デフォルト
  terraform workspace new prod prodという名で作成なら
main.tf作成し記載
 terraform fmt tfファイルのフォーマット(書式は適当で書けばいい)
  gcloud auth list 認証確認
  gcloud auth application-default login クレデンシャルが必要なら
   API&Servicesでクレデンシャルは取得できそう、key=xxxx
terraform init
既存のリソースを調査
terrafrom import google_storage_bucket.pri-bucket project-abc123/asia-northeast1/pri-bucket でimportとか
 terraform refresh tfstateの最新化、どのタイミングで使う?

■既存のリソースを調査
Terraform と gcloud CLI を使用した完璧な Google Cloud インフラストラクチャの構築 | Google Cloud Blog
gcloud beta resource-config bulk-export --help
gcloud beta resource-config bulk-export --project=kuso12345 --resource-format=terraform --path=/path/to/dir/
 対応を見ると数が少ないgcloud beta resource-config list-resource-types --format=json --project=kuso12345

terraformer import google list --projects=xxxx-123 で対象のリソース確認
terraformer import google --resources=instances,forwardingRules --regions=us-west1 --projects=xxxx-123 とか

既存リソースimport
https://www.apps-gcp.com/terraformit-gcp/
https://qiita.com/uu4k/items/48d3ecfefe57dba1d7e1

■Terraform applyで意図しない権限削除で障害が発生する
Terraform x GCP で、IAM権限を全削除してしまった - Qiita
resource "google_project_iam_policy" "unko" {
  project = "my-project"
  role = "roles/noguso"
  members = [
    "serviceAccount:${google_service_account.baka.email}"
  ]
}
google_project_iam_policy:書き換えるので他は無くなる(他を消したいときに使う)
google_project_iam_binding:付与、Authritativeだが他は現状維持?
google_project_iam_member:付与、Non-authoritativeで安全、まとめ難いか
 ※_iam_policyと_iam_bindingとt_iam_memberは一緒に使えない
 ※_iam_bindingと_iam_memberは一緒に使える

google_bigquery_dataset_iam_binding:(承認済みビューの権限はなくなる>google_bigquery_dataset_accessを使え)
google_bigquery_dataset_iam_member:roleとmemberを1対1でresourceを作りまくる、Non-authoritative
 ※_iam_policyや_bindingはまとめ易そうだが権限消しそう

Terraform で GCP のサービスアカウントを管理する - Eng (なりたい) (hatenablog.com)
Terraform で GCP IAM 設定どれ使うのがいいのか - pokutuna (scrapbox.io)
google_project_iam | Resources | hashicorp/google | Terraform Registry
Authoritative: TFに明示していないものをApply時に削除しますという意、TFの権威
Non-authoritative: TFは権威を示さず、TFに明示していないものは現状維持ですという意

■勝手に公開
terraform vpc auto_create_subnetworks = falseにせなサブネットを公開して作りよる

■Applyの依存関係はdepends_on(プロジェクト作成の前に権限を付与しようとしてエラー等の順序)
[Terraform]Module間の値の受け渡しについて | DevelopersIO (classmethod.jp)
 これより先にあれをTFしてくれという記述

■データセット
google_bigquery_dataset | Resources | hashicorp/google | Terraform Registry
スキーマ取得: bq show --schema --format=prettyjson bangboo-prj:test-dataset.tbl001
ビューはコンソール>BQ>該当ビュー>detailからコピー

■組織ポリシー
google_organization_policy | Resources | hashicorp/google | Terraform Registry
制約について  |  Resource Manager のドキュメント  |  Google Cloud

■parallelismで早くなるかもしれない
あなたのterraform planを手軽に高速化する(かもしれない)魔法の言葉 - Qiita
シェル変数を設定、確認cmdは printenv
export TF_CLI_ARGS_plan="--parallelism=50"
export TF_CLI_ARGS_apply="$TF_CLI_ARGS_plan"

■テスト
TF Apply後には検証をしっかりしたい、最低Apply後にPlanを再実行したい、テストスクリプト的にチェックしたい
適応されていないことや、TF定義とtfstateと実設定の差分が想定と違うことがある感じがするからだ
moduleを含めて条件的な書き方だと、適応の順序の関係で適応が抜け2回以上TF applyしないといけなかったり

■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 クレデン発行
 export GOOGLE_CLOUD_KEYFILE_JSON=path_to/account.json クレデン設定
↑サービスアカウントで認証 環境変数にファイルパスを渡す
 gcloud auth application-default login だと個人
 これにクレデンシャルファイルのパスを渡すとサービスアカウントでgcloudコマンド打てるはず

Terraformで複数リージョンをまたいだリソース制御する (mosuke.tech)
Terraform workspaceを利用して環境毎のリソース名の変更を行う (mosuke.tech)


End

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 ../ 上に上がる
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が含まれるファイルを検索

nano text.txt 作成あるいは開く、nano簡単かも、画面下コマンドでctrl+?すればいい
 コマンドM-UはEsc+u
 ctrl+k で1行削除

sudo apt install vim
vi text.txt ファイル作成あるいは開く
 viは2つ+αのモード
 ┣コマンドモード
 ┃┗コロンモード(exモード:祖先のラインエディタ)
 ┗入力モード
 https://docs.oracle.com/cd/E19253-01/816-3946/editorvi-5/index.html
 viのコロンモードコロンモードのコマンドは、このw、q、q!、x、$5... - Yahoo!知恵袋
Escでコマンドへ抜ける
 ┗挿入 i (入力モード)
ファイル名を指定し保存 :w new_file_name.txt
強制保存のコマンド :w!
保存せず終了 :q 強制終了 :q!
:10 10行目に移動
:set number 行数を表示
:num 現在のカーソル位置行数を表示
$ カーソルを行末へ
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!
コマンド集 viコマンド集 (ritsumei.ac.jp)
カーソル移動 viでのカーソル移動方法を一通りまとめました (eng-entrance.com)
検索 【初心者向け】viでの文字列の検索方法を一通り (eng-entrance.com)

テキスト選択
 Shift↑or↓ で行全体
 home(+fn)で行頭、end(+fn)で行末移動

=============
■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)


March 9, 2021

Treachery

:||

2021/4/25に気づいた、ハニーちゃんおめでとうとありがとう、エピソードは今度どこかで

Posted by funa : 11:39 PM | Column | Comment (0) | Trackback (0)


March 6, 2021

ZERO

値段と糖質とプリン体と度数、モノによっては明らかに太る感じがしない、ゆって0じゃ無い安酒でも糖質15g位らしいので良いのがなければいつものでいいかも。それより現像ができない!!→LR再インスコ→LRよりSony謹製の方が色が良かった→元画像が暗すぎが理由→LRでノイズを追加調整(元画像に注意、14mmf1.8の使い道がなく勿体ない)

極ZERO: 138/0/0/5 ちょい高、不味い、5%で軽いが酔えなくはない、太る感じ×
Asahi Off: 118/0/0/3-4 酔えない、ノンアルの亜種かフルーティで旨い〇
のどごしZERO: 118/0/0/4 フルーティで旨い、軽いが酔えなくはない〇
贅沢ZERO: 118/0/x/6 プリン有 6%で嬉しいが雑味がすごくある気が▲
バーリアル糖質50%off緑: 85/5-10/?/4 かるくない、そもそもZEROでないが旨い◯+
氷結ZEROレモン: 108/0/0/5  レモンが強く旨い、飲みやすい◎
鏡月焼酎ハイ: 98/0/0/7 スッキリ高アルコール度で満足感、ドライが好きかも◯+
いいちんこ下町のハイボール: 168/0/0/7 高ぇ、重い感じがする▲
パーフェクトサントリービール: 168/0/x/5.5 高ぇ、旨い〇
 →氷結Zeroレモン>鏡月ドライのコンボが強い

イオン麻婆豆腐辛口(肉付)vs丸美屋辛口(花椒なし):丸は味穏やか、Aは塩と肉多い
 →Aeonのとろみ入れるの減らす、甘口は邪魔甘さで、中辛が一番いい
イオン四川式(肉無)vs丸美屋大辛(花椒付):Aは高いし辛い、お口は甘め好きda
 冷食が新しくなった、Palmボックスは忘れて何度か買ったが小さい

「カルト」はすぐ隣に: オウムに引き寄せられた若者たち (岩波ジュニア新書) | 紹子, 江川 |本 | 通販 | Amazon
霊的体験は飲み物にLSDを入れていたとなっている、まぁ殆どコレで教祖になれる

Posted by funa : 01:43 PM | Column | Comment (0) | Trackback (0)


February 21, 2021

BigQuery
■Big queryリファレンス
標準SQLとレガシーSQLがある、違いは?
標準 SQL のクエリ構文  |  BigQuery  |  Google Cloud
標準 SQL への移行  |  BigQuery  |  Google Cloud
標準 SQL のデータ型  |  BigQuery  |  Google Cloud
レガシー SQL 関数と演算子  |  BigQuery  |  Google Cloud
レガシー SQL のデータ型  |  BigQuery  |  Google Cloud
BigQuery: クラウド データ ウェアハウス  |  Google Cloud(チュートリアルみたいな) 

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

パブリックデータに直でアクセスできる
SELECT * FROM `bigquery-public-data.usa_names.usa_1910_2013`
BigQuery の一般公開データセット  |  Google Cloud
 →FROM句の書き方:他のプロジェクトを指す名前にハイフンがあるとバッククォートで囲む必要がある
  `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に使用している
地理関数とかJSON関数とか色々関数もありそう
スクリプトで変数やIfやLoopが使える 標準 SQL のスクリプト  |  BigQuery  |  Google Cloud
join on a.c=b.cはjoin on using (c)とできる

■レガシー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 Cloud
https://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,
)

■bqコマンドはコンソールで実行できる
ブラウザで該当プロジェクトに入りコンソールボタン、下記ではスキーマをJSONで取得できる
bq show --schema --format=prettyjson myProject:myDataset.tbl001
bq ls -n 3000 dataset_aho (データセット内のリスト3000件、デフォ50件?)

■データアップロード時のスキーマ指定
自動検出は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"
  }
]
なお一旦Google Cloud Storageに放り込んでからやると高速 BigQueryにデータをバッチでインポートする - Qiita

COUNT DISTINCTだが、BigQueryでは概算値が返ってくる??。正確な値が必要な場合は、GROUP EACH BYとCOUNT(*)を組み合わせる
https://www.buildinsider.net/web/bigquery/01

■BQはUTC(Universal Time, Coordinatedの頭文字)
ScheduledQueryを終了日6/9 13:00JSTで即時設定→6/9 01:20UTCで実行された
(終了時間にJST/UTCの考慮が必要か→SQ実行時間設定についてはJSTかUTCに注意するだけ)
実行履歴はUTCのためJSTに読み替える必要がある(UTCはJSTの-9時間)

■BigQuery機能
///クエリ結果を別テーブルに書き込む
その他>クエリの設定>クエリ結果の宛先テーブルを設定する
BigQueryではSELECT結果を他テーブルにInsert / テーブル洗い替えなどができる - コード日進月歩 (hateblo.jp)
クエリ結果の書き込み  |  BigQuery  |  Google Cloud

///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にもヒットしてしまう

where _TABLE_FUFFIX between format_date('%Y%m%d', date_sub(current_date(), interval 3 day))
 and format_date('%Y%m%d', current_date())

///時間のパラメータを使う
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

///パーティション
パーティション分割テーブルの概要  |  BigQuery  |  Google Cloud
BigQueryのStandardSQLで日付(date, datetime, timestamp)を変換する方法 - 寝ても覚めてもこんぴうた (hatenablog.com)

パーティション分割テーブルは2種類:パーティショニングとシャーディング

1)パーティショニング
BigQueryでパーティション分割テーブルを作成する - goodbyegangsterのブログ (hatenablog.com) を見よ
パーティショニングは事前に作っておくこと
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 Overflow
select 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日以内なら復元することも可能
https://cloud.google.com/bigquery/docs/managing-tables?hl=ja#undeletetable


///UNNEST
UNNESTを知らないとBigQueryを使えない? | 4番は司令塔 (pep4.net)
ARRAY を一組の行にフラット化するには、UNNEST 演算子を使用
SELECT id, title FROM games, UNNEST(titles) AS title
idtitles
1[skyrim, fortnite]
2[atvvsmx, mario]
↓フラット化
idtitle
1skyrim
1fortnite
2atvvsmx
2mario

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 Overflow
Unnestでも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型と表記される

CREATE TABLE IF NOT EXISTS `bangboo-prj.ds.x_list` (
  `record_time` TIMESTAMP,
  `name` ARRAY<STRING>
)
INSERT INTO `bangboo-prj.ds.x_list` (`record_time`,`name`) VALUES (CURRENT_TIMESTAMP(),['a','b'])

struct型(record型)は子や孫でヒットすれば親を含めて表示されてしまう
見やすくするため*ではなく、カラムを特定すると空欄が表示されなくなり
親が出なくなり理解しやすくなる(必ずカラム指定したい)

例)権限が変わっていないかの確認する等
降順で最新の日付のアイテムを見る、そして最終ページの古い日付のアイテムを見る
そしてそれらを比較する
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 Cloud

with 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
BigQueryでPreviewになったPIVOTとUNPIVOTを試す | DevelopersIO (classmethod.jp)
【SQL】クロス集計を扱う。PIVOT句とUNPIVOT句についてコードを踏まえて解説。 | ポテパンスタイル (potepan.com)
集計をして行を列に変換(生ログをある単位でまとめカラムにする)

--toolのactiveがonなら1、nullなら0でユーザAとBの状況を見る
SELECT * FROM (
 SELECT user, tool, active FROM `tools`
)
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)]
引き当てが無い場合はSAFE_OFFSETはNullを返し、OFFSETはエラーを返す

BigQueryの標準SQLでGROUP_CONCATしたいときはSTRING_AGG - GAミント至上主義 (hatenablog.com)
逆にまとめるには
SELECT type, STRING_AGG(DISTINCT name) FROM testData GROUP BY type;
赤身 | ブリ,いわし,アジ,マグロ,カツオ,サバ
白身 | タイ,タラ,フグ,サケ

///Job kill
CALL BQ.JOBS.CANCEL('job_id')
CALL BQ.JOBS.CANCEL('project_id.job_id')

ジョブ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 Cloud
SELECT SESSION_USER() as user;
+----------------------+
| user                 |
+----------------------+
| jdoe@example.com     |
+----------------------+

///プログラムで使う
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)

///承認済みビュー authorized view
authorized viewを設定するとそのviewを対象とする権限だけ必要で
権限をさかのぼり付与しなくていい(通常のviewは参照元の権限も必要)
 被参照の元テーブル側に許可するview名を設定する
authorized viewが設定されていないと参照先のviewの更に先の参照先に権限が必要でエラーがでる
 問題のないユーザと問題のあるユーザの権限の差分を見ると分析ができる
 authrized viewを設定できればいいが管理者がいないと混迷するかも
 →単純にエラー内容の権限を付与すればいいが
authorized viewを付与すると玄関となったビューはdataEditorではビュー更新ができなくなる?
 対象のauthorized viewは管理者を立て一元管理するのが良さそう
 →dataOwerやOwnerなら問題ないかも?基本はauthorized view設定を外す>ビュー変更>再設定

■saturationの場合、詰まっている、サチっている
対象にクエリを発行 select 1
同プロジェクトの他のテーブルにクエリを発行 select 1
別プロジェクトから対象にクエリを発行 select 1
reservationsのoverviewを見る
対象のSQLを発行
別のプロジェクトで同SQLを発行
 時間を比べる
Google側の問題と思われるときはGoogleのサポートへGo
Google Could Status Google Cloud Status Dashboard

INFORMATION_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は戻り値がある、テーブル関数は副問い合わせとして使う形か

///Scheduled query
サービスアカウントを使用しないなら設定者が実行者になる
設定者一覧を出したい場合
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

■SQLはカラム数の増加数で構成考える?
left outer joinはカラム数がカラム数の合計から共通のjoin onのカラム数を引いた数(行数はleftに同じ)
 full outer join はカラム数がカラム数の合計から共通のjoin onのカラム数を引いた数(行数はleftの要素数にrightの要素数を合計したもの)
unionは重複を除外し表を足し合わせるため行数が両表の合計行数(カラム数は合致必要でカラム数は変わらない)
unian allは重複を除外せず表を足し合わせるため行数が両表の合計行数(カラム数は合致必要でカラム数は変わらない)
cross joinはカラム数が両表のカラム数の合計、行数は両表の行数の掛け算
 再帰的にSQL処理はcross joinし条件を付けるか?
  標準SQLのFrom句のカンマはcross joinとなる
with句は副問い合わせを見やすくしたもの
distinctで(組み合わせで)一意になる行のみにし重複を省く
UNION とUNION ALLの違い - Qiita
CROSS JOIN (クロス結合)を使ってデータを取得する - JOIN (結合)を使いこなそう - SQL Server 入門 (sql55.com)
SQLのDISTINCTとは?(OracleやMySQLで使用する方法) | IT職種コラム (it-kyujin.jp)

デカい表をいくつか持ちJOINすると再帰的にWhere句で条件検索しなくてよい

■課金
クエリ課金:使用しているプロジェクトで課金、データの置き場所ではない
 定額:$2000/100slot/m(全プロジェクトでスロットを共有)、オンデマンド:$5/T=2Gスキャンで1円位
 量を減らす:カラムを減らす、パーティショニング
データ保管課金:データ量
 $1/50G/m
6,000スロットを使うBigQueryのリソース配分最適化への挑戦 (plaid.co.jp)
サポートを付けるとGoogleに聞き放題になったりする

■権限
事前定義ロールと権限  |  BigQuery  |  Google Cloud
job user:select文クエリ実行だけでもジョブでjob userとdata viewerが要る(data viewerだけでは不足)
 課金プロジェクトでjob userを持ち、参照先プロジェクトでdata viewerを持つという権限構成だから
 例えばjob userがなくdata ownerだけの場合はデータセットやテーブルやビューの削除作成ができるが、データロードやselect文発行はできない
IAMかデータセット/tblに必要な権限を付与する
 data editorでも自分で作成したものは自分がOwnerになり削除や変更権限がある

■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
■importとfrom
Pythonのモジュールとimportとfrom入門 - Qiita
Python, importの使い方(from, as, PEP8の推奨スタイル, 注意点など) | note.nkmk.me
Pythonインポート周り徹底理解への道 - Qiita
Pythonの相対インポートで上位ディレクトリ・サブディレクトリを指定 | note.nkmk.me
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インスコ
pipの使い方 (2014/1バージョン) — そこはかとなく書くよん。 ドキュメント (tdoc.info)
Python:pip における管理者権限と user install - pyてよn日記 (hatenablog.com)
Python でパッケージを開発して配布する標準的な方法 - Qiita
pythonのsetup.pyについてまとめる - Qiita
PyPIでサードパーティライブラリを管理していてインスコ可
setup.pyが含まれたローカルディレクトリも指定しインスコ可
eオプションで編集可能な状態でインスコ
--userで~/.local下の管理権限不要なユーザディレクトリ以下でシステムが汚れない
--userなしで/usr下にインスコ
pip install --user -e unko
pip3 install pipenv
pip list インスコ済みのものを確認

/// 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 です")
文字数: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でグローバル変数henにアクセスできる
返り値複数はcsvでタプルになる、リストが楽か? return a,b → (a, b) あるいは return [a, b] → [a, b]
try/exceptを関数内で設定することも、逆に関数呼び出し時にも使用ができる、else, finally, raiseも使う
とほほのPython入門 - リスト・タプル・辞書 - とほほのWWW入門 (tohoho-web.com)
リストa=[1,2,3]はmap(), filter(), reduce()等が使える、set()は重複の無いリストを扱いセット同士の減算、OR、AND、XOR 操作が可能
tuple→タプルは定数リスト、更新無しならリストより速い a = 1,2,3 a = (1, 2, 3)
dict→辞書は連想配列みたいな{a:1,b:2}はitems(), keys(), valus(), iteritems(), get()を使える
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している
 impo順:標準ライブラリ>サードパーティライブラリ>ローカルライブラリ(自作のライブラリ)

関数や変数:小文字スネークケース(sample_func)
クラス名、例外、型変数:キャピタルパスカルケース(SampleClass)
定数名:大文字アンダースコア区切り(SAMPLE_CONST)
モジュール名:小文字(samplemodule, sample_module)
パッケージ(フォルダ)名:小文字。アンダースコア非推奨(samplepackage)

インデントは半角スペース4つ
1行半角で79文字以内
トップレベルの関数やクラスは2行開ける
クラス内部では1行ずつ開けてメソッド定義
ドックストリングでクラスや関数についてコメントする(慣習的にダブルクォート)
 コード中は処理についてのコメントをなくし関数化とdocstringで参照するように
 「コメント(#)とdocstring(""")の違いは?」コメントとdocstringについて
 [Python]可読性を上げるための、docstringの書き方を学ぶ(NumPyスタイル) - Qiita

※参照になりコピーされない、必要ならコピー(値を入れた時点で参照が外れるので実際問題少ない?)
a = []
b = a
b.append(1)
print(a) #[1]
https://qiita.com/ponnhide/items/cda0f3f7ac88262eb31e
https://nishiohirokazu.hatenadiary.org/entry/20120125/1327461670

※テキスト選択
 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.org

HTMLの中に少し埋め込めず、基本的にプログラムの中にHTMLを埋め込む:CGI(Perl然)
 さくらインターネットでPython CGI (mwsoft.jp)
WSGI Python で WSGI (Web Server Gateway Interface) に従ったシンプルな Web サーバで Hello World - Qiita
Python用Webサイト用途フレームワーク:Flask(軽量)、Django
 WSGI について — Webアプリケーションフレームワークの作り方 in Python (c-bata.link)
 GCPでどう使うかは不明だがホスティングは↓
 ウェブ ホスティング | Google Cloud 静的ウェブサイトのホスティング  |  Cloud Storage  |  Google Cloud

str.split() 区切り文字で分割しリスト等に入れる Pythonで文字列を分割(区切り文字、改行、正規表現、文字数) | note.nkmk.me
print('Sam' in 'I am Sam') # True 任意の文字列を含むか判定: in演算子 Pythonで文字列を検索(〜を含むか判定、位置取得、カウント) | note.nkmk.me
==============
ここで動かせるgoogle colaboratory→ Colaboratory へようこそ - Colaboratory (google.com)

コラボラトリはマークダウン Qiita マークダウン記法 一覧表・チートシート - Qiita
半角スペース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じゃ~い、チェーンソー魔わすっぞ

/// BANGBOO BLOG /// - Python Python

Posted by funa : 07:30 PM | Web | Comment (0) | Trackback (0)


January 27, 2021

Framework
群雄割拠か弱肉強食か政治解決か遣りたい放題の中、当事者なら自然に身につくだろうが時代に参加していない貴殿には到底分からない、シルバーブレットはなく結局は愚直しかない、どう愚直になるか/どう立ち回るかを発見するのがフレームワークだ、もしトレンドを感じればそれに乗ればよい、他にシーズがあればプロダクトアウト、ニーズがあればマーケットインだ

■フレームワーク
3C(Customer/Competitor/Company:自社)
SWOT(Strength-Weakness x Opportunity-Threat)
PEST分析(Politics/Economy/Society/Technology)
3M(人物金、Men/Material/Money)
3M(ムリ:負荷が人に掛かる/ムダ:資源が余り浪費しコスト高/ムラ:負荷と浪費が交互)
7S(<3sはハード>Structure/Strategy/System、<4sはソフト>Shared value:価値観/Skill/Staff/Style:文化)
VRIO(Value/Rarity/Inimitability:模範困難性/Organization)
MVV(Mission:使命why/Vision:将来像what/Value:価値観how)
マーケ4P4C(4p:product/price/place/promotion, 4c:customer cost/customer cost/convenience/communication)
QCD(Quarity品質/Costコスト/Delivery納期)

ポーターの5forces(Competitive Rivalry:競争企業間の敵対関係/Supplier Power:売り手の交渉力/Buyer Power:買い手=顧客の交渉力/Threat of Substitution:代替品の脅威/Threat of New Entry:新規参入業者の脅威)
コトラーのSTP(segmentation:顧客やニーズや特性等で細分化/targeting:セグメ選択/positioning:勝てる位置取り)
競争戦略ポジショニング (コストや差別化や集中戦略等で業界ポジを練る)
PPM:product portfolio mgt(市場成長率xシェア->問題児:花形に育てる/花形:継続投資/金のなる木:投資無し/負け犬:撤退検討)
製品ライフサイクル:PLC(導入期:認知度と需要up/成長期:製品多角化販路拡大/成熟期:差別化とコストダウン/衰退期:選択と集中効率化)
イノベータ理論(Innovators/Early Adopters/Early Majority/Late Majority/Laggards:16%キャズム:段階で戦略を変えていく)
RFM(recency/frequency/monetary->優良顧客を見つけよりマーケ)
ポーターのバリューチェーン(企画/開発/購買/製造/物流/販売/サービス/人事の各々での価値->VRIOで分析)
アンゾフの成長マトリクス(既存市場浸透:既存市場x既存商品/新市場開拓:新規市場x既存商品/新商品開発:既存市場x新規商品/多角化:新規市場x新規商品)
TOWS(クロスSWOT分析:SWOTをSWOTする->SWOTで現状分析、さらにSWOTで戦略化)
SCAMPER(アイデアの展開->substitute代用/combine結合/adapt応用/modify修正-magnify拡大/put to other uses転用/elininate削除-minify削減/reverse逆転-rearrange再編集)
ECRS:イクルス(改善策->排除/統合/交換/簡素)

ギャップ分析(As Is/To Be<-間にaction)
特性要因図:フィッシュボーンチャート(要因を網羅的に調べる、他にも親和図法やマインドマップ)
意思決定マトリックス(縦軸に候補、評価基準を横軸、評価基準に重みをつけて点を出し、合計の総合点で判断)
CS/CE分析(Customer satisfaction/Customer expectation->各機能のcsをceに合わせる、ce高cs低の改善)
リスク評価マップ(インパクトx不確実性、インパクト大に対処し小は静観、不確実性が高いと注意が必要<-pest/5f)
AIDMA...etc...

ユダヤの商法:78対22の法則で上手くいく、契約主義で約束を守る
ケイパビリティ戦略:ビジネスプロセスを能力化、スピード/整合性/明瞭性/俊敏性/革新性が上がる、CEOがツールや組織を検討
ポジショニング戦略:競合との位置付け、STP分析をしどうポジションを取り差別化するか
タイムベース競争戦略:時間こそが希少資源、スピードが一番顧客満足が高い、数稼ぐ
アダプティブ型戦略:多くの新しいアプローチを試し最も有望なものを拡大展開、PDCA、やらな分からん時代

ランチェスターの法則:
奇襲/武器/集中、逆にシェアトップで武器も兵数あると模倣し広域戦
 自分を知る、競合を知る、シェア1位を知る
 地域限定、顧客志向営業、販路、陽動奇襲の企画、強みに集中

逆転の競争戦略:
業界破壊者(枠を壊す)/侵入者(他業種からの参入)/挑戦者(競合が攻撃)がトップシェア企業を脅かす
1)企業資産の負債化=リーダーが持つ競争優位の源泉を攻めリーダーが蓄積してきた優位な経営資源を価値のないものにし負債にしてしまう戦略:モスは店内で調理しマックより優位に、あるいは逆にセントラルキッチン
2)市場資産の負債化=リーダー企業に有利に働いていた競争のルールを変更し、顧客が持つ資産(ソフトウェア、交換部品など)を使えなくする戦略:VISAよりQRのPaypay
3)論理の自縛化=安易に追随するとリーダー企業が発信してきたメッセージと矛盾することになり、企業イメージを低下させてしまう戦略:手作り丁寧より100均
4)事業の共喰化=リーダー企業が強みとしてきた製品・サービスと共喰い関係にあるような製品・サービスを市場に出すことで、リーダー企業内に追随するか否かの不協和音を引き起こす戦略:カーシェア

ーーーーーーーーーーーーーーーーーーーーーーーーーー
■現代思想
ニーチェ:ルサンチマン、奴隷道徳<>快と力の高揚感が生を肯定、ニヒリズム
マルクス:神格化、砂漠の水を都市で売ろう、紙一枚が命より大事…社会的関係の錯覚
フロイト:無意識<>理性、理性は単なるハリボテであり無意識が主人で自律神経も管理
 エス(快楽主義)>自我:Ego(調整役)>超自我:Super ego(親/社会/会社の価値観の同一化)
  親や社会等から裏切られると同一化できずトラウマ、葛藤を無意識化に隠したい
ユング:Collective unconscious(人類は人種に限らず同じ記憶を持っている)

ーーーーーーーーーーーーーーーーーーーーーーーーーー
■リーダーシップで面白いほど結果が出る本
(仕事の種類)リーダシップ分類:指示/率先/構想/合意/育成/関係構築
  リーダシップ→変化、コントロール→維持(基本どちらもPDCA)
  若手に新しい変化のリーダシップが期待されている
(担当)鷹の眼と蟻の眼(大きな視点の戦略+現場の改善)
(頭脳)1)構想力、2)推進力、3)育成力
  →アイデア発表、ダメ出し、頼りにされる
1)構想力:戦略をゲームとして導入する、仕事の意味を伝える、今を楽しむフロー没入
2)推進力:手段の目的化を防ぐダメ出し、メンバーに寄り添う:会話の時間が足りない、現場のアイデアや成功事例を吸い出し
3)育成力:個々人の心のベクトルを少しプラスに、共通言語の定着(これがないと心の障壁や違和感)
(発想は言葉から、リーダは言葉が大事)

ーーーーーーーーーーーーーーーーーーーーーーーーーー
JCOM回線不安定:
インターネット回線の信号レベルはタブレットで通信でモデムに入って測れる
宅外でモデムを繋いででも宅外で調査しろ
同時接続数等々でスロットリングしているだろうが

Posted by funa : 03:00 AM | Column | Comment (0) | Trackback (0)


Navi: <  1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19  >
PhotoGallery


TWITTER
Search

Mobile
QR for cellphone  QR for smart phone
For mobile click here
For smart phone click here
Popular Page
#1Web
#2Hiace 200
#3Gadget
#4The beginning of CSSレイアウト
#5Column
#6Web font test
#7Ora Ora Ora Ora Ora
#8Wifi cam
#9みたらし団子
#10Arcade Controller
#11G Suite
#12PC SPEC 2012.8
#13Javascript
#14REMIX DTM DAW - Acid
#15RSS Radio
#16Optimost
#17通話SIM
#18Attachment
#19Summer time blues
#20Enigma
#21Git
#22Warning!! Page Expired.
#23Speaker
#24Darwinian Theory Of Evolution
#25AV首相
#26htaccess mod_rewite
#27/// BANGBOO BLOG /// From 2016-01-01 To 2016-01-31
#28竹書房
#29F☆ck CSS
#30Automobile Inspection
#31No ID
#32Win7 / Win10 Insco
#33Speaker
#34Arcade Controller
#35Agile
#36G Suite
#37Personal Information Privacy Act
#38Europe
#39Warning!! Page Expired.
#40GoogleMap Moblile
#41CSS Selectors
#42MySQL DB Database
#43Ant
#44☆od damnit
#45Teeth Teeth
#46Itinerary with a eurail pass
#47PHP Developer
#48Affiliate
#49/// BANGBOO BLOG /// From 2019-01-01 To 2019-01-31
#50/// BANGBOO BLOG /// From 2019-09-01 To 2019-09-30
#51/// BANGBOO BLOG /// On 2020-03-01
#52/// BANGBOO BLOG /// On 2020-04-01
#53Windows env tips
#54恐慌からの脱出方法
#55MARUTAI
#56A Rainbow Between Clouds‏
#57ER
#58PDF in cellphone with microSD
#59DJ
#60ICOCA
#61Departures
#62Update your home page
#63CSS Grid
#64恐慌からの脱出方法
#65ハチロクカフェ
#66/// BANGBOO BLOG /// On 2016-03-31
#67/// BANGBOO BLOG /// From 2017-02-01 To 2017-02-28
#68/// BANGBOO BLOG /// From 2019-07-01 To 2019-07-31
#69/// BANGBOO BLOG /// From 2019-10-01 To 2019-10-31
#70/// BANGBOO BLOG /// On 2020-01-21
#71Bike
#72Where Hiphop lives!!
#73The team that always wins
#74Tora Tora Tora
#75Blog Ping
#76無料ストレージ
#77jQuery - write less, do more.
#78Adobe Premire6.0 (Guru R.I.P.)
#79PC SPEC 2007.7
#80Google Sitemap
#81Information privacy & antispam law
#82Wifi security camera with solar panel & small battery
#83Hope get back to normal
#84Vice versa
#85ハイエースのメンテ
#86Camoufla
#87α7Ⅱ
#88Jack up Hiace
#89Fucking tire
#90Big D
#914 Pole Plug
#925-year-old shit
#93Emancipation Proclamation
#94Windows env tips
#95Meritocracy
#96Focus zone
#97Raspberry Pi
#98Mind Control
#99Interview
#100Branding Excellent
Category
Recent Entry
Trackback
Comment
Archive
<     May 2022     >
Sun Mon Tue Wed Thi Fri Sat
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Link