Kubernetes 部署动态端口转发

Kubernetes Deployment dynamic port forwarding

我正在将 Docker 映像从 Docker 移动到 K8s 部署。我有自动缩放规则,所以它从 5 开始,但可以到 12。K8s 上的 Docker 图像完美地开始,前面有一个 k8s 服务来集群部署。

现在每个容器都有自己的 JVM,其中有一个 Prometheus 应用程序可以检索其统计信息。在 Docker 中,这没有问题,因为提供 Prometheus 信息的端口是动态创建的,起始端口为 8000,因此 docker-compose.yml 会根据端口数量增加 1图片已启动。

问题是我无法在 K8s [deployment].yml 文件中找到如何执行此操作。因为 Deployment pods 是动态的,我原以为会有一些方法可以根据启动的容器数量来设置起始 HOST 端口。

也许我看错了,所以任何澄清都会有所帮助,同时我会继续在 Google 中搜索有关此类事情的任何信息。

理想情况下,您应该对所有副本使用 JVM 的平均值。如果您是 运行 单个 相同的 Docker 图像 ,那么使用不同的 端口 创建不同的部署是没有意义的在所有 副本中

我认为将资源需求设置为部署的单个部署是最佳实践。

您可以获得所有 运行 副本的 JVM 平均值

sum(jvm_memory_max_bytes{area="heap", app="app-name",job="my-job"}) / sum(kube_pod_status_phase{phase="Running"})

因为你是 运行 所有副本和 K8s 服务的相同 Docker 映像默认情况下将管理负载平衡,平均利用率将是一个监控选项。

不过,如果您想过滤并获得不同的值,您可以创建不同的 deployments(这不是很好的方法)或使用 stateful sets.

您还可以在 Prometheus 中通过 主机名(POD 名称) 过滤数据,这样会得到每个副本的使用情况。

好吧,在读了又读又读了这么多之后我得出的结论是 K8s 不负责为 Docker 图像打开端口或在一些奇怪的端口上为您的应用程序提供入口,这不是它的责任. K8s 部署只是部署您请求的 Pods。您可以在 DEPLOYMENT -> SPEC -> CONTAINERS -> PORTS 上设置 Ports 选项,就像 Docker 一样只是提供信息。但这允许您使用可用的 Prometheus 端口对所有 PODS(容器)进行 JSONPath 查询。这将允许您重建 Prometheus.yaml 文件中的“目标”值。现在有了这些目标,Grafana 就可以使用它们来创建仪表板。

就是这样,非常简单。我把事情复杂化了,因为我不明白。我附上了一个我快速编写的脚本,让您自行承担使用风险。

顺便说一句,我交替使用Pod和Container。

  #!/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)(.*)?//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\[)(.*)(\]).*//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}.*)?//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\[.*\]/$_finalPrometheusTargetString/" ./$_prometheusyamlFile

  docker-compose down
  sleep 4
  docker-compose up -d

  echo "All changes were made. Exiting"

  exit 0