Continuous Delivery within Kubernetes: Shifting Responsibilities from Ops to Dev
Tools, practices, and configuration for developers creating and integrating a build pipeline for deploying applications to Kubernetes
As Humble and Farley stated in their book Continuous Delivery back in 2010, “getting software released to users is often a painful, risky, and time-consuming process”. However, there is clear value in being able to rapidly release functionality in a safe and reliable manner. The adoption of cloud native architectures means that developers are now creating more moving parts with differing runtime requirements and dependencies. This means that although initially a sysadmin or platform concern, the knowledge and responsibility that developers now have means that implementing cloud native continuous delivery falls firmly on their shoulders.
The goal has always been to get a fast application build-release-verification feedback loop established. Traditionally developers committed their code to version control and the rest of the delivery lifecycle was managed by operations. But, to borrow a phrase from Netflix, fullstack developers are now becoming full lifecycle developers; they are responsible for ensuring that the code they write delivers value to users. This increase in operational responsibilities means that developers must be able to configure the continuous deployment and release of applications.
This guide applies to a developer simply experimenting with Kubernetes and also a new engineer onboarding onto a team deploying onto Kubernetes. Although the fast feedback goal remains the same when working with cloud native technologies, when adopting containers and Kubernetes there are a few more tools to install and configurations to tweak.
From Pre-Cloud CI/CD to Kubernetes Continuous Deployment
Before cloud native architecture became the dominant approach to designing, deploying, and releasing software the continuous delivery story was much simpler. Typically a sysadmin would create a build server and install a version control system and continuous integration tool such as Jenkins, TeamCity, or GoCD. In addition to continually building and integrating code, these tools could be augmented via plugins to perform rudimentary continuous deployment operations, such as FTPing binaries to VMs or uploading an artifact to a remote application server via a bespoke SDK/API.
This approach worked well when dealing with a small number of applications and a relatively static deployment environment. The initial configuration of a delivery pipeline was typically challenging and involved much trial and error. When a successful configuration was discovered, this was used as a template and then copy-pasted as more build jobs were added. Debugging a build failure often required specialist support.
With the rise in popularity of containers and Kubernetes has meant that roles and responsibilities in relation to continuous delivery have changed. Operators may still set up the initial continuous integration and deployment tooling, but developers now want to self-service as they are releasing and operating what they build. This means that the scope of the infrastructure a developer needs to understand and manage has expanded from pure development tools (e.g., IDE, libraries and APIs) to deployment infrastructure (e.g., container registries and deployment templates) to runtime infrastructure (e.g., API gateways and observability systems).
|Number of services per application or system||~1 large service||Many small (micro)services|
|Deployment Artifact||Small number of language-specific packages or binaries||Large number of container images|
|Artifact manifests||Low-medium complexity (language/platform specific). A limited amount of small-medium scripts||High complexity (language, OS, and framework). Potentially a large amount of long configuration files|
|CI infrastructure required||Bare metal or VMs||Bare metal, VMs, Docker / containers, Kubernetes|
|Deployment mechanisms||Custom (imperative) scripts run via SSH or FTP etc., or proprietory SDKs/APIs||Well-defined declarative configuration applied via standardised APIs|
|Release mechanisms||Deployment and release implicitly coupled. Verification managed by eyeballing metrics systems and dashboards.||Release controlled via traffic shifting e.g. canaries (north-south and east-west) and verification managed automatically with observability system integrations|
|Environment management||Small number of manually curated test and staging environments. Artifacts and configuration relatively static||Large number of bespoke. Artifacts and configuration highly dynamic and transient|
Creating an Effective Kubernetes Continuous Deployment Pipeline
Being able to configure an effective Kubernetes deployment pipeline is not dependent on a single tool or technique. A combination of technologies are required:
- Container Build Tools
- YAML Templating and Package Managers
- Continuous Integration Tooling
- Continuous Deployment Tooling
Frequently Asked Questions
- Can I continue using my existing CI/CD tools when migrating to Kubernetes?
- Should developers be responsible for defining Dockerfiles and Kubernetes YAML manifests?
- Do developers need to learn Kubernetes YAML syntax?
- Is continuous integration (CI) different in comparison with continuous deployment (CD)? I often see them written as CI/CD?