/// 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

June 2, 2024

Cloud SQL
■Cloud SQL Python Connector (Cloud SQL language Connector)
CloudSQL auth proxyのバイナリインストールでないやり方
Cloud SQL Python Connector自体は暗号化しないが、内部IPならサーバレスVPCコネクタで暗号化された通信が使え安全になっている。外部IPアドレスの場合はCloud SQL Auth Proxyで通信を暗号化。
Cloud SQL 言語コネクタの概要  |  Cloud SQL for MySQL  |  Google Cloud
GitHub - GoogleCloudPlatform/cloud-sql-python-connector: A Python library for connecting securely to your Cloud SQL instances.

事前必要(pip install>requirements.txt)
Flask==3.0.3
gunicorn==22.0.0
Werkzeug==3.0.3
google-cloud-bigquery==3.25.0
google-cloud-logging==3.11.1
google-cloud-secret-manager==2.20.2
google-api-python-client==2.141.0
google-auth-httplib2==0.2.0
google-auth-oauthlib==1.2.1
websocket-client==1.8.0
google-cloud-resource-manager==1.12.5
Flask-WTF==1.2.1
cloud-sql-python-connector==1.16.0
pymysql==1.0.3

from flask import Flask, jsonify
from google.cloud.sql.connector import Connector
from google.cloud import secretmanager
import pymysql

# 環境変数の定義
PW_NAME = "sql-pw"
PROJECT_NUM = "1234567890"
DB_INSTANCE = "prj:asia-northeast1:db_instance"
DB_USER = "db-user"
DB_NAME = "db001"

# Secret Manager からパスワードを取得する関数
def get_pw(pw_name, project_num):
    client = secretmanager.SecretManagerServiceClient()
    resource_name = f"projects/{project_num}/secrets/{pw_name}/versions/latest"
    res = client.access_secret_version(name=resource_name)
    credentials = res.payload.data.decode("utf-8")
    return credentials

# Cloud SQL接続
def sql_getconn(connector):
    pw = get_pw(PW_NAME, PROJECT_NUM)
    conn = connector.connect(
        DB_INSTANCE,
        "pymysql",
        user=DB_USER,
        password=pw,
        db=DB_NAME,
        ip_type="private",
    )
    return conn

app = Flask(__name__)

@app.route('/test', methods=['GET'])
def get_table_data():
    try:
        connector = Connector()
        conn = sql_getconn(connector)
        cursor = conn.cursor()

        # SQLを実行して結果を取得
        cursor.execute("SELECT no, name, targetDate FROM test")
        rows = cursor.fetchall()

        # 結果をJSON形式に変換
        result = [
            {
                "no": row[0],
                "name": row[1],
                "targetDate": row[2].strftime("%Y-%m-%d %H:%M:%S") if row[2] else None
            }
            for row in rows
        ]

        cursor.close()
        conn.close()
        return jsonify(result), 200

    except Exception as e:
        return jsonify({"error": str(e)}), 500

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8080)

=============
# 追加オプションを使った接続も可
    connector = Connector(
        ip_type="public",  # "private" または "psc" も使用可能
        enable_iam_auth=False,
        timeout=30,
        credentials=None,  # 必要ならGoogle認証情報を渡す
        refresh_strategy="lazy",  # "lazy" または "background"
    )

#トランザクション
    try:
        conn = sql_getconn(connector)
        conn.autocommit = False  # トランザクション開始、あるいは conn.begin()
        cursor = conn.cursor()
        # 挿入するデータを準備
        new_data = [
            {"no": 4, "name": "新しい名前4", "targetDate": "2024-05-01"},
            {"no": 5, "name": "新しい名前5", "targetDate": "2024-05-02"},
        ]
        # INSERT文を構築して実行
        for data in new_data:
            sql = "INSERT INTO test (no, name, targetDate) VALUES (%s, %s, %s)"
            values = (data["no"], data["name"], data["targetDate"])
            cursor.execute(sql, values)
        conn.commit()  # トランザクションをコミット
        print("Data inserted successfully.")
    except Exception as e:
        conn.rollback()  # エラーが発生した場合はロールバック
        print(f"Transaction rolled back due to an error: {e}")
    finally:
        cursor.close()
        conn.close()

#カーソル
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
 params: dict形式で取得#[{'no': 1, 'name': 'Alice',...}, ...]
cursor = conn.cursor(cursor=pymysql.cursors.SSCursor)
 大量のデータを効率的に取得するためにストリーミングで結果を処理
cursor.execute(query, params=None)
 cursor.execute("SELECT * FROM test WHERE no = %s", (1,))
 params: プレースホルダーに対応する値のタブルまたはリスト
cursor.executemany(query, param list)
 cursor.executemany("INSERT INTO test (no, name) VALUES (%s, %s)", [(1, 'Alice'), (2, 'Bob')])
 param list:繰り返し実行するパラメータのリストまたはタブルのリスト
cursor.fetchone()
 row = cursor.fetchone()
 #結果があれば (1, 'Alice', "2025-01-01") のような形式で1行のみ取得
cursor.rowcount
 print(cursor.rowcount) #影響を受けた行数を返す

■接続検証用コンテナをビルド (内部IPを使うrun用)
gcloud builds submit --tag asia-northeast1-docker.pkg.dev/prj/artifact_reg_name/app_name

■IAM?
Cloud SQL設定にCloud SQL 管理者 (roles/cloudsql.admin)、Cloud SQL インスタンス ユーザー (roles/cloudsql.instanceUser)等のIAMが要る?
IAMユーザならいる、ローカルUserなら不要と思われる、ローカルでもCloud SQL Client (roles/cloudsql.client)等は要る

