Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unstable connection when using "-tcp" suffix in targetPort with Helm chart #11603

Open
a1expol opened this issue Jul 11, 2024 · 17 comments
Open
Labels
kind/support Categorizes issue or PR as a support question. lifecycle/frozen Indicates that an issue or PR should not be auto-closed due to staleness. needs-priority needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one.

Comments

@a1expol
Copy link

a1expol commented Jul 11, 2024

Title: Unstable Redis Connection When Using "-tcp" Suffix in targetPort with Helm chart

What happened:

While deploying Redis through Helm chart and specifying the targetPort with a "-tcp" suffix (e.g. "6379-tcp"), I'm experiencing unstable connections to Redis. The connections frequently drop and are lost.

What you expected to happen:

I expect a reliably stable connection to Redis even when using the "-tcp" suffix. I suspect that this instability may be related to how the ingress configuration or Helm chart is handling this suffix.

NGINX Ingress controller version: 1.8.0

Kubernetes version (run kubectl version):
Client Version: v1.29.2
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.29.5-gke.1091000

Environment:

  • Cloud provider or hardware configuration: Google Cloud Platform, GKE cluster
  • OS (e.g. from /etc/os-release): Ubuntu 20.04.6 LTS
  • Kernel (e.g. uname -a): Linux

How was the ingress-nginx-controller installed:
Helm Chart.

ingress-test               default 15              2024-07-11 11:30:07.167762801 +0300 EEST        deployed          ingress-nginx-4.7.0                     1.8.0
USER-SUPPLIED VALUES:
controller:
  containerPort:
    redis-dev: 6379
    redis-prod: 6380
  ingressClass: research-nginx
  ingressClassResource:
    controllerValue: k8s.io/research-ingress-nginx
    name: research-nginx
  publishService:
    enabled: true
  service:
    internal:
      nodePorts:
        tcp:
        - 31100
        - 31101
    loadBalancerSourceRanges:
    - xxx.xxx.xxx.xxx/xx
    type: LoadBalancer
tcp:
  "6379": default/redis-stack-server-dev:6379
  "6380": default/redis-stack-server-prod:6380

Current State of the controller:
Ingress controller is functional, but the traffic on port 6379 is being handled incorrectly.

Name: research-nginx
Labels: app.kubernetes.io/component=controller
app.kubernetes.io/instance=ingress-test
app.kubernetes.io/managed-by=Helm
app.kubernetes.io/name=ingress-nginx
app.kubernetes.io/part-of=ingress-nginx
app.kubernetes.io/version=1.8.0
helm.sh/chart=ingress-nginx-4.7.0
Annotations: meta.helm.sh/release-name: ingress-test
meta.helm.sh/release-namespace: default
Controller: k8s.io/research-ingress-nginx
Events:

Name:             ingress-test-ingress-nginx-controller-985dbdcj4nhh
Namespace:        default
Priority:         0
Service Account:  ingress-test-ingress-nginx
Node:             gke-common-t4-node-po-53125293-9gw8/10.100.0.38
Start Time:       Wed, 10 Jul 2024 17:39:04 +0300
Labels:           app.kubernetes.io/component=controller
                  app.kubernetes.io/instance=ingress-test
                  app.kubernetes.io/managed-by=Helm
                  app.kubernetes.io/name=ingress-nginx
                  app.kubernetes.io/part-of=ingress-nginx
                  app.kubernetes.io/version=1.8.0
                  helm.sh/chart=ingress-nginx-4.7.0
                  pod-template-hash=985dbdc74
Annotations:      cni.projectcalico.org/containerID: 04d5736e5a6e97eca16b21c05bad032f4db0be89aa236728ef3845e1f42cc2a8
                  cni.projectcalico.org/podIP: 10.48.3.249/32
                  cni.projectcalico.org/podIPs: 10.48.3.249/32
Status:           Running
IP:               10.48.3.249
IPs:
  IP:           10.48.3.249
