操作場景
負載均衡( LoadBalancer )可以通過彈性負載均衡從公網訪問到工作負載,與彈性IP方式相比提供了高可靠的保障,一般用于系統中需要暴露到公網的服務。
負載均衡訪問方式由公網彈性負載均衡服務地址以及設置的訪問端口組成,例如“10.117.117.117:80”。
在訪問時從ELB過來的流量會先訪問到節點,然后通過Service轉發到Pod。
圖 負載均衡( LoadBalancer )

在使用CCE Turbo集群 + 獨享型ELB實例時,支持ELB直通Pod,使部署在容器中的業務時延降低、性能無損耗。
從集群外部訪問時,從ELB直接轉發到Pod;集群內部訪問可通過Service轉發到Pod。
圖 ELB直通容器

約束與限制
- CCE中的負載均衡 ( LoadBalancer )訪問類型使用彈性負載均衡 ELB提供網絡訪問,存在如下產品約束:
- 自動創建的ELB實例建議不要被其他資源使用,否則會在刪除時被占用,導致資源殘留。
- 1.15及之前版本集群使用的ELB實例請不要修改監聽器名稱,否則可能導致無法正常訪問。
- 創建service后,如果服務親和從集群級別切換為節點級別,連接跟蹤表將不會被清理,建議用戶創建service后不要修改服務親和屬性,如需修改請重新創建service。
- 當服務親和設置為節點級別(即externalTrafficPolicy為local)時,集群內部可能使用ELB地址訪問不通,具體情況請參見集群內使用ELB地址無法訪問Service說明。
- l CCE Turbo集群僅支持集群級別服務親和。
- 獨享型ELB僅支持1.17及以上集群。
- 獨享型ELB規格必須支持網絡型(TCP/UDP),且網絡類型必須支持私網(有私有IP地址)。如果需要Service支持HTTP,則獨享型ELB規格需要為網絡型(TCP/UDP)和應用型(HTTP/HTTPS)。
- 使用控制臺創建LoadBalancer類型Service時會自動生成一個節點端口(nodeport),端口號隨機。使用kubectl創建LoadBalancer類型Service時,如不指定節點端口,也會隨機生成一個節點端口,端口號隨機。
- 使用CCE集群時,如果LoadBalancer類型Service的服務親和類型為集群級別(cluster),當請求進入到集群時,會使用SNAT分發到各個節點的節點端口(nodeport),不能超過節點可用的nodeport數量,而服務親和為節點級別(local)則無此約束。使用CCE Turbo集群時,如果是使用共享型ELB依然有此約束,而獨享型ELB無此約束,建議使用CCE Turbo時配合使用獨享型ELB。
- 集群服務轉發模式為IPVS時,不支持配置節點的IP作為Service的externalIP,會導致節點不可用。
- IPVS模式集群下,Ingress和Service使用相同ELB實例時,無法在集群內的節點和容器中訪問Ingress,因為kube-proxy會在ipvs-0的網橋上掛載LB類型的Service地址,Ingress對接的ELB的流量會被ipvs-0網橋劫持。建議Ingress和Service使用不同ELB實例。
創建LoadBalancer類型Service
步驟 1 登錄CCE控制臺,單擊集群名稱進入集群。
步驟 2 在左側導航欄中選擇“服務發現”,在右上角單擊“創建服務”。
步驟 3 設置參數。
- Service名稱: 自定義服務名稱,可與工作負載名稱保持一致。
- 訪問類型 :選擇“負載均衡 LoadBalancer”。
- 命名空間: 工作負載所在命名空間。
- 服務親和: 詳情請參見externalTrafficPolicy(服務親和)。
- 集群級別:集群下所有節點的IP+訪問端口均可以訪問到此服務關聯的負載,服務訪問會因路由跳轉導致一定性能損失,且無法獲取到客戶端源IP。
- 節點級別:只有通過負載所在節點的IP+訪問端口才可以訪問此服務關聯的負載,服務訪問沒有因路由跳轉導致的性能損失,且可以獲取到客戶端源IP。
- 選擇器: 添加標簽,Service根據標簽選擇Pod,填寫后單擊“添加”。也可以引用已有工作負載的標簽,單擊“引用負載標簽”,在彈出的窗口中選擇負載,然后單擊“確定”。
- IPv6: 默認不開啟,開啟后服務的集群內IP地址(ClusterIP)變為IPv6地址。該功能僅在1.15及以上版本的集群創建時開啟了IPv6功能才會顯示。
- 負載均衡器:
選擇對接的ELB實例,僅支持與集群在同一個VPC下的ELB實例。如果沒有可選的ELB實例,請單擊“創建負載均衡器”跳轉到ELB控制臺創建。
CCE控制臺支持自動創建ELB實例,在下拉框選擇自動創建,填寫ELB實例名稱、是否公網訪問(將創建 5 Mbit/s 帶寬的彈性公網 IP。默認按照流量計費),獨享型ELB實例還需選擇可用區、子網和規格。當前僅支持自動創建網絡型(TCP/UDP)獨享型ELB實例。
您可以單擊“編輯”配置ELB實例的參數,在彈出窗口中配置ELB實例的參數。
分配策略:可選擇加權輪詢算法、加權最少連接或源IP算法。
說明
加權輪詢算法:根據后端服務器的權重,按順序依次將請求分發給不同的服務器。它用相應的權重表示服務器的處理性能,按照權重的高低以及輪詢方式將請求分配給各服務器,相同權重的服務器處理相同數目的連接數。常用于短連接服務,例如HTTP等服務。
加權最少連接:最少連接是通過當前活躍的連接數來估計服務器負載情況的一種動態調度算法。加權最少連接就是在最少連接數的基礎上,根據服務器的不同處理能力,給每個服務器分配不同的權重,使其能夠接受相應權值數的服務請求。常用于長連接服務,例如數據庫連接等服務。
源IP算法:將請求的源IP地址進行Hash運算,得到一個具體的數值,同時對后端服務器進行編號,按照運算結果將請求分發到對應編號的服務器上。這可以使得對不同源IP的訪問進行負載分發,同時使得同一個客戶端IP的請求始終被派發至某特定的服務器。該方式適合負載均衡無cookie功能的TCP協議。
會話保持類型:默認不啟用,可選擇“源IP地址”。負載均衡監聽是基于IP地址的會話保持,即來自同一IP地址的訪問請求轉發到同一臺后端服務器上。
健康檢查:默認不啟用。此處健康檢查是設置負載均衡的健康檢查配置。當端口配置協議為TCP時,支持TCP和HTTP協議,當端口配置協議為UDP時,支持UDP協議。健康檢查默認使用業務端口(Service的NodePort和容器端口)作為健康檢查的端口;您也可以重新指定端口用于健康檢查,重新制定端口會為服務增加一個名為cce-healthz的服務端口配置。
- 端口配置:
- 協議:請根據業務的協議類型選擇。
- 服務端口:Service使用的端口,端口范圍為1-65535。
- 容器端口:工作負載程序實際監聽的端口,需用戶確定。例如nginx默認使用80端口。
步驟 4 單擊“確定”,創建Service。
ELB轉發說明
LoadBalancer類型Service創建完后,可以在ELB控制臺查看ELB實例的監聽器轉發規則,如下所示。
圖 ELB轉發說明

可以看到這個ELB實例創建了一個監聽器,其后端服務器地址是Pod的IP地址,業務端口是容器端口。這是因為Pod使用了ENI或Sub-ENI,ELB會直通Pod,當有流量通過ELB請求時,會直接轉發給Pod,從而訪問到Pod,這跟操作場景中所述是一致的。
ELB直通容器場景(CCE Turbo + 獨享型ELB實例)下,LoadBalancer類型Service創建完后,可以在ELB控制臺查看ELB實例的監聽器轉發規則,如下所示。
圖 ELB轉發說明

Service使用HTTP
說明
?Service使用HTTP僅v1.19.16及以上版本集群支持。
CCE控制臺當前僅支持自動創建4層獨享型ELB實例,此種情況下無法使用HTTP能力,在控制臺創建Service使用HTTP時請選擇對接已有獨享型ELB實例。
請勿將Ingress與使用HTTP的Service對接同一個ELB下的同一個監聽器,否則將產生端口沖突。
Service支持使用ELB的7層能力,共享型和獨享型ELB都支持對接。
獨享型ELB實例有如下限制:
- 對接已有的獨享型ELB實例,需要 獨享型ELB實例同時支持4層和7層的flavor ,否則會功能不可用。
- 使用自動創建的ELB實例,注意 同時使用獨享型ELB實例的4層和7層能力 ,需要在kubernetes.io/elb.autocreate的annotation中指定4層和7層flavor。
使用ELB的7層能力時,需要添加如下annotation
- kubernetes.io/elb.protocol-port : "https:443,http:80"
protocol-port的取值需要和service的spec.ports字段中的端口對應,格式為protocol:port,port中的端口會匹配service.spec.ports中端口,并將該端口發布成對應的protocol協議。
- kubernetes.io/elb.cert-id : "17e3b4f4bc40471c86741dc3aa211379"
cert-id內容為ELB證書管理的證書ID,當protocol-port指定了https協議,ELB監聽器的證書會設置為cert-id證書,當發布多個HTTPS的服務,會使用同一份證書。
配置示例如下,其中spec.ports中兩個端口與kubernetes.io/elb.protocol-port中對應,443端口、80端口分別發布成HTTPS、HTTP協議。
apiVersion: v1
kind: Service
metadata:
annotations:
kubernetes.io/elb.autocreate: '
{
"type": "public",
"bandwidth_name": "cce-bandwidth-1634816602057",
"bandwidth_chargemode": "bandwidth",
"bandwidth_size": 5,
"bandwidth_sharetype": "PER",
"eip_type": "5_bgp",
"available_zone": [
"cn-north-4b"
],
"l7_flavor_name": "L7_flavor.elb.s2.small",
"l4_flavor_name": "L4_flavor.elb.s1.medium"
}'
kubernetes.io/elb.class: performance
kubernetes.io/elb.protocol-port: "https:443,http:80"
kubernetes.io/elb.cert-id: "17e3b4f4bc40471c86741dc3aa211379"
labels:
app: nginx
name: test
name: test
namespace: default
spec:
ports:
- name: cce-service-0
port: 443
protocol: TCP
targetPort: 80
- name: cce-service-1
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
version: v1
sessionAffinity: None
type: LoadBalancer
使用上面的示例創建Service,在新建的ELB實例中可以看到創建了443端口和80端口的監聽器。

集群內使用ELB地址無法訪問Service說明
當LoadBalancer Service設置了服務親和為節點級別,即externalTrafficPolicy取值為Local時,在使用中可能會碰到從集群內部(節點上或容器中)使用ELB地址訪問不通的情況,回顯類似如下內容:
upstream connect error or disconnect/reset before headers. reset reason: connection failure
這是由于Kubernetes在創建LoadBalancer Service時,kube-proxy會把ELB的訪問地址作為External-IP添加到iptables或IPVS中。如果客戶端從集群內部發起訪問ELB地址的請求,該地址會被認為是服務的External-IP,被kube-proxy直接轉發,而不再經過集群外部的ELB。
當externalTrafficPolicy的取值為Local時,在不同容器網絡模型和服務轉發模式下,情況會有所不同,詳情如下:
Server Client 容器隧道集群(IPVS) VPC集群(IPVS) 容器隧道集群(iptables) VPC集群(iptables) 節點訪問類型Service 同節點 OK,Pod容器所在節點通,其他不通 OK,訪問Pod容器所在節點通 OK,訪問Pod容器所在節點通 OK,訪問Pod容器所在節點通 跨節點 OK,Pod容器所在節點通,其他不通 OK,訪問Pod容器所在節點通 OK,訪問Pod容器所在節點通,訪問本節點IP+訪問端口通;其他不通 OK,訪問Pod容器所在節點通,訪問本節點IP+訪問端口通;其他不通 同節點容器 OK,Pod容器所在節點通,其他不通 OK,訪問Pod容器所在節點不通 OK,訪問Pod容器所在節點通 OK,訪問Pod容器所在節點不通 跨節點容器 OK,Pod容器所在節點通,其他不通 OK,訪問Pod容器所在節點通 OK,訪問Pod容器所在節點通 OK,訪問Pod容器所在節點通 獨享型負載均衡類型Service 同節點 公網通,私網不通 公網通,私網不通 公網通,私網不通 公網通,私網不通 同節點容器 公網通,私網不通 公網通,私網不通 公網通,私網不通 公網通,私網不通 nginx-ingress插件的service為Local級別獨享型 同節點 公網通,私網不通 公網通,私網不通 公網通,私網不通 公網通,私網不通 同節點容器 公網通,私網不通 公網通,私網不通 公網通,私網不通 公網通,私網不通
-
( 推薦 )在集群內部訪問使用Service的ClusterIP或服務域名訪問。
-
將Service的externalTrafficPolicy設置為Cluster,即集群級別服務親和。不過需要注意這會影響源地址保持。
apiVersion: v1 kind: Service metadata: annotations: kubernetes.io/elb.class: union kubernetes.io/elb.autocreate: '{"type":"public","bandwidth_name":"cce-bandwidth","bandwidth_chargemode":"bandwidth","bandwidth_size":5,"bandwidth_sharetype":"PER","eip_type":"5_bgp","name":"james"}' labels: app: nginx name: nginx spec: externalTrafficPolicy: Cluster ports: - name: service0 port: 80 protocol: TCP targetPort: 80 selector: app: nginx type: LoadBalancer -
使用Service的pass-through特性,使用ELB地址訪問時繞過kube-proxy,先訪問ELB,經過ELB再訪問到負載。
說明獨享型負載均衡配置pass-through后,在工作負載同節點和同節點容器內無法通過Service訪問。 -
1.15及以下老版本集群暫不支持該能力。
-
IPVS網絡模式下,對接同一個ELB的Service需保持pass-through設置情況一致。
apiVersion: v1
kind: Service
metadata:
annotations:
kubernetes.io/elb.pass-through: "true"
kubernetes.io/elb.class: union
kubernetes.io/elb.autocreate: '{"type":"public","bandwidth_name":"cce-bandwidth","bandwidth_chargemode":"bandwidth","bandwidth_size":5,"bandwidth_sharetype":"PER","eip_type":"5_bgp","name":"james"}'
labels:
app: nginx
name: nginx
spec:
externalTrafficPolicy: Local
ports:
- name: service0
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
type: LoadBalancer