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.

29955e7f5ba4bd072e7c0e98e4a788fb?s=128

Gergely Nemeth

July 25, 2018
Tweet

Transcript

  1. 2.

    Who am I? • Gergely Nemeth • Engineering Manager @

    Uber (Web Platform, and I am hiring) • Software Developer • Coffee Lover ☕ ◦ https://www.meetup.com/Cafe-js-San-Francisco/
  2. 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
  3. 6.

    Kubernetes architecture • At least one master • Multiple worker

    nodes https://thenewstack.io/kubernetes-an-overview/
  4. 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) https://thenewstack.io/kubernetes-an-overview/
  5. 8.

    Nodes • Node components run on every node, maintaining running

    pods and providing the Kubernetes runtime environment. https://thenewstack.io/kubernetes-an-overview/
  6. 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
  7. 13.

    Running Kubernetes Locally • With the help of ◦ Minikube

    - https://github.com/kubernetes/minikube ◦ Skaffold - https://github.com/GoogleCloudPlatform/skaffold
  8. 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"
  9. 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
  10. 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
  11. 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
  12. 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 ◦ https://hub.docker.com/r/godaddy/node/ ◦ https://github.com/godaddy/docker-node
  13. 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
  14. 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 https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle
  15. 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 https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/
  16. 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.
  17. 27.

    Terminus is an open-source project that adds health checks and

    graceful shutdown to your applications.
  18. 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);
  19. 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 ♂
  20. 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
  21. 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 README.md # 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
  22. 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.
  23. 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.
  24. 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?
  25. 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
  26. 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
  27. 51.

    Set of policies and procedures - they answers the question

    of what to do when a disaster hits the system?
  28. 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 https://github.com/heptio/ark