Kubernetes is a self healing, high availability and load balanced environment.
Even if you have one node you still use cluster solutions to achieve
best performance. In this kind of situation all software components are running
on one machine. So there is a lot of software running - your application images and Kubernetes processes.
This requires to have enough resources for every aspect of this configuration.
What if your application (that means docker image for example) is running out of
resources? Kubernetes will kill it. Exhausted memory limits will cause OOO behavior to run and kill the container.
In log you've provided I found the following entry:
I0518 12:31:55.369911 7 main.go:150] Received SIGTERM, shutting down
So Kubernetes decided to kill Ingress controller due to exhausted resources.
Try to extend the memory of the machine (or vm) and observe if it helps.
Another option is to start another node and extend cluster from one node to multi node with all features like HA and load balancing enabled to avoid issue
like this.
Bare-metal environments lacks the commodity that traditional cloud environments provide where network load balancers are available and single K8s manifest is enough to provide single point of contact to the NGINX ingress controller.
Of course we have to remember that internal redirect follows the ingress resource which then configures the ingress controller accordingly.
With External IP method the source IP of HTTP is not preserved therefore not recommended to use it despite it's apparent simplicity. So you will loose the information what is going with your requests (unless you will montor ingress controller)
To answer the question how to configure external IP redirect inside Nginx Ingress Controller we have to start from knowing what ingress actually is:
Ingress exposes HTTP and HTTPS routes from outside the cluster to services within the cluster. Traffic routing is controlled by rules defined on the Ingress resource. There must be an Ingress controller to satisfy an Ingress. Only creating an Ingress resource has no effect.
To achieve expected results you should create two separate ingress objects (not controllers). First one with no host is specified so the rule applies to all inbound HTTP traffic through the IP address specified as described in the Ingress rules:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/permanent-redirect: "https://www.google.com"
name: ingress-redirect
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
serviceName: example
servicePort: 12
And the second ingress object with a host that is provided (for example, hello-world.info, so that the rules apply to that host. Like in the example below:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-host
spec:
rules:
- host: hello-world.info
http:
paths:
- path: /
pathType: Prefix
backend:
serviceName: web
servicePort: 80
As you can see below, the above configuration creates the following sections in the nginx-ingress-controller's nginx.conf. One is responsible for serving requests with specific Host: header, another is for serving requests w/o Host: header e.g. if request is sent to IP address directly:
enter http {
# works when no Host header is provided
## start server _
server {
server_name _ ;
listen 80 default_server reuseport backlog=511 ;
listen 443 default_server reuseport backlog=511 ssl http2 ;
location / {
set $namespace "default";
set $ingress_name "ingress-redirect";
set $service_name "";
set $service_port "";
set $location_path "/";
return 301 https://www.google.com;
# works when specific Host header is provided
## start server hello-world.info
server {
server_name hello-world.info ;
listen 80 ;
listen 443 ssl http2 ;
location / {
set $namespace "default";
set $ingress_name "ingress-host";
set $service_name "web";
set $service_port "80";
set $location_path "/";
}
}
## end server hello-world.info
For testing purposes I have deployed quickly those two ingress objects and nginx pod:
➜ kubectl run --image nginx web
And expose it to have serivce behind the second ingress object:
➜ kubectl expose pod web --port 80
As you can see when curling the redirect works as expected:
➜ ~ curl $(minikube ip) -I
HTTP/1.1 301 Moved Permanently
Server: nginx/1.19.0
Date: Tue, 27 Oct 2020 13:22:06 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://www.google.com
And if you curl the same address with the host name it redirects towards nginx pod:
➜ ~ curl $(minikube ip) -H "Host: hello-world.info"
---
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
---
Also it is worth to mention about Kubernetes docs that provide also good example of Name based virtual hosting. It supports routing HTTP traffic to multiple host names at the same IP address. The example in the document tells the backing load balancer to route requests based on the Host header.
For example the Ingress mentioned in the documentation page above routes traffic requested for first.bar.com
to service1
, second.foo.com
to service2
, and any traffic to the IP address without a hostname
defined in request (that is, without a request header being presented) to service3
.
Best Answer
You can exec into the pods using
kubectl exec <pod_name> -n <namespace> <command>
and check if your application is creating log files in the paths that you have mentioned. If you are able to verify the existence of those files, you can add a busybox sidecar to the deployment and you can directly stream your logs using the sidecar and tail them usingkubectl logs
You can use the following template to do the same:
Add the following volume-mount to the existing deployment
And then you can add the sidecar using the following template
Please note that this will stream both your error and access logs into the same stream. Although, the correct method to do this is to create symlinks for error and access logs, the method I have mentioned can be used as an alternative.
Hope this helps!