As many know, Go is a designed for performance with an emphasis on memory management and garbage collection. When used within cgroups with Kubernetes and Red Hat OpenShift Go maximizes for the available memory on the node and the available processors. This approach, as noted by Uber’s automaxprocs, a shared system can see slightly degraded performance when allocated CPUs are not limited to the actually available CPUs (e.g., a prescribed limit).
Using environment
variables, Go lets a user control Memory limits and processor limits.
GOMEMLIMIT
limits the Go heap and all other runtime memoryruntime/debug.SetMemoryLimit
GOMAXPROCS
limits the number of operating system threads that can execute user-level Go code simultaneously.
There is an opensource go packages to control GOMAXPROCS
automatically when used with cgroups
called automaxproces.
In OpenShift/Kubernetes, there is a concept of spec.containers[].resources.limits
for cpus and memory, as described in the article Resource Management for Pods and Containers.
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: myimage
resources:
limits:
memory: "128Mi"
cpu: 2
To facilitate sharing these details to a container Kubernetes provides the downwardAPI. The downwardAPI provides the details as an environment variableor a file.
To see how this works in combination:
- Create a yaml test.yaml with
resources.limits
andenv.valueFrom.fieldRef.fieldPath
set to the GOMEMLIMIT and GOMAXPROCS value you want.
kind: Namespace
apiVersion: v1
metadata:
name: demo
---
apiVersion: v1
kind: Pod
metadata:
name: dapi-go-limits
namespace: demo
spec:
containers:
- name: test-container
image: registry.access.redhat.com/ubi8/pause
resources:
limits:
memory: 128Mi
cpu: "2"
command:
- sh
- '-c'
args:
- >-
while true; do echo -en '\n'; printenv GOMEMLIMIT; printenv GOMAXPROCS
sleep 10; done;
env:
- name: GOMEMLIMIT
valueFrom:
resourceFieldRef:
containerName: test-container
resource: limits.memory
- name: GOMAXPROCS
valueFrom:
resourceFieldRef:
containerName: test-container
resource: limits.cpu
restartPolicy: Never
-
Apply the file to the
oc apply -f test.yaml
-
Check the logs file
$ oc -n demo logs pod/dapi-go-limits
134217728
2
- Delete the pod when you are done with the demonstration
$ oc -n demo delete pod/dapi-go-limits
pod "dapi-go-limits" deleted
There is a clear / easy way to control go runtime configuration.
Reference
- https://kubernetes.io/docs/tasks/inject-data-application/downward-api-volume-expose-pod-information/
- https://stackoverflow.com/questions/17853831/what-is-the-gomaxprocs-default-value
- https://github.com/uber-go/automaxprocs#performance
- https://kubernetes.io/docs/tasks/inject-data-application/environment-variable-expose-pod-information/