From e29f0a2d66681846edd8bf86c15487f4ae1ce5d4 Mon Sep 17 00:00:00 2001 From: Evan Jones Date: Mon, 20 Jan 2020 10:55:01 -0500 Subject: [PATCH] Don't use debug base; Add pprof handlers Add pprof web handlers mostly for testing, not because it is needed. Dockerfile: Use the non-debug base image. Use user nobody since that is a bit more standard than user "nonroot" pprofweb-deploy.yaml: Example Kubernetes configuration --- Dockerfile | 5 ++-- pprofweb-deploy.yaml | 60 ++++++++++++++++++++++++++++++++++++++++++++ pprofweb.go | 8 ++++++ 3 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 pprofweb-deploy.yaml diff --git a/Dockerfile b/Dockerfile index 3fa0403..f2defb9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,15 +13,14 @@ RUN cd /tmp && \ for deb in *.deb; do dpkg --extract $deb /dpkg || exit 10; done -FROM gcr.io/distroless/base-debian10:debug AS run +FROM gcr.io/distroless/base-debian10:latest AS run COPY --from=builder /go/src/pprofweb/pprofweb /pprofweb COPY --from=deb_extractor /dpkg / # Configure dot plugins RUN ["dot", "-c"] - # Use a non-root user: slightly more secure (defense in depth) -USER nonroot +USER nobody WORKDIR / EXPOSE 8080 ENTRYPOINT ["/pprofweb"] diff --git a/pprofweb-deploy.yaml b/pprofweb-deploy.yaml new file mode 100644 index 0000000..39a0884 --- /dev/null +++ b/pprofweb-deploy.yaml @@ -0,0 +1,60 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: pprofweb + labels: + app: pprofweb +spec: + replicas: 1 + selector: + matchLabels: + app: pprofweb + template: + metadata: + labels: + app: pprofweb + annotations: + # allow scale down even though this uses an emptyDir for tmp + cluster-autoscaler.kubernetes.io/safe-to-evict: "true" + spec: + containers: + - name: pprofweb + image: us.gcr.io/gosignin-demo/pprofweb:20200120-1 + + resources: + requests: + memory: 64Mi + #ephemeral-storage: 256Mi + limits: + memory: 128Mi + #ephemeral-storage: 256Mi + + volumeMounts: + - mountPath: /tmp + name: tmp + + # defense in depth: read-only FS; run as nobody/nogroup + securityContext: + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 65534 + runAsGroup: 65534 + + volumes: + - name: tmp + emptyDir: + # TODO: replace with resource request/limit? + sizeLimit: 256Mi +--- +apiVersion: v1 +kind: Service +metadata: + name: pprofweb +spec: + selector: + app: pprofweb + ports: + - name: http + protocol: TCP + port: 8080 + targetPort: 8080 diff --git a/pprofweb.go b/pprofweb.go index 9fa1407..dd5e0e6 100644 --- a/pprofweb.go +++ b/pprofweb.go @@ -5,6 +5,7 @@ import ( "io" "log" "net/http" + "net/http/pprof" "os" "path" "strings" @@ -128,6 +129,13 @@ func main() { mux.HandleFunc(uploadPath, s.uploadHandlerErrHandler) mux.HandleFunc(pprofWebPath, s.servePprof) + // copied from net/http/pprof to avoid relying on the global http.DefaultServeMux + mux.HandleFunc("/debug/pprof/", pprof.Index) + mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline) + mux.HandleFunc("/debug/pprof/profile", pprof.Profile) + mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) + mux.HandleFunc("/debug/pprof/trace", pprof.Trace) + port := os.Getenv(portEnvVar) if port == "" { port = defaultPort