我们前面介绍过用Service做集群代理,Service一般情况下只作用于内部Pod的代理调度,就算有NodePort类型,其访问节点相对复杂,流程大概如下:
image.png
但是我们知道,如果只指定一个NodeIP,随着业务量增大,这个Node的压力就会很大,所以我们可能会在前端再加一个代理,代理几个Node,比如我们在前端加一个NG,流程如下:
image.png

在应用小的情况下,这种架构虽然调度复杂,但是也可以使用,但是如果有大量应用,这种管理就非常麻烦,因为 我们要管理大量的NodePort,这个时候使用Ingress就非常方便。

再则,Service的转发不论是iptables还是ipvs,都是4层的,但是在实际中基本都https请求,https是7层,4层是没办法对起进行SSL校验的,如果我们是第二幅流程图,我们可以在前置NG上配置SSL,但是如果我们是第一幅图的流程,我们只能在Pod上配置SSL,因为Service上是无法进行校验,那么就会出现一个问题,SSL的校验是很耗资源的,我们的客户端访问Pod,如果Pod非常多并且访问模式是轮询,那么每访问一次就要做一次SSL校验,这就非常不科学,我们就只有用类似于第二副图的架构,Ingress可以很完美的解决这种问题。

一、Ingress

image.png
流程图如上,其中Ingress代理的并不是Pod的Service,而是Pod,之所以在配置的时候是配置的Service,是为了获取Pod的信息。

Ingress提供外部访问集群的入口,将外部的HTTP或者HTTPS请求转发到集群内Service上,流量规则是在Ingress资源上定义。
配置Ingress资源的必要条件是你的kubernetes集群种由Ingress controller。其中Ingress Controller常用的有如下:

  • HAProxy Ingress Controller
  • Nginx Ingress Controller
  • Traefik Ingress Controller
  • Kong Ingress Controller

其中最常用的是Nginx Controller和Traefik Ingress Controller。
定义一个简单的Ingresss:
[root@master ingress]# cat ingress-simple-daemo.yaml

  1. apiVersion: networking.k8s.io/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: ingress-simple-daemo
  5. annotations:
  6. nginx.ingress.kubernetes.io/rewrite-target: /
  7. spec:
  8. rules:
  9. - http:
  10. paths:
  11. - path: /joker
  12. backend:
  13. serviceName: nginx
  14. servicePort: 80

简要说明:
apiVersion,kind,metadata,spec都是Kubernetes YAML文件的标准字段,Ingress经常通过annotations来配置一些选项,比如rewrite-target,不同的Ingress Controller支持不同的annotations。对于规则而言,每个HTTP都有如下规则:

  • 主机:主机是可选参数,如果不配置表示适用于所有主机HTTP通信,如果配置了表示只适用于该主机;
  • 路径:类似于NG的location,每个路径后面都有后端ServiceName和ServicePort;
  • 后端:后端是ServiceName和ServicePort组合,符合该规则的流量会转发到这个后端Service上。通常会在Ingress中配置默认后端,以匹配任何不符合规则的请求流量转发;
  • 具体的语法规则可以通过kubectl explain ingress来查看。

1.1、Ingress 类型

1.1.1、单服务Ingress

Kubernetes中已经存在一些概念可以暴露单个service(查看替代方案),但是你仍然可以通过Ingress来实现,通过指定一个没有rule的默认backend的方式。比如:
[root@master ingress]# cat single-service-ingress.yaml

  1. apiVersion: extensions/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: single-service-ingress
  5. spec:
  6. backend:
  7. serviceName: nginx
  8. servicePort: 80

1.1.2、简单展开

如前面描述的那样,kubernete pod中的IP只在集群网络内部可见,我们需要在边界设置一个东西,让它能够接收ingress的流量并将它们转发到正确的端点上。这个东西一般是高可用的loadbalancer。使用Ingress能够允许你将loadbalancer的个数降低到最少,例如,假如你想要创建这样的一个设置:

  1. foo.bar.com -> 178.91.123.132 -> / foo service1:4200
  2. / bar service2:8080

