初始Ingress策略
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: <ingress-name>
spec:
rules:
- host: <your.domain>
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: <servicename>
port:
number: 80
ingressClassName: nginx
基于annotations灰度发布策略
示例(根据权重转发):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: <ingress-name>
spec:
rules:
- host: <your.domain>
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: <old_servicename>
port:
number: 80
ingressClassName: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: <ingress-name>
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "30" # 30%权重
spec:
rules:
- host: <your.domain>
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: <new_servicename>
port:
number: 80
ingressClassName: nginx
nginx.ingress.kubernetes.io/canary-weight
基于服务权重的流量切分,适用于蓝绿部署,权重范围 0 - 100 按百分比将请求路由到 Canary Ingress 中指定的服务。权重为 0 意味着该金丝雀规则不会向 Canary 入口的服务发送任何请求。权重为30意味着30%流量转到canary。权重为 100 意味着所有请求都将被发送到 Canary 入口。
for i in $(seq 1 10); do curl http://<your.domain>; echo '\n'; done hello world-version1 hello world-version1 hello world-version2 hello world-version2 hello world-version1 hello world-version1 hello world-version1 hello world-version1 hello world-version1 hello world-version1
一、根据请求头转发
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "test"
-
nginx.ingress.kubernetes.io/canary-by-header
基于Request Header的流量切分,适用于灰度发布以及 A/B 测试。当Request Header 设置为
always
时,请求将会被一直发送到 Canary 版本;当 Request Header 设置为never
时,请求不会被发送到 Canary 入口。测试结果如下:
for i in $(seq 1 5); do curl http://<your.domain>; echo '\n'; done hello world-version1 hello world-version1 hello world-version1 hello world-version1 hello world-version1 for i in $(seq 1 5); do curl -H 'test:always' http://<your.domain>; echo '\n'; done hello world-version2 hello world-version2 hello world-version2 hello world-version2 hello world-version2
二、根据特定的请求头和值转发
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "test"
nginx.ingress.kubernetes.io/canary-by-header-value: "abc"
-
nginx.ingress.kubernetes.io/canary-by-header-value
要匹配的 Request Header 的值,用于通知 Ingress 将请求路由到 Canary Ingress 中指定的服务。当 Request Header 设置为此值时,它将被路由到 Canary 入口。
测试结果如下:
for i in $(seq 1 5); do curl -H 'test:always' http://<your.domain>; echo '\n'; done hello world-version1 hello world-version1 hello world-version1 hello world-version1 hello world-version1 for i in $(seq 1 5); do curl -H 'test:abc' http://<your.domain>; echo '\n'; done hello world-version2 hello world-version2 hello world-version2 hello world-version2 hello world-version2
三、根据 COOKIE 转发
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-cookie: "like_music"
-
nginx.ingress.kubernetes.io/canary-by-cookie
基于 Cookie 的流量切分,适用于灰度发布与 A/B 测试。用于通知 Ingress 将请求路由到 Canary Ingress 中指定的服务的cookie。当 cookie 值设置为
always
时,它将被路由到 Canary 入口;当 cookie 值设置为never
时,请求不会被发送到 Canary 入口。测试结果如下:
for i in $(seq 1 5); do curl -b 'like_music=1' http://<your.domain>; echo '\n'; done hello world-version1 hello world-version1 hello world-version1 hello world-version1 hello world-version1 for i in $(seq 1 5); do curl -b 'like_music=always' http://<your.domain>; echo '\n'; done hello world-version2 hello world-version2 hello world-version2 hello world-version2 hello world-version2
常用ingress配置
access log
annotations:
nginx.ingress.kubernetes.io/enable-access-log: "false"
nginx ingress 默认是开启access log的,如果你想关闭,可以通过将
nginx.ingress.kubernetes.io/enable-access-log
设置成false。
默认服务
annotations:
nginx.ingress.kubernetes.io/default-backend:
当客户端请求一个不存在的path的时候,我们不希望返回 404 ,跳转到一个默认的服务上。
允许最大body
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: 8m
这个主要是针对外部请求,防止将流量打满,proxy-body-size 设置最大请求 body,如果超过则会返回 413 请求错误。
限流
annotations:
nginx.ingress.kubernetes.io/limit-rps: "5"
nginx.ingress.kubernetes.io/limit-rpm: "300"
nginx.ingress.kubernetes.io/limit-connections: "10"
通过 rps 限制每秒请求数,rpm 限制每分钟请求数,connections限制连接数。
跨域访问
annotations:
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-headers: "X-Forwarded-For, X-app123-XPTO"
nginx.ingress.kubernetes.io/cors-expose-headers: "*, X-CustomResponseHeader"
nginx.ingress.kubernetes.io/cors-max-age: 600
nginx.ingress.kubernetes.io/cors-allow-credentials: "false"
我们经常将nginx作为api的网关,支持跨域必不可少。通过
nginx.ingress.kubernetes.io/cors-allow-methods
设置支持跨域请求的方法。
请求超时
annotations:
nginx.org/proxy-connect-timeout: "30s"
nginx.org/proxy-read-timeout: "20s"
nginx.org/proxy-connect-timeout 和nginx.org/proxy-read-timeout
这两个参数分别设置nginx的建立连接以及等待结果的超时时间。
强制https
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/preserve-trailing-slash: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
通过这个annotation可以强制 https,如果是http请求,会通过 301 redirect到 https
https
apiVersion: v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "false" # 禁用https强制跳转
generation: 1
name: test-tls
namespace: ratel-test1
spec:
rules:
- host: test-tls.test.com
http:
paths:
- backend:
serviceName: ingress-test
servicePort: 80
path: /
tls:
- hosts:
- test-tls.test.com
secretName: ca-cert
设置默认证书:--default-ssl-certificate=default/foo-tls
更改的ingress-controller的启动参数
Redirect
apiVersion: v1
items:
- apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/permanent-redirect: https://www.baidu.com # 重定向到想去的url
name: ingress-test
namespace: ratel-test1
spec:
rules:
- host: ingress.test.com
http:
paths:
- backend:
serviceName: ingress-test
servicePort: 80
path: /
kind: List
metadata:
resourceVersion: ""
selfLink: ""
Rewrite
apiVersion: v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
generation: 4
name: ingress-test
namespace: ratel-test1
spec:
rules:
- host: rewrite.test.com
http:
paths:
- backend:
serviceName: ingress-test
servicePort: 80
path: /something(/|$)(.*) #($1)($2)
黑白名单
黑名单:拒绝某段IP访问
**白名单:**只允许某段IP访问
Annotations:只对指定的ingress生效
ConfigMap:全局生效
黑名单可以使用ConfigMap去配置,白名单建议使用Annotations去配置
白名单配置(建议使用Annotations)
annotations:
nginx.ingress.kubernetes.io/whitelist-source-range 10.0.0.0/24,172.10.0.1
黑名单设置(建议使用ConfigMap)(全局生效)
kubectl edit cm -n ingress-nginx ingress-nginx-controller -oyaml
---
apiVersion: v1
data: # 加上data
block-cidrs: 192.168.1.201 # 黑名单
kind: ConfigMap
metadata:
annotations:
meta.helm.sh/release-name: ingress-nginx
meta.helm.sh/release-namespace: ingress-nginx
...
kubectl delete po -n ingress-nginx --all
针对某个域名设置黑名单–snippet
# 比如ingress代理了www.test.com这个域名,那么想针对这个域名(www.test.com)设置访问黑名单,就编辑这个ingress即可
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
# 在annotations下面加上这几行配置,有多个IP可以deny多个
annotations:
nginx.ingress.kubernetes.io/server-snippet: |-
deny 192.168.1.101;
deny 192.168.1.102;
allow all;
# 然后在deny的主机上访问 www.test.com 就403
[root@k8s-master02 ~]# curl ngdemo.qikqiak.com
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>
匹配请求头设置
annotations:
nginx.ingress.kubernetes.io/server-snippet: |
set $agentflag 0;
if ($http_user_agent ~* "(iPhone)" ){ # 匹配规则设置(设置匹配为iPhone的手机,则重定向到下面的url)
set $agentflag 1;
}
if ( $agentflag = 1 ) {
return 301 https://www.baidu.com; # 重定向到指定的url
}
ingress-nginx基本认证(Basic Auth)
在 Ingress Controller 上面配置基本的 Auth 认证,如 Basic Auth,用 htpasswd 生成一个密码文件来验证身份验证。
[root@k8s-master01 ~]# htpasswd -c auth foo # 账号foo 密码 123456
New password: # 123456
Re-type new password: # 123456
Adding password for user foo
# 生成一个auth文件
根据上面的 auth 文件创建一个 secret 对象:
kubectl create secret generic basic-auth --from-file=auth
对上面的 my-nginx 应用创建一个具有 Basic Auth 的 Ingress 对象:
annotations:
nginx.ingress.kubernetes.io/auth-type: basic # 认证类型
nginx.ingress.kubernetes.io/auth-secret: basic-auth # 包含 user/password 定义的 secret 对象名
nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required' # 提示文本
不带用户名和密码进行认证:
➜ curl -v http://k8s.qikqiak.com -H 'Host: foo.bar.com'
...
< HTTP/1.1 401 Unauthorized
< Server: openresty/1.15.8.2
< Date: Sun, 08 Dec 2019 06:44:35 GMT
< Content-Type: text/html
< Content-Length: 185
< Connection: keep-alive
< WWW-Authenticate: Basic realm="Authentication Required"
...
带上用户名和密码进行认证:
➜ curl -v http://k8s.qikqiak.com -H 'Host: foo.bar.com' -u 'foo:foo'
...
< HTTP/1.1 200 OK
< Server: openresty/1.15.8.2
< Date: Sun, 08 Dec 2019 06:46:27 GMT
< Content-Type: text/html
< Content-Length: 612
< Connection: keep-alive
< Vary: Accept-Encoding
< Last-Modified: Tue, 19 Nov 2019 12:50:08 GMT
< ETag: "5dd3e500-264"
< Accept-Ranges: bytes
...