One of the most underrated features of Kubernetes is namespaces. In the market, instead of using this feature, people are still stuck with having different clusters for their environments. This talk will try to break this approach, and will introduce how we end up using ephemeral namespaces within our CI/CD pipeline. It will cover the architecture of our system for running the user acceptance tests on isolated ephemeral namespaces with every bits and pieces running within pods. While doing this, we will set up our CI/CD pipeline on top of TravisCI, GoCD, and Selenium that is controlled by Nightwatch.js.
Sched Link: http://sched.co/6Bcb
7. Resource ControlResource Control
apiVersion: v1
kind: ResourceQuota
metadata:
name: quota
spec:
- hard:
memory: "1Gi"
cpu: 20
pods: 15
services: 5
replicationcontrollers: 10
resourcequotas: 1
Cluster:
32 GB RAM, and 16 cores
Team A:
20 GB RAM, and 10 cores
Team B:
10 GB RAM, and 4 cores
8. How to Partition?How to Partition?
Environment based partitioningEnvironment based partitioning
qa, stage, production...
System / team based partitioningSystem / team based partitioning
kube-system, devops, bots
Project based partitioningProject based partitioning
example.com, better-example.com
9. A Day of a CI/CD PipelineA Day of a CI/CD Pipeline
Provision separate machines for every build
Run your tests on isolated clusters
When all tests are successful tear down the cluster
If it fails keep the cluster up for a while for debugging
Ephemeral Namespaces!Ephemeral Namespaces!
namespaces
namespaces
namespace
10. Ephemeral Namespaces AreEphemeral Namespaces Are
Isolated environments that are running different versions
of services on top of it
The environments where we run our integrations/e2e tests,
and gets dumped when we get the end results
11. Namespaces with Benefits!Namespaces with Benefits!
Time effective provisioning
Efficient resource utilization
In a CI/CD pipeline, namespaces provide:In a CI/CD pipeline, namespaces provide:
14. Deployment ProcessDeployment Process
1. Run your unit tests
2. Build Docker Image
3. Deploy to sandbox
4. Provision services that you will run your
tests against
5. Run your integration/e2e tests
6. Delete namespace
7. Deploy updated services to staging/prod
Happy Path!
16. Pods From Different NamespacesPods From Different Namespaces
➜ kubectl get po --namespace=e2e-1
NAME READY STATUS RESTARTS AGE
mongo-oij3f 1/1 Running 0 10m
nginx-44k6p 1/1 Running 0 10m
selenium-9bcfc 1/1 Running 0 10m
todo-service-phgrb 1/1 Running 0 10m
todo-service-rbrjl 1/1 Running 0 10m
➜ kubectl get po --namespace=e2e-2
NAME READY STATUS RESTARTS AGE
mongo-p6g8c 1/1 Running 0 5m
nginx-mgdzz 1/1 Running 0 5m
selenium-9l81p 1/1 Running 0 5m
todo-service-mt9gh 1/1 Running 0 5m
todo-service-yxo9v 1/1 Running 0 5m
➜ kubectl get po --namespace=e2e-3
NAME READY STATUS RESTARTS AGE
mongo-llm3x 1/1 Running 0 1m
nginx-vvov6 1/1 Running 0 1m
nightwatch 1/1 Running 0 34s
selenium-g2g1i 1/1 Running 0 1m
todo-service-1k8vc 1/1 Running 0 1m
todo-service-ddfjw 1/1 Running 0 1m
17. Adding E2E Components as PodsAdding E2E Components as Pods
Selenium server
Nightwatch.js scripts
18. All Tests PassedAll Tests Passed ✓✓
$ kubectl delete namespace e2e-10
It will dump every Kubernetes component
within that namespace!
19. Test Gets FailedTest Gets Failed 😞
Find a way to connect to the Selenium Server for
debugging
Expose VNC Port 5900
kubectl port-forward selenium :5900 --namespace=e2e-1
23. Running Every Piece in PodsRunning Every Piece in Pods
Nightwatch scripts
kubectl run -i -tty nightwatch --image=canthefason/e2e-tests:$E2E_IMAGE_TAG
--restart=Never --namespace=e2e-$GO_PIPELINE_LABEL
state=$(kubectl get -o template po nightwatch $kubeargs
--template={{.status.phase}})
while [ "$state" == "Running" ]; do
sleep 5
echo "waiting for the state"
state=$(kubectl get -o template po nightwatch $kubeargs
--template={{.status.phase}})
done
echo "State: $state"
if [ "$state" == "Failed" ]; then
exit 1
fi
25. Health CheckersHealth Checkers
Text
curl -k --retry 10 --retry-delay 5 -v
https://$KUBE_HOST/api/v1/proxy/namespaces/sandbox/services/todo/ping
curl -k --silent --output /dev/stderr --write-out "%{http_code}" -v
https://$KUBE_HOST/api/v1/proxy/namespaces/sandbox/services/todo/ping
if [ "$STATUSCODE" -ne "200" ]; then
if [ "$rcExist" != "ReplicationController" ]; then
kubectl delete -f scripts/rc.yml $kubeargs
fi
exit 1
fi
26. Future WorkFuture Work
Scale down the pods when the namespace is idle
Automatically delete namespaces that are older
than certain age
Build a Selenium Grid infrastructure and utilize
Selenium Agents among the namespaces
27. TakeawaysTakeaways
Never ever expose your Apiserver 8080 port!
Think twice before defining your ssh keys as
secrets!
Make sure that you properly setup kubelet
garbage collectors
--maximum-dead-containers=100
--maximum-dead-containers-per-container=2
--minimum-container-ttl-duration=1m0s