使用 OpenShift 验证参考设计中的路由将服务迁移到 Citrix ADC

OpenShift 集群中的静态路由和自动路由

静态路由(默认)-通过静态路由将 OpenShift 主机子网映射到外部 ADC

静态路由在使用 HAProxy 的传统 OpenShift 部署中很常见。将服务从一个服务代理迁移到另一个服务代理时,静态路由可以与 Citrix 节点控制器 (CNC)、Citrix Ingress Controller (CIC) 和 CPX 并行使用,而不会中断正常运行的集群中已部署的命名空间。

Citrix ADC 的静态路由配置示例:

    oc get hostsubnet (Openshift Cluster) snippet
        oc311-master.example.com 10.x.x.x 10.128.0.0/23
        oc311-node1.example.com 10.x.x.x 10.130.0.0/23
        oc311-node2.example.com 10.x.x.x 10.129.0.0/23

    show route (external Citrix VPX) snippet
        10.128.0.0 255.255.254.0 10.x.x.x STATIC
        10.129.0.0 255.255.254.0 10.x.x.x STATIC
        10.130.0.0 255.255.254.0 10.x.x.x STATIC
<!--NeedCopy-->

自动路由-使用 CNC(Citrix 节点控制器)自动执行到已定义路由分片的外部路由

您可以通过两种方式将 Citrix ADC 与 OpenShift 集成,两种方式都支持 OpenShift 路由器分片。

路线类型

  • 不安全-连接到 CIC 路由器的外部负载均衡器,HTTP 流量未加密。
  • secured-edge - 外部负载平衡器到终止 TLS 的 CIC 路由器。
  • 安全直通-外部负载均衡器到终止 TLS 的目标
  • 安全重新加密-外部负载平衡器到终止 TLS 的 CIC 路由器。使用 TLS 加密到目的地的 CIC 路由器。

Citrix Ingress Controller 部署解决方案中详细了解不同路由类型。

部署具有 OpenShift 路由器分片支持的 Citrix Ingress Controller

Citrix Ingress Controller (CIC) 充当路由器,并将流量重定向到各种容器,以便在各种可用容器之间分配传入流量。

此迁移过程也可以是集群升级过程的一部分,从传统的 OpenShift 拓扑到使用 Citrix CNC、CIC 和 CPX 组件进行集群迁移和升级程序的自动部署。

这个解决方案可以通过两种方法来实现:

  • CIC 路由器插件 (Pod)
  • OpenShift 里面的 CPX 路由器 (Sidecar)

下面将介绍这两种方法以及迁移示例。

OpenShift 路由器分片 允许在多个 OpenShift 路由器之间分发一组路由。默认情况下,OpenShift 路由器会从所有命名空间中选择所有路由。在路由器分片中,标签会添加到路由或命名空间,将标签选择器添加到路由器以过滤路由。每个路由器分片仅选择具有与其标签选择参数匹配的特定标签的路由。

要在 OpenShift 上为 Citrix ADC 部署配置路由器分片,每个分片都需要一个 Citrix Ingress Controller 实例。根据分片所需的条件,Citrix Ingress Controller 实例通过路由或命名空间标签或两者作为环境变量进行部署。当 Citrix Ingress Controller 处理路由时,它会将路由的标签或路由的命名空间标签与其上配置的选择条件进行比较。如果路由满足条件,则将相应的配置应用于 Citrix ADC,否则不会应用配置。

在路由器分片中,从整个路由池中选择路由子集是基于选择表达式的。选择表达式是多个值和操作的组合。在此 Citrix 博客中详细了解表达式、值和操作。

Bookinfo 部署

Bookinfo 应用程序的架构如下图所示。CIC 在第一层中作为 OpenShift 路由器插件进行部署,将 Citrix ADC VPX 配置为将南北流量路由到产品页面。在第二层中,Citrix ADC CPX 部署为 OpenShift 路由器,在详细信息和产品页面微服务之间路由东西向流量,而产品页面、评论和评级微服务之间的东西向流量则通过默认的 HAProxy 路由器路由。

部署为服务网格精简版架构的 Bookinfo 应用程序的路径分片图

Citrix 组件

  • VPX-向 DNS 提供群集服务的入口 ADC。
  • CIC-通过 CNC 路由向外部 Citrix ADC 提供 ROUTE_LABELS 和 NAMESPACE_LABELS。
  • CPX-在 OpenShift 集群中提供 OpenShift 路由。

