2

I’ve written an API in Golang, and the production image is built using a multistage Dockerx build. The output of the Dockerx build is an image that is FROM scratch, and the compiled Go executable inside of it is statically compiled (my understanding is that it wouldn’t work with FROM scratch if it were dynamically linked).

As a result of the multistage build being FROM scratch, the output image is incredibly small (2-4MB), the Snyk analysis also finds no security issues with the image (I’m assuming since the attack surface of the image is so small).

The issue is that the image doesn’t use gzip to compress the responses - so my responses are theoretically larger than they need to be. If I were working with another language, I’d typically be using Nginx within the image to act as a reverse proxy - so I’d just configure it to enable gzip (something like this), but in this case, adding in Nginx would result in a larger image (with more vulnerabilities).

I’ve thought about it, and my other two options are:

  • Add compression directly into the Go API by using the gzip package. This would involve writing code to handle the compression based on response type, and adding in testing for the functionality. This is my least favourite option because I would eventually have to create a bespoke solution.
  • Add Istio to my cluster, inject it as a sidecar into the pods in my Go API service, then set up an Istio compression filter that will gzip any responses to requests made through the ingress controller (nginx ingress) - this would theoretically allow me to control the compression depending on the source of the request, and I wouldn’t have to alter/redeploy my image in order for any gzip config changes to take effect. So far this is my favourite option.

Are there any other factors/options to consider here?

EDIT: The reason I was leaning towards adding it at the service mesh (Istio) level as opposed to the Ingress layer is because there's a possibility of switching/using multiple ingress controllers down the line (which would mean multiple disparate gzip implementations). Also as I said "[Istio] would theoretically allow me to control the compression depending on the source of the request" - this would theoretically allow me to add compression for service-to-service requests later on.

ChardeeMacdennis
  • 175
  • 1
  • 10
  • This is what an [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) is for. This is not the job of your API. – tadman Apr 15 '21 at 21:42
  • Updated the question to add more info. – ChardeeMacdennis Apr 15 '21 at 22:07
  • "mean multiple disparate gzip implementations" is a problem, how? These things are tiny. What are the costs here of not compressing? How much data are you shipping? Where is it going? It's far from clear what problem you're trying to solve here other than fretting about image sizes or data transmission costs, and even then, without quantifying why this is a problem it's anyone's guess as to what the solution is or might be. – tadman Apr 15 '21 at 22:12
  • Surely there's a Go zlib library you can just include and call this done if that's all you're concerned about. – tadman Apr 15 '21 at 22:14
  • The problem with managing multiple separate implementations is that rolling out a change across every separate implementation at some point becomes untenable. – ChardeeMacdennis Apr 15 '21 at 22:34
  • I don't want to implement Zlib directly in the API because it would make handling compression within apps the de facto standard within my cluster - so if it came to altering Zlib configuration, it could mean changes across multiple apps. As you said in your initial comment, "This is not the job of [my] API". It's the same reason that I use a service mesh for circuit breaking - implementing this functionality directly in apps would eventually become untenable. If we implement zlib on the ingress, then move to a multi-ingress model, zlib would have to be configured in multiple places. – ChardeeMacdennis Apr 15 '21 at 22:40
  • I'm trying to untangle this explanation as it seems contradictory. You can put it in your API, or you can put it in your Ingress. Both have advantages and drawbacks, but I'm not sure "configuration" is one. How often do you tinker with zlib settings? Usually you just set it to max compression and forget about it. – tadman Apr 15 '21 at 22:53

0 Answers0