<aside> ⏰ 本文我们将通过 golang 来实现一个简单的自定义的 Ingress 控制器。

</aside>

在 Kubernetes 中通过 Ingress 来暴露服务到集群外部,这个已经是一个很普遍的方式了,而真正扮演请求转发的角色是背后的 Ingress Controller,比如我们经常使用的 traefik、ingress-nginx 等就是一个 Ingress Controller。本文我们将通过 golang 来实现一个简单的自定义的 Ingress Controller,可以加深我们对 Ingress 的理解。

概述

我们在 Kubernetes 集群上往往会运行很多无状态的 Web 应用,一般来说这些应用是通过一个 Deployment 和一个对应的 Service 组成,比如我们在集群上运行一个 whoami 的应用,对应的资源清单如下所示:

# whoami.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami
  labels:
    app: whoami
spec:
  replicas: 1
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
        - name: whoami
          image: cnych/whoami
          ports:
            - containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
  name: whoami
spec:
  selector:
    app: whoami
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

可以直接使用上面的资源清单部署该应用:

$ kubectl apply -f whoami.yaml

通过部署该应用,在 Kubernetes 集群内部我们可以通过地址 whoami.default.svc.cluster.local 来访问该 Web 应用,但是在集群外部的用户应该如何来访问呢?当然我们可以使用 NodePort 类型的 Service 来进行访问,但是当我们应用越来越多的时候端口的管理也是一个很大的问题,所以一般情况下不采用该方式,之前我们的方法是用 DaemonSet 在每个边缘节点上运行一个 Nginx 应用:

spec:
  hostNetwork: true
  containers:
  - image: nginx:1.15.3-alpine
    name: nginx
    ports:
      - name: http
        containerPort: 80
        hostPort: 80

通过设置 hostNetwork:true,容器将绑定节点的80端口,而不仅仅是容器,这样我们就可以通过节点的公共 IP 地址的 80 端口访问到 Nginx 应用了。这种方法理论上肯定是有效的,但是有一个最大的问题就是需要创建一个 Nginx 配置文件,如果应用有变更,还需要手动修改配置,不能自动发现和热更新,这对于大量的应用维护的成本显然太大。这个时候我们就可以用另外一个 Kubernetes 提供的方案了:Ingress

Ingress 对象

Kubernetes 内置就支持通过 Ingress 对象将外部的域名映射到集群内部服务,我们可以通过如下的 Ingress 对象来对外暴露服务:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: whoami
spec:
  tls:
    - hosts:
        - "*.qikqiak.com"
      secretName: qikqiak-tls
  rules:
    - host: who.qikqiak.com
      http:
        paths:
          - path: /
            backend:
              serviceName: whoami
              servicePort: 80

该资源清单声明了如何将 HTTP 请求路由到后端服务:

这个配置显然比我们取手动维护 Nginx 的配置要方便太多了,完全就是自动化的。

Ingress Controllers