部署步骤

  1. 为部署创建命名空间。 oc create ns sml
  2. 将 Bookinfo 应用程序部署到命名空间中。 oc apply -f bookinfo.yaml

    ##################################################################################################
    # Details service
    ##################################################################################################
    apiVersion: v1
    kind: Service
    metadata:
      name: details
      labels:
        app: details
        service: details
    spec:
      ports:
      - port: 9080
        name: http
      selector:
        app: details
    ---
    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: details-v1
      labels:
        app: details
        version: v1
    spec:
      replicas: 1
      template:
        metadata:
          annotations:
            sidecar.istio.io/inject: "false"
          labels:
            app: details
            version: v1
        spec:
          containers:
    "bookinfo.yaml" 224L, 5120C
    
    <!--NeedCopy-->
    
  3. 部署映射到我们的产品页面服务的路由文件。指定 frontend-ip (这是第 1 层 ADC 上的内容交换 vip) oc apply -f routes-productpage.yaml

    apiVersion: v1
    kind: Route
    metadata:
       name: productpage-route
       namespace: sml
       annotations:
        ingress.citrix.com/frontend-ip: "X.X.X.X"
       labels:
        name: productpage
    spec:
       host: bookinfo.com
       path: /
       port:
         targetPort: 80
       to:
         kind: Service
         name: productpage-service
    <!--NeedCopy-->
    
  4. 为 sml 命名空间部署 RBAC 文件,该文件授予 CIC 运行所需的权限。RBAC 文件已存在命名空间。 oc apply -f rbac.yaml

     kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1beta1
    metadata:
      name: cpx
    rules:
      - apiGroups: [""]
        resources: ["endpoints", "ingresses", "services", "pods", "secrets", "nodes", "routes", "namespaces","tokenreviews","subjectaccessreview"]
        verbs: ["get", "list", "watch"]
      # services/status is needed to update the loadbalancer IP in service status for integrating
      # service of type LoadBalancer with external-dns
      - apiGroups: [""]
        resources: ["services/status"]
        verbs: ["patch"]
      - apiGroups: ["extensions"]
        resources: ["ingresses", "ingresses/status"]
        verbs: ["get", "list", "watch"]
      - apiGroups: ["apiextensions.k8s.io"]
        resources: ["customresourcedefinitions"]
        verbs: ["get", "list", "watch"]
      - apiGroups: ["apps"]
        resources: ["deployments"]
        verbs: ["get", "list", "watch"]
      - apiGroups: ["citrix.com"]
        resources: ["rewritepolicies", "canarycrds", "authpolicies", "ratelimits"]
        verbs: ["get", "list", "watch"]
      - apiGroups: ["citrix.com"]
        resources: ["vips"]
        verbs: ["get", "list", "watch", "create", "delete"]
      - apiGroups: ["route.openshift.io"]
        resources: ["routes"]
        verbs: ["get", "list", "watch"]
    
    ---
    kind: ClusterRoleBinding
    apiVersion: rbac.authorization.k8s.io/v1beta1
    metadata:
      name: cpx
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cpx
    subjects:
    - kind: ServiceAccount
      name: cpx
      namespace: sml
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
    "rbac.yaml" 51L, 1513C
     <!--NeedCopy-->
    
  5. 部署您的 CIC 以将路由配置推送到您的 VPX。将参数路由标签与 route-productpage.yaml 中指定的标签匹配。有关 ROUTE_LABELS 语法的更多信息,请参阅此 博客oc apply -f cic-productpage-v2.yaml

    apiVersion: v1
    kind: Pod
    metadata:
      name: cic
      labels:
        app: cic
    spec:
      serviceAccount: cpx
      containers:
      - name: cic
        image: "quay.io/citrix/citrix-k8s-ingress-controller:1.7.6"
        securityContext:
           privileged: true
        env:
        - name: "EULA"
          value: "yes"
        # Set NetScaler NSIP/SNIP, SNIP in case of HA (mgmt has to be enabled)
        - name: "NS_IP"
          value: "X.X.X.X"
        # Set NetScaler VIP that receives the traffic
    #    - name: "NS_VIP"
    #      value: "X.X.X.X"
        - name: "NS_USER"
          value: "nsroot"
        - name: "NS_PASSWORD"
          value: "nsroot"
        - name: "NS_APPS_NAME_PREFIX"
          value: "BOOK"
        - name: "ROUTE_LABELS"
          value: "name in (productpage)"
    #    - name: "NAMESPACE_LABELS"
    #      value: "app=hellogalaxy"
        # Set username for Nitro
    #    - name: "NS_USER"
    #      valueFrom:
    #       secretKeyRef:
    #        name: nslogin
    #        key: nsroot
    #    # Set user password for Nitro
    #    - name: "NS_PASSWORD"
    #      valueFrom:
    #       secretKeyRef:
    #        name: nslogin
    #        key: nsroot
        args:
    #    - --default-ssl-certificate
    #      default/default-cert
        imagePullPolicy: Always
    ~
    "cic-productpage-v2.yaml" 48L, 1165C
    <!--NeedCopy-->
    
  6. 现在,我们必须创建一个无头服务,使用集群中的 DNS pod 将寻找详细信息的用户指向我们的 CPX。 oc apply -f detailsheadless.yaml

    ##################################################################################################
    # Details service
    ##################################################################################################
    apiVersion: v1
    kind: Service
    metadata:
      name: details
    spec:
      ports:
      - port: 9080
        name: http
      selector:
        app: cpx
    <!--NeedCopy-->
    
  7. 部署新服务以公开 details 容器。 oc apply -f detailsservice.yaml

    ##################################################################################################
    # Details service
    ##################################################################################################
    apiVersion: v1
    kind: Service
    metadata:
      name: details-service
      labels:
        app: details-service
        service: details-service
    spec:
      clusterIP: None
      ports:
      - port: 9080
        name: http
      selector:
        app: details
    <!--NeedCopy-->
    
  8. 在我们创建的 details 服务前面部署一个新的路径定义。注意标签是“名称:详情”。 oc apply -f detailsroutes.yaml

    apiVersion: v1
    kind: Route
    metadata:
       name: details-route
       namespace: sml
       annotations:
        ingress.citrix.com/insecure-port: "9080"
       labels:
        name: details
    spec:
       host: details
       path: /
       port:
          targetPort: 9080
       to:
         kind: Service
         name: details-service
    <!--NeedCopy-->
    
  9. 为 E/W 流量部署 CPX。CIC 作为边车部署,配置了 ROUTE_LABEL 参数以匹配 detailsroutes.yaml 中的标签。 oc apply -f cpx.yaml

    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: cpx
      labels:
        app: cpx
        service: cpx
    spec:
      replicas: 1
      template:
        metadata:
          name: cpx
          labels:
            app: cpx
            service: cpx
          annotations:
            NETSCALER_AS_APP: "True"
        spec:
          serviceAccountName: cpx
          containers:
            - name: cpx
              image: "quay.io/citrix/citrix-k8s-cpx-ingress:13.0-36.28"
              securityContext:
                 privileged: true
              env:
              - name: "EULA"
                value: "yes"
              - name: "KUBERNETES_TASK_ID"
                value: ""
              - name: "MGMT_HTTP_PORT"
                value: "9081"
              ports:
              - name: http
                containerPort: 9080
              - name: https
                containerPort: 443
              - name: nitro-http
                containerPort: 9081
              - name: nitro-https
                containerPort: 9443
    # readiness probe?
              imagePullPolicy: Always
            # Add cic as a sidecar
            - name: cic
              image: "quay.io/citrix/citrix-k8s-ingress-controller:1.7.6"
              env:
              - name: "EULA"
                value: "yes"
              - name: "NS_IP"
    "cpx.yaml" 75L, 1939C
    <!--NeedCopy-->
    

微服务环境中的持续交付选择

持续集成 (CI) 是一种开发实践,要求开发人员每天多次将代码集成到共享存储库中。

持续交付(CD)是持续集成的自然延伸:在这种方法中,团队可以确保对系统的每一项更改都是可发布的,并且我们只需按一下按钮即可发布任何版本。

不同的 CD 选择及其优缺点是:

  • 重新创建 -终止版本 1 (V1),然后推出版本 2 (V2)。
    • 优点
      • 易于设置。
      • 应用程序状态已完全更新。
    • 缺点
      • 对用户的影响很大。预计停机时间取决于关机和启动持续时间。
  • 渐进/滚动更新 -V2 正在缓慢推出并取代 V1。
    • 优点
      • 易于设置。
      • 版本缓慢地跨实例发布。
      • 对于可以处理数据重新平衡的有状态应用程序来说非常方便。
    • 缺点
      • 推出/回滚可能需要一些时间。
      • 支持多个 API 很难。
      • 交通几乎没有控制。
  • Blue Gre en-V2 与 V1 一起发布,然后流量切换到 V2。
    • 优点
      • 即时部署/回滚。
      • 避免版本问题,因为整个应用程序会立即更改。
    • 缺点
      • 成本高昂,因为它需要双倍的资源。
      • 在发布到生产环境之前,应对整个平台进行适当的测试。
      • 处理多个有状态应用程序可能很困难。
  • Canary -V2 向部分用户发布,然后全面推出。
    • 优点
      • 为部分用户发布的版本。
      • 便于错误率和性能监视。
      • 快速回滚。
    • 缺点
      • 推出缓慢。
      • 处理多个有状态应用程序可能很困难。
  • A/B 测试 -V2 在特定条件下发布给一部分用户。
    • 优点
      • 多个版本并行运行。
      • 完全控制流量分布。
    • 缺点
      • 需要智能负载均衡器。
      • 很难对给定会话的错误进行故障排除,因此必须进行分布式跟踪。
  • Shadow -V2 与 V11 一起接收真实流量,不会影响响应。
    • 优点
      • 使用生产流量对应用程序进行性能测试。
      • 对用户没有影响。
      • 在应用程序的稳定性和性能满足要求之前不进行部署。
    • 缺点
      • 成本高昂,因为它需要双倍的资源。
      • 不是真正的用户测试,可能会产生误导。
      • 设置复杂。
      • 某些情况下需要模拟服务。

参考资料

Citrix GitHub:“OpenShift 路线和入口”

Citrix Developer 文档:“部署解决方案”

Citrix 博客:“使用 Citrix ADC 启用 OpenShift 路由器分片支持”

OpenShift 路线文档: