peter12345678
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    --- type: slide --- # K8s 部署策略 [TOC] --- ## Recap: K8s Deployment ---- ### strategy - `RollingUpdate` - `Recreate`. ---- ![image](https://hackmd.io/_uploads/BJOYZF-ta.png =800x) ---- ### **MaxSurge** and **MaxUnavailable** ![image](https://hackmd.io/_uploads/r1IfZtbta.png) --- ## 部署側略 ---- ### 情境 ---- ㄟ我 IG 首頁怎麼跟妳不一樣?! ---- 有人不喜歡有人喜歡 ---- 哭啊我 Uber Eats 進不去 ---- (應該) 都沒人喜歡? ![image](https://hackmd.io/_uploads/B1XVP3cYa.png) ---- ### 一個好的部署策略 一個好的部署策略應該是要具備盡可能的 - 讓服務不中斷 - 戰略性的試試市場水溫 - 回退到歷史版本的能力 ---- ![image](https://hackmd.io/_uploads/BJOYZF-ta.png =800x) ---- ### 1. 重建部署 (Recreate) 重建部署是一個成本偏沈重的方式 簡單來說它會將舊版本完全下線後才開始上線新版本,這意味著你的服務將會有一段停機時間依賴於應用下線跟啟動的耗時。 ---- #### 優點: - 便於設定。 - 線上只會同時運行一種版本。 - 部署過程中不會造成主機額外負擔。 ---- #### 缺點: - 對使用者影響大,預期的停機時間取決於下線時間和啟動服務的耗時。 ---- ### 2. 滾動部署 (Rolling-update) 滾動部署策略就是指容器會如同水漸漸地往傾斜的地方聚集一樣的更新版本,能緩慢平和的釋出新版本。 如同水流的流速快慢一樣,滾動部署也能通過調整下列引述來調整部署穩定性以及速率: ---- #### 參數 - 最大執行數:可以同時釋出的服務數目。 - 最大峰值:升級過程中最多可以比原先設定所多出的服務數量。 - 最大不可用數:最多可以有幾個服務處在無法服務的狀態。 ---- #### 優點: 相較於藍綠部署更加節省資源。 便於設定,服務不中斷。 ---- #### 缺點: - 釋出與回滾耗時,想想當我們有 100 個服務,每次需要花五分鐘更新其中 10 個,當更新到第 80 個時發現錯誤需要緊急回滾的情況? - 部署期間新舊兩版服務都會同時在線上運作,無法控制流量且噴錯時除錯困難高。 ---- ### 3. 藍綠部署 (Blue / Green) 相較於滾動更新,藍綠部署則是會先將新版本的服務完整的開啟,並且在新版本滿足上線條件的測試後,才將流量在負載均衡層從舊版本切換到新版本。 ---- #### 優點: - 實時釋出、回滾。 - 避免新舊版本衝突,整個過程同時只會有一個版本存在。 - 服務不中斷。 ---- #### 缺點: - 部署完成前需要雙倍的資源要求所增加的開銷及成本。有時新版本通過不了測試時,舊版本將持續運行到新版本通過為止。 - 當切換到新版本的瞬間,如果有未處理完成的業務將會是比較麻煩的問題。 ---- ### 4. 金絲雀部署 (Canary) 金絲雀部署,與藍綠部署不同的是,它不是非黑即白的部署方式,所以又稱為灰度部署。 灰度部署是指在黑與白之間,能夠平滑過度的一種部署方式。我們能夠緩慢的將新版本先推廣到一小部分的使用者,驗證沒有問題後才完成部署,以降低生產環境引入新功能帶來的風險 ---- #### 使用情境 例如將 90% 的請求導向舊版本,10% 的請求轉向新版本。這種部署大多用於缺少可靠測試或者對新版本穩定性缺乏信心的情況下 ---- #### 金絲雀??? 金絲雀部署的命名來自於 17 世紀的礦井工人發現金絲雀對瓦斯這種氣體非常敏感,哪怕是只有及其微量的瓦斯,金絲雀也會停止歌唱率先比人類出現不良反應,所以工人每次下井時都會帶上一隻金絲雀作為危險狀況下的救命符 ---- #### 優點: - 方便除錯以及監控。 - 只向一小部分使用者釋出。 - 快速回滾、快速迭代。 ---- #### 缺點: - 完整釋出期漫長。 - 只能適用於相容迭代的方式,如果是大版本不相容就沒辦法使用這種方式了 ---- ### 5. A / B 測試 (A / B Testing) A / B 測試實際上是一種基於統計信息而非部署策略來製定業務決策的技術,與業務結合非常緊密。但是它們也是相關的,也可以使用金絲雀發布來實現。 除了基於權重在版本之間進行流量控制之外,A / B 測試還可以基於一些其他參數(比如**Cookie**、**User Agent**、**地區**等等)來精確定位給定的用戶群,該技術廣泛用於測試一些功能特性的效果,然後按照效果來進行確定。 ---- #### 假設檢定 假設檢驗是用來判斷樣本與樣本,樣本與總體之間的差異是由抽樣誤差引起還是本質差別造成的統計推斷方法,其基本原理是先對總體特徵做出某種假設,然後通過抽樣研究的統計推理,對此假設應該被拒絕還是接受做出判斷,假設檢驗使用了一種類似反證法的推理,通過A/B Test,我們要驗證的其實是一對假設,原假設和備擇假設。 假設檢驗的基本思路是“小概率事件在少量實驗中是幾乎不可能出現的”,如果在實驗中出現了小概率事件,那麼我們就可以推斷原假設是錯誤的,從而推斷備擇假設可能是正確的。 ---- 蛤你在說什麼? ---- 等等好像看過類似的情境ㄟ ---- 若天堂M紫布製作成功率$p=5%$,則: 虛無假設 $H_0:p=0.05$ 對立假設 $H_1:p<0.05$ 顯著水準$=0.05$ ---- 《第一次直播4/175》 丁特實抽機率 $\hat{p}=4/175$ 求得 $P-value=0.049779$ 《第二次直播7/300》 丁特實抽機率 $\hat{p}=7/300$ 求得 $P-value=0.017045$ 《總計11/475》 丁特實抽機率$\hat{p} =11/475$ 求得 $P-value=0.003637$ ---- 三次計算結果的 $P-value$ 分別為 $0.049779、0.017045、0.003637$ 當 $P-value < 0.05$ (顯著水準),就必需拒絕 $H_0$ 接受 $H_1$ *** 即「拒絕製作成功機率=5%的假設,接受製作成功機率<5%的假設」 而這三次的數值均小於顯著水準 代表不論哪個情況 ---- 天堂M的紫布製作成功機率皆顯著低於5% ---- #### 終於知道為什麼有些人會在限動說: 為什麼我的便利貼不見ㄌ, 可是我看都好好的ㄚ ---- A / B 測試是線上同時執行多個不同版本的服務,這些服務更多的是使用者側的體驗不同,比如**頁面佈局**、**按鈕顏色**,**互動方式**等,通常底層業務邏輯還是一樣的,也就是通常說的換湯不換藥。諸如 Google Analysis 等網站分析工具服務通常也可以搭配**自家負載均衡器**實現 A / B 測試。 ---- #### 優點: - 多版本並行執行 - 完全控制流量分佈 ---- ### 缺點: - 需要更全面的負載均衡(通常由雲端服務實現) - 難以定位辨別(要額外紀錄) ---- ### 6. 影子部署 (Shadow) 影子部署是指在原有版本旁完整運行新版本,並且將流入原有版本的請求同時分發到新版本,得以實現在更新之前就模擬正式產品環境的運作情況,直到滿足上線條件後才將進入點轉往新版本並關閉舊版本。 ---- #### 優點: - 可以直接對正式環境流量進行效能測試而不影響使用者。 - 直到應用穩定且達到上線條件時才釋出。 ---- #### 缺點: - 與藍綠部署一樣需要雙倍的資源請求。 - 配置複雜,容易出現預期外的情況。 --- ## 要怎麼做到ㄚ ---- ### 1. 重建部署 [deployment strategy](https://hackmd.io/@peter12345678/S1mRGUZYT#/2/8) ---- ### 2. 滾動部署 [deployment strategy](https://hackmd.io/@peter12345678/S1mRGUZYT#/2/8) ---- ### 3. 藍綠部署 1. 啟動一個原有的 v1 版本服務並且用 Service 的 label selector 指向該 v1 版本服務管理對外端口。 2. 啟動並且等待我們的 v2 版本完全就緒,此時新舊兩個版本處於同時存在的狀態。 3. 將 Service 的 label selector 從 v1 版本指向到 v2 版本。 4. 確保終止了舊的 v1 版本。 ---- #### V1 and V2 Deployment ---- 開兩個版本的 Deployment ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: foo-deployment labels: app: my-app spec: replicas: 3 selector: matchLabels: app: my-app version: v1 template: metadata: labels: app: my-app version: v1 spec: containers: - name: foo image: mikehsu0618/foo ports: - containerPort: 8080 --- apiVersion: apps/v1 kind: Deployment metadata: name: bar-deployment labels: app: my-app spec: replicas: 3 selector: matchLabels: app: my-app version: v2 template: metadata: labels: app: my-app version: v2 spec: containers: - name: bar image: mikehsu0618/bar ports: - containerPort: 8080 ``` ---- ### Service Version Transition ---- 先開一個綁 V1 deployment 的 service ```yaml! apiVersion: v1 kind: Service metadata: name: blue-green-service spec: selector: app: my-app version: v1 type: LoadBalancer ports: - protocol: TCP port: 8080 targetPort: 8080 ``` ---- #### Perform Transition ---- 把 label 從 v1 改成 v2 !!! ```diff apiVersion: v1 kind: Service metadata: name: blue-green-service spec: selector: app: my-app - version: v1 + version: v2 type: LoadBalancer ports: - protocol: TCP port: 8080 targetPort: 8080 ``` ---- #### Delete old version Deployment ```shell! kubectl delete deployment bar-deployment ``` ---- ### 4. 金絲雀部署 ---- 哭了這要怎麼用ㄚ ---- ㄟ流量 ---- ㄟˋ Ingress ---- #### Nginx Ingress 在 Kubernetes 中的使用 Ingress 在 Kubernetes 集群中基於七層的 HTTP 和 HTTPS 協議進行轉發,允許通過域名和路徑對訪問進行更細粒度的劃分。作為 Kubernetes 中的一種獨立資源,Ingress 通過創建來定義外部訪問流量的轉發規則,並由 Ingress Controller 負責將流量分配到一個或多個 Service。 ---- 可四ㄌㄟ Ingress要怎麼弄金絲雀? ---- 感覺[上一份簡報](https://hackmd.io/@peter12345678/S1mRGUZYT#/3/6) annotations 好像沒什麼提到 ![image](https://hackmd.io/_uploads/H1gPQ6cYT.png =400x) ---- #### Nginx Ingress 的外部流量切分策略 Nginx Ingress 提供基於 **Header**、**Cookie*、**權重**的三種外部流量切分策略 ---- 1. **`nginx.ingress.kubernetes.io/canary`** - 設定為 `true` 時,將被視為 Canary Ingress,用於流量切分 2. **`nginx.ingress.kubernetes.io/canary-by-header-value`** - 通知 Ingress 如有與 Header 設定值匹配的請求 Header,則轉導流量到 Canary Ingress ---- 3. **`nginx.ingress.kubernetes.io/canary-by-header-pattern`** - 功能類似於 `canary-by-header-value`,可以用 regex 配對 - 注意:若有 `canary-by-header-value` 設定,則此 Annotation 的功能將被忽略 4. **`nginx.ingress.kubernetes.io/canary-by-cookie`** - 通知 Ingress 如有與 Cookie 設定值匹配的請求 Cookie,則轉導流量到 Canary Ingress - 設定為 `always` 時,所有流量將被轉導 ---- 5. **`nginx.ingress.kubernetes.io/canary-weight`** - 數值為基於 0 到 100 的整數,表示有多少百分比的流量將被轉導到 Canary Ingress ---- #### 優先級 優先級由高到低為: 1. `canary-by-header` 2. `canary-by-cookie` 3. `canary-weight` ---- 來看看實際怎麼做 ---- #### V1 and V2 Deployments ---- 開兩個版本的 Deployment ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: foo-deployment labels: app: my-app spec: replicas: 3 selector: matchLabels: app: my-app version: v1 template: metadata: labels: app: my-app version: v1 spec: containers: - name: foo image: mikehsu0618/foo ports: - containerPort: 8080 --- apiVersion: apps/v1 kind: Deployment metadata: name: bar-deployment labels: app: my-app spec: replicas: 3 selector: matchLabels: app: my-app version: v2 template: metadata: labels: app: my-app version: v2 spec: containers: - name: bar image: mikehsu0618/bar ports: - containerPort: 8080 ``` ---- #### V1 and V2 Services ---- 開兩個版本的 Service 去綁 V1 and V2 deployment ```yaml! apiVersion: v1 kind: Service metadata: name: foo-service spec: selector: app: my-app version: v1 type: NodePort ports: - protocol: TCP port: 8080 targetPort: 8080 --- apiVersion: v1 kind: Service metadata: name: bar-service spec: selector: app: my-app version: v2 type: NodePort ports: - protocol: TCP port: 8080 targetPort: 8080 ``` ---- #### Ingress Transition ---- 先跑一個 Ingress serve V1 的 Service ---- ```yaml! apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress spec: ingressClassName: nginx defaultBackend: service: name: foo-service port: number: 8080 ``` ---- #### 開始金絲雀 ---- 加入一個 Canary Ingress (不用刪掉原本的) ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-weight: "10" name: canary-ingress spec: ingressClassName: nginx defaultBackend: service: name: bar-service port: number: 8080 ``` 設定將 10% 比重的請求分流到 bar-service 這個 v2 版本的服務 ---- #### and then? ---- 將 Ingress 設定為新版本的 v2 並且刪除過渡使用的 Canary Ingress 以及 v1 版本資源即可。 ---- ### 5. A / B 測試 ---- 剛剛有提到這其實是基於統計的策略, 並沒有固定的做法 ---- 但是我統計不太好 ---- 所以我們來嘗試讓中國用戶連不到我們的新服務吧~ ---- ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-by-header: "X-Country" nginx.ingress.kubernetes.io/canary-by-header-pattern: "^(?!China$).*" name: canary-ingress spec: ingressClassName: nginx defaultBackend: service: name: bar-service port: number: 8080 ``` --- ## Thank you for participating! --- ## Reference - [x] 1. [Kubernetes 的組件 ](https://ithelp.ithome.com.tw/articles/10287576) - [x] 2. [實戰做一個 Pod](https://ithelp.ithome.com.tw/articles/10288199) - [x] 3. [實戰做一個 Service](https://ithelp.ithome.com.tw/articles/10288389) - [x] 4. [實戰做一個 Deployment](https://ithelp.ithome.com.tw/articles/10288602) - [x] 5. [Ingress](https://ithelp.ithome.com.tw/articles/10288843) - [x] 6. [部署策略](https://ithelp.ithome.com.tw/articles/10289496) - [x] [Grayscale](https://ithelp.ithome.com.tw/articles/10290317) - [x] [Canry](https://ithelp.ithome.com.tw/articles/10290852)

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully