一 Service簡介 1.1 Service概念 Service是Kubernetes的核心概念,通過創建Service,可以為一組具有相同功能的容器應用提供一個統一的入口地址,並且將請求負載分發到後端的各個容器應用上。 1.2 Service定義詳解 1 apiVersion: v1 #必須,a ...
一 Service簡介
1.1 Service概念
Service是Kubernetes的核心概念,通過創建Service,可以為一組具有相同功能的容器應用提供一個統一的入口地址,並且將請求負載分發到後端的各個容器應用上。1.2 Service定義詳解
1 apiVersion: v1 #必須,api版本 2 kind: Service #必須,類型為Service 3 metadata: #必須,元數據 4 name: string #必須,Service名稱 5 namespace: string #必須,命名空間,預設為default 6 labels: #自定義標簽屬性列表 7 - name: string 8 annotations: #自定義註解屬性列表 9 - name: string 10 spec: #必須,詳細描述 11 selector: [] #必須,Label Selector配置 12 type: ClusterIP #必須,Serice類型,詳見如下 13 sessionAffinity: string #虛擬服務IP地址,當選擇type=ClusterIP時,若不指定,則系統進行自動分配;當type=LoadBalancer時,需要指定 14 ports: #Service需要暴露的埠列表 15 - name: string #埠名稱 16 protocol: #埠協議,支持TCP和UDP,預設為TCP 17 port: int #服務監聽的埠號 18 targetPort: 8080 #需要轉發到後端Pod的埠號 19 nodePort: int #當spec.type=NodePort時,指定映射到物理機的埠號 20 status: #當spec.type=LoadBalancer時,設置外部負載均衡的地址,用於公有雲 21 loadBalancer: #外部負載均衡器 22 ingress: #外部負載均衡器 23 ip: string #外部負載均衡器的IP地址 24 hostname: string #外部負載均衡器的主機名spec.type:Service的類型,指定Service的訪問方式,預設為ClusterIP。
- ClusterIP:虛擬的服務IP地址,該地址用於Kubernetes集群內部的Pod訪問,在Node上kube-proxy通過設置的iptables規則進行轉發;
- NodePort:使用宿主機的埠,使能夠訪問各Node的外部客戶端通過Node的IP地址和埠號就能訪問服務;
- LoadBalancer:使用外接負載均衡器完成到服務的負載分發,需要在spec.status.loadBalancer欄位指定外部負載均衡器的IP地址,並同時定義nodePort和clusterIP,用於公有雲。
二 Service基本使用
2.1 Service的基本用法
一般來說,對外提供服務的應用程式需要通過某種機制來實現,對於容器應用最簡便的方式就是通過TCP/IP機制及監聽IP和埠號來實現。 示例:定義一個提供Web服務的RC,由兩個Tomcat容器副本組成,每個容器都通過containerPort設置提供服務的埠號為8080。[root@k8smaster01 study]# cat webapp-rc.yaml
1 apiVersion: v1 2 kind: ReplicationController 3 metadata: 4 name: webapp 5 spec: 6 replicas: 2 7 template: 8 metadata: 9 name: webapp 10 labels: 11 app: webapp 12 spec: 13 containers: 14 - name: webapp 15 image: tomcat 16 ports: 17 - containerPort: 8080[root@k8smaster01 study]# kubectl create -f webapp-rc.yaml [root@k8smaster01 study]# kubectl get pods -l app=webapp -o yaml | grep podIP podIP: 172.24.9.88 podIP: 172.24.9.199 [root@k8smaster01 study]# curl 172.24.9.88:8080 直接通過Pod的IP地址和埠號可以訪問到容器應用內的服務,但是Pod的IP地址是不可靠的,例如當Pod所在的Node發生故障時,Pod將被Kubernetes重新調度到另一個Node,Pod的IP地址將發生變化。 如果容器應用本身是分散式的部署方式,通過多個實例共同提供服務,就需要在這些實例的前端設置一個負載均衡器來實現請求的分發。Kubernetes中的Service就是用於解決這些問題的核心組件。 Service示例:以如上webapp應用為例,為了讓客戶端應用訪問到兩個Tomcat Pod實例,可以創建一個Service來提供服務。Kubernetes提供了一種快速的方法,即通過kubectl expose命令來創建Service。[root@k8smaster01 study]# kubectl expose rc webapp [root@k8smaster01 study]# kubectl get svc | grep -E 'NAME|webapp' NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE webapp ClusterIP 10.10.10.51 <none> 8080/TCP 45s [root@k8smaster01 study]# curl 10.10.10.51:8080 #測試訪問 提示:如上Service地址10.10.10.51:8080的訪問被自動負載分發到後端兩個Pod。 Service示例2:通過Service配置文件暴露服務。 [root@k8smaster01 study]# vi webappsvc.yaml
1 apiVersion: v1 2 kind: Service 3 metadata: 4 name: webappservice 5 spec: 6 ports: 7 - port: 8081 8 targetPort: 8080 9 selector: 10 app: webapp[root@k8smaster01 study]# kubectl create -f webappsvc.yaml [root@k8smaster01 study]# kubectl get svc | grep -E 'NAME|webappser' NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE webappservice ClusterIP 10.10.10.83 <none> 8081/TCP 22s 提示:如上Service定義中的關鍵欄位是ports和selector。本例中ports定義部分指定了Service所需的虛擬埠號為8081,由於與Pod容器埠號8080不一樣,所以需要再通過targetPort來指定後端Pod的埠號。selector定義部分設置的是後端Pod所擁有的label:app=webapp。 [root@k8smaster01 study]# curl 10.10.10.83:8081 #訪問測試
- Service負載分發策略:RoundRobin和SessionAffinity
- RoundRobin:輪詢模式,即輪詢將請求轉發到後端的各個Pod上。
- SessionAffinity:基於客戶端IP地址進行會話保持的模式,即第1次將某個客戶端發起的請求轉發到後端的某個Pod上,之後從相同的客戶端發起的請求都將被轉發到後端相同的Pod上。
2.2 多埠Service
有時一個容器應用也可能提供多個埠的服務,那麼在Service的定義中也可以相應地設置為將多個埠對應到多個應用服務。 示例1:如下,Service設置了兩個埠號,並且為每個埠號都進行了命名。 [root@k8smaster01 study]# vi twoportservice.yaml1 apiVersion: v1 2 kind: Service 3 metadata: 4 name: webapp 5 spec: 6 ports: 7 - port: 8080 8 targetPort: 8080 9 name: web 10 - port: 8005 11 targetPort: 8005 12 name: management 13 selector: 14 app: webapp[root@k8smaster01 study]# vi kubednsservice.yaml
1 apiVersion: v1 2 kind: Service 3 metadata: 4 name: kube-dns 5 namespace: kube-system 6 labels: 7 k8s-app: kube-dns 8 kubernetes.io/cluster-service: "true" 9 kubernetes.io/name: "KubeDNS" 10 spec: 11 selector: 12 k8s-app: kube-dns 13 clusterIP: 169.169.0.100 14 ports: 15 - name: dns 16 port: 53 17 protocol: UDP 18 19 - name: dns-tcp 20 port: 53 21 protocol: TCP
2.3 外部服務Service
在某些環境中,應用系統需要將一個外部資料庫、另一個集群或Namespace中的服務作為服務的後端,則可通過創建一個無Label Selector的Service來實現。 [root@k8smaster01 study]# vi noselectorservice.yaml1 apiVersion: v1 2 kind: Service 3 metadata: 4 name: my-service 5 spec: 6 ports: 7 - protocol: TCP 8 port: 80 9 targetPort: 80[root@k8smaster01 study]# kubectl create -f noselectorservice.yaml 如上定義創建的是一個不帶標簽選擇器的Service,即無法選擇後端的Pod,系統不會自動創建Endpoint,因此需要手動創建一個和該Service對應的Endpoint,用於指向實際的後端訪問地址。 如下所示的Endpoint的定義文件: [root@k8smaster01 study]# vi noselectorendpoint.yaml
1 apiVersion: v1 2 kind: Endpoints 3 metadata: 4 name: my-service 5 subsets: 6 - addresses: 7 - IP: 47.96.145.131 8 ports: 9 - port: 80[root@k8smaster01 study]# kubectl create -f noselectorendpoint.yaml [root@k8smaster01 study]# kubectl get svc | grep -E 'NAME|my-service' NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-service ClusterIP 10.10.10.211 <none> 80/TCP 3s [root@k8smaster01 study]# curl 10.10.10.211 提示:如上所示,訪問沒有標簽選擇器的Service和帶有標簽選擇器的Service一樣,請求將會被路由到由用戶手動定義的後端Endpoint上。
三 Headless Service
3.1 無頭服務簡介
在某些應用場景中,若需要人為指定負載均衡器,不使用Service提供的預設負載均衡的功能,或者應用程式希望知道屬於同組服務的其他實例。Kubernetes提供了Headless Service來實現這種功能,即不為Service設置ClusterIP(入口IP地址),僅通過Label Selector將後端的Pod列表返回給調用的客戶端。 此場景中,Service就不再具有一個特定的ClusterIP地址,對其進行訪問將獲得包含Label“app=nginx”的全部Pod列表,然後客戶端程式自行決定如何處理這個Pod列表。 例如,StatefulSet就是使用Headless Service為客戶端返回多個服務地址的。 對於“去中心化”類的應用集群,Headless Service非常適合。3.2 Nginx場景實驗
通過對Headless Service搭建Nginx集群,從而自動實現應用集群的創建。 [root@k8smaster01 study]# vi nginx-service.yaml #創建Service1 apiVersion: v1 2 kind: Service 3 metadata: 4 labels: 5 name: nginx-svc 6 name: nginx-svc 7 spec: 8 ports: 9 - protocol: TCP 10 port: 80 11 targetPort: 80 12 selector: 13 name: nginx-demo #定義selector 14 clusterIP: None[root@k8smaster01 study]# kubectl create -f nginx-service.yaml [root@k8smaster01 study]# vi nginx-deployment.yaml
1 apiVersion: apps/v1 2 kind: Deployment 3 metadata: 4 labels: 5 name: nginx-demo 6 name: nginx-demo 7 spec: 8 replicas: 2 9 selector: 10 matchLabels: 11 name: nginx-demo 12 template: 13 metadata: 14 labels: 15 name: nginx-demo 16 spec: 17 containers: 18 - name: nginx 19 image: nginx:1.7.9 20 ports: 21 - containerPort: 80 22 name: web[root@k8smaster01 study]# kubectl create -f nginx-deployment.yaml [root@k8smaster01 study]# kubectl create -f nginx-service.yaml [root@k8smaster01 study]# kubectl get svc -o wide [root@k8smaster01 study]# kubectl get pods -o wide [root@k8smaster01 study]# nslookup nginx-svc.default.svc.cluster.local 10.10.190.170 提示:由上可知,通過解析SVC的地址,直接解析出來的為Pod的IP。