iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 5
1
DevOps

從題目中學習k8s系列 第 5

【從題目中學習k8s】-【Day5】K8s中的resource object(二) - Service


title: 【從題目中學習k8s】-【Day5】K8s中的resource object(二) - Service
description: 以無比的恆毅力堅持30天鍊成鐵人--連續30天,一天發表一篇IT技術文章

【從題目中學習k8s】-【Day5】K8s中的resource object(二) - Service

tags: DevOps CICD K8s Docker

Service

在前一天介紹的PodDeployment物件其實是不能在網路上被"直接"存取到的,雖然它們都有各自的IP Address,但這些 IP 僅有在 K8s cluster 內部才有辦法存取的到,若 K8s cluster 要提供對外服務,則需要透過第四層的port-forward,將PodPort對應到NodePort,expose給外部使用者。但若同時有多個 Pods 想要同時被存取時,就需要透過 Service 這個元件。

簡言之:

Service就是K8s提供讓集群內部Pod和集群外世界溝通的一種方式。

可能大家會好奇,為甚麼要有Service的設計?為甚麼不能讓外部直接存取Pod的IP?還要透過Service? 原因有二:

  1. 需要同時被access的Pod可能很多,例如一個Deployment下的所有Pod,還有之後會介紹的IngressService可以透過 "Selector" 同時選取所有物件,在實務上很方便
  2. Pod其實是經常重啟的,一旦Pod重啟,每次的IP都會跟著變動,為了防止每次重啟Pod就要更改一次設定,就需要有個"東西"來幫我們找到重啟後的Pod,這個"東西"就是Service

Service的YAML範例如下:

$ vim svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

創建Service

$ kubectl apply -f svc.yaml

我們看一下其中的欄位設定:

  • selsctor
    指定這個 Service 要適用到哪些 Pod,依據label: app=MyApp來選取
  • Port
    要作port-forward的設定,指定PodPort對應到的NodePort,下面會有詳細介紹

上述是第一種Service創建方式 (透過YAML),還有第二種創建Service的方法,即透過kubectl expose

$ kubectl expose po <pod-name> --name=<svc-name> --type=<type-of-svc>

這種方法是將Pod expose給外部使用者,相當於創建一個Service。創建的Service會自動將該Podlabel填入selector欄位,name欄位則輸入Service的名稱,typeService的類別。

沒錯,Service是有類別區分的喔,依照不同功能及使用場景,共有三種類別。


Service Types

Service依照不同功能及使用場景,共有三種ServiceNodePort, ClusterIPLoadBlancer

NodePort


NodePort的目標是將Pod expose給外部使用者。在Node上開放一個特定Port,再透過Service將port mapping到PodPort,如下圖

  • nodePort
    指定這個Node要開放哪個PortService會將此Port mapping到PodPort上。NodePort範圍是30000 ~ 32767,若NodePort欄位沒有給定,K8s會自動assign一個範圍內的PortNodePort
  • port
    Service上的Cluster IPPort,此Port會和targetPort 作 mapping。port通常會指定為80

Service可以想像成一個Cluster之中的Virtual Server,這個Virtual Server會擁有自己的IP,這個IP稱為Cluster IP

  • targetPort
    指定 Pod 上允許外部資源存取的 Port Number,Service會將request forward到這個Port。若在YAML中沒有給定targetPort,則K8s會設定為和port相同的值

NodePort的YAML範例如下:

$ vim NP-Svc.yaml

apiVersion: v1
kind: Service
metadata: 
  name: nodeport-service
spec:
  type: NodePort
  ports:
    - targetPort: 80
      port: 80
      nodePort: 30008
  selector: 
    app: MyApp

ClusterIP


ClusterIPK8s default的Service Type,它只提供集群內部的服務,集群內的Pod都可以透過它互相訪問,集群外部則無法訪問它

若創建Service時沒有定義type,K8s會默認為ClusterIP

ClusterIP的應用場景通常是保護某些資料不被外部存取,例如一個Web Application有back-end和front-end,我只想將front-end Pod expose出去,但又想back-end和front-end可以溝通,這時就可以用到ClusterIP Service

ClusterIP的YAML範例如下:

$ vim CIP-Svc.yaml

apiVersion: v1
kind: Service
metadata: 
  name: clusterip-service
spec:
  type: NodePort
  ports:
    - targetPort: 80
      port: 80
  selector: 
    app: MyApp

LoadBlancer


LoadBalancer 服務expose到 Internet 的標準方式。所有通往指定的Port的流量都會被forward到對應的服務。它沒有過濾條件,沒有路由等。也就是說,你可以發送任何種類的流量到該服務,像 HTTP,TCP,UDP,Websocket,gRPC 或其它種類。這個方式的最大缺點是每一個用 LoadBalancer 暴露的服務都會有它自己的 IP ,每個用到的 LoadBalancer 都需要付費,所以LoadBalancer通常會和Ingress一起使用。

因為LoadBalancer通常會和Ingress一起使用,而Ingress又比較複雜,有機會的話之後再介紹

事實上,Service不是存在於任一Node的物件,它是屬於Cluster basedresource-object,因此當Service在select Pod時,才可以選到其他NodePod


結論

今天介紹了Service這個物件,因為Service內容比較多,如果不拉一天介紹的話感覺不太能銜接後面會遇到的題目,所以特別介紹一下。好啦,今天就到這囉~ 謝謝大家~

推薦這個教學影片,介紹的非常詳細

參考資料

Service
Kubernetes - Services Explained in 15 Minutes!
[Kubernetes] How to Implement Kubernetes Service - ClusterIP
KubernetesService Overview

Thank you!

You can find me on

  • george4908090@gmail.com

上一篇
【從題目中學習k8s】-【Day4】K8s中的resource object(一) - Pod、Deployment
下一篇
【從題目中學習k8s】-【Day6】奇怪的Pod - Static Pod
系列文
從題目中學習k8s31

尚未有邦友留言

立即登入留言