Controlled By:  ReplicaSet/ingress-test-ingress-nginx-controller-985dbdc74
Containers:
  controller:
    Container ID:  containerd://a617fa6b84112609ac290b58459de2c977c3929cf8cef30c669077181f88533c
    Image:         registry.k8s.io/ingress-nginx/controller:v1.8.0@sha256:744ae2afd433a395eeb13dc03d3313facba92e96ad71d9feaafc85925493fee3
    Image ID:      registry.k8s.io/ingress-nginx/controller@sha256:744ae2afd433a395eeb13dc03d3313facba92e96ad71d9feaafc85925493fee3
    Ports:         80/TCP, 443/TCP, 6379/TCP, 6380/TCP, 8443/TCP
    Host Ports:    0/TCP, 0/TCP, 6379/TCP, 0/TCP, 0/TCP
    Args:
      /nginx-ingress-controller
      --publish-service=$(POD_NAMESPACE)/ingress-test-ingress-nginx-controller
      --election-id=ingress-test-ingress-nginx-leader
      --controller-class=k8s.io/research-ingress-nginx
      --ingress-class=research-nginx
      --configmap=$(POD_NAMESPACE)/ingress-test-ingress-nginx-controller
      --tcp-services-configmap=$(POD_NAMESPACE)/ingress-test-ingress-nginx-tcp
      --validating-webhook=:8443
      --validating-webhook-certificate=/usr/local/certificates/cert
      --validating-webhook-key=/usr/local/certificates/key
      --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
    State:          Running
      Started:      Wed, 10 Jul 2024 17:39:05 +0300
    Ready:          True
    Restart Count:  0
    Requests:
      cpu:      100m
      memory:   90Mi
    Liveness:   http-get http://:10254/healthz delay=10s timeout=1s period=10s #success=1 #failure=5
    Readiness:  http-get http://:10254/healthz delay=10s timeout=1s period=10s #success=1 #failure=3
    Environment:
      POD_NAME:      ingress-test-ingress-nginx-controller-985dbdcj4nhh (v1:metadata.name)
      POD_NAMESPACE:  default (v1:metadata.namespace)
      LD_PRELOAD:     /usr/local/lib/libmimalloc.so
    Mounts:
      /usr/local/certificates/ from webhook-cert (ro)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-9w7vm (ro)
Conditions:
  Type                        Status
  PodReadyToStartContainers   True
  Initialized                 True
  Ready                       True
  ContainersReady             True
  PodScheduled                True
Volumes:
  webhook-cert:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  ingress-test-ingress-nginx-admission
    Optional:    false
  kube-api-access-9w7vm:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   Burstable
Node-Selectors:              kubernetes.io/os=linux
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:                      <none>
Name:                        ingress-test-ingress-nginx-controller
Namespace:                   default
Labels:                      app.kubernetes.io/component=controller
                             app.kubernetes.io/instance=ingress-test
                             app.kubernetes.io/managed-by=Helm
                             app.kubernetes.io/name=ingress-nginx
                             app.kubernetes.io/part-of=ingress-nginx
                             app.kubernetes.io/version=1.8.0
                             helm.sh/chart=ingress-nginx-4.7.0
Annotations:                 meta.helm.sh/release-name: ingress-test
                             meta.helm.sh/release-namespace: default
Selector:                    app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-test,app.kubernetes.io/name=ingress-nginx
Type:                        LoadBalancer
IP Family Policy:            SingleStack
IP Families:                 IPv4
IP:                          10.52.8.129
IPs:                         10.52.8.129
LoadBalancer Ingress:        34.31.132.131
Port:                        http  80/TCP
TargetPort:                  http/TCP
NodePort:                    http  31388/TCP
Endpoints:                   10.48.3.249:80
Port:                        https  443/TCP
TargetPort:                  https/TCP
NodePort:                    https  32016/TCP
Endpoints:                   10.48.3.249:443
Port:                        6379-tcp  6379/TCP
TargetPort:                  6379-tcp/TCP
NodePort:                    6379-tcp  31100/TCP
Endpoints:
Port:                        6380-tcp  6380/TCP
TargetPort:                  6380-tcp/TCP
NodePort:                    6380-tcp  31024/TCP
Endpoints:                   10.48.3.249:6380
Session Affinity:            None
External Traffic Policy:     Cluster
LoadBalancer Source Ranges:  xxx.xxx.xxx.xxx/xx
Events:                      <none>

Current state of ingress object, if applicable:

Name:             redis-stack-server-dev
Labels:           app=redis-stack-server-dev
                  app.kubernetes.io/managed-by=Helm
Namespace:        default
Address:          34.31.132.131
Ingress Class:    research-nginx
Default backend:  <default>
TLS:
  redis-dev-tls terminates my-redis.domain.name
Rules:
  Host                        Path  Backends
  ----                        ----  --------
  my-redis.domain.name
                              /   redis-stack-server-dev:6379 (<none>)
Annotations:                  cert-manager.io/cluster-issuer: acme-devops-delivery
                              kubernetes.io/ingress.class: research-nginx
                              meta.helm.sh/release-name: redis-dev
                              meta.helm.sh/release-namespace: default
                              nginx.ingress.kubernetes.io/proxy-buffering: off
                              nginx.ingress.kubernetes.io/proxy-read-timeout: 86400
                              nginx.ingress.kubernetes.io/proxy-send-timeout: 86400
                              nginx.ingress.kubernetes.io/ssl-passthrough: true
                              nginx.ingress.kubernetes.io/ssl-redirect: true
Events:                       <none>

How to reproduce this issue:
To reproduce the problem, you need to have a Kubernetes cluster with the redis-stack-server installed on port 6379. The problem is very simple to reproduce: you just need to expose port 6379 on the redis-stack-server service, port needs to be exposed through the Helm chart (it is necessary for the "-tcp" suffix to be added to the targetPort), and try to run redis-cli -h your-redis.domain.name -p 6379 from the local machine several times.

Anything else we need to know:
I would like to add that without the "-tcp" suffix the problem disappears and the service responds consistently. But with this suffix, the connection becomes unstable.

$ redis-cli -h my-redis.domain.name -p 6379
Could not connect to Redis at my-redis.domain.name:6379: Connection refused
not connected>
$ redis-cli -h my-redis.domain.name -p 6379
my-redis.domain.name:6379>
$ redis-cli -h my-redis.domain.name -p 6379
my-redis.domain.name:6379>
$ redis-cli -h my-redis.domain.name -p 6379
Could not connect to Redis at my-redis.domain.name:6379: Connection refused
not connected>
$ redis-cli -h my-redis.domain.name -p 6379
Could not connect to Redis at my-redis.domain.name:6379: Connection refused
not connected>
@a1expol a1expol added the kind/bug Categorizes issue or PR as related to a bug. label Jul 11, 2024
@k8s-ci-robot k8s-ci-robot added the needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. label Jul 11, 2024
@k8s-ci-robot
Copy link
Contributor

This issue is currently awaiting triage.

If Ingress contributors determines this is a relevant issue, they will accept it by applying the triage/accepted label and provide further guidance.

The triage/accepted label can be added by org members by writing /triage accepted in a comment.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@longwuyuan
Copy link
Contributor

/remove-kind bug
/kind support

Delete the ingress named "redis-stack-server-dev"

@k8s-ci-robot k8s-ci-robot added kind/support Categorizes issue or PR as a support question. and removed kind/bug Categorizes issue or PR as related to a bug. labels Jul 12, 2024
@a1expol
Copy link
Author

a1expol commented Jul 16, 2024

/remove-kind bug /kind support

Delete the ingress named "redis-stack-server-dev"

But for me, the whole point is to use this ingress with the domain. If you do it manually using the example https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/exposing-tcp-udp-services.md then everything works perfectly, which is what I want to achieve through helm. But I can't understand what the -tcp suffix does in targetPort, what is its role there in general.

@longwuyuan
Copy link
Contributor

I am not clear on the question. I am wondering if you are asking that you can set a value like "6379 -tcp" to the field

% k explain service.spec.ports.targetPort
KIND:       Service
VERSION:    v1

FIELD: targetPort <IntOrString>


