Code has evolved from being something that’s developed internally and guarded with licenses to something that’s written and developed by a community. With this change has come the need for organizations to cater to and account for code coming in from a number of external sources (like the open source community, for instance). Even within organizations where updates used to be few and far between, you now have a situation where every developer is constantly adding new code. With code being updated so frequently and from so many different sources, it’s pretty easy to lose parity in today’s highly distributed environments.
Even a modestly sized modern-day project could potentially have thousands of dependencies, and making sure all dependencies are updated and available is an integral part of cluster management. Kubernetes has now become the de facto standard for deploying containerized applications at scale in private, public and hybrid cloud environments. This is because Kubernetes lets you describe not just the target resource, but also its dependencies, policies, health checks and other attributes. Maintaining parity between Kubernetes deployments, however, requires additional skills, tools, practices and automation.
Building in consistency right from code commit
To maintain parity between Kubernetes deployments, Dev and Ops teams need to be on the same page at the start. For this to happen, it’s important to establish some standards for Kubernetes cluster management. Shared repositories like GitHub are a great way for Dev and Ops teams to work together and use the same resource pools without conflict. There are a variety of modern software repository hosting tools available to choose from. Each code repository system has its own strengths and weaknesses. Additionally, each repository hosting tool has various support for underlying version control systems.
Version control systems like Git and Mercurial prevent code from building up inconsistencies over time by tracking all changes, along with details like who, when and why. This not only makes code easier to read and understand — It also gives you a broad view of how your project has evolved between deployments. It does this by requesting a short description of what was changed every time someone makes a change to your project, and showing you exactly what was changed in the file’s content. Using a distributed VCS like Git can also act as a backup, since every team member essentially has a complete version history of the project on their disk.
Checks and balances in the build process
It’s also important to have access policies in place to dictate who can submit code and in what format. This would require a CI tool like Jenkins or CircleCI, or a more niche build automation tool like AWS Code Build or Google Cloud Build. Build automation tools are a great way to enforce a standard with regard to code updates, and are a necessary prerequisite for continuous integration and continuous testing. Using tools to automate the build process not only eliminates variations that cause disparity, it also eliminates redundant and manually heavy tasks like documenting dependencies on third-party products and the like.
As mentioned earlier, Kubernetes allows users to declare not just their target clusters, but all related resources as well, varying from simple memcached pods to full web app stacks. Managing infrastructure in a declarative manner in Kubernetes, however, requires that you understand Kubernetes resources and are able to edit YAML files. While this is a pretty steep learning curve for coders not yet familiar with Kubernetes, it is an essential step to achieving parity between deployments. The good thing about Kubernetes is that support for it runs pretty deep, and there is an entire ecosystem of tools aimed at improving the end-user experience with Kubernetes.
Parity in production
The overwhelming support of the open source community and the backing of the CNCF have effectively solidified Helm as the de facto standard for Kubernetes package management. Helm-based deployments are based on Helm charts, which are basically a collection of YAML template files organized into specific directory structures. Helm’s popularity is probably due to the fact that it not only lets users configure actions before installation and after upgrades, but also during deployment. Additionally, the steep learning curve is replaced by an intuitive CLI, and developers can even share charts via repositories. This eliminates tedious and often OS-specific environment setup for each stack component in order to achieve parity.
When it’s time to deploy code across multiple clusters with varying configuration, it’s easy for configuration drift to slip in. Using a tool like Spinnaker enforces the kind of immutability that containers enable. The ability to build complex pipelines that can take code to production, irrespective of the complexities, is key to seeing parity to the very last mile. Mature deployment strategies like blue-green and canary releases make it more possible to bring parity between environments.
While being able to declare static values for resources and the complex relationships between their dependencies is a handy feature, it’s just the tip of the iceberg in the context of what Kubernetes can actually do. Where cluster management really gets interesting is when you start enforcing policies rather than just assigning static values. Kubernetes doesn’t just support but requires this level of sophistication to be used to its full potential, and tools like Istio allow this with its policies to control traffic.
In conclusion, we have just begun to tap the potential of Kubernetes and the cloud native environment which is still evolving (and probably always will). Environmental parity will continue to be a concern for customers as Kubernetes grows, and with it, the ecosystem of tools around it.