我们就可以这样配置Ingress:

  1. apiVersion: networking.k8s.io/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: simple-fanout-example
  5. annotations:
  6. nginx.ingress.kubernetes.io/rewrite-target: /
  7. spec:
  8. rules:
  9. - host: foo.bar.com
  10. http:
  11. paths:
  12. - path: /foo
  13. backend:
  14. serviceName: service1
  15. servicePort: 4200
  16. - path: /bar
  17. backend:
  18. serviceName: service2
  19. servicePort: 8080

1.1.3、基于名称的虚拟主机

如果想实现下面这种需求:

  1. foo.bar.com --| |-> foo.bar.com s1:80
  2. | 178.91.123.132 |
  3. bar.foo.com --| |-> bar.foo.com s2:80

我们就可以这样配置Ingress:

  1. apiVersion: networking.k8s.io/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: name-virtual-host-ingress
  5. spec:
  6. rules:
  7. - host: foo.bar.com
  8. http:
  9. paths:
  10. - backend:
  11. serviceName: service1
  12. servicePort: 80
  13. - host: bar.foo.com
  14. http:
  15. paths:
  16. - backend:
  17. serviceName: service2
  18. servicePort: 80

如果要增加配置默认的backend,可以配置成如下Ingress:

  1. apiVersion: networking.k8s.io/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: name-virtual-host-ingress
  5. spec:
  6. rules:
  7. - host: first.bar.com
  8. http:
  9. paths:
  10. - backend:
  11. serviceName: service1
  12. servicePort: 80
  13. - host: second.foo.com
  14. http:
  15. paths:
  16. - backend:
  17. serviceName: service2
  18. servicePort: 80
  19. - http:
  20. paths:
  21. - backend:
  22. serviceName: service3
  23. servicePort: 80

默认backend:一个没有rule的ingress,所有流量都将发送到一个默认backend。你可以用该技巧通知loadbalancer如何找到你网站的404页面,通过制定一些列rule和一个默认backend的方式。如果请求header中的host不能跟ingress中的host匹配,并且/或请求的URL不能与任何一个path匹配,则流量将路由到你的默认backend。

1.1.4、TLS

你可以通过指定包含TLS私钥和证书的secret来加密Ingress。 目前,Ingress仅支持单个TLS端口443,并假定TLS termination。 如果Ingress中的TLS配置部分指定了不同的主机,则它们将根据通过SNI TLS扩展指定的主机名(假如Ingress controller支持SNI)在多个相同端口上进行复用。 TLS secret中必须包含名为tls.crttls.key的密钥,这里面包含了用于TLS的证书和私钥,例如:

  1. apiVersion: v1
  2. kind: Secret
  3. metadata:
  4. name: testsecret-tls
  5. namespace: default
  6. data:
  7. tls.crt: base64 encoded cert
  8. tls.key: base64 encoded key
  9. type: kubernetes.io/tls

在Ingress中引用这个secret将通知Ingress controller使用TLS加密从将客户端到loadbalancer的channel:

  1. apiVersion: networking.k8s.io/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: tls-example-ingress
  5. spec:
  6. tls:
  7. - hosts:
  8. - sslexample.foo.com
  9. secretName: testsecret-tls
  10. rules:
  11. - host: sslexample.foo.com
  12. http:
  13. paths:
  14. - path: /
  15. backend:
  16. serviceName: service1
  17. servicePort: 80

注意:各种Ingress controller支持的TLS功能之间存在差距。 请参阅有关nginxGCE或任何其他平台特定Ingress controller的文档,以了解TLS在你的环境中的工作原理。

1.2、Ingress更新

如果你想更改你现在正工作的Ingress,比如新增一个HOST,可以使用kubectl edit ingress my-ingress进行更新,在保存退出后其会触发Ingress Controller重新配置LB。比如我们现有一个ingress:

  1. [root@master ingress]# kubectl get ingresses.
  2. NAME HOSTS ADDRESS PORTS AGE
  3. * 80 58m

然后我们使用kubectl edit ingress ingress-simple-daemo来新增一个HOST:

  1. ......
  2. spec:
  3. rules:
  4. - http:
  5. paths:
  6. - backend:
  7. serviceName: nginx-service
  8. servicePort: 8000
  9. path: /joker
  10. - host: bar.baz.com
  11. http:
  12. paths:
  13. - backend:
  14. serviceName: nginx
  15. servicePort: 80
  16. path: /foo
  17. status:
  18. loadBalancer: {}

