使用Golang SDK操作GCE的Instance Group Manager
除了一部分,GCP的各种服务的Golang SDK都是根据API定义的JSON Schema自动生成的。
由于API定义和生成的SDK具有一些特点,实际使用时可能会遇到一些困难,因此我想在这里举几个例子进行解释。
可以在这里查看实际的JSON Schema和Golang的代码。
GCE概念的解释
「Instance Group Manager」是什么意思?
一个可以管理通过GCE创建的实例的工具,这是对它直接的解释。
具体而言,它可以做到以下几点:
– 监控实例的状态
– 分配负载
– 自动扩展
– 使用实例模板
有一些实例组,具体内容如下所示。
“Instance Template” 是什么意思?
要进行的是对Instance的配置。
可以进行配置的内容有:
– 操作系统和机型
– 硬盘
– 启动时的脚本
– 网络
创建实例模板。
具体举例
我打算使用Golang SDK来创建上述资源。
具体步骤是在GCP上创建一个实例模板,然后使用该模板创建托管实例组。
样本
import (
"errors"
"fmt"
"strings"
"time"
"golang.org/x/net/context"
"golang.org/x/oauth2/google"
compute "google.golang.org/api/compute/v1"
)
func readError(op *compute.Operation) error {
if op.Error == nil {
return nil
}
errs := []string{}
for _, err := range op.Error.Errors {
errs = append(errs, err.Message)
}
return errors.New(strings.Join(errs, ","))
}
func main() {
err := func() error {
s, err := ioutil.ReadFile("/path/to/credential.json") // GoogleのIAMで作成するCredentialのJSON
if err != nil {
return err
}
c, err := google.JWTConfigFromJSON(s, compute.ComputeScope)
if err != nil {
return err
}
ctx := context.Background()
client := c.Client(ctx)
service, err := compute.New(client) // 上記のCredentialにより作成したこのServiceを全リクエストで用いる
if err != nil {
return err
}
startupScript := `
#!/bin/bash
sudo apt-get update && sudo apt-get install nginx
`
temp := &compute.InstanceTemplate{
Name: "sample-template",
Properties: &compute.InstanceProperties{
Tags: &compute.Tags{
Items: []string{
"https-server", // GoogleのFirewallはタグによってルールをインスタンスに設定する形で用いる。
"http-server",
},
},
NetworkInterfaces: []*compute.NetworkInterface{
{
AccessConfigs: []*compute.AccessConfig{
{
Name: "external-IP",
Type: "ONE_TO_ONE_NAT",
},
},
Network: "global/networks/default",
},
},
Disks: []*compute.AttachedDisk{
{
Boot: true,
InitializeParams: &compute.AttachedDiskInitializeParams{
SourceImage: "projects/debian-cloud/global/images/debian-8-jessie-v20170308",
},
},
},
MachineType: "n1-standard-1",
Metadata: &compute.Metadata{
Items: []*compute.MetadataItems{
{
Key: "startup-script", // 起動時に走らせるscriptはこの名前でメタデータに登録する。
Value: &startupScript,
},
},
},
},
}
op, err := compute.NewInstanceTemplatesService(service).
Insert(project, temp).
Do()
if err != nil {
return err
}
if err := readError(op); err != nil {
return err
}
// templateが登録されるまでラグがあるので待つ必要がある
for {
time.Sleep(1 * time.Second)
b := false
ts, err := compute.NewInstanceTemplatesService(service).
List(project).
Do()
if err != nil {
return err
}
for _, t := range ts.Items {
if "sample-template" == t.Name {
b = true
}
}
if !b {
continue
}
break
}
grp := &compute.InstanceGroupManager{
InstanceTemplate: "global/instanceTemplates/sample-template",
TargetSize: 1,
Name: "sample-group-manager",
BaseInstanceName: "sample-group",
}
op, err = compute.NewInstanceGroupManagersService(service).
Insert(project, zone, grp).
Do()
if err != nil {
return err
}
if err := readError(op); err != nil {
return err
}
return nil
}()
if err != nil {
fmt.Println(err)
return
}
}
sample-template被应用于sample-group-manager,根据sample-template的设定,会创建一个实例并正确地启动一台。
说明
服务
Golang SDK中有一个名为Service的概念(其他SDK可能也有这个概念)。
通过提供带有Credential信息的JSON来创建该Service,该JSON会由每个Service Account生成,
因此每个请求都将使用这个特殊Service进行创建。
请求主体
由于Golang SDK中没有关于各个请求属性的信息,所以需要查看每个API的参考资料。
实例模板
实例组管理器
在我使用Golang SDK尝试操作GCP服务时,我发现只有在API参考文档中才能找到哪些属性是必需的,以及它们受到了怎样的验证。也许由于自动生成的特性,这很困难,而且相当难以处理。
完全是另一回事,同样是自动生成的Cloud Vision API的Golang SDK的Godoc,它的示例代码由Python、Java、Objective-C等组成,却没有Golang的示例代码,这破坏了Godoc的完整性。
元数据
在Instance Template中,可以加入Metadata。这样做有很多方便之处,但在此我们略过(详细内容请参考本文)。重点是,可以通过名为startup-script的脚本来嵌入脚本,在服务器启动或重新启动时运行该脚本。详情如下:
运行启动脚本
操作
关于插入和删除请求,它们的返回值是通过操作(Operation)来确定的。
若要创建具有多个依赖关系的资源,则需要充分理解各个供应商服务的特性,并进行应用。由于模板的创建可能需要一些微妙的时间来反映变化,因此在重现某些难以捉摸的错误时,我确实有这样的经历。
总结
因为学习GCP的Golang SDK需要相当大的成本,所以对于小规模项目来说,最好还是用gcloud来构建。我觉得这可能是因为在我使用Golang SDK的时候,似乎很少见到其他人使用它的原因,所以我暂时自己去解释了一下。
我什么也不了解,所以希望有人能教我正直的实践方法。