在 Kubernetes 環境中,服務發現和名稱解析至關重要。本文將詳細說明如何整合外部 DNS 與 CoreDNS,以實作動態服務註冊,確保服務名稱能被正確解析。此過程涉及使用 ETCD 作為 DNS 資訊儲存函式庫,並利用 external-dns 自動更新 DNS 紀錄。我們將逐步講解安裝 Helm、佈署 ETCD、組態 CoreDNS 和 external-dns,最後透過建立 LoadBalancer 服務驗證整個流程。
整合外部 DNS 與 CoreDNS 實作動態服務註冊
在 Kubernetes 叢集中,CoreDNS 提供了叢集內部的 DNS 名稱解析服務。然而,CoreDNS 的功能不僅限於此,它還能夠提供外部名稱解析,支援任何由 CoreDNS 佈署管理的 DNS 區域。
設定 external-dns
目前我們的 CoreDNS 只解析內部叢集名稱,因此需要為新的 DNS 條目建立區域。假設 FooWidgets 希望所有應用程式都位於 foowidgets.k8s 區域,我們將使用該區域作為新的 DNS 區域。
整合 external-dns 與 CoreDNS
要提供動態服務註冊功能給叢集,最後一步是佈署並整合 external-dns 與 CoreDNS。為了組態 external-dns 和 CoreDNS 在叢集中協同工作,需要設定兩者都使用 ETCD 來管理新的 DNS 區域。由於我們的叢集使用 KinD 並預裝了 ETCD,我們將佈署一個新的 ETCD Pod,專門用於 external-dns 區域。
安裝 Helm 與佈署 ETCD
首先,需要安裝 Helm 二進位制檔案。可以使用 Helm 團隊提供的指令碼快速安裝 Helm:
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
接著,使用 Helm 建立 ETCD 叢集:
helm install etcd-dns --set customResources.createEtcdClusterCRD=true stable/etcd-operator --namespace kube-system
這個命令將佈署 ETCD Operator 並建立一個三節點的 ETCD 叢集。
#### 內容解密:
此步驟中,我們使用了 Helm 來安裝 ETCD Operator 和建立 ETCD 叢集。Helm 是 Kubernetes 的套件管理器,可以簡化應用程式的佈署和管理。ETCD Operator 可以自動化 ETCD 叢集的管理工作。
檢視 ETCD 佈署狀態
佈署完成後,可以透過檢視 kube-system 名稱空間中的 Pod 狀態來檢查 ETCD Operator 和節點的狀態:
kubectl get pods -n kube-system
成功佈署後,將看到三個 ETCD Operator Pod 和三個 ETCD 叢集 Pod。
取得 ETCD 服務 IP
佈署完成後,檢視 kube-system 名稱空間中的服務,以取得新建立的 ETCD 服務的 IP 地址:
kubectl get svc -n kube-system
找到名為 etcd-cluster-client 的服務,並記錄其 IP 地址。
#### 內容解密:
此步驟中,我們需要找到 etcd-cluster-client 服務的 IP 地址,以便在後續步驟中組態 external-dns 和 CoreDNS。
新增 ETCD 區域至 CoreDNS
external-dns 需要 CoreDNS 將區域儲存在 ETCD 伺服器上。編輯 CoreDNS 的 ConfigMap,並新增以下組態:
apiVersion: v1
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf
etcd foowidgets.k8s {
stubzones
path /skydns
endpoint http://<ETCD_SERVICE_IP>:2379
}
cache 30
loop
reload
loadbalance
}
kind: ConfigMap
將 <ETCD_SERVICE_IP> 替換為之前取得的 ETCD 服務 IP 地址。
#### 內容解密:
此步驟中,我們在 CoreDNS 的 ConfigMap 中增加了 etcd 外掛的組態,以啟用對 foowidgets.k8s 區域的支援。endpoint 欄位需要填入 ETCD 服務的 IP 地址和埠。
佈署 external-dns
使用以下命令佈署 external-dns:
ETCD_URL=$(kubectl -n kube-system get svc etcd-cluster-client -o go-template='{{ .spec.clusterIP }}')
cat external-dns.yaml | sed -E "s/<ETCD_URL>/${ETCD_URL}/" > external-dns-deployment.yaml
kubectl apply -f external-dns-deployment.yaml
或者,手動建立 external-dns-deployment.yaml 檔案,並填入正確的 ETCD 服務 IP 地址:
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: external-dns
rules:
- apiGroups: [""]
resources: ["services","endpoints","pods"]
verbs: ["get","watch","list"]
- apiGroups: ["extensions"]
resources: ["ingresses"]
verbs: ["get","watch","list"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["list"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: external-dns-viewer
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: external-dns
subjects:
- kind: ServiceAccount
name: external-dns
namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: external-dns
namespace: kube-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
namespace: kube-system
spec:
strategy:
type: Recreate
selector:
matchLabels:
app: external-dns
template:
metadata:
labels:
app: external-dns
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: registry.opensource.zalan.do/teapot/external-dns:latest
args:
- --source=service
- --provider=coredns
- --log-level=info
env:
- name: ETCD_URLS
value: http://<ETCD_SERVICE_IP>:2379
將 <ETCD_SERVICE_IP>替換為正確的 ETCD服務IP 位址。
#### 內容解密:
此步驟中,我們佈署了 external-dns,它將監控 Kubernetes 中的服務變化,並自動更新 CoreDNS 中的 DNS 紀錄。ETCD_URLS 環境變數需要填入正確的 ETCD服務 URL。
使用 external-dns 建立 LoadBalancer 服務
在 Kubernetes 中,external-dns 可以與 LoadBalancer 服務整合,實作動態 DNS 註冊。本文將介紹如何建立一個具有 external-dns 整合的 LoadBalancer 服務。
步驟 1:建立 nginx-dynamic.yaml 檔案
首先,建立一個名為 nginx-dynamic.yaml 的檔案,並新增以下內容:
apiVersion: v1
kind: Service
metadata:
annotations:
external-dns.alpha.kubernetes.io/hostname: nginx.foowidgets.k8s
name: nginx-ext-dns
namespace: default
spec:
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
run: nginx-web
type: LoadBalancer
內容解密:
external-dns.alpha.kubernetes.io/hostname註解指定了要建立的 DNS 記錄名稱,即nginx.foowidgets.k8s。name和namespace指定了服務的名稱和名稱空間。spec部分定義了服務的埠、協定和目標埠,以及選擇器和服務型別。
步驟 2:應用 nginx-dynamic.yaml 檔案
使用以下命令應用 nginx-dynamic.yaml 檔案:
kubectl apply -f nginx-dynamic.yaml
external-dns 將在約一分鐘內檢測到 DNS 更改。
步驟 3:驗證 DNS 記錄建立
使用以下命令檢查 external-dns pod 日誌:
kubectl logs -n kube-system -l app=external-dns
如果 DNS 記錄已建立,您將看到類別似以下的輸出:
time="2020-04-27T18:14:38Z" level=info msg="Add/set key /skydns/k8s/foowidgets/nginx/03ebf8d8 to Host=172.17.201.101, Text=\"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/default/nginx-lb\", TTL=0"
內容解密:
- 日誌輸出表明 external-dns 已建立了 DNS 記錄。
Host欄位顯示了分配給服務的 IP 地址。
步驟 4:測試連線
執行一個 Netshoot 容器:
kubectl run --generator=run-pod/v1 tmp-shell --rm -i --tty --image nicolaka/netshoot -- /bin/bash
在 Netshoot 容器中,使用 nslookup 命令驗證 DNS 記錄:
nslookup nginx.foowidgets.k8s
輸出應顯示 DNS 記錄已成功建立。
將 CoreDNS 與企業 DNS 整合
本文將介紹如何將 CoreDNS 與企業 DNS 服務整合。
組態主 DNS 伺服器
在 Windows DNS 主機上,建立一個條件轉發器,將 foowidgets.k8s 域的請求轉發到執行 CoreDNS pod 的主機。
測試 DNS 轉發
使用一台組態為使用 Windows DNS 伺服器的工作站,執行 nslookup 命令測試 DNS 解析:
nslookup nginx.foowidgets.k8s
輸出應顯示正確的 IP 地址。
將 Kubernetes 叢集與企業驗證整合
在大多數企業環境中,確保使用者能夠安全地與 Kubernetes 叢集互動至關重要。這意味著需要對個別使用者進行驗證,並確保他們只能存取執行工作所需的資源。Kubernetes 提供了多種驗證選項,包括 OpenID Connect(OIDC)協定和 Kubernetes 偽裝功能。
Kubernetes 如何識別使用者身份
在 Kubernetes 中,使用者並不存在於系統中,除了服務帳戶外,沒有所謂的「User」或「Group」物件。每個 API 互動都必須包含足夠的資訊,以告知 API 伺服器使用者的身份以及所屬群組。這種斷言可以根據整合驗證的方式採用不同的形式。
OIDC 驗證流程
理解 OpenID Connect:OIDC 是一種建立在 OAuth 2.0 之上的驗證協定,能夠提供安全的驗證機制。Kubernetes 可以組態為使用 OIDC 進行使用者驗證。
組態 KinD 以使用 OIDC:若要將 KinD 叢集組態為使用 OIDC,需要進行一系列設定,包括設定 OIDC 發行者 URL、使用者名稱宣告等。
偽裝組態:Kubernetes 的偽裝功能允許管理員以其他使用者的身份執行操作,這對於測試和除錯非常有用。
組態 KinD 以使用 OIDC
步驟一:建立 KinD 叢集
首先,需要使用 KinD 建立一個 Kubernetes 叢集。可以使用以下命令建立叢集:
kind create cluster --config kind-config.yaml
步驟二:組態 OIDC
接下來,需要組態 Kubernetes API 伺服器以使用 OIDC。這涉及修改 API 伺服器的組態,以包含 OIDC 發行者 URL 和其他必要的設定。
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
apiServer:
extraArgs:
oidc-issuer-url: "https://oidc.example.com"
oidc-client-id: "kubernetes"
oidc-username-claim: "email"
#### 內容解密:
此 YAML 組態片段用於定義 Kubernetes 叢集的 API 伺服器組態。其中,oidc-issuer-url 指定了 OIDC 發行者的 URL,oidc-client-id 指定了客戶端 ID,而 oidc-username-claim 指定了用於使用者名稱的宣告。
常見問題與解答
服務如何知道哪些 Pod 應該用作服務的端點?
- 答案:D. By the selector label
哪個 kubectl 命令有助於排查可能無法正常運作的服務?
- 答案:B. kubectl get ep <service name>
所有 Kubernetes 發行版都支援使用 LoadBalancer 型別的服務。
- 答案:B. False
哪種型別的負載平衡器支援所有 TCP/UDP 連線埠並接受流量,而不管封包內容如何?
- 答案:D. Layer 4
在沒有新增元件的情況下,您可以使用下列哪種服務型別來支援多種協定?
- 答案:C. NodePort, LoadBalancer, 和 ClusterIP