| Portable Cloud Programming with Go Cloud |
| 24 Jul 2018 |
| |
| Eno Compton |
| |
| Cassandra Salisbury |
| |
| * Introduction |
| |
| Today, the Go team at Google is releasing a new open source project, |
| [[https://github.com/google/go-cloud][Go Cloud]], |
| a library and tools for developing on the [[https://cloud.google.com/open-cloud/][open cloud]]. |
| With this project, we aim to make Go the language of choice for developers |
| building portable cloud applications. |
| |
| This post explains why we started this project, the details of how Go Cloud works, and how to get involved. |
| |
| * Why portable cloud programming? Why now? |
| |
| We estimate there are now [[https://research.swtch.com/gophercount][over one million]] |
| Go developers worldwide. |
| Go powers many of the most critical cloud infrastructure projects, |
| including Kubernetes, Istio, and Docker. |
| Companies like Lyft, Capital One, Netflix and [[https://github.com/golang/go/wiki/GoUsers][many more]] |
| are depending on Go in production. |
| Over the years, we've found that developers love Go for cloud development |
| because of its efficiency, |
| productivity, built-in concurrency, and low latency. |
| |
| As part of our work to support Go's rapid growth, |
| we have been interviewing teams who work with Go to understand how they |
| use the language and how the Go ecosystem can improve further. |
| One common theme with many organizations is the need for portability across cloud providers. |
| These teams want to deploy robust applications in [[https://en.wikipedia.org/wiki/Cloud_computing#Multicloud][multi-cloud]] |
| and [[https://en.wikipedia.org/wiki/Cloud_computing#Hybrid_cloud][hybrid-cloud]] environments, |
| and migrate their workloads between cloud providers without significant |
| changes to their code. |
| |
| To achieve this, some teams attempt to decouple their applications from |
| provider-specific APIs in order to produce simpler and more portable code. |
| However the short-term pressure to ship features means teams often sacrifice |
| longer-term efforts toward portability. |
| As a result, most Go applications running in the cloud are tightly coupled |
| to their initial cloud provider. |
| |
| As an alternative, teams can use Go Cloud, |
| a set of open generic cloud APIs, to write simpler and more portable cloud applications. |
| Go Cloud also sets the foundation for an ecosystem of portable cloud libraries |
| to be built on top of these generic APIs. |
| Go Cloud makes it possible for teams to meet their feature development goals |
| while also preserving the long-term flexibility for multi-cloud and hybrid-cloud architectures. |
| Go Cloud applications can also migrate to the cloud providers that best meet their needs. |
| |
| * What is Go Cloud? |
| |
| We have identified common services used by cloud applications and have created |
| generic APIs to work across cloud providers. |
| Today, Go Cloud is launching with blob storage, |
| MySQL database access, runtime configuration, |
| and an HTTP server configured with request logging, |
| tracing, and health checking. |
| Go Cloud offers support for Google Cloud Platform (GCP) and Amazon Web Services (AWS). |
| We plan to work with cloud industry partners and the Go community to add |
| support for additional cloud providers very soon. |
| |
| Go Cloud aims to develop vendor-neutral generic APIs for the most-used services |
| across cloud providers such that deploying a Go application on another cloud is simple and easy. |
| Go Cloud also lays the foundation for other open source projects to write |
| cloud libraries that work across providers. |
| Community feedback, from all types of developers at all levels, |
| will inform the priority of future APIs in Go Cloud. |
| |
| * How does it work? |
| |
| At the core of Go Cloud is a collection of generic APIs for portable cloud programming. |
| Let's look at an example of using blob storage. |
| You can use the generic type [[https://godoc.org/github.com/google/go-cloud/blob#Bucket][`*blob.Bucket`]] |
| to copy a file from a local disk to a cloud provider. |
| Let's start by opening an S3 bucket using the included [[https://godoc.org/github.com/google/go-cloud/blob/s3blob][s3blob package]]: |
| |
| // setupBucket opens an AWS bucket. |
| func setupBucket(ctx context.Context) (*blob.Bucket, error) { |
| // Obtain AWS credentials. |
| sess, err := session.NewSession(&aws.Config{ |
| Region: aws.String("us-east-2"), |
| }) |
| if err != nil { |
| return nil, err |
| } |
| // Open a handle to s3://go-cloud-bucket. |
| return s3blob.OpenBucket(ctx, sess, "go-cloud-bucket") |
| } |
| |
| Once a program has a `*blob.Bucket`, it can create a `*blob.Writer`, |
| which implements `io.Writer`. |
| From there, the program can use the `*blob.Writer` to write data to the bucket, |
| checking that `Close` does not report an error. |
| |
| ctx := context.Background() |
| b, err := setupBucket(ctx) |
| if err != nil { |
| log.Fatalf("Failed to open bucket: %v", err) |
| } |
| data, err := ioutil.ReadFile("gopher.png") |
| if err != nil { |
| log.Fatalf("Failed to read file: %v", err) |
| } |
| w, err := b.NewWriter(ctx, "gopher.png", nil) |
| if err != nil { |
| log.Fatalf("Failed to obtain writer: %v", err) |
| } |
| _, err = w.Write(data) |
| if err != nil { |
| log.Fatalf("Failed to write to bucket: %v", err) |
| } |
| if err := w.Close(); err != nil { |
| log.Fatalf("Failed to close: %v", err) |
| } |
| |
| Notice how the logic of using the bucket does not refer to AWS S3. |
| Go Cloud makes swapping out cloud storage a matter of changing the function |
| used to open the `*blob.Bucket`. |
| The application could instead use Google Cloud Storage by constructing a |
| `*blob.Bucket` using [[https://godoc.org/github.com/google/go-cloud/blob/gcsblob#OpenBucket][`gcsblob.OpenBucket`]] |
| without changing the code that copies the file: |
| |
| // setupBucket opens a GCS bucket. |
| func setupBucket(ctx context.Context) (*blob.Bucket, error) { |
| // Open GCS bucket. |
| creds, err := gcp.DefaultCredentials(ctx) |
| if err != nil { |
| return nil, err |
| } |
| c, err := gcp.NewHTTPClient(gcp.DefaultTransport(), gcp.CredentialsTokenSource(creds)) |
| if err != nil { |
| return nil, err |
| } |
| // Open a handle to gs://go-cloud-bucket. |
| return gcsblob.OpenBucket(ctx, "go-cloud-bucket", c) |
| } |
| |
| While different steps are needed to access buckets on different cloud providers, |
| the resulting type used by your application is the same: `*blob.Bucket`. |
| This isolates application code from cloud-specific code. |
| To increase interoperability with existing Go libraries, |
| Go Cloud leverages established interfaces like `io.Writer`, |
| `io.Reader`, and `*sql.DB`. |
| |
| The setup code needed to access cloud services tends to follow a pattern: |
| higher abstractions are constructed from more basic abstractions. |
| While you could write this code by hand, Go Cloud automates this with *Wire*, |
| a tool that generates cloud-specific setup code for you. |
| The [[https://github.com/google/go-cloud/tree/master/wire][Wire documentation]] |
| explains how to install and use the tool and the [[https://github.com/google/go-cloud/tree/master/samples/guestbook][Guestbook sample]] |
| shows Wire in action. |
| |
| * How can I get involved and learn more? |
| |
| To get started, we recommend following [[https://github.com/google/go-cloud/tree/master/samples/tutorial][the tutorial]] |
| and then trying to build an application yourself. |
| If you're already using AWS or GCP, you can try migrating parts of your |
| existing application to use Go Cloud. |
| If you're using a different cloud provider or an on-premise service, |
| you can extend Go Cloud to support it by implementing the driver interfaces |
| (like [[https://godoc.org/github.com/google/go-cloud/blob/driver#Bucket][`driver.Bucket`]]). |
| |
| We appreciate any and all input you have about your experience. |
| [[https://github.com/google/go-cloud][Go Cloud's]] development is conducted on GitHub. |
| We are looking forward to contributions, including pull requests. |
| [[https://github.com/google/go-cloud/issues/new][File an issue]] to tell |
| us what could be better or what future APIs the project should support. |
| For updates and discussion about the project, |
| join [[https://groups.google.com/forum/#!forum/go-cloud][the project's mailing list]]. |
| |
| The project requires contributors to sign the same Contributor License Agreement |
| as that of the Go project. |
| Read the [[https://github.com/google/go-cloud/blob/master/CONTRIBUTING.md][contribution guidelines]] for more details. |
| Please note, Go Cloud is covered by the Go [[https://github.com/google/go-cloud/blob/master/CODE_OF_CONDUCT.md][Code of Conduct]]. |
| |
| Thank you for taking the time to learn about Go Cloud. |
| We are excited to work with you to make Go the language of choice for developers |
| building portable cloud applications. |