title: Why does this setup with contour on kubernetes (GKE) result in 2 functioning external IPs?
body: <p>I've been experimenting with <a href="https://github.com/heptio/contour" rel="nofollow noreferrer">contour</a> as an alternative ingress controller on a test GKE kubernetes cluster.</p>
  
  <p>Following the contour <a href="https://github.com/heptio/contour/blob/master/docs/deploy-options.md" rel="nofollow noreferrer">deployment docs</a> with a few modifications, I've got a working setup serving test HTTP responses.</p>
  
  <p>First, I created a "helloworld" pod that serves http responses, exposed via a NodePort service and an ingress:</p>
  
  <pre><code>apiVersion: extensions/v1beta1
  kind: Deployment
  metadata:
      name: helloworld
  spec:
    replicas: 4
    template:
      metadata:
        labels:
          app: helloworld
      spec:
        containers:
          - name: "helloworld-http"
            image: "nginxdemos/hello:plain-text"
            imagePullPolicy: Always
            resources:
              requests:
                cpu: 250m
                memory: 256Mi
        affinity:
          podAntiAffinity:
            preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                  - key: app
                    operator: In
                    values:
                    - helloworld
                topologyKey: "kubernetes.io/hostname"
  ---
  apiVersion: v1
  kind: Service
  metadata:
    name: helloworld-svc
  spec:
    ports:
    - port: 80
      protocol: TCP
      targetPort: 80
    selector:
      app: helloworld
    sessionAffinity: None
    type: NodePort
  ---
  apiVersion: extensions/v1beta1
  kind: Ingress
  metadata:
    name: helloworld-ingress
  spec:
    backend:
      serviceName: helloworld-svc
      servicePort: 80
  </code></pre>
  
  <p>Then, I created a deployment for <code>contour</code> that's directly copied from their docs:</p>
  
  <pre><code>apiVersion: v1
  kind: Namespace
  metadata:
    name: heptio-contour
  ---
  apiVersion: v1
  kind: ServiceAccount
  metadata:
    name: contour
    namespace: heptio-contour
  ---
  apiVersion: extensions/v1beta1
  kind: Deployment
  metadata:
    labels:
      app: contour
    name: contour
    namespace: heptio-contour
  spec:
    selector:
      matchLabels:
        app: contour
    replicas: 2
    template:
      metadata:
        labels:
          app: contour
        annotations:
          prometheus.io/scrape: "true"
          prometheus.io/port: "9001"
          prometheus.io/path: "/stats"
          prometheus.io/format: "prometheus"
      spec:
        containers:
        - image: docker.io/envoyproxy/envoy-alpine:v1.6.0
          name: envoy
          ports:
          - containerPort: 8080
            name: http
          - containerPort: 8443
            name: https
          command: ["envoy"]
          args: ["-c", "/config/contour.yaml", "--service-cluster", "cluster0", "--service-node", "node0", "-l", "info", "--v2-config-only"]
          volumeMounts:
          - name: contour-config
            mountPath: /config
        - image: gcr.io/heptio-images/contour:master
          imagePullPolicy: Always
          name: contour
          command: ["contour"]
          args: ["serve", "--incluster"]
        initContainers:
        - image: gcr.io/heptio-images/contour:master
          imagePullPolicy: Always
          name: envoy-initconfig
          command: ["contour"]
          args: ["bootstrap", "/config/contour.yaml"]
          volumeMounts:
          - name: contour-config
            mountPath: /config
        volumes:
        - name: contour-config
          emptyDir: {}
        dnsPolicy: ClusterFirst
        serviceAccountName: contour
        terminationGracePeriodSeconds: 30
        affinity:
          podAntiAffinity:
            preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchLabels:
                    app: contour
                topologyKey: kubernetes.io/hostname
  ---
  apiVersion: v1
  kind: Service
  metadata:
    name: contour
    namespace: heptio-contour
  spec:
   ports:
   - port: 80
     name: http
     protocol: TCP
     targetPort: 8080
   - port: 443
     name: https
     protocol: TCP
     targetPort: 8443
   selector:
     app: contour
   type: LoadBalancer
  ---
  </code></pre>
  
  <p>The default and heptio-contour namespaces now look like this:</p>
  
  <pre><code>$ kubectl get pods,svc,ingress -n default
  NAME                              READY     STATUS    RESTARTS   AGE
  pod/helloworld-7ddc8c6655-6vgdw   1/1       Running   0          6h
  pod/helloworld-7ddc8c6655-92j7x   1/1       Running   0          6h
  pod/helloworld-7ddc8c6655-mlvmc   1/1       Running   0          6h
  pod/helloworld-7ddc8c6655-w5g7f   1/1       Running   0          6h
  
  NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
  service/helloworld-svc   NodePort    10.59.240.105   &lt;none&gt;        80:31481/TCP   34m
  service/kubernetes       ClusterIP   10.59.240.1     &lt;none&gt;        443/TCP        7h
  
  NAME                                    HOSTS     ADDRESS         PORTS     AGE
  ingress.extensions/helloworld-ingress   *         y.y.y.y   80        34m
  
  $ kubectl get pods,svc,ingress -n heptio-contour
  NAME                          READY     STATUS    RESTARTS   AGE
  pod/contour-9d758b697-kwk85   2/2       Running   0          34m
  pod/contour-9d758b697-mbh47   2/2       Running   0          34m
  
  NAME              TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)                      AGE
  service/contour   LoadBalancer   10.59.250.54   x.x.x.x   80:30882/TCP,443:32746/TCP   34m
  </code></pre>
  
  <p>There's 2 publicly routable IP addresses:</p>
  
  <ul>
  <li>x.x.x.x - a GCE TCP load balancer that forwards to the contour pods</li>
  <li>y.y.y.y - a GCE HTTP load balancer that forwards to the helloworld pods via the helloworld-ingress</li>
  </ul>
  
  <p>A <code>curl</code> on both public IPs returns a valid HTTP response from the helloworld pods.</p>
  
  <pre><code># the TCP load balancer
  $ curl -v x.x.x.x
  * Rebuilt URL to: x.x.x.x/  
  *   Trying x.x.x.x...
  * TCP_NODELAY set
  * Connected to x.x.x.x (x.x.x.x) port 80 (#0)
  &gt; GET / HTTP/1.1
  &gt; Host: x.x.x.x
  &gt; User-Agent: curl/7.58.0
  &gt; Accept: */*
  &gt;
  &lt; HTTP/1.1 200 OK
  &lt; server: envoy
  &lt; date: Mon, 07 May 2018 14:14:39 GMT
  &lt; content-type: text/plain
  &lt; content-length: 155
  &lt; expires: Mon, 07 May 2018 14:14:38 GMT
  &lt; cache-control: no-cache
  &lt; x-envoy-upstream-service-time: 1
  &lt;
  Server address: 10.56.4.6:80
  Server name: helloworld-7ddc8c6655-w5g7f
  Date: 07/May/2018:14:14:39 +0000
  URI: /
  Request ID: ec3aa70e4155c396e7051dc972081c6a
  
  # the HTTP load balancer
  $ curl http://y.y.y.y 
  * Rebuilt URL to: y.y.y.y/
  *   Trying y.y.y.y...
  * TCP_NODELAY set
  * Connected to y.y.y.y (y.y.y.y) port 80 (#0)
  &gt; GET / HTTP/1.1
  &gt; Host: y.y.y.y
  &gt; User-Agent: curl/7.58.0
  &gt; Accept: */*
  &gt; 
  &lt; HTTP/1.1 200 OK
  &lt; Server: nginx/1.13.8
  &lt; Date: Mon, 07 May 2018 14:14:24 GMT
  &lt; Content-Type: text/plain
  &lt; Content-Length: 155
  &lt; Expires: Mon, 07 May 2018 14:14:23 GMT
  &lt; Cache-Control: no-cache
  &lt; Via: 1.1 google
  &lt; 
  Server address: 10.56.2.8:80
  Server name: helloworld-7ddc8c6655-mlvmc
  Date: 07/May/2018:14:14:24 +0000
  URI: /
  Request ID: 41b1151f083eaf30368cf340cfbb92fc
  </code></pre>
  
  <p>Is it by design that I have two public IPs? Which one should I use for customers? Can I choose based on my preference between a TCP and HTTP load balancer? </p>