主機配置規劃
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5iM2MDN3EDNkN2N1YWOyEmNzYzXxQTNwgTM4AzLcFTMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
Service概述
Kubernetes Service定義了這樣一種抽象:邏輯上的一組 Pod,一種可以通路它們的政策 —— 通常被稱為微服務。這一組 Pod 能夠被 Service 通路到,通常是通過 selector實作的。
舉例:考慮一個圖檔處理 backend,它運作了3個副本。這些副本是可互換的 —— frontend 不需要關心它們調用了哪個 backend 副本。然而組成這一組 backend 程式的 Pod 實際上可能會發生變化,frontend 用戶端不應該也沒必要知道,而且也不需要跟蹤這一組 backend 的狀态。Service 定義的抽象能夠解耦這種關聯。
Service可以提供負載均衡的能力,但是使用上存在如下限制:
- 隻能提供4層負載均衡能力,而沒有7層功能。有時我們可能需要更多的比對規則來轉發請求,這點上4層負載均衡是不支援的、
如web通路的service服務示例圖:
VIP和Service代理
在 Kubernetes 叢集中,每個 Node 運作一個 kube-proxy 程序。kube-proxy 負責為 Service 實作了一種 VIP(虛拟 IP)的形式,而不是 ExternalName 的形式。
從Kubernetes v1.0開始,已經可以使用 userspace代理模式。Kubernetes v1.1添加了 iptables 代理模式,在 Kubernetes v1.2 中kube-proxy 的 iptables 模式成為預設設定。Kubernetes v1.8添加了 ipvs 代理模式。
為什麼不使用 DNS 輪詢?
原因如下:
- DNS 實作的曆史由來已久,它不遵守記錄 TTL,并且在名稱查找到結果後會對其進行緩存。
- 有些應用程式僅執行一次 DNS 查找,并無限期地緩存結果。
- 即使應用和庫進行了适當的重新解析,DNS 記錄上的 TTL 值低或為零也可能會給 DNS 帶來高負載,進而使管理變得困難。
總之就是因為有緩存,是以不合适。
userspace代理模式
這種模式,kube-proxy 會監視 Kubernetes master 對 Service 對象和 Endpoints 對象的添加和移除。對每個 Service,它會在本地 Node 上打開一個端口(随機選擇)。任何連接配接到“代理端口”的請求,都會被代理到 Service 的backend Pods 中的某個上面(如 Endpoints 所報告的一樣)。使用哪個 backend Pod,是 kube-proxy 基于 SessionAffinity 來确定的。
最後,它配置 iptables 規則,捕獲到達該 Service 的 clusterIP(是虛拟 IP)和 Port 的請求,并重定向到代理端口,代理端口再代理請求到 backend Pod。
預設情況下,userspace模式下的kube-proxy通過循環算法選擇後端。
預設的政策是,通過 round-robin 算法來選擇 backend Pod。
iptables 代理模式
這種模式,kube-proxy 會監視 Kubernetes 控制節點對 Service 對象和 Endpoints 對象的添加和移除。對每個 Service,它會配置 iptables 規則,進而捕獲到達該 Service 的 clusterIP 和端口的請求,進而将請求重定向到 Service 的一組 backend 中的某個上面。對于每個 Endpoints 對象,它也會配置 iptables 規則,這個規則會選擇一個 backend 組合。
預設的政策是,kube-proxy 在 iptables 模式下随機選擇一個 backend。
使用 iptables 處理流量具有較低的系統開銷,因為流量由 Linux netfilter 處理,而無需在使用者空間和核心空間之間切換。這種方法也可能更可靠。
如果 kube-proxy 在 iptables模式下運作,并且所選的第一個 Pod 沒有響應,則連接配接失敗。這與userspace模式不同:在這種情況下,kube-proxy 将檢測到與第一個 Pod 的連接配接已失敗,并會自動使用其他後端 Pod 重試。
我們可以使用 Pod readiness 探測器 驗證後端 Pod 是否可以正常工作,以便 iptables 模式下的 kube-proxy 僅看到測試正常的後端。這樣做意味着可以避免将流量通過 kube-proxy 發送到已知已失敗的Pod。
IPVS 代理模式
在 ipvs 模式下,kube-proxy監視Kubernetes服務(Service)和端點(Endpoints),調用 netlink 接口相應地建立 IPVS 規則, 并定期将 IPVS 規則與 Kubernetes服務(Service)和端點(Endpoints)同步。該控制循環可確定 IPVS 狀态與所需狀态比對。通路服務(Service)時,IPVS 将流量定向到後端Pod之一。
IPVS代理模式基于類似于 iptables 模式的 netfilter 挂鈎函數,但是使用哈希表作為基礎資料結構,并且在核心空間中工作。這意味着,與 iptables 模式下的 kube-proxy 相比,IPVS 模式下的 kube-proxy 重定向通信的延遲要短,并且在同步代理規則時具有更好的性能。與其他代理模式相比,IPVS 模式還支援更高的網絡流量吞吐量。
IPVS提供了更多選項來平衡後端Pod的流量。這些是:
- rr: round-robin
- lc: least connection (smallest number of open connections)
- dh: destination hashing
- sh: source hashing
- sed: shortest expected delay
- nq: never queue
注意:要在 IPVS 模式下運作 kube-proxy,必須在啟動 kube-proxy 之前使 IPVS Linux 在節點上可用。當 kube-proxy 以 IPVS 代理模式啟動時,它将驗證 IPVS 核心子產品是否可用。如果未檢測到 IPVS 核心子產品,則 kube-proxy 将退回到以 iptables 代理模式運作。
Service服務類型
Kubernetes 中Service有以下4中類型:
- ClusterIP:預設類型,自動配置設定一個僅Cluster内部可以通路的虛拟IP
- NodePort:通過每個 Node 上的 IP 和靜态端口(NodePort)暴露服務。以ClusterIP為基礎,NodePort 服務會路由到 ClusterIP 服務。通過請求
,可以從叢集的外部通路一個叢集内部的 NodePort 服務。<NodeIP>:<NodePort>
- LoadBalancer:使用雲提供商的負載均衡器,可以向外部暴露服務。外部的負載均衡器可以路由到 NodePort 服務和 ClusterIP 服務。
- ExternalName:通過傳回 CNAME 和它的值,可以将服務映射到 externalName 字段的内容(例如,foo.bar.example.com)。沒有任何類型代理被建立。
需要注意的是:Service 能夠将一個接收 port 映射到任意的 targetPort。預設情況下,targetPort 将被設定為與 port 字段相同的值。
Service域名格式:
$(service name).$(namespace).svc.cluster.local
,其中 cluster.local 為指定的叢集的域名
Deployment的yaml資訊
yaml檔案
[root@k8s-master service]# pwd
/root/k8s_practice/service
[root@k8s-master service]# cat myapp-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: myapp
release: v1
template:
metadata:
labels:
app: myapp
release: v1
env: test
spec:
containers:
- name: myapp
image: registry.cn-beijing.aliyuncs.com/google_registry/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
啟動Deployment并檢視狀态
[root@k8s-master service]# kubectl apply -f myapp-deploy.yaml
deployment.apps/myapp-deploy created
[root@k8s-master service]#
[root@k8s-master service]# kubectl get deploy -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
myapp-deploy 3/3 3 3 31h myapp registry.cn-beijing.aliyuncs.com/google_registry/myapp:v1 app=myapp,release=v1
[root@k8s-master service]#
[root@k8s-master service]# kubectl get rs -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
myapp-deploy-5695bb5658 3 3 3 31h myapp registry.cn-beijing.aliyuncs.com/google_registry/myapp:v1 app=myapp,pod-template-hash=5695bb5658,release=v1
[root@k8s-master service]#
[root@k8s-master service]# kubectl get pod -o wide --show-labels
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
myapp-deploy-5695bb5658-2866m 1/1 Running 2 31h 10.244.2.116 k8s-node02 <none> <none> app=myapp,env=test,pod-template-hash=5695bb5658,release=v1
myapp-deploy-5695bb5658-dcfw7 1/1 Running 2 31h 10.244.4.105 k8s-node01 <none> <none> app=myapp,env=test,pod-template-hash=5695bb5658,release=v1
myapp-deploy-5695bb5658-n2b5w 1/1 Running 2 31h 10.244.2.115 k8s-node02 <none> <none> app=myapp,env=test,pod-template-hash=5695bb5658,release=v1
curl通路
[root@k8s-master service]# curl 10.244.2.116
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master service]#
[root@k8s-master service]# curl 10.244.2.116/hostname.html
myapp-deploy-5695bb5658-2866m
[root@k8s-master service]#
[root@k8s-master service]# curl 10.244.4.105
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master service]#
[root@k8s-master service]# curl 10.244.4.105/hostname.html
myapp-deploy-5695bb5658-dcfw7
[root@k8s-master service]#
[root@k8s-master service]# curl 10.244.2.115
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master service]#
[root@k8s-master service]# curl 10.244.2.115/hostname.html
myapp-deploy-5695bb5658-n2b5w
ClusterIP類型示例
yaml檔案
[root@k8s-master service]# pwd
/root/k8s_practice/service
[root@k8s-master service]# cat myapp-svc-ClusterIP.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-clusterip
namespace: default
spec:
type: ClusterIP # 可以不寫,為預設類型
selector:
app: myapp
release: v1
ports:
- name: http
port: 80
targetPort: 80
啟動Service并檢視狀态
[root@k8s-master service]# kubectl apply -f myapp-svc-ClusterIP.yaml
service/myapp-clusterip created
[root@k8s-master service]#
[root@k8s-master service]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 22d <none>
myapp-clusterip ClusterIP 10.106.66.120 <none> 80/TCP 15s app=myapp,release=v1
檢視pod資訊
[root@k8s-master service]# kubectl get pod -o wide --show-labels
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
myapp-deploy-5695bb5658-2866m 1/1 Running 2 31h 10.244.2.116 k8s-node02 <none> <none> app=myapp,env=test,pod-template-hash=5695bb5658,release=v1
myapp-deploy-5695bb5658-dcfw7 1/1 Running 2 31h 10.244.4.105 k8s-node01 <none> <none> app=myapp,env=test,pod-template-hash=5695bb5658,release=v1
myapp-deploy-5695bb5658-n2b5w 1/1 Running 2 31h 10.244.2.115 k8s-node02 <none> <none> app=myapp,env=test,pod-template-hash=5695bb5658,release=v1
檢視ipvs資訊
[root@k8s-master service]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
………………
TCP 10.106.66.120:80 rr
-> 10.244.2.115:80 Masq 1 0 0
-> 10.244.2.116:80 Masq 1 0 0
-> 10.244.4.105:80 Masq 1 0 0
curl通路
[root@k8s-master service]# curl 10.106.66.120
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master service]#
[root@k8s-master service]# curl 10.106.66.120/hostname.html
myapp-deploy-5695bb5658-2866m
[root@k8s-master service]#
[root@k8s-master service]# curl 10.106.66.120/hostname.html
myapp-deploy-5695bb5658-n2b5w
[root@k8s-master service]#
[root@k8s-master service]# curl 10.106.66.120/hostname.html
myapp-deploy-5695bb5658-dcfw7
[root@k8s-master service]#
[root@k8s-master service]# curl 10.106.66.120/hostname.html
myapp-deploy-5695bb5658-2866m
Headless Services
有時不需要或不想要負載均衡,以及單獨的 Service IP。遇到這種情況,可以通過指定 Cluster IP(spec.clusterIP)的值為 “None” 來建立 Headless Service。
這對headless Service 并不會配置設定 Cluster IP,kube-proxy 不會處理它們,而且平台也不會為它們進行負載均衡和路由。
使用場景
- 第一種:自主選擇權,有時候client想自己來決定使用哪個Real Server,可以通過查詢DNS來擷取Real Server的資訊。
- 第二種:Headless Services還有一個用處(PS:也就是我們需要的那個特性)。Headless Service對應的每一個Endpoints,即每一個Pod,都會有對應的DNS域名;這樣Pod之間就可以互相通路。【結合statefulset有狀态服務使用,如Web、MySQL叢集】
示例
yaml檔案
[root@k8s-master service]# pwd
/root/k8s_practice/service
[root@k8s-master service]# cat myapp-svc-headless.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-headless
namespace: default
spec:
selector:
app: myapp
release: v1
clusterIP: "None"
ports:
- port: 80
targetPort: 80
啟動Service并檢視狀态和詳情
[root@k8s-master service]# kubectl apply -f myapp-svc-headless.yaml
service/myapp-headless created
[root@k8s-master service]#
[root@k8s-master service]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 22d <none>
myapp-headless ClusterIP None <none> 80/TCP 6s app=myapp,release=v1
[root@k8s-master service]#
[root@k8s-master service]# kubectl describe svc/myapp-headless
Name: myapp-headless
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"myapp-headless","namespace":"default"},"spec":{"clusterIP":"None"...
Selector: app=myapp,release=v1
Type: ClusterIP
IP: None
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.2.115:80,10.244.2.116:80,10.244.4.105:80 # 後端的Pod資訊
Session Affinity: None
Events: <none>
service隻要建立成功就會寫入到coredns。我們得到coredns IP的指令如下:
[root@k8s-master service]# kubectl get pod -o wide -A | grep 'coredns'
kube-system coredns-6955765f44-c9zfh 1/1 Running 29 22d 10.244.0.62 k8s-master <none> <none>
kube-system coredns-6955765f44-lrz5q 1/1 Running 29 22d 10.244.0.61 k8s-master <none> <none>
在主控端安裝nslookup、dig指令安裝
yum install -y bind-utils
coredns記錄資訊如下
# 其中 10.244.0.61 為 coredns IP
# myapp-headless.default.svc.cluster.local 為Headless Service域名。格式為:$(service name).$(namespace).svc.cluster.local,其中 cluster.local 指定的叢集的域名
[root@k8s-master service]# nslookup myapp-headless.default.svc.cluster.local 10.244.0.61
Server: 10.244.0.61
Address: 10.244.0.61#53
Name: myapp-headless.default.svc.cluster.local
Address: 10.244.2.116
Name: myapp-headless.default.svc.cluster.local
Address: 10.244.4.105
Name: myapp-headless.default.svc.cluster.local
Address: 10.244.2.115
[root@k8s-master service]#
### 或使用如下指令
[root@k8s-master service]# dig -t A myapp-headless.default.svc.cluster.local. @10.244.0.61
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-16.P2.el7_8.6 <<>> -t A myapp-headless.default.svc.cluster.local. @10.244.0.61
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7089
;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;myapp-headless.default.svc.cluster.local. IN A
;; ANSWER SECTION:
myapp-headless.default.svc.cluster.local. 14 IN A 10.244.2.116
myapp-headless.default.svc.cluster.local. 14 IN A 10.244.4.105
myapp-headless.default.svc.cluster.local. 14 IN A 10.244.2.115
;; Query time: 0 msec
;; SERVER: 10.244.0.61#53(10.244.0.61)
;; WHEN: Wed Jun 03 22:34:46 CST 2020
;; MSG SIZE rcvd: 237
NodePort類型示例
如果将 type 字段設定為 NodePort,則 Kubernetes 控制層面将在 --service-node-port-range 标志指定的範圍内配置設定端口(預設值:30000-32767)。
yaml檔案
[root@k8s-master service]# pwd
/root/k8s_practice/service
[root@k8s-master service]# cat myapp-svc-NodePort.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-nodeport
namespace: default
spec:
type: NodePort
selector:
app: myapp
release: v1
ports:
- name: http
# 預設情況下,為了友善起見,`targetPort` 被設定為與 `port` 字段相同的值。
port: 80 # Service對外提供服務端口
targetPort: 80 # 請求轉發後端Pod使用的端口
nodePort: 31682 # 可選字段,預設情況下,為了友善起見,Kubernetes 控制層面會從某個範圍内配置設定一個端口号(預設:30000-32767)
啟動Service并檢視狀态
[root@k8s-master service]# kubectl apply -f myapp-svc-NodePort.yaml
service/myapp-nodeport created
[root@k8s-master service]#
[root@k8s-master service]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 22d <none>
myapp-nodeport NodePort 10.99.50.81 <none> 80:31682/TCP 6s app=myapp,release=v1
由上可見,類型變為了NodePort
檢視ipvs資訊
[root@k8s-master service]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
………………
TCP 10.99.50.81:80 rr
-> 10.244.2.115:80 Masq 1 0 0
-> 10.244.2.116:80 Masq 1 0 0
-> 10.244.4.105:80 Masq 1 0 0
端口檢視,可見在本地主控端監聽了相應的端口(備注:叢集所有機器都監聽了該端口)
# 叢集所有機器都可以執行檢視
[root@k8s-master service]# netstat -lntp | grep '31682'
tcp6 0 0 :::31682 :::* LISTEN 3961/kube-proxy
curl通過ClusterIP通路
# 通過ClusterIP通路
[root@k8s-master service]# curl 10.99.50.81
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master service]#
[root@k8s-master service]# curl 10.99.50.81/hostname.html
myapp-deploy-5695bb5658-2866m
[root@k8s-master service]#
[root@k8s-master service]# curl 10.99.50.81/hostname.html
myapp-deploy-5695bb5658-n2b5w
[root@k8s-master service]#
[root@k8s-master service]# curl 10.99.50.81/hostname.html
myapp-deploy-5695bb5658-dcfw7
curl通過節點IP通路
# 通過叢集節點IP通路
[root@k8s-master service]# curl 172.16.1.110:31682
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master service]#
[root@k8s-master service]# curl 172.16.1.110:31682/hostname.html
myapp-deploy-5695bb5658-2866m
[root@k8s-master service]#
[root@k8s-master service]# curl 172.16.1.110:31682/hostname.html
myapp-deploy-5695bb5658-n2b5w
[root@k8s-master service]#
[root@k8s-master service]# curl 172.16.1.110:31682/hostname.html
myapp-deploy-5695bb5658-dcfw7
# 通路叢集其他節點。每台機器都有LVS,和相關排程
[root@k8s-master service]# curl 172.16.1.111:31682/hostname.html
myapp-deploy-5695bb5658-dcfw7
[root@k8s-master service]#
[root@k8s-master service]# curl 172.16.1.112:31682/hostname.html
myapp-deploy-5695bb5658-dcfw7
通路日志檢視
kubectl logs -f svc/myapp-nodeport
LoadBalancer類型示例
需要相關雲廠商服務支援,這裡就不表述了。
ExternalName類型示例
這種類型的Service通過傳回CNAME和它的值,可以将服務映射到externalName字段的内容(例如:my.k8s.example.com;可以實作跨namespace名稱空間通路)。ExternalName Service是Service的特例,它沒有selector,也沒有定義任何的端口和Endpoint。相反的,對于運作在叢集外部的服務,它通過傳回該外部服務的别名這種方式提供服務。
[root@k8s-master service]# pwd
/root/k8s_practice/service
[root@k8s-master service]# cat myapp-svc-ExternalName.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-externalname
namespace: default
spec:
type: ExternalName
externalName: my.k8s.example.com
啟動Service并檢視狀态
[root@k8s-master service]# kubectl apply -f myapp-svc-ExternalName.yaml
service/myapp-externalname created
[root@k8s-master service]#
[root@k8s-master service]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 21d <none>
myapp-externalname ExternalName <none> my.k8s.example.com <none> 21s <none>
由上可見,類型變為了ExternalName
主控端dig指令安裝
yum install -y bind-utils
coredns記錄資訊如下
# 其中 10.244.0.61 為 coredns IP
# myapp-externalname.default.svc.cluster.local 為Service域名。格式為:$(service name).$(namespace).svc.cluster.local,其中 cluster.local 指定的叢集的域名
##### 通過 nslookup 通路
[root@k8s-master service]# nslookup myapp-externalname.default.svc.cluster.local 10.244.0.61
Server: 10.244.0.61
Address: 10.244.0.61#53
myapp-externalname.default.svc.cluster.local canonical name = my.k8s.example.com.
** server can't find my.k8s.example.com: NXDOMAIN
[root@k8s-master service]#
##### 通過 dig 通路
[root@k8s-master service]# dig -t A myapp-externalname.default.svc.cluster.local. @10.244.0.61
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-16.P2.el7_8.6 <<>> -t A myapp-externalname.default.svc.cluster.local. @10.244.0.61
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39541
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;myapp-externalname.default.svc.cluster.local. IN A
;; ANSWER SECTION:
myapp-externalname.default.svc.cluster.local. 30 IN CNAME my.k8s.example.com.
;; Query time: 2072 msec
;; SERVER: 10.244.0.61#53(10.244.0.61)
;; WHEN: Wed Jun 03 23:15:47 CST 2020
;; MSG SIZE rcvd: 149
ExternalIP示例
如果外部的 IP 路由到叢集中一個或多個 Node 上,Kubernetes Service 會被暴露給這些 externalIPs。通過外部 IP(作為目的 IP 位址)進入到叢集,打到 Service 端口上的流量,将會被路由到 Service 的 Endpoint 上。
externalIPs 不會被 Kubernetes 管理,它屬于叢集管理者的職責範疇。
根據 Service 的規定,externalIPs 可以同任意的 ServiceType 來一起指定。在下面的例子中,my-service 可以在【模拟外網IP】“10.0.0.240”(externalIP:port) 上被用戶端通路。
yaml檔案
[root@k8s-master service]# pwd
/root/k8s_practice/service
[root@k8s-master service]# cat myapp-svc-externalIP.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-externalip
namespace: default
spec:
selector:
app: myapp
release: v1
ports:
- name: http
port: 80
targetPort: 80
externalIPs:
- 10.0.0.240
啟動Service并檢視狀态
[root@k8s-master service]# kubectl apply -f myapp-svc-externalIP.yaml
service/myapp-externalip created
[root@k8s-master service]#
[root@k8s-master service]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 22d <none>
myapp-externalip ClusterIP 10.107.186.167 10.0.0.240 80/TCP 8s app=myapp,release=v1
檢視ipvs資訊
[root@k8s-master service]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
………………
TCP 10.107.186.167:80 rr
-> 10.244.2.115:80 Masq 1 0 0
-> 10.244.2.116:80 Masq 1 0 0
-> 10.244.4.105:80 Masq 1 0 0
………………
TCP 10.0.0.240:80 rr
-> 10.244.2.115:80 Masq 1 0 0
-> 10.244.2.116:80 Masq 1 0 0
-> 10.244.4.105:80 Masq 1 0 0
curl通路,通過ClusterIP
[root@k8s-master service]# curl 10.107.186.167
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master service]#
[root@k8s-master service]# curl 10.107.186.167/hostname.html
myapp-deploy-5695bb5658-n2b5w
[root@k8s-master service]#
[root@k8s-master service]# curl 10.107.186.167/hostname.html
myapp-deploy-5695bb5658-2866m
[root@k8s-master service]#
[root@k8s-master service]# curl 10.107.186.167/hostname.html
myapp-deploy-5695bb5658-dcfw7
curl通路,通過ExternalIP
[root@k8s-master service]# curl 10.0.0.240
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master service]#
[root@k8s-master service]# curl 10.0.0.240/hostname.html
myapp-deploy-5695bb5658-2866m
[root@k8s-master service]#
[root@k8s-master service]# curl 10.0.0.240/hostname.html
myapp-deploy-5695bb5658-dcfw7
[root@k8s-master service]#
[root@k8s-master service]# curl 10.0.0.240/hostname.html
myapp-deploy-5695bb5658-n2b5w