I have a couple of questions
When we make changes to ingress resource, are there any cases where we have to delete the resource and re-create it again or is kubectl apply -f <file_name> sufficient?
When I add the host attribute without www i.e. (my-domain.in), I am not able to access my application but with www i.e. (www.my-domain.in) it works, what's the difference?
Below is my ingress resource
When I have the host set to my-domain.in, I am unable to access my application, but when i set the host to www.my-domain.in I can access the application.
my domain is on a different provider and I have added CNAME (www) pointing to DNS name of my ALB.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: eks-learning-ingress
namespace: production
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/certificate-arn: arn:aws:a982529496:cerd878ef678df
labels:
app: eks-learning-ingress
spec:
rules:
- host: my-domain.in **does not work**
http:
paths:
- path: /*
backend:
serviceName: eks-learning-service
servicePort: 80
First answering your question 1:
When we make changes to ingress resource, are there any cases where we have to delete the resource and re-create it again or is kubectl apply -f sufficient?
In theory, yes, the kubectl apply is the correct way, either it will show ingress unchanged or ingress configured.
Other valid documented option is kubectl edit ingress INGRESS_NAME which saves and apply at the end of the edition if the output is valid.
I said theory because bugs happen, so we can't fully discard it, but bug is the worst case scenario.
Now the blurrier question 2:
When I add the host attribute without www i.e. (my-domain.in), I am not able to access my application but with www i.e. (www.my-domain.in) it works, what's the difference?
To troubleshoot it we need to isolate the processes, like in a chain we have to find which link is broken. One by one:
Endpoint > Domain Provider> Cloud Provider > Ingress > Service > Pod.
DNS Resolution (Domain Provider)
DNS Resolution (Cloud Provider)
Kubernetes Ingress (Ingress > Service > Pod)
DNS Resolution
Domain Provider:
To the Internet, who answers for my-domain.in is your Domain Provider.
What are the rules for my-domain.in and it's subdomains (like www.my-domain.in or admin.my-domain.in)?
You said "domain is on a different provider and I have added CNAME (www) pointing to DNS name of my ALB."
Are my-domain.in and my-domain.in being redirected to the ALB address instinctively?
How does it handle URL subdomains? how the request is passed on to your Cloud?
Cloud Provider:
Ok, the cloud provider is receiving the request correctly and distinctly.
Does your ALB have generic or specific rules for subdomains or path requests?
Test with another host, a different VM with a web server.
Check ALB Troubleshooting Page
Kubernetes Ingress
Usually we would start the troubleshoot from this part, but since you mentioned it works with www.my-domain.in, we can presume that your service, deployment and even ingress structure is working correctly.
You can check the Types of Ingress Docs to get a few examples of how it should work.
Bottom Line: I believe your DNS has a route for www.my-domain.in but the root domain has no route to your cloud provider that's why it's only working when you are enabling the ingress for www.
Related
I am running an ingress in GKE. I am routing most of my traffic to one backend but I wish some calls to be routed to another backend. The ingress looks something like this:
---
apiVersion: networking.k8s.io/v1
kind: Ingress
spec:
rules:
- http:
paths:
- backend:
service:
name: zone-search
port:
name: external
path: /api/v2/zones/location-search
pathType: Prefix
- http:
paths:
- backend:
service:
name: api-service
port:
name: external
path: /*
pathType: ImplementationSpecific
If I do a request like GET /api/v2/zones/location-search, it works fine.
However, if I do GET /api/v2/zones/location-search?foo=bar my request ends up in the api-service backend and not the zone-search as I expected.
I have tried using pathType: ImplementationSpecific and had both path: /api/v2/zones/location-search and path: /api/v2/zones/location-search/* but still no progress. Google requires wildcard to follow a slash but location-search is the endpoint itself and has no slash after it.
I also tried using a default backend with the same result. The problem still seems to be that the url including ?foo=bar doesn't match the path i specified.
I can't do path: /api/v2/zones/* since there are other endpoints in the api that would go to the zone-search backend that isn't supposed to.
Update
I tried using double quotes, plus removing the second
- http:
paths:
and started getting failed_to_pick_backend errors. It ended up solved by changing the health check for the backend service.
I don't know if the health check problem meant that the api-service was selected as a backup when the zone-search service was unhealthy or if one of my two changes solved my initial problem.
Name-based virtual hosts support routing HTTP traffic to multiple host names at the same IP address. You can use Ingress to reuse the load balancer for multiple domain names, subdomains, and to expose multiple services on a single IP address and load balancer. Check out the simple fanout and name-based virtual hosting examples to learn how to configure Ingress for these tasks.
Note: Always modify the properties of the Load Balancer via the Ingress object. Making changes directly on the load balancing resources might get lost or overridden by the GKE Ingress controller.
On the other hand :
Each external HTTP(S) load balancer or internal HTTP(S) load balancer uses a single URL map, which references one or more backend services. One backend service corresponds to each Service referenced by the Ingress.
Additionally, to create an Ingress that specifies rules for routing requests depending on the URL path in the request. When you create the Ingress, the GKE Ingress controller creates and configures an external HTTP(S) load balancer, see the official documentation.
I'm trying to set up GKE Gateway with an HTTPS listener using a wildcard certificate managed via Certificate Manager.
The problem I'm facing is not in provisioning of the certificate, which was done successfully following the DNS Authorization tutorial and this answer. I've successfully provisioned a wildcard certificate, which is shown by gcloud certificate-manager certificates describe <cert-name> as ACTIVE and
AUTHORIZED on both the domain and its wildcard subdomain. I've also provisioned the associated Certificate Map and Map Entry (all via Terraform) and created a global static IP address and a wildcard A record for it in Cloud DNS.
However, when I try to use this cert and address in the GKE Gateway resource, the resource gets "stuck" (never reaches SYNC phase), and there's no HTTPS GCLB provisioned as seen via gcloud or Cloud Console.
Here's the config I was trying to use for it:
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: external-https
annotations:
networking.gke.io/certmap: gke-gateway
spec:
gatewayClassName: gke-l7-gxlb
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
kinds:
- kind: HTTPRoute
- name: https
protocol: HTTPS
port: 443
allowedRoutes:
kinds:
- kind: HTTPRoute
addresses:
- type: NamedAddress
value: gke-gateway
I've tried multiple different combinations of this config, including with an explicit IPAddress, or without allowedRoutes. But no matter what I try, it doesn't seem to work. I can only see the initial ADD and UPDATE events in the output of kubectl describe gateway external-http, and there're no logs for it to be found anywhere afaik (since GKE Gateway Controller is part of the GKE Control Plane and without any logging exposed to the customers, from what I understand).
The only time I was able to make either internal or external Gateway to work is when using HTTP protocol, i.e. without certificates. Hence, I think this has to do with HTTPS, and probably more specifically with linking to the managed wildcard certificate.
Additionally, I should mention that my attempts at deploying the Gateway fail most of the time (i.e. the resource gets "stuck" in the same way), even when reusing a previously-working HTTP config. I'm not sure what the source of this flakiness is (apart from maybe some internal quota), but I imagine this is fully expected, as the service is still in Beta.
Has anyone been able to actually provision a Gateway with HTTPS listener and wildcard certs, and how?
I am trying to set up a service and expose it externally on EKS. I have already done it on GKE pretty easily but now AWS is giving me a hard time.
My NGINX yaml looks something like that:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- app.mydomain.com
secretName: myapp-tls
rules:
- host: app.mydomain.com
http:
paths:
- path: /
backend:
serviceName: myapp-service
servicePort: 80
And then I have my domain app.mydomain.com on Google Domains pointing at the ingress external address. There is also a cert-manager service running in order to support HTTPS.
However, while basically the same setup worked completely out of the box on GKE, EKS gives me a hard time.
From what I understand it has something to do with EKS default LoadBalancer being layer 4 in comparison to Google's layer 7 (Which explains HTTPS not working) but there is also issues with redirections of the domain as it just resolves as the ingress address instead of my desired address and thus my app doesn't show up.
The domain is registered over Google Domains and I'm creating Synthetic Records (for my subdomain) that points to my ingress external address on EKS. The same scheme works perfectly fine on GKE but here it resolves the address as the ingress address instead of my domain which results in 404 on the ingress side.
I was wondering if someone could please point me to how to properly set it up? Should I give up on nginx ingress on EKS and move onto ALB? and how to properly associate the domain?
Thank you very much in advance!
Edit:
output of kubectl describe ingress myapp-ingress:
Name: myapp-ingress
Namespace: default
Address: ********************************-****************.elb.eu-west-1.amazonaws.com
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
TLS:
myapp-tls terminates app.mydomain.com
Rules:
Host Path Backends
---- ---- --------
app.mydomain.com
/ myapp-service:80 (172.31.2.238:8000)
Annotations: cert-manager.io/cluster-issuer: myapp-letsencrypt-prod
kubernetes.io/ingress.class: nginx
Events: <none>
Should I give up on nginx ingress on EKS and move onto ALB
No. NGinX ingress controllers work perfectly well on EKS. It is possible to configure them as either layer 4 or layer 7; we use it in layer 7 mode.
Can you update your question with the output of
kubectl get ingress myapp-ingress
I think your ingress path is also incorrect. Unless I'm mistaken that's just routing the root of your app, not all uris. We use the scheme
spec:
rules:
- host: service.d.tld
http:
paths:
- path: /?(.*) # <---
backend:
serviceName: my-service
servicePort: http
Are you seeing errors in the nginx ingress controller's logs? That + kubectl events are both useful for debugging purposes.
I'd disable TLS everywhere and get your service working on http, then work stepwise on getting TLS enabled on the ingress controller.
Edit: Based on your response above,
curl -H "Host: app.mydomain.com" http://<elb-address>:80
SHOULD call through to your service behind the ingress.
How is app.mydomain.com defined? Is it a CNAME to the dns entry?
I followed this tutorial https://cloud.google.com/storage/docs/hosting-static-website
But I am not able to reach the site on https because of ERR_SSL_VERSION_OR_CIPHER_MISMATCH / SSL_ERROR_NO_CYPHER_OVERLAP depending on the browser
I use managed certificate provided by google, but no browser seems to be compatible with it. I use GCP default SSL policy, but I also tried create one for testing with minimal requirements of TSL 1.0, but nothing changed.
Yes , if using google managed cert sometimes it takes time to propagate to your associate domain , so in future you could eiter use "curl" command or used dig command to verify it , sometimes it takes 24 hrs too which is maximum time.
Please verify following points:
verify your website pointing towards frontend LB
check the state of google managed cert added on the front end of LB
verify that frontend is using HTTPS and backend is using HTTP
verify your ssl cert
I'm sure it's a problem with the DNS server. If your config is correct, you have to wait a few hours more and redeploy again.
In my case, I was setting up a subdomain with different IP used in the domain.
My managed certificate it was something like this:
apiVersion: networking.gke.io/v1beta1
kind: ManagedCertificate
metadata:
name: my-certificate
spec:
domains:
- www.sub.example.com
My ingress was fine:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: st-ext-ip-prod
networking.gke.io/v1beta1.FrontendConfig: ssl-redirect
networking.gke.io/managed-certificates: my-certificate
spec: ...
The problem was the configuration in my DNS SERVER. In my certificate, I was using the domain starting with wwww but in my server, I didn't have the CNAME to support the www.sub
# A DOMAIN-IP
www CNAME example.com
sub A SUBDOMAIN-IP
www.sub CNAME sub.example.com
Doing that configuration (CNAME for www.sub) I had to wait like 5 hours (it could take more)
I had to redeploy everything from the beginning and finally, I didn't have that issue ERR_SSL_VERSION_OR_CIPHER_MISMATCH again.
I've had great difficulties routing traffic to k8s API and services.
First I've created a cluster(k8s.buycheese.com) with KOPS in private
topology, within a VPC, so that, master and nodes are only accessible from a bastion using SSH.
I own a domain in namecheap (buycheese.com) and I've created a hosted zone(k8s.buycheese.com) in route53.
After KOPS has installed the cluster, it added a couple of record sets to the hosted zone like api.k8s.buycheese.com.
I've added the hosted zone's namespaces to my domain in namecheap, so that I can access the Kubernetes cluster(kubectl). That works correctly!
Next, I've installed an ingress nginx controller. Then I've created 2 ingresses:
One to expose the Kubernetes dashboard
Another one to expose a nodeJS application
I then tested my nodeJS Application using the ingress nginx ELB's URL and I can confirm that works! So I know that my pods are running correctly and the ELB works fine!
But obviously, I want my applications to be accessed through the domain I own...
So basically:
I need a new subdomain dashboard.buycheese.com to get to the Kubernetes dashboard.
And I need buycheese.com and www.buycheese.com domains to redirect to my nodeJS app.
Well, to do that, I've created a new hosted zone named buycheese.com in route53, and added 4 new namespaces to my domain buycheese.com in namecheap.
Then I've created 2 aliases(A) within that same hosted zone:
dashboard.buycheese.com with Alias Target: ingress nginx's ELB
www.buycheese.com with Alias Target: ingress nginx's ELB
Then within my 2 ingress files
# Dashboard
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
name: kubernetes-dashboard-oidc
namespace: kube-system
spec:
rules:
- host: dashboard.buycheese.com
http:
paths:
- path: /
backend:
serviceName: kubernetes-dashboard-oidc
servicePort: 80
# NodeJS App
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
name: app
namespace:default
spec:
rules:
- host: buycheese.com
http:
paths:
- path: /
backend:
serviceName: app-service
servicePort: 3000
To sum up I have 2 hosted zones
1) k8s.buycheese.com
2) buycheese.com
2 Alias within hosted zone buycheese.com:
1) www.buycheese.com
2) dashboard.buycheese.com
2 Ingresses to expose the dashboard and my app
That configuration does not work at all! The below URLs are not reachable!
dashboard.buycheese.com
www.buycheese.com
buycheese.com
Only the ELB's URL works!
So first I would like to know whether my set up is correct(obviously no, but why ?)
What's the right way to make all of those URLs exposing my services and applications?
Thanks for your help!
The only thing that I think may be happening here is that Alias Target: is not forwarding to the ELB.
You can try using CNAME records instead. You can always test using dig from the command line:
$ dig buycheese.com
$ dig www.buycheese.com
$ dig dashboard.buycheese.com
I created new record set in Route 53 with Type=A and alias to my ELB DNS Name for me also initially the same problem was there but after waiting for some time it started working this could be DNS propagation issue as told by denixtry