kubeconfig === ###### tags: `K8s` ###### tags: `Kubernetes`, `k8s`, `kubeconfig`, `host`, `remote`, `kubectl` <br> [TOC] <br> ## cmd ### 測試 K8s 連線 - ### 直接透過 https 測試 ``` https://<target_ip>:<target_port>/version ``` 正常結果: ```json { "major": "1", "minor": "31", "gitVersion": "v1.31.7", "gitCommit": "da53587841b4960dc3bd2af1ec6101b57c79aff4", "gitTreeState": "clean", "buildDate": "2025-03-11T19:55:18Z", "goVersion": "go1.23.6", "compiler": "gc", "platform": "linux/amd64" } ``` - 測試 kubeconfig 中的 `clusters[].cluster.server` 代入上面 `<target_ip>:<target_port>` 看是否能連線 <br> ### 從自建叢集取得 kubeconfig ```yaml= $ cat ~/.kube/config # or $ sudo cat /etc/kubernetes/admin.conf [sudo] password for ubuntu: apiVersion: v1 clusters: - cluster: certificate-authority-data: LS0tLS......== server: https://10.78.153.24:6443 name: kubernetes contexts: - context: cluster: kubernetes user: kubernetes-admin name: kubernetes-admin@kubernetes current-context: kubernetes-admin@kubernetes kind: Config preferences: {} users: - name: kubernetes-admin user: client-certificate-data: LS0tLS......== client-key-data: LS0tLS......= ``` <br> ### 將主機相依config -> 與主機無關config (嵌入式config) > 主機無關config:獨立可攜、不依賴 host 的 `.kube/config` - ### 主機相依config - `certificate-authority: /home/<USER>/.minikube/ca.crt` - `client-certificate: /home/<USER>/.minikube/profiles/mymini/client.crt` - `client-key: /home/<USER>/.minikube/profiles/mymini/client.key` - 範例: ```yaml= apiVersion: v1 clusters: - cluster: certificate-authority: /home/tj_tsai/.minikube/ca.crt extensions: - extension: last-update: Wed, 07 May 2025 15:05:22 CST provider: minikube.sigs.k8s.io version: v1.33.0 name: cluster_info server: https://192.168.49.2:8443 name: mymini contexts: - context: cluster: mymini extensions: - extension: last-update: Wed, 07 May 2025 15:05:22 CST provider: minikube.sigs.k8s.io version: v1.33.0 name: context_info namespace: default user: mymini name: mymini current-context: mymini kind: Config preferences: {} users: - name: mymini user: client-certificate: /home/tj_tsai/.minikube/profiles/mymini/client.crt client-key: /home/tj_tsai/.minikube/profiles/mymini/client.key ``` - ### 轉換指令 ```yaml kubectl config view --minify --flatten --raw > /tmp/minikube.kubeconfig ``` | 參數 | 說明 | |-----|-----| | `--minify` | 只輸出目前使用中的 context(e.g. `mymini`) | | `--flatten` | 合併使用到的 cert / key 等資訊 | | `--raw` | 保留原始 base64 內容,便於複製給其他環境使用 | - ### 原始參數說明 - ### `--minify=false` Remove all information not used by current-context from the output > 只保留與 current-context 使用到的資訊,移除未被使用的內容。 - ### `--flatten=false` Flatten the resulting kubeconfig file into self-contained output (useful for creating portable kubeconfig files) > 將產生的 kubeconfig 檔展平成自足(self-contained)的輸出(用於建立可攜式 kubeconfig 檔案)。 - ### `--raw=false`: Display raw byte data and sensitive data > 顯示原始位元組資料與敏感資料。 - ### 驗證產生結果 ``` grep "certificate-authority-data" /tmp/minikube.kubeconfig grep "client-certificate-data" /tmp/minikube.kubeconfig ``` 若出現 base64 格式內容,代表成功內嵌 <br> ### 指定 config 連線 - ### 方法一:透過環境變數 `KUBECONFIG=<abspath/to/your/cocnfig> kubectl get nodes` - ### 方法二:透過 `--kubeconfig` 參數 `kubectl --kubeconfig=/path/to/your/config get nodes` - ### 方法三 `cp /path/to/your/config ~/ get nodes` - ### 若沒有回應,回到用 https 測試 ``` https://<target_ip>:<target_port>/version ``` <br> ## 討論 ### 我要如何在本機端下達 K8s 指令,等同直接操作遠端 K8s? - ### gpt-o1 (2025/01/08) > 如何在本機端執行 `kubectl` 指令,直接操作遠端 Kubernetes 叢集 ### 1. 安裝 kubectl #### macOS ``` brew install kubectl ``` 或直接從 [Kubernetes 官方文件](https://kubernetes.io/docs/tasks/tools/) 下載對應版本的二進位檔。 #### Linux ``` curl -LO "https://dl.k8s.io/release/$(curl -L \ https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" chmod +x kubectl sudo mv kubectl /usr/local/bin/ ``` - 根據需求替換下載連結的 OS/架構 - `curl -L https://dl.k8s.io/release/stable.txt` -> `v1.32.0` (2025/01/08) #### Windows 從 [Kubernetes 官方文件](https://kubernetes.io/docs/tasks/tools/) 或 [GitHub 釋出頁面](https://github.com/kubernetes/kubernetes/releases) 下載 Windows 版本的 `kubectl.exe`,放入 PATH 中即可。 --- ### 2. 取得遠端 K8s 叢集連線資訊 1. **若是雲端服務 (GKE / EKS / AKS / etc.)** - **GKE**: ``` gcloud container clusters get-credentials <CLUSTER_NAME> --zone <ZONE> --project <PROJECT_ID> ``` 上述指令會將認證資訊更新到 `~/.kube/config` 檔案。 - **EKS**: ``` aws eks --region <REGION> update-kubeconfig --name <CLUSTER_NAME> ``` - **AKS**: ``` az aks get-credentials --resource-group <RESOURCE_GROUP> --name <CLUSTER_NAME> ``` 2. **若是自建 Kubernetes 叢集** - 可以跟叢集管理者 (或 CI/CD Pipeline 產生) 取得 kubeconfig 檔案,或由叢集管理面板 (如 Rancher、Kubernetes Dashboard 或其他管理工具) 下載對應使用者 / namespace 的 kubeconfig。 - 將取得到的 kubeconfig 檔案內容合併或直接覆蓋到本機的 `~/.kube/config` 中。 --- ### 3. 驗證並使用指令 ``` # 預設會使用 ~/.kube/config kubectl config get-contexts kubectl config current-context kubectl get nodes ``` 或若想要指定不同 kubeconfig 檔案位置,可以使用 `--kubeconfig` 參數,例如: ``` kubectl --kubeconfig=/path/to/your/config get nodes ``` 若能看到叢集上的 Node / Pod 資訊,即表示你的本機 `kubectl` 已連上遠端 K8s。 --- ### 4. 常見注意事項 1. **版本對應性** - 確認本機安裝的 `kubectl` 版本與 Kubernetes 叢集 API 版本相容。一般來說,前後一個 Minor 版本都能相互運作,但若差距過大,可能會有相容性問題。 2. **認證檔案與權限** - 常見的認證方式包含 Token、X.509 憑證等。若使用者權限不足,可能會導致某些操作受限 (例如無法建立 deployment、無法存取某些 namespace)。 3. **多叢集管理** - 你可以在 `~/.kube/config` 中同時設定多個叢集的存取資訊,透過 `kubectl config use-context <contextName>` 來切換目標叢集。 4. **安全性** - 如果這些認證檔案具有生產環境的最高權限,建議妥善管理並確保不會外洩到 Git 或其他公開管道。 --- ### 總結 1. **安裝 `kubectl`**:確保可以在本機使用 `kubectl` 指令。 2. **設定 kubeconfig**:透過雲端 CLI (如 gcloud、aws cli、az cli) 或由叢集管理者提供的 kubeconfig 檔案,將遠端叢集的連線資訊合併/設定在本機的 `~/.kube/config` 中。 3. **驗證連線**:執行簡單的 `kubectl get nodes/pods` 等指令,確認能正常存取遠端 Kubernetes 叢集。 只要設定完成後,你在本機下達的所有 `kubectl` 指令就會直接對應到遠端叢集,達到「在本機端操作遠端 K8s」的目的。 <br> ### 若是自建 Kubernetes 叢集,要如何取得 config? - ### gpt-o1 (2025/01/08) > 如何在自建 Kubernetes 叢集取得 config 如果是「自建」的 Kubernetes 叢集(例如使用 kubeadm、Rancher、Kubespray 或手動部署的方式),通常會在叢集的控制平面 (Control Plane) 主節點上產生一份 kubeconfig 檔案,存放在特定路徑下。透過以下方式即可取得並帶回本地使用: --- ### 1. 確認 kubeconfig 在控制平面上的位置 #### (a) 使用 kubeadm 建立的叢集 - **預設存放位置**: `/etc/kubernetes/admin.conf` - 可直接查看: ```bash cat /etc/kubernetes/admin.conf ``` 或使用 `sudo` 權限查看檔案內容。 #### (b) 其他工具 (Rancher / Kubespray / 手動部署等) - Rancher 之類的管理工具,通常會提供直接下載 kubeconfig 的功能 (例如透過 Rancher UI)。 - 若是手動部署或使用其他工具,檔案通常也會放在類似 `/etc/kubernetes/` 目錄下,或是管理者手動放在家目錄 (`~/.kube/config`)。 - 如果不確定位置,可以諮詢叢集管理者或檢查 `/etc/kubernetes/`、`/root/.kube/` 等常見路徑。 --- ### 2. 複製 kubeconfig 回本地 假設你可以使用 SSH 連線到控制平面主節點,可將檔案直接複製下來,例如 (以 kubeadm 為例): ```bash # 在本地主機上 scp user@<控制平面IP>:/etc/kubernetes/admin.conf ~/mycluster.conf ``` 若是透過 Rancher UI 或其他管理工具,則可以直接透過網頁或 CLI 下載,保存成一個檔案 (例如 `mycluster.conf`)。 --- ### 3. 在本地合併或指定使用 #### (a) 合併到本地 `~/.kube/config` 1. 先備份本機已有的 `~/.kube/config` (如果有的話) ```bash cp ~/.kube/config ~/.kube/config.bak ``` 2. 使用編輯器打開兩邊的檔案,手動合併 `clusters`, `contexts`, `users` 欄位至同一個 `~/.kube/config`。 #### (b) 直接指定 kubeconfig - 如果不想手動合併,也可以直接指定該檔案使用: ```bash kubectl --kubeconfig=~/mycluster.conf get nodes ``` - 或是先行複製 / 覆蓋: ```bash mkdir -p ~/.kube cp ~/mycluster.conf ~/.kube/config ``` --- ### 4. 驗證並操作 將 kubeconfig 檔案放到本機後,可執行以下指令確認已成功連線: ```bash kubectl config get-contexts kubectl config current-context kubectl get nodes ``` 若能正常列出 Cluster 內的節點資訊,表示你的本地已成功連線到遠端 Kubernetes 叢集。 --- ### 小結 1. **定位 kubeconfig**:在自建 K8s 叢集主節點找到並下載 kubeconfig (常見於 `/etc/kubernetes/admin.conf`)。 2. **複製到本地**:可以使用 `scp` 或管理工具 UI 直接下載。 3. **合併或指定使用**:放到本地 `~/.kube/config`,或透過 `--kubeconfig` 指令來使用。 4. **驗證連線**:確認可以執行 `kubectl` 指令並查看叢集資訊。 這樣就能在本機端使用 `kubectl` 操作自建 Kubernetes 叢集。 <br> ### 一座 K8s 的 config 和一座 K8s 的 config,要怎麼合併放在當前的 ~/.kube/ 底下? - ### gpt-o3-mini-high (2025/02/21) > 合併多個 Kubeconfig 檔案 在 Kubernetes 中,你可以透過兩種方式將多個 kubeconfig 檔案合併到 `~/.kube/config` 中,使它們共存。以下將分別說明兩種方法: --- ### 1. 使用環境變數和 kubectl 指令自動合併 你可以利用 `KUBECONFIG` 環境變數同時指定多個 kubeconfig 檔案,再透過 `kubectl config view --flatten` 將它們合併並輸出到單一檔案。 例如,假設你有兩個檔案 `config1` 和 `config2`: ```bash export KUBECONFIG=~/path/to/config1:~/path/to/config2 kubectl config view --flatten > ~/.kube/config ``` - **備註**: - 實際測試,最終只會看 `KUBECONFIG` 環境變數,不會讀取 `~/.kube/config` - 必須清除 `KUBECONFIG` 環境變數,才會讀取 `~/.kube/config` `$ unset KUBECONFIG` 這樣會將兩個檔案中的 clusters、users、contexts 資訊合併成一個完整的 kubeconfig 檔案。 --- ### 2. 手動合併 kubeconfig 檔案本質上是 YAML 格式,你也可以打開各個檔案,手動將兩個檔案中的 `clusters`、`contexts`、`users` 等區塊合併到一個檔案中。 步驟如下: - **打開兩個檔案**:檢查每個檔案中 `clusters`、`contexts`、`users` 的列表。 - **合併列表**:將兩個檔案中相應的列表內容合併,注意避免重複定義相同名稱的 cluster、user 或 context。如果有重複,你可能需要修改名稱以區分不同的叢集。 - **設定 current-context**:選擇一個你常用的 context 作為預設的 `current-context`。 完成後,將合併後的 YAML 存放在 `~/.kube/config`。 例如,手動合併後的檔案可能會像這樣: ```yaml= apiVersion: v1 kind: Config clusters: - cluster: server: https://cluster1.example.com name: cluster1 - cluster: server: https://cluster2.example.com name: cluster2 contexts: - context: cluster: cluster1 user: user1 namespace: default name: context-cluster1 - context: cluster: cluster2 user: user2 namespace: default name: context-cluster2 current-context: context-cluster1 users: - name: user1 user: token: <token1> - name: user2 user: token: <token2> ``` --- ### 方法比較 - **自動合併**: - 優點:操作簡單、能夠保持來源檔案的獨立性,適合定期更新來源檔案後重新合併。 - 缺點:依賴環境變數和指令,可能在 CI/CD 腳本中更方便使用。 - **手動合併**: - 優點:可以進行更細微的調整,靈活修改命名和設定。 - 缺點:需要注意 YAML 的格式與命名衝突,較為繁瑣。 這樣就可以讓你的 kubeconfig 檔案同時包含多個 K8s 叢集的設定,方便日後透過 `kubectl config use-context` 指令切換使用不同的叢集。 <br> ### 處理 API Server 憑證與連線地址不匹配問題-Case1 - ### Question ``` $ kubectl get crd Unable to connect to the server: x509: certificate is valid for 10.96.0.1, 192.168.211.5, 192.168.211.200, 192.168.211.38, 192.168.211.89, not 127.0.0.1 ``` - ### gpt-o3-mini-high (2025/02/21) > 解決 x509 憑證錯誤問題 這個錯誤訊息代表 kubeconfig 中設定的 API server 位址(在這裡是 127.0.0.1)與伺服器憑證中允許的位址不匹配,憑證中只允許以下位址: - 10.96.0.1 - 192.168.211.5 - 192.168.211.200 - 192.168.211.38 - 192.168.211.89 當你使用 `kubectl get crd` 時,若使用了不在上述範圍內的地址(例如 127.0.0.1),就會出現 x509 憑證錯誤。 ### 原因 - **憑證驗證失敗**:當你使用 127.0.0.1 存取 API server 時,Kubernetes 會檢查伺服器回傳的憑證。若憑證的 Subject Alternative Names (SAN) 不包含 127.0.0.1,就會拋出這個錯誤。 - **kubeconfig 中的 server 設定不正確**:可能是之前用某個工具(例如 minikube)生成的 kubeconfig,內部的 server 地址與實際應存取的地址不符。 ### 解決方法 #### 1. 更新 kubeconfig 中的 server 欄位 將該 cluster 內的 server 位址修改成憑證中列出的有效位址之一,例如 `192.168.211.200`。可以使用以下命令: ```bash kubectl config set-cluster mymini --server=https://192.168.211.200:8443 ``` 這條命令會更新 kubeconfig 中名為 `mymini` 的 cluster,使其使用正確的 API server 位址。 #### 2. 直接編輯 kubeconfig 檔案 手動編輯 `~/.kube/config` 檔案,找到類似以下的區塊: ```yaml - cluster: certificate-authority-data: DATA+OMITTED server: https://127.0.0.1:8443 name: mymini ``` 將 `server` 欄位改成正確的地址: ```yaml - cluster: certificate-authority-data: DATA+OMITTED server: https://192.168.211.200:8443 name: mymini ``` 儲存檔案後,再次執行 `kubectl get crd` 應該可以正確連線。 ### 注意事項 - **憑證與 IP 的一致性**:更換 server 地址時,請確保憑證中的 IP 與實際存取的地址匹配。否則,仍會出現憑證驗證錯誤。 - **使用正確的端口**:確認 API server 使用的端口正確(例如 8443 或 6443)。 以上方法可以解決 x509 憑證錯誤問題,確保 `kubectl` 能夠正確連線到 Kubernetes API server。 <br> ### 處理 API Server 憑證與連線地址不匹配問題-Case2 - ### Question server ip 是 204.146.216.50 但 server x509 又只能是 10.96.0.1, 192.168.211.5, 192.168.211.200, 192.168.211.38, 192.168.211.89 怎麼有辦法將 server 指到目的端的內部 IP ? - ### gpt-o3-mini-high (2025/02/21) 當你遇到錯誤訊息: > Unable to connect to the server: x509: certificate is valid for 10.96.0.1, 192.168.211.5, 192.168.211.200, 192.168.211.38, 192.168.211.89, not 127.0.0.1 這表示 kubeconfig 中設定的 API server 位址與憑證中的 Subject Alternative Names (SANs) 不一致。 ### 問題描述 在你的情況中,server 的 IP 為 `204.146.216.50`,但憑證中僅包含以下 IP: - 10.96.0.1 - 192.168.211.5 - 192.168.211.200 - 192.168.211.38 - 192.168.211.89 這意味著直接使用 `204.146.216.50` 會導致憑證驗證失敗,因為該 IP 不在憑證的有效範圍內。 ### 解決方案 有幾種方法可以解決這個問題: #### 1. 更新 API server 憑證 重新生成 API server 的憑證,並在生成時將外部 IP (`204.146.216.50`) 加入憑證的 SAN 列表中。 例如,在使用 kubeadm 初始化集群時,可使用以下參數: ```bash kubeadm init --apiserver-cert-extra-sans=204.146.216.50,... ``` 這樣生成的憑證就會包含外部 IP,連線時就不會因為憑證不匹配而失敗。 #### 2. 使用憑證中允許的內部 IP 如果你從連線端能夠存取集群內部網路,則可以在 kubeconfig 中指定憑證允許的內部 IP 作為 server 地址,例如 `192.168.211.200`。 這樣可以利用現有憑證,而不需要重新生成憑證。 #### 3. 跳過憑證驗證(僅限測試環境) 作為權宜之計,你可以在 kubeconfig 中設定 `insecure-skip-tls-verify: true`,這會跳過憑證驗證。 請注意,這樣做會降低連線安全性,僅適用於測試或開發環境。 在 kubeconfig 中的設定範例如下: ```yaml clusters: - cluster: server: https://204.146.216.50:8443 insecure-skip-tls-verify: true name: mycluster ``` - 備註:經測試可行 ### 小結 - **生產環境最佳做法**:重新生成 API server 憑證,將外部 IP 加入 SAN 列表,確保憑證與連線地址一致。 - **簡易測試方案**:如果可以存取內部網,則直接使用憑證中允許的 IP;或在測試環境下暫時跳過憑證驗證。 依照你的實際需求與環境架構,選擇最適合的方法來維護 kubeconfig 與 API server 憑證,使得外部連線能夠通過驗證。 <br> {%hackmd vaaMgNRPS4KGJDSFG0ZE0w %}