Categorygithub.com/arturhoo/k8slimiter
repositorypackage
0.1.0
Repository: https://github.com/arturhoo/k8slimiter.git
Documentation: pkg.go.dev

# README

k8slimiter

Rate limits for Pods, Deployments and StatefulSets through Validating Webhooks in Kubernetes

For context, please refer to: Rate limiting Kubernetes pod creation with dynamic admission control

Local Development

Generate local certs and an empty config file:

$ mkcert -cert-file ./certs/tls.crt -key-file ./certs/tls.key localhost
$ export CONFIG_PATH=/tmp/k8slimiter-config.yaml
$ touch $CONFIG_PATH

Run the server:

$ TLS_ENABLED=true go run .

Test the server:

$ xh https://localhost:8443/healthz
HTTP/2.0 200 OK
content-length: 15
content-type: application/json; charset=utf-8
date: Sun, 22 Oct 2023 09:05:35 GMT

{
    "status": "ok"
}

Testing Locally with Kind

Setup

Create a cluster:

$ kind create cluster

Build and load the image:

$ KO_DOCKER_REPO=kind.local ko build -B

Install cert-manager in the cluster:

$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.15.1/cert-manager.yaml

Finally, install k8slimiter:

$ kubectl apply -f test/k8slimiter-kind.yaml

Port-forward the service locally:

$ kubectl -n k8slimiter port-forward service/k8slimiter-service 8443:https

Test the server (note the --verify=no flag, since we don't have the cluster CA installed locally):

$ xh --verify=no https://localhost:8443/healthz
HTTP/2.0 200 OK
content-length: 15
content-type: application/json; charset=utf-8
date: Sun, 22 Oct 2023 09:09:19 GMT

{
    "status": "ok"
}

Rate limit test

The rate limit is set to 1 pod per 10 seconds. To test this, try scheduling more than one pod in a short period of time:

$ kubectl run "tmp-pod-$(date +%s)" --restart Never --image alpine -- sleep 1
pod/tmp-pod-1698005111 created
$ kubectl run "tmp-pod-$(date +%s)" --restart Never --image alpine -- sleep 1
Error from server: admission webhook "k8slimiter-pod-creation.k8slimiter.svc" denied the request: rate limit exceeded

For testing deployments or statefulsets:

$ kubectl create deployment "tmp-deploy-$(date +%s)" --image=nginx
$ NAME="tmp-sts-$(date +%s)"; echo '{"apiVersion":"apps/v1","kind":"StatefulSet","metadata":{"name":"'$NAME'"},"spec":{"serviceName":"'$NAME'","replicas":1,"selector":{"matchLabels":{"app":"'$NAME'"}},"template":{"metadata":{"labels":{"app":"'$NAME'"}},"spec":{"containers":[{"name":"nginx","image":"nginx"}]}}}}' | kubectl apply -f -