Deploying Go & Redis For Free With Pebl!
Tags: pebl, redis, cloud, devops
Published: 2023-07-22 03:44:55

In this guide we will be looking at combing a simple Go server with Redis, and deploying it all for free with [pebl](https://www.pebl.io/).

## Setup

  1. Make sure that you have [docker](https://www.docker.com/) and [Go](https://go.dev/) installed.
  2. Install the pebl cli by following the steps here: https://docs.pebl.io/setup
  3. Head over to [pebl.io](https://www.pebl.io) and create a free account

After creating your account, make sure to claim your free `*.pebl.rocks` subdomain (https://www.pebl.io/signup/claim), as we'll be using this for the rest of the series!

We will be using `hey.pebl.rocks` to make things concrete, so make sure to replace any instances of that with your own subdomain.

## Project Creation

Now it's time to create our project!

  1. Create a scratch folder to act as the root of the project. For this tutorial we'll be creating `pebl-tutorial`:

    ```
    $ mkdir ~/work/pebl-tutorial
    ```

  2. Then initialize the project by creating a Go module:

    ```
    $ cd ~/work/pebl-tutorial
    $ go mod init pebl-tutorial
    ```

  3. Download the pebl Go SDK by running `go get` inside the project folder:

    ```
    $ cd ~/work/pebl-tutorial
    $ go get github.com/peblcloud/go
    ```

## Adding Redis

Let's first install the [redis client](https://github.com/redis/go-redis) that we will use:

```
$ go get github.com/redis/go-redis/v9
```

Then create a `main.go` at the root of the project, and paste the following:

```go
package main

import (
    "net/http"
    "github.com/peblcloud/go"
    "github.com/redis/go-redis/v9"
)

func main() {
    redisConn, _ := pebl.Redis("redis-1")
    rdb := redis.NewClient(&redis.Options{
        Addr: redisConn.Addr,
    })

    svc := http.NewServeMux()
    svc.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
        count, _ := rdb.Get(context.Background(), "count").Result()
        res := fmt.Sprintf("current count: %s", count)
        w.Write([]byte(res))
    })

    svc.HandleFunc("/incr", func(w http.ResponseWriter, _ *http.Request) {
        rdb.Incr(context.Background(), "count")
    })

    pebl.Service(svc, "hey.pebl.rocks")
}
```

Pebl is a unique cloud platform, one where everything is driven with code. There are no configurations required! Here we are utilizing `pebl.Service` to create a service out of the standard `net/http` Go server, which will serve at `hey.pebl.rocks`. (Make sure to change this to your own subdomain that you claimed).

In a similar fashion, we get access to redis by using `pebl.Redis`. This method returns a struct that contains the connection information for the redis instance. This gets passed into the redis client.

And finally we have two endpoints configured on the server: `/incr` which increments the key `count`, and the root endpoint `/` that returns the current count.

## Running Locally

Let's try running this locally!

### Local Cluster

First we need to initialize the local cluster:

```
$ pebl up
 :: initializing new pebl cluster...
 :: done!
 :: run `pebl info` to see logs, endpoints, and other info about the running cluster!
$
```

Then execute `pebl info` to attach to the running cluster. This let's you see information about the running cluster, including any running workloads, logs, etc. The info screen should look something like this:

```

  pebl cluster version: 0.0.9
  ctrl-C or q to exit the info pane
  (exiting will not stop the cluster)


══ logs ═══════════════════════════════
```

And you can exit the info pane by pressing `q` or `Ctrl-C`.

### Running the Project

Now make sure you are at the root of the project, and execute `pebl run`:

```
$ cd ~/work/pebl-tutorial
$ pebl run
 :: building golang project...
 :: staging build at: /tmp/dir
 :: containerizing the build...
 :: starting container...
$
```

And now if you check your info pane, you should see two workloads, the endpoint and the redis instance.

```

  pebl cluster version: 0.0.9
  ctrl-C or q to exit the info pane
  (exiting will not stop the cluster)

      redis: redis-1 → localhost:55000
      endpoint: hey.pebl.rocks → localhost:55001

══ logs ════════════════════════════════
```

### Sending Requests

The info pane shows the locally bound port for the service. In our example it is bound to `:55001`, but your own case will differ. Send a test curl to the bound port:

```
$ curl localhost:55001/incr
$ curl localhost:55001/
current count: 1
$ curl localhost:55001/incr
$ curl localhost:55001/incr
$ curl localhost:55001/
current count: 3
$
```

## Making Changes

Now to make it a bit more interesting! Let's add an endpoint to `/reset`, which will set the `count` key back to zero.

```go
package main

import (
	"net/http"
	"github.com/peblcloud/go"
	"github.com/redis/go-redis/v9"
)

func main() {
    redisConn, _ := pebl.Redis("redis-1")
    rdb := redis.NewClient(&redis.Options{
        Addr: redisConn.Addr,
    })

    svc := http.NewServeMux()
    svc.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
        count, _ := rdb.Get(context.Background(), "count").Result()
        res := fmt.Sprintf("current count: %s", count)
        w.Write([]byte(res))
    })

    svc.HandleFunc("/incr", func(w http.ResponseWriter, _ *http.Request) {
        rdb.Incr(context.Background(), "count")
    })


    svc.HandleFunc("/reset", func(w http.ResponseWriter, _ *http.Request) {
        rdb.Set(context.Background(), "count", "0", 0)
    })

    pebl.Service(svc, "hey.pebl.rocks")
}
```

Notice the new `/reset` handler that's been attached to `svc`.

In other platforms making changes can be an involved process. But with pebl we just need to re-run the project! Pebl understands what it means to update an endpoint and will automatically handle switching the underlying server to the latest version without any interruption.

Run the project again with `pebl run` and then send requests to the `/reset` endpoint:

```
$ curl localhost:55001/
current count: 3
$ curl localhost:55001/reset
$ curl localhost:55001/
current count: 0
$
```

## Cloud Runtime

To really give you a sense of why the pebl approach is so powerful, we are going to deploy this project to the cloud. And we are going to do this without any changes, no extra configuration required!

Just use `pebl deploy` at the root of the project:

```
$ cd ~/work/pebl-tutorial
$ pebl deploy
```

Once deployed, you can visit the [pebl console](https://www.pebl.io/console) to see the running redis instance. You can also create a local tunnel to the remote redis instance in order to inspect or debug:

```
$ pebl tunnel redis
 :: tunnel established at: 127.0.0.1:50000
 :: use redis-cli to connect:
 :: redis-cli -p 50000
```

And as the output suggests, we can use `redis-cli` to the locally bound port to tunnel to your remote redis instance:

```
$ redis-cli -p 50000
127.0.0.1:50000> get counter
"1"
```

note that there's no need to create a "tunnel" to your local cluster. the info pane already shows the locally bound port which you can use to inspect the local redis!

## Next

You can continue to make changes to the Go server, perhaps adding authentication or caching.

For more tutorials, check out our [many guides](https://docs.pebl.io/category/guides). Pebl is currently also available in Python and Node.

For a reference to the Go SDK, check out https://pkg.go.dev/github.com/peblcloud/go

For an overview of all cloud functionality available with pebl, check out the [reference](https://docs.pebl.io/reference/SDK).