暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

k8s部署-44-带你深入学习ingress-nginx(终)

运维家 2022-04-24
387

 

续接上文,我们来看下如何进行访问控制吧~~~

 

4

访问控制

我们之前学了如何使用ingress-nginx来进行多节点配置,如何代理4层协议,如何配置https,那么我们还剩下一个,那就是访问控制,本文来详细实操一下。

1、session保持;
在同一段时间,长期访问同一个后端服务,不要进行轮训;那么我们首先来准备下环境吧。为了做测试,我们要实现的是,经过同一个域名,访问两个使用不同镜像的后端服务,就是我们要采用金丝雀部署的方式,来看看吧。
    [root@node1 ~]# kubectl get pod
    NAME READY STATUS RESTARTS AGE
    nginx-ds-q2pjt 1/1 Running 35 26d
    nginx-ds-zc5qt 1/1 Running 40 32d
    springboot-web-demo-5c9446ffbf-qvq69 1/1 Running 1 15h
    [root@node1 ~]#

    可以看到我们现在运行了一个pod,使用的镜像如下:
      [root@node1 ~]# kubectl get pod springboot-web-demo-5c9446ffbf-qvq69 -o yaml | grep image
      f:image: {}
      f:imagePullPolicy: {}
      - image: registry.cn-beijing.aliyuncs.com/yunweijia0909/springboot-web:v1
      imagePullPolicy: IfNotPresent
      image: registry.cn-beijing.aliyuncs.com/yunweijia0909/springboot-web:v1
      imageID: registry.cn-beijing.aliyuncs.com/yunweijia0909/springboot-web@sha256:1953bfa3859e02f7f8ab10e5b69a0505c738f2d05040be6222e63c2971e8b45d
      [root@node1 ~]#

      然后我们再次创建个同样域名的pod,使用不同的镜像来看看;
        [root@node1 ~]# cd namespace/
        [root@node1 namespace]# mkdir control
        [root@node1 namespace]# cd control/
        [root@node1 control]#
        [root@node1 control]# vim control-ceshi.yaml 
        #deploy
        apiVersion: apps/v1
        kind: Deployment
        metadata:
        name: springboot-web-demo-new
        spec:
        selector:
        matchLabels:
        app: springboot-web-demo
        replicas: 1
        template:
        metadata:
        labels:
        app: springboot-web-demo
        spec:
        containers:
        - name: springboot-web-demo
        image: registry.cn-beijing.aliyuncs.com/yunweijia0909/tomcat:jre8-openjdk
        ports:
        - containerPort: 8080
        ---
        #service
        apiVersion: v1
        kind: Service
        metadata:
        name: springboot-web-demo
        spec:
        ports:
        - port: 80
        protocol: TCP
        targetPort: 8080
        selector:
        app: springboot-web-demo
        type: ClusterIP

        ---
        #ingress
        apiVersion: extensions/v1beta1
        kind: Ingress
        metadata:
        name: springboot-web-demo
        spec:
        rules:
        - host: springboot.yunweijia.com
        http:
        paths:
        - backend:
        serviceName: springboot-web-demo
        servicePort: 80
        path:
        [root@node1 control]#
        [root@node1 control]

        可以看到我们使用了同样的域名,但是镜像不一样,当然了,我们使用的配置https,还是和上文是一样的,如下(只需要执行一个就行,因为域名是一样的):

          [root@node1 control]# cat web-demo-ingress.yaml 
          apiVersion: extensions/v1beta1
          kind: Ingress
          metadata:
          name: springboot.yunweijia.com
          spec:
          rules:
          - host: springboot.yunweijia.com
          http:
          paths:
          - backend:
                    serviceName: springboot-web-demo
          servicePort: 80
          path: /
          tls:
          - hosts:
          - springboot.yunweijia.com
          secretName: yunweijia-tls
          [root@node1 control]#

          看下访问结果哈,一直按着刷新;

          会在这两个界面中来回切换,说明我们的环境就搞定了。(不要在意我的404 ,上次镜像搞崩了,一直没修复。)
          环境搞定之后,我们就该做session保持了,操作的对象是ingress-nginx;
            [root@node1 control]# vim ingress-session.yaml 
            apiVersion: extensions/v1beta1
            kind: Ingress
            metadata:
            annotations:
            nginx.ingress.kubernetes.io/affinity: cookie
            nginx.ingress.kubernetes.io/session-cookie-hash: sha1
            nginx.ingress.kubernetes.io/session-cookie-name: route
            name: springboot-web-demo
            spec:
            rules:
            - host: springboot.yunweijia.com
            http:
            paths:
            - backend:
            serviceName: springboot-web-demo
            servicePort: 80
            path: /
            tls:
            - hosts:
            - springboot.yunweijia.com
            secretName: yunweijia-tls
            [root@node1 control]#
            然后我们再次浏览器刷新的时候,会发现他一直保持在一个界面,这个时候我们看看他的session是什么样子的;

            只要是同一个cookie就会一直保持在同一个界面中,除非你关闭浏览器再次打开,这样子你的cookie就换了,那么有可能就不是这个后台程序了。

            2、流量控制

            比如说当我们有两个服务,我们再升级的时候,升了一个,想切10%的流量到我们的新服务上,验证下有没有问题,那么我们应该如何来做呢?
              [root@node1 control]# cd ../tls/
              [root@node1 tls]kubectl create secret tls yunweijia-tls --key yunweijia.key --cert yunweijia.crt -n canary
              上面这步不太理解的,看一下前面的文章。
              PS:该项操作,需要在较新的ingress-nginx版本上才有的哈,如果版本太老了,可能不支持,可以更新一下image,替换版本为0.23.0之后方可;
                [root@node1 control]# mkdir canary
                [root@node1 control]# cd canary/
                [root@node1 canary]# vim web-canary-a.yaml 
                #deploy
                apiVersion: apps/v1
                kind: Deployment
                metadata:
                name: web-canary-a
                namespace: canary
                spec:
                strategy:
                rollingUpdate:
                maxSurge: 25%
                maxUnavailable: 25%
                type: RollingUpdate
                selector:
                matchLabels:
                app: web-canary-a
                replicas: 1
                template:
                metadata:
                labels:
                app: web-canary-a
                spec:
                containers:
                - name: web-canary-a
                image: registry.cn-beijing.aliyuncs.com/yunweijia0909/springboot-web:v1
                ports:
                - containerPort: 8080
                livenessProbe:
                tcpSocket:
                port: 8080
                initialDelaySeconds: 20
                periodSeconds: 10
                failureThreshold: 3
                successThreshold: 1
                timeoutSeconds: 5
                readinessProbe:
                httpGet:
                path: /hello?name=test
                port: 8080
                scheme: HTTP
                initialDelaySeconds: 20
                periodSeconds: 10
                failureThreshold: 1
                successThreshold: 1
                timeoutSeconds: 5
                ---
                #service
                apiVersion: v1
                kind: Service
                metadata:
                name: web-canary-a
                namespace: canary
                spec:
                ports:
                - port: 80
                protocol: TCP
                targetPort: 8080
                selector:
                app: web-canary-a
                type: ClusterIP

                [root@node1 canary]# vim web-canary-b.yaml 
                #deploy
                apiVersion: apps/v1
                kind: Deployment
                metadata:
                name: web-canary-b
                namespace: canary
                spec:
                strategy:
                rollingUpdate:
                maxSurge: 25%
                maxUnavailable: 25%
                type: RollingUpdate
                selector:
                matchLabels:
                app: web-canary-b
                replicas: 1
                template:
                metadata:
                labels:
                app: web-canary-b
                spec:
                containers:
                - name: web-canary-b
                image: registry.cn-beijing.aliyuncs.com/yunweijia0909/tomcat:jre8-openjdk
                ports:
                        - containerPort: 8080
                ---
                #service
                apiVersion: v1
                kind: Service
                metadata:
                name: web-canary-b
                namespace: canary
                spec:
                ports:
                - port: 80
                protocol: TCP
                targetPort: 8080
                selector:
                app: web-canary-b
                type: ClusterIP

                [root@node1 canary]#
                可以看到我们写了两个yaml文件,我们下来运行一下;
                  [root@node1 canary]# kubectl create ns canary
                  namespace/canary created
                  [root@node1 canary]# kubectl apply -f web-canary-a.yaml
                  deployment.apps/web-canary-a created
                  service/web-canary-a created
                  [root@node1 canary]# kubectl apply -f web-canary-b.yaml
                  deployment.apps/web-canary-b created
                  service/web-canary-b created
                  [root@node1 canary]#
                  然后我们还需要准备一个ingress的yaml文件;
                    [root@node1 canary]# vim ingress-common.yaml 
                    #ingress
                    apiVersion: extensions/v1beta1
                    kind: Ingress
                    metadata:
                    name: web-canary-a
                    namespace: canary
                    spec:
                    rules:
                    - host: canary.yunweijia.com
                    http:
                    paths:
                    - path:
                    backend:
                    serviceName: web-canary-a
                    servicePort: 80
                    tls:
                    - hosts:
                    - canary.yunweijia.com
                    secretName: yunweijia-tls
                    [root@node1 canary]#
                    [root@node1 canary]# kubectl apply -f ingress-common.yaml 
                    ingress.extensions/web-canary-a created
                    [root@node1 canary]#
                    然后我们访问验证一下试试;(需要先添加hosts文件哈,自行添加,不演示了哈)

                    接着我们需要上线canary-b;
                      [root@node1 canary]# cat ingress-weight.yaml 
                      #ingress
                      apiVersion: extensions/v1beta1
                      kind: Ingress
                      metadata:
                      name: web-canary-b
                      namespace: canary
                      annotations:
                      nginx.ingress.kubernetes.io/canary: "true"
                      nginx.ingress.kubernetes.io/canary-weight: "10"
                      spec:
                      rules:
                      - host: canary.yunweijia.com
                      http:
                      paths:
                      - path:
                      backend:
                      serviceName: web-canary-b
                      servicePort: 80
                      tls:
                      - hosts:
                      - canary.yunweijia.com
                      secretName: yunweijia-tls
                      [root@node1 canary]# kubectl apply -f ingress-weight.yaml 
                      ingress.extensions/web-canary-b created
                      [root@node1 canary]#
                      然后我们再次访问验证下,发现只有10%的流量切到了canary-b上;这就是我们实现的流量控制。这个10%可以根据自己的需要自行调节。我们可以写个脚本测试下:
                        while sleep 0.2; do curl -k https://canary.yunweijia.com/hello?name=yunweijia && echo "";done
                        等待一段时间之后,发现如下图:

                        基本控制在了十分之一的访问切换。
                        3、控制访问

                        还有一种情况是,替换完了之后并不想让其他人来访问,只想让指定的人来访问,这个时候我们如何来做呢?

                        可以通过控制cookie的方式来实现;

                          [root@node1 canary]# cat ingress-cookie.yaml 
                          #ingress
                          apiVersion: extensions/v1beta1
                          kind: Ingress
                          metadata:
                          name: web-canary-b
                          namespace: canary
                          annotations:
                          nginx.ingress.kubernetes.io/canary: "true"
                          nginx.ingress.kubernetes.io/canary-by-cookie: "web-canary"
                          spec:
                          rules:
                          - host: canary.yunweijia.com
                          http:
                          paths:
                          - path:
                          backend:
                          serviceName: web-canary-b
                          servicePort: 80
                          [root@node1 canary]#
                          我们让其生效;
                            [root@node1 canary]# kubectl apply -f ingress-cookie.yaml 
                            当我们再次访问的时候,会发现全部访问的都是canary-a了,如下图:

                            那么我们如何来canary-b的服务呢?需要指定一个cookie,当你浏览器访问的时候,添加如下:

                            然后我们再来访问的话,就变成了canary-b的服务了;

                            4、请求头控制
                            还有一种方式是通过请求头来控制访问哪个服务,我们继续来测试下;
                              [root@node1 canary]# cat ingress-header.yaml 
                              #ingress
                              apiVersion: extensions/v1beta1
                              kind: Ingress
                              metadata:
                              name: web-canary-b
                              namespace: canary
                              annotations:
                              nginx.ingress.kubernetes.io/canary: "true"
                              nginx.ingress.kubernetes.io/canary-by-header: "web-canary"
                              spec:
                              rules:
                              - host: canary.yunweijia.com
                              http:
                              paths:
                              - path:
                              backend:
                              serviceName: web-canary-b
                              servicePort: 80
                              [root@node1 canary]#
                              我们使其生效一下;
                                [root@node1 canary]# kubectl apply -f ingress-header.yaml 

                                ingress.extensions/web-canary-b created
                                [root@node1 canary]#
                                然后我们继续浏览器访问,这个时候我们依旧会一直访问canary-a的服务,我们如何访问到canary-b的服务呢,是不是需要添加请求头啊;
                                  curl -H "web-canary: always" -k https://canary.yunweijia.com/hello?name=yunweijia && echo ""


                                  5、组合控制
                                  上面我们介绍了三种方式,是可以组合到一块的哈,优先级如下:
                                    header > cookie > weight

                                    如下:
                                      #ingress
                                      apiVersion: extensions/v1beta1
                                      kind: Ingress
                                      metadata:
                                      name: web-canary-b
                                      namespace: canary
                                      annotations:
                                      nginx.ingress.kubernetes.io/canary: "true"
                                      nginx.ingress.kubernetes.io/canary-by-header: "web-canary"
                                      nginx.ingress.kubernetes.io/canary-by-cookie: "web-canary"
                                      nginx.ingress.kubernetes.io/canary-weight: "90"
                                      spec:
                                      rules:
                                      - host: canary.yunweijia.com
                                      http:
                                      paths:
                                      - path: /
                                      backend:
                                      serviceName: web-canary-b
                                      servicePort: 80

                                      至此,本文结束,下一篇咱们继续进行ingress-nginx的深入学习哈。
                                      PS:创建了一个群,感兴趣的老板们加我下面的微信号,拉你入群,一起讨论技术哈,共同学习进步。 
                                      长按以识别二维码关注运维家~
                                      微信号:yunweijia0909


                                      往期推荐

                                      如何将不同linux服务器的目录内容进行双向同步

                                      linux 虚拟化

                                      linux下普通用户如何免密执行sudo命令呢


                                      文章转载自运维家,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                      评论