【问题标题】:k8s ramped deployment -- css from same podk8s 加速部署——来自同一个 pod 的 css
【发布时间】:2019-10-19 15:43:34
【问题描述】:

我有一个webapp 在 Kubernetes 上的 2 个 pod 上运行。

我使用新的映像版本编辑我的部署,从 webapp:v1webapp:v2

我在推出期间发现了一个问题...

podA is v2
podB is still v1

html is served from podA
with a <link> to styles.css

styles.css is served from podB
with v1 styles

=> html v2 + css v1 = ????

如何保证所有后续请求都来自同一个 pod,或者与 html 提供的版本相同的 pod?

【问题讨论】:

标签: kubernetes continuous-deployment


【解决方案1】:

如何保证所有后续请求都来自同一个 pod,或者与 html 提供的版本相同的 pod?

即使你这样做了,你仍然会遇到问题。特别是如果您的应用程序是单页应用程序。考虑一下:

  • 用户进入你的网站,得到index.html v1
  • 您发布了 webapp:v2。几分钟后,所有 pod 都在运行 v2。
  • 用户仍然打开了 webapp,index.html v1
  • 用户在应用程序中导航。这需要加载styles.css。用户获得styles.css v2。砰,你在混合版本,失败了。

我在生产中遇到了这个问题,解决起来很痛苦。根据我的经验,最好的解决方案是:

  • 使用版本后缀(例如styles.css -> styles-v1.css,或文件内容的哈希styles-39cf1a0b.css)标记所有资源(css、js、imgs 等)。 webpack、gulp 等许多工具都可以自动执行此操作。
  • index.html 没有被标记,但它确实引用了具有正确标记的其他资源。
  • 部署时,不要删除旧版本的资源,只需将它们与最新的资源合并即可。确保拥有旧 index.html 的客户仍然可以成功获取它们。
  • 在几个版本后删除旧资源,或者更好,在一段时间后(可能是 1 周?)。

有了这个,上面的场景现在可以正常工作了!

  • 用户进入你的网站,得到index.html v1
  • 您发布了 webapp:v2。这将替换 index.html,但保留所有 js/css,添加具有新版本后缀的新内容。
  • 用户仍然打开了 webapp,index.html v1
  • 用户在应用程序中导航。这里需要加载styles-v1.css,加载成功并匹配index.html版本。没有版本混合 = 好!
  • 下次用户重新加载页面时,他们会得到index.html v2,它指向新的styles-v2.css等。仍然没有版本混合!

用 kubernetes 做这件事有点棘手,你需要让你的镜像构建过程从几个旧镜像中获取文件并将它们包含在新镜像中,这有点奇怪。

另一种解决方案是停止从 pod 提供 html/css/js,而是从 blob 存储中提供。 (亚马逊 S3、谷歌云存储等)。这样,部署只是复制所有文件,这些文件与旧文件合并,为您提供所需的行为。

【讨论】:

    【解决方案2】:

    这看起来不是滚动升级的材料。这不能由 Kubernetes 自己解决(假设它是最纯粹的最小形式)。

    也就是说,例如,如果您使用 nginx 入口控制器,您可以查看 https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md#session-affinity 以使用户尽可能地保持在同一上游。

    【讨论】:

      【解决方案3】:

      这是关于部署更新策略的好消息article,您可以考虑使用蓝/绿部署,而不是斜坡。

      Ramped 是缓慢推出,在使用新映像修补部署后会创建新的副本集,直到达到所需的副本数,它会慢慢终止旧的副本 pod,那么你可以忍受这个是正常的版本控制问题同时滚动更新。

      蓝/绿,与斜坡策略不同,新版本的服务,一旦确认新版本是健康的,就会改变。 Here 您可以找到此策略的示例部署

      希望对您有所帮助!

      【讨论】:

        【解决方案4】:

        感觉您的问题与 label and selectors 相关......您描述的行为不太可能(除非选择器本身没有根据您的需要准确)。

        让我们以这个流程为例(在该解释中入口是一次性的,只是为了描绘它对应用程序的访问):

        Ingress -&gt; Service -&gt; [endpoints] -&gt; Pods

        1. Ingress 将路由到定义的服务;
        2. 该服务有一个类型和选择器,它是 generate the endpoint 的规则,基于您要路由请求的 pod 上的标签;
        3. 端点将代表您的 Pod 的内部 IP 地址。

        在第 2 项中,我认为您正在使用两个版本上都存在的标签的选择器,例如 app: webapp,如果您只是为包含 version 的 pod 添加一个新标签,那么您可以更改您的服务仅选择指定版本上的 pod (version: v1 || version: v2),这样您就不会再报告不一致了。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-03-09
          • 2020-11-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-07-01
          • 2019-10-08
          相关资源
          最近更新 更多