Immutable infrastructure: deploying and destroying Kubernetes services

Seven months ago, we shipped Forge 0.1. Our goal at the time was simple: we needed a simple way to deploy services from source into Kubernetes. Since then, we’ve discovered many of the nuances of service deployment. We’ve added features such as dependency management, customized deployments (via profiles), Jinja2 templates for Kubernetes manifests, Git integration, and more. All of these features share a common denominator — they simplify the deployment of services from source into Kubernetes.

Going from Kubernetes to source

However, what about the reverse? How do you get from Kubernetes to source? We found that as we started adding more services with more developers this became a problem.

When one of our services has a problem, we want the on-call engineer to be able to start the troubleshooting process right away. A crucial piece of information in that troubleshooting process is the actual source of the service.

Forge 0.4

Today, we are releasing Forge 0.4 which addresses this problem. Forge now adds metadata to every Kubernetes resource it creates. This metadata includes information about which Git repository was used to create the resource.

Forge 0.4 also adds list and delete commands for managing deployed resources. These commands rely on the metadata tagging features.

$ forge list
ambassador[default]: git@github.com:datawire/blackbird.git | ambassador/service.yaml | 706dbf7abb3a0dddb74d06a9a169c9fa08dbcc68.sha
clusterrole .ambassador:
{}
clusterrolebinding .ambassador:
{}
deployment datawire.ambassador:
Deployment has minimum availability.
namespace .datawire:
{u'phase': u'Active'}
service datawire.ambassador:
READY(10.40.54.6:80)
service datawire.ambassador-admin:
READY(10.40.54.6:8877)
serviceaccount datawire.ambassador:
{}

java-spring-api[default]: git@github.com:datawire/blackbird.git | java-spring-api/service.yaml | ed80c87364384f1ef208ffa72722c5dd99cd9262.git
deployment datawire.java-spring-api-dev-test:
ReplicaSet "java-spring-api-dev-test-f5cd8c468" has successfully progressed.
service datawire.java-spring-api-dev-test:
READY(10.40.54.3:8080)

Immutable infrastructure

The Forge deployment model is oriented around the concept of immutable infrastructure. With Forge, you no longer upgrade your service. Instead, you roll out a new Kubernetes deployment of your service, and incrementally route traffic to the new deployment. The (old) service is then destroyed.

Forge 0.4 now lets you now manage this entire lifecycle, from deployment to deletion.

lost-cause:python-api richard$ forge deploy --profile dev python-api
║ 57 tasks run, 0 errors
║
║ rendered: namespace/datawire, service/python-api-stable, deployment/python-api-stable
║ deployed: python-api
$ kubectl get svc -n datawire python-api
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
python-api-dev-test 10.43.253.235 <none> 80/TCP 4d
python-api-stable 10.43.245.189 <none> 80/TCP 26s
...
$ forge delete python-api dev
...
║ deployment "python-api-dev-test" deleted
║ endpoints "python-api-dev-test" deleted
║ service "python-api-dev-test" deleted
...

Interested in using Forge? Check out our quickstart. If you have any questions, join our Gitter chat!