保存退出后就会生效:

  1. [root@master ingress]# kubectl describe ingresses ingress-simple-daemo
  2. Name: ingress-simple-daemo
  3. Namespace: default
  4. Address:
  5. Default backend: default-http-backend:80 (<none>)
  6. Rules:
  7. Host Path Backends
  8. ---- ---- --------
  9. *
  10. /joker nginx-service:8000 (172.20.2.84:80)
  11. bar.baz.com
  12. /foo nginx:80 (172.20.2.79:80,172.20.2.82:80)
  13. Annotations:
  14. kubernetes.io/ingress.class: traefik
  15. kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"networking.k8s.io/v1beta1","kind":"Ingress","metadata":{"annotations":{"kubernetes.io/ingress.class":"traefik"},"name":"ingress-simple-daemo","namespace":"default"},"spec":{"rules":[{"http":{"paths":[{"backend":{"serviceName":"nginx-service","servicePort":8000},"path":"/joker"}]}}]}}
  16. Events: <none>

二、Nginx Ingress

2.1、安装

2.1.1 在线安装

在线安装直接执行以下命令:

  1. kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml

然后安装NodePort:

  1. kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/baremetal/service-nodeport.yaml

2.1.2、离线安装

https://github.com/kubernetes/ingress-nginx/tree/master/deploy/static这个下面下载对应的YAML文件,有configmap.yamlnamespace.yamlrbac.yamlwith-rbac.yaml,可以写一个如下循环下载:

  1. for yaml in configmap.yaml namespace.yaml rbac.yaml with-rbac.yaml; do wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/$yaml;done

然后执行如下命令安装,前提先执行namespace.yaml这个YAML文件:

  1. kubectl apply -f namespace.yaml
  2. kubectl apply -f .

然后我们可以执行以下命令查看:

  1. [root@master nginx]# kubectl get pod -n ingress-nginx
  2. NAME READY STATUS RESTARTS AGE
  3. nginx-ingress-controller-799dbf6fbd-zxvmp 0/1 ContainerCreating 0 12s

然后安装nodePort:

  1. wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/baremetal/service-nodeport.yaml
  2. kubectl apply -f service-nodeport.yaml

然后我修改了nodePort的端口,如下:

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: ingress-nginx
  5. namespace: ingress-nginx
  6. labels:
  7. app.kubernetes.io/name: ingress-nginx
  8. app.kubernetes.io/part-of: ingress-nginx
  9. spec:
  10. type: NodePort
  11. ports:
  12. - name: http
  13. port: 80
  14. targetPort: 80
  15. nodePort: 30080
  16. protocol: TCP
  17. - name: https
  18. port: 443
  19. targetPort: 443
  20. nodePort: 30443
  21. protocol: TCP
  22. selector:
  23. app.kubernetes.io/name: ingress-nginx
  24. app.kubernetes.io/part-of: ingress-nginx
  25. ---

然后查看结果:

  1. [root@master nginx]# kubectl get pod -n ingress-nginx
  2. NAME READY STATUS RESTARTS AGE
  3. nginx-ingress-controller-799dbf6fbd-zxvmp 1/1 Running 0 52m
  4. [root@master nginx]# kubectl get svc -n ingress-nginx
  5. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  6. ingress-nginx NodePort 10.68.194.177 <none> 80:30080/TCP,443:30443/TCP 46m

2.2、使用

先创建Pod,service,定义如下YAML:
[root@master test]# cat nginx-ingress-demo.yaml

  1. ---
  2. apiVersion: extensions/v1beta1
  3. kind: Deployment
  4. metadata:
  5. name: nginx-deploy
  6. namespace: default
  7. spec:
  8. replicas: 3
  9. selector:
  10. matchLabels:
  11. app: nginx-demo
  12. release: canary
  13. template:
  14. metadata:
  15. name: my-nginx
  16. labels:
  17. app: nginx-demo
  18. release: canary
  19. spec:
  20. containers:
  21. - name: my-nginx
  22. image: nginx
  23. imagePullPolicy: IfNotPresent
  24. ports:
  25. - name: http
  26. containerPort: 80
  27. ---
  28. apiVersion: v1
  29. kind: Service
  30. metadata:
  31. name: nginx-svc
  32. namespace: default
  33. spec:
  34. selector:
  35. app: nginx-demo
  36. release: canary
  37. ports:
  38. - name: http
  39. port: 80
  40. targetPort: 80

