0%

网关

官网列出了很多厂商的Gateway API实现,本次安装我们最熟悉的nginx官方实现NGINX Gateway Fabric

由于k8s版本更新,Ingress已经被弃用,未来可以用Gateway API将其取代,二者区别可参考官方给出的解释从 Ingress 迁移 - Kubernetes Gateway API ,本次直接安装Kubernetes Gateway API

image-20240424154043878

根据readme步骤安装

Getting Started

  1. Quick Start on a kind cluster.
  2. Install NGINX Gateway Fabric.
  3. Deploy various examples.
  4. Read our How-to guides.

第一步安装一个集群,我们已经完成,跳过

第二步安装NGINX Gateway Fabric

安装Gateway API 资源
1
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml
部署NGINX Gateway Fabric CRDs
1
kubectl apply -f https://github.com/nginxinc/nginx-gateway-fabric/releases/download/v1.2.0/crds.yaml
部署NGINX Gateway Fabric
1
kubectl apply -f https://github.com/nginxinc/nginx-gateway-fabric/releases/download/v1.2.0/nginx-gateway.yaml
验证
1
2
3
[root@k8s-master gateway-example]# kubectl get pods -n nginx-gateway
NAME READY STATUS RESTARTS AGE
nginx-gateway-66765f47f9-tctd4 2/2 Running 2 (33m ago) 74m
安装完成

部署测试

这一步需要先部署一个网关services暴漏集群端口供外部访问

创建 NodePort 服务
1
2
3
4
5
[root@k8s-master gateway-example]# kubectl apply -f https://raw.githubusercontent.com/nginxinc/nginx-gateway-fabric/v1.2.0/deploy/manifests/service/nodeport.yaml

[root@k8s-master gateway-example]# kubectl get svc -n nginx-gateway
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-gateway NodePort 10.97.97.176 <none> 80:31741/TCP,443:30532/TCP 165m

接下来就可以使用端口31741来访问了

使用 HTTPRoute将流量路由到应用

使用以下三个配置文件创建示例应用程序

gateway.yaml

1
2
3
4
5
6
7
8
9
10
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: cafe
spec:
gatewayClassName: nginx
listeners:
- name: http
port: 80
protocol: HTTP

cafe-routes.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: coffee
spec:
parentRefs:
- name: cafe
hostnames:
- "cafe.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: coffee
port: 80

coffee.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
apiVersion: apps/v1
kind: Deployment
metadata:
name: coffee
spec:
replicas: 2
selector:
matchLabels:
app: coffee
template:
metadata:
labels:
app: coffee
spec:
containers:
- name: coffee
image: nginxdemos/nginx-hello:plain-text
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: coffee
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: coffee

部署并查看状态

1
2
3
4
5
6
7
8
9
[root@k8s-master gateway-example2]# kubectl apply -f .
httproute.gateway.networking.k8s.io/coffee created
deployment.apps/coffee created
service/coffee created
gateway.gateway.networking.k8s.io/cafe created
[root@k8s-master gateway-example2]# kubectl get po
NAME READY STATUS RESTARTS AGE
coffee-6b8b6d6486-24t8z 1/1 Running 0 12s
coffee-6b8b6d6486-wf4v9 1/1 Running 0 12s

image-20240424144358556

高级应用

跨命名空间路由

假如我需要将ns=default的流量路由到ns=cafe,那么就需要在ns=cafe下新建一个ReferenceGrant,内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: access-to-cafe-services
namespace: cafe
spec:
to:
- group: ""
kind: Service
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: default

并在需要路由的后端服务增加ns配置

1
2
3
4
5
6
7
8
9
rules:
- matches:
- path:
type: PathPrefix
value: /coffee
backendRefs:
- name: coffee
namespace: cafe
port: 80
根据HTTP参数路由
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
rules:
- matches:
- path:
type: PathPrefix # 路径前缀匹配
value: /coffee
backendRefs:
- name: coffee-v1-svc
port: 80
- matches:
- path:
type: PathPrefix
value: /coffee
headers: # 请求头匹配
- name: version
value: v2
- path:
type: PathPrefix
value: /coffee
queryParams: # 请求参数匹配
- name: TEST
value: v2
backendRefs:
- name: coffee-v1-svc
port: 80
weight: 80 # 流量权重
- name: coffee-v2-svc
port: 80
weight: 20 # 流量权重
配置请求头过滤器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
rules:
- matches:
- path:
type: PathPrefix
value: /headers
filters:
- type: RequestHeaderModifier # 请求头修改
requestHeaderModifier:
set: # 设置请求头
- name: My-Overwrite-Header
value: this-is-the-only-value
add: # 追加请求头内容
- name: Accept-Encoding
value: compress
- name: My-cool-header
value: this-is-an-appended-value
remove: # 移除请求头
- User-Agent
backendRefs:
- name: coffee-v1-svc
port: 80
配置https

配置网关gateway.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: gateway
spec:
gatewayClassName: nginx
listeners:
- name: http
port: 80
protocol: HTTP
- name: https
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: cafe-secret
namespace: certificate

配置ReferenceGrant

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: access-to-cafe-secret
namespace: certificate
spec:
to:
- group: ""
kind: Secret
name: cafe-secret # 如果省略, ns=default内的Gateway能访问ns=certificate的所有Secrets
from:
- group: gateway.networking.k8s.io
kind: Gateway
namespace: default

配置ns和Secret

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: Namespace
metadata:
name: certificate
---
apiVersion: v1
kind: Secret
metadata:
name: cafe-secret
namespace: certificate
type: kubernetes.io/tls
data:
tls.crt: xxxxxxxxx
tls.key: xxxxxxxxx

配置路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: cafe-tls-redirect
spec:
parentRefs:
- name: gateway
sectionName: http
hostnames:
- "cafe.example.com"
rules:
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
port: 443
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: coffee
spec:
parentRefs:
- name: gateway
sectionName: https
hostnames:
- "cafe.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /coffee
backendRefs:
- name: coffee
port: 80
配置url重写

下面配置会将url前缀为/coffee/**重写为/beans

将/latte/** 重写为/**

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
rules:
- matches:
- path:
type: PathPrefix
value: /coffee
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplaceFullPath
replaceFullPath: /beans
backendRefs:
- name: coffee
port: 80
- matches:
- path:
type: PathPrefix
value: /latte
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /
backendRefs:
- name: coffee
port: 80
路由到https服务

创建后端https服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-app
spec:
replicas: 1
selector:
matchLabels:
app: secure-app
template:
metadata:
labels:
app: secure-app
spec:
containers:
- name: secure-app
image: nginxinc/nginx-unprivileged:latest
ports:
- containerPort: 8443
volumeMounts:
- name: secret
mountPath: /etc/nginx/ssl
readOnly: true
- name: config-volume
mountPath: /etc/nginx/conf.d
volumes:
- name: secret
secret:
secretName: app-tls-secret
- name: config-volume
configMap:
name: secure-config
---
apiVersion: v1
kind: Service
metadata:
name: secure-app
spec:
ports:
- port: 8443
targetPort: 8443
protocol: TCP
name: https
selector:
app: secure-app
---
apiVersion: v1
kind: ConfigMap
metadata:
name: secure-config
data:
app.conf: |-
server {
listen 8443 ssl;
listen [::]:8443 ssl;

server_name secure-app.example.com;

ssl_certificate /etc/nginx/ssl/tls.crt;
ssl_certificate_key /etc/nginx/ssl/tls.key;

default_type text/plain;

location / {
return 200 "hello from pod secure-app\n";
}
}
---
apiVersion: v1
kind: Secret
metadata:
name: app-tls-secret
type: Opaque
data:
tls.crt: xxxxxxxx
tls.key: xxxxxxxx

创建网关和路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: gateway
spec:
gatewayClassName: nginx
listeners:
- name: http
port: 80
protocol: HTTP
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: secure-app
spec:
parentRefs:
- name: gateway
sectionName: http
hostnames:
- "secure-app.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: secure-app
port: 8443

这时直接应用之后访问会报错400 Bad Request

还需要接着配

1
2
3
4
5
6
7
8
9
kind: ConfigMap
apiVersion: v1
metadata:
name: backend-cert
data:
ca.crt: |
-----BEGIN CERTIFICATE-----
xxxxxx
-----END CERTIFICATE-----

创建BackendTLSPolicy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: BackendTLSPolicy
metadata:
name: backend-tls
spec:
targetRef:
group: ''
kind: Service
name: secure-app
namespace: default
tls:
caCertRefs:
- name: backend-cert
group: ''
kind: ConfigMap
hostname: secure-app.example.com
赏口饭吃吧!