Gunosy Tech Blog

Gunosy Tech Blogは株式会社Gunosyのエンジニアが知見を共有する技術ブログです。

マルチクラウド環境のためのGoパッケージ、Go Cloudを使ってみた

こんにちは、メディア事業本部のエンジニアの@__timakin__ です。 僕が好きなGo言語は、先日バージョン1.11のリリースパーティも開かれ、wasmサポートやModules機能など、結構目新しさのある機能が足されることになりました。

で、その最新のGo界隈の話題の機能の一つとして、「Go Cloud」というものがあります。

github.com

先日のリリースパーティでも、@ymotongpooさんによってGo Cloudが紹介されていました。

docs.google.com

Public Keyさんでもちょうど本日記事が公開されていました。

www.publickey1.jp

Go公式のブログ告知にもあるとおり、Goのエコシステムがより良くなる過程で、多くの企業・機関で課題となった「マルチ(ハイブリッド)クラウド」へのデプロイという、ポータビリティの実現のためのAPIを提供するパッケージが、Go Cloudです。

特定のクラウド環境、AWSやGCPなどに依存したコードを書くことがあると思いますが、チームによってはそれらのクラウドベンダーの環境を複数使いこなす、Multi-Cloudな状態になっているところもあるかと思います。

同じような考え方だと、Rubyのgemでfog というのがありますが、それを使ったことがあるひとはイメージつきやすいでしょうか。

今回は、このgo-cloudをしれっと、影響の少ない場面で導入してみました。その際に感じたことを書いてみようと思います。

Go Cloudを入れてみる

今回はAWS RDSに繋ぎに行って簡単な処理を行う際に、database/sqlを直接使わずに、google/go-cloudを使ってみることにしました。

なお、Goの環境が少し古いと、Go Cloudが内部的に呼んでいるdatabase/sqlのOpenDBという関数が実装されてなかったりするので、新し目のバージョンにしておきましょう。

sql package - database/sql - Go Packages

その後、go-cloudを入れていきます。

go get github.com/google/go-cloud

この際、公式のgithubにwireというツールをインストールする記述がありますが、これについてはこちらの記事が詳しいです。自前のDIツールのようですね。

midori5.hatenablog.com

さて、go getに成功したらあとは使うのみなのですが、例えばgo-cloudを使わずにmysqlを利用する場合、DBの接続情報の初期化は以下のようになると思います。

func main() {
    // 環境変数からデータソースの情報を取得してDBの接続情報を初期化
    c := mysql.Config{
        DBName:    dbenv.DB,
        User:      dbenv.Username,
        Passwd:    dbenv.Password,
        Net:       "tcp",
        Addr:      fmt.Sprintf("%s:%d", dbenv.Host, dbenv.Port),
        Loc:       time.UTC,
        ParseTime: true,
        Params:    dbenv.Options,
    }
    db, err := sql.Open("mysql", c.FormatDSN())
    defer db.Close()

    // 省略
}

これをgo-cloudに置き換えると、以下のようになります。AWSのRDSを利用している場合は、rdsmysqlというパッケージを利用することになります。

func main() [
    // 環境変数からデータソースの情報を取得してDBの接続情報を初期化
    db, cleanup, err := rdsmysql.Open(ctx, new(rdsmysql.CertFetcher), &rdsmysql.Params{
        Endpoint: dbenv.Host,
        User:     dbenv.Username,
        Password: dbenv.Password,
        Database: dbenv.DB,
    })
    defer cleanup()
]

見ればわかることですが、だいぶ差分は少ないですね。このcleanupという関数も、内部的にはdb.Closeを呼んでいるだけです。 明確に違うのは、CertFetcherという構造体と、指定してるパラメーターの数が少ないことでしょうか。

まず、CertFetcherについてですが、RDSに対してSSLする際の証明書情報を取ってくるための構造体のようです。

https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem という証明書取得用URLを叩きに行って取ってきているように見えます。RDS特有の接続処理をラップしている代表的な点ではないでしょうか。

https://github.com/google/go-cloud/blob/master/mysql/rdsmysql/rdsmysql.go#L169github.com

次に、パラメーターの数についてです。rdsmysqlパッケージの接続用のパラメーターは、実は結構指定できるフィールドが少ないです。じゃあ他に必要なパラメーターはどこで指定しているかというと、内部でこのように指定しています。

https://github.com/google/go-cloud/blob/master/mysql/rdsmysql/rdsmysql.go#L113github.com

マルチクラウドという仕様の縛りとはいえ、もう少し指定したいパラメーターもあると思うので、これは一長一短あるインターフェースだなと感じました。(とはいえ、今回の例だと単にインターフェースをさらっただけで、マルチクラウドの旨味を理解してるとは言えないのですが)

軽く使ってみた所感

さて、このように比較的簡単にRDSへの接続をすることができました。

その上での個人的な意見ですが、あくまでまだ試用段階だと感じます。

このブログ記事の内容を書くまでに、実は1件ほどgo-cloudにコントリビュートをしました。1行なので対したことはないですが、このオプションがないとMySQLのバージョンによっては動きません。

github.com

指定できるパラメーターの数も少なく、若干自由度はまだ低いのと、そもそも接続できない問題に早々にぶつかってしまったのは驚きでした。

とはいえ、構想自体は面白く、どこまでプラットフォームをカバーできるのかへの期待や、コミットの余地がある可能性を感じます。

こういった大きな構想を持ったライブラリに対して、コミットの余地があるというのはなかなか例としてないので、是非利用できる場面で隙を見て導入してみて、フィードバックやコミットをしてみると、楽しい経験になると思います。

Goに限らず、新しい技術を隙あらば使いたい、事業とのバランスを見つつ技術的にチャレンジしたいという方、是非弊社にご応募ください。

そうじゃなくても気軽にGoの話がしたい、Gunosyを見てみたいという方でも歓迎ですので、そういった方は@__timakin__までご一報ください。

https://hrmos.co/pages/1009778707507720193/jobs/0000003hrmos.co