李哲豪
    • 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
    # 將 Pod 指派給 Node 今天來看 Scheduler 分配 Pods 到 Node 的一些依據。在這之前需要先認識 [Label 和 Annotation 的用法](https://hackmd.io/@6j0OMC7UQbGqQLfUg9pauA/rkgWcv7Yda)。 您可以限制 Pod,讓它只能在特定 Node 上運行,或**更傾向**在特定 Node 上運行。有多種方法可以做到這一點,建議的方法都使用 [Label Selector](https://hackmd.io/@6j0OMC7UQbGqQLfUg9pauA/rkgWcv7Yda#Label-selectors) 來方便選擇。 通常,您不需要設定任何此類限制;Scheduler 會自動進行合理的放置(例如,將 Pod 分散到各個 Node 上,以免將 Pod 放置在可用資源不足的 Node 上)。但是,在某些情況下,您可能想要控制 Pod 部署到哪個 Node,例如,確保 Pod 最終位於連接了 SSD 的 Node 上,或是有 GPU 裝置的 Node。 您可以使用以下任何方法來選擇 Kubernetes 調度特定 Pod 的位置: + **`nodeSelector`** 字段與 Node Labels 匹配 + Affinity and anti-affinity + **`nodeName`** 字段 + Pod topology spread constraints(本教程不會示範,請參閱[官方文件](https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/)) ## nodeSelector **`nodeSelector`** 是最簡單的 Node 選擇限制推薦形式。您可以將 **`nodeSelector`** 字段新增至 Pod **`spec`** 中,並指定您希望目標 Node 具有的 Node Labels。Kubernetes 僅將 Pod 調度到具有您指定的每個 Label 的 Node 上。 ```yaml apiVersion: v1 kind: Pod metadata: name: node-selector-demo spec: containers: - name: nginx image: nginx ports: - containerPort: 80 nodeSelector: role: agent # ===>> here <<=== ``` 這裡的 key-value 會是 Node 身上的 Label。因此必須要有一個 Node 擁有 **`role`** 這個 key 並且 value 等於 **`agent`**,這個 Pod 才會被分配到該 Node 上。 ### Node labels 幫 Node 增加 Label 的指令 **`kubectl label nodes <node-name> <label-key>=<label-value>`**: ```bash kubectl label nodes k3d-mycluster-agent-0 role=agent # node/k3d-mycluster-agent-0 labeled ``` 顯示 Node 及其 Label: ```bash kubectl get nodes --show-labels # NAME STATUS ROLES AGE VERSION LABELS # k3d-mycluster-server-0 Ready control-plane,master 8d v1.27.4+k3s1 ...,kubernetes.io/hostname=k3d-mycluster-server-0 # k3d-mycluster-agent-1 Ready <none> 8d v1.27.4+k3s1 ...,kubernetes.io/hostname=k3d-mycluster-agent-1 # k3d-mycluster-agent-0 Ready <none> 8d v1.27.4+k3s1 ...,role=agent,kubernetes.io/hostname=k3d-mycluster-agent-0 ``` 不過使用 **`nodeSelector`**,我們只能指定單一個條件,如果我們希望更彈性的去安排這些 Pods 呢? 接下來就是介紹 - Affinity and anti-affinity。 ## Affinity and anti-affinity **`nodeSelector`** 是將 Pod 限制到具有特定 Label 的 Node 的最簡單方法。Affinity 和 anti-affinity 擴展了您可以定義的限制類型。Affinity 和 anti-affinity 的一些好處包括: + Affinity/anti-affinity 功能的表達方式更加豐富。**`nodeSelector`** 只選擇具有所有特定 Label 的 Node。Affinity/anti-affinit 為您提供了更多控制在選擇邏輯的能力。 + 您可以指定規則是 *soft* 或 *preferred*,以便 Scheduler 即使找不到匹配的 Node,仍然會調度 Pod。 + 您可以使用 Node 上運行的其他 Pod 的 Label(或其他拓撲域的 Label)來限制 Pod,而不僅僅是使用 Node Label,這允許您定義哪些 Pod 可以共同位於一個 Node 上的規則。 Affinity 特徵由兩種類型的 affinity 組成: + *Node affinity* 的功能類似於 **`nodeSelector`** 字段,但表達能力更強,允許您指定 soft 規則。 + *Inter-pod affinity/anti-affinity* 允許您根據其他 Pod 上的 Label 來限制 Pod。(本教程不會示範,請參閱[官方文件](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity)) ### Node affinity Node affinity 在概念上類似於 **`nodeSelector`**,讓您可以根據 Node Label 來限制您的 Pod 可以調度到哪些 Node 上。Node affinity 有兩種類型: + **`requiredDuringSchedulingIgnoredDuringExecution`**:除非滿足規則,否則 Scheduler 無法調度 Pod。它的功能類似於 **`nodeSelector`**,但使用更具表達力的語法。 + **`preferredDuringSchedulingIgnoredDuringExecution`**:Scheduler 嘗試找到滿足規則的 Node。如果沒有相符的 Node,Scheduler 仍會調度 Pod。 :::success :notebook: **Note:** 在上述類型中,IgnoredDuringExecution 表示如果 Kubernetes 調度 Pod 後 Node Label 發生變化,則該 Pod 繼續運作。 ::: 您可以使用 Pod **`spec`** 中的 **`.spec.affinity.nodeAffinity`** 字段指定 Node affinities。 例如,考慮以下 Pod **`spec`**: ```yaml apiVersion: v1 kind: Pod metadata: name: with-node-affinity spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: topology.kubernetes.io/zone operator: In values: - antarctica-east1 - antarctica-west1 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: another-node-label-key operator: In values: - another-node-label-value containers: - name: with-node-affinity image: registry.k8s.io/pause:2.0 ``` 在此範例中,適用以下規則: + 該 Node **必須**有一個帶有 key **`topology.kubernetes.io/zone`** 的 Label,並且該 Label 的 value 必須是 **`antarctica-east1`** 或 **`antarctica-west1`**。 + 此 Node **傾向**具有 key **`another-node-label-key`** 和 value **`another-node-label-value`** 的 Label。 您可以使用 **`operator`** 字段指定 Kubernetes 在解釋規則時使用的邏輯運算子。您可以使用 **`In`**、**`NotIn`**、**`Exists`**、**`DoesNotExist`**、**`Gt`** 和 **`Lt`**。 **`NotIn`** 和 **`DoesNotExist`** 可讓您定義 Node anti-affinity 行為。或者,您可以使用 Node taints 來排斥特定 Node 的 Pod。 :::success :notebook: **Note:** 如果您同時指定了 **`nodeSelector`** 和 **`nodeAffinity`**,則必須**同時**滿足這兩個條件才能將 Pod 調度到 Node 上。 如果您在與 **`nodeAffinity`** 類型相關的 **`nodeSelectorTerms`** 中指定了多個規則,那麼如果能滿足其中一個指定的規則,Pod 就可以被調度到一個 Node 上(規則之間是以 OR 的方式組合的)。 ```yaml nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: ... - matchExpressions: ... ``` 如果您在與 **`nodeSelectorTerms`** 中某個規則相關的單個 **`matchExpressions`** 字段中指定了多個表達式,那麼只有當所有這些表達式都被滿足時(表達式之間是以 AND 的方式組合的),Pod 才能被調度到一個 Node 上。 ```yaml nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: ... ... - key: ... ... ``` ::: ### Node affinity weight **`preferredDuringSchedulingIgnoredDuringExecution`** 的部分還能夠設定 **`weight`** 要多少,可設定 1-100 之間。這個 **`weight`** 會被 Scheduler 拿來計算分數,當 Pod 要被分配時會優先放到分數最高的 Node。 ```yaml preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: label-1 operator: In values: - key-1 - weight: 50 preference: matchExpressions: - key: label-2 operator: In values: - key-2 ``` 如果有兩個可能的 Node 與 **`PreferredDuringSchedulingIgnoredDuringExecution`** 規則匹配,一個具有 **`label-1:key-1`** Label,另一個具有 **`label-2:key-2`** Label,則 Scheduler 會考慮每個 Node 的 **`weight`**,並將權重添加到該 Node 的其他分數,並將 Pod 調度到最終分數最高的 Node。 ## nodeName **`nodeName`** 是比 affinity 或 **`nodeSelector`** 更直接的 Node 選擇形式。**`nodeName`** 是 Pod **`spec`** 中的一個字段。如果 **`nodeName`** 字段不為空,則 Scheduler 會忽略該 Pod,並且指定 Node 上的 kubelet 會嘗試將 Pod 放置在該 Node 上。使用 **`nodeName`** 會否決使用 **`nodeSelector`** 或 affinity 和 anti-affinity 規則。 使用 **`nodeName`** 選擇 Node 的一些限制是: + 如果指定的 Node 不存在,Pod 將不會運行,並且在某些情況下可能會自動刪除。 + 如果指定的 Node 沒有足夠的資源來容納該 Pod,則 Pod 會因無法部署而失敗,其失敗原因會被指明,例如記憶體不足(OutOfmemory)或 CPU 資源不足(OutOfcpu)。 + 雲端環境中的 Node 名稱並不總是可預測或穩定的。 :::success :notebook: **Note:** **`nodeName`** 用於自定義 Scheduler 或當您需要避開已設定的 Scheduler 時的進階應用情境。但如果直接指定 Node 而不經過 Scheduler,可能會因為 Node 資源不足而導致 Pod 啟動失敗。您可以使用 Node affinity 或 **`nodeselector`** 字段來安排 Pod 到特定 Node,而無需繞過 Scheduler。 ::: 以下是使用 **`nodeName`** 字段的 Pod **`spec`** 範例: ```yaml apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - name: nginx image: nginx nodeName: kube-01 ``` 上面的 Pod 只會運行在 Node **`kube-01`** 上。

    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