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

AWS ACM support for GRPC protocol as backend #12795

Open
Laveshsp opened this issue Feb 4, 2025 · 5 comments
Open

AWS ACM support for GRPC protocol as backend #12795

Laveshsp opened this issue Feb 4, 2025 · 5 comments
Assignees
Labels
needs-kind Indicates a PR lacks a `kind/foo` label and requires one. needs-priority needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one.

Comments

@Laveshsp
Copy link

Laveshsp commented Feb 4, 2025

What happened:

I have a Thanos sidecar pod exposed on GRPC protocol. So, I want to create an nginx ingress for GRPC backend protocol with ingress controller load balancer service using AWS NLB having AWS ACM configured to it. With this in place, I wanted the requests to go flow smoothly but I see errors in ingress controller logs without any info which I can act on and troubleshoot.
Below are few manifest files

  1. ingress controller load balancer service manifest
apiVersion: v1
kind: Service
metadata:
  annotations:
    meta.helm.sh/release-name: ingress-nginx
    meta.helm.sh/release-namespace: ingress
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: ssl
    service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "3600"
    service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "false"
    service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: '*'
    service.beta.kubernetes.io/aws-load-balancer-scheme: internal
    service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:us-west-2:934411234492:certificate/aa2cf1bd-7810-4f44-97af-9fb6ff0fb8f0
    service.beta.kubernetes.io/aws-load-balancer-ssl-negotiation-policy: ELBSecurityPolicy-TLS13-1-2-2021-06
    service.beta.kubernetes.io/aws-load-balancer-ssl-ports: https
    service.beta.kubernetes.io/aws-load-balancer-target-group-attributes: proxy_protocol_v2.enabled=true
    service.beta.kubernetes.io/aws-load-balancer-type: nlb
  creationTimestamp: "2023-09-19T23:03:22Z"
  finalizers:
  - service.k8s.aws/resources
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.9.3
    helm.sh/chart: ingress-nginx-4.8.2
  name: ingress-nginx-controller
  namespace: ingress
  resourceVersion: "380575858"
  uid: 31c57612-0c19-465b-a17e-e5fc70ad0b6b
spec:
  allocateLoadBalancerNodePorts: true
  clusterIP: 172.20.171.242
  clusterIPs:
  - 172.20.171.242
  externalTrafficPolicy: Cluster
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  loadBalancerClass: service.k8s.aws/nlb
  loadBalancerSourceRanges:
  - 10.0.0.0/8
  ports:
  - name: http
    nodePort: 30353
    port: 80
    protocol: TCP
    targetPort: http
  - name: https
    nodePort: 31181
    port: 443
    protocol: TCP
    targetPort: https
  selector:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
  sessionAffinity: None
  type: LoadBalancer
  1. GRPC Ingress configuration is as below
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    meta.helm.sh/release-name: kube-prometheus-stack
    meta.helm.sh/release-namespace: prometheus
    nginx.ingress.kubernetes.io/backend-protocol: GRPC
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/grpc-backend: "true"
    nginx.ingress.kubernetes.io/modsecurity-snippet: |
      SecRule REQUEST_HEADERS:Content-Type "@contains application/grpc" "id:100001,phase:1,pass,t:none,nolog,ctl:ruleRemoveById=920420"
    nginx.ingress.kubernetes.io/protocol: h2c
    nginx.ingress.kubernetes.io/proxy-read-timeout: "160"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
  labels:
    app: kube-prometheus-stack-prometheus
    app.kubernetes.io/instance: kube-prometheus-stack
  name: thanos-sidecar-nlb
  namespace: prometheus
spec:
  ingressClassName: nginx
  rules:
    - host: prometheus.pssbx.test.cloud
      http:
        paths:
        - backend:
            service:
              name: kube-prometheus-stack-prometheus
              port:
                number: 10901
          path: /
          pathType: Prefix

What you expected to happen:

I expected that metrics get exported to Thanos sidecar as expected and no connectivity issue. But I see the nginx ingress controller giving below error logs

 2025/02/04 12:45:22 [error] 2017#2017: *886728 broken header: "" while reading PROXY protocol, client: 10.151.144.23, server: 0.0.0.0:443                                                                                              │
│ {"timestamp": "2025-02-04T12:45:25+00:00", "requestID": "8b3ec8a4ce11a483c3bf253bb1d95be8", "proxyUpstreamName": "", "proxyAlternativeUpstreamName": "","upstreamStatus": , "upstreamAddr": "", "httpRequest": {"requestMethod": "", " │
│ requestUrl": "_", "status": 400,"requestSize": 0, "responseSize": , "userAgent": "", "remoteIp": "10.151.144.139", "referer": "", "latency": " s", "protocol": ""}}                                                                    │
│ {"timestamp": "2025-02-04T12:45:25+00:00", "requestID": "3ef754ed07fe9d46aeeb19cbcef11933", "proxyUpstreamName": "", "proxyAlternativeUpstreamName": "","upstreamStatus": , "upstreamAddr": "", "httpRequest": {"requestMethod": "", " │
│ requestUrl": "_", "status": 400,"requestSize": 0, "responseSize": , "userAgent": "", "remoteIp": "10.135.64.111", "referer": "", "latency": " s", "protocol": ""}}                                                                     │
│ 2025/02/04 12:45:26 [error] 2016#2016: *886835 broken header: "" while reading PROXY protocol, client: 10.151.146.6, server: 0.0.0.0:443                                                                                               │
│ 2025/02/04 12:45:26 [error] 2016#2016: *886836 broken header: "" while reading PROXY protocol, client: 10.135.70.167, server: 0.0.0.0:443                                                                                              │
│ {"timestamp": "2025-02-04T12:45:26+00:00", "requestID": "97801dd895e5c5e976a6670f9ad938be", "proxyUpstreamName": "", "proxyAlternativeUpstreamName": "","upstreamStatus": , "upstreamAddr": "", "httpRequest": {"requestMethod": "", " │
│ requestUrl": "_", "status": 400,"requestSize": 0, "responseSize": , "userAgent": "", "remoteIp": "10.135.67.90", "referer": "", "latency": " s", "protocol": ""}}                                                                      │
│ 2025/02/04 12:45:27 [error] 2017#2017: *886864 broken header: "" while reading PROXY protocol, client: 10.151.144.13, server: 0.0.0.0:443                                                                                              │
│ {"timestamp": "2025-02-04T12:45:27+00:00", "requestID": "b49da2bddb0004b5c2cd9cdfbceda7a8", "proxyUpstreamName": "", "proxyAlternativeUpstreamName": "","upstreamStatus": , "upstreamAddr": "", "httpRequest": {"requestMethod": "", " │
│ requestUrl": "_", "status": 400,"requestSize": 0, "responseSize": , "userAgent": "", "remoteIp": "10.135.70.115", "referer": "", "latency": " s", "protocol": ""}}                                                                     │
│ {"timestamp": "2025-02-04T12:45:30+00:00", "requestID": "5dca7941af0dd3c64cd0db377784c9a7", "proxyUpstreamName": "", "proxyAlternativeUpstreamName": "","upstreamStatus": , "upstreamAddr": "", "httpRequest": {"requestMethod": "", " │
│ requestUrl": "_", "status": 400,"requestSize": 0, "responseSize": , "userAgent": "", "remoteIp": "10.151.146.79", "referer": "", "latency": " s", "protocol": ""}}                                                                     │
│ {"timestamp": "2025-02-04T12:45:31+00:00", "requestID": "1b231196fdfed70cb39cdf4db508b3a7", "proxyUpstreamName": "", "proxyAlternativeUpstreamName": "","upstreamStatus": , "upstreamAddr": "", "httpRequest": {"requestMethod": "", " │
│ requestUrl": "_", "status": 400,"requestSize": 0, "responseSize": , "userAgent": "", "remoteIp": "10.135.64.173", "referer": "", "latency": " s", "protocol": ""}}                                                                     │
│ 2025/02/04 12:45:31 [error] 2026#2026: *887009 broken header: "" while reading PROXY protocol, client: 10.135.68.50, server: 0.0.0.0:443                                                                                               │
│ {"timestamp": "2025-02-04T12:45:33+00:00", "requestID": "4a2575239a99bea786474131e300253f", "proxyUpstreamName": "", "proxyAlternativeUpstreamName": "","upstreamStatus": , "upstreamAddr": "", "httpRequest": {"requestMethod": "", " │
│ requestUrl": "_", "status": 400,"requestSize": 0, "responseSize": , "userAgent": "", "remoteIp": "10.135.70.167", "referer": "", "latency": " s", "protocol": ""}}                                                                     │
│ 2025/02/04 12:45:33 [error] 2016#2016: *887064 broken header: "" while reading PROXY protocol, client: 10.135.67.48, server: 0.0.0.0:443                                                                                               │
│ 2025/02/04 12:45:34 [error] 2026#2026: *887096 broken header: "" while reading PROXY protocol, client: 10.151.147.96, server: 0.0.0.0:443                                                                                              │
│ {"timestamp": "2025-02-04T12:45:35+00:00", "requestID": "c4789c83e00c9168398b218844839701", "proxyUpstreamName": "", "proxyAlternativeUpstreamName": "","upstreamStatus": , "upstreamAddr": "", "httpRequest": {"requestMethod": "", " │
│ requestUrl": "_", "status": 400,"requestSize": 0, "responseSize": , "userAgent": "", "remoteIp": "10.135.67.204", "referer": "", "latency": " s", "protocol": ""}}                                                                     │
│ {"timestamp": "2025-02-04T12:45:37+00:00", "requestID": "339892e7556505129356f576109bf8e4", "proxyUpstreamName": "", "proxyAlternativeUpstreamName": "","upstreamStatus": , "upstreamAddr": "", "httpRequest": {"requestMethod": "", " │
│ requestUrl": "_", "status": 400,"requestSize": 0, "responseSize": , "userAgent": "", "remoteIp": "10.135.68.101", "referer": "", "latency": " s", "protocol": ""}}                                                                     │
│ {"timestamp": "2025-02-04T12:45:37+00:00", "requestID": "43bd50da92ea14fcf44591ea17e2bb65", "proxyUpstreamName": "", "proxyAlternativeUpstreamName": "","upstreamStatus": , "upstreamAddr": "", "httpRequest": {"requestMethod": "", " │
│ requestUrl": "_", "status": 400,"requestSize": 0, "responseSize": , "userAgent": "", "remoteIp": "10.151.145.10", "referer": "", "latency": " s", "protocol": ""}}                                                                     │
│ 2025/02/04 12:45:37 [error] 2017#2017: *887172 broken header: "" while reading PROXY protocol, client: 10.135.64.245, server: 0.0.0.0:443                                                                                              │
│ 2025/02/04 12:45:38 [error] 2016#2016: *887195 broken header: "" while reading PROXY protocol, client: 10.135.66.42, server: 0.0.0.0:443

So, I want to know how can I achieve this wherein I need to use AWS ACM Certs which is a requirement in my case and also use the nginx ingress.

NGINX Ingress controller version: 1.9.3

Kubernetes version (use kubectl version): 1.30

Environment:

  • Cloud provider or hardware configuration: AWS EKS 1.30

  • How was the ingress-nginx-controller installed:

    • If helm was used then please show output of helm ls -A | grep -i ingress: ingress-nginx ingress 36 2024-11-04 11:53:23.847501744 +0000 UTC deployed ingress-nginx-4.8.2 1.9.3

    • If helm was used then please show output of helm -n <ingresscontrollernamespace> get values <helmreleasename>

USER-SUPPLIED VALUES:
clusterName: SHARED-CUSTOMER-DEV-CL
controller:
allowSnippetAnnotations: true
autoscaling:
enabled: true
maxReplicas: 2
config:
enable-modsecurity: true
enable-real-ip: true
enable-underscores-in-headers: true
http-snippet: 'more_set_headers "X-ModSecurity: enabled";'
log-format-escape-json: true
log-format-upstream: '{"timestamp": "$time_iso8601", "requestID": "$req_id", "proxyUpstreamName":
"$proxy_upstream_name", "proxyAlternativeUpstreamName": "$proxy_alternative_upstream_name","upstreamStatus":
$upstream_status, "upstreamAddr": "$upstream_addr", "httpRequest": {"requestMethod":
"$request_method", "requestUrl": "$host$request_uri", "status": $status,"requestSize":
$request_length, "responseSize": $upstream_response_length, "userAgent": "$http_user_agent",
"remoteIp": "$remote_addr", "referer": "$http_referer", "latency": "$upstream_response_time
s", "protocol": "$server_protocol"}}'
modsecurity-snippet: |
# this enables the default OWASP Core Rule Set
Include /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf

  # Enable prevention mode. Options: DetectionOnly On Off (default is DetectionOnly)
  SecRuleEngine On

  # Enable scanning of the request body
  SecRequestBodyAccess On

  # Reject if larger (we could also let it pass with ProcessPartial)
  SecRequestBodyLimitAction Reject

  # Send ModSecurity audit logs to the stdout (only for rejected requests)
  SecAuditLog /dev/stdout

  # Format the logs in JSON
  SecAuditLogFormat JSON

  # could be On/Off/RelevantOnly
  SecAuditEngine RelevantOnly
use-forwarded-headers: true
use-proxy-protocol: true

extraArgs:
default-ssl-certificate: ingress/default-tls
metrics:
enabled: true
podAnnotations:
'"prometheus.io/port"': 10254
'"prometheus.io/scrape"': true
replicaCount: 1
tolerations:

  • effect: NoSchedule
    key: mainnode
    operator: Exists

Can someone please  help me in how can I achieve this wherein I need to use AWS ACM Certs which is a requirement in my case and also use the nginx ingress.
@Laveshsp Laveshsp added the kind/bug Categorizes issue or PR as related to a bug. label Feb 4, 2025
@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.

@k8s-ci-robot k8s-ci-robot added needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. needs-priority labels Feb 4, 2025
@longwuyuan
Copy link
Contributor

/remove-kind bug
These 2 annotations are data that indicate misconfiguration (no such annotation in this controller) ;

  • nginx.ingress.kubernetes.io/grpc-backend: "true"
  • nginx.ingress.kubernetes.io/protocol: h2c

I can expose my kube-prometheus-stack's prometheus service without GRPC, and using plain old HTTPS to controller and plaintext from controller to backend

image

% k -n observability get svc
NAME                                         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
alertmanager-operated                        ClusterIP   None            <none>        9093/TCP,9094/TCP,9094/UDP   28h
prometheus-operated                          ClusterIP   None            <none>        9090/TCP                     28h
prometheusgrafana                            ClusterIP   10.96.89.16     <none>        80/TCP                       28h
prometheusgrafana-kube-pro-alertmanager      ClusterIP   10.96.95.90     <none>        9093/TCP,8080/TCP            28h
prometheusgrafana-kube-pro-operator          ClusterIP   10.96.48.171    <none>        443/TCP                      28h
prometheusgrafana-kube-pro-prometheus        ClusterIP   10.96.165.190   <none>        9090/TCP,8080/TCP            28h
prometheusgrafana-kube-state-metrics         ClusterIP   10.96.186.138   <none>        8080/TCP                     28h
prometheusgrafana-prometheus-node-exporter   ClusterIP   10.96.83.91     <none>        9100/TCP                     28h
% k -n observability create ing prometheus --class nginx --rule prometheus.dev.enjoydevops.com/"*"=prometheusgrafana-kube-pro-prometheus:9090,tls
ingress.networking.k8s.io/prometheus created
% k get ing -A
NAMESPACE       NAME         CLASS   HOSTS                            ADDRESS      PORTS     AGE
observability   grafana      nginx   grafana.dev.enjoydevops.com      172.18.0.2   80, 443   28h
observability   prometheus   nginx   prometheus.dev.enjoydevops.com                80, 443   12s
[~/Documents/mypython/myudemybootcamp/milestone1project] 
% k -n observability describe ing prometheus 
Name:             prometheus
Labels:           <none>
Namespace:        observability
Address:          172.18.0.2
Ingress Class:    nginx
Default backend:  <default>
TLS:
  SNI routes prometheus.dev.enjoydevops.com
Rules:
  Host                            Path  Backends
  ----                            ----  --------
  prometheus.dev.enjoydevops.com  
                                  /   prometheusgrafana-kube-pro-prometheus:9090 (10.244.0.11:9090)
Annotations:                      <none>
Events:
  Type    Reason  Age                   From                      Message
  ----    ------  ----                  ----                      -------
  Normal  Sync    2m3s (x2 over 2m45s)  nginx-ingress-controller  Scheduled for sync
[~/Documents/mypython/myudemybootcamp/milestone1project] 

@k8s-ci-robot k8s-ci-robot added needs-kind Indicates a PR lacks a `kind/foo` label and requires one. and removed kind/bug Categorizes issue or PR as related to a bug. labels Feb 4, 2025
@Laveshsp
Copy link
Author

Laveshsp commented Feb 4, 2025

Hey @longwuyuan ,

I'm trying to reach out to Thanos Sidecar exposed over gRPC protocol so that it can then ship metrics to Thanos store. So, I believe I need to use gRPC here.

Also, I tried to remove these two annotations too but the same error in ingress controller pod
nginx.ingress.kubernetes.io/grpc-backend: "true"
nginx.ingress.kubernetes.io/protocol: h2c

@longwuyuan
Copy link
Contributor

longwuyuan commented Feb 4, 2025 via email

@strongjz strongjz self-assigned this Feb 13, 2025
@longwuyuan
Copy link
Contributor

We discussed this yesterday in the community meeting but could not conclude much.
My opinion is this ;

  • Manifest is useless
  • State is required so post outputs of kubectl describe
  • Post screenshot of NLB proxy-protocol config
  • Remove these 2
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: ssl
    service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "3600"
  • Remove these
   nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/grpc-backend: "true"
    nginx.ingress.kubernetes.io/modsecurity-snippet: |
      SecRule REQUEST_HEADERS:Content-Type "@contains application/grpc" "id:100001,phase:1,pass,t:none,nolog,ctl:ruleRemoveById=920420"
    nginx.ingress.kubernetes.io/protocol: h2c
    nginx.ingress.kubernetes.io/proxy-read-timeout: "160"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
  • Send grpcurl request to hostname prometheus.pssbx.test.cloud and show the logs

There is one factor you are not understanding that when you use AWS ACM cert, then the termination of TLS is on the NLB and not on the controller.

That means your installation of the controller needs to use the NLB-TEERMINATION related documentation to install the ingress-nginx controller https://kubernetes.github.io/ingress-nginx/deploy/#tls-termination-in-aws-load-balancer-nlb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs-kind Indicates a PR lacks a `kind/foo` label and requires one. needs-priority needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one.
Projects
Development

No branches or pull requests

4 participants