DESCRIPTION:
    Number or name of the port to access on the pods targeted by the service.
    Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. If
    this is a string, it will be looked up as a named port in the target Pod's
    container ports. If this is not specified, the value of the 'port' field is
    used (an identity map). This field is ignored for services with
    clusterIP=None, and should be omitted or set equal to the 'port' field. More
    info:
    https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service
    IntOrString is a type that can hold an int32 or a string.  When used in JSON
    or YAML marshalling and unmarshalling, it produces or consumes the inner
    type.  This allows you to have, for example, a JSON field that can accept a
    name or number.

@a1expol
Copy link
Author

a1expol commented Jul 16, 2024

I am not clear on the question. I am wondering if you are asking that you can set a value like "6379 -tcp" to the field

image
This suffix is ​​added independently in the template https://github.com/kubernetes/ingress-nginx/blob/a6727d81e7cd510ac5fed4bb1773f9aefefe8fbe/charts/ingress-nginx/templates/controller-service.yaml#L84C1-L85C1. I understand that this is a reference to the port name, but it is not working correctly in my case. Because of it, I can't use expose tcp service

@longwuyuan
Copy link
Contributor

Sorry, with the little I understand, it may be that I will need to helm template the chart with a value suggested by you, to a key in the values.yaml file . That will be relatvely more ambiguous when compared to directly asking you about what precise value do you desire to set to which field of which K8S object.

So can you kindly help and mention both the precise field like my example "k explain service.spec.ports.targetPort" and that what precise value you want to set to that field, in the final K8S object that is created on the cluster.

After reading all the posts here I made a guess of the field and the value and asked you that directly. So kindly help by going past all the templating and the yaml and json to apiserver etc etc, and kindly type out the precise field and the complete precise value you want to set, during a helm install.

Confused because I am not aware of any field in any K8S object where "-tcp" is a valid value (in the context of the ingress-controller I mean)

@a1expol
Copy link
Author

a1expol commented Jul 16, 2024

Sorry, with the little I understand, it may be that I will need to helm template the chart with a value suggested by you, to a key in the values.yaml file . That will be relatvely more ambiguous when compared to directly asking you about what precise value do you desire to set to which field of which K8S object.

So can you kindly help and mention both the precise field like my example "k explain service.spec.ports.targetPort" and that what precise value you want to set to that field, in the final K8S object that is created on the cluster.

After reading all the posts here I made a guess of the field and the value and asked you that directly. So kindly help by going past all the templating and the yaml and json to apiserver etc etc, and kindly type out the precise field and the complete precise value you want to set, during a helm install.

Confused because I am not aware of any field in any K8S object where "-tcp" is a valid value (in the context of the ingress-controller I mean)

If I understand you correctly, I need to change the targetPort value in line 84

targetPort: {{ if $.Values.portNamePrefix }}{{ $.Values.portNamePrefix }}-{{ end }}{{ $key }}-tcp
to
{{ (split ":" $value)._1 }}
as a reference to the service port.
How it should works:
image

Let me know if I misunderstood you. Thank you.

@longwuyuan
Copy link
Contributor

Hi,

Sorry, I am not sure what you understood as there is no clear confirmed conclusive info on what is your desired expected end-result.

Is there any chance you can name the exact name of the field. For example is this the field that you want to configure ;

service.spec.ports.targetPort

if yes, what is the real exact complete value you want to set for this field ?

@a1expol
Copy link
Author

a1expol commented Jul 16, 2024

Hi,

Sorry, I am not sure what you understood as there is no clear confirmed conclusive info on what is your desired expected end-result.

Is there any chance you can name the exact name of the field. For example is this the field that you want to configure ;

service.spec.ports.targetPort

if yes, what is the real exact complete value you want to set for this field ?

Yes, this is the field I want to configure. In the value of this field, I want to see the destination port of the service that I refer to in the "tcp" value

@longwuyuan
Copy link
Contributor

I already mentioned to you that the K8S spec for valid values is this

% k explain service.spec.ports.targetPort
KIND:       Service
VERSION:    v1

FIELD: targetPort <IntOrString>


