如何使用 golang 在 google 云函数中创建多实例
How to create multi instance in google cloud functions with golang
我正在尝试使用云功能在 GCP 中创建多实例,使用 golang 编程。
我参考了 https://medium.com/google-cloud/using-cloud-scheduler-and-cloud-functions-to-deploy-a-periodic-compute-engine-vm-worker-2b897ef68dc5 中的教程,然后在我的上下文中编写了一些自定义内容。这是我的代码
package cloudfunctions
import (
"context"
"fmt"
"log"
"net/http"
"os"
"google.golang.org/api/compute/v1"
)
var ProjectID = ""
var Zone = ""
var Region = ""
var InstanceName = ""
var InstanceType = ""
func DeployInstance(w http.ResponseWriter, r *http.Request) {
ProjectID = os.Getenv("PROJECT_ID")
Zone = os.Getenv("ZONE")
Region = os.Getenv("REGION")
cs, err := InitComputeService()
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Fatal(err)
}
var listInstance = []string{"e2-standard-2", "e2-standard-8", "n2-standard-2", "n2-standard-8", "n1-custom-2-8192", "n1-custom-8-32768", "c2-standard-8" }
for i:=0; i < 7; i++ {
InstanceType = listInstance[i]
InstanceName = "benchmark-"+InstanceType
instance, err := GetInstance(cs)
if err != nil {
w.WriteHeader(http.StatusTemporaryRedirect)
w.Write([]byte(err.Error() + " instance may not exist yet"))
log.Print(err)
_, err = CreateInstance(cs)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("creating instance " + InstanceName + "in zone: " + Zone))
startInstance(cs, w)
}
} else {
msg := "instance is in intermediate state: " + instance.Status
w.WriteHeader(http.StatusAccepted)
w.Write([]byte(msg))
log.Println(msg)
}
}
}
func InitComputeService() (*compute.Service, error) {
ctx := context.Background()
return compute.NewService(ctx)
}
func GetInstance(computeService *compute.Service) (*compute.Instance, error) {
return computeService.Instances.Get(ProjectID, Zone, InstanceName).Do()
}
func StartInstance(computeService *compute.Service) (*compute.Operation, error) {
return computeService.Instances.Start(ProjectID, Zone, InstanceName).Do()
}
// CreateInstance creates a given instance with metadata that logs its information.
func CreateInstance(computeService *compute.Service) (*compute.Operation, error) {
instance := &compute.Instance{
Name: InstanceName,
MachineType: fmt.Sprintf("zones/%s/machineTypes/%s", Zone, InstanceType),
NetworkInterfaces: []*compute.NetworkInterface{
{
Name: "default",
Subnetwork: fmt.Sprintf("projects/%s/regions/%s/subnetworks/default", ProjectID, Region),
AccessConfigs: []*compute.AccessConfig{
{
Name: "External NAT",
Type: "ONE_TO_ONE_NAT",
NetworkTier: "PREMIUM",
},
},
},
},
Scheduling: &compute.Scheduling{
Preemptible: true,
},
Disks: []*compute.AttachedDisk{
{
Boot: true, // The first disk must be a boot disk.
AutoDelete: true, //Optional
Mode: "READ_WRITE", //Mode should be READ_WRITE or READ_ONLY
Interface: "SCSI", //SCSI or NVME - NVME only for SSDs
InitializeParams: &compute.AttachedDiskInitializeParams{
DiskName: "worker-instance-boot-disk",
SourceImage: "projects/centos-cloud/global/images/family/centos-7",
DiskType: fmt.Sprintf("projects/%s/zones/%s/diskTypes/pd-ssd", ProjectID, Zone),
DiskSizeGb: 200,
},
},
},
}
return computeService.Instances.Insert(ProjectID, Zone, instance).Do()
}
// startInstance is a wrapper function for the switch statement
func startInstance(cs *compute.Service, w http.ResponseWriter) {
operation, err := StartInstance(cs)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Fatal(err)
}
w.WriteHeader(http.StatusOK)
data, _ := operation.MarshalJSON()
w.Write(data)
}
在上面的代码中,我想创建7个具有7个不同设置的实例,具体是实例类型和实例名称。我在云函数中测试此代码,DeployInstance 是启动函数。但是只创建了一个实例,名称为benchmark-e2-standard-2,类型为e2-standard-2。它输出错误消息 Error: Infrastructure cannot communicate with function。用户提供的代码中可能存在崩溃或死锁。可以在 https://cloud.google.com/functions/docs/troubleshooting#logging
找到其他故障排除文档
我访问了网站,但没有找到修复代码的解决方案。谁能帮助我为什么我的代码不正确,我该如何解决。如果可能,一步一步来。
提前致谢。
我找到了答案。根本原因是每个实例都必须有一个磁盘分区,名称不同。
所以,我对我的代码进行了一些更改,您可以在下面看到它。
package cloudfunctions
import (
"context"
"fmt"
"log"
"net/http"
"os"
"google.golang.org/api/compute/v1"
"time"
)
var ProjectID = ""
var Zone = ""
var Region = ""
var InstanceName = ""
var InstanceType = ""
var IDiskName = ""
func DeployInstance(w http.ResponseWriter, r *http.Request) {
ProjectID = os.Getenv("PROJECT_ID")
Zone = os.Getenv("ZONE")
Region = os.Getenv("REGION")
var listInstance = []string{"e2-standard-8","e2-standard-2", "n2-standard-2", "n2-standard-8", "n1-custom-2-8192", "n1-custom-8-32768", "c2-standard-8"}
for i:=0; i < len(listInstance); i++ {
cs, err := compute.NewService(context.Background())
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Fatal(err)
}
InstanceType = listInstance[i]
InstanceName = "benchmark-"+InstanceType
IDiskName = InstanceName+"-boot-disk"
instance, err := GetInstance(cs)
if err != nil {
w.WriteHeader(http.StatusTemporaryRedirect)
w.Write([]byte(err.Error() + " instance may not exist yet"))
_, err = CreateInstance(cs)
if err != nil {
for {
disk, derr := cs.Disks.Get(ProjectID, Zone, IDiskName).Context(context.Background()).Do()
log.Print(IDiskName + " is " + disk.Status)
time.Sleep(1 * time.Second)
if derr != nil {
startInstance(cs, w)
break
}
}
}
} else {
msg := "instance "+ InstanceName +" is in intermediate state: " + instance.Status
w.WriteHeader(http.StatusAccepted)
w.Write([]byte(msg))
log.Println(msg)
}
}
}
func GetInstance(computeService *compute.Service) (*compute.Instance, error) {
return computeService.Instances.Get(ProjectID, Zone, InstanceName).Do()
}
func StartInstance(computeService *compute.Service) (*compute.Operation, error) {
return computeService.Instances.Start(ProjectID, Zone, InstanceName).Do()
}
// CreateInstance creates a given instance with metadata that logs its information.
func CreateInstance(computeService *compute.Service) (*compute.Operation, error) {
instance := &compute.Instance{
Name: InstanceName,
MachineType: fmt.Sprintf("zones/%s/machineTypes/%s", Zone, InstanceType),
NetworkInterfaces: []*compute.NetworkInterface{
{
Name: "default",
Subnetwork: fmt.Sprintf("projects/%s/regions/%s/subnetworks/default", ProjectID, Region),
AccessConfigs: []*compute.AccessConfig{
{
Name: "External NAT",
Type: "ONE_TO_ONE_NAT",
NetworkTier: "PREMIUM",
},
},
},
},
Scheduling: &compute.Scheduling{
Preemptible: true,
},
Disks: []*compute.AttachedDisk{
{
Boot: true, // The first disk must be a boot disk.
AutoDelete: true, //Optional
Mode: "READ_WRITE", //Mode should be READ_WRITE or READ_ONLY
Interface: "SCSI", //SCSI or NVME - NVME only for SSDs
InitializeParams: &compute.AttachedDiskInitializeParams{
DiskName: IDiskName,
SourceImage: "projects/centos-cloud/global/images/family/centos-7",
DiskType: fmt.Sprintf("projects/%s/zones/%s/diskTypes/pd-ssd", ProjectID, Zone),
DiskSizeGb: 100,
},
},
},
}
return computeService.Instances.Insert(ProjectID, Zone, instance).Do()
}
// startInstance is a wrapper function for the switch statement
func startInstance(cs *compute.Service, w http.ResponseWriter) {
operation, err := StartInstance(cs)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Fatal(err)
}
w.WriteHeader(http.StatusOK)
data, _ := operation.MarshalJSON()
w.Write(data)
}
如果您对此问题有任何疑问,请留下您的评论。我希望我能支持你。
谢谢大家
我正在尝试使用云功能在 GCP 中创建多实例,使用 golang 编程。
我参考了 https://medium.com/google-cloud/using-cloud-scheduler-and-cloud-functions-to-deploy-a-periodic-compute-engine-vm-worker-2b897ef68dc5 中的教程,然后在我的上下文中编写了一些自定义内容。这是我的代码
package cloudfunctions
import (
"context"
"fmt"
"log"
"net/http"
"os"
"google.golang.org/api/compute/v1"
)
var ProjectID = ""
var Zone = ""
var Region = ""
var InstanceName = ""
var InstanceType = ""
func DeployInstance(w http.ResponseWriter, r *http.Request) {
ProjectID = os.Getenv("PROJECT_ID")
Zone = os.Getenv("ZONE")
Region = os.Getenv("REGION")
cs, err := InitComputeService()
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Fatal(err)
}
var listInstance = []string{"e2-standard-2", "e2-standard-8", "n2-standard-2", "n2-standard-8", "n1-custom-2-8192", "n1-custom-8-32768", "c2-standard-8" }
for i:=0; i < 7; i++ {
InstanceType = listInstance[i]
InstanceName = "benchmark-"+InstanceType
instance, err := GetInstance(cs)
if err != nil {
w.WriteHeader(http.StatusTemporaryRedirect)
w.Write([]byte(err.Error() + " instance may not exist yet"))
log.Print(err)
_, err = CreateInstance(cs)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("creating instance " + InstanceName + "in zone: " + Zone))
startInstance(cs, w)
}
} else {
msg := "instance is in intermediate state: " + instance.Status
w.WriteHeader(http.StatusAccepted)
w.Write([]byte(msg))
log.Println(msg)
}
}
}
func InitComputeService() (*compute.Service, error) {
ctx := context.Background()
return compute.NewService(ctx)
}
func GetInstance(computeService *compute.Service) (*compute.Instance, error) {
return computeService.Instances.Get(ProjectID, Zone, InstanceName).Do()
}
func StartInstance(computeService *compute.Service) (*compute.Operation, error) {
return computeService.Instances.Start(ProjectID, Zone, InstanceName).Do()
}
// CreateInstance creates a given instance with metadata that logs its information.
func CreateInstance(computeService *compute.Service) (*compute.Operation, error) {
instance := &compute.Instance{
Name: InstanceName,
MachineType: fmt.Sprintf("zones/%s/machineTypes/%s", Zone, InstanceType),
NetworkInterfaces: []*compute.NetworkInterface{
{
Name: "default",
Subnetwork: fmt.Sprintf("projects/%s/regions/%s/subnetworks/default", ProjectID, Region),
AccessConfigs: []*compute.AccessConfig{
{
Name: "External NAT",
Type: "ONE_TO_ONE_NAT",
NetworkTier: "PREMIUM",
},
},
},
},
Scheduling: &compute.Scheduling{
Preemptible: true,
},
Disks: []*compute.AttachedDisk{
{
Boot: true, // The first disk must be a boot disk.
AutoDelete: true, //Optional
Mode: "READ_WRITE", //Mode should be READ_WRITE or READ_ONLY
Interface: "SCSI", //SCSI or NVME - NVME only for SSDs
InitializeParams: &compute.AttachedDiskInitializeParams{
DiskName: "worker-instance-boot-disk",
SourceImage: "projects/centos-cloud/global/images/family/centos-7",
DiskType: fmt.Sprintf("projects/%s/zones/%s/diskTypes/pd-ssd", ProjectID, Zone),
DiskSizeGb: 200,
},
},
},
}
return computeService.Instances.Insert(ProjectID, Zone, instance).Do()
}
// startInstance is a wrapper function for the switch statement
func startInstance(cs *compute.Service, w http.ResponseWriter) {
operation, err := StartInstance(cs)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Fatal(err)
}
w.WriteHeader(http.StatusOK)
data, _ := operation.MarshalJSON()
w.Write(data)
}
在上面的代码中,我想创建7个具有7个不同设置的实例,具体是实例类型和实例名称。我在云函数中测试此代码,DeployInstance 是启动函数。但是只创建了一个实例,名称为benchmark-e2-standard-2,类型为e2-standard-2。它输出错误消息 Error: Infrastructure cannot communicate with function。用户提供的代码中可能存在崩溃或死锁。可以在 https://cloud.google.com/functions/docs/troubleshooting#logging
找到其他故障排除文档我访问了网站,但没有找到修复代码的解决方案。谁能帮助我为什么我的代码不正确,我该如何解决。如果可能,一步一步来。 提前致谢。
我找到了答案。根本原因是每个实例都必须有一个磁盘分区,名称不同。 所以,我对我的代码进行了一些更改,您可以在下面看到它。
package cloudfunctions
import (
"context"
"fmt"
"log"
"net/http"
"os"
"google.golang.org/api/compute/v1"
"time"
)
var ProjectID = ""
var Zone = ""
var Region = ""
var InstanceName = ""
var InstanceType = ""
var IDiskName = ""
func DeployInstance(w http.ResponseWriter, r *http.Request) {
ProjectID = os.Getenv("PROJECT_ID")
Zone = os.Getenv("ZONE")
Region = os.Getenv("REGION")
var listInstance = []string{"e2-standard-8","e2-standard-2", "n2-standard-2", "n2-standard-8", "n1-custom-2-8192", "n1-custom-8-32768", "c2-standard-8"}
for i:=0; i < len(listInstance); i++ {
cs, err := compute.NewService(context.Background())
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Fatal(err)
}
InstanceType = listInstance[i]
InstanceName = "benchmark-"+InstanceType
IDiskName = InstanceName+"-boot-disk"
instance, err := GetInstance(cs)
if err != nil {
w.WriteHeader(http.StatusTemporaryRedirect)
w.Write([]byte(err.Error() + " instance may not exist yet"))
_, err = CreateInstance(cs)
if err != nil {
for {
disk, derr := cs.Disks.Get(ProjectID, Zone, IDiskName).Context(context.Background()).Do()
log.Print(IDiskName + " is " + disk.Status)
time.Sleep(1 * time.Second)
if derr != nil {
startInstance(cs, w)
break
}
}
}
} else {
msg := "instance "+ InstanceName +" is in intermediate state: " + instance.Status
w.WriteHeader(http.StatusAccepted)
w.Write([]byte(msg))
log.Println(msg)
}
}
}
func GetInstance(computeService *compute.Service) (*compute.Instance, error) {
return computeService.Instances.Get(ProjectID, Zone, InstanceName).Do()
}
func StartInstance(computeService *compute.Service) (*compute.Operation, error) {
return computeService.Instances.Start(ProjectID, Zone, InstanceName).Do()
}
// CreateInstance creates a given instance with metadata that logs its information.
func CreateInstance(computeService *compute.Service) (*compute.Operation, error) {
instance := &compute.Instance{
Name: InstanceName,
MachineType: fmt.Sprintf("zones/%s/machineTypes/%s", Zone, InstanceType),
NetworkInterfaces: []*compute.NetworkInterface{
{
Name: "default",
Subnetwork: fmt.Sprintf("projects/%s/regions/%s/subnetworks/default", ProjectID, Region),
AccessConfigs: []*compute.AccessConfig{
{
Name: "External NAT",
Type: "ONE_TO_ONE_NAT",
NetworkTier: "PREMIUM",
},
},
},
},
Scheduling: &compute.Scheduling{
Preemptible: true,
},
Disks: []*compute.AttachedDisk{
{
Boot: true, // The first disk must be a boot disk.
AutoDelete: true, //Optional
Mode: "READ_WRITE", //Mode should be READ_WRITE or READ_ONLY
Interface: "SCSI", //SCSI or NVME - NVME only for SSDs
InitializeParams: &compute.AttachedDiskInitializeParams{
DiskName: IDiskName,
SourceImage: "projects/centos-cloud/global/images/family/centos-7",
DiskType: fmt.Sprintf("projects/%s/zones/%s/diskTypes/pd-ssd", ProjectID, Zone),
DiskSizeGb: 100,
},
},
},
}
return computeService.Instances.Insert(ProjectID, Zone, instance).Do()
}
// startInstance is a wrapper function for the switch statement
func startInstance(cs *compute.Service, w http.ResponseWriter) {
operation, err := StartInstance(cs)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Fatal(err)
}
w.WriteHeader(http.StatusOK)
data, _ := operation.MarshalJSON()
w.Write(data)
}
如果您对此问题有任何疑问,请留下您的评论。我希望我能支持你。 谢谢大家