I'm trying to replicate what we have set up in our bare-metal infrastructure using AWS. I'm admittedly not well-versed with K8S, but a colleague of mine had started to use it in AWS so I've been piggybacking on some of the work he's done. He's been able to answer most of my questions, but this one seems to have us a little stumped.
In our bare-metal setup, there are about 20k unique sites with individual SSL certificates. In doing a small scale test with a few sites and certs, it works. However, at full scale, it does not.
I was able to script importing the certificates into K8S and create a voyager ingress configuration yaml file from it, but when I try to apply it, I get the following error message:
bash-5.0# kubectl apply -f generated-ingress.yaml
The Ingress "generated-ingress" is invalid: metadata.annotations: Too long: must have at most 262144 characters
It seems that the ingress configuration is too large.
The generated ingress looks something like this:
---
apiVersion: voyager.appscode.com/v1beta1
kind: Ingress
metadata:
name: generated-ingress
namespace: default
spec:
tls:
- secretName: ssl-cert-eample-domain.com
hosts:
- example-domain.com
# Repeated for each domain using SSL
rules:
- host: '*'
http:
paths:
- backend:
serviceName: the-backend
servicePort: '80'
- host: example-domain.com
http:
paths:
- backend:
serviceName: the-backend
servicePort: '80'
headerRules:
- X-HTTPS YES
# Repeated for each domain using SSL
FYI the X-HTTPS
header is needed for our backend to generate absolute urls correctly using https
instead of http
. It would be nice if this could be specified for all SSL connections instead of having to specify it for each individual domain, making the configuration more lean.
In any case, is there a way to increase the limit for the configuration? Or is there a better way to configure the ingress for numerous SSL certificates?
I believe you are getting bitten by kubectl
trying to record the previous state of affairs in an {"metadata":{"annotation":{"kubectl.kubernetes.io/last-applied-configuration": "GINORMOUS string"}}}
as described here. It's not the Ingress
itself that is causing you problems.
In your case, because the input object is so big, I believe you will have to use kubectl replace
instead of apply
, since (a) you appear to have the whole declaration in-hand anyway (b) I don't think kubectl replace
tries to capture that annotation unless one explicitly provides --save-config=true
to replace
Separate from your question, if you are not already aware, one need not declare every single Ingress
in one resource -- it is much, much, much, much, much easier to manage and reason about Ingress
resources when they are distinct
So your config of:
apiVersion: voyager.appscode.com/v1beta1
kind: Ingress
metadata:
name: generated-ingress
namespace: default
spec:
tls:
- secretName: ssl-cert-eample-domain.com
hosts:
- example-domain.com
# Repeated for each domain using SSL
rules:
- host: '*'
http:
paths:
- backend:
serviceName: the-backend
servicePort: '80'
- host: example-domain.com
http:
paths:
- backend:
serviceName: the-backend
servicePort: '80'
headerRules:
- X-HTTPS YES
would become:
apiVersion: voyager.appscode.com/v1beta1
kind: Ingress
metadata:
name: star-domain
namespace: default
spec:
rules:
- host: '*'
http:
paths:
- backend:
serviceName: the-backend
servicePort: '80'
and then repeat this structure for every one of the domains:
apiVersion: voyager.appscode.com/v1beta1
kind: Ingress
metadata:
name: example-domain
namespace: default
spec:
tls:
- secretName: ssl-cert-example-domain.com
hosts:
- example-domain.com
rules:
- host: example-domain.com
http:
paths:
- backend:
serviceName: the-backend
servicePort: '80'
headerRules:
- X-HTTPS YES
it's also redundantly redundant to put ingress
in the metadata: name:
of an Ingress
resource, as when one is typing its name you will need to say kubectl describe ingress/generated-ingress