Sidecar pattern with Go, SQS and k8s

Alvin Lucillo
Nullify
Published in
3 min readSep 17, 2023

One of the topics that piqued my interest when I was studying for AWS Certified Developer Associate is the need to periodically look for queue messages and process them. There are several approaches to address that need, but I focused on the sidecar pattern. This article describes the SQS Processor, a small project I created to demonstrate how a sidecar container, a decoupled process, is used by another container. The project uses Go and gRPC to create the backend services, EKS to orchestrate the containers, and Terraform to manage some AWS resources.

In a nutshell, the sidecar pattern decouples functionalities from a container for reasons like scalability and optimization. The decoupled processes are now separate containers that can be used by other containers. For example, sqsservice container of the SQS Processor project provides SQS-related services. This way, sqsclient only focuses on the business processes.

GitHub Repo: https://github.com/alvinlucillo/sqsprocessor

SQS Processor deployed in AWS

The diagram shows there are two containers: sqsclient and sqsservice.

  • sqsclientis an example of a container that implements the business logic and needs SQS messages. In the project, it continually checks with the sidecar container, sqsservice, any available messages. Once it receives the messages, it deletes them using another service from the sidecar container.
  • Both containers are in a single pod
  • EKS cluster is in a VPC, so sqsservice accesses SQS via IGW (Internet Gateway)

The process in action 🚀

Before we look into the implementation, let’s see the process in action, so you’ll have a picture of what goes on

1. Stream the logs for the two containers:
- kubectl logs pod/pod_name -c sqsservice -f
- kubectl logs pod/pod_name -c sqsclient -f

2. While there’s no message in the queue, you’ll see the following

sqsclientpolls the sqsservice continuously

{"level":"info","caller":"/app/cmd/client/main.go:16","time":"2023-09-17T10:12:58Z","message":"Client starting"}
{"level":"info","package":"client","function":"Run","time":"2023-09-17T10:12:58Z","message":"Polling count: 1"}{"level":"info","package":"client","function":"Run","time":"2023-09-17T10:13:03Z","message":"Received 0 message(s)"}
{"level":"info","package":"client","function":"Run","time":"2023-09-17T10:13:08Z","message":"Polling count: 2"}

sqsservicepolls SQS continuously

{"level":"info","caller":"/app/cmd/sqsservice/main.go:18","time":"2023-09-17T10:12:55Z","message":"Server starting"}
{"level":"debug","function":"ReceiveMessage","time":"2023-09-17T10:12:58Z","message":"Received input: visibility_timeout:5 wait_time:5 maximum_number_of_messages:5"}
{"level":"debug","function":"ReceiveMessage","time":"2023-09-17T10:13:03Z","message":"Returned output: []"}

3. Create an SQS message (replace the region and account number)

aws sqs send-message — queue-url https://sqs.us-east-1.amazonaws.com/your-aws_account_no/sqs-sample-1 — message-body “hello”

4. sqsservice will pick up the new message

 {"level":"debug","function":"ReceiveMessage","time":"2023-09-17T10:15:14Z","message":"Returned output: [messageID:\"AQEBo4QCIVXuMaMZew==\"  messageBody:\"hello\"]"}

5. sqsclient will receive the message from sqsservice then delete it

{"level":"info","package":"client","function":"Run","time":"2023-09-17T10:15:14Z","message":"Received 1 message(s)"}
{"level":"info","package":"client","function":"Run","time":"2023-09-17T10:15:14Z","message":"Deleting message messageID:\"AQEBo4QCIVXuMaMZew==\" messageBody:\"hello\""}
{"level":"info","package":"client","function":"Run","time":"2023-09-17T10:15:14Z","message":"Message deleted successfully: AQEBo4QCIVXuMaMZew==\"}

Setting up your environment🛠️

The project repo contains steps on how to set up your local and cloud environment. You may visit the readme page here. I update the repo more frequently, so it’s better to refer to the steps there than this article to ensure you’re referring to the updated steps. But what can you expect from the setup? A glimpse into what it entails:

  • Deploying containers in local and EKS clusters
  • AWS configuration for EKS
  • Terraform initialization for SQS and IAM resources

What could be done better 🤔

There are things I’ll do in the future to improve this project:

  1. Use AWS Encryption SDK and SSM Parameter store for k8s secrets. In the project, secrets are created based on the environment variable values. Those secrets are the access and secret keys.
  2. Include VPC and EKS in the resources managed by Terraform. I hadn’t figured it out yet fully at the time of writing. Though I tried some things, those are still clunky.
  3. Create unit test for Terraform
  4. Create integration tests
  5. Create a UI to better visualize the process

--

--

Alvin Lucillo
Nullify
Editor for

Software engineer, writer, self-taught pianist, and a lifelong learner