Kubernetes Ingress/nginx pod specific value - nginx

I'm very new to Kubernetes and still learning how to use LB, ingress, etc. Currently, I'm trying to set pod-specific value(config) for each host. Looks like in ingress yaml spec, it can read config from values. But I would like to read ingress spec, e.g. host, in Values.yaml.
For example, I have two hosts
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: service
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: service-A.com
http:
paths:
- path: /
backend:
serviceName: myservicea
servicePort: 80
- host: service-B.com
http:
paths:
- path: /
backend:
serviceName: myserviceb
servicePort: 80
And I have two variables in values.yaml:
var1: aaa
var2: bbb
I want to pass
var1 to service-A.com/myservicea
var2 to service-B.com/myserviceb
or pass both, but the application must be able to identify what host it is, then it can use the right variable.
Is there any configuration/apis available to use for this purpose?

This is how you can create a secret.
kubectl create secret generic CUSTOM_VAR\
--from-literal=VAR_A=aaa\
--from-literal=VAR_B=bbb
This is how you can access the secrets in you deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myservicea-depl
spec:
replicas: 1
selector:
matchLabels:
app: myservice
template:
metadata:
labels:
app: myservice
spec:
containers:
- name: myservice
image: user/myservicea
env:
- name: VAR_A
value: aaa // this way you directly pass values here
- name: VAR_A // this way you can store this as secret in k8s
valueFrom:
secretKeyRef:
name: CUSTOM_VAR
key: VAR_A

Related

Setup ingress for my application with url start by /# on GKE and EKS

I have setup application with statefulset
# Simple deployment used to deploy and manage the app in nigelpoulton/getting-started-k8s:1.0
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: coredeploy
labels:
app: core123
spec:
replicas: 1
# minReadySeconds: 10
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 0
# maxSurge: 1
selector:
matchLabels:
app: core123
serviceName: core123
template:
metadata:
labels:
app: core123
spec:
terminationGracePeriodSeconds: 1
containers:
- name: hello
image: docker-registry.myregistry.com:5000/core_centos:LMS-130022
imagePullPolicy: Always
ports:
- containerPort: 8008
readinessProbe:
tcpSocket:
port: 8008
periodSeconds: 1
This is my service
apiVersion: v1
kind: Service
metadata:
name: service-core
spec:
selector:
app: core123
type: NodePort
ports:
- name: nodeportcore
protocol: TCP
port: 9988
targetPort: 8008
This is my ingress
apiVersion: "networking.k8s.io/v1"
kind: "Ingress"
metadata:
name: "testIngress"
spec:
rules:
- http:
paths:
- path: "/"
backend:
service:
name: "service-core"
port:
number: 9988
pathType: "ImplementationSpecific"
After i apply ingress manifest file. My application is running but not login => Logs login successful but still back to login screen. After check i recognize url of my application when i run it in localhost on-premise (Not container this url in container is the same)
http://localhost:8008/#/public/login
http://localhost:8008/#/user/settings
http://localhost:8008/#/user/dashboard/overview
http://localhost:8008/#/user/history/processing
http://localhost:8008/#/user/policy/template
It url start with # and then url name as /public/login, /user/settings, /user/dashboard/overview, /#//
=> My question how i setup correctly ingress to run with my application

Example needed: How to migrate ingress routing from Nginx to Traefik-V1 (or V2)?

I try to switch from nginx to traefik in a Kubernetes cluster. I am totally new to Traefik.
I have an app with Frontend and Backend:
demo.myapp.com/ # frontend
demo.myapp.com/backend # backend
With Nginx I did that following code, which worked like a charm:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- host: demo.myapp.at
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-app
port:
number: 80
- path: /backend(/|$)(.*)
pathType: Prefix
backend:
service:
name: backend-api
port:
number: 80
Do I need two Ingresses for one domain, if I wanna route to a subfolder?
It seems with Traefik V1 and Traefik V2 (where V2 also needs a CRD for IngressRoute and/or Middleware manifest) more complex.
But I am totally lost with the examples in the docs as well with the mix of Version1 and Version2.
At the moment I use rancher/library-traefik:1.7.19 but I also can give V2 a try.
my V1 approach at the moment:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: demo-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: traefik
traefik.frontend.rule.type: PathPrefixStrip
spec:
rules:
- host: demo.myapp.com
http:
paths:
- path: /
pathType: Prefix
backend:
serviceName: frontend-app
servicePort: 80
- path: /backend # old nginx regex -> (/|$)(.*)
pathType: Prefix
backend:
serviceName: backend-api
servicePort: 80
Problem with that V1 example:
all paths below /backend are not rewritten correctly.
Instead of routing to /backend/someImage.png it routes to /someImage.png
If someone can help me with an example (optimal would be one for V1 and one for V2), would be great.
Thank you in advance
These examples are allegories from the Nginx questioned examples above
For V1
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: demo-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: traefik
# traefik.ingress.kubernetes.io/redirect-permanent: "true"
traefik.ingress.kubernetes.io/redirect-regex: /backend$
traefik.ingress.kubernetes.io/redirect-replacement: /backend/
traefik.ingress.kubernetes.io/request-modifier: "ReplacePathRegex: ^/backend/(.*) /$1"
spec:
rules:
- host: demo.myapp.com
http:
paths:
- path: /
pathType: ImplementationSpecific
backend:
serviceName: frontend-app
servicePort: 80
- path: /backend # (/|$)(.*)
pathType: ImplementationSpecific
backend:
serviceName: backend-api
servicePort: 80
V2
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
annotations:
kubernetes.io/ingress.class: traefik
name: demo-ingress-route
namespace: default
spec:
entryPoints:
- web
routes:
- kind: Rule
match: Host(`demo.myapp.com`)
priority: 0
services:
- name: frontend-app
port: 80
- kind: Rule
match: Host(`demo.myapp.com`) && PathPrefix(`/backend/`)
middlewares:
- name: middleware-to-strip-backend-path
priority: 0
services:
- name: backend-api
port: 80
---
# this middleware will strip /backend from your request to align the requested url to the root / path of your API
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: middleware-to-strip-backend-path
namespace: default
spec:
stripPrefix:
prefixes:
- /backend

How can I update kuberenet pod based on configuration change?

I have a configuration file like below. I deploy it to EKS cluster successfully. However, when I change the nginx-conf ConfigMap and run kubectl apply command, it doesn't seem to update the nginx.config in the pod. I tried to login to the pod and look at the file /etc/nginx/nginx.config but its content is still the old one.
I have tried to run kubectl rollout status deployment sidecar-app but it doesn't help.
And it shows the updated config map when I run kubectl describe configmap nginx-conf.
It seems the container doesn't take the config map change. How can I apply the changes without deleting the pod?
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-conf
data:
nginx.conf: |
user nginx;
worker_processes 1;
events {
worker_connections 10240;
}
http {
server {
listen 8080;
server_name localhost;
location / {
proxy_pass http://localhost:9200/;
}
location /health {
proxy_pass http://localhost:9200/_cluster/health;
}
}
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sidecar-app
namespace: default
spec:
replicas: 1
selector:
matchLabels:
name: sidecar-app
template:
metadata:
labels:
name: sidecar-app
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- name: http
containerPort: 8080
volumeMounts:
- name: nginx-conf
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
readOnly: true
volumes:
- name: nginx-conf
configMap:
name: nginx-conf
items:
- key: nginx.conf
path: nginx.conf
---
apiVersion: v1
kind: Service
metadata:
name: sidecar-entrypoint
spec:
selector:
name: sidecar-app
ports:
- port: 8080
targetPort: 8080
protocol: TCP
type: NodePort
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: sidecar-ingress-1
namespace: default
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/group.name: sidecar-ingress
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/group.order: '2'
alb.ingress.kubernetes.io/healthcheck-path: /health
# alb.ingress.kubernetes.io/healthcheck-port: '8080'
spec:
rules:
- http:
paths:
- path: /*
backend:
serviceName: sidecar-entrypoint
servicePort: 8080
Kubernetes treats POD and Configmap as a different/separate object and pods don't automatically restart on specific Configmap version.
There are few alternatives to achieve this.
1 ) Reloader: https://github.com/stakater/Reloader
kind: Deployment
metadata:
annotations:
reloader.stakater.com/auto: "true"
spec:
template: metadata:
configHash annotation.
https://blog.questionable.services/article/kubernetes-deployments-configmap-change/
Use wave.
https://github.com/wave-k8s/wave
You can use kubectl rollout restart deploy/sidecar-app but this will restart the pods with zero downtime. Rolling updates allow Deployments' update to take place with zero downtime by incrementally updating Pods instances with new ones.

How to expose gRPC in Istio

Anyone know if it is possible to use gRPC with Istio-ingress or other ways?
Yes/no, anything is welcome - thanks in advance.
apiVersion: v1
kind: Service
metadata:
name: grpc-service
spec:
# type: LoadBalancer
selector:
app: grpc
ports:
- port: 3000
name: grpc
# protocol: HTTP2
targetPort: 3000
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: grpc-ingress
annotations:
kubernetes.io/ingress.class: "istio"
# ingress.kubernetes.io/ssl-passthrough: "true"
spec:
rules:
- http:
paths:
- path: /ghw/.*
backend:
serviceName: grpc-service
servicePort: 3000
Go code:
const (
address = "localhost/ghw/:3000"
)

nginx ingress & rewrite-target

I have a pod that responds to requests to /api/
I want to do a rewrite where requests to /auth/api/ go to /api/.
Using an Ingress (nginx), I thought that with the ingress.kubernetes.io/rewrite-target: annotation I could do it something like this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myapi-ing
annotations:
ingress.kubernetes.io/rewrite-target: /api
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: api.myapp.com
http:
paths:
- path: /auth/api
backend:
serviceName: myapi
servicePort: myapi-port
What's happening however is that /auth/ is being passed to the service/pod and a 404 is rightfully being thrown. I must be misunderstanding the rewrite annotation.
Is there a way to do this via k8s & ingresses?
I don't know if this is still an issue, but since version 0.22 it seems you need to use capture groups to pass values to the rewrite-target value
From the nginx example available here
Starting in Version 0.22.0, ingress definitions using the annotation nginx.ingress.kubernetes.io/rewrite-target are not backwards compatible with previous versions. In Version 0.22.0 and beyond, any substrings within the request URI that need to be passed to the rewritten path must explicitly be defined in a capture group.
For your specific needs, something like this should do the trick
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myapi-ing
annotations:
ingress.kubernetes.io/rewrite-target: /api/$2
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: api.myapp.com
http:
paths:
- path: /auth/api(/|$)(.*)
backend:
serviceName: myapi
servicePort: myapi-port
I have created the following example that works and which I will explain. To run this minimal example, run these commands:
$ minikube start
$ minikube addons enable ingress # might take a while for ingress pod to bootstrap
$ kubectl apply -f kubernetes.yaml
$ curl https://$(minikube ip)/auth/api/ --insecure
success - path: /api/
$ curl https://$(minikube ip)/auth/api --insecure
failure - path: /auth/api
$ curl https://$(minikube ip)/auth/api/blah/whatever --insecure
success - path: /api/blah/whatever
As you'll notice, the ingress rewrite annotation appears to be very particular about trailing slashes. If a trailing slash is not present, the request will not be rewritten. However, if a trailing slash is provided, the request uri will be rewritten and your proxy will function as expected.
After inspecting the generated nginx.conf file from inside the ingress controller, the line of code responsible for this behavior is:
rewrite /auth/api/(.*) api/$1 break;
This line tells us that only requests matching the first argument will be rewritten with the path specified by the second argument.
I believe this is bug worthy.
kubernetes.yaml
---
apiVersion: v1
kind: Service
metadata:
name: ingress-rewite-example
spec:
selector:
app: ingress-rewite-example
ports:
- name: nginx
port: 80
protocol: TCP
targetPort: 80
type: NodePort
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: ingress-rewite-example
spec:
template:
metadata:
labels:
app: ingress-rewite-example
spec:
containers:
- name: ingress-rewite-example
image: fbgrecojr/office-hours:so-47837087
imagePullPolicy: Always
ports:
- containerPort: 80
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-rewite-example
annotations:
ingress.kubernetes.io/rewrite-target: /api
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- http:
paths:
- path: /auth/api
backend:
serviceName: ingress-rewite-example
servicePort: 80
main.go
package main
import (
"fmt"
"strings"
"net/http"
)
func httpHandler(w http.ResponseWriter, r *http.Request) {
var response string
if strings.HasPrefix(r.URL.Path, "/api") {
response = "success"
} else {
response = "failure"
}
fmt.Fprintf(w, response + " - path: " + r.URL.Path + "\n")
}
func main() {
http.HandleFunc("/", httpHandler)
panic(http.ListenAndServe(":80", nil))
}

Resources