kubernetes云原生纪元:领悟 Ingress Nginx(下)

kubernetes云原生纪元:领悟 Ingress Nginx(下)

续领悟Ingress Nginx(中)

文章目录


解决https 证书问题

ingress-nginx 配置证书

  1. 生产证书

    首先生成一个证书gen-secret.sh脚步生成证书,输出一个key 一个密钥

注意这里我生成完后直接在kubernetes 创建了secret

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

gen-secret.sh

#!/bin/bash

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout mooc.key -out mooc.crt -subj "/CN=*.mooc.com/O=*.mooc.com"

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

生成证书

[root@master-001 ~]# sh gen-secret.sh
Generating a 2048 bit RSA private key
.........+++
..........................+++
writing new private key to 'mooc.key'
-----
secret/mooc-tls created

我们查看 ,tls.crt是kubernetes 的规范

[root@master-001 ~]# kubectl get secret mooc-tls -o yaml
apiVersion: v1
data:
  tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lKQUlCTGUrTEVEcEJSTUEwR0NTcUdTSWIzRFFFQkN3VUFNQ...
  tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2QUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktZd2dnU2lBZ0VBQW9JQkF.....
kind: Secret
metadata:
  creationTimestamp: "2020-01-28T13:48:54Z"
  name: mooc-tls
  namespace: dev
  resourceVersion: "334008"
  selfLink: /api/v1/namespaces/dev/secrets/mooc-tls
  uid: d12f095c-a79b-4765-a06f-62d32d731eeb
type: kubernetes.io/tls
  1. 证书挂载到ingress-controller

修改nginx-ingress-controller,在配置中增加==–default-ssl-certifcate=default/mooc-tls==,意思是指定default命名空间下的mooc-tls

[root@master-001 ~]# vi nginx-ingress-controller.yaml
apiVersion: apps/v1
kind: DaemonSet 
metadata:
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
  name: nginx-ingress-controller
  namespace: ingress-nginx
spec:
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx
      app.kubernetes.io/part-of: ingress-nginx
  updateStrategy:
    rollingUpdate:
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      annotations:
        prometheus.io/port: "10254"
        prometheus.io/scrape: "true"
      creationTimestamp: null
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
    spec:
      containers:
      - 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
        - --default-ssl-certifcate=default/mooc-tls #看这里
        # 增加数据卷挂载,
        volumeMounts:
          - mountPath: /etc/nginx/template
            name: nginx-template
            readOnly: true
            # end
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.namespace
        image: siriuszg/nginx-ingress-controller:latest
        imagePullPolicy: Always
        lifecycle:
          preStop:
            exec:
              command:
              - /wait-shutdown
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /healthz
            port: 10254
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 10
        name: nginx-ingress-controller
        ports:
        - containerPort: 80
          hostPort: 80
          name: http
          protocol: TCP
        - containerPort: 443
          hostPort: 443
          name: https
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /healthz
            port: 10254
            scheme: HTTP
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 10
        resources: {}
        securityContext:
          allowPrivilegeEscalation: true
          capabilities:
            add:
            - NET_BIND_SERVICE
            drop:
            - ALL
          runAsUser: 33
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      hostNetwork: true 
      nodeSelector:
        kubernetes.io/os: linux
        app: ingress 
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      serviceAccount: nginx-ingress-serviceaccount
      serviceAccountName: nginx-ingress-serviceaccount
      terminationGracePeriodSeconds: 300
       # 通过configmap指定我们上面创建的nginx.tmpl
      volumes:
        - name: nginx-template-volume
          configMap:
            name: nginx-template
            items:
            - key: nginx.tmpl
              path: nginx.tmpl

更新一下

[root@master-001 ~]# kubectl apply -f nginx-ingress-controller.yaml
daemonset.apps/nginx-ingress-controller configured

3 . 指定域名使用创建的tls

然后具体给哪个服务指定一下域名使用哪个tls ,我们给你web-demo 服务指定一下

测试的机器上必须有web-demo这个服务

web-ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: web-demo
  namespace: dev
spec:
  rules:
  - host: web-dev.mooc.com
    http:
      paths:
      - backend:
          serviceName: web-demo
          servicePort: 80
        path: /
  tls:
    - hosts:
      - web-dev.mooc.com
      secretName: mooc-tls #指定我们刚创建的tls

创建一下

[root@master-001 ~]# kubectl apply -f web-ingress.yaml
ingress.extensions/web-demo configured

否则没有他就不会创建一个web-dev.mooc.comhttps的服务

  1. 访问测试

直接在浏览器访问https://web-dev.mooc.com 就可以看到他返回了,表示我们这里配置证书成功

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UyEMmyjS-1580869872957)(/Users/zck/Library/Application Support/typora-user-images/image-20200128225447406.png)]

解决问题访问控制

ingress-nginx session保持

web服务需要会话保持的,需要访问同一个后端

环境:

有一个service ,有两个后端一个是web版本一个spring-boot版本,service 轮训访问这个两个后端