然后执行kubectl apply -f nginx-ingress-demo.yaml,查看结果:

  1. [root@master test]# kubectl get pod
  2. NAME READY STATUS RESTARTS AGE
  3. nginx-deploy-549cb5c7ff-65fbb 1/1 Running 0 21s
  4. nginx-deploy-549cb5c7ff-75fmt 1/1 Running 0 21s
  5. nginx-deploy-549cb5c7ff-wg4w7 1/1 Running 0 17s
  6. [root@master test]# kubectl get svc
  7. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  8. kubernetes ClusterIP 10.68.0.1 <none> 443/TCP 5d2h
  9. nginx-svc ClusterIP 10.68.214.28 <none> 80/TCP 6m21s

然后定义Ingress Nginx,YAML文件如下:
[root@master test]# cat ingress-nginx.yaml

  1. apiVersion: networking.k8s.io/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: ingress-nginx
  5. annotations:
  6. kubernetes.io/ingress.class: "nginx"
  7. spec:
  8. rules:
  9. - host:
  10. http:
  11. paths:
  12. - path:
  13. backend:
  14. serviceName: nginx-svc
  15. servicePort: 80

然后查看结果:

  1. [root@master test]# kubectl describe ingresses ingress-nginx
  2. Name: ingress-nginx
  3. Namespace: default
  4. Address: 10.68.194.177
  5. Default backend: default-http-backend:80 (<none>)
  6. Rules:
  7. Host Path Backends
  8. ---- ---- --------
  9. *
  10. nginx-svc:80 (172.20.1.61:80,172.20.1.62:80,172.20.2.87:80)
  11. Annotations:
  12. kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"networking.k8s.io/v1beta1","kind":"Ingress","metadata":{"annotations":{"kubernetes.io/ingress.class":"nginx"},"name":"ingress-nginx","namespace":"default"},"spec":{"rules":[{"host":null,"http":{"paths":[{"backend":{"serviceName":"nginx-svc","servicePort":80},"path":null}]}}]}}
  13. kubernetes.io/ingress.class: nginx
  14. Events:
  15. Type Reason Age From Message
  16. ---- ------ ---- ---- -------
  17. Normal CREATE 11m nginx-ingress-controller Ingress default/ingress-nginx
  18. Normal UPDATE 77s (x3 over 11m) nginx-ingress-controller Ingress default/ingress-nginx

在流量器访问:
image.png

2.3、TLS

Nginx Ingress不止支持HTTP,还支持HTTPS。我们使用如下命令手动创建证书:

  1. openssl genrsa -out tls.key 2048
  2. openssl req -new -x509 -key tls.key -out tls.crt -subj "/C=CN/ST=Chongqing/L=Chongqing/OU=DevOps/CN=nginx.joker.com"

然后配置Secrect:

  1. kubectl create secret tls tls-secret --key tls.key --cert tls.crt

然后查看:

  1. [root@master test]# kubectl get secret
  2. NAME TYPE DATA AGE
  3. default-token-gmdbb kubernetes.io/service-account-token 3 5d3h
  4. tls-secret kubernetes.io/tls 2 20s
  5. [root@master test]# kubectl describe secrets tls-secret
  6. Name: tls-secret
  7. Namespace: default
  8. Labels: <none>
  9. Annotations: <none>
  10. Type: kubernetes.io/tls
  11. Data
  12. ====
  13. tls.crt: 1302 bytes
  14. tls.key: 1679 bytes

配置Ingress nginx:
[root@master test]# cat ingress-nginx-tls.yaml

  1. apiVersion: networking.k8s.io/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: ingress-nginx-tls
  5. annotations:
  6. kubernetes.io/ingress.class: "nginx"
  7. spec:
  8. tls:
  9. - host:
  10. secretName: tls-secret
  11. rules:
  12. - host:
  13. http:
  14. paths:
  15. - path:
  16. backend:
  17. serviceName: nginx-svc
  18. servicePort: 80

