Google Container Engine - How to update L7 ingress to load new TLS certificate? - load-balancing

I am using the standard L7 load balancing ingress on Google Container Engine. I have installed it through the following ingress definition:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: l7-ingress-{{environment}}
spec:
tls:
- secretName: web-secret
backend:
serviceName: web
servicePort: 80
Now, my question is, how do I ensure that the TLS certificate is updated once the secret web-secret changes? AFAICT, it currently stays the same even though the underlying secret changes.

Apparently, the L7 ingress doesn't currently monitor the TLS secret for changes. But a PR to solve this has been merged, so it should only be a matter of time.

My experience to workaround this is to delete and create the ingress, but making sure you specify the IP in the YAML you pass to kubectl create -f:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: dev-ing
spec:
tls:
- secretName: tls-sekret
rules:
- host: tryout.example.com
http:
paths:
- backend:
serviceName: nginx
servicePort: 80
status:
loadBalancer:
ingress:
- ip: 130.211.n.n
I couldn't find any documentation stating that this is the way to ensure you will get the same IP, but for me it worked. Use with caution on production systems where you can not afford to loose the IP!

I just tried a simple apply on an edited secret, and yes it worked. The web console and gcloud compute ssl-certificates list reported the change right away, and the load balancer started serving it up in about 10 minutes. It would be nice to have this officially documented! Especially because there are other corners of k8s where changes to secrets aren't automatically picked up, like deployments, so we don't take it for granted.

The Google L7 loadbalancer does exchange the underlying certificate if updated. You have to apply the correct annotations:
Secret
apiVersion: v1
kind: Secret
data:
tls.crt: xxx
tls.key: xxx
metadata:
name: tls-secret
type: kubernetes.io/tls
Ingress
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: dev-ing
annotations:
# Do not forget this annotation
kubernetes.io/ingress.class: "gce"
spec:
tls:
- hosts:
- tryout.example.com
secretName: tls-secret
backend:
serviceName: nginx
servicePort: 80
The exchange happens somehow in the background, be aware of the time it takes (5-15 minutes).

Related

Kubernetes cert-manager certificate is created but can not get vertified

I am working on a DO kubernetes cluster and install ingress nginx and argocd on it, All seems fine and I can easily use the ingress as long as they are accessing the services via http.
I have also installed certmanager and here are the main files regarding my ingress, certificate and issuer:
Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rancher-demo
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /
certmanager.k8s.io/cluster-issuer: "letsencrypt-production"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
tls:
- hosts:
- {sub-domain}
secretName: ssl-cert-production
rules:
- host: {sub-domain}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: rancher-demo
port:
number: 80
Issuer
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-production
namespace: default
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: {my-email}
privateKeySecretRef:
name: letsencrypt-production
solvers:
- selector: {}
http01:
ingress:
class: nginx
Certificate
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: ssl-cert-production
namespace: default
spec:
secretName: ssl-cert-production
issuerRef:
name: letsencrypt-production
kind: ClusterIssuer
commonName: {sub-domain}
dnsNames:
- {sub-domain}
I went through some other samples on github and questions on stackoverflow and unfortunetly I can not figure out where I am doing it wrong.
Thank you in advance for your attentions
I finally managed to fix the issue, what I have done was as follow:
creating a new kubernete instance
installing cert-manager manaully
installing ingress-nginx manaully
creating the issuer (waiting for it to complete)
creating deployment and cluster
creating ingress config for my application
creating the certificate (waiting for it to complete)
I was working on ArgoCD and had to first do these setups myself before handling CD with Argo. It was my own fault that I did not properly go through their documentations. The order is important, but the way I sat up Argo, it was provisioing everything in parallel so for example certificate was being provision before ingress be up or issuer be in place
Also for anyone who is interested in a detailed version please checkout the github repo I created below:
https://github.com/mehdiamenein/cert-manager-nginx-ingress-do
I hope this can be helpful to someone else as well :)
Huge thanks to marcel.dempers for his wonderful video https://www.youtube.com/watch?v=hoLUigg4V18
and many thanks to #justin and #harsh-manvar for their comments

How can I make one route public in kubernetes ingress with auth-url set?

I am playing a little bit with path-based routing via Kubernetes ingresses (we use Nginx ingress). We have one service up and running behind authentication via external service like the one in the first snippet. This service is already used by other services in our ecosystem, however, as the development progresses, the service now has management API and we need to turn off the authentication for specific paths. According to this answer, this is not possible for basic auth and, according to what I have tried (second snippet), it is not possible for authentication via external service either. Is there any other way to allow specific paths without authentication without completely rearchitecting ingresses and domains/paths?
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: path-based-routing-1
annotations:
kubernetes.io/tls-acme: "true"
kubernetes.io/ingress.class: nginx-external
nginx.ingress.kubernetes.io/auth-url: http://authorizer.dev.svc.cluster.local
spec:
tls:
- hosts:
- 'routing.example.com'
secretName: routing.example.com
rules:
- host: 'routing.example.com'
http:
paths:
- path: /
backend:
serviceName: path-based-routing-1
servicePort: 80
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: path-based-routing-2
annotations:
kubernetes.io/tls-acme: "true"
nginx.ingress.kubernetes.io/auth-type: ""
kubernetes.io/ingress.class: nginx-external
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
tls:
- hosts:
- 'routing.example.com'
secretName: routing.example.com
rules:
- host: 'routing.example.com'
http:
paths:
- path: /management-api
backend:
serviceName: path-based-routing-2
servicePort: 80

