At my current project, we have started restructuring our cluster’s namespaces model. We are moving from one namespace
to namespace per team/domain
model.
One of the challenges that we immediately encountered was that when you move application to a different namespace, you need to change service URLs of all dependent applications and include namespace. Here is an abstracted example:
There are 3 applications AppA
, AppB
and AppC
. All deployed with corresponding Kubernetes services called ServiceA
, ServiceB
and ServiceC
.
All 3 applications are deployed to the same namespace called foobar
. AppA
has inbound dependency from AppC
and outbound dependency to AppB
.
Since everything is deployed to the same namespace, we use the following URLs to call our services:
http://servicea/
http://serviceb/
http://servicec/
Now, we want to move AppA
to the new foo
namespace.
Since applications are now deployed to different namespaces, we need to change and use the following URLs to call services:
http://servicea.foo.svc.cluster.local/
http://serviceb.foobar.svc.cluster.local/
http://servicec.foobar.svc.cluster.local/
Not only that requires changes at all 3 applications, but also may cause a possible down time at AppC
during the migration period. In real life, with hundreds of applications migrating to several namespaces, that can cause even longer down time and depending on the dependency graph, can require a lot of deployment orchestration during transition period. Not to mention that it might be that some of the applications can’t be re-configured and re-deployed at the moment.
All these factors forced us to think how we can do such a migration with close to zero down time.
Proxy with ExternalName Service type
The solution that we came up with was to introduce a proxy-service at the old namespace with the same name as service being migrated, pointing to the service in the new namespace.
The proxy-service ServiceA
is deployed to the foobar
namespace and routes traffic to the “real” ServiceA
at the foo
namespace. Because proxy-service deployed to the same namespace, AppC
can still call it by using http://servicea/
.
Kubernetes documentation describes services of type ExternalName as Service that maps a Service to a DNS name, not to a typical selector.
Here is a proxy-service definition for servicea
at foobar
namespace:
apiVersion: v1
kind: Service
metadata:
name: servicea
namespace: foobar
spec:
type: ExternalName
externalName: servicea.foo.svc.cluster.local
Migration plan
With proxy-service in place, here is our migration strategy:
- Re-configure
AppA
with correct URLs for all outbound dependencies - Deploy
AppA
intofoo
namespace
- Replace
servicea
infoobar
namespace with proxy-service
- Delete
AppA
pods (and other related Kubernetes resources) fromfoobar
namespace
- Deploy new version of
AppC
with URL pointing toservica
atfoo
namespace
- When all applications calling
AppA
atfoobar
namespace are re-configured and re-deployed, deleteservicea
fromfoobar
namespace
Useful links
With that - thanks for reading :)