Kubernetes Ingress

Kubernetes Ingress

Posted by alovn on November 26, 2020

Ingress 是什么

Ingress 可以通过HTTP或HTTPS公开集群内部的Service,而不需要再通过NodePort的方式暴露服务。

下面是一个将所有流量都发送到同一 Service 的简单 Ingress 示例:

1
客户端--->Ingress---路由规则--->Service--->Pod

Ingress-Controller 并不是K8S自带的组件,它只是一个统称,我们可以选择不同的Ingress-Controller的实现。官方提供了ingress-nginx, 也可以选择 其它的ingress实现, 比如有:

  • APISIX ingress
  • Nginx ingress
  • Kong ingress
  • Traefik ingress
  • Haproxy ingress
  • Istio ingress
  • Ambassador ingress

它们的实现机制都大同小异,Ingress-Controller一般都会有一个Pod,里面跑着反向代理,并不断的监听着集群的变化,动态生成路由配置。

你可以将 ingress-nginx 看作一个nginx外加一些 golang 和 lua 代码。

部署 ingress-nginx

可以想将yaml文件下载过来,根据自己的需要稍作修改修改:

1
2
3
wget  -e "https_proxy=http://172.16.10.11:8118" https://github.com/kubernetes/ingress-nginx/raw/nginx-0.30.0/deploy/static/mandatory.yaml

kubectl apply -f mandatory.yaml

我这里作了两处改动:

  1. 将 nginx-ingress-controller 的 Deployment 改为DaemonSet,这样就可以在每个node节点上部署一个ingress-nginx了。
  2. Deployment 下增加配置 hostNetwork 并设置为 true,这样可以每个节点上将80端口和443端口暴露出来, 还可以增加一个SLB前置负载到每个节点。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    spec:
      hostNetwork: true # 增加的配置
      terminationGracePeriodSeconds: 300
      serviceAccountName: nginx-ingress-serviceaccount
      nodeSelector:
        kubernetes.io/os: linux
      containers:
        - name: nginx-ingress-controller
          image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
          args:
            - /nginx-ingress-controller
            - --configmap=$(POD_NAMESPACE)/nginx-configuration
            - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
            - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
            - --publish-service=$(POD_NAMESPACE)/ingress-nginx
            - --annotations-prefix=nginx.ingress.kubernetes.io

你可能也会看到这样的警告:

1
Warning: rbac.authorization.k8s.io/v1beta1 ClusterRole is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 ClusterRole

有的api版本已经过期,根据提示将yaml文件中的v1beta1改为v1, 再重新执行 kubectl apply就可以了。看下ingress-nginx的pod部署情况:

1
2
3
4
5
# kubectl get pods -n ingress-nginx
NAME                                        READY   STATUS    RESTARTS   AGE
nginx-ingress-controller-54b86f8f7b-fq899   1/1     Running   0          11h
nginx-ingress-controller-sv7z8              1/1     Running   0          20m
nginx-ingress-controller-znq5r              1/1     Running   0          20m

另外需要注意的是执行 kubectl apply -f mandatory.yaml 会自动下载需要的镜像,可能需要翻墙,如果没有成功,可以检查下是不是没有下载到镜像。

通过ingress-nginx暴露服务

现在可以通过ingress-nginx暴露后端的服务了, 增加ingress-nginx.yaml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: ingress
      annotations:
        kubernetes.io/ingress.class: "nginx"
        nginx.ingress.kubernetes.io/rewrite-target: /
    spec:
      rules:
      - host: "foo.bar.com" # 指定host
        http:
          paths:
          - pathType: Prefix
            path: "/" # 可以定义路由规则
            backend:
              service:
                name: nginx # 要通过ingres暴露的服务
                port:
                  number: 80

执行一下:

1
kubectl apply -f ingress-nginx.yaml

查看ingress:

1
2
3
# kubectl get ingress
NAME      CLASS    HOSTS         ADDRESS   PORTS   AGE
ingress   <none>   foo.bar.com             80      3m

通过curl测试一下, 这个IP是宿主机的IP:

1
2
3
4
5
6
7
8
9
10
11
# curl -I  http://foo.bar.com -x 172.16.10.13:80
HTTP/1.1 200 OK
Server: nginx/1.17.8
Date: Thu, 26 Nov 2020 13:47:11 GMT
Content-Type: text/html
Content-Length: 612
Connection: keep-alive
Vary: Accept-Encoding
Last-Modified: Thu, 26 Oct 2020 15:09:20 GMT
ETag: "5f983820-264"
Accept-Ranges: bytes

通过ingress-nginx暴露tcp服务

通过 ingress-nginx 不仅可以暴露基于http的内部服务,还可以通过L4负载暴露内部的tcp,upd服务。

通过查看以上mandatory.yaml文件,可以看到 tcp-services-configmap, udp-services-configmap 这些都是通过 configmap 动态配置的。可以修改名称为 tcp-services 和 udp-services的 ConfigMap 暴露服务。

示例:

1
2
3
4
5
6
7
8
9
10
kind: ConfigMap
apiVersion: v1
metadata:
  name: tcp-services
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
data:
    16379: "default/redis-svc:6379" # 增加的配置

这里是将default命名空间下的redis-svc的6379端口负载到ingress-nginx的16379端口,udp-service也是一样的。

参考文档

K8S Ingress

Ingress控制器

Github-Ingress-Nginx