Deploying Node.js Applications with Confidence using Kubernetes

Deploying Node.js Applications with Confidence using Kubernetes

Deploying Node.js applications just got a lot easier using Kubernetes. To be successful with Kubernetes and Node.js, we have to make sure our applications fit into Kubernetes’s model. This talk will help you understand how you can prepare your software to be deployed and operated in Kubernetes.


Gergely Nemeth

July 25, 2018


  1. Deploying Node.js Applications with Confidence using Kubernetes Gergely Nemeth | | @nthgergo
  2. Who am I? • Gergely Nemeth • Engineering Manager @

    Uber (Web Platform, and I am hiring) • Software Developer • Coffee Lover ☕ ◦
  3. Deploying Node.js Applications with Confidence using Kubernetes Gergely Nemeth | | @nthgergo
  4. Agenda 1. How Kubernetes is architected - (very briefly) 2.

    Running Kubernetes 3. Containerizing Node.js Applications 4. Handle Application Lifecycle Events 5. Packaging Applications 6. Securing the Kubernetes Cluster 7. Resource Constraints 8. Disaster Recovery
  5. Kubernetes architecture 101

  6. Kubernetes architecture • At least one master • Multiple worker

  7. Master • Provides the cluster’s control plane • Makes the

    cluster’s current state match the desired state • Makes global decisions about the cluster (for example, scheduling)
  8. Nodes • Node components run on every node, maintaining running

    pods and providing the Kubernetes runtime environment.
  9. Running Kubernetes

  10. Just use GCP's Kubernetes Engine, if you can.

  11. Or if you feel a bit more adventurous, AWS.

  12. Running Kubernetes • Follow Kelsey Hightower's Kubernetes The Hard Way

    to understand how each component work together: ◦ containerd Container Runtime ◦ gVisor ◦ CNI Container Networking ◦ etcd
  13. Running Kubernetes Locally • With the help of ◦ Minikube

    - ◦ Skaffold -
  14. apiVersion: apps/v1 kind: Deployment metadata: name: localstack spec: selector: matchLabels:

    app: localstack template: metadata: labels: app: localstack spec: containers: - name: localstack image: localstack/localstack:0.8.6 ports: # exposing dynamodb - containerPort: 31001 env: - name: SERVICES value: "dynamodb:31001" - name: PORT_WEB_UI value: "32000"
  15. apiVersion: v1 kind: Service metadata: name: localstack spec: # selector

    tells Kubernetes what Deployment this Service # belongs to selector: app: localstack ports: - port: 32000 protocol: TCP name: ui nodePort: 32000 - port: 31001 protocol: TCP name: dynamodb nodePort: 31001 type: LoadBalancer
  16. apiVersion: skaffold/v1alpha2 kind: Config build: artifacts: - imageName: your-app workspace:

    . docker: {} bazel: null local: skipPush: null googleCloudBuild: null kaniko: null deploy: helm: null kubectl: manifests: - path-to-localstack-manifest.yml - path-to-your-app-manifest.yml
  17. Containerizing Node.js Applications

  18. Let's look at a common Dockerfile for Node.js apps!

  19. Most Node.js Docker tutorials have this FROM node:8.6.0-alpine WORKDIR /usr/src/app

    COPY package-lock.json . RUN npm ci COPY . . EXPOSE 3000 CMD node index.js
  20. Most Node.js Docker tutorials have this • But it has

    the following issues: ◦ Does not handle proper signal forwarding for sudo and su ◦ Does not use an unprivileged user for running the applications • These best practices are handled out of the box in the godaddy/docker-node images ◦ ◦
  21. Handle Application Lifecycle Events

  22. What are Pods? • Smallest deployable unit • It is

    a group of one or more containers ◦ Shared networking and storage ◦ The “one-container-per-Pod” model is the most common Kubernetes use case • Each pod has a unique IP address
  23. Application life-cycle 1/2 1. Application are running in Pods a.

    represents a running process on your cluster 2. Possible states: a. Pending b. Running c. Succeeded d. Failed e. Unknown
  24. Application life-cycle 2/2 • States are determined using probes ◦

    Liveness ▪ to know when to restart a container ◦ Readiness ▪ to know when a container is ready to start accepting traffic
  25. What happens when you deploy a new version of your

  26. What does your application have to do when shutting down?

    1. Finishes (or tries to finish) all ongoing requests 2. Free up used resources (database connections, file handlers, etc…) 3. Stop. This is called graceful shutdown.
  27. Terminus is an open-source project that adds health checks and

    graceful shutdown to your applications.
  28. const terminus = require('@godaddy/terminus'); const server = http.createServer(app); async function

    onSignal() { console.log('server is starting cleanup'); } async function onHealthCheck() {} terminus(server, { signals: ['SIGTERM'], healthChecks: { '/healthcheck': onHealthCheck, }, onSignal }); server.listen(3000);
  29. Be careful with the NGINX ingress controller!

  30. The NGINX ingress controller • By default, if a Pod

    receives a SIGTERM, it gets removed from the load-balancer (Service) • The NGINX ingress controller does not use a Service under the hood, it routes traffic directly to the pods, so: ◦ NGINX may route traffic to Pods which are terminating (the requests will fail), ◦ To fix that, you have to delay the shutdown with gracePeriod seconds ♂
  31. Packaging Applications

  32. Before start using Kubernetes, you have figure out how to

    write configuration for it.
  33. Kubernetes can become extremely complex with all the objects you

    need to handle.
  34. Hi Helm! • Helm is a package manager for Kubernetes

    ◦ You can focus on building application logic, and not yet-another environment ◦ Helm provides "1-click" deployment, making adoption simpler ◦ Reusability
  35. The Anatomy of a Helm Charts node-app/ Chart.yaml # A

    YAML file containing information about the chart LICENSE # OPTIONAL: A plain text file containing the license for the chart # OPTIONAL: A human-readable README file requirements.yaml # OPTIONAL: A YAML file listing dependencies for the chart values.yaml # The default configuration values for this chart charts/ # A directory containing any charts upon which this chart depends. templates/ # A directory of templates that, when combined with values, # will generate valid Kubernetes manifest files. templates/NOTES.txt # OPTIONAL: A plain text file containing short usage notes
  36. Securing the Kubernetes Cluster

  37. You tell Kubernetes what to do through a REST API.

  38. Securing Kubernetes - Access • To secure access to the

    Kubernetes cluster, and the resources it is responsible for: ◦ make sure to use TLS for all communication towards the API, ◦ use role-based access control for authorization.
  39. But it is not just the API. What about running

  40. Securing Kubernetes - Pod Security Policies • Pod Security Policies:

    ◦ can prevent Pods from running with root privileges, ◦ can limit what volumes Pods can access, ◦ can prevent pods from accessing host ports, ◦ support AppArmor and Seccomp.
  41. Securing Kubernetes - Audit by

  42. Resource Constraints

  43. Most Kubernetes deployments run multiple different applications.

  44. Just as in a PaaS environment, some multitenancy problems apply

    to Kubernetes too.
  45. Let's talk about performance • You have two applications running

    in Kubernetes ◦ One service sending out marketing emails ◦ The other serving HTTP traffic • What happens with different traffic patterns?
  46. Let's talk about performance

  47. Let's talk about performance

  48. Let's talk about performance • Resource Constraints to the rescue

    ◦ You can define Pod-level resource limits for CPU and memory ◦ Or on the namespace level too
  49. Let's talk about performance apiVersion: v1 kind: Pod metadata: name:

    cpu-demo namespace: cpu-example spec: containers: - name: cpu-demo-ctr image: vish/stress resources: limits: cpu: "1" requests: cpu: "0.5" apiVersion: v1 kind: LimitRange metadata: name: mem-limit-range spec: limits: - default: memory: 512Mi defaultRequest: memory: 256Mi type: Container for pods / deployments for namespaces
  50. Disaster Recovery

  51. Set of policies and procedures - they answers the question

    of what to do when a disaster hits the system?
  52. • Ark gives you tools to backup and restore your

    Kubernetes cluster resources and persistent volumes: ◦ Take backups of your cluster and restore in case of loss ◦ Copy cluster resources across cloud providers ◦ Replicate your production environment for development and testing environments Ark by Heptio
  53. Ark is not enough. Backups are only valuable if you

    know how to use them.
  54. Schedule regular practice runs to simulate disaster recovery.

  55. That's it folks. Gergely Nemeth | | @nthgergo

  56. Further reading • • • •