ECS(Fargate)からTiDB Cloud(Serverless)にPrivateLink経由で接続してみた

2023.10.24

こんにちは、ゲームソリューション部のsoraです。
今回は、ECS(Fargate)からTiDB Cloud(Serverless)にPrivateLink経由で接続してみたことについて書いていきます。

構成

プライベートサブネットにあるECS(Fargate)からPrivateLinkを経由して、TiDB Cloudのクラスターへ接続する構成です。
TiDB管理側の環境やVPCを明示的に記載していますが、ユーザー側で意識する必要はありません。 TiDB Cloudとは何か、TiDB Cloudのアカウント作成手順の説明は割愛します。
詳細については、以下記事をご参照ください。

TiDB Cloudでの準備

クラスタの作成

TiDB Cloudにてクラスタを作成します。
Tierは無料枠があるServerlessを利用し、リージョンは東京(ap-northeast-1)を選択します。
クラスタが作成できるとダッシュボードでクラスタの情報を確認することができます。

データインポート

TiDB Cloudのインポート機能を使用して、テスト用のデータをインポートします。
インポートの方法として、ローカルかS3を選択したり、データのフォーマットとしてCSV・Parquet・Aurora Snapshot・SQL Fileを選択することができます。
今回はCSVで作成したテストデータをインポートします。
インポートするCSVファイルは以下です。

prefectual.csv

prefecturename,prefecturalcapital,region
Hokkaido,Sapporo,Hokkaido
Tokyo,Tokyo,Kanto
Aichi,Nagoya,Chubu
Osaka,Osaka,Kansai
Hukuoka,Hakata,Kyushu

インポートのプレビュー画面にて、自動で読み取られたテーブル構造が表示されます。
プライマリキーを選択してインポートを行います。
インポートができたため、実際にインポートされたデータを、自然言語処理を用いたSQLジェネレータであるChat2Queryで確認してみます。
Chat2QueryはSQL文を理解していなくても、簡単にSQL文を生成することができます。

接続情報の取得

クラスタを作成し、データも準備できたため、クラスタに接続するための情報を取得します。
クラスタのダッシュボードからConnectを押下して、接続情報を表示します。
サービス名・AZ・リージョンIDが、PrivateLink作成に必要な情報です。
接続用コードは、ECSで実行するタスクで使用します。/testの部分はデータベース名のため書き換える必要があります。
これでTiDB Cloud側の準備は完了です。

AWS環境での準備

ここからはAWS側の準備をしていきます。
以降のAWS側の設定については、TiDB Cloudがかかわる部分を中心に説明し、その他のリソースの作成については適宜割愛します。

TiDB Cloud接続用のエンドポイントの作成

まずTiDB Cloud接続用のエンドポイント作成を作成します。
その他のエンドポイントサービスで、サービス名にTiDB Cloudで取得したサービス名を入力して、サービスの検証を行います。
DNS名は有効化する必要があります。

ECSで使用するエンドポイントの作成

プライベートサブネットでECS(Fargate)を使用するために必要なエンドポイントを作成します。
作成するのはECRを利用するための3つと、CloudWatch Logsへの接続用の1つです。

  • com.amazonaws.region.ecr.dkr
  • com.amazonaws.region.ecr.api
  • com.amazonaws.region.s3
  • com.amazonaws.region.logs

必要なエンドポイントについての詳細は、以下が参考になりました。

エンドポイントの作成手順については、今回の本筋とはずれるため割愛します。

イメージの作成

TiDB Cloudへ接続する際のタスクを作成します。
ECRへpushする環境にはCloud9を使用しました。(dockerもデフォルトでインストールされています)
ディレクトリ構成は以下です。

$ tree
.
├── dockerfile
└── src
    └── main.go

TiDB Cloud接続用のソースコードは以下です。
TiDB Cloudで取得した接続コードにてDB接続し、テーブル内の全てのデータを取得します。

main.go

package main

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
)

func main() {
	// TiDB Cloudにて表示された接続コード
	db, err := sql.Open("mysql", "<接続情報>:4000)/GoECSTest")
	if err != nil {
		fmt.Println("err", err)
		fmt.Println("DB connection error")
	}
	defer db.Close()

	// SQL実行
	rows, err := db.Query("SELECT * from PrefecturesTable")
	if err != nil {
		fmt.Println("err", err)
		fmt.Println("SQL error")
	}
	defer rows.Close()

	fmt.Println("都道府県名, 県庁所在地, 地域")
	for rows.Next() {
		var prefecturename, prefecturalcapital, region string
		err := rows.Scan(&prefecturename, &prefecturalcapital, &region)
		if err != nil {
			fmt.Println("Scan error")
			return
		}
		fmt.Printf("%s, %s, %s\n", prefecturename, prefecturalcapital, region)
	}
}

Dockerfileは以下です。

dockerfile

FROM golang:1.21.3-alpine

WORKDIR /app

RUN apk update && apk add git

COPY /src .
RUN go mod init app
RUN go get github.com/go-sql-driver/mysql
RUN go mod tidy
CMD go run main.go

ファイルが準備できたら、ECRへイメージをpushします。

接続

ECSからTiDB Cloudへ接続するための準備ができたため、ECSにてタスクを実行します。
タスクを実行した後、CloudWatch Logsを確認すると、データが取得できていることが確認できました。

参考ページ

公式ページ(Connect to TiDB Serverless via Private Endpoint)

最後に

今回は、ECS(Fargate)からTiDB Cloud(Serverless)にPrivateLink経由で接続してみたことを記事にしました。
今後もTiDBやTiDB Cloudを試してみて、記事にしていきたいと思います。