/gse

small http services to help debugging containers environnements

Primary LanguageGoGNU General Public License v3.0GPL-3.0

GSE: "Go Show Env" micro HTTP service

1. Introduction

GSE is a small standalone web app designed to help debugging the environment of orchestred containers, through a very small go app.

It can be be easly packaged into a < 3 MB docker image that will run with less than 20 Mo of ram, making it easly to deploy. See the image on dockerhub

It offers 4 endpoints
  • displays its env and the details of the http request it received

    • usefull to understand what env and request your containers receive

  • display its version in a single line of text

  • healthcheck that can also be turned in ok or ko state through a simple http call

    • usefull to play with your container orchestrator (kubernetes, nomad…​) routing system.

  • logger tonoutput what you want on the log output

    • usefull to test your that log gathering system

⚠️
This was my first attempt as golang. Quick’n Dirty, but this tool has been proven usefull during our journey with Nomad or Kube…​

2. Endpoints

GSE offers 4 end points

2.1. Display environment

  • /gse endpoint can be queried through any HTTP method (GET, PUT, …​). It will answer an HTTP 200 status, with an HTML content displaying information about the HTTP request received

    • headers

    • hostname

    • path

    • POST/PUT/…​ parameters

  • note that this endpoint will write a one line log to stdout

  • /gse can be changed to another path via the GSE_BASEPATH pararameter. Other endpoints (version, healthcheck) will inherit this parameters.

2.2. Display version & stamp

  • /gse/version endpoint can be queried through any HTTP method (GET, PUT, …​). It will answer an HTTP 200 status,with a single text line content made of program version and its stamp (if one has been specified, default stamp being empty)

  • the "stamp" allows us to test rolling, blue/green, or canary update with our container orchestrator: the same docker image (=same version) can be run with a given stamp (see GSE_STAMP bellow) given as parameter by the orchestrator, so we can differenciate to deployments, exemple:

    • with no stamp, the answer will be 3.0

    • with GSE_STAMP="A", the answer will be 3.0A

2.3. Healthcheck

  • /gse/health is a endpoint to be used as healthcheck through an HTTP GET query. Answer will be

    • when healtcheck is on: HTTP 200 status, content will be the text string I’m alive

    • when healthcheck is off: HTTP 503 status, content will be the text string I’m sick

    • no log will be written to stdout

  • healthcheck can be switched on/off (flip/flop) with an access with HTTP POST or PUT methods:

2.4. logger

⚠️
This endpoint is not activated by default since input sanitization is crappy. Use at your own risk
  • /gse/logger is an HTTP POST endpoint that will write to stdout the payload of the POST request

  • answer: HTTP 200 status, content will be the text string data ingested.

3. Parameters

GSE accepts some parameters, either through command line flags or env vars.

Table 1. GSE parameters
parameter env var name cli name type default value

path in the url (note: impacts all endpoints)

GSE_BASEPATH

-basepath

string

/gse

tcp port to listen to

GSE_PORT

-port

int

28657

stamp added to version endpoint

GSE_STAMP

-stamp

string

empty

set healthcheck answer to HTTP 200 or HTTP 503

GSE_HEALTHCHECK

-healthcheck

boolean

true

activate logger endpoint

GSE_LOGGER

-logger

boolean

false

We also have the standard -h cli arg
$ ./gse -h

Since we use https://github.com/namsral/flag to parse arguments, they can be fed either through command line or env vars.

🔥
flag parsing when value is /…​ seems to be bugged on windows. You cannot change the basepath on gse if you run on windows.

4. Compile

Goal is to create a small but standalone binary to allow us to build a small container image.

Build with static linking so we can Dockerfile FROM scratch
$ CGO_ENABLED=0 GOOS=linux go build -a -tags netgo -ldflags "-s -w" .

The resulting binary should be < 9 Mb.

💡
If that’s too big, you can use upx to reduce file size to ~ 2.5 Mb
Run
$ ./gse

point your web browser to http://localhost:28657/gse

5. Create docker image

the following is a multi stage docker build. first we compile and compress executable in the builder stage, then we create an image `FROM scratch'

Dockerfile
FROM devalias/upx:devel AS upx

FROM golang AS builder
COPY --from=upx /usr/bin/upx /usr/bin/upx
WORKDIR /go/src/github.com/DBuret/gse
RUN go get -d -v github.com/namsral/flag
COPY gse.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -tags netgo -ldflags "-s -w" .
RUN  /usr/bin/upx --brute gse

FROM scratch
LABEL version="4.1"
LABEL link="https://github.com/DBuret/gse"
LABEL description="Go Show Env - micro HTTP service to help understanding container orchestrators environment"
WORKDIR /
COPY --from=builder /go/src/github.com/DBuret/gse .
ADD template.html .

CMD ["/gse"]
Build image
$ sudo docker build -t gse .

6. Run locally with docker

6.1. Using default config

$ sudo docker run -p 28657:28657 gse

point your web browser to http://localhost:28657/gse

6.2. using parameters

$ sudo docker run -e GSE_BASEPATH=/foo -e GSE_PORT=2000 -e GSE_STAMP=A -e GSE_HEALTHCHECK=false -e GSE_LOGGER=true -p 2000:2000 gse
Set healthcheck endpoint to "ok"
$ curl -X PUT http://localhost:2000/foo/health

6.3. RAM usage

⚠️
gse will eat around 14 Mb of RAM (even if your file has been shrinked by upx, upon execution it will be uncompressed to RAM. Using upx just saves disk space and download time). When setting ressources quota to a gse container, allow 20 Mb of RAM to the container and you will be safe.
$ ps -ef |grep gse
root      20034  17983  0 20:20 pts/0    00:00:00 sudo docker run -e GSE_BASEPATH=/foo -e GSE_PORT=2000 -e GSE_STAMP=A -e GSE_HEALTHCHECK=false -e GSE_LOGGER=true -p 2000:2000 gse
root      20035  20034  0 20:20 pts/0    00:00:00 /usr/bin/docker-current run -e GSE_BASEPATH=/foo -e GSE_PORT=2000 -e GSE_STAMP=A -e GSE_HEALTHCHECK=false -e GSE_LOGGER=true -p 2000:2000 gse
root      20068  20055  0 20:20 ?        00:00:00 /gse
$ sudo pmap -x 20068
20068:   /gse
Address           Kbytes     RSS   Dirty Mode  Mapping
0000000000400000    3324    3324    3324 r-x--   [ anon ]
000000000073f000    3740    3740    3740 r----   [ anon ]
0000000000ae6000     372     280     280 rw---   [ anon ]
000000c000000000   65536    2048    2048 rw---   [ anon ]
00007f3397dc5000   35524    4216    4216 rw---   [ anon ]
00007fffa460b000     132      32      32 rw---   [ stack ]
00007fffa468f000       8       4       0 r-x--   [ anon ]
ffffffffff600000       4       0       0 r-x--   [ anon ]
---------------- ------- ------- -------
total kB          108640   13644   13640

7. screenshots

7.1. main endpoint

ss1