■Cloud SQL MySQL設定
【開発環境】db_instance01
Enterprise / Sandbox / AsiaNorthEast1 (Tokyo) / Single zone
MySQL ver 8.4
Shared core/1cpu 0.6GB/HDD/10GB(auto increase)
PrivateIP/設定にnwが必要(下記)/Enable private path
Auto daily backup 7days (1-5AM) / Enable point-in-time recovery
Week1 sun 0-1am/Enable query insights
root PW: 69696969
【本番環境】
Enterprise plus? キャッシュ使う?
※CloudSQLはTFファイルに記載がなくてもTFステートファイルにPWを含めてしまうためTF化しない

- NW: projects/prj/global/networks/sql-vpc-nw
- Connection name: prj:asia-northeast1 db_instance01

ユーザの作成 sql-user/82828282
 PWをコードに入れない、シクレMgrに保存

■MySQL
utf8mb4_ja_0900_as_cs_ksを使う
_ai... アクセントを区別しない (Accent Insensitive)
_as... アクセントを区別する (Accent Sensitive)
_ci... 大文字・小文字を区別しない (Case Insensitive)
_cs... 大文字・小文字を区別する (Case Sensitive)
_ks... カナを区別する (Kana Sensitive)
_bin... バイナリ

データベースとテーブルの作成
CREATE DATABASE db;
USE db;
CREATE TABLE test (
    no INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    name VARCHAR(8) NOT NULL,
    targetDate TIMESTAMP NOT NULL,
    PRIMARY KEY (no),
    INDEX index_name (name),
    INDEX index_targetDate (targetDate)
)
ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_ja_0900_as_cs_ks;

サンプルデータ
INSERT INTO `table` (`name`, `date`) VALUES ('aaa', '2002-02-23');

ORMapperは面倒なのでSQLを使う
ORM Quick Start — SQLAlchemy 2.0 Documentation
【SQLAlchemy】Generic Typesと各種DBの型 対応表
SQLAlchemyでのテーブル定義 #Python - Qiita

■データベースフラグ
confが直接変更できなためフラグとしてパラメータを渡せる
 Cloud SQL studio (コンソールでMySQLが使える)
  MySQLクライアントを使いたいならAuth proxyが必要
 HA構成だとフェールオーバーやリードレプリカ等が使える

■NW
Cloud SQLを徹底解説! - G-gen Tech Blog
Cloud SQLが内部IPだとサーバレスVPCコネクタ、or 外部IPならSQL + auth proxy
内部IPで良いのでVPCを作る、CloudSQLを内部IPで作る
サーバレスVPCアクセスコネクタを作る
 vpc: sql-vpc-nw, subnet: sql-vpc-subnet 192.168.77.0/24
  Gateway 192.168.77.1, Private Google Access On
  sql-vpc-nw-ip-range 192.168.78.0/24 on cloudSQL
  run-serverless-vpc-ac 192.168.79.0/28 on Run
ファイアウォールルールでポート (デフォルトで3306など) を開放
Cloud Run のNW設定で、サーバーレス VPCコネクタを選択、ルートオプションとしてすべてのトラフィックを VPC コネクタ経由で送信を選択
CloudSQLを30分程度掛けて起動、接続>接続テスト

VPC(例: 10.0.0.0/16)
サブネット(Cloud SQL 用): 10.10.0.0/24(例: us-central1、VPC内)
サブネット(VPCコネクタ用): 10.8.0.0/28(RunからVPCへ通信用、VPC外)
 VPC コネクタのサブネットは 10.8.0.0/28 のような小さな範囲を使用、VPC外だがrun自体がVPC外だから?
 VPC コネクタはリージョン単位なので、Cloud Run と Cloud SQL を同じリージョンに配置するのが望ましい
Google Cloudの内部NW設計によりVPC内の異なるサブネット間でも通信可能
 VPC内なら異なるリージョンのサブネットでもOK(VPC自体には範囲を設定なしでサブネットでIPが被らなければOKかと
 追加の設定なしで、例えば us-central1 の VM から asia-northeast1 の Cloud SQLに直接アクセス可

外部IPの場合:
アプリがrunならサイドカーコンテナとしてAuth Proxyを追加できる
 サイドカーは同Pod内なのでループバックアドレス127.0.0.1あるいはlocalhost:5432 (Auth Proxy起動時に指定したポート) に通信しCloudSQLに接続する
GCEにDLしてAuth proxyインストールでもいい
 アプリのコネクタはAuth Proxy動いているGCEのIP:ポート番号を指定に通信しCloudSQLに接続する
 FWでポートも開けること

■run サービスアカウント
run-sql@prj.iam.gserviceaccount.com に必要な権限
 Cloud SQL Client (roles/cloudsql.client)
 Run Invoker (roles/run.invoker)
 Compute Network User (roles/compute.networkUser) -VPCコネクタを使用する

runを建てるが、InternalIPのため同プロジェクト同VPCのGCE を作成し移動してCURLでテスト
curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" "https://run-sql-test-1212124.asia-northeast1.run.app/test"

■MySQLでUUIDを使うか、連番を使うか? > ULIDを使う
UUIDは連番に対し
 セキュリティ上より安全、サーバが異なってもユニーク
 パフォーマンスが悪い (UUIDをプライマリキーにすると速度が落ちる場合がある)
連番とUUIDの両方を振り出しておく? > ULIDを使うことにする
twitter
Hatena
Google Buzz
newsing
Yahoo!
Buzzurl
Technorati
del.icio.us
Choix
Iza!
Livedoor Clip
Facebook
Evernote
 

Posted by funa : 01:06 PM | Web | Comment (0) | Trackback (0)


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
<     February 2025     >
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
Link