GKE, NGINX ingress, HTTPS, and certificates

I have set up a Kubernetes cluster on GCP/GKE and it's all working well except for one thing. When I access the external IP for the service the (default?) "Kubernetes Ingress Controller Fake Certificate" is served.
I am trying to use the NGINX Ingress (https://kubernetes.github.io/ingress-nginx/) and have followed what I believe are the correct instructions for associating a TLS secret with the Ingress. For example:
https://estl.tech/configuring-https-to-a-web-service-on-google-kubernetes-engine-2d71849520d
https://kubernetes.github.io/ingress-nginx/user-guide/tls/
I have created a secret like this:
apiVersion: v1
kind: Secret
metadata:
name: example-tls
namespace: default
data:
tls.crt: [removed]
tls.key: [removed]
type: kubernetes.io/tls
And associated that secret (which I can confirm is applied correctly and I can see in the cluster config) with the Ingress like this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: example-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
kubernetes.io/ingress.allow-http: "false"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/affinity: "cookie"
spec:
backend:
serviceName: example-service
servicePort: 80
tls:
- secretName: example-tls
From the documentation I feel that this should work (but, barring a bug, I am obviously mistaken!).
I've also seen some documentation around requiring target proxies for HTTPS. Perhaps that is the way that I should be doing this?
Many thanks for your help in advance.
Cheers,
Ben
PS: This is my load balancer configuration:
kind: Service
apiVersion: v1
metadata:
name: ingress-nginx
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
externalTrafficPolicy: Cluster
loadBalancerIP: [removed]
sessionAffinity: ClientIP
type: LoadBalancer
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
ports:
- name: http
port: 80
targetPort: http
- name: https
port: 443
targetPort: https
Edit 1:
Looking at my Ingress I can see this:
➜ gke git:(develop) ✗ kubectl describe ing example-tls-ingress
Name: example-tls-ingress
Namespace: default
Address: [removed]
Default backend: example-webapp-service:80 ([removed])
TLS:
example-tls terminates
Rules:
Host Path Backends
---- ---- --------
* * example-webapp-service:80 ([removed])
So it looks like the secret is picked up.
And this makes me think that there is a difference between Ingress-terminated TLS and Load Balancer-terminated TLS?
You can just refer to this stackoverflow post.
You need to install jetstack cert-Manager, create clusterissuer/issuer, along with a certificate in which you have to pass domain name / hostname and jetstack will automatically create the secret for you, by the name you mentioned in the 'Certificate'.
That secret has to be patched to TLS in ingress rule.

TTFB increated by 200+ ms after enabling SSL via Nginx Ingress controller & cert-manager

Right after enabling cert-manager in Ingress Controller by TTFB (time to first byte) increased by 200+ms in most of the regions. Without SSL, it was <200ms to 80% of the regions. After enabling SSL only 30% have TTFB <200ms
without SSL
with SSL
My Ingress definition:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
annotations:
kubernetes.io/ingress.class: nginx
certmanager.k8s.io/cluster-issuer: letsencrypt-prod
kubernetes.io/tls-acme: "true"
spec:
rules:
- host: gce.wpspeedmatters.com
http:
paths:
- path: /
backend:
serviceName: wordpress
servicePort: 80
tls:
- secretName: tls-prod-cert
hosts:
- gce.wpspeedmatters.com
Switched to TLS 1.3 and I was able to above shave off extra 50-150ms!
I wrote a detailed blog post too: https://wpspeedmatters.com/tls-1-3-in-wordpress/
With TLS 1.3:

Trouble configuring ssl-redirect on Kubernetes Ingress

I have configured an ingress on a kubernetes cluster from Google Cloud. I followed the instructions as is on this doc.
My manifest:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: web-proxy
annotations:
ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
tls:
- hosts:
- foo.bar.com
secretName: foo-bar-secret
rules:
- host: foo.bar.com
http:
paths:
- backend:
serviceName: foo-bar-service
servicePort: 80
path: /*
From the documentation, it specifies that ssl-redirect
is by default true if tls is configured but it doesn't work. I've also tried to set force-ssl-redirect to true(default is false), still no luck.
I'm confused if there is actually a bug or I'm doing something wrong, because when I run kubectl describe ing web-proxy, it displays that annotations were set:
Annotations:
force-ssl-redirect: true
[...]
Any suggestions?
EDIT 1:
I was using the 1.8.3.gke.0 version but when I upgraded to 1.8.4.gke.0 this seems to have solved the problem.
I'll keep this post updated while I test more annotations(like: nginx.ingress.kubernetes.io/from-to-www-redirect)