极客时间《Kubernetes 入门实战课》之《加餐分享 (2讲)》
全笔记:
《开篇词 (2讲)》
《入门篇 (8讲)》
《初级篇 (9讲)》
《中级篇 (8讲)》
《高级篇 (10讲)》
《加餐分享 (2讲)》
考虑扩展学习:
- Helm
- 运维多个 k8s 集群:OpenLens 、Rancher
《加餐|谈谈Kong Ingress Controller》
-
认识 Kong Ingress Controller
我们已经见过了 Nginx 官方开发的 Nginx Ingress Controller,但它局限于 Nginx 自身的能力,Ingress、Service 等对象更新时必须要修改静态的配置文件,再重启进程(reload),在变动频繁的微服务系统里就会引发一些问题。
而今天要说的 Kong Ingress Controller,则是站在了 Nginx 这个巨人的肩膀之上,基于 OpenResty 和内嵌的 LuaJIT 环境,实现了完全动态的路由变更,消除了 reload 的成本,运行更加平稳,而且还有很多额外的增强功能 -
安装 Kong Ingress Controller
下载:wget https://github.com/Kong/kubernetes-ingress-controller/archive/refs/tags/v2.7.0.tar.gz,然后解压缩,可选择相对简单的无数据库部署方式(在deploy目录下有一个 all-in-one-dbless.yaml)。安装之后,Kong Ingress Controller 会创建一个新的名字空间kong,里面有一个默认的 Ingress Controller,还有对应的 Service:

在 kubectl get pod 输出的READY列里显示的是“2/2”,意思是这个 Pod 里有两个容器。
尝试访问一下 Kong Ingress Controller:

我们还可以用 kubectl exec 命令进入 Pod,查看它的内部信息:
《加餐|尝鲜Gateway API:更强大、更灵活、面向未来的Ingress》
长期以来被关注的“下一代” Ingress 对象:Gateway API,在经过了近 4 年的讨论、测试和验证之后,终于在 2023 年的 11 月正式发布,可以用于生产环境,也就是我们常说的 GA(generally available)。
- 什么是 Gateway API
同一个功能在不同的 Ingress Controller 之间用法差异极大,迁移的成本非常高,没有统一的标准导致 Ingress 使用起来相当麻烦。
在 2023 年 11 月发布的Gateway API 1.0 版本里包括 3 个已经成熟稳定的对象,Gateway Class、Gateway 和 HTTPRoute。
Gateway API is an official Kubernetes project focused on L4 and L7 routing in Kubernetes.

最上层的 Gateway Class 类似于 Ingress Class,由各个云厂商提供;中间的 Gateway 类似于 Ingress Controller,由集群管理员管理;下面的 HTTPRoute 类似于 Ingress,由开发人员管理,定义路由规则,规定流量将如何被 Gateway 分发到集群里的 Service 和 Pod。
下面以 Kong 为例,来介绍 Gateway API 的用法。
-
安装 Gateway API
Gateway API 只支持较新的 Kubernetes(比如1.28.3),不能运行在 Kubernetes 1.23。 -
- 升级minikube
学习第9节时,我在某台机器上安装过老版本的minikube。现在我回到这台机器,下载更新版本的minikube:
curl -Lo minikube-linux-amd64 https://storage.googleapis.com/minikube/releases/v1.32.0/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube # 覆盖安装,替换旧版本
minikube version #验证版本
查看已有所有 minikube 集群:
minikube delete # 清理旧集群
启动minikube很费了一番周折,主要是minikube无法拉取kicbase镜像,为此可以1先拉取国内镜像: docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kicbase:v0.0.42, 并将其填入随后启动命令中的--base-image参数(启动时开启了科学上网,不知是否有必要 ):
minikube start \
--base-image='registry.cn-hangzhou.aliyuncs.com/google_containers/kicbase:v0.0.42' \
--registry-mirror='https://docker.m.daocloud.io,https://docker.mirrors.ustc.edu.cn,https://hub-mirror.c.163.com' \
--kubernetes-version=v1.28.3
第一次启动还是很久,比如在Creating docker container 这一行就卡了十几分钟。豆包说加参数--download-mirror=cn 与 --image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers,可加快速度,未试。另外注意参数只在minikube集群第一次start时生效,比如我第一次start时没有加–registry-mirror参数,后面start时再加也设置不了镜像源了,除非minikube delete再重来,这样又是一个新的minikube集群了。所以本章从这里开始我全程开着科学上网:

可以看到,不需要另外安装kubectl。而且之前我为minikube kubectl --配置的别名kubectl仍然有效。
-
- 部署 Gateway API
安装Gateway API:
wget https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml
kubectl apply -f standard-install.yaml
创建实验用的 Gateway Class 和 Gateway 对象。这个 YAML 定义了一个叫 kong-gc 的 Gateway Class 对象,指定使用的 Controller 是 konghq.com/kic-gateway-controller。然后 Gateway 对象的名字是 kong-gtw,它关联了 kong-gc,在 80 端口上处理 HTTP 协议:
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: kong-gc
annotations:
konghq.com/gatewayclass-unmanaged: 'true'
spec:
controllerName: konghq.com/kic-gateway-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: kong-gtw
spec:
gatewayClassName: kong-gc
listeners:
- name: proxy
port: 80
protocol: HTTP
创建成功。Gateway Class 的缩写是 gc,Gateway 的缩写是 gtw :

- 安装 Kong Ingress Controller
Kong Ingress Controller 2.x 可以使用 YAML 文件直接安装,但 3.0.0 已经废弃了这种方式,只能够使用 Helm 或 Operator 来安装,这里选用的是 Helm。
Helm类似于 Linux 里的 yum、apt,对复杂的云原生应用非常有用,可以把众多的 YAML 文件组合成安装包的形式,再轻松地把应用部署进 Kubernetes 集群。
安装Helm: curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash :

添加远端仓库(Helm charts):

之后可以查看远端仓库里可用的安装包,这里显示的 kong/ingress 就是 Kong Ingress Controller:

使用命令 helm install 安装 Kong Ingress Controller:

Kong Ingress Controller 默认安装在 kong 名字空间。注意kong-gateway-proxy 这个 Service,它的类型是 LoadBalancer,也就是对外的服务接口,在实验环境里使用的端口是 32379,后续我们要使用这个端口来测试。使用 curl 访问这个服务可以验证 Kong Ingress Controller 是否正常工作。curl -i $(minikube ip):32379的输出是 404,这是因为我们还没有配置 HTTPRoute 资源,没有路由规则,所以 Gateway 无法处理流量:


这时再检查 Gateway Class 和 Gateway 对象,会看到 ACCEPTED 和 PROGRAMMED 字段都已经变成了 True,这就表示 Gateway 对象已经正确关联了 Kong Ingress Controller:

- 准备后端服务
对以下yaml文件使用sed 命令,就可以快速得到red-svc、green-svc、bule-svc、black-svc 4 个 Service:
apiVersion: v1
kind: ConfigMap
metadata:
name: ngx-conf
data:
default.conf: |
server {
listen 80;
location / {
default_type text/plain;
return 200
'ngx\nsrv : $server_addr:$server_port\nhost: $hostname\nuri : $request_method $host $request_uri\n';
}
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ngx-dep
labels:
app: ngx-dep
spec:
replicas: 1
selector:
matchLabels:
app: ngx-dep
template:
metadata:
labels:
app: ngx-dep
spec:
volumes:
- name: ngx-conf-vol
configMap:
name: ngx-conf
containers:
- image: nginx:alpine
name: nginx
ports:
- containerPort: 80
volumeMounts:
- mountPath: /etc/nginx/conf.d
name: ngx-conf-vol
---
apiVersion: v1
kind: Service
metadata:
name: ngx-svc
spec:
selector:
app: ngx-dep
ports:
- port: 80
protocol: TCP
targetPort: 80
sed 's/ngx/red/g' backend.yml | kubectl apply -f -
sed 's/ngx/green/g' backend.yml | kubectl apply -f -
sed 's/ngx/blue/g' backend.yml | kubectl apply -f -
sed 's/ngx/black/g' backend.yml | kubectl apply -f -
通过http访问每个Service url的流量,会被转发至nginx Pod 的 80 端口, 得到有效响应。
-
使用 Gateway API
-
- 从最简单的路由开始,只使用域名规则,创建一个 HTTPRoute 对象。HTTPRoute 对象和 Ingress 很相似,但要简洁一些。这里使用 parentRefs 指定了路由使用的 Gateway 对象,用 hostnames 指定一个或多个域名,用 backendRefs 指定后端 Service。合起来看,就是要求 Gateway 把域名 gtw.test 的流量都转发到 red-svc :
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: ngx-host-route
spec:
parentRefs:
- name: kong-gtw
hostnames:
- "gtw.test"
rules:
- backendRefs:
- name: red-svc
port: 80
验证:

我:HTTPRoute.spec.hostnames 不是用来匹配 curl 请求的 URL 地址,只是用来匹配HTTP请求头中host(除端口部分),比如下面就能成功:

Q:Ingress.spec.rules.host, 是不是也像HTTPRoute.spec.hostnames 一样,是为了匹配 curl -H ‘host:’ 部分,而不是为了匹配 curl 的目标url? 豆包:Yes
-
- 再来编写两个路由规则,分别测试HTTPRoute.spec.rules.matches.path type: PathPrefix 的路径匹配效果,和HTTPRoute.spec.rules.matches.headers的头字段匹配效果:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: ngx-path-route
spec:
parentRefs:
- name: kong-gtw
hostnames:
- "gtw.ops"
rules:
- matches:
- path:
type: PathPrefix
value: /hello
backendRefs:
- name: green-svc
port: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: ngx-header-route
spec:
parentRefs:
- name: kong-gtw
hostnames:
- "gtw.dev"
rules:
- matches:
- headers:
- type: Exact
name: area
value: north
backendRefs:
- name: blue-svc
port: 80


-
- Gateway API 不仅支持路由转发,它还能够轻松实现流量拆分,比如常见的金丝雀部署和蓝绿部署。
Q: HTTPRoute.spec.rules[]优先匹配哪条rule? 豆包:
Gateway API官方规范:rules数组从上向下依次评估,命中第一条matches匹配的rule即停止;
但是主流 Envoy 系网关(Kong、Istio、Gloo)实现不同:matches.path约束更强(更具体的)的rule 优先匹配,其次才看rules数组顺序。
所以推荐:把matches约束越精细的rule,写在rules数组靠前位置,泛匹配兜底rule放在最后。
- Gateway API 不仅支持路由转发,它还能够轻松实现流量拆分,比如常见的金丝雀部署和蓝绿部署。
我改了下yaml,因为原文应该搞反了,蓝绿才是100%切换的。另外也是为了验证以下结论:matches数组的每个数组元素之间的逻辑关系是OR,数组元素内部的逻辑关系才是AND:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: ngx-blue-green-route
spec:
parentRefs:
- name: kong-gtw
hostnames:
- "blue-green.test"
rules:
- backendRefs:
- name: blue-svc
port: 80
- matches:
- headers:
- name: traffic
value: green1
path:
type: Exact
value: /green1
- headers:
- name: traffic
value: green2
path:
type: Exact
value: /green2
backendRefs:
- name: green-svc
port: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: ngx-canary-route
spec:
parentRefs:
- name: kong-gtw
hostnames:
- "canary.test"
rules:
- backendRefs:
- name: black-svc
port: 80
weight: 70
- name: red-svc
port: 80
weight: 30

我:金丝雀发布(灰度发布)的weight,是同一个rules[].backendRefs[]数组内各服务的比例。
测试灰度效果:curl $(minikube ip):32379 -H 'host: canary.test',可以看到大部分流量(7成)打到了black-svc,其它打到red-svc。
-
- 最后我们再来看一下 Gateway API 的 filter 特性,它可以对应到 Kong Gateway 的插件机制,实现对流量的附加处理,比如速率限制、改写数据、身份验证等等,不过目前标准的 filter 还不多,所以有的时候还是要依赖 CRD 资源定义 Plugin。
下面的 YAML 添加了响应头和限速:
- 最后我们再来看一下 Gateway API 的 filter 特性,它可以对应到 Kong Gateway 的插件机制,实现对流量的附加处理,比如速率限制、改写数据、身份验证等等,不过目前标准的 filter 还不多,所以有的时候还是要依赖 CRD 资源定义 Plugin。
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: kong-rate-limiting-plugin
plugin: rate-limiting
config:
minute: 2
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: ngx-filter-route
annotations:
konghq.com/plugins: kong-rate-limiting-plugin #把上面的kong限流插件绑定到这条HTTPRoute
spec:
parentRefs:
- name: kong-gtw
hostnames:
- "filter.test"
rules:
- backendRefs:
- name: black-svc
port: 80
filters:
- type: ResponseHeaderModifier #GatewayAPI内置过滤器,和Kong插件相互独立
responseHeaderModifier:
add:
- name: A-New-Header
value: k8s-gtw-api
连续发送请求curl请求3次,可以看到kong-rate-limiting-plugin的限速效果。响应头中,红框是kong-rate-limiting-plugin造成的,黄框是filter造成的:

- 小结
Gateway API,它是 Ingress 的继任者,功能更强大、用法更灵活,也是 Kubernetes 社区今后的重点发展方向。
我画的图:

更多推荐

所有评论(0)