Slide 1

Slide 1 text

Deploying Node.js Applications with Confidence using Kubernetes Gergely Nemeth | nemethgergely.com | @nthgergo

Slide 2

Slide 2 text

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/

Slide 3

Slide 3 text

Deploying Node.js Applications with Confidence using Kubernetes Gergely Nemeth | nemethgergely.com | @nthgergo

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

Kubernetes architecture 101

Slide 6

Slide 6 text

Kubernetes architecture ● At least one master ● Multiple worker nodes https://thenewstack.io/kubernetes-an-overview/

Slide 7

Slide 7 text

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/

Slide 8

Slide 8 text

Nodes ● Node components run on every node, maintaining running pods and providing the Kubernetes runtime environment. https://thenewstack.io/kubernetes-an-overview/

Slide 9

Slide 9 text

Running Kubernetes

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

Or if you feel a bit more adventurous, AWS.

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

Running Kubernetes Locally ● With the help of ○ Minikube - https://github.com/kubernetes/minikube ○ Skaffold - https://github.com/GoogleCloudPlatform/skaffold

Slide 14

Slide 14 text

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"

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

Containerizing Node.js Applications

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

Handle Application Lifecycle Events

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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/

Slide 25

Slide 25 text

What happens when you deploy a new version of your application?

Slide 26

Slide 26 text

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.

Slide 27

Slide 27 text

Terminus is an open-source project that adds health checks and graceful shutdown to your applications.

Slide 28

Slide 28 text

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);

Slide 29

Slide 29 text

Be careful with the NGINX ingress controller! https://github.com/godaddy/terminus/pull/58

Slide 30

Slide 30 text

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 ♂

Slide 31

Slide 31 text

Packaging Applications

Slide 32

Slide 32 text

Before start using Kubernetes, you have figure out how to write configuration for it.

Slide 33

Slide 33 text

Kubernetes can become extremely complex with all the objects you need to handle.

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

Securing the Kubernetes Cluster

Slide 37

Slide 37 text

You tell Kubernetes what to do through a REST API.

Slide 38

Slide 38 text

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.

Slide 39

Slide 39 text

But it is not just the API. What about running apps?

Slide 40

Slide 40 text

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.

Slide 41

Slide 41 text

Securing Kubernetes - Audit by kubesec.io

Slide 42

Slide 42 text

Resource Constraints

Slide 43

Slide 43 text

Most Kubernetes deployments run multiple different applications.

Slide 44

Slide 44 text

Just as in a PaaS environment, some multitenancy problems apply to Kubernetes too.

Slide 45

Slide 45 text

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?

Slide 46

Slide 46 text

Let's talk about performance

Slide 47

Slide 47 text

Let's talk about performance

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

Disaster Recovery

Slide 51

Slide 51 text

Set of policies and procedures - they answers the question of what to do when a disaster hits the system?

Slide 52

Slide 52 text

● 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

Slide 53

Slide 53 text

Ark is not enough. Backups are only valuable if you know how to use them.

Slide 54

Slide 54 text

Schedule regular practice runs to simulate disaster recovery.

Slide 55

Slide 55 text

That's it folks. Gergely Nemeth | nemethgergely.com | @nthgergo

Slide 56

Slide 56 text

Further reading ● https://nemethgergely.com/using-kubernetes-for-local-development/ ● https://nemethgergely.com/skaffold-and-localstack-to-develop-aws-locally/ ● https://github.com/heptio/ark ● https://github.com/godaddy/terminus