然后查看结果:

  1. [root@master test]# kubectl get ingresses.
  2. NAME HOSTS ADDRESS PORTS AGE
  3. ingress-nginx-tls * 80, 443 4s

浏览器访问:
image.png

三、Traefik Ingress

3.1、安装

创建namespace(namespace.yaml):

  1. apiVersion: v1
  2. kind: Namespace
  3. metadata:
  4. name: ingress-traefik
  5. labels:
  6. app.kubernetes.io/name: ingress-traefik
  7. app.kubernetes.io/part-of: ingress-traefik
  8. ---

创建RBAC安全认证(rdac.yaml):

  1. ---
  2. apiVersion: v1
  3. kind: ServiceAccount
  4. metadata:
  5. name: traefik-ingress-controller
  6. namespace: ingress-traefik
  7. ---
  8. kind: ClusterRole
  9. apiVersion: rbac.authorization.k8s.io/v1beta1
  10. metadata:
  11. name: traefik-ingress-controller
  12. rules:
  13. - apiGroups:
  14. - ""
  15. resources:
  16. - services
  17. - endpoints
  18. - secrets
  19. verbs:
  20. - get
  21. - list
  22. - watch
  23. - apiGroups:
  24. - extensions
  25. resources:
  26. - ingresses
  27. verbs:
  28. - get
  29. - list
  30. - watch
  31. ---
  32. kind: ClusterRoleBinding
  33. apiVersion: rbac.authorization.k8s.io/v1beta1
  34. metadata:
  35. name: traefik-ingress-controller
  36. roleRef:
  37. apiGroup: rbac.authorization.k8s.io
  38. kind: ClusterRole
  39. name: traefik-ingress-controller
  40. subjects:
  41. - kind: ServiceAccount
  42. name: traefik-ingress-controller
  43. namespace: ingress-traefik

配置traefik(traefik.yaml):

  1. ---
  2. kind: Deployment
  3. apiVersion: extensions/v1beta1
  4. metadata:
  5. name: traefik-ingress-controller
  6. namespace: ingress-traefik
  7. labels:
  8. k8s-app: traefik-ingress-lb
  9. spec:
  10. replicas: 1
  11. selector:
  12. matchLabels:
  13. k8s-app: traefik-ingress-lb
  14. template:
  15. metadata:
  16. labels:
  17. k8s-app: traefik-ingress-lb
  18. name: traefik-ingress-lb
  19. spec:
  20. serviceAccountName: traefik-ingress-controller
  21. terminationGracePeriodSeconds: 60
  22. # tolerations:
  23. # - operator: "Exists"
  24. # nodeSelector:
  25. # kubernetes.io/hostname: master
  26. containers:
  27. - image: traefik:v1.7.17
  28. name: traefik-ingress-lb
  29. ports:
  30. - name: http
  31. containerPort: 80
  32. - name: admin
  33. containerPort: 8080
  34. args:
  35. - --api
  36. - --kubernetes
  37. - --logLevel=INFO
  38. ---
  39. kind: Service
  40. apiVersion: v1
  41. metadata:
  42. name: traefik-ingress-service
  43. namespace: ingress-traefik
  44. spec:
  45. selector:
  46. k8s-app: traefik-ingress-lb
  47. ports:
  48. - protocol: TCP
  49. port: 80
  50. name: web
  51. nodePort: 38000
  52. - protocol: TCP
  53. port: 8080
  54. nodePort: 38080
  55. name: admin
  56. type: NodePort

然后执行如下命令创建:

  1. kubectl apply -f .

查看其结果:

  1. [root@master traefik]# kubectl get svc -n ingress-traefik
  2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  3. traefik-ingress-service NodePort 10.68.173.196 <none> 80:38000/TCP,8080:38080/TCP 9m19s
  4. [root@master traefik]# kubectl get pod -n ingress-traefik
  5. NAME READY STATUS RESTARTS AGE
  6. traefik-ingress-controller-86769d5d99-fvf82 1/1 Running 0 7m10s

