Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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
Tweet

More Decks by Gergely Nemeth

Other Decks in Programming

Transcript

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

    View full-size slide

  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/

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  5. Kubernetes architecture 101

    View full-size slide

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

    View full-size slide

  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/

    View full-size slide

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

    View full-size slide

  9. Running Kubernetes

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

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

    View full-size slide

  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"

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  17. Containerizing Node.js
    Applications

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  21. Handle Application Lifecycle
    Events

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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/

    View full-size slide

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

    View full-size slide

  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.

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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 ♂

    View full-size slide

  31. Packaging Applications

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  36. Securing the Kubernetes Cluster

    View full-size slide

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

    View full-size slide

  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.

    View full-size slide

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

    View full-size slide

  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.

    View full-size slide

  41. Securing Kubernetes - Audit by kubesec.io

    View full-size slide

  42. Resource Constraints

    View full-size slide

  43. Most Kubernetes deployments run
    multiple different applications.

    View full-size slide

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

    View full-size slide

  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?

    View full-size slide

  46. Let's talk about performance

    View full-size slide

  47. Let's talk about performance

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  50. Disaster Recovery

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

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

    View full-size slide

  54. Schedule regular practice runs to
    simulate disaster recovery.

    View full-size slide

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

    View full-size slide

  56. 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

    View full-size slide