Use a service's external IP as an environment variable to a deployment

10/5/2018

Is it possible to pass a Service's external IP (NodePort or LoadBalancer) as an environment variable to a container in a different service's Deployment?

For a concrete example, consider a Kubernetes cluster with namespaces for multiple teammates so they each have their own environment for testing. In a single environment, there are at least two services:

  1. An API Gateway service, for routing traffic to other services
  2. A service that can register DNS entries to the environment

For Service #2, it needs to know the external IP address of service #1. So far I've only been able to find examples that make use of kubectl to describe service #1 to find this information. I was hoping it would be possible to do something like this:

apiVersion: v1
kind: Service
metadata:
  name: gateway
  namespace: "${ env }"
  labels:
    app: gateway
spec:
  type: LoadBalancer
  ports:
     - port: 8080
  selector:
    app: gateway

and

apiVersion: extensions/v1
kind: Deployment
metadata:
  name: svc2-deployment
  namespace: "${ env }"
  labels:
    app: svc2
spec:
  template:
    metadata:
      labels:
        app: svc2
    spec:
      containers:
        - name: app
          env:
            - name: GATEWAY_IP
              valueFrom:
                fieldRef:
                  fieldPath: service.gateway.----.ingressIp

instead of using say an initContainers with a script that does kubectl things. Especially since I'm very new to Kubernetes :)

-- mrusinak
kubernetes

2 Answers

10/5/2018

Not really but you can use DNS for that. For example:

apiVersion: extensions/v1
kind: Deployment
metadata:
  name: svc2-deployment
  namespace: "${ env }"
  labels:
    app: svc2
spec:
  template:
    metadata:
      labels:
        app: svc2
    spec:
      containers:
        - name: app
          env:
            - name: GATEWAY_IP
              value: gateway.<namespace-where-gw-is-running>.svc.cluster.local
-- Rico
Source: StackOverflow

10/5/2018

It isn't currently an out of the box feature but there are tools you can install to get that external IP and put it in a configmap - for example the Jenkins-X expose-controller. However, I found it easier to just use DNS and parameterise the DNS name in your descriptors.

If you have wildcard DNS then you can give each service a dedicated external hostname under the domain like service1.domain and service2.domain etc. The wildcard DNS will route all of these to your ingress controller and it can then route to the right service based on hostname. (As the Jenkins-X guys note, you can get Willard DNS for free if your ingress IP is public with nip.io if you don't have something like route53 available.)

My experience of this was on the activiti project. We found that services needed to have a property injected that told them the external URL to the keycloak authentication system because each service contained keycloak code to validate that the token was issued on a valid external URL. You can see the result in the helm charts and there's a README there that explains a bit more. We took inspiration from the gitlab helm chart - their instructions ask the user to put in a wildcard DNS, presumably for similar reasons.

-- Ryan Dawson
Source: StackOverflow