Traefik提供一个WEB UI工具,就是上面8080端口,可以通过其映射的NodePort端口在浏览器访问,如下:
image.png

3.2、使用

使用和上面nginx ingress一样,只是在annotations里配置的kubernetes.io/ingress.class: “traefik”。

3.3、配置

生成SSL证书:

  1. openssl req -newkey rsa:2048 -nodes -keyout tls.key -x509 -days 365 -out tls.crt

创建Secret来存储证书:

  1. # kubectl create secret generic traefik-cert --from-file=tls.crt --from-file=tls.key -n ingress-traefik

配置traefik,让其支持https,配置文件如下:

  1. defaultEntryPoints = ["http", "https"]
  2. [entryPoints]
  3. [entryPoints.http]
  4. address = ":80"
  5. [entryPoints.http.redirect]
  6. entryPoint = "https"
  7. [entryPoints.https]
  8. address = ":443"
  9. [entryPoints.https.tls]
  10. [[entryPoints.https.tls.certificates]]
  11. CertFile = "/ssl/tls.crt"
  12. KeyFile = "/ssl/tls.key"

将上面的 traefik.toml 配置文件通过一个 ConfigMap 对象挂载到 traefik pod 中去。
创建configMap:

  1. # kubectl create configmap traefik-conf --from-file=traefik.toml -n ingress-traefik

更改traefik的YAML文件:

  1. ---
  2. kind: Deployment
  3. apiVersion: extensions/v1beta1
  4. metadata:
  5. name: traefik-ingress-controller
  6. namespace: ingress-traefik
  7. labels:
  8. k8s-app: traefik-ingress-lb
  9. spec:
  10. replicas: 1
  11. selector:
  12. matchLabels:
  13. k8s-app: traefik-ingress-lb
  14. name: traefik-ingress-lb
  15. template:
  16. metadata:
  17. labels:
  18. k8s-app: traefik-ingress-lb
  19. name: traefik-ingress-lb
  20. spec:
  21. serviceAccountName: traefik-ingress-controller
  22. terminationGracePeriodSeconds: 60
  23. # tolerations:
  24. # - operator: "Exists"
  25. # nodeSelector:
  26. # kubernetes.io/hostname: master
  27. containers:
  28. - image: traefik:v1.7.17
  29. name: traefik-ingress-lb
  30. volumeMounts:
  31. - name: ssl
  32. mountPath: "/ssl"
  33. - name: config
  34. mountPath: "/config"
  35. ports:
  36. - name: http
  37. containerPort: 80
  38. - name: https
  39. containerPort: 443
  40. - name: admin
  41. containerPort: 8080
  42. args:
  43. - --configfile=/config/traefik.toml
  44. - --api
  45. - --kubernetes
  46. - --logLevel=INFO
  47. volumes:
  48. - name: ssl
  49. secret:
  50. secretName: traefik-cert
  51. - name: config
  52. configMap:
  53. name: traefik-conf
  54. ---
  55. kind: Service
  56. apiVersion: v1
  57. metadata:
  58. name: traefik-ingress-service
  59. namespace: ingress-traefik
  60. spec:
  61. selector:
  62. k8s-app: traefik-ingress-lb
  63. ports:
  64. - protocol: TCP
  65. port: 80
  66. name: web
  67. nodePort: 38000
  68. - protocol: TCP
  69. port: 8080
  70. nodePort: 38080
  71. name: admin
  72. type: NodePort

然后生成配置清单,并查看日志观察其是否生效;

  1. # kubectl apply -f traefik.yaml
  2. # kubectl logs traefik-ingress-controller-867f5668dd-7p7tv -n ingress-traefik
  3. time="2019-11-25T08:25:30Z" level=info msg="Using TOML configuration file /config/traefik.toml"
  4. time="2019-11-25T08:25:30Z" level=info msg="No tls.defaultCertificate given for https: using the first item in tls.certificates as a fallback."
  5. time="2019-11-25T08:25:30Z" level=info msg="Traefik version v1.7.17 built on 2019-09-23_06:22:08PM"
  6. time="2019-11-25T08:25:30Z" level=info msg="\nStats collection is disabled.\nHelp us improve Traefik by turning this feature on :)\nMore details on: https://docs.traefik.io/v1.7/basics/#collected-data\n"
  7. time="2019-11-25T08:25:30Z" level=info msg="Preparing server https &{Address::443 TLS:0xc0002b22d0 Redirect:<nil> Auth:<nil> WhitelistSourceRange:[] WhiteList:<nil> Compress:false ProxyProtocol:<nil> ForwardedHeaders:0xc00050a100} with readTimeout=0s writeTimeout=0s idleTimeout=3m0s"
  8. time="2019-11-25T08:25:30Z" level=info msg="Preparing server traefik &{Address::8080 TLS:<nil> Redirect:<nil> Auth:<nil> WhitelistSourceRange:[] WhiteList:<nil> Compress:false ProxyProtocol:<nil> ForwardedHeaders:0xc00050a120} with readTimeout=0s writeTimeout=0s idleTimeout=3m0s"
  9. time="2019-11-25T08:25:30Z" level=info msg="Starting server on :443"
  10. time="2019-11-25T08:25:30Z" level=info msg="Preparing server http &{Address::80 TLS:<nil> Redirect:0xc000843fc0 Auth:<nil> WhitelistSourceRange:[] WhiteList:<nil> Compress:false ProxyProtocol:<nil> ForwardedHeaders:0xc00050a0e0} with readTimeout=0s writeTimeout=0s idleTimeout=3m0s"
  11. time="2019-11-25T08:25:30Z" level=info msg="Starting server on :8080"
  12. time="2019-11-25T08:25:30Z" level=info msg="Starting provider configuration.ProviderAggregator {}"
  13. time="2019-11-25T08:25:30Z" level=info msg="Starting server on :80"
  14. time="2019-11-25T08:25:30Z" level=info msg="Starting provider *kubernetes.Provider {\"Watch\":true,\"Filename\":\"\",\"Constraints\":[],\"Trace\":false,\"TemplateVersion\":0,\"DebugLogGeneratedTemplate\":false,\"Endpoint\":\"\",\"Token\":\"\",\"CertAuthFilePath\":\"\",\"DisablePassHostHeaders\":false,\"EnablePassTLSCert\":false,\"Namespaces\":null,\"LabelSelector\":\"\",\"IngressClass\":\"\",\"IngressEndpoint\":null,\"ThrottleDuration\":0}"
  15. time="2019-11-25T08:25:30Z" level=info msg="ingress label selector is: \"\""
  16. time="2019-11-25T08:25:30Z" level=info msg="Creating in-cluster Provider client"
  17. time="2019-11-25T08:25:30Z" level=info msg="Server configuration reloaded on :443"
  18. time="2019-11-25T08:25:30Z" level=info msg="Server configuration reloaded on :8080"
  19. time="2019-11-25T08:25:30Z" level=info msg="Server configuration reloaded on :80"

3.4、Rewrite

测试demo:

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: nginx-demo
  5. spec:
  6. selector:
  7. app: nginx
  8. ports:
  9. - name: nginx
  10. port: 80
  11. ---
  12. apiVersion: extensions/v1beta1
  13. kind: Deployment
  14. metadata:
  15. name: nginx
  16. labels:
  17. app: nginx
  18. spec:
  19. replicas: 2
  20. selector:
  21. matchLabels:
  22. app: nginx
  23. template:
  24. metadata:
  25. labels:
  26. app: nginx
  27. spec:
  28. containers:
  29. - name: nginx
  30. image: nginx
  31. imagePullPolicy: IfNotPresent

正常访问的ingress如下:

  1. apiVersion: extensions/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: nginx-ingress-demo
  5. annotations:
  6. kubernetes.io/ingress.class: "traefik"
  7. spec:
  8. rules:
  9. - host:
  10. http:
  11. paths:
  12. - backend:
  13. serviceName: nginx-demo
  14. servicePort: 80
  15. path: /

但是如果我们把path改为如下:

  1. apiVersion: extensions/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: nginx-ingress-demo
  5. annotations:
  6. kubernetes.io/ingress.class: "traefik"
  7. spec:
  8. rules:
  9. - host:
  10. http:
  11. paths:
  12. - backend:
  13. serviceName: nginx-demo
  14. servicePort: 80
  15. path: /app

那么这时候访问就会报404.
image.png

这时候我们可以在配置里加上rewrite规则,如下:

  1. apiVersion: extensions/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: nginx-ingress-demo
  5. annotations:
  6. kubernetes.io/ingress.class: "traefik"
  7. traefik.ingress.kubernetes.io/rewrite-target: /
  8. spec:
  9. rules:
  10. - host:
  11. http:
  12. paths:
  13. - backend:
  14. serviceName: nginx-demo
  15. servicePort: 80
  16. path: /app

然后就可以正常访问了,如下:
image.png

为了更友好化,我们可以定义如下:

  1. apiVersion: extensions/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: nginx-ingress-demo
  5. annotations:
  6. kubernetes.io/ingress.class: "traefik"
  7. traefik.ingress.kubernetes.io/rewrite-target: /$2
  8. spec:
  9. rules:
  10. - host:
  11. http:
  12. paths:
  13. - backend:
  14. serviceName: nginx-demo
  15. servicePort: 80
  16. path: /app(/|$)(.*)

但是这种还是会有问题,比如有的静态资源无法正常显示,比如静态资源的路径在/static下面,现在我们做了 url rewrite 过后,要正常访问也需要带上前缀才可以:http://xxx.xxx/static/screen.css,对于图片或者其他静态资源也是如此,当然我们去更改页面引入静态资源的方式为相对路径也是可以的,但是毕竟要修改代码,这个时候我们可以借助 ingress-traefik 中的 configuration-snippet 来对静态资源做一次跳转,如下所示:

  1. apiVersion: extensions/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: nginx-ingress-demo
  5. annotations:
  6. kubernetes.io/ingress.class: "traefik"
  7. traefik.ingress.kubernetes.io/rewrite-target: /$2
  8. traefik.ingress.kubernetes.io/configuration-snippet: |
  9. rewrite ^/static/(.*)$ /app/static/$1 redirect;
  10. rewrite ^/image/(.*)$ /app/image/$1 redirect;
  11. spec:
  12. rules:
  13. - host:
  14. http:
  15. paths:
  16. - backend:
  17. serviceName: nginx-demo
  18. servicePort: 80
  19. path: /app(/|$)(.*)

这时候就可以正常加载静态资源了。

但是我们还想直接访问主域名,但是会报404,要解决这种问题,可以app-root的注解,这样我们访问主域名的时候就可以跳转到app-root目录(真实存在的路径)下面,如下:

  1. apiVersion: extensions/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: nginx-ingress-demo
  5. annotations:
  6. kubernetes.io/ingress.class: "traefik"
  7. traefik.ingress.kubernetes.io/app-root: /app/
  8. traefik.ingress.kubernetes.io/rewrite-target: /$2
  9. traefik.ingress.kubernetes.io/configuration-snippet: |
  10. rewrite ^/static/(.*)$ /app/static/$1 redirect;
  11. rewrite ^/image/(.*)$ /app/image/$1 redirect;
  12. spec:
  13. rules:
  14. - host:
  15. http:
  16. paths:
  17. - backend:
  18. serviceName: nginx-demo
  19. servicePort: 80
  20. path: /app(/|$)(.*)

但是还有一个问题是我们的 path 路径其实也匹配了 /app 这样的路径,可能我们更加希望我们的应用在最后添加一个 / 这样的 slash,同样我们可以通过 configuration-snippet 配置来完成,如下 Ingress 对象:

  1. apiVersion: extensions/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: nginx-ingress-demo
  5. annotations:
  6. kubernetes.io/ingress.class: "traefik"
  7. traefik.ingress.kubernetes.io/app-root: /app/
  8. traefik.ingress.kubernetes.io/rewrite-target: /$2
  9. traefik.ingress.kubernetes.io/configuration-snippet: |
  10. rewrite ^(/app)$ $1/ redirect;
  11. rewrite ^/static/(.*)$ /app/static/$1 redirect;
  12. rewrite ^/image/(.*)$ /app/image/$1 redirect;
  13. spec:
  14. rules:
  15. - host:
  16. http:
  17. paths:
  18. - backend:
  19. serviceName: nginx-demo
  20. servicePort: 80
  21. path: /app(/|$)(.*)