Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

k8s ramped deployment -- css from same pod

I have a webapp running on Kubernetes on 2 pods.

I edit my deployment with a new image version, from webapp:v1 to webapp:v2.

I figure an issue during the rolling out...

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 = 💥

How can I be guaranteed, that all subsequent requests will be served from the same pod, or a pod with the same version that the html served?

like image 614
abernier Avatar asked Jun 04 '19 06:06

abernier


1 Answers

How can I be guaranteed, that all subsequent requests will be served from the same pod, or a pod with the same version that the html served?

Even if you do this, you will still have problems. Especially if your app is a single-page application. Consider this:

  • User enters your website, gets index.html v1
  • You release webapp:v2. After a few minutes, all the pods are running v2.
  • The user still has the webapp opened, with index.html v1
  • The user navigates in the app. This needs to load styles.css. The user gets styles.css v2. Boom, you're mixing versions, fail.

I've run into this issue in production, and it's a pain to solve. In my experience, the best solution is:

  • Tag all the resources (css, js, imgs, etc) with a version suffix (eg styles.css -> styles-v1.css, or a hash of the file contents styles-39cf1a0b.css). Many tools such as webpack, gulp, etc can do this automatically.
  • index.html is not tagged, but it does reference the other resources with the right tag.
  • When deploying, do not delete the resources for older versions, just merge them with the newest ones. Make sure clients that have an old index.html can still get them succesfully.
  • Delete old resources after a few versions, or better, after a period of time passes (maybe 1 week?).

With this, the above scenario now works fine!

  • User enters your website, gets index.html v1
  • You release webapp:v2. This replaces index.html, but leaves all the js/css in place, adding new ones with the new version suffix.
  • The user still has the webapp opened, with index.html v1
  • The user navigates in the app. This needs to load styles-v1.css, which loads successfully and matches the index.html version. No version mixing = good!
  • Next time the user reloads the page, they get index.html v2, which points to the new styles-v2.css, etc. Still no version mixing!

Doing this with kubernetes is a bit tricky, you need to make your image build process take the files from a few older images and include them inside the new image, which is a bit strange.

Another solution is to stop serving your html/css/js from a pod, and serve it from blob storage instead. (Amazon S3, Google Cloud Storage, etc). This way, a deployment is just copying all the files, which get merged with the old files, giving you the desired behavior.

like image 124
Dirbaio Avatar answered Oct 02 '22 14:10

Dirbaio