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 %}