DESCRIPTION:
    Number or name of the port to access on the pods targeted by the service.
    Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. If
    this is a string, it will be looked up as a named port in the target Pod's
    container ports. If this is not specified, the value of the 'port' field is
    used (an identity map). This field is ignored for services with
    clusterIP=None, and should be omitted or set equal to the 'port' field. More
    info:
    https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service
    IntOrString is a type that can hold an int32 or a string.  When used in JSON
    or YAML marshalling and unmarshalling, it produces or consumes the inner
    type.  This allows you to have, for example, a JSON field that can accept a
    name or number.

So if you want to put a number there, then put the number like 6379.

Its not clear to me if you want to put a name there like "6379-tcp". Or you want to put a number and also a flag there like "6379 -tcp" .

In either case, the spec field is explained by the apiserver as per my copy/paste above. It contains precise desciption of what values are valid and accepted.

@a1expol
Copy link
Author

a1expol commented Jul 17, 2024

I already mentioned to you that the K8S spec for valid values is this

% k explain service.spec.ports.targetPort
KIND:       Service
VERSION:    v1

FIELD: targetPort <IntOrString>


DESCRIPTION:
    Number or name of the port to access on the pods targeted by the service.
    Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. If
    this is a string, it will be looked up as a named port in the target Pod's
    container ports. If this is not specified, the value of the 'port' field is
    used (an identity map). This field is ignored for services with
    clusterIP=None, and should be omitted or set equal to the 'port' field. More
    info:
    https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service
    IntOrString is a type that can hold an int32 or a string.  When used in JSON
    or YAML marshalling and unmarshalling, it produces or consumes the inner
    type.  This allows you to have, for example, a JSON field that can accept a
    name or number.

So if you want to put a number there, then put the number like 6379.

Its not clear to me if you want to put a name there like "6379-tcp". Or you want to put a number and also a flag there like "6379 -tcp" .

In either case, the spec field is explained by the apiserver as per my copy/paste above. It contains precise desciption of what values are valid and accepted.

I want to set the 'service.spec.ports.targetPort' field to a numeric value (for example '6379'). The issue I'm having is that when creating the Load Balancer resource via Helm, a '-tcp' suffix is getting added on (making it '6379-tcp') which is causing my application to malfunction. I need to figure out how to prevent this '-tcp' suffix from being added when using Helm.

@longwuyuan
Copy link
Contributor

Thank you for finally providing the simple easy understandable discussion.

Redis is not HTTP or HTTPS so creating a ingress for redis is INVALID. Delete the ingress.

@a1expol
Copy link
Author

a1expol commented Jul 17, 2024

Thank you for finally providing the simple easy understandable discussion.

Redis is not HTTP or HTTPS so creating a ingress for redis is INVALID. Delete the ingress.

Understood, Redis does not use HTTP or HTTPS protocols, thus creating an Ingress for Redis is incorrect. However, when I manually expose the TCP service, everything works as presented in this repository's documentation. Therefore, I am curious as to why the Helm configuration differs from the documentation?

@longwuyuan
Copy link
Contributor

longwuyuan commented Jul 17, 2024 via email

@a1expol
Copy link
Author

a1expol commented Jul 17, 2024

Can you please explain in complete and elaborate details by what you mean
different

By 'different', I mean why is there a discrepancy between the manual TCP service exposure method outlined in the documentation and the Helm chart deployment. In the documentation, we manually specify the destination service port for the exposure in targetPort. However, in the Helm chart, this isn't specified and only the value from the 'name' parameter is duplicated. Why is that?

@longwuyuan
Copy link
Contributor

I don't understand the difference clearly.
Can you please help and copy paste the 2 different information pieces that are conflicting or different. Kindly ensure to provide links also.

Copy link

This is stale, but we won't close it automatically, just bare in mind the maintainers may be busy with other tasks and will reach your issue ASAP. If you have any question or request to prioritize this, please reach #ingress-nginx-dev on Kubernetes Slack.

@github-actions github-actions bot added the lifecycle/frozen Indicates that an issue or PR should not be auto-closed due to staleness. label Aug 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/support Categorizes issue or PR as a support question. lifecycle/frozen Indicates that an issue or PR should not be auto-closed due to staleness. needs-priority needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one.
Projects
Development

No branches or pull requests

3 participants