Sidecar pattern with Go, SQS and k8s
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
The diagram shows there are two containers: sqsclient
and sqsservice
.
sqsclient
is 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
sqsclient
polls 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"}
sqsservice
polls 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:
- 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.
- 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.
- Create unit test for Terraform
- Create integration tests
- Create a UI to better visualize the process