本文将使用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:

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

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

1
helm show values kong/kong

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
ingressController:
  ingressClass: kong
postgresql:
  enabled: false

proxy:
  http:
    hostPort: 80
  tls:
    hostPort: 443

nodeSelector:
  node-role.kubernetes.io/edge: ''
affinity:
  podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app.kubernetes.io/instance
            operator: In
            values:
            - kong
          - key: app.kubernetes.io/name
            operator: In
            values:
            - kong
        topologyKey: kubernetes.io/hostname
tolerations:
    - key: node-role.kubernetes.io/master
      operator: Exists
      effect: NoSchedule
    - key: node-role.kubernetes.io/master
      operator: Exists
      effect: PreferNoSchedule

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

使用下面的命令安装:

1
helm 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上。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
kubectl get all -n ingress-kong
NAME                                     READY   STATUS    RESTARTS   AGE
pod/ingress-kong-kong-554f65c956-44xlq   2/2     Running   0          2m11s

NAME                              TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
service/ingress-kong-kong-proxy   LoadBalancer   10.98.63.185   <pending>     80:31374/TCP,443:32492/TCP   2m11s

NAME                                READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ingress-kong-kong   1/1     1            1           2m11s

NAME                                           DESIRED   CURRENT   READY   AGE
replicaset.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。

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

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

1
2
3
4
5
6
7
kubectl get pod -n ingress-kong -o wide
NAME                                 READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
ingress-kong-kong-554f65c956-44xlq   2/2     Running   0          14m   10.244.166.136   node1   <none>           <none>

iptables -nvL -t nat | grep  DNAT | grep 10.244.166.136
    2   120 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:10.244.166.136:8000
    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如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: kong
    konghq.com/protocols: "https"
  name: kubernetes-dashboard
  namespace: kube-system
spec:
  rules:
  - host: k8s.example.com
    http:
      paths:
      - backend:
          service:
            name: kubernetes-dashboard
            port:
              number: 443
        path: /
        pathType: Prefix
  tls:
  - hosts:
    - k8s.example.com
    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不具备的,后边单独展开。

参考