Search code examples
dockerkuberneteskubernetes-pod

Kubernetes Deployment dynamic port forwarding


I am moving a Docker Image from Docker to a K8s Deployment. I have auto-scale rules on so it starts 5 but can go to 12. The Docker image on K8s starts perfectly with a k8s service in front to cluster the Deployment.

Now each container has its own JVM which has a Prometheus app retrieving its stats. In Docker, this is no problem because the port that serves Prometheus info is dynamically created with a starting port of 8000, so the docker-compose.yml grows the port by 1 based on how many images are started.

The problem is that I can't find how to do this in a K8s [deployment].yml file. Because Deployment pods are dynamic, I would have thought there would be some way to set a starting HOST port to be incremented based on how many containers are started.

Maybe I am looking at this the wrong way so any clarification would be helpful meanwhile will keep searching the Google for any info on such a thing.


Solution

  • Well after reading and reading and reading so much I came to the conclusion that K8s is not responsible to open ports for a Docker Image or provide ingress to your app on some weird port, it's not its responsibility. K8s Deployment just deploys the Pods you requested. You can set the Ports option on a DEPLOYMENT -> SPEC -> CONTAINERS -> PORTS which just like Docker is only informational. But this allows you to JSONPath query for all PODS(containers) with a Prometheus port available. This will allow you to rebuild the "targets" value in Prometheus.yaml file. Now having those targets makes them available to Grafana to create a dashboard.

    That's it, pretty easy. I was complicating something because I did not understand it. I am including a script I QUICKLY wrote to get something going USE AT YOUR OWN RISK.

    By the way, I use Pod and Container interchangeably.

      #!/usr/bin/env bash
      #set -x
    
      _MyappPrometheusPort=8055
      _finalIpsPortArray=()
      _prometheusyamlFile=prometheus.yml
    
      cd /docker/images/prometheus
    
    
      #######################################################################################################################################################
      #One container on the K8s System is weave and it holds the subnet we need to validate against.
      #weave-net-lwzrk                            2/2     Running   8 (7d3h ago)   9d    192.168.2.16   accl-ffm-srv-006   <none>           <none>
      _weavenet=$(kubectl get pod -n kube-system -o wide | grep weave | cut -d ' ' -f1 )
      echo "_weavenet: $_weavenet"
    
      #The default subnet is the one that lets us know the conntainer is part of kubernetes network.
      #          Range: 10.32.0.0/12
      #  DefaultSubnet: 10.32.0.0/12
      _subnet=$( kubectl exec -n kube-system $_weavenet -c weave -- /home/weave/weave --local status | sed -En "s/^(.*)(DefaultSubnet:\s)(.*)?/\3/p" )
      echo "_subnet: $_subnet"
      _cidr2=$( echo "$_subnet" | cut -d '/' -f2 )
      echo "_cidr2: /$_cidr2"
    
    
    
      #######################################################################################################################################################
      #This is an array of the currently monitored containers that prometheus was sstarted with.
      #We will remove any containers form the array that fit the K8s Weavenet subnet with the myapp prometheus port.
      _targetLineFound_array=($( egrep '^\s{1,20}-\s{0,5}targets\s{0,5}:\s{0,5}\[.*\]' $_prometheusyamlFile | sed -En "s/(.*-\stargets:\s\[)(.*)(\]).*/\2/p"  | tr "," "\n"))
      for index in "${_targetLineFound_array[@]}"
      do
          _ip="${index//\'/$''}"
          _ipTocheck=$( echo $_ip | cut -d ':' -f1 )
          _portTocheck=$( echo $_ip | cut -d ':' -f2 )
          #We need to check if the IP is within the subnet mask attained from K8s.
          #The port must also be the prometheus port in case some other port is used also for Prometheus.
          #This means the IP should be removed since we will put the list of IPs from
          #K8s currently in production by Deployment/AutoScale rules.
          #Network:   10.32.0.0/12
          _isIpWithinSubnet=$( ipcalc $_ipTocheck/$_cidr2 | sed -En "s/^(.*)(Network:\s+)([0-9]{1}[0-9]?[0-9]?\.[0-9]{1}[0-9]?[0-9]?\.[0-9]{1}[0-9]?[0-9]?\.[0-9]{1}[0-9]?[0-9]?)(\/[0-9]{1}[0-9]{1}.*)?/\3/p" )
          if [[ "$_isIpWithinSubnet/$_cidr2" == "$_subnet" && "$_portTocheck" == "$_MyappPrometheusPort" ]]; then
              echo "IP managed by K8s will be deleted: _isIpWithinSubnet: ($_ip) $_isIpWithinSubnet"
          else
              _finalIpsPortArray+=("$_ip")
          fi
      done
    
    
    
      #######################################################################################################################################################
      #This is an array of the current running myapp App containers with a prometheus port that is available.
      #From this list we will add them to the prometheus file to be available for Grafana monitoring.
      readarray -t _currentK8sIpsArr < <( kubectl get pods --all-namespaces --chunk-size=0 -o json | jq '.items[] | select(.spec.containers[].ports != null) | select(.spec.containers[].ports[].containerPort == '$_MyappPrometheusPort' ) | .status.podIP' )
      for index in "${!_currentK8sIpsArr[@]}"
      do
          _addIPToMonitoring=${_currentK8sIpsArr[index]//\"/$''}
          echo "IP Managed by K8s as myapp app with prometheus currently running will be added to monitoring: $_addIPToMonitoring"
          _finalIpsPortArray+=("$_addIPToMonitoring:$_MyappPrometheusPort")
      done
    
    
    
      ######################################################################################################################################################
      #we need to recreate this string and sed it into the file
      #- targets: ['192.168.2.13:3201', '192.168.2.13:3202', '10.32.0.7:8055', '10.32.0.8:8055']
    
      _finalPrometheusTargetString="- targets: ["
      i=0
    
      # Iterate the loop to read and print each array element
      for index in "${!_finalIpsPortArray[@]}"
      do
          ((i=i+1))
          _finalPrometheusTargetString="$_finalPrometheusTargetString '${_finalIpsPortArray[index]}'"
          if [[ $i != ${#_finalIpsPortArray[@]}  ]]; then
               _finalPrometheusTargetString="$_finalPrometheusTargetString,"
          fi
      done
    
      _finalPrometheusTargetString="$_finalPrometheusTargetString]"
    
      echo "$_finalPrometheusTargetString"
    
      sed -i -E "s/(.*)-\stargets:\s\[.*\]/\1$_finalPrometheusTargetString/" ./$_prometheusyamlFile
    
      docker-compose down
      sleep 4
      docker-compose up -d
    
      echo "All changes were made. Exiting"
    
      exit 0