Envoy: An open-source edge and service proxy, designed for cloud-native applications.
Contour: Contour is an open-source Kubernetes ingress controller providing the control plane for the Envoy edge and service proxy.
Installation
The recommended installation is for contour to run as a Deployment and Envoy run as a Daemonset.
kubectl apply -f https://projectcontour.io/quickstart/contour.yaml
# namespace/projectcontour created
# serviceaccount/contour created
# serviceaccount/envoy created
# configmap/contour created
# customresourcedefinition.apiextensions.k8s.io/extensionservices.projectcontour.io created
# customresourcedefinition.apiextensions.k8s.io/httpproxies.projectcontour.io created
# customresourcedefinition.apiextensions.k8s.io/tlscertificatedelegations.projectcontour.io created
# serviceaccount/contour-certgen created
# rolebinding.rbac.authorization.k8s.io/contour created
# role.rbac.authorization.k8s.io/contour-certgen created
# job.batch/contour-certgen-v1.13.1 created
# clusterrolebinding.rbac.authorization.k8s.io/contour created
# clusterrole.rbac.authorization.k8s.io/contour created
# service/contour created
# service/envoy created
# deployment.apps/contour created
# daemonset.apps/envoy created
kubectl get -n projectcontour service envoy -o wide
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
# envoy LoadBalancer 10.96.245.72 <pending> 80:31066/TCP,443:31774/TCP 66s app=envoy
Test with HTTPProxy
kubectl apply -f https://projectcontour.io/examples/kuard-httpproxy.yaml
# deployment.apps/kuard created
# service/kuard created
# httpproxy.projectcontour.io/kuard created
kubectl get po,svc,httpproxy -l app=kuard
NAME READY STATUS RESTARTS AGE
pod/kuard-798585497b-469qs 1/1 Running 0 26m
pod/kuard-798585497b-ntkq5 1/1 Running 0 26m
pod/kuard-798585497b-vwgjd 1/1 Running 0 26m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kuard ClusterIP 10.105.243.149 <none> 80/TCP 26m
NAME FQDN TLS SECRET STATUS STATUS DESCRIPTION
httpproxy.projectcontour.io/kuard kuard.local valid Valid HTTPProxy
kubectl get httpproxy
NAME FQDN TLS SECRET STATUS STATUS DESCRIPTION
kuard kuard.local valid Valid HTTPProxy
kubectl edit httpproxy kuard
httpproxy.projectcontour.io/kuard edited
kubectl get httpproxy
NAME FQDN TLS SECRET STATUS STATUS DESCRIPTION
kuard kuardapp.com valid Valid HTTPProxy
sudo vim /etc/hosts
192.168.64.10 kuardapp.com
curl kuardapp.com
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>KUAR Demo</title>
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
<link rel="stylesheet" href="/static/css/styles.css">
<script>
var pageContext = {"hostname":"kuard-798585497b-vwgjd","addrs":["172.17.0.19"],"version":"v0.8.1-1","versionColor":"hsl(18,100%,50%)","requestDump":"GET / HTTP/1.1\r\nHost: kuardapp.com\r\nAccept: */*\r\nContent-Length: 0\r\nUser-Agent: curl/7.64.1\r\nX-Envoy-Expected-Rq-Timeout-Ms: 15000\r\nX-Envoy-Internal: true\r\nX-Forwarded-For: 192.168.64.1\r\nX-Forwarded-Proto: http\r\nX-Request-Id: 0521f208-808f-4759-9f29-728fe636be9d\r\nX-Request-Start: t=1615859840.336","requestProto":"HTTP/1.1","requestAddr":"172.17.0.16:46890"}
</script>
</head>
<svg style="position: absolute; width: 0; height: 0; overflow: hidden;" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol id="icon-power" viewBox="0 0 32 32">
<title>power</title>
<path class="path1" d="M12 0l-12 16h12l-8 16 28-20h-16l12-12z"></path>
</symbol>
<symbol id="icon-notification" viewBox="0 0 32 32">
<title>notification</title>
<path class="path1" d="M16 3c-3.472 0-6.737 1.352-9.192 3.808s-3.808 5.72-3.808 9.192c0 3.472 1.352 6.737 3.808 9.192s5.72 3.808 9.192 3.808c3.472 0 6.737-1.352 9.192-3.808s3.808-5.72 3.808-9.192c0-3.472-1.352-6.737-3.808-9.192s-5.72-3.808-9.192-3.808zM16 0v0c8.837 0 16 7.163 16 16s-7.163 16-16 16c-8.837 0-16-7.163-16-16s7.163-16 16-16zM14 22h4v4h-4zM14 6h4v12h-4z"></path>
</symbol>
</defs>
</svg>
<body>
<div id="root"></div>
<script src="/built/bundle.js" type="text/javascript"></script>
</body>
</html>
curl -H 'Host: kuardapp.com' http://192.168.64.10
- Example apiVersion: projectcontour.io/v1
kind: HTTPProxy
apiVersion: v1
items:
- apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"projectcontour.io/v1","kind":"HTTPProxy","metadata":{"annotations":{},"labels":{"app":"kuard"},"name":"kuard","namespace":"default"},"spec":{"routes":[{"conditions":[{"prefix":"/"}],"services":[{"name":"kuard","port":80}]}],"virtualhost":{"fqdn":"kuard.local"}}}
creationTimestamp: "2021-03-16T01:29:11Z"
generation: 2
labels:
app: kuard
managedFields:
- apiVersion: projectcontour.io/v1
fieldsType: FieldsV1
fieldsV1:
f:status:
.: {}
f:conditions:
.: {}
k:{"type":"Valid"}:
.: {}
f:lastTransitionTime: {}
f:message: {}
f:observedGeneration: {}
f:reason: {}
f:status: {}
f:type: {}
f:currentStatus: {}
f:description: {}
f:loadBalancer: {}
manager: contour
operation: Update
time: "2021-03-16T01:29:11Z"
- apiVersion: projectcontour.io/v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.: {}
f:kubectl.kubernetes.io/last-applied-configuration: {}
f:labels:
.: {}
f:app: {}
f:spec:
.: {}
f:routes: {}
f:virtualhost:
.: {}
f:fqdn: {}
manager: kubectl-client-side-apply
operation: Update
time: "2021-03-16T01:29:11Z"
- apiVersion: projectcontour.io/v1
fieldsType: FieldsV1
fieldsV1:
f:spec:
f:virtualhost:
f:fqdn: {}
manager: kubectl-edit
operation: Update
time: "2021-03-16T01:54:28Z"
name: kuard
namespace: default
resourceVersion: "197936"
uid: 0ff0be76-d434-430f-bbaf-50a28ee5d635
spec:
routes:
- conditions:
- prefix: /
services:
- name: kuard
port: 80
virtualhost:
fqdn: kuardapp.com
status:
conditions:
- lastTransitionTime: "2021-03-16T01:54:28Z"
message: Valid HTTPProxy
observedGeneration: 2
reason: Valid
status: "True"
type: Valid
currentStatus: valid
description: Valid HTTPProxy
loadBalancer: {}
kind: List
metadata:
resourceVersion: ""
selfLink: ""
HTTPProxy API Specification
There are a number of working examples of HTTPProxy objects in the examples/example-workload
directory.
We will use these examples as a mechanism to describe HTTPProxy API functionality.
Virtual Host Configuration
Fully Qualified Domain Name
Similar to Ingress, HTTPProxy support name-based virtual hosting. Name-based virtual hosts use multiple host names with the same IP address.
foo.bar.com --| |-> foo.bar.com s1:80
| 178.91.123.132 |
bar.foo.com --| |-> bar.foo.com s2:80
Unlike Ingress, HTTPProxy only support a single root domain per HTTPProxy object. As an example, this Ingress object:
Example
# httpproxy-name.yaml
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: name-example-foo
namespace: default
spec:
virtualhost:
fqdn: foo1.bar.com
routes:
- services:
- name: s1
port: 80
---
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: name-example-bar
namespace: default
spec:
virtualhost:
fqdn: bar1.bar.com
routes:
- services:
- name: s2
port: 80
Real
# httpproxy-name.yaml
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: board-frontend
namespace: front
spec:
virtualhost:
fqdn: board.front.com
routes:
- services:
- name: board-fe-service
port: 8080
---
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: board-api
namespace: api
spec:
virtualhost:
fqdn: board.api.com
routes:
- services:
- name: board-api-service
port: 8080