← Back to go-kit/kit

How to Deploy & Use go-kit/kit

Go kit: A Standard Library for Microservices

This guide provides comprehensive instructions for deploying and using Go kit, a programming toolkit for building microservices in Go.

Prerequisites

Before you begin, ensure you have the following installed:

Installation

Go kit is designed to be consumed as a library within your Go projects. There is no standalone installation for Go kit itself. You integrate it into your Go module.

  1. Create a new Go module (if you don't have one):

    mkdir my-microservice
    cd my-microservice
    go mod init my-microservice
    
  2. Add Go kit as a dependency:

    go get github.com/go-kit/kit
    

    This command will download the Go kit library and add it to your go.mod file.

Configuration

Go kit itself doesn't require global configuration files or environment variables. Configuration is typically handled within your application code when you instantiate and configure Go kit components (e.g., transports, metrics, logging).

However, specific components might require external configuration:

  • Metrics Backends:

    • DogStatsD/InfluxStatsD: These typically require the address of the DogStatsD/InfluxStatsD server (e.g., localhost:8125). This is usually passed during the SendLoop or WriteLoop setup.
    • CloudWatch: Requires AWS credentials and region configuration, typically managed via environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION), AWS shared credential files, or IAM roles. The namespace for metrics is configured when creating the CloudWatch client.
  • Transports:

    • AMQP: Requires connection details for the RabbitMQ server (e.g., amqp://guest:guest@localhost:5672/).
    • HTTP: HTTP servers listen on a specific port and address, configured within your application.

Example (CloudWatch Metrics with Environment Variables):

export AWS_ACCESS_KEY_ID="YOUR_ACCESS_KEY"
export AWS_SECRET_ACCESS_KEY="YOUR_SECRET_KEY"
export AWS_REGION="us-east-1"

Build & Run

Since Go kit is a library, you build and run your application that uses Go kit.

Development Build and Run

  1. Write your Go kit application: Create a Go file (e.g., main.go) that imports and uses Go kit components. A minimal example might look like:

    package main
    
    import (
    	"context"
    	"fmt"
    	"net/http"
    
    	"github.com/go-kit/kit/endpoint"
    	httptransport "github.com/go-kit/kit/transport/http"
    )
    
    // Service definition
    type MyService interface {
    	Uppercase(context.Context, string) (string, error)
    }
    
    type myService struct{}
    
    func (myService) Uppercase(_ context.Context, s string) (string, error) {
    	return fmt.Sprintf("%s!", s), nil
    }
    
    // Endpoints
    func makeUppercaseEndpoint(svc MyService) endpoint.Endpoint {
    	return func(_ context.Context, request interface{}) (interface{}, error) {
    		req := request.(uppercaseRequest)
    		s, err := svc.Uppercase(context.Background(), req.S)
    		if err != nil {
    			return uppercaseResponse{s, err.Error()}, nil
    		}
    		return uppercaseResponse{s, ""}, nil
    	}
    }
    
    // Request/Response types
    type uppercaseRequest struct {
    	S string `json:"s"`
    }
    
    type uppercaseResponse struct {
    	V   string `json:"v"`
    	Err string `json:"err,omitempty"`
    }
    
    func main() {
    	svc := myService{}
    
    	uppercaseHandler := httptransport.NewServer(
    		makeUppercaseEndpoint(svc),
    		func(_ context.Context, r *http.Request) (interface{}, error) {
    			var req uppercaseRequest
    			if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
    				return nil, err
    			}
    			return req, nil
    		},
    		func(_ context.Context, w http.ResponseWriter, response interface{}) error {
    			return json.NewEncoder(w).Encode(response)
    		},
    	)
    
    	http.Handle("/uppercase", uppercaseHandler)
    	fmt.Println("Listening on :8080")
    	http.ListenAndServe(":8080", nil)
    }
    
  2. Run your application:

    go run main.go
    

    Your service will typically start listening on the configured port (e.g., http://localhost:8080/uppercase).

Production Build

For production, you'll want to build a statically linked binary.

  1. Build the binary:

    go build -o my-microservice-app .
    

    This creates an executable named my-microservice-app in the current directory.

  2. Run the binary:

    ./my-microservice-app
    

Deployment

Go applications, including those built with Go kit, compile into single static binaries, making them highly portable and easy to deploy.

Suggested Deployment Platforms:

  • Containerization (Docker, Kubernetes):

    1. Create a Dockerfile:
      # Use a minimal base image
      FROM alpine/git as builder
      
      # Set environment variables for Go build
      ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64
      
      # Install Go (if not using a Go base image)
      RUN apk add --no-cache go
      
      # Set the working directory
      WORKDIR /app
      
      # Copy go.mod and go.sum first to leverage Docker cache
      COPY go.mod .
      COPY go.sum .
      
      # Download dependencies
      RUN go mod download
      
      # Copy the rest of the application source
      COPY . .
      
      # Build the application
      RUN go build -o /my-microservice-app .
      
      # Use a scratch image for the final, minimal image
      FROM scratch
      
      # Copy the built binary from the builder stage
      COPY --from=builder /my-microservice-app /my-microservice-app
      
      # Expose the port your service listens on
      EXPOSE 8080
      
      # Run the application
      CMD ["/my-microservice-app"]
      
    2. Build the Docker image:
      docker build -t my-microservice:latest .
      
    3. Run the Docker container:
      docker run -p 8080:8080 my-microservice:latest
      
    4. Deploy to Kubernetes: Create Kubernetes Deployment and Service YAMLs referencing your Docker image.
  • Virtual Machines (AWS EC2, Google Cloud Compute Engine, Azure VMs):

    1. Build the binary for the target OS/architecture (e.g., GOOS=linux GOARCH=amd64 go build -o my-microservice-app .).
    2. Copy the binary to your VM (e.g., using scp).
    3. Run the binary directly, optionally using a process manager like systemd or supervisord to keep it running and manage logs.
  • Serverless Platforms (AWS Lambda, Google Cloud Functions, Azure Functions): While Go kit is primarily designed for long-running microservices, core components like endpoint and transport can be adapted for serverless functions, especially for HTTP triggers. You would typically wrap your Go kit endpoint in a function handler compatible with the serverless platform's runtime.

Troubleshooting

  • "go: command not found": Ensure Go is installed and its bin directory is in your system's PATH.
  • "unrecognized import path": Check your go.mod file and ensure go get github.com/go-kit/kit was successful. If working in an existing module, run go mod tidy.
  • Service not responding/connection refused:
    • Verify your application is running and listening on the expected port.
    • Check firewall rules on the host or in your cloud provider's security groups.
    • Ensure the correct port is exposed in Docker or Kubernetes configurations.
  • Metrics not appearing in backend (DogStatsD, CloudWatch, etc.):
    • DogStatsD/InfluxStatsD:
      • Confirm the DogStatsD/InfluxStatsD agent is running and accessible from your service.
      • Check the agent's logs for any errors or dropped metrics.
      • Verify the address provided to SendLoop is correct.
    • CloudWatch:
      • Check your AWS credentials and IAM permissions for cloudwatch:PutMetricData.
      • Ensure the namespace configured in your Go kit CloudWatch client matches what you're looking for in the AWS console.
      • Review logs from your Go kit application for any errors reported by the CloudWatch client.
  • Endpoint errors (e.g., JSON decoding issues):
    • Enable logging in your Go kit transport components (e.g., httptransport.ServerErrorLogger or httptransport.ServerErrorHandler) to get more detailed error messages.
    • Verify your request/response structs match the expected JSON (or other serialization format).
    • Use a tool like curl or Postman to test your endpoints with valid payloads.
  • Go kit version conflicts: If you encounter issues with dependencies, try go clean -modcache followed by go mod tidy and go build.