Ingress是什么?

An API object that manages external access to the services in a cluster, typically HTTP.

Ref: https://kubernetes.io/docs/concepts/services-networking/ingress/

HTTP方式暴露K8S服务到集群外面的规范方式就是通过Ingress

和NodePort方式和LoadBalancer方式的不同?

An Ingress does not expose arbitrary ports or protocols. Exposing services other than HTTP and HTTPS to the internet typically uses a service of type Service.Type=NodePort or Service.Type=LoadBalancer.

除了提供HTTP,HTTPS的服务之外, 还有很多以TCP方式提供服务的如Redis等数据库是不能用Ingress方式暴露服务的,也就是说Ingress只适合Web应用或提供HTTP Restful API的应用

Ingress

首先需要创建一个Ingress Controller,它处于一个独立的命名空间,用来监听所有的namespace的Ingress对象,设置URL重写规则需要在Ingress对象里。

安装nginx插件

受DNS污染,你可能下载不了这个yaml,需要重新配置/etc/hosts.或者使用我的Copy:
https://gitee.com/oneslideicywater/docker-utils/raw/master/conf/nginx/deploy.yaml

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

查看ingress安装是否成功:

kubectl get pods -n ingress-nginx \
  -l app.kubernetes.io/name=ingress-nginx --watch

创建Ingress对象

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  namespace: default
  annotations:
     nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
     - http:
         paths:
           - backend:
               serviceName: "tomcatapp"
               servicePort: 8080
             path: /tomcatapp(/|$)(.*)

查看ingress:

$ kubectl get ingress test-ingress
NAME           HOSTS   ADDRESS   PORTS   AGE
test-ingress   *                 80      3m35s

查看ingress的规则:

[root@k8s-master pv]# kubectl describe ingress -A
Name:             test-ingress
Namespace:        default
Address:          192.168.3.254
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
  Host        Path  Backends
  ----        ----  --------
  *           
              /tomcatapp(/|$)(.*)   tomcatapp:8080 (10.244.0.9:8080)
Annotations:  nginx.ingress.kubernetes.io/rewrite-target: /$2
Events:
  Type    Reason  Age                   From                      Message
  ----    ------  ----                  ----                      -------
  Normal  UPDATE  18s (x12 over 3h40m)  nginx-ingress-controller  Ingress default/test-ingress
ingress的重写规则:

需要注意!!!nginx-ingress-controller会默认加一个Context Path,比如你的backend写的是tomcatapp,那么访问重写为:/hello--->/tomcatapp/hello, 为了去掉这个前缀,你需要捕获它。

其中/tomcatapp(/|$)(.*)(/|$)匹配/$(结束),.*.代表单个字符,*代表任意次,.*代表单个字符匹配任意次。

$n代表匹配子模式(()里面的表达式)的索引,$1是第一个小括号里的内容,$2是第二个小括号里面的内容,依此类推。

这里/tomcatapp/hello中的$1/$2hello,因此/tomcatapp/hello->/$2->/hello

具体细节参考:
https://kubernetes.github.io/ingress-nginx/examples/rewrite/

部署Tomcat

nginx通过Service的名字来路由:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-tomcat
spec:
  selector:
   matchLabels:  
        app: my-tomcat
  replicas: 1
  template:
    metadata:
      labels:
        app: my-tomcat
    spec:
      containers:
      - name: my-tomcat
        image: tomcat
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: test # 这里对应Ingress.spec.backend.ServiceName
spec:
   ports:
     - name: test  
       port: 80
       targetPort: 80
   selector:
     app: my-tomcat

查看Tomcat界面

nginx通过nodePort方式暴露服务,用户可以通过nginx来访问tomcat:

[root@k8s-master pv]# kubectl get svc -A
NAMESPACE              NAME                                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx          ingress-nginx-controller             NodePort    10.96.195.4      <none>        80:31761/TCP,443:30123/TCP   159m
ingress-nginx          ingress-nginx-controller-admission   ClusterIP   10.110.121.126   <none>        443/TCP                      159m

可以看到ingress-nginx-controller暴露31761端口,因此可以通过nodeip:31761/testpath来访问tomcat.

Ingress方式暴露vue前端没有css,js等静态文件问题

ingress文件大概是这样:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app
  namespace: app
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
    - host: "app.k8s"
      http:
        paths:
        - pathType: Prefix
          path: "/app(/|$)(.*)"
          backend:
            service:
              name: app-svc
              port:
                number: 80

但是浏览器访问${k8s_master_ip}:${ingress_port}/app却发现js,css都访问不到。

核心的问题在哪里? 就是在前面加了一个前缀/app后,其实js的路径在/app/static/xxx.js,而不是/static/js.

这和vue的打包方式的问题,vue打包方式改成相对路径,即所有静态资源路径前面有.
比如:<script src=js/xx.js> => <script src=./js/xx.js>

每个版本vue都不一样。我的是改了vue.config.js:

module.exports = {
  publicPath: "././"
  ...
}  

然后访问:${k8s_master_ip}:${ingress_port}/app/

你会发现后面这个/很突兀,没错一定要加!一定要加!一定要加!不然浏览器又会去掉/app这个路径。

Reference List

  1. https://kubernetes.io/docs/concepts/services-networking/ingress/
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