🐷
GoでAWS Auroraを操作する
やろうとしたこと
オートスケーリングとは別でアプリケーションからAWS auroraインスタンスを増減するようにしたかった
使用したパッケージ
Auroraに対応していないメソッドや関数があるのでそれはドキュメントを見つつ確認する
参考にしたドキュメント
-
AWS ドキュメント
https://docs.aws.amazon.com/ja_jp/code-library/latest/ug/go_2_aurora_code_examples.html -
AWS SDK ドキュメント
https://aws.github.io/aws-sdk-go-v2/docs/configuring-sdk/ -
Golang ドキュメント
https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/rds#section-documentation
前提として
- AWS IAMにて操作を行うためのアカウント、ポリシーの許可、アクセスキーの発行を行う
- 後述するコードに使用する設定、認証ファイルの作成
IAMで作成したユーザーの名前を「test-aurora」と仮定します。
それぞれ/configディレクトリ以下に作成(ドキュメントに記載あり)
[profile test-aurora]
region = ap-northeast-1
output = json
[test-aurora]
aws_access_key_id = 発行されたアクセスキー
aws_secret_access_key = シークレットキー
全体のコード
クリーンアーキテクチャを想定しての記述となるため一部を抜粋しています。
- 環境変数のGoファイル
config/config.go
package config
type Config struct {
AbsolutePath string
Aurora struct {
ClusterName string
DBInstancePrefix string
}
}
func NewConfig() *Config {
c := new(Config)
c.AbsolutePath = "/var/www/html"
c.Aurora.ClusterName = "test-aurora-cluster
c.Aurora.DBInstancePrefix = "test-aurora-instance-"
return c
}
- ロジック内で値を扱うための構造体(ここは必要に応じて追加する)
domain/aws_aurora_db_instances.go
package domain
type AwsAuroraDBInstances struct {
ClusterName string
InstanceName string
Engine string
DBInstanceClass string
DBParameterGroupName string
}
- Auroraを操作するGoファイル
ここでは主にAWSクライアントへの接続、インスタンスの取得、作成、削除を行なっている(ロジック内で扱うように返り値は加工しています。)
infrastructure/aurora.go
package infrastructure
import (
"context"
"fmt"
"github.com/sample-aurora/domain"
"github.com/sample-aurora/config"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/rds"
)
type AwsAurora struct {
AuroraClient *rds.Client
ClusterName string
DBInstancePrefix string
}
func NewAwsAurora(c *config.Config) *AwsAurora {
return newAwsAurora(c)
}
func newAwsAurora(c *config.Config) *AwsAurora {
sdkConfig, err := config.LoadDefaultConfig(context.TODO(),
config.WithSharedCredentialsFiles(
[]string{
c.AbsolutePath + "/config/credentials", // staging
},
),
config.WithSharedConfigFiles(
[]string{
c.AbsolutePath + "/config/config",
},
),
config.WithSharedConfigProfile("sdk-aurora"))
if err != nil {
fmt.Println(err)
panic("Couldn't load default configuration. Have you set up your AWS account?")
}
auroraClient := rds.NewFromConfig(sdkConfig)
a := &AwsAurora{
ClusterName: c.Aurora.ClusterName,
AuroraClient: auroraClient,
DBInstancePrefix: c.Aurora.DBInstancePrefix,
}
return a
}
// クラスター内のReader Instanceを取得する
func (a *AwsAurora) GetDbInstanceInCluster() (instances []domain.AwsAuroraDBInstances, err error) {
output, err := a.AuroraClient.DescribeDBClusters(context.TODO(),
&rds.DescribeDBClustersInput{
DBClusterIdentifier: aws.String(a.ClusterName),
})
if err != nil {
return []domain.AwsAuroraDBInstances{}, err
}
instances = []domain.AwsAuroraDBInstances{}
for _, cluster := range output.DBClusters {
for _, member := range cluster.DBClusterMembers {
// リードレプリカのみ処理を行う
if !*member.IsClusterWriter {
identifer := *member.DBInstanceIdentifier
output, err := a.AuroraClient.DescribeDBInstances(context.TODO(),
&rds.DescribeDBInstancesInput{
DBInstanceIdentifier: aws.String(identifer),
})
if err != nil {
return []domain.AwsAuroraDBInstances{}, err
}
engine := *output.DBInstances[0].Engine
instanceClass := *output.DBInstances[0].DBInstanceClass
parameterGroupName := *output.DBInstances[0].DBParameterGroups[0].DBParameterGroupName
instance := domain.AwsAuroraDBInstances{}
instance.ClusterName = a.ClusterName
instance.InstanceName = identifer
instance.Engine = engine
instance.DBInstanceClass = instanceClass
instance.DBParameterGroupName = parameterGroupName
instances = append(instances, instance)
}
}
}
return instances, err
}
func (a *AwsAurora) CreateInstanceInCluster(instance domain.AwsAuroraDBInstances) error {
_, err := a.AuroraClient.CreateDBInstance(context.TODO(), &rds.CreateDBInstanceInput{
DBInstanceIdentifier: aws.String(fmt.Sprintf("%s%s", a.DBInstancePrefix, instance.InstanceName)),
DBClusterIdentifier: aws.String(instance.ClusterName),
Engine: aws.String(instance.Engine),
DBInstanceClass: aws.String(instance.DBInstanceClass),
DBParameterGroupName: aws.String(instance.DBParameterGroupName),
})
if err != nil {
return err
}
return nil
}
func (a *AwsAurora) DeleteDBInstance(instanceName string) error {
_, err := a.AuroraClient.DeleteDBInstance(context.TODO(), &rds.DeleteDBInstanceInput{
DBInstanceIdentifier: aws.String(a.DBInstancePrefix + instanceName),
SkipFinalSnapshot: aws.Bool(true),
DeleteAutomatedBackups: aws.Bool(true),
})
if err != nil {
return err
}
return nil
}
個人的に困った箇所
環境設定ごとに対応できるようにした
sdkConfig, err := config.LoadDefaultConfig(context.TODO(),
config.WithSharedCredentialsFiles(
[]string{
c.AbsolutePath + "/config/credentials", // staging
},
),
config.WithSharedConfigFiles(
[]string{
c.AbsolutePath + "/config/config",
},
),
config.WithSharedConfigProfile("sdk-aurora"))
Discussion