はしがき
ネットにある記事を参考にしながら作業を行うと躓くことが多くありました。この記事では、Compute Engine上でMySQLが動き、ローカルからログインできるところまでの手順を記載します。
無料枠のCompute EngineでMySQLを使いたい人には参考になるかもしれません。
最後には、Go言語を使ったGCEのインスタンスの起動と停止、IPアドレス取得プログラムが書いてあります。
環境
- 2024年4月17日
- Mac OS 14.0 (Intel Mac)
- Google Chrome
手順
Compute Engineのインスタンスを作成
有効になっていない場合は、Compute Engine APIを有効化
-
リージョン:us-west1
-
ゾーン:us-west1-b
-
マシンタイプ:e2-micro
-
ブートディスク:
- OS:CentOS
- バージョン:CentOS 7
- ブートディスクの種類:標準永続ディスク
- サイズ:30GB
-
「詳細オプション」→「ネットワーキング」から見られる、「ネットワークタグ」に好きなタグ名を入力。(これはファイアウォール設定で使用します)
無料枠の構成です。
ファイアウォールでTCP 3306を許可
「VPCネットワーク」→「ファイアウォール」から「ファイアウォール ルールを作成」に進む。
- 名前:<任意の名前>
- トラフィックの方向:上り
- 一致したときのアクション:許可
- ターゲットタグ:<上で決めたネットワークタグ>
- 送信元 IPv4 範囲:お試しで使用するなら
0.0.0.0/0
- プロトコルとポート
- 指定したプロトコルとポート
- TCP:(チェックをつける)
- ポート:3306
- TCP:(チェックをつける)
- 指定したプロトコルとポート
Compute EngineにSSHで接続
接続後、シェルで下記のコマンドを上から実行
sudo yum localinstall -y https://dev.mysql.com/get/mysql80-community-release-el7-2.noarch.rpm
# 鍵がないと怒られるため実行
sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2023
sudo yum install -y mysql-community-server
sudo systemctl start mysqld.service
sudo systemctl enable mysqld.service
# 下記コマンドでパスワードが表示されるのでメモ
sudo grep 'temporary password' /var/log/mysqld.log
# 下記コマンドは、上記で表示されたパスワードを最初に入力する
# その後、任意のパスワードを入力したり、質問に回答したりする
mysql_secure_installation
# MySQLにログイン(パスワードは先ほど決めたもの)
mysql -u root -p
下記では、全ての権限を付与しています。
CREATE USER '<任意のユーザ名>' IDENTIFIED BY '<任意のパスワード>';
GRANT ALL ON *.* TO '<上と同じユーザ名>';
exit;
MySQLから抜けます。
sudo firewall-cmd --add-service=mysql --zone=public --permanent
sudo firewall-cmd --list-services --zone=public --permanent
上記で外部からの接続を許可します。
ローカルから接続
# 作成したユーザでログイン
mysql -h <Compute Engineインスタンスの外部IPアドレス> -P 3306 -u <作成したユーザ名> -p
おまけ
下のような関数を利用すると、
- インスタンスの起動
- IPアドレスの取得
- MySQLにアクセスして処理
- インスタンスを停止
のようなことが一つのプログラムでできます。
環境変数GOOGLE_APPLICATION_CREDENTIALS
には、サービスアカウントのJSONキーへのパスを書いておきます。
必要な権限はcompute.instances.get
、compute.instances.start
、compute.instances.stop
の三つです。下記プログラムを実行する場合は、「IAMと管理」から「ロール」、「ロールを作成」で新しくロールを作成するか、既存のそれっぽいロールをサービスアカウントに付与します。
言語はGoです。
package main
import (
"context"
"fmt"
"os"
compute "cloud.google.com/go/compute/apiv1"
"cloud.google.com/go/compute/apiv1/computepb"
"google.golang.org/api/option"
)
// Compute Engineのインスタンスを起動する
func StartInstance(projectID, zone, instanceName string) error {
ctx := context.Background()
sa := option.WithCredentialsFile(os.Getenv("GOOGLE_APPLICATION_CREDENTIALS"))
instancesClient, err := compute.NewInstancesRESTClient(ctx, sa)
if err != nil {
return fmt.Errorf("NewInstancesRESTClient: %w", err)
}
defer instancesClient.Close()
req := &computepb.StartInstanceRequest{
Project: projectID,
Zone: zone,
Instance: instanceName,
}
op, err := instancesClient.Start(ctx, req)
if err != nil {
return fmt.Errorf("unable to start instance: %w", err)
}
if err = op.Wait(ctx); err != nil {
return fmt.Errorf("unable to wait for the operation: %w", err)
}
fmt.Println("Instance started.")
return nil
}
// 外部ipアドレスを取得する
func GetIPAddress(projectID, zone, instanceName string) (string, error) {
ctx := context.Background()
sa := option.WithCredentialsFile(os.Getenv("GOOGLE_APPLICATION_CREDENTIALS"))
instancesClient, err := compute.NewInstancesRESTClient(ctx, sa)
if err != nil {
return "", fmt.Errorf("NewInstancesRESTClient: %w", err)
}
defer instancesClient.Close()
req := &computepb.GetInstanceRequest{
Project: projectID,
Zone: zone,
Instance: instanceName,
}
resp, err := instancesClient.Get(ctx, req)
if err != nil {
return "", fmt.Errorf("unable to get instance: %w", err)
}
ip := *resp.NetworkInterfaces[0].AccessConfigs[0].NatIP
return ip, nil
}
// Compute Engineのインスタンスを停止する
func StopInstance(projectID, zone, instanceName string) error {
ctx := context.Background()
sa := option.WithCredentialsFile(os.Getenv("GOOGLE_APPLICATION_CREDENTIALS"))
instancesClient, err := compute.NewInstancesRESTClient(ctx, sa)
if err != nil {
return fmt.Errorf("NewInstancesRESTClient: %w", err)
}
defer instancesClient.Close()
req := &computepb.StopInstanceRequest{
Project: projectID,
Zone: zone,
Instance: instanceName,
}
op, err := instancesClient.Stop(ctx, req)
if err != nil {
return fmt.Errorf("unable to stop instance: %w", err)
}
if err = op.Wait(ctx); err != nil {
return fmt.Errorf("unable to wait for the operation: %w", err)
}
fmt.Println("Instance stopped.")
return nil
}
参考