原文連接html
Service能夠爲一組具備相同功能的容器應用提供一個統一的入口地址,而且將請求負載分發到後端的各個容器應用上。前端
Service的存在主要爲了解決 客戶端沒法肯定爲它提供服務的Pod的地址
的問題。node
可能因爲一些問題(Pod調度、異常等),該Pod從該節點被驅逐到其餘節點上,此時Pod的IP可能會變; 或者因爲Pod的水平伸縮,多出來或者少幾個提供一樣服務的Pod。nginx
此時須要一箇中間層轉發客戶端的請求,爲客戶端提供穩定的服務。 同時該中間層也能夠作負載均衡、服務暴露等工做。git
Service在配置過程當中,會要求配置一個Pod選擇規則。經過該規則找到提供服務的Pod列表。 而後客戶端不會直接訪問這些Pod,而是經過Service來訪問這些Pod。github
例如客戶端要訪問前端,前端要訪問後端。web
外部客戶端不關心前端Pod數量,而直接鏈接到前端服務上,由前端服務選擇一個Pod來提供服務。 前端服務也不關心後端Pod數量,而直接鏈接到後端服務商,由後端服務選擇一個Pod來提供服務。 在此期間,不管是Pod變動、遷移,上游都不須要關心。json
經過Service的結構能夠清晰地瞭解Service完整的配置內容。後端
更多說明能夠經過kubernetes.io/docs/concep…查看。api
列出經常使用的Service配置結構。
type Service struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` // Service的定義 Spec ServiceSpec `json:"spec,omitempty"` // Service最近的狀態,由系統維護。只讀。 Status ServiceStatus `json:"status,omitempty"` } type ServiceSpec struct { // 服務暴露端口配置列表 Ports []ServicePort `json:"ports,omitempty"` // 服務的路由配置 // 使用該字段配置和Pod的Label配置進行匹配 // 若是該字段爲空或者未定義,會假設有一個外部的Endpoints // 只能在Type字段爲ClusterIP、NodePort和LoadBalancer時生效,在Type是ExternalName時被忽略 Selector map[string]string `json:"selector,omitempty"` // 集羣IP。 // 一般狀況下該值是由master隨機分配的,可是若是手動聲明瞭,就要保證在集羣中未被使用,不然該服務會建立失敗。 // 該字段不能被更新 // 有效值爲None,空字符串("")和有效的IP地址 // 若是使用Headeless服務,不須要代理時,可使用None // 該字段只在Type爲ClusterIP、NodePOrt和LoadBalancer生效,在Type是ExternalName時被忽略 ClusterIP string `json:"clusterIP,omitempty"` // 服務類型,聲明瞭服務如何暴露出去 // 有效值爲ClusterIP(默認)、ExternalName、NodePort和LoadBalancer時起做用 // ClusterIP 分配一個集羣內網IP給該服務。經過Selector配置選擇指定的服務Pod,若是未配置Selector,則根據已有的Endpoints對象來肯定。 // 若是cluserIP爲None,則不會分配虛擬IP,endpoints也會被定爲一組endpoints而非一個肯定的IP // NodePort 在分配了集羣IP的基礎上(不論是指定的仍是master分配的),額外在節點上分配一個端口,能夠該端口將請求路由到該集羣IP上 // LoadBalancer 在NodePort的基礎上,額外建立一個負載均衡器來路由到該集羣IP上 Type ServiceType `json:"type,omitempty"` // 集羣中節點的IP地址列表。 // 服務將會在該列表中的節點上暴露服務端口。 // 這些端口暴露行爲不屬於K8S系統的管理部分。 ExternalIPs []string `json:"externalIPs,omitempty"` // Session親和配置 // 該字段可使用ClientIP和None(默認)做爲值 // ClientIP,則相同IP每次訪問都會訪問到同一個Pod SessionAffinity ServiceAffinity `json:"sessionAffinity,omitempty"` // Only applies to Service Type: LoadBalancer // LoadBalancer will get created with the IP specified in this field. // This feature depends on whether the underlying cloud-provider supports specifying // the loadBalancerIP when a load balancer is created. // This field will be ignored if the cloud-provider does not support the feature. LoadBalancerIP string `json:"loadBalancerIP,omitempty"` // If specified and supported by the platform, this will restrict traffic through the cloud-provider // load-balancer will be restricted to the specified client IPs. This field will be ignored if the // cloud-provider does not support the feature." // More info: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/ LoadBalancerSourceRanges []string `json:"loadBalancerSourceRanges,omitempty"` // 使用該字段後,服務在被訪問的時候kubedns將會將該字段的值做爲CNAME返回。 // 使用該字段Type必須爲ExternalName ExternalName string `json:"externalName,omitempty"` // 定義了服務將外部請求路由到本地節點仍是集羣中其餘節點。 // 該字段值能夠爲Local和Cluster // 若是該字段值爲Local,則能夠保留客戶端的IP,而且避免了Loadbalancer和Nodeport中網絡的第二跳,但存在流量不均衡的問題。 // 若是該字段爲Cluster,則不會保留真正客戶端的IP,可是流量分佈均勻 ExternalTrafficPolicy ServiceExternalTrafficPolicyType `json:"externalTrafficPolicy,omitempty"` // 該字段爲服務健康檢查使用的端口 // 若是未定義,則service api後端會自動分配一個端口 // 若是定義了,則使用用戶定義的端口 // 該字段只會在Type設置爲LoadBalancer 和 ExternalTrafficPolicy設置爲Local時生效 HealthCheckNodePort int32 `json:"healthCheckNodePort,omitempty"` // publishNotReadyAddresses,意爲發佈未準備好的地址到DNS,默認爲false // 當該字段設置爲true時,DNS則會爲Endpoints查找Service發佈notReadyAddresses。 // 防止readinessProbe在服務沒啓動時找不到DNS。 PublishNotReadyAddresses bool `json:"publishNotReadyAddresses,omitempty"` // sessionAffinityConfig能夠配置Session的最大過時時間,默認爲3小時 SessionAffinityConfig *SessionAffinityConfig `json:"sessionAffinityConfig,omitempty"` // 定義了服務的IP類型偏好(IPv四、IPv6) // 若是定義了該字段而且集羣支持該IP類型,則clusterIP字段將會被分配該類的IP // 若是未定義,則使用集羣IP的類型 IPFamily *IPFamily `json:"ipFamily,omitempty"` } type ServicePort struct { // 服務內端口的名稱,必須是一個DNS_LABEL // 全部在ServiceSpec中聲明的端口必須有一個惟一名稱 // 若是須要定義Endpoint的話,該名字必須和定義的Endpoint中的EndpointPort同樣 Name string `json:"name,omitempty"` // 該端口的IP協議,當前支持TCP(默認)、UDP和SCTP Protocol Protocol `json:"protocol,omitempty"` // 要暴露的服務端口 Port int32 `json:"port"` // 與服務對應的Pod上的端口號或者端口名 // 端口號須要在1-65535之間,名字必須是一個IANA_SVC_NAME // 若是是名字(字符串),將會在Pod的容器中查找與之對應的端口。若是未找到,則port字段的值將會被使用 // 當Service的ClusterIP=None時,忽略此字段,會缺省爲port字段的值 // 更多信息 : https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service TargetPort intstr.IntOrString `json:"targetPort,omitempty"` // 節點端口 // 當type=NodePort或者LoadBalancer時會使用該值。一般狀況下該字段的值由操做系統來分配。 // 若是定義了,若是端口被佔用,則服務建立失敗 // 在須要該字段的時候,默認爲自動分配 // 更多信息:https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport NodePort int32 `json:"nodePort,omitempty"` } // 服務類型 type ServiceType string const ( // 集羣IP,服務只能在集羣內被發現 ServiceTypeClusterIP ServiceType = "ClusterIP" // ClusterIP的擴展,額外使用節點端口,將會在全部部署了該服務的節點上都暴露一個端口 ServiceTypeNodePort ServiceType = "NodePort" // NodePort的擴展,額外使用負載均衡,服務將會被暴露在一個已經存在的負載均衡器中,由負載均衡器負責分發訪問 ServiceTypeLoadBalancer ServiceType = "LoadBalancer" // 額外的名字,在訪問服務的時候將會返回一個CNAME記錄。使用該字段的Service不會暴露或者代理任何的Pod。 ServiceTypeExternalName ServiceType = "ExternalName" ) // Session親和類型 type ServiceAffinity string const ( ServiceAffinityClientIP ServiceAffinity = "ClientIP" ServiceAffinityNone ServiceAffinity = "None" ) // Service External Traffic Policy Type string type ServiceExternalTrafficPolicyType string const ( // 該值定義了使用節點本地的行爲 ServiceExternalTrafficPolicyTypeLocal ServiceExternalTrafficPolicyType = "Local" // 該值定義了使用節全局節點的行爲 ServiceExternalTrafficPolicyTypeCluster ServiceExternalTrafficPolicyType = "Cluster" ) type SessionAffinityConfig struct { // 針對客戶端IP的配置信息 ClientIP *ClientIPConfig `json:"clientIP,omitempty"` } type ClientIPConfig struct { // 超時時間定義,單位秒,值必須在0~86400之間 TimeoutSeconds *int32 `json:"timeoutSeconds,omitempty"` } type IPFamily string const ( // IPv4Protocol IPv4協議 IPv4Protocol IPFamily = "IPv4" // IPv6Protocol IPv6協議 IPv6Protocol IPFamily = "IPv6" // 服務最多支持的拓撲域個數 MaxServiceTopologyKeys = 16 ) 複製代碼
以此Deployment配置爲基礎,進行Service的測試
apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx ports: - name: http containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx spec: ports: - name: web-8080 port: 8080 targetPort: http selector: app: nginx 複製代碼
建立該Service,再建立一個busybox執行 wget nginx:8080
進行驗證
上述配置建立了一個名稱爲nginx的Service對象,該對象對外暴露了8080端口。Service會將請求代理到使用具備標籤app=nginx的Pod的80端口上。
服務的默認協議是tcp,除此以外也支持udp和sctp。
因爲許多服務須要公開多個端口,所以在服務對象上支持多個端口定義。每一個端口定義的協議能夠不一樣。
須要注意的是 若是配置的是多端口Service,那麼配置端口的時候須要配置每一個端口的name屬性,單端口則不須要 。
$ kubectl run -it --rm --generator=run-pod/v1 busybox --image=busybox /bin/sh If you don't see a command prompt, try pressing enter. / # wget nginx:8080 Connecting to nginx:8080 (10.96.100.16:8080) saving to 'index.html' index.html 100% |*******************************| 612 0:00:00 ETA 'index.html' saved 複製代碼