The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

使用 MicroK8s 架設 Kubernetes 叢集時應注意的連線管理注意事項

使用 MicroK8s 架設 Kubernetes 叢集,無論是本機的開發環境,或是實際運作的生產環境,都有一些應該注意的事情。本篇文章著重在「連線管理」部分,分享我過往的一些研究心得與筆記。

Ubuntu + MicroK8s

頻繁的更動節點 IP 怎麼辦

在 Windows 環境搭配 Hyper-V 安裝 MicroK8s 叢集時,預設會使用 Hyper-V 內建的 Default Switch 做為預設的虛擬交換器(vSwitch),但由於 Default Switch 的特殊性,它有以下幾點限制:

  1. 連線類型(Connection type)預設採用「內部網路」(Internel network)

    這意味著使用 Default Switch 的 VM 只能從「本機」進行連接,從外部網路是無法連上的,也無法實現 Port forwarding (通訊埠轉發)

  2. 透過 DHCP 伺服器自動配發 IP 地址

    由於 Default Switch 使用了 Windows 內建的 Internet Connection Sharing (ICS) 機制,而正式這個機制配發了動態的私有 IP 地址給 VM 使用,並提供了相當基礎的 NAT 機制,讓你的 VM 可以連接到外部網路。

    透過 ICS 機制取得 IP 地址有好有壞。好的地方是,建立好的 VM 會自動配發 IP 地址,簡化網路管理。壞的地方是,這個 DHCP 伺服器無法停用,也無法自行指定 IP 範圍。更糟的地方是,你無法對 VM 設定「靜態 IP 地址」(Static IP Address),而且只要電腦重開機後,這個 DHCP 伺服器就會配發全新的 IP 地址給 VM 使用,而且這個 IP 是無法事先設定或預測的。

  3. 所有使用 Default Switch 的 VM 都會擁有一個本機可存取的網域名稱(Domain Name)

    因為 IP 無法固定的緣故,這個 ICS 機制還會自動維護一份本機的 hosts.ics 檔案,路徑如下:

    %systemroot%\system32\drivers\etc\hosts.ics
    

    這個檔案與我們常用的 hosts 檔案放在同一個資料夾下,但是你不用特別維護 hosts.ics 檔案。

    基本上,你只要在建立好 VM 之後的幾秒鐘內,系統就會自動更新 hosts.ics 檔案,提供你一個 *.mshome.net 的域名。例如你的 VM 名稱如果是 microk8s-vm 的話,那麼你就會有一個 microk8s-vm.mshome.net 域名可以直接取得這台 VM 的當時的 IP 地址 (請記得重開機 IP 就會變更),這點倒是相當的便利。不過,這個域名是不能改的,改了也沒用,因為隨時可能會被 Hyper-V 覆寫。

上述限制,正是 MicroK8s 在最簡單的 microk8s install 安裝好環境後,其 VM 的 IP 會在每次重開機後變更的原因! 🔥

其解決方案有兩個:

  1. 調整 KUBECONFIG 設定檔,改用 microk8s-vm.mshome.net 做為預設的伺服器位址

    kubectl config set-cluster microk8s-cluster --server=https://microk8s-vm.mshome.net:16443
    
    microk8s kubectl config set-cluster microk8s-cluster --server=https://microk8s-vm.mshome.net:16443
    
  2. 每次重開機後,自動執行以下命令,更新 KUBECONFIG 設定檔中的 server IP 地址

    # 更新 microk8s kubectl 命令專用的 KUBECONFIG 內容
    microk8s config > $env:LOCALAPPDATA\MicroK8s\config
    
    # 更新 kubectl 命令專用的 KUBECONFIG 內容
    microk8s config > ~/.kube/config
    
  3. 不要使用 Default Switch 虛擬交換器

    你可以參考我先前的 利用 Multipass 在區域網路架設一套 MicroK8s 叢集環境 文章,額外建立一個 External network 虛擬交換器,直接讓 VM 取得外部網路的 IP 地址。

設定 k 別名

我在 Linux 的 Shell 環境下,幾乎都會用 k 來取代 kubectl 命令,簡化指令輸入的時間。若是在 Windows 環境下,你可以透過 PowerShell 的 Set-Alias 來做到一樣的功能。

以下有 2 種不同用法:

  1. 簡單的 k 對應到 kubectl

    這是在有事先安裝 kubectl.exe 工具並設定好 PATH 環境變數的前提下才能這樣設定:

    Set-Alias -Name k -Value kubectl
    
  2. 透過 k 去執行 microk8s kubectl 命令的話,也可以這樣寫:

    注意: 透過這種方式執行 kubectl 非常慢,建議不要這樣用。

    function RunKubectl([Parameter(ValueFromRemainingArguments = $true)]$params) {
        & microk8s.exe kubectl $params
    }
    Set-Alias -Name k -Value RunKubectl
    

    同樣的技巧,也可以用在執行 microk8s 的時候,因為打這個命令實在太花時間,我可以簡化成 mks 就好 👍

    function RunMicroK8s([Parameter(ValueFromRemainingArguments = $true)]$params) {
        & microk8s.exe $params
    }
    Set-Alias -Name mks -Value RunMicroK8s
    

常見的 KUBECONFIG 管理

以下是一些管理 KUBECONFIG 的常見命令:

  • 預設的 KUBECONFIG 路徑

    ~/.kube/config
    
  • 指定自訂的 KUBECONFIG 路徑

    $env:KUBECONFIG = '~/.kube/microk8s-config'
    

    清除 KUBECONFIG 環境變數設定:

    $env:KUBECONFIG = ''
    
  • 取得目前 KUBECONFIG 中的叢集名稱

    k config get-clusters
    
  • 取得目前 KUBECONFIG 中的叢集設定

    # 僅顯示重要參數並隱藏憑證的內容(因為內容很長)
    k config view
    
    # 顯示完整的原始內容
    k config view --raw
    
  • 設定目前 KUBECONFIG 中的叢集相關參數

    k config set-cluster -h
    # 重新指定叢集節點的 kube-apiserver 端點
    k config set-cluster microk8s-cluster --server=https://microk8s-vm.mshome.net:16443
    
    # 變更 CA 根憑證內容
    k config set-cluster microk8s-cluster --embed-certs --certificate-authority=~/.kube/e2e/kubernetes.ca.crt
    
    # 設定跳過 TLS 有效性驗證
    k config set-cluster microk8s-cluster --insecure-skip-tls-verify=true
    
  • 設定目前 KUBECONFIG 中的 Context 設定

    所謂的 Context 就是一個連線到 K8s 叢集的連線情境,這個情境包含了 NAME (情境名稱)、CLUSTER (叢集名稱)、AUTHINFO (認證資訊) 與 NAMESPACE (命名空間) 等 4 個欄位。一個 KUBECONFIG 可以包含多種連線情境,而且可以任意切換。你可以一個叢集設定好幾組情境,也可以每個情境連到不同的叢集,你可以自由搭配。

    # 列出目前所有的連線情境
    k config get-contexts
    
    # 切換到不同的連線情境
    kubectl config use-context myaks
    
    # 設定 microk8s 連線情境改用不同的使用者登入
    k config set-context microk8s --user=admin
    
    # 修改目前的連線情境改用 admin 來連線
    k config set-context --current --user=admin
    
    # 修改目前的連線情境改用 willh 為預設命名空間
    k config set-context --current --namespace=default
    
    # 列出 KUBECONFIG 中所有使用者
    k config get-users
    
    # 建立/更新 cluster-admin 使用者的 Bearer Token
    k config set-credentials cluster-admin --token=uXFGweU9l35q
    
    # 建立/更新 cluster-admin 使用者的 Private Key
    k config set-credentials cluster-admin --client-key=~/.kube/admin.key
    
    # 建立/更新 cluster-admin 使用者的 Client Certificate (用戶端憑證)
    k config set-credentials cluster-admin --client-certificate=~/.kube/admin.crt --embed-certs=true
    

關於 MicroK8s 叢集重要的認證檔

進入到 MicroK8s 叢集主節點後,可以找到幾個重要的設定檔,這些設定檔決定了叢集要如何對使用者進行驗證,其主要目錄如下:

$ ll /var/snap/microk8s/current/credentials/
total 32
drwxrwx---  2 root microk8s 4096 Aug 15 13:56 ./
drwxr-xr-x 13 root root     4096 Aug 17 15:37 ../
-rw-rw----  1 root microk8s 1869 Aug 15 13:56 client.config
-rw-rw----  1 root microk8s 1879 Aug 15 13:56 controller.config
-rw-rw----  1 root microk8s  486 Aug 15 13:56 known_tokens.csv
-rw-rw----  1 root microk8s 1873 Aug 15 13:56 kubelet.config
-rw-rw----  1 root microk8s 1877 Aug 15 13:56 proxy.config
-rw-rw----  1 root microk8s 1877 Aug 15 13:56 scheduler.config

各檔案說明如下:

  1. known_tokens.csv

    這裡記錄了所有系統使用者的 Bearer Token 清單

    預設 MicroK8s 都是使用 Bearer Token 來驗證使用者,預設會從 /var/snap/microk8s/3582/args/kube-apiserver 啟動參數定義檔載入這個 known_tokens.csv 檔案。

    --cert-dir=${SNAP_DATA}/certs
    --service-cluster-ip-range=10.152.183.0/24
    --authorization-mode=AlwaysAllow
    --service-account-key-file=${SNAP_DATA}/certs/serviceaccount.key
    --client-ca-file=${SNAP_DATA}/certs/ca.crt
    --tls-cert-file=${SNAP_DATA}/certs/server.crt
    --tls-private-key-file=${SNAP_DATA}/certs/server.key
    --kubelet-client-certificate=${SNAP_DATA}/certs/server.crt
    --kubelet-client-key=${SNAP_DATA}/certs/server.key
    --secure-port=16443
    --token-auth-file=${SNAP_DATA}/credentials/known_tokens.csv
    --insecure-port=0
    --storage-backend=dqlite
    --storage-dir=${SNAP_DATA}/var/kubernetes/backend/
    --allow-privileged=true
    --service-account-issuer='https://kubernetes.default.svc'
    --service-account-signing-key-file=${SNAP_DATA}/certs/serviceaccount.key
    --feature-gates=RemoveSelfLink=false
    
  2. client.config

    系統管理員專用的預設 KUBECONFIG 設定檔,預設使用者名稱為 admin

  3. controller.config

    controller 預設使用的 KUBECONFIG 設定檔,預設使用者名稱為 controller

  4. kubelet.config

    kubelet 設使用的 KUBECONFIG 設定檔,預設使用者名稱為 kubelet

  5. proxy.config

    kube-proxy 設使用的 KUBECONFIG 設定檔,預設使用者名稱為 kubeproxy

  6. scheduler.config

    scheduler 設使用的 KUBECONFIG 設定檔,預設使用者名稱為 admin

相關連結