本文将使用helm在Kubernetes集群中部署微服务API网关kong,并将其用作Kubernetes的Ingress Controller。

Kong官方单独维护了一个项目叫Kong for Kubernetes,项目的地址是https://github.com/Kong/kubernetes-ingress-controller。 Kong for Kubernetes是一个Kubernetes的Ingress Controller,通过插件架构提供API管理能力。 Kong官方另外提供了一个Helm Chart,使用Helm安装这个Chart可以在Kubernetes集群上运行Kong所需的所有组件。

使用helm部署在Kubernetes集群中部署kong for kubernetes,需要先添加kong的chart repo:

1helm repo add kong https://charts.konghq.com
2helm repo update

接下来需要针对所部署的Kubernetes环境定制配置,可以参考kong helm chart的配置文档https://github.com/Kong/charts/blob/main/charts/kong/README.md, 也可以使用下面的命令打印chart的默认配置再参考默认配置结合部署环境做出定制:

1helm show values kong/kong

这里先做最基本的安装,目标是基本实现与nginx ingress controller相同的功能,kong对API管理的高级功能后边再单独详细介绍。 根据最基本安装的目标对配置定制如下,创建kong-values.yaml文件:

 1ingressController:
 2  ingressClass: kong
 3postgresql:
 4  enabled: false
 5
 6proxy:
 7  http:
 8    hostPort: 80
 9  tls:
10    hostPort: 443
11
12nodeSelector:
13  node-role.kubernetes.io/edge: ''
14affinity:
15  podAntiAffinity:
16      requiredDuringSchedulingIgnoredDuringExecution:
17      - labelSelector:
18          matchExpressions:
19          - key: app.kubernetes.io/instance
20            operator: In
21            values:
22            - kong
23          - key: app.kubernetes.io/name
24            operator: In
25            values:
26            - kong
27        topologyKey: kubernetes.io/hostname
28tolerations:
29    - key: node-role.kubernetes.io/master
30      operator: Exists
31      effect: NoSchedule
32    - key: node-role.kubernetes.io/master
33      operator: Exists
34      effect: PreferNoSchedule

上面的配置指定kong以dbless模式部署,并指定ingressClass为空,另外做了Pod调度相关配置。

使用下面的命令安装:

1helm install ingress-kong kong/kong --create-namespace -n ingress-kong -f kong-values.yaml

安装完成后,查看可以看出默认以Deployment部署,同时创建了Type为LoadBalancer的service kong-kong-proxy并暴露了30444和30079两个NodePort分别对应http和https协议, 由云提供商外部负载均衡器将流量路由到自动创建的两个NodePort上。

 1kubectl get all -n ingress-kong
 2NAME                                     READY   STATUS    RESTARTS   AGE
 3pod/ingress-kong-kong-554f65c956-44xlq   2/2     Running   0          2m11s
 4
 5NAME                              TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
 6service/ingress-kong-kong-proxy   LoadBalancer   10.98.63.185   <pending>     80:31374/TCP,443:32492/TCP   2m11s
 7
 8NAME                                READY   UP-TO-DATE   AVAILABLE   AGE
 9deployment.apps/ingress-kong-kong   1/1     1            1           2m11s
10
11NAME                                           DESIRED   CURRENT   READY   AGE
12replicaset.apps/ingress-kong-kong-554f65c956   1         1         1       2m11s

因为这里使用的Kubernetes集群并没有cloud provider,所以上面ingress-kong-kong-proxyEXTERNAL-IP一直处于pending状态,不过没有关系,helm在安装时的定制配置中开启了 http和https的两个hostPort,而且通过podAntiAffinity限制Pod在调度时相同的两个Pod不会调度到同一个Node上,所以我们可以使用http//edgeNodeIphttps//edgeNodeIp的形式来访问kong的proxy服务。 ingress-kong-kong-554f65c956-44xlq这个Pod中有两个容器,一个是Proxy即kong本身,另一个是kong ingress controller。

1curl http://192.168.100.101
2{"message":"no Route matched with those values"}

在node上使用netstat -nltp查看发现并没有监听80和443端口,而可以使用hostPort直接访问的原因是因为,是k8s帮我们创建了hostPort到containerPort的nat,可以下面的命令查看:

1kubectl get pod -n ingress-kong -o wide
2NAME                                 READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
3ingress-kong-kong-554f65c956-44xlq   2/2     Running   0          14m   10.244.166.136   node1   <none>           <none>
4
5iptables -nvL -t nat | grep  DNAT | grep 10.244.166.136
6    2   120 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:10.244.166.136:8000
7    2   128 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:443 to:10.244.166.136:8443

我们已经完成kong ingress controller的安装,注意这里使用的Kubernetes集群中并没有安装其他的ingress controller(如nginx ingress controller),如果需要在集群中安装多个不同的ingress controller 还需要做特别的配置和避免冲突,k8s的ingress文档https://kubernetes.io/docs/concepts/services-networking/ingress/中有这部分内容描述(例如IngressClass资源),这里不再展开,后边有机会再详细介绍。

到目前为止我们已经在Kubernetes集群中部署了Kong for Kubernetes这个Ingress Controller,下面我们来创建Ingress尝试使用它。 我们使用它来将k8s的dashbaord暴露到集群外部,创建k8s dashbaord的ingress如下:

 1apiVersion: networking.k8s.io/v1
 2kind: Ingress
 3metadata:
 4  annotations:
 5    kubernetes.io/ingress.class: kong
 6    konghq.com/protocols: "https"
 7  name: kubernetes-dashboard
 8  namespace: kube-system
 9spec:
10  rules:
11  - host: k8s.example.com
12    http:
13      paths:
14      - backend:
15          service:
16            name: kubernetes-dashboard
17            port:
18              number: 443
19        path: /
20        pathType: Prefix
21  tls:
22  - hosts:
23    - k8s.example.com
24    secretName: example-com-tls-secret

因为后端k8s dashboard使用的是https,所以还需要修改k8s dashbaord的service加入konghq.com/protocol: https这个annotation。 关于kong ingress的配置注解可以查看文档。完成以上配置后,访问https://k8s.example.com可以正常打开k8s dashboard。k8s dashboard的由kong暴露到k8s集群外部。

到这里,我们已经完成Kong for Kubernetes最简单的基本部署,实现了与nginx ingress controller相同的功能,kong对API管理的高级功能这是nginx ingress controller不具备的,后边单独展开。

参考