contour: The "includes" function in HTTPProxy causes bad life-cycle management

The “includes” function in HTTPProxy causes bad life-cycle management

The “includes” can be used to delegate route definitions to sub-objects;

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
  name: kahttp-default
spec:
  virtualhost:
    fqdn: kahttp.com
    tls:
      secretName: contour-secret
  includes:
    - name: kahttp-default
    - name: kahttp-admin

In a larger site where route definitions are updates regularly this can be used to allow applications to provide their own route definition and add them to the virtual host when loaded and remove them when un-loaded.

The problem is that the “top” object containing the vhost and the “includes” array must be updated for these operations.

This update operation of the top object requires coordination between otherwise independent applications. To update the top object manually is not feasible in a larger sites.

Use Case

As an operator I want to be able to deploy a applications that adds a route definitions to a vhost with a simple install, e.g. with “helm”. When an application is removed it’s route definition shall be removed automatically.

As an application owner I want to use “secure backend” to protect my traffic.

Comparison with the Ingress object

K8s allows “Ingress” objects to specify the same vhost in multiple instances;

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kahttp-default
spec:
  tls:
  - hosts:
    - kahttp.com
    secretName: contour-secret
  rules:
  - host: kahttp.com
    http:
      paths:
      - path: /
        backend:
          serviceName: kahttp-ipv4
          servicePort: 80
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kahttp-admin
spec:
  tls:
  - hosts:
    - kahttp.com
    secretName: contour-secret
  rules:
  - host: kahttp.com
    http:
      paths:
      - path: /admin
        backend:
          serviceName: kahttp-admin
          servicePort: 80

Contour handles this nicely. An “admin” application can be deployed (and removed) independently and the route to “/admin” is updated automatically. The vhost can set with a value/parameter in a helm install.

But Contour supports backend encryption only for HTTPProxy.

Proposal

Allow to specify the relation in the sub-objects, example;

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
  name: kahttp-admin
spec:
  virtualhost:
    from:
	- name: kahttp-default
	  namespace: default
  routes:
    - conditions:
      - prefix: /admin
      services:
        - name: kahttp-admin
          port: 443
          weight: 1000
          validation:
            caSecret: kahttp-admin-ca
            subjectName: kahttp-admin.com

The “from” field is an array to be compliant with the current implementation where multiple “top” objects can include the same sub-object.

There are of course misconfigurations that must be checked but I leave them for the moment because I can’t think of anything unsolvable.

The Canary aspect

A spin-off I find really cool is the elegance of which canary testing can be made with this addition. To test a new kahttp-admin simply install a canary with something like;

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
  name: kahttp-admin-canary
spec:
  virtualhost:
    from:
	- name: kahttp-default
	  namespace: default
  routes:
    - conditions:
      - prefix: /admin
      services:
        - name: kahttp-admin-canary
          port: 443
          weight: 100
          validation:
            caSecret: kahttp-admin-ca
            subjectName: kahttp-admin.com

The canary will grab ~10% of the traffic to “/admin”. After a test period the canary can simply be removed and traffic goes back to normal. If the canary is ok the normal backend application can be updated.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 22 (19 by maintainers)

Most upvoted comments

There are a number of ways to think about security policy and HTTPProxy can support many different policies. Fundamentally, vhosts are global to the cluster, and may even be global to an organization or exposed to the internet. So, we expect that many organizations will need controls around these. Because of this, the HTTPProxy requires that control over the proxy configuration be explicitly delegated from the root to the leaf objects. If we allowed the leaf to attach itself to the vhost, it would be harder to reason about and implement the organizational policy. Most likely, you would need some sort of admission control to ensure that only authorized routes attached themselves to the vhost.

When you create a vhost (i.e. a root HTTPProxy), you can delegate the definition of all the routes if you want to. Using your example above:

---
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
  name: kahttp-default
  namespace: protected
spec:
  virtualhost:
    fqdn: kahttp.com
    tls:
      secretName: contour-secret
  includes:
    - name: kahttp-delegate
       namespace: application

---
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
  name: kahttp-delegate
  namespace: application
spec:
  includes:
    - name: kahttp-default
    - name: kahttp-admin

Now, when you want to use includes to adjust the routes, you only need to edit the kahttp-delegate document, not the root HTTPProxy.

The problem is that the “top” object containing the vhost and the “includes” array must be updated for these operations.

You are right that there are some properties (specifically TLS and vhost policy) that can only me set on the root document. However, because includes can be nested to an arbitrary degree, it is possible to create a document tree where the top document rarely needs to be updated.

So, your current request is:

  • as an application owner, I want to be able to add routes that will be associated with an FQDN without having to update any other configuration.
  • any matching configuration should be transparently merged in to the resulting config across all matches.

Is that correct? I’d like to make sure I have the correct thing before we go any further.