k8s gateway
为什么会有 Gateway API传统 Ingress 有很多问题• 功能有限• 不同厂商实现不统一• TCP/UDP 支持差• 权限控制粗糙• 不适合大型平台所以 Kubernetes 推出了Gateway API二、Gateway API 的核心组件主要有 4 个资源资源作用GatewayClass网关实现类型Gateway网关实例HTTPRoute路由规则ReferenceGrant跨命名空间授权三、和 Ingress 对比传统 IngressIngress├── 域名├── 路由├── TLS└── Controller所有东西都混在一起Gateway APIGateway负责监听端口HTTPRoute负责路由规则实现了解耦。这也是它最大的优势。四、安装、使用gateway发布服务目前k8s本身是没有自带gateway的我们需要安装他的一些组件安装gateway API的CRDkubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml然后我们还需要安装一个控制器控制器类型较多以下控制器都可以我这里选择envoyController支持情况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[rootmaster gateway]# kubectl get pods -n envoy-gateway-systemNAME READY STATUS RESTARTS AGEenvoy-default-web-gateway-6a499eb1-6d6c8c9b99-s6dcg 2/2 Running 2 (74m ago) 13henvoy-gateway-798d84ccb8-znxpd 1/1 Running 1 (74m ago) 24h都正常running之后咱们需要自己创建对应的gatewayclassgateway了当然也可以使用官方的yaml文件直接创建这里采用手动编写yaml并创建的方式一步步来更好理解官网yaml文件地址envoy官网4.1 创建gatewayClassapiVersion: gateway.networking.k8s.io/v1kind: GatewayClassmetadata:name: envoyspec:controllerName: gateway.envoyproxy.io/gatewayclass-controller这里的controllerName如果你也是安装的envoy那么就是这个如果你是安装的其他控制器那么你需要查对应的controllerName是什么如果填错了将不会被控制器接管kubectl apply -f gatewayClass.yaml等待他创建完成之后我们查看[rootmaster gateway]# kubectl get gatewayclasses.gateway.networking.k8s.ioNAME CONTROLLER ACCEPTED AGEenvoy gateway.envoyproxy.io/gatewayclass-controller True 13h这里的ACCEPTED一定要是True如果为false的话就是错的要么控制器名写错了要么控制器还没创建好自己检查一下4.2 创建gateway有了gatewayClass之后我们就可以创建gateway了apiVersion: gateway.networking.k8s.io/v1kind: Gatewaymetadata:name: web-gatewaynamespace: defaultspec:gatewayClassName: envoylisteners:- name: httpprotocol: HTTPport: 80hostname: www.test.comallowedRoutes:namespaces:from: Same下面这一段的 allowedRoutes表示这个gateway将会接管那些路由我这写的是 namespaces: from : Same 表示只会接管相同命名空间下的route这里还有其他选项如All 和Selector生产环境建议使用选择器(selector)这种方式更灵活kubectl apply -f gateway.yaml接下来我们可以创建路由了apiVersion: gateway.networking.k8s.io/v1kind: HTTPRoutemetadata:name: web-routespec:parentRefs:- name: web-gatewayrules:- matches:- path:type: PathPrefixvalue: /backendRefs:- name: nginxport: 80backendRefs: 表示流量转发到哪个后端svc现在我们的环境上没有后端一会把他创建出来我们先把路由给写出来kubectl apply -f route.yaml路由创建成功之后我们就可以来创建podsvc了这一步非常简单kubectl run nginx --image ngnixkubectl 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这个请求头这个可行的话接着往下看[rootmaster gateway]# kubectl get gatewayNAME CLASS ADDRESS PROGRAMMED AGEweb-gateway envoy True 13h这里的address是空的原因是刚刚创建的gateway的svc的类型是loadBalancer而我们不是云上的环境没有提供loadBalancer的能力所以这里没有被分配到地址。接下来我们安装第三方工具来实现loadBalancer4.3 安装metalLB之前的博客有写过直接附上链接各位自行参考loadBalancer要注意的是博客里面的地址段你得写一个你真正能通的比如你的k8s节点的地址是192.168.88.0/24的那么你最好将loadBalancer的地址段也写成这个安装完对应的插件之后再去查看[rootmaster gateway]# kubectl get gatewayNAME CLASS ADDRESS PROGRAMMED AGEweb-gateway envoy 192.168.88.240 True 13h此时就被分配到了一个地址段内的的IP了接下来我们直接将hosts文件内的映射关系改为新的地址[rootmaster gateway]# cat /etc/hosts127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4::1 localhost localhost.localdomain localhost6 localhost6.localdomain6192.168.88.100 harbor01.test.com192.168.88.110 harbor02.test.com192.168.88.240 www.test.com这个时候我们再去访问www.test.com[rootmaster gateway]# curl www.test.com!DOCTYPE htmlhtmlheadtitleWelcome to nginx!/titlestylehtml { color-scheme: light dark; }body { width: 35em; margin: 0 auto;font-family: Tahoma, Verdana, Arial, sans-serif; }/style/headbodyh1Welcome to nginx!/h1pIf 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./ppFor online documentation and support please refer toa hrefhttps://nginx.org/nginx.org/a.br/To engage with the community please visita hrefhttps://community.nginx.org/community.nginx.org/a.br/For enterprise grade support, professional services, additionalsecurity features and capabilities please refer toa hrefhttps://f5.com/nginxf5.com/nginx/a./ppemThank 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 nginxkubectl expose login --port 80 --target-port 80 --type ClusterIPkubectl exec -it login -- bashecho Please login... /usr/share/nginx/html/index.htmlexit以上步骤的意思是创建一个nignx容器并给他一个ClusterIP类型的svc然后进入这个pod修改他的首页文件使用这个pod来模拟登录功能接下来直接上yaml文件apiVersion: gateway.networking.k8s.io/v1kind: HTTPRoutemetadata:name: login-routenamespace: defaultspec:parentRefs:- name: web-gatewayhostnames:- www.test.comrules:- matches:- path:type: PathPrefixvalue: /login# 这一段是之前没有的filters:- type: URLRewriteurlRewrite:path:type: ReplaceFullPathreplaceFullPath: /backendRefs:- name: loginport: 80这一段yaml文件出现了一段新的内容作用是重写url因为如果不重写的话我们访问www.test.com/login那么gateway就会直接转发到pod内请求的内容依旧是/login但是我们的想法是你转发到login这个pod没有错但是你得让他请求的是index.html这个文件才对所以我们需要设置重写kubectl apply -f rewrite.yaml这个时候再去测试一下[rootmaster gateway]# curl www.test.com!DOCTYPE htmlhtmlheadtitleWelcome to nginx!/titlestylehtml { color-scheme: light dark; }body { width: 35em; margin: 0 auto;font-family: Tahoma, Verdana, Arial, sans-serif; }/style/headbodyh1Welcome to nginx!/h1pIf 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./ppFor online documentation and support please refer toa hrefhttps://nginx.org/nginx.org/a.br/To engage with the community please visita hrefhttps://community.nginx.org/community.nginx.org/a.br/For enterprise grade support, professional services, additionalsecurity features and capabilities please refer toa hrefhttps://f5.com/nginxf5.com/nginx/a./ppemThank you for using nginx./em/p/body/html访问www.test.com是没有问题的接下来访问login[rootmaster gateway]# curl www.test.com/loginPlease login...各位可以试试看不加上重写会是什么样的效果。