Kubernetes Native Phoenix Apps: Introduction

I’m kicking off a new blog series that focuses on the intersection of Elixir and Kubernetes. This is becoming a more and more popular deployment target for companies and developers who don’t find a comfortable fit with other options that make different trade-offs.

I’ve spent most of the last two years helping several companies leverage Kubernetes effectively, both as a direct employee on a systems/platform team and as a specialized consultant, and I’d like to share some of those learnings with the community that is nearest and dearest to my heart: Elixir. These companies varied in size and scope, but their chief commonality is that Kubernetes has proved to be an accelerant for their business goals.

In particular, I consider Kubernetes an excellent target for deployment when dealing with teams that are shipping polygot solutions, teams who are managing multiple products without a dedicated team for each product, organizations looking to achieve better infrastructure density or standardization, or organizations who highly value infrastructure agility.

Elixir’s deployment story has come a long way since I started working with the language in 2015, but depending on your needs, there is still a lot of information to assimilate, and a lot of practices to synthesize into a unified, effective solution.

Prerequisites

Infrastructure and deployment practices are not and can not be a one-size-fits-all problem space, so I’m going to focus on presenting an opinionated, focused, and polished approach that makes a few simplifying assumptions:

  • You have at least one Elixir app that leverages Phoenix for a web interface
  • You are already using, prepared to upgrade to, or are otherwise capable of using Distillery 2.x in your project
  • You are deploying your product on one of the infrastructure-as-a-service platforms that are suitable for use with production-grade Kubernetes, such as:
  • Importantly, you already have a viable Kubernetes cluster in place with kubectl access ready to go
  • You are already comfortable with Kubernetes primitives or are capable of learning these from another reference

Planned series content

Off-topic Subjects

This series will avoid deep coverage of a few topics that are worthy of their own separate coverage and will distract from the ideas being presented here:

  • CI/CD practices or tooling recommendations - I’ve worked with almost all of them by now other than GoCD, and I’ve assumed the position that these needs are heavily informed by your organizational structure and tolerance for certain constraints or limitations, and aren’t able to be addressed in a generalized way
  • Automating the actual deployment workflows from SCM - similar to the above, it’s hard to cover this adequately in a generic way
  • Kubernetes-as-development-environment tools - Tools like Draft, Skaffold, Knative, along with some of the other features of Telepresence, don’t currently offer a compelling use-case for me. I’ve attempted several iterations where I’ve tried to evaluate them in earnest, and I unfortunately found them to be feature-incomplete, unreliable, hard to triage without RTFS, and high-friction to use.

Additionally, I will avoid covering subjects that I consider to be out-of-scope:

  • Elixir/Phoenix fundamentals
  • Elixir/Phoenix development environment
  • Kubernetes fundamentals
  • A direct treatment of the pros/cons of using containers with the BEAM
  • Individual merits of alternate container schedulers (K8s vs GKE/AKS/EKS vs OpenShift vs ECS vs Mesos vs Nomad)
  • Hot code upgrades in the context of Docker/Kubernetes

Other Caveats

This series will avoid documenting certain practices that I strongly consider to be development or deployment antipatterns. I’m aware that there are some situations where they are more appropriate, or at very least more expedient under the constraints in play, but these are generally to be avoided if you have the opportunity to choose otherwise.

  • Long-term use of Docker images and long-lived containers as your actual development environment - stick with native development practices for best productivity
  • Single-stage Docker images which include a full development/compilation toolchain in the final product
  • Building Docker images on your Kubernetes cluster by mounting the Docker daemon’s socket into a container (with a partial exception for the Minikube phase)
  • Raw YAML templates as a long-term solution for managing Kubernetes workloads
  • Tools such as Kompose which translate directly from docker-compose.yml to Kubernetes resource manifests
  • Namespaces and RBAC as your sole boundary between logical environments (such as dev/staging/production as implied by MIX_ENV conventions)

Alternate Deployment Tooling

More Reading
Older// Hardware
comments powered by Disqus