配置信息在领悟 Ingress Nginx(上)环境部分有,这里不展示

Web 版本访问

kubernetes云原生纪元:领悟 Ingress Nginx(下)

spring-boot版本访问

kubernetes云原生纪元:领悟 Ingress Nginx(下)

我们直接修改ingress的配置增加session保持就可以实现只是访问一个后端

ingress-session.yaml

#ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/affinity: cookie # cookine保存
    nginx.ingress.kubernetes.io/session-cookie-hash: sha1 # session 算法
    nginx.ingress.kubernetes.io/session-cookie-name: route # 随便起的一个名字 ,cookie 名字
  name: spring-boot-demo
 # namespace: dev
spec:
  rules:
  - host: spring-boot.demo.com
    http:
      paths:
      - path: /
        backend:
          serviceName: spring-boot-demo
          servicePort: 80

创建下

[root@master-001 ~]# kubectl apply -f ingress-session.yaml
ingress.extensions/spring-boot-demo created

这样他就一直保持一个后端访问了

kubernetes云原生纪元:领悟 Ingress Nginx(下)

ingress+ 金丝雀模式 流量控制

小流量 刚上线不知道服务有没有问题先把流量切到刚上线的服务切10%,没有问题开20%,50%,100%。

流量控制基于金丝雀模式

ingress-nginx 从 0.21.0 开始支持金丝雀(canary)模式

金丝雀annotations使Ingress规范可以作为路由到请求的替代服务

 annotations:
   nginx.ingress.kubernetes.io/canary: "true"
   nginx.ingress.kubernetes.io/canary-by-header: "version"
   nginx.ingress.kubernetes.io/canary-by-header-value: "canary"
   nginx.ingress.kubernetes.io/canary-by-cookie: "canary-cookie"
   nginx.ingress.kubernetes.io/canary-weight: <weight>

nginx.ingress.kubernetes.io/canary-by-header用于通知Ingress将请求路由到Canary Ingress中指定的服务的标头。当请求标头设置always时,它将被路由到金丝雀。当标头设置never为时,它将永远不会被路由到金丝雀。对于任何其他值,将忽略标头,并通过优先级将请求与其他金丝雀规则进行比较。nginx.ingress.kubernetes.io/canary-by-header-value: 要匹配的标头值,用于通知Ingress将请求路由到Canary Ingress中指定的服务。当请求标头设置为此值时,它将被路由到金丝雀。对于任何其他标头值,标头将被忽略,并且请求与其他金丝雀规则的优先级进行比较。此注释必须与nginx.ingress.kubernetes.io/canary-by-header一起使用。nginx.ingress.kubernetes.io/canary-by-header允许自定义标头值而不是使用硬编码值的扩展。如果nginx.ingress.kubernetes.io/canary-by-header未定义注释,则没有任何效果。

nginx.ingress.kubernetes.io/canary-by-cookie: 用于通知Ingress将请求路由到Canary Ingress中指定的服务的cookie。当cookie值设置always时,它将被路由到金丝雀。当cookie被设置never时,它将永远不会被路由到金丝雀。对于任何其他值,将忽略cookie并将请求与其他金丝雀规则进行优先比较。

nginx.ingress.kubernetes.io/canary-weight: 该路由到金丝雀Ingress中指定的服务的随机请求的整数(0 – 100)百分比。权重为0意味着该金丝雀规则不会向Canary入口中的服务发送任何请求。权重为100意味着所有请求都将被发送到Ingress中指定的替代服务。

优先顺序如下: canary-by-header -> canary-by-cookie -> canary-weight
已知限制目前,每个Ingress规则最多可以应用一个金丝雀入口。

场景:我现在有两个服务分别是web-canary-aweb-canary-b同时都有service,然后有一个ingress名字是web-canary-a,他只访问 web-canary-a的服务,这时候我们要上线web-canary-b

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: hub.zhang.com/kubernetes/spring-boot-demo:v1 #版本不一样
        ports:
        - containerPort: 8080
        livenessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 20
          periodSeconds: 10
          failureThreshold: 3
          successThreshold: 1
          timeoutSeconds: 5
        readinessProbe:
          httpGet:
            path: /
            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

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: hub.zhang.com/kubernetes/spring-boot-demo:v2 #版本不一样
        ports:
        - containerPort: 8080
        livenessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 20
          periodSeconds: 10
          failureThreshold: 3
          successThreshold: 1
          timeoutSeconds: 5
        readinessProbe:
          httpGet:
            path: /
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 20
          periodSeconds: 10
          failureThreshold: 1
          successThreshold: 1
          timeoutSeconds: 5
---
#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


ingress-common.yaml

#ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
 name: web-canary-a  
 namespace: canary
spec:
 rules:
 - host: canary.demo.com
   http:
     paths:
     - path: /
       backend:
         serviceName: web-canary-a #只是指定web-canary-a的service
         servicePort: 80

全部创建一下:

