<p>My yaml file.</p>
<pre><code>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
</code></pre>
<pre><code>kubectl apply -f file.yaml

error: error validating &quot;ingress.yaml&quot;: error validating data: ValidationError(Ingress.spec.rules): invalid type for io.k8s.api.networking.v1beta1.IngressSpec.rules: got &quot;map&quot;, expected &quot;array&quot;; if you choose to ignore these errors, turn validation off with --validate=false
</code></pre>

<p><strong>The issue</strong> is with typo in "-http" (no whitespace char between the hyphen and the 'h' letter).</p>

<pre><code>spec:
  rules:
    -http:   &lt;--- this doesn't create an array, and array is expected instead of map
      paths:
</code></pre>

<p><strong>How to troubleshoot</strong> such issues (and what Kubernetes does "under_the_hood"):</p>

<ul>
<li>yamllint . It is possible to put the yaml code to any online <a href="http://www.yamllint.com/" rel="nofollow noreferrer">YAML syntax validator</a> . Let's check the line_11. There is <code>?</code> symbol that states that yamllint had to guess what is wrong with that line. Please note that yamllint still considers this YAML as Valid.</li>
</ul>

<p><a href="https://i.stack.imgur.com/C5s4P.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/C5s4P.png" alt="enter image description here"></a></p>

<ul>
<li>convert yaml to JSON. That's exactly what <code>kubectl</code> does before sending data to  <code>kube-apiserver</code>. it is possible to do that with <a href="https://www.json2yaml.com/" rel="nofollow noreferrer">json2yaml</a> tool for example. You'll immidiately see that the tool parses it as a map and not as an array.</li>
</ul>

<p>Tha is how it converted to JSON with incorrect YAML.
<a href="https://i.stack.imgur.com/ZFzhr.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ZFzhr.png" alt="incorrect YAML"></a></p>

<p>And with the corrected YAML it parsed as <code>array</code>
<a href="https://i.stack.imgur.com/Y3Sln.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Y3Sln.png" alt="correct YAML . &lt;code&gt;rules&lt;/code&gt; contain an array"></a></p>

<p><strong>How it is supposed to work</strong>.
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. </p>

<p>If anyone needs comprehensive info on rewrite-target, that can be found <a href="https://github.com/kubernetes/ingress-nginx/blob/master/docs/examples/rewrite/README.md" rel="nofollow noreferrer">here</a> </p>

<p>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.</p>

<p><code>host</code> have to be of a <code>string</code> 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"):</p>

<ul>
<li>IPs aren't allowed. IngressRuleValue can only apply to the IP in the Spec of the parent Ingress.</li>
<li>The <code>:</code> 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. </li>
</ul>

<p>Both these may change in the future.</p>

<p>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.</p>

<p>So, the structure shall be as the following: </p>

<pre><code>apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: dual-ingress
  annotations:
    &lt;your-annotations-go-here&gt;
spec:
  rules:
  - host: &lt;your-hostname-1-goes-here&gt;
    http:
      paths:
      - path: &lt;host-1-path-1&gt;
        backend:
          serviceName: &lt;service1&gt;
          servicePort: &lt;service1-port&gt;
      - path: &lt;host-1-path-2&gt;
        backend:
          serviceName: &lt;service2&gt;
          servicePort: &lt;service2-port&gt;
  - host: &lt;your-hostname-2-goes-here&gt;
    http:
      paths:
      - path: &lt;host-2-path-1&gt;
        backend:
          serviceName: &lt;service3&gt;
          servicePort: &lt;service3-port&gt;
      - path: &lt;host-2-path-2&gt;
        backend:
          serviceName: &lt;service4&gt;
          servicePort: &lt;service4-port&gt;

</code></pre>

<p>the above YAML creates the following Ingress :</p>

<pre><code>kubectl get ingress 

NAME           HOSTS                                     ADDRESS   PORTS   AGE
dual-ingress   your-hostname-1,your-hostname-2,bar.com             80      14s

</code></pre>

<p>In case you don't specify host in YAML all  traffic will be routed according to IngressRuleValue.
YAML example:</p>

<pre><code>apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: mono-ingress
  annotations:
    &lt;your-annotations-go-here&gt;
spec:
  rules:
     - http:
        paths:
          - path: &lt;path-1&gt;
            backend:
              serviceName: &lt;service1&gt;
              servicePort: &lt;service1-port&gt;
          - path: &lt;path-2&gt;
            backend:
              serviceName: &lt;service2&gt;
              servicePort: &lt;service2-port&gt;
</code></pre>

<p>The above YAML creates the following Ingress :</p>

<pre><code>kubectl get ingress -o wide 
NAME           HOSTS                ADDRESS   PORTS   AGE
mono-ingress   *                              80      10s
</code></pre>

<p>So, to sum up, <code>rules:</code> field shall contain an <code>array</code> (and topic starter missed single space char between "-" and "http", so it wasn't parsed as an <code>array</code>, but <code>map</code>)</p>

<p>Hope that helps.</p>
