My yaml file.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
-http:
paths:
- path: /?(.*)
backend:
serviceName: nginx-service
servicePort: 80
kubectl apply -f file.yaml
error: error validating "ingress.yaml": error validating data: ValidationError(Ingress.spec.rules): invalid type for io.k8s.api.networking.v1beta1.IngressSpec.rules: got "map", expected "array"; if you choose to ignore these errors, turn validation off with --validate=false
The issue is with typo in "-http" (no whitespace char between the hyphen and the 'h' letter).
spec:
rules:
-http: <--- this doesn't create an array, and array is expected instead of map
paths:
How to troubleshoot such issues (and what Kubernetes does "under_the_hood"):
?
symbol that states that yamllint had to guess what is wrong with that line. Please note that yamllint still considers this YAML as Valid.kubectl
does before sending data to kube-apiserver
. it is possible to do that with json2yaml tool for example. You'll immidiately see that the tool parses it as a map and not as an array.Tha is how it converted to JSON with incorrect YAML.
And with the corrected YAML it parsed as array
How it is supposed to work. As with all other Kubernetes resources, an Ingress needs apiVersion, kind, and metadata fields. Additionally, Ingress frequently uses annotations to configure some options depending on the Ingress controller, an example of which is the rewrite-target annotation. Different Ingress controllers support different annotations.
If anyone needs comprehensive info on rewrite-target, that can be found here
IngressRule represents the rules mapping the paths under a specified host to the related backend services. Incoming requests are first evaluated for a host match, then routed to the backend associated with the matching IngressRuleValue.
host
have to be of a string
type and contain fully qualified domain name (FQDN) of a network host. Current Limitations (client GitVersion:"v1.16.3", Server GitVersion:"v1.14.8-gke.12"):
:
delimiter is not respected because ports are not allowed. As of now, the port of an Ingress is implicitly :80 for http and :443 for https.Both these may change in the future.
Incoming requests are matched against the host before the IngressRuleValue. If the host is unspecified, the Ingress routes all traffic based on the specified IngressRuleValue.
So, the structure shall be as the following:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: dual-ingress
annotations:
<your-annotations-go-here>
spec:
rules:
- host: <your-hostname-1-goes-here>
http:
paths:
- path: <host-1-path-1>
backend:
serviceName: <service1>
servicePort: <service1-port>
- path: <host-1-path-2>
backend:
serviceName: <service2>
servicePort: <service2-port>
- host: <your-hostname-2-goes-here>
http:
paths:
- path: <host-2-path-1>
backend:
serviceName: <service3>
servicePort: <service3-port>
- path: <host-2-path-2>
backend:
serviceName: <service4>
servicePort: <service4-port>
the above YAML creates the following Ingress :
kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
dual-ingress your-hostname-1,your-hostname-2,bar.com 80 14s
In case you don't specify host in YAML all traffic will be routed according to IngressRuleValue. YAML example:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: mono-ingress
annotations:
<your-annotations-go-here>
spec:
rules:
- http:
paths:
- path: <path-1>
backend:
serviceName: <service1>
servicePort: <service1-port>
- path: <path-2>
backend:
serviceName: <service2>
servicePort: <service2-port>
The above YAML creates the following Ingress :
kubectl get ingress -o wide
NAME HOSTS ADDRESS PORTS AGE
mono-ingress * 80 10s
So, to sum up, rules:
field shall contain an array
(and topic starter missed single space char between "-" and "http", so it wasn't parsed as an array
, but map
)
Hope that helps.
this is yaml template error only, use
kubectl explain ingress.spec.rules
to get idea.
The hostname is also missing in the ingress rule, should have been something like
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
-host:{replace-me-with-hostname}
http:
paths:
- path: /?(.*)
backend:
serviceName: nginx-service
servicePort: 80