[root@master-001 ~]# kubectl apply -f web-canary-a.yaml
deployment.apps/web-canary-a created
service/web-canary-a created
[root@master-001 ~]# kubectl apply -f web-canary-b.yaml
deployment.apps/web-canary-b created
service/web-canary-b created
[root@master-001 ~]# kubectl apply -f ingress-common.yaml
ingress.extensions/web-canary-a created

这个时候我们只能访问web-canary-a的服务

kubernetes云原生纪元:领悟 Ingress Nginx(下)

ingress + 金丝雀模式 流量定向访问

还是跟上面的流量控制一样都依赖金丝雀模式实现

这个时候我们要上线web-canary-b而且流量只是给web-canary-b 10%

主要使用 金丝雀模式的 nginx.ingress.kubernetes.io/canary-weight:

kubernetes云原生纪元:领悟 Ingress Nginx(下)

同一个域名服务canary.demo.com

nginx.ingress.kubernetes.io/canary: “true” # 开启金丝雀
nginx.ingress.kubernetes.io/canary-weight: “10” # 流量权重分配为10

nginx.ingress.kubernetes.io/canary-weight: 该路由到金丝雀Ingress中指定的服务的随机请求的整数(0 – 100)百分比。权重为0意味着该金丝雀规则不会向Canary入口中的服务发送任何请求。权重为100意味着所有请求都将被发送到Ingress中指定的替代服务。

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" # 流量权重分配为10
spec:
  rules:
  - host: canary.demo.com
    http:
      paths:
      - path: /
        backend:
          serviceName: web-canary-b
          servicePort: 80

创建下

[root@master-001 ~]# kubectl apply -f ingress-weight.yaml
ingress.extensions/web-canary-b created

我们偶尔可以看到web-canary-b,大部分都web-canary-b

kubernetes云原生纪元:领悟 Ingress Nginx(下)

kubernetes云原生纪元:领悟 Ingress Nginx(下)

没问题就把 nginx.ingress.kubernetes.io/canary-weight: 改成90这样全部百分90都是web-canary-b

#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: "90" # 流量权重分配为90
spec:
  rules:
  - host: canary.demo.com
    http:
      paths:
      - path: /
        backend:
          serviceName: web-canary-b
          servicePort: 80


[root@master-001 ~]# kubectl apply -f ingress-weight.yaml
ingress.extensions/web-canary-b configured

还有一种场景就是我不让用户去访问我们要上线的服务,让测试人员去访问,测试完成我在走上线流程。

nginx.ingress.kubernetes.io/canary-by-cookie: 用于通知Ingress将请求路由到Canary Ingress中指定的服务的cookie。当cookie值设置always时,它将被路由到金丝雀。当cookie被设置never时,它将永远不会被路由到金丝雀。对于任何其他值,将忽略cookie并将请求与其他金丝雀规则进行优先比较

主要使用 金丝雀模式的 nginx.ingress.kubernetes.io/canary-by-cookie:

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" # 设置金丝雀cookie 名字
spec:
  rules:
  - host: canary.demo.com
    http:
      paths:
      - path: /
        backend:
          serviceName: web-canary-b
          servicePort: 80

创建下

[root@master-001 ~]# kubectl apply -f ingress-cookie.yaml
ingress.extensions/web-canary-b configured

我们访问下发现全是web-canary-a版本

kubernetes云原生纪元:领悟 Ingress Nginx(下)

这个时候怎么访问web-canary-b 呢需要添加一个cookie名字上面我们在配置中写的是web-canary,cookie值是always

注意:发现只有火狐浏览器可以添加cookie

kubernetes云原生纪元:领悟 Ingress Nginx(下)

kubernetes云原生纪元:领悟 Ingress Nginx(下)

这里可以实现一个流量的定向访问了,这种手动加cookie只是测试,

但是我们真实中举个例子:

我们新上线的服务只是让女性访问,看下女性的反馈,男性还是访问之前的,这样我们就可以根据登录用户性别做出判断,在程序设置cookie 值=always了。

除了 nginx.ingress.kubernetes.io/canary-by-cookie: 进行定向流量之外还可以通过header实现:nginx.ingress.kubernetes.io/canary-by-header:

主要使用 金丝雀模式的 nginx.ingress.kubernetes.io/canary-by-header:

还是通过web-canary-b测试

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.demo.com
    http:
      paths:
      - path: /
        backend:
          serviceName: web-canary-b
          servicePort: 80

创建下

[root@master-001 ~]# kubectl apply -f ingress-header.yaml
ingress.extensions/web-canary-b configured

这时候浏览器已经只是访问web-canary-a了,

kubernetes云原生纪元:领悟 Ingress Nginx(下)

我们做测试可以用curl方便测试,我们看大加上header web-canary 值等于always 就访问到web-canary-a

➜  ~ curl -H 'web-canary: always' http://canary.demo.com/
上一篇:hibernate(三) 一对多映射关系


下一篇:linux使用crontab -e 遇到No space left on device