參考:
https://kubernetes.github.io/ingress-nginx/examples/
https://github.com/kubernetes/ingress-nginx/tree/main/docs/examples
https://cloud.tencent.com/developer/article/1761376html
除非另有說明,在示例中使用的TLS祕密是2048位RSA密鑰/證書對與任意選擇的主機名,建立以下:node
$ openssl req -x509 -sha256 -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
注意:若是使用CA認證,以下所述,您將須要與CA簽署服務器證書nginx
CA認證也被稱爲相互身份驗證容許服務器和客戶端經過一個共同的CA.驗證對方的身份git
咱們有一個一般從證書頒發機構得到的 CA 證書,並使用它來簽署咱們的服務器證書和客戶端證書。 那麼每次咱們要訪問咱們的後端時,都必須經過客戶端證書。github
這些說明基於如下博客(https://medium.com/@awkwardferny/configuring-certificate-based-mutual-authentication-with-kubernetes-ingress-nginx-20e7e38fdfca)json
生成 CA 密鑰和證書:後端
openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 356 -nodes -subj '/CN=My Cert Authority'
生成服務器密鑰和證書並使用 CA 證書籤名:api
openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN=mydomain.com' openssl x509 -req -sha256 -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
生成客戶端密鑰和證書並使用 CA 證書籤名:安全
openssl req -new -newkey rsa:4096 -keyout client.key -out client.csr -nodes -subj '/CN=My Client' openssl x509 -req -sha256 -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out client.crt
完成後,您能夠繼續按照此處(https://kubernetes.github.io/ingress-nginx/examples/auth/client-certs/#creating-certificate-secrets)的說明進行操做。服務器
全部須要測試 HTTP 服務的示例都使用標準的 http-svc pod,您能夠按以下方式部署:
$ kubectl create -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/docs/examples/http-svc.yaml service "http-svc" created replicationcontroller "http-svc" created $ kubectl get po NAME READY STATUS RESTARTS AGE http-svc-p1t3t 1/1 Running 0 1d $ kubectl get svc NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE http-svc 10.0.122.116 <pending> 80:30301/TCP 1d
您能夠經過暫時公開它來測試 HTTP 服務是否有效:
$ kubectl patch svc http-svc -p '{"spec":{"type": "LoadBalancer"}}' "http-svc" patched $ kubectl get svc http-svc NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE http-svc 10.0.122.116 <pending> 80:30301/TCP 1d $ kubectl describe svc http-svc Name: http-svc Namespace: default Labels: app=http-svc Selector: app=http-svc Type: LoadBalancer IP: 10.0.122.116 LoadBalancer Ingress: 108.59.87.136 Port: http 80/TCP NodePort: http 30301/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.136 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 http-svc -p '{"spec":{"type": "NodePort"}}' "http-svc" patched
示例:
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: nginx-test annotations: nginx.ingress.kubernetes.io/affinity: "cookie" nginx.ingress.kubernetes.io/session-cookie-name: "route" nginx.ingress.kubernetes.io/session-cookie-expires: "172800" nginx.ingress.kubernetes.io/session-cookie-max-age: "172800" spec: rules: - host: stickyingress.example.com http: paths: - backend: serviceName: http-svc servicePort: 80 path: /
驗證:
$ kubectl describe ing nginx-test Name: nginx-test Namespace: default Address: Default backend: default-http-backend:80 (10.180.0.4:8080,10.240.0.2:8080) Rules: Host Path Backends ---- ---- -------- stickyingress.example.com / nginx-service:80 (<none>) Annotations: affinity: cookie session-cookie-name: INGRESSCOOKIE session-cookie-expires: 172800 session-cookie-max-age: 172800 Events: FirstSeen LastSeen Count From SubObjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 7s 7s 1 {nginx-ingress-controller } Normal CREATE default/nginx-test $ curl -I http://stickyingress.example.com HTTP/1.1 200 OK Server: nginx/1.11.9 Date: Fri, 10 Feb 2017 14:11:12 GMT Content-Type: text/html Content-Length: 612 Connection: keep-alive Set-Cookie: INGRESSCOOKIE=a9907b79b248140b56bb13723f72b67697baac3d; Expires=Sun, 12-Feb-17 14:11:12 GMT; Max-Age=172800; Path=/; HttpOnly Last-Modified: Tue, 24 Jan 2017 14:02:19 GMT ETag: "58875e6b-264" Accept-Ranges: bytes
$ htpasswd -c auth foo New password: <bar> New password: Re-type new password: Adding password for user foo
$ kubectl create secret generic basic-auth --from-file=auth secret "basic-auth" created
$ kubectl get secret basic-auth -o yaml apiVersion: v1 data: auth: Zm9vOiRhcHIxJE9GRzNYeWJwJGNrTDBGSERBa29YWUlsSDkuY3lzVDAK kind: Secret metadata: name: basic-auth namespace: default type: Opaque
echo " apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: ingress-with-auth annotations: # type of authentication nginx.ingress.kubernetes.io/auth-type: basic # name of the secret that contains the user/password definitions nginx.ingress.kubernetes.io/auth-secret: basic-auth # message to display with an appropriate context why the authentication is required nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - foo' spec: rules: - host: foo.bar.com http: paths: - path: / backend: serviceName: http-svc servicePort: 80 " | kubectl create -f -
$ curl -v http://10.2.29.4/ -H 'Host: foo.bar.com' * Trying 10.2.29.4... * Connected to 10.2.29.4 (10.2.29.4) port 80 (#0) > GET / HTTP/1.1 > Host: foo.bar.com > User-Agent: curl/7.43.0 > Accept: */* > < HTTP/1.1 401 Unauthorized < Server: nginx/1.10.0 < Date: Wed, 11 May 2016 05:27:23 GMT < Content-Type: text/html < Content-Length: 195 < Connection: keep-alive < WWW-Authenticate: Basic realm="Authentication Required - foo" < <html> <head><title>401 Authorization Required</title></head> <body bgcolor="white"> <center><h1>401 Authorization Required</h1></center> <hr><center>nginx/1.10.0</center> </body> </html> * Connection #0 to host 10.2.29.4 left intact
$ curl -v http://10.2.29.4/ -H 'Host: foo.bar.com' -u 'foo:bar' * Trying 10.2.29.4... * Connected to 10.2.29.4 (10.2.29.4) port 80 (#0) * Server auth using Basic with user 'foo' > GET / HTTP/1.1 > Host: foo.bar.com > Authorization: Basic Zm9vOmJhcg== > User-Agent: curl/7.43.0 > Accept: */* > < HTTP/1.1 200 OK < Server: nginx/1.10.0 < Date: Wed, 11 May 2016 06:05:26 GMT < Content-Type: text/plain < Transfer-Encoding: chunked < Connection: keep-alive < Vary: Accept-Encoding < CLIENT VALUES: client_address=10.2.29.4 command=GET real path=/ query=nil request_version=1.1 request_uri=http://foo.bar.com:8080/ SERVER VALUES: server_version=nginx: 1.9.11 - lua: 10001 HEADERS RECEIVED: accept=*/* connection=close host=foo.bar.com user-agent=curl/7.43.0 x-request-id=e426c7829ef9f3b18d40730857c3eddb x-forwarded-for=10.2.29.1 x-forwarded-host=foo.bar.com x-forwarded-port=80 x-forwarded-proto=http x-real-ip=10.2.29.1 x-scheme=http BODY: * Connection #0 to host 10.2.29.4 left intact -no body in request-
kubectl create secret generic ca-secret --from-file=ca.crt=ca.crt kubectl create secret generic tls-secret --from-file=tls.crt=server.crt --from-file=tls.key=server.key
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: annotations: # Enable client certificate authentication nginx.ingress.kubernetes.io/auth-tls-verify-client: "on" # Create the secret containing the trusted ca certificates nginx.ingress.kubernetes.io/auth-tls-secret: "default/ca-secret" # Specify the verification depth in the client certificates chain nginx.ingress.kubernetes.io/auth-tls-verify-depth: "1" # Specify an error page to be redirected to verification errors nginx.ingress.kubernetes.io/auth-tls-error-page: "http://www.mysite.com/error-cert.html" # Specify if certificates are passed to upstream server nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: "true" name: nginx-test namespace: default spec: rules: - host: mydomain.com http: paths: - backend: serviceName: http-svc servicePort: 80 path: / tls: - hosts: - mydomain.com secretName: tls-secret
$ kubectl create -f ingress.yaml ingress "external-auth" created $ kubectl get ing external-auth NAME HOSTS ADDRESS PORTS AGE external-auth external-auth-01.sample.com 172.17.4.99 80 13s $ kubectl get ing external-auth -o yaml apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/auth-url: https://httpbin.org/basic-auth/user/passwd creationTimestamp: 2016-10-03T13:50:35Z generation: 1 name: external-auth namespace: default resourceVersion: "2068378" selfLink: /apis/networking/v1beta1/namespaces/default/ingresses/external-auth uid: 5c388f1d-8970-11e6-9004-080027d2dc94 spec: rules: - host: external-auth-01.sample.com http: paths: - backend: serviceName: http-svc servicePort: 80 path: / status: loadBalancer: ingress: - ip: 172.17.4.99 $
... metadata: name: application annotations: nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth" nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri" ...
適用於特定Ingress:
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: nginx-configuration-snippet annotations: nginx.ingress.kubernetes.io/configuration-snippet: | more_set_headers "Request-Id: $req_id"; spec: rules: - host: custom.configuration.com http: paths: - backend: serviceName: http-svc servicePort: 80 path: /
使用於全部Ingress:
apiVersion: v1 data: X-Different-Name: "true" X-Request-Start: t=${msec} X-Using-Nginx-Controller: "true" kind: ConfigMap metadata: name: custom-headers namespace: ingress-nginx
apiVersion: v1 data: proxy-set-headers: "ingress-nginx/custom-headers" kind: ConfigMap metadata: name: ingress-nginx-controller namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx
使用 ConfigMap 能夠自定義 NGINX 配置。
例如,若是咱們想更改超時,咱們須要建立一個 ConfigMap:
$ cat configmap.yaml apiVersion: v1 data: proxy-connect-timeout: "10" proxy-read-timeout: "120" proxy-send-timeout: "120" kind: ConfigMap metadata: name: ingress-nginx-controller
若是 Configmap 更新,NGINX 將使用新配置從新加載。
調優參數:
net.core.somaxconn = 32768 net.ipv4.ip_local_port_range 1024 65000
此示例旨在演示使用 Init Container 來調整 sysctl 默認值 kubectl patch
kubectl patch deployment -n ingress-nginx nginx-ingress-controller \ --patch="$(curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/docs/examples/customization/sysctl/patch.json)"
變化:
在 NGINX 博客的一篇文章中(https://www.nginx.com/blog/tuning-nginx/),能夠看到對這些變化的解釋。
可使用如下注釋控制重寫:
從版本 0.22.0 開始,使用註解的入口定義 nginx.ingress.kubernetes.io/rewrite-target不向後兼容之前的版本。 在版本 0.22.0 及更高版本中,請求 URI 中須要傳遞到重寫路徑的任何子字符串都必須在 明肯定義 捕獲組中 。
捕獲的組 按時間順序保存在編號的佔位符中,格式爲 $1, $2 ... $n. 這些佔位符能夠用做參數 rewrite-target註解。
建立帶有重寫註釋的 Ingress 規則:
$ echo ' apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 name: rewrite namespace: default spec: rules: - host: rewrite.bar.com http: paths: - backend: serviceName: http-svc servicePort: 80 path: /something(/|$)(.*) ' | kubectl create -f -
在這個入口定義中,任何被捕獲的字符 (.*)將分配給佔位符 $2,而後將其用做參數 rewrite-target註解。
例如,上面的入口定義將致使如下重寫:
建立帶有 app-root 註釋的 Ingress 規則:
$ echo " apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/app-root: /app1 name: approot namespace: default spec: rules: - host: approot.bar.com http: paths: - backend: serviceName: http-svc servicePort: 80 path: / " | kubectl create -f -
檢查重寫是否有效
$ curl -I -k http://approot.bar.com/ HTTP/1.1 302 Moved Temporarily Server: nginx/1.11.10 Date: Mon, 13 Mar 2017 14:57:15 GMT Content-Type: text/html Content-Length: 162 Location: http://stickyingress.example.com/app1 Connection: keep-alive
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: todo namespace: default annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/app-root: /app/ nginx.ingress.kubernetes.io/rewrite-target: /$2 nginx.ingress.kubernetes.io/configuration-snippet: | ## 藉助 ingress-nginx 中的 configuration-snippet 來對靜態資源作一次跳轉 rewrite ^(/app)$ $1/ redirect; ## 應用在最後添加一個 / 這樣的 slash rewrite ^/stylesheets/(.*)$ /app/stylesheets/$1 redirect; rewrite ^/images/(.*)$ /app/images/$1 redirect; spec: rules: - host: todo.example.com http: paths: - backend: serviceName: todo servicePort: 3000 path: /app(/|$)(.*)
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: nginx-test spec: tls: - hosts: - foo.bar.com # This assumes tls-secret exists and the SSL # certificate contains a CN for foo.bar.com secretName: tls-secret rules: - host: foo.bar.com http: paths: - path: / backend: # This assumes http-svc exists and routes to healthy endpoints serviceName: http-svc servicePort: 80
$ 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 (<none>) 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:
在今天的大多數集羣中,默認狀況下,全部資源(例如 Deployments 和 ReplicatSets)都具備建立 pod 的權限。 然而,Kubernetes 提供了一種更細粒度的受權策略,稱爲 Pod 安全策略 (PSP) 。
PSP 容許集羣全部者定義每一個對象的權限,例如建立 pod。 若是您在集羣上啓用了 PSP,而且您部署了 ingress-nginx,您將須要爲 Deployment 提供建立 pod 的權限。
在應用任何對象以前,首先經過運行來應用 PSP 權限:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/docs/examples/psp/psp.yaml
注意:必須在建立 Deployment 和 ReplicaSet 以前授予 PSP 權限。
在平常工做中咱們常常須要對服務進行版本更新升級,因此咱們常常會使用到滾動升級、藍綠髮布、灰度發佈等不一樣的發佈操做。而 ingress-nginx 支持經過 Annotations 配置來實現不一樣場景下的灰度發佈和測試,能夠知足金絲雀發佈、藍綠部署與 A/B 測試等業務場景。ingress-nginx 的 Annotations 支持如下 4 種 Canary 規則:
nginx.ingress.kubernetes.io/canary-by-header:基於 Request Header 的流量切分,適用於灰度發佈以及 A/B 測試。當 Request Header 設置爲 always 時,請求將會被一直髮送到 Canary 版本;當 Request Header 設置爲 never時,請求不會被髮送到 Canary 入口;對於任何其餘 Header 值,將忽略 Header,並經過優先級將請求與其餘金絲雀規則進行優先級的比較。
nginx.ingress.kubernetes.io/canary-by-header-value:要匹配的 Request Header 的值,用於通知 Ingress 將請求路由到 Canary Ingress 中指定的服務。當 Request Header 設置爲此值時,它將被路由到 Canary 入口。該規則容許用戶自定義 Request Header 的值,必須與上一個 annotation (即:canary-by-header) 一塊兒使用。
nginx.ingress.kubernetes.io/canary-weight:基於服務權重的流量切分,適用於藍綠部署,權重範圍 0 - 100 按百分比將請求路由到 Canary Ingress 中指定的服務。權重爲 0 意味着該金絲雀規則不會向 Canary 入口的服務發送任何請求,權重爲 100 意味着全部請求都將被髮送到 Canary 入口。
nginx.ingress.kubernetes.io/canary-by-cookie:基於 cookie 的流量切分,適用於灰度發佈與 A/B 測試。用於通知 Ingress 將請求路由到 Canary Ingress 中指定的服務的cookie。當 cookie 值設置爲 always 時,它將被路由到 Canary 入口;當 cookie 值設置爲 never 時,請求不會被髮送到 Canary 入口;對於任何其餘值,將忽略 cookie 並將請求與其餘金絲雀規則進行優先級的比較。
須要注意的是金絲雀規則按優先順序進行排序:canary-by-header - > canary-by-cookie - > canary-weight
總的來講能夠把以上的四個 annotation 規則劃分爲如下兩類:
建立一個用於 production 環境訪問的 Ingress 資源對象:
# production-ingress.yaml apiVersion: extensions/v1beta1 kind: Ingress metadata: name: production annotations: kubernetes.io/ingress.class: nginx spec: rules: - host: echo.example.com http: paths: - backend: serviceName: production servicePort: 80
命令行訪問應用:
curl echo.example.com
建立一個基於權重的 Canary 版本的應用路由 Ingress 對象。
# canary-ingress.yaml apiVersion: extensions/v1beta1 kind: Ingress metadata: name: canary annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/canary: "true" # 要開啓灰度發佈機制,首先須要啓用 Canary nginx.ingress.kubernetes.io/canary-weight: "30" # 分配30%流量到當前Canary版本 spec: rules: - host: echo.example.com http: paths: - backend: serviceName: canary servicePort: 80
命令行訪問應用:
curl -s echo.example.com
在上面的 Canary 版本的 Ingress 對象中新增一條 annotation 配置 nginx.ingress.kubernetes.io/canary-by-header: canary(這裏的 value 能夠是任意值),使當前的 Ingress 實現基於 Request Header 進行流量切分,因爲 canary-by-header 的優先級大於 canary-weight,因此會忽略原有的 canary-weight 的規則。
annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/canary: "true" # 要開啓灰度發佈機制,首先須要啓用 Canary nginx.ingress.kubernetes.io/canary-by-header: canary # 基於header的流量切分 nginx.ingress.kubernetes.io/canary-weight: "30" # 會被忽略,由於配置了 canary-by-header Canary版本
注意:當 Request Header 設置爲 never 或 always 時,請求將不會或一直被髮送到 Canary 版本,對於任何其餘 Header 值,將忽略 Header,並經過優先級將請求與其餘 Canary 規則進行優先級的比較。
命令行訪問應用:
curl -s -H "canary: never" echo.example.com curl -s -H "canary: always" echo.example.com curl -s -H "canary: other-value" echo.example.com
當咱們請求設置的 Header 值爲 canary: other-value 時,ingress-nginx 會經過優先級將請求與其餘 Canary 規則進行優先級的比較,咱們這裏也就會進入 canary-weight: "30" 這個規則去。
這個時候咱們能夠在上一個 annotation (即 canary-by-header)的基礎上添加一條 nginx.ingress.kubernetes.io/canary-by-header-value: user-value 這樣的規則,就能夠將請求路由到 Canary Ingress 中指定的服務了。
annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/canary: "true" # 要開啓灰度發佈機制,首先須要啓用 Canary nginx.ingress.kubernetes.io/canary-by-header-value: user-value nginx.ingress.kubernetes.io/canary-by-header: canary # 基於header的流量切分 nginx.ingress.kubernetes.io/canary-weight: "30" # 分配30%流量到當前Canary版本
一樣更新 Ingress 對象後,從新訪問應用,當 Request Header 知足 canary: user-value 時,全部請求就會被路由到 Canary 版本。
curl -s -H "canary: user-value" echo.example.com
一樣咱們更新 Canary 版本的 Ingress 資源對象,採用基於 Cookie 來進行流量切分:
annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/canary: "true" # 要開啓灰度發佈機制,首先須要啓用 Canary nginx.ingress.kubernetes.io/canary-by-cookie: "users_from_Beijing" # 基於 cookie nginx.ingress.kubernetes.io/canary-weight: "30" # 會被忽略,由於配置了 canary-by-cookie
更新上面的 Ingress 資源對象後,咱們在請求中設置一個 users_from_Beijing=always 的 Cookie 值,再次訪問應用的域名:
curl -s -b "users_from_Beijing=always" echo.example.com
能夠看到應用都被路由到了 Canary 版本的應用中去了,若是咱們將這個 Cookie 值設置爲 never,則不會路由到 Canary 應用中。