From f75ef4a576d4245b1298ea75e6cdc40657c2395c Mon Sep 17 00:00:00 2001 From: bprashanth Date: Fri, 27 Jan 2017 17:51:00 -0800 Subject: [PATCH] Add a tls-termination example --- examples/PREREQUISITES.md | 131 ++++++++++++++++++ examples/README.md | 4 +- examples/health-checks/gce.md | 3 + examples/http-svc.yaml | 35 +++++ examples/tls-termination/gce-tls-ingress.yaml | 15 ++ examples/tls-termination/gce.md | 78 +++++++++++ .../tls-termination/nginx-tls-ingress.yaml | 18 +++ examples/tls-termination/nginx.md | 74 ++++++++++ 8 files changed, 357 insertions(+), 1 deletion(-) create mode 100644 examples/PREREQUISITES.md create mode 100644 examples/health-checks/gce.md create mode 100644 examples/http-svc.yaml create mode 100644 examples/tls-termination/gce-tls-ingress.yaml create mode 100644 examples/tls-termination/gce.md create mode 100644 examples/tls-termination/nginx-tls-ingress.yaml create mode 100644 examples/tls-termination/nginx.md diff --git a/examples/PREREQUISITES.md b/examples/PREREQUISITES.md new file mode 100644 index 000000000..bbb066ee4 --- /dev/null +++ b/examples/PREREQUISITES.md @@ -0,0 +1,131 @@ +# Prerequisites + +Many of the examples in this directory have common prerequisites. + +## Deploying a controller + +Unless you're running on a cloudprovider that supports Ingress out of the box +(eg: GCE/GKE), you will need to deploy a controller. You can do so following +[these instructions](/examples/deployment). + +## Firewall rules + +If you're using a bare-metal controller (eg the nginx ingress controller), you +will need to create a firewall rule that targets port 80/443 on the specific VMs +the nginx controller is running on. On cloudproviders, the respective backend +will auto-create firewall rules for your Ingress. + +## TLS certificates + +Unless otherwise mentioned, the TLS secret used in examples is a 2048 bit RSA +key/cert pair with an arbitrarily chosen hostname, created as follows + +```console +$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc" +Generating a 2048 bit RSA private key +......................................................................................................................................+++ +....................................................................+++ +writing new private key to 'tls.key' +----- + +$ kubectl create secret tls tls-secret --key tls.key --cert tls.crt +secret "tls-secret" created +``` + +## Test HTTP Service + +All examples that require a test HTTP Service use the standard echoheaders pod, +which you can deploy as follows + +```console +$ kubectl create -f http-svc.yaml +service "http-svc" created +replicationcontroller "http-svc" created + +$ kubectl get po +NAME READY STATUS RESTARTS AGE +echoheaders-p1t3t 1/1 Running 0 1d + +$ kubectl get svc +NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE +echoheaders 10.0.122.116 80/TCP 1d +``` + +You can test that the HTTP Service works by exposing it temporarily +```console +$ kubectl patch svc echoheaders -p '{"spec":{"type": "LoadBalancer"}}' +"echoheaders" patched + +$ kubectl get svc echoheaders +NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE +echoheaders 10.0.122.116 80:32100/TCP 1d + +$ kubectl describe svc echoheaders +Name: echoheaders +Namespace: default +Labels: app=echoheaders +Selector: app=echoheaders +Type: LoadBalancer +IP: 10.0.122.116 +LoadBalancer Ingress: 108.59.87.136 +Port: http 80/TCP +NodePort: http 32100/TCP +Endpoints: 10.180.1.6:8080 +Session Affinity: None +Events: + FirstSeen LastSeen Count From SubObjectPath Type Reason Message + --------- -------- ----- ---- ------------- -------- ------ ------- + 1m 1m 1 {service-controller } Normal Type ClusterIP -> LoadBalancer + 1m 1m 1 {service-controller } Normal CreatingLoadBalancer Creating load balancer + 16s 16s 1 {service-controller } Normal CreatedLoadBalancer Created load balancer + +$ curl 108.59.87.126 +CLIENT VALUES: +client_address=10.240.0.3 +command=GET +real path=/ +query=nil +request_version=1.1 +request_uri=http://108.59.87.136:8080/ + +SERVER VALUES: +server_version=nginx: 1.9.11 - lua: 10001 + +HEADERS RECEIVED: +accept=*/* +host=108.59.87.136 +user-agent=curl/7.46.0 +BODY: +-no body in request- + +$ kubectl patch svc echoheaders -p '{"spec":{"type": "NodePort"}}' +"echoheaders" patched +``` + +## Ingress Class + +If you have multiple Ingress controllers in a single cluster, you can pick one +by specifying the `ingress.class` annotation, eg creating an Ingress with an +annotation like + +```yaml +metadata: + name: foo + annotations: + kubernetes.io/ingress.class: "gce" +``` + +will target the GCE controller, forcing the nginx controller to ignore it, while +an annotation like + +```yaml +metadata: + name: foo + annotations: + kubernetes.io/ingress.class: "nginx" +``` + +will target the nginx controller, forcing the GCE controller to ignore it. + +__Note__: Deploying multiple ingress controller and not specifying the +annotation will result in both controllers fighting to satisfy the Ingress. diff --git a/examples/README.md b/examples/README.md index 78e0adf65..2a00a24d7 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,6 +1,8 @@ # Ingress examples -A catalog of examples on how to run, configure and scale Ingress. +This directory contains a catalog of examples on how to run, configure and +scale Ingress. Please review the [prerequisities](prerequisites.md) before +trying them. ## Basic cross platform diff --git a/examples/health-checks/gce.md b/examples/health-checks/gce.md new file mode 100644 index 000000000..9d3831a6f --- /dev/null +++ b/examples/health-checks/gce.md @@ -0,0 +1,3 @@ +# Health checks for the GCE controller + +Placeholder diff --git a/examples/http-svc.yaml b/examples/http-svc.yaml new file mode 100644 index 000000000..c76d21d01 --- /dev/null +++ b/examples/http-svc.yaml @@ -0,0 +1,35 @@ +apiVersion: v1 +kind: Service +metadata: + name: http-svc + labels: + app: http-svc +spec: + type: NodePort + ports: + - port: 80 + # This port needs to be available on all nodes in the cluster + nodePort: 30301 + targetPort: 8080 + protocol: TCP + name: http + selector: + app: http-svc +--- +apiVersion: v1 +kind: ReplicationController +metadata: + name: http-svc +spec: + replicas: 2 + template: + metadata: + labels: + app: http-svc + spec: + containers: + - name: http-svc + image: gcr.io/google_containers/echoserver:1.3 + ports: + - containerPort: 8080 + diff --git a/examples/tls-termination/gce-tls-ingress.yaml b/examples/tls-termination/gce-tls-ingress.yaml new file mode 100644 index 000000000..705a17d36 --- /dev/null +++ b/examples/tls-termination/gce-tls-ingress.yaml @@ -0,0 +1,15 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: test + annotations: + kubernetes.io/ingress.class: "gce" +spec: + tls: + # This assumes tls-secret exists. + - secretName: tls-secret + backend: + # This assumes http-svc exists and routes to healthy endpoints. + serviceName: http-svc + servicePort: 80 + diff --git a/examples/tls-termination/gce.md b/examples/tls-termination/gce.md new file mode 100644 index 000000000..ef2b99544 --- /dev/null +++ b/examples/tls-termination/gce.md @@ -0,0 +1,78 @@ +# TLS termination + +This example demonstrates how to terminate TLS through the GCE Ingress controller. + +## Prerequisites + +You need a [TLS cert](/examples/PREREQUISITES.md#tls-certificates) and a [test HTTP service](/examples/PREREQUISITES.md#test-http-service) for this example. +You will also need to make sure you Ingress targets exactly one Ingress +controller by specifying the [ingress.class annotation](/examples/PREREQUISITES.md#ingress-class). + +## Deployment + +The following command instructs the controller to terminate traffic using +the provided TLS cert, and forward un-encrypted HTTP traffic to the test +HTTP service. + +```console +$ kubectl create -f gce-tls-ingress.yaml +``` + +## Validation + +You can confirm that the Ingress works. + +```console +$ kubectl describe ing gce-test +Name: gce-test +Namespace: default +Address: 35.186.221.137 +Default backend: http-svc:80 (10.180.1.9:8080,10.180.3.6:8080) +TLS: + tls-secret terminates +Rules: + Host Path Backends + ---- ---- -------- + * * http-svc:80 (10.180.1.9:8080,10.180.3.6:8080) +Annotations: + target-proxy: k8s-tp-default-gce-test--32658fa96c080068 + url-map: k8s-um-default-gce-test--32658fa96c080068 + backends: {"k8s-be-30301--32658fa96c080068":"Unknown"} + forwarding-rule: k8s-fw-default-gce-test--32658fa96c080068 + https-forwarding-rule: k8s-fws-default-gce-test--32658fa96c080068 + https-target-proxy: k8s-tps-default-gce-test--32658fa96c080068 + static-ip: k8s-fw-default-gce-test--32658fa96c080068 +Events: + FirstSeen LastSeen Count From SubObjectPath Type Reason Message + --------- -------- ----- ---- ------------- -------- ------ ------- + 2m 2m 1 {loadbalancer-controller } Normal ADD default/gce-test + 1m 1m 1 {loadbalancer-controller } Normal CREATE ip: 35.186.221.137 + 1m 1m 3 {loadbalancer-controller } Normal Service default backend set to http-svc:30301 + +$ curl 35.186.221.137 -k +curl 35.186.221.137 -L +curl: (60) SSL certificate problem: self signed certificate +More details here: http://curl.haxx.se/docs/sslcerts.html + +$ curl 35.186.221.137 -kl +CLIENT VALUES: +client_address=10.240.0.3 +command=GET +real path=/ +query=nil +request_version=1.1 +request_uri=http://35.186.221.137:8080/ + +SERVER VALUES: +server_version=nginx: 1.9.11 - lua: 10001 + +HEADERS RECEIVED: +accept=*/* +connection=Keep-Alive +host=35.186.221.137 +user-agent=curl/7.46.0 +via=1.1 google +x-cloud-trace-context=bfa123130fd623989cca0192e43d9ba4/8610689379063045825 +x-forwarded-for=104.132.0.80, 35.186.221.137 +x-forwarded-proto=https +``` diff --git a/examples/tls-termination/nginx-tls-ingress.yaml b/examples/tls-termination/nginx-tls-ingress.yaml new file mode 100644 index 000000000..c73452dd6 --- /dev/null +++ b/examples/tls-termination/nginx-tls-ingress.yaml @@ -0,0 +1,18 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: nginx-test + annotations: + kubernetes.io/ingress.class: "nginx" +spec: + tls: + # This assumes tls-secret exists. + - secretName: tls-secret + rules: + - http: + paths: + - backend: + # This assumes http-svc exists and routes to healthy endpoints. + serviceName: http-svc + servicePort: 80 + diff --git a/examples/tls-termination/nginx.md b/examples/tls-termination/nginx.md new file mode 100644 index 000000000..b116cad09 --- /dev/null +++ b/examples/tls-termination/nginx.md @@ -0,0 +1,74 @@ +# TLS termination + +This example demonstrates how to terminate TLS through the nginx Ingress controller. + +## Prerequisites + +You need a [TLS cert](/examples/PREREQUISITES.md#tls-certificates) and a [test HTTP service](/examples/PREREQUISITES.md#test-http-service) for this example. +You will also need to make sure you Ingress targets exactly one Ingress +controller by specifying the [ingress.class annotation](/examples/PREREQUISITES.md#ingress-class). + +## Deployment + +The following command instructs the controller to terminate traffic using +the provided TLS cert, and forward un-encrypted HTTP traffic to the test +HTTP service. + +```console +$ kubectl create -f nginx-tls-ingress.yaml +``` + +## Validation + +You can confirm that the Ingress works. + +```console +$ kubectl describe ing nginx-test +Name: nginx-test +Namespace: default +Address: 104.198.183.6 +Default backend: default-http-backend:80 (10.180.0.4:8080,10.240.0.2:8080) +TLS: + tls-secret terminates +Rules: + Host Path Backends + ---- ---- -------- + * + http-svc:80 () +Annotations: +Events: + FirstSeen LastSeen Count From SubObjectPath Type Reason Message + --------- -------- ----- ---- ------------- -------- ------ ------- + 7s 7s 1 {nginx-ingress-controller } Normal CREATE default/nginx-test + 7s 7s 1 {nginx-ingress-controller } Normal UPDATE default/nginx-test + 7s 7s 1 {nginx-ingress-controller } Normal CREATE ip: 104.198.183.6 + 7s 7s 1 {nginx-ingress-controller } Warning MAPPING Ingress rule 'default/nginx-test' contains no path definition. Assuming / + +$ curl 104.198.183.6 -L +curl: (60) SSL certificate problem: self signed certificate +More details here: http://curl.haxx.se/docs/sslcerts.html + +$ curl 104.198.183.6 -Lk +CLIENT VALUES: +client_address=10.240.0.4 +command=GET +real path=/ +query=nil +request_version=1.1 +request_uri=http://35.186.221.137:8080/ + +SERVER VALUES: +server_version=nginx: 1.9.11 - lua: 10001 + +HEADERS RECEIVED: +accept=*/* +connection=Keep-Alive +host=35.186.221.137 +user-agent=curl/7.46.0 +via=1.1 google +x-cloud-trace-context=f708ea7e369d4514fc90d51d7e27e91d/13322322294276298106 +x-forwarded-for=104.132.0.80, 35.186.221.137 +x-forwarded-proto=https +BODY: + +```