K8S學習筆錄 - Service基本用法

原文連接html

Service能夠爲一組具備相同功能的容器應用提供一個統一的入口地址,而且將請求負載分發到後端的各個容器應用上。前端

爲何須要Service

Service的存在主要爲了解決 客戶端沒法肯定爲它提供服務的Pod的地址 的問題。node

可能因爲一些問題(Pod調度、異常等),該Pod從該節點被驅逐到其餘節點上,此時Pod的IP可能會變; 或者因爲Pod的水平伸縮,多出來或者少幾個提供一樣服務的Pod。nginx

此時須要一箇中間層轉發客戶端的請求,爲客戶端提供穩定的服務。 同時該中間層也能夠作負載均衡、服務暴露等工做。git

Service是如何工做的

Service在配置過程當中,會要求配置一個Pod選擇規則。經過該規則找到提供服務的Pod列表。 而後客戶端不會直接訪問這些Pod,而是經過Service來訪問這些Pod。github

例如客戶端要訪問前端,前端要訪問後端。web

外部客戶端不關心前端Pod數量,而直接鏈接到前端服務上,由前端服務選擇一個Pod來提供服務。 前端服務也不關心後端Pod數量,而直接鏈接到後端服務商,由後端服務選擇一個Pod來提供服務。 在此期間,不管是Pod變動、遷移,上游都不須要關心。json

svc-overview.png

Service配置定義

經過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 複製代碼
相關文章
相關標籤/搜索