ArgoCD GRPCRoute for CLI Auth with Cilium GatewayAPI
Notice: All following words with their typos and incoherent train of thought has been written without AI assistance. LLMs have been used in troubleshooting process of the issue described in this post
I love ArgoCD UI but iterative deployment and troubleshooting can be a pain in the ass so having CLI access so I had to take a detour and setup CLI access.
I’ve been using GatewayAPI ever since I setup Cilium in my homelab cluster. Gladly so, I avoided migrating from nginx-ingress which has abruptly been deprecated.
However, GatewayAPI support in Cillium is kind of barebones. No annotations, no hackery allowed. Cilium strives to implement GatewayAPI to the spec and if the spec is lacking - they want to extend it. It’s a noble cause and we’re yet to see how coding to abstraction pans out in the end.
Routes
GatewayAPI splits Gateways - which are setup by infra engineers, and (HTTP,TLS,GRPC-)Routes - which are setup by application developers. ArgoCD API is native gRPC, so CLI is communicating with the API in gRPC - unless —grpc-web is supplied.
However, --grpc-web flag did not end up working for me. I am not sure why, it could be because of the Envoy proxy that implements gatewayAPI in Cilium - and potentially because of grpc_web filter on Envoy.
ArgoCD docs for --grpc-web stipulates:
--grpc-web Enables gRPC-web protocol. Useful if Argo CD server is behind proxy which does not support HTTP2.
In theory, that should wrap API call in HTTP/1.0 before it reaches the gateway. On the gateway, though, seems Envoy is translating grpc_web calls and they don’t end up reaching the back-end if only HTTPRoute is configured. The documentation is sparse on the exact mechanism.
Setting up GRPCRoute with a different prefix
So we need to setup GRPCRoute. However, if routes are listening on the same endpoint they will conflict with HTTPRoute. One option is to define a separate route - eg grpc.argocd.<domain>.
I have not tested this.
Setting up GRPCRoute with filtering
Some folks at argocd project on Github created a PR to address the docs on setting up GRPCRoute’s. This was the exact solution I needed.
This configures both HTTPRoute and GRPCRoute on the same hostname with a tweak - GRPCRoute filters requests based on headers and only matches if Content-Type is ^application/grpc.*$.
This explains why LLMs were useless when troubleshooting this issue. This hasn’t landed in the training set yet!
A wrap
TLDR: Create a GRPCRoute on the same hostname as your HTTPRoute ArgoCD with the filter.
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
name: argocd-grpc-route
namespace: argocd
spec:
parentRefs:
- name: cluster-gateway
namespace: gateway
hostnames:
- "argocd.local.example.com"
rules:
- backendRefs:
- name: argocd-server
port: 443
matches:
- headers:
- name: Content-Type
type: RegularExpression
value: "^application/grpc.*$"