類型ExternalName
類型為 ExternalName 的服務將服務映射到 DNS 名稱,而不是典型的選擇器,例如 my-service 或者 cassandra。 您可以使用 spec.externalName 參數指定這些服務。
例如,以下 Service 定義將 prod 名稱空間中的 my-service 服務映射到 my.database.example.com:
apiVersion: v1 kind: Service metadata: name: my-service namespace: prod spec: type: ExternalName externalName: my.database.example.com
說明: ExternalName 接受 IPv4 地址字符串,但作為包含數字的 DNS 名稱,而不是 IP 地址。 類似於 IPv4 地址的外部名稱不能由 CoreDNS 或 ingress-nginx 解析,因為外部名稱旨在指定規范的 DNS 名稱。 要對 IP 地址進行硬編碼,請考慮使用 [headless Services](#headless-services)。
當查找主機 my-service.prod.svc.cluster.local 時,群集DNS服務返回 CNAME 記錄,其值為 my.database.example.com。 訪問 my-service 的方式與其他服務的方式相同,但主要區別在於重定向發生在 DNS 級別,而不是通過代理或轉發。 如果以后您決定將數據庫移到群集中,則可以啟動其 Pod,添加適當的選擇器或端點以及更改服務的類型。
以下文章引用: https://www.qedev.com/cloud/244937.html
ExternalName 介紹
記得很多年前大陸流行音樂剛開始流行,李春波的一首《小芳》風靡大街小巷,正處於青春懵懂期的少男,頃刻間就被它的旋律捕獲了,於是小芳就是初戀,初戀就是小芳.
后來上了大學,讀了計算機系,學到了很多基於控制台的命令,但是不知道為什么,每當我敲打 ln 命令的時候,都會想起小芳,那時我天真地認為,只要找到了小芳,我就可以找到幸福,於是我向一個情場老手討教全年級最好記的女生姓名叫什么?他想都沒想,脫口而出——“殷靜”、“史珍香”。
后來學了 k8s,知道了常用的 k8s service 類型—— ClusterIP、NodePort、LoadBalancer,唯獨對 externalName 置若罔聞,直到有一天在學習 Istio Sidecar 這種 API 資源的時候,才突然領悟了 ExternalName 這種 k8s service 類型是使用場景。
ExternalName 這種 service 類型的作用類似軟鏈或者快捷方式。下面舉一個具體的例子。

該樣例目的是讓處於 default 命名空間下的 httpd-pod 訪問到處於 nginx-ns 命名空間下的 nginx-svc,不像以往 svc-name.ns-name.svc.cluster.local 方式跨命名空間訪問的方式,這里我們使用 ExternalName 方式。
jiuxi-client.yaml

jiuxi-client-svc.yaml

關鍵點就在這個文件,該文件中指定了到 nginx-svc 的軟鏈,這么做的好處是對使用者做到了透明,讓使用者感覺就好像調用自己命名空間的服務一樣。
jiuxi-nginx.yaml

jiuxi-nginx-svc.yaml

jiuxi-ns.yaml

自此整個樣例代碼編寫完畢。
首先創建 jiuxi-ns.yaml 命名空間,然后再應用其他資源文件,如下命令所示:
kubectl apply -f jiuxi-ns.yaml
kubectl apply -f jiuxi-client.yaml
kubectl apply -f jiuxi-client-svc.yaml
kubectl apply -f jiuxi-nginx.yaml
kubectl apply -f jiuxi-nginx-svc.yaml
驗證樣例
所有 pod 都爭取運行之后,登錄 client,然后執行如下語句:
wget -q -O - http://jiuxi-client-svc
wget -q -O - http://jiuxi-nginx-svc.nginx-ns.svc.cluster.local
發現兩種方式都可以正常訪問。
擴展閱讀
K8S 最佳實踐-映射外部服務
場景 1:具有 IP 地址的集群外數據庫
其中一個常見場景是在集群外部托管自己的數據庫,例如在 Google 計算引擎實例中。如果您在 Kubernetes 內部和外部分別運行一些服務,或者需要在 Kubernetes 允許的基礎上獲得更多定制或控制,通常可采用上述這種方式。
希望未來某個時候您可以將所有服務都移入集群內,但在此之前將是“內外混用”的狀態。幸運的是,您可以使用靜態 Kubernetes 服務來緩解上述痛點。
在本例中,我使用 Cloud Launcher 創建了一個 MongoDB 服務器。由於此服務器在與 Kubernetes 集群相同的網絡(或 VPC)中創建,因此可以使用高性能的內部 IP 地址訪問。在 Google Cloud 中,這是默認設置,因此無需進行任何特殊配置。
現在我們有了 IP 地址,那么第一步就是創建服務:
kind: Service
apiVersion: v1
metadata:
name: mongo
Spec:
type: ClusterIP
ports:
– port: 27017
targetPort: 27017
您可能會注意到此服務沒有 Pod 選擇器。此操作將創建一個服務,但它不知道往哪里發送流量。這樣一來,您可以手動創建一個將從此服務接收流量的 Endpoints 對象。
kind: Endpoints
apiVersion: v1
metadata:
name: mongo
subsets:
– addresses:
– ip: 10.240.0.4
ports:
– port: 27017
您可以看到 Endpoints 手動定義了數據庫的 IP 地址,並且使用的名稱與服務名稱相同。Kubernetes 將 Endpoints 中定義的所有 IP 地址視為與常規 Kubernetes Pod 一樣。現在您可以用一個簡單的連接字符串訪問數據庫:
mongodb://mongo
> 根本不需要在代碼中使用 IP 地址!如果以后 IP 地址發生變化,您可以為端點更新 IP 地址,而應用無需進行任何更改。
場景 2:具有 URI 的遠程托管數據庫
如果您使用的是來自第三方的托管數據庫服務,它們可能會為您提供可用於連接的統一資源標識符 (URI)。如果它們為您提供 IP 地址,則可以使用場景 1 中的方法。
在本例中,我在 mLab 上托管了兩個 MongoDB 數據庫。一個是我的開發數據庫,另一個是生產數據庫。

這些數據庫的連接字符串如下所示:
mongodb://<dbuser>:<dbpassword>@ds149763.mlab.com:49763/devmongodb://<dbuser>:<dbpassword>@ds145868.mlab.com:45868/prodmLab
為您提供了動態 URI 和動態端口,您可以看到兩者都不同。我們來使用 Kubernetes 基於這些差異創建一個抽象層。在本例中,我們將連接開發數據庫。
您可以創建一個 “ExternalName” Kubernetes 服務,此服務為您提供將流量重定向到外部服務的靜態 Kubernetes 服務。此服務在內核級別執行簡單的 CNAME 重定向,因此對性能的影響非常小。
服務的 YAML 如下所示:
kind: Service
apiVersion: v1
metadata:
name: mongo
spec:
type: ExternalName
externalName: ds149763.mlab.com
現在,您可以使用更簡化的連接字符串:
mongodb://<dbuser>:<dbpassword>@mongo:<port>/dev
由於 “ExternalName” 使用 CNAME 重定向,因此無法執行端口重映射。對於使用靜態端口的服務來說,這可能不成問題,然而本例中使用的是動態端口。mLab 免費版為您提供了動態端口號,並且不允許更改。這意味着您需要對開發和生產數據庫使用其他連接字符串。
但如果您可以獲取 IP 地址,就可以執行端口重映射,關於此內容,我將在下一部分進行介紹。
場景 3:具有 URI 和端口重映射功能的遠程托管數據庫
CNAME 重定向對於每個環境均使用相同端口的服務非常有效,但如果每個環境的不同端點使用不同的端口,CNAME 重定向就略顯不足。幸運的是我們可以使用一些基本工具來解決這個問題。
第一步是從 URI 獲取 IP 地址。
對 URI 運行 nslookup、hostname 或 ping 命令即可獲取數據庫的 IP 地址。

您現在可以創建一個重新映射 mLab 端口的服務,並為此 IP 地址創建端點。
kind: Service
apiVersion: v1
metadata:
name: mongo
spec:
ports:
– port: 27017
targetPort: 49763
—
kind: Endpoints
apiVersion: v1
metadata:
name: mongo
subsets:
– addresses:
– ip: 35.188.8.12
ports:
– port: 49763
注:URI 可以使用 DNS 在多個 IP 地址之間進行負載平衡,因此,如果 IP 地址發生變化,這個方法可能會有風險!如果您通過上述命令獲取多個 IP 地址,則可以將所有這些地址都包含在 Endpoints YAML 中,並且 Kubernetes 會在所有 IP 地址之間進行流量的負載平衡。
通過這種方式,您無需指定端口即可連接到遠程數據庫。Kubernetes 服務重映射端口的過程完全透明!
mongodb://<dbuser>:<dbpassword>@mongo/dev
結論
將外部服務映射到內部服務可讓您未來靈活地將這些服務納入集群,同時最大限度地減少重構工作。即使您今天不打算將服務加入集群,以后可能也會這樣做!而且,這樣一來,您可以更輕松地管理和了解組織所使用的外部服務。
如果外部服務具有有效域名,並且您不需要重新映射端口,那么使用 “ExternalName” 服務類型將外部服務映射到內部服務十分簡便、快捷。如果您沒有域名或需要執行端口重映射,只需將 IP 地址添加到端點並使用即可。
實例
ExternalName
apiVersion: v1 kind: Service metadata: name: "baiducom" # 設置 IP 14.215.177.39和www.baidu.com 錯誤,不允許'.' spec: type: ExternalName externalName: "www.baidu.com" # 設置 IP 14.215.177.39 無效 # 所以 externalName 的意義就是為域名設置一個別名,如上 為 www.baidu.com 設置別名 baiducom,以便 pod 內容器使用 --- apiVersion: apps/v1 kind: Deployment metadata: name: busybox labels: app: busybox spec: replicas: 1 selector: matchLabels: app: busybox template: metadata: labels: app: busybox spec: containers: - name: busybox image: busybox command: ["/bin/sh", "-c", "sleep 3600"]

- 外部 IP 鏈接
ip.yaml 外部訪問:
apiVersion: v1 kind: Service metadata: name: nginx labels: run: nginx spec: type: NodePort ports: - port: 80 targetPort: 80 protocol: TCP name: http nodePort: 81 selector: run: nginx --- apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: selector: matchLabels: run: nginx replicas: 1 template: metadata: labels: run: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80
kubectl apply -f ip.yaml
創建服務 ips.yaml
apiVersion: v1 kind: Service metadata: name: nginx-ip spec: ports: - protocol: TCP port: 88 targetPort: 81 --- apiVersion: v1 kind: Endpoints metadata: name: nginx-ip subsets: - addresses: - ip: 182.254.186.198 ports: - port: 81 # IP相關的端口,可以是外部連接端口,也可以是內部容器連接端口
kubectl apply -f ips.yaml

-

-

