k8s gateway
一、为什么会有 Gateway API?
传统 Ingress 有很多问题:
• 功能有限
• 不同厂商实现不统一
• TCP/UDP 支持差
• 权限控制粗糙
• 不适合大型平台
所以 Kubernetes 推出了:Gateway API
二、Gateway API 的核心组件
主要有 4 个资源:
| 资源 | 作用 |
|---|---|
| GatewayClass | 网关实现类型 |
| Gateway | 网关实例 |
| HTTPRoute | 路由规则 |
| ReferenceGrant | 跨命名空间授权 |
三、和 Ingress 对比
传统 Ingress:
Ingress
├── 域名
├── 路由
├── TLS
└── Controller
所有东西都混在一起
Gateway API:
Gateway |
|
负责监听端口 |
|
HTTPRoute |
|
负责路由规则 |
|
实现了解耦。
这也是它最大的优势。
四、安装、使用gateway发布服务
目前k8s本身是没有自带gateway的,我们需要安装他的一些组件
安装gateway API的CRD
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml |
然后我们还需要安装一个控制器,控制器类型较多,以下控制器都可以,我这里选择envoy
| Controller | 支持情况 |
|---|---|
| Istio | 很好 |
| Cilium | 很好 |
| Nginx Gateway Fabric | 支持 |
| Envoy Gateway | 官方推荐之一 |
| Kong | 支持 |
helm install eg oci://docker.io/envoyproxy/gateway-helm --version v1.8.0 -n envoy-gateway-system --create-namespace |
这里需要上点手段,不然会因为网络问题导致下载失败进而无法安装成功
等几分钟让pod都正常running
[root@master gateway]# kubectl get pods -n envoy-gateway-system |
|
NAME READY STATUS RESTARTS AGE |
|
envoy-default-web-gateway-6a499eb1-6d6c8c9b99-s6dcg 2/2 Running 2 (74m ago) 13h |
|
envoy-gateway-798d84ccb8-znxpd 1/1 Running 1 (74m ago) 24h |
都正常running之后咱们需要自己创建对应的gatewayclass,gateway了,当然也可以使用官方的yaml文件直接创建,这里采用手动编写yaml并创建的方式,一步步来更好理解,官网yaml文件地址envoy官网
4.1 创建gatewayClass
apiVersion: gateway.networking.k8s.io/v1 |
|
kind: GatewayClass |
|
metadata: |
|
name: envoy |
|
spec: |
|
controllerName: gateway.envoyproxy.io/gatewayclass-controller |
这里的controllerName,如果你也是安装的envoy那么就是这个,如果你是安装的其他控制器,那么你需要查对应的controllerName是什么,如果填错了将不会被控制器接管
kubectl apply -f gatewayClass.yaml |
等待他创建完成之后我们查看
[root@master gateway]# kubectl get gatewayclasses.gateway.networking.k8s.io |
|
NAME CONTROLLER ACCEPTED AGE |
|
envoy gateway.envoyproxy.io/gatewayclass-controller True 13h |
这里的ACCEPTED一定要是True,如果为false的话就是错的,要么控制器名写错了,要么控制器还没创建好,自己检查一下
4.2 创建gateway
有了gatewayClass之后,我们就可以创建gateway了
apiVersion: gateway.networking.k8s.io/v1 |
|
kind: Gateway |
|
metadata: |
|
name: web-gateway |
|
namespace: default |
|
spec: |
|
gatewayClassName: envoy |
|
listeners: |
|
- name: http |
|
protocol: HTTP |
|
port: 80 |
|
hostname: "www.test.com" |
|
allowedRoutes: |
|
namespaces: |
|
from: Same |
下面这一段的 allowedRoutes表示这个gateway将会接管那些路由,我这写的是 namespaces: from : Same 表示只会接管相同命名空间下的route,这里还有其他选项,如All 和Selector
生产环境建议使用选择器(selector),这种方式更灵活
kubectl apply -f gateway.yaml |
接下来我们可以创建路由了
apiVersion: gateway.networking.k8s.io/v1 |
|
kind: HTTPRoute |
|
metadata: |
|
name: web-route |
|
spec: |
|
parentRefs: |
|
- name: web-gateway |
|
rules: |
|
- matches: |
|
- path: |
|
type: PathPrefix |
|
value: / |
|
backendRefs: |
|
- name: nginx |
|
port: 80 |
backendRefs: 表示流量转发到哪个后端svc,现在我们的环境上没有后端,一会把他创建出来,我们先把路由给写出来
kubectl apply -f route.yaml |
路由创建成功之后我们就可以来创建pod,svc了这一步非常简单
kubectl run nginx --image ngnix |
|
kubectl expose nginx --port 80 --target-port 80 --type ClusterIP |
执行这2条命令即可创建出来,到这里,我们就可以访问了,只不过现在访问的方式有一些麻烦。不过我们依旧可以试一下
因为我们定义的域名是www.test.com,那么我们访问这个域名看看,记得修改hosts文件
curl www.test.com |
此时你会发现,根本无法访问,或者访问出来的内容是你其他服务启动的80端口的内容,这是因为我们的gateway他还没有地址
或者使用另一种方式测试一下
curl -H "Host: www.test.com" http://IP |
这种方式也行,意思就是我访问这个ip的时候加上 www.test.com这个请求头,这个可行的话接着往下看
[root@master gateway]# kubectl get gateway |
|
NAME CLASS ADDRESS PROGRAMMED AGE |
|
web-gateway envoy True 13h |
这里的address是空的,原因是刚刚创建的gateway的svc的类型是loadBalancer,而我们不是云上的环境,没有提供loadBalancer的能力,所以这里没有被分配到地址。接下来我们安装第三方工具来实现loadBalancer
4.3 安装metalLB
之前的博客有写过,直接附上链接各位自行参考loadBalancer
要注意的是,博客里面的地址段你得写一个你真正能通的,比如你的k8s节点的地址是192.168.88.0/24的,那么你最好将loadBalancer的地址段也写成这个
安装完对应的插件之后再去查看
[root@master gateway]# kubectl get gateway |
|
NAME CLASS ADDRESS PROGRAMMED AGE |
|
web-gateway envoy 192.168.88.240 True 13h |
此时就被分配到了一个地址段内的的IP了,接下来我们直接将hosts文件内的映射关系改为新的地址
[root@master gateway]# cat /etc/hosts |
|
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 |
|
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 |
|
192.168.88.100 harbor01.test.com |
|
192.168.88.110 harbor02.test.com |
|
192.168.88.240 www.test.com |
这个时候我们再去访问www.test.com
[root@master gateway]# curl www.test.com |
|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>Welcome to nginx!</title> |
|
<style> |
|
html { color-scheme: light dark; } |
|
body { width: 35em; margin: 0 auto; |
|
font-family: Tahoma, Verdana, Arial, sans-serif; } |
|
</style> |
|
</head> |
|
<body> |
|
<h1>Welcome to nginx!</h1> |
|
<p>If you see this page, nginx is successfully installed and working. |
|
Further configuration is required for the web server, reverse proxy, |
|
API gateway, load balancer, content cache, or other features.</p> |
|
<p>For online documentation and support please refer to |
|
<a href="https://nginx.org/">nginx.org</a>.<br/> |
|
To engage with the community please visit |
|
<a href="https://community.nginx.org/">community.nginx.org</a>.<br/> |
|
For enterprise grade support, professional services, additional |
|
security features and capabilities please refer to |
|
<a href="https://f5.com/nginx">f5.com/nginx</a>.</p> |
|
<p><em>Thank you for using nginx.</em></p> |
|
</body> |
|
</html> |
此时就能拿到正确的结果了
到这k8s的gateway就已经正常工作了,目前我们只写了一个路由,假设我们有多条路由呢? 比如我访问www.test.com是转发到nginx这个pod上,我访问www.test.com/login会转到登录页面上,这个如何做呢?
4.4 多路由、重写
有了刚刚的想法之后我们直接开干,先创建一个pod来模拟登录业务
kubectl run login --image nginx |
|
kubectl expose login --port 80 --target-port 80 --type ClusterIP |
|
kubectl exec -it login -- bash |
|
echo "Please login..." > /usr/share/nginx/html/index.html |
|
exit |
以上步骤的意思是,创建一个nignx容器并给他一个ClusterIP类型的svc,然后进入这个pod修改他的首页文件,使用这个pod来模拟登录功能,接下来直接上yaml文件
apiVersion: gateway.networking.k8s.io/v1 |
|
kind: HTTPRoute |
|
metadata: |
|
name: login-route |
|
namespace: default |
|
spec: |
|
parentRefs: |
|
- name: web-gateway |
|
hostnames: |
|
- "www.test.com" |
|
rules: |
|
- matches: |
|
- path: |
|
type: PathPrefix |
|
value: /login |
|
# 这一段是之前没有的 |
|
filters: |
|
- type: URLRewrite |
|
urlRewrite: |
|
path: |
|
type: ReplaceFullPath |
|
replaceFullPath: / |
|
backendRefs: |
|
- name: login |
|
port: 80 |
这一段yaml文件出现了一段新的内容,作用是重写url,因为如果不重写的话,我们访问www.test.com/login,那么gateway就会直接转发到pod内,请求的内容依旧是/login
但是我们的想法是你转发到login这个pod没有错,但是你得让他请求的是index.html这个文件才对,所以我们需要设置重写
kubectl apply -f rewrite.yaml |
这个时候再去测试一下
[root@master gateway]# curl www.test.com |
|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>Welcome to nginx!</title> |
|
<style> |
|
html { color-scheme: light dark; } |
|
body { width: 35em; margin: 0 auto; |
|
font-family: Tahoma, Verdana, Arial, sans-serif; } |
|
</style> |
|
</head> |
|
<body> |
|
<h1>Welcome to nginx!</h1> |
|
<p>If you see this page, nginx is successfully installed and working. |
|
Further configuration is required for the web server, reverse proxy, |
|
API gateway, load balancer, content cache, or other features.</p> |
|
<p>For online documentation and support please refer to |
|
<a href="https://nginx.org/">nginx.org</a>.<br/> |
|
To engage with the community please visit |
|
<a href="https://community.nginx.org/">community.nginx.org</a>.<br/> |
|
For enterprise grade support, professional services, additional |
|
security features and capabilities please refer to |
|
<a href="https://f5.com/nginx">f5.com/nginx</a>.</p> |
|
<p><em>Thank you for using nginx.</em></p> |
|
</body> |
|
</html> |
访问www.test.com是没有问题的,接下来访问login
[root@master gateway]# curl www.test.com/login |
|
Please login... |
更多推荐




所有评论(0)