Home > Software design >  How to get kubernetes service external ip dynamically inside manifests file?
How to get kubernetes service external ip dynamically inside manifests file?

Time:08-05

We are creating a deployment in which the command needs the IP of the pre-existing service pointing to a statefulset. Below is the manifest file for the deployment. Currently, we are manually entering the service external IP inside this deployment manifest. Now we would like it to auto-populate during runtime. Is there a way to achieve this dynamically using environment variables or another way?

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-api
  namespace: app-api
spec:
  selector:
    matchLabels:
      app: app-api
  replicas: 1
  template:
    metadata:
      labels:
        app: app-api
    spec:
      containers:
      - name: app-api
        image: asia-south2-docker.pkg.dev/rnd20/app-api/api:09
        command: ["java","-jar","-Dallow.only.apigateway.request=false","-Dserver.port=8084","-Ddedupe.searcher.url=http://10.10.0.6:80","-Dspring.cloud.zookeeper.connect-string=10.10.0.6:2181","-Dlogging$.file.path=/usr/src/app/logs/springboot","/usr/src/app/app_api/dedupe-engine-components.jar",">","/usr/src/app/out.log"]
        livenessProbe:
          httpGet:
            path: /health
            port: 8084
            httpHeaders:
            - name: Custom-Header
              value: ""
          initialDelaySeconds: 60
          periodSeconds: 60
        ports:
        - containerPort: 4016
        resources:
          limits:
            cpu: 1
            memory: "2Gi"
          requests:
            cpu: 1
            memory: "2Gi"

NOTE: The IP in question here is the Internal load balancer IP, i.e. the external IP for the service and the service is in a different namespace. Below is the manifest for the same

apiVersion: v1
kind: Service
metadata:
  name: app
  namespace: app
  annotations:
    cloud.google.com/load-balancer-type: "Internal"
  labels:
    app: app
spec:
  selector:
    app: app
  type: LoadBalancer
  ports:
  - name: container
    port: 80
    targetPort: 8080
    protocol: TCP

CodePudding user response:

You could use the following command instead:

command:
  - /bin/bash
  - -c
  - |-
    set -exuo pipefail

    ip=$(dig  search  short servicename.namespacename)

    exec java -jar -Dallow.only.apigateway.request=false -Dserver.port=8084 -Ddedupe.searcher.url=http://$ip:80 -Dspring.cloud.zookeeper.connect-string=$ip:2181 -Dlogging$.file.path=/usr/src/app/logs/springboot /usr/src/app/app_api/dedupe-engine-components.jar > /usr/src/app/out.log

It first resolves the ip address using dig (if you don't have dig in your image - you need to substitute it with something else you have), then execs your original java command.

As of today I'm not aware of any "native" kubernetes way to provide IP meta information directly to the pod.

CodePudding user response:

If you are sure they exist before, and you deploy into the same namespace, you can read them from environment variables. It's documented here: https://kubernetes.io/docs/concepts/services-networking/service/#environment-variables.

When a Pod is run on a Node, the kubelet adds a set of environment variables for each active Service. It adds {SVCNAME}_SERVICE_HOST and {SVCNAME}_SERVICE_PORT variables, where the Service name is upper-cased and dashes are converted to underscores. It also supports variables (see makeLinkVariables) that are compatible with Docker Engine's "legacy container links" feature.

For example, the Service redis-master which exposes TCP port 6379 and has been allocated cluster IP address 10.0.0.11, produces the following environment variables:

REDIS_MASTER_SERVICE_HOST=10.0.0.11
REDIS_MASTER_SERVICE_PORT=6379
REDIS_MASTER_PORT=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP_PROTO=tcp
REDIS_MASTER_PORT_6379_TCP_PORT=6379
REDIS_MASTER_PORT_6379_TCP_ADDR=10.0.0.11

Note, those wont update after the container is started.

  • Related