全笔记:
《开篇词 (2讲)》
《入门篇 (8讲)》
《初级篇 (9讲)》
《中级篇 (8讲)》
《高级篇 (10讲)》
《加餐分享 (2讲)》

Kubernetes英文博客

考虑扩展学习:

  • 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放在最后。

我改了下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 添加了响应头和限速:
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 社区今后的重点发展方向。
    我画的图:
    在这里插入图片描述

  1. CSDN:安装minikube无法拉取kicbase镜像 ↩︎

更多推荐