Service就好像一個快遞站,而Pod就是快遞員。假設你要寄送一個包裹,你需要把包裹交給快遞員,讓他送到指定的地址。但是,如果你不知道快遞員的具體位置,你就需要打電話查詢他的位置,然後再交給他包裹。這樣很麻煩,效率也不高。如果有一個快遞站,快遞員可以把包裹交給這個快遞站,讓它進行分發和管理。當你要寄送包裹時,你只需要把包裹交給這個快遞站,讓它根據地址進行分發,就可以了。這樣就可以省去查詢快遞員位置的麻煩,也提高了效率和可靠性。
編寫Service定義檔
把指令產生的Service貼到之前Deployment範例底下
apiVersion: apps/v1
kind: Deployment
metadata:
name: wadweb-deployment
labels:
app: wadweb-deployment
spec:
selector:
matchLabels:
app: wadweb
replicas: 1
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
template:
metadata:
name: wadweb
labels:
app: wadweb
spec:
containers:
- name: wadwebapp
image: "你的registryURL/wad-web:v2.0.0"
imagePullPolicy: Always
resources:
limits:
cpu: 200m
memory: 500Mi
requests:
cpu: 100m
memory: 200Mi
ports:
- containerPort: 80
name: http
- name: wadwebapi
image: "你的registryURL/wad-web-api:v2.0.0"
imagePullPolicy: Always
resources:
limits:
cpu: 2000m
memory: 2Gi
requests:
cpu: 1000m
memory: 1Gi
env:
- name: DOTNET_RUNNING_IN_CONATINER
value: "true"
- name: ASPNETCORE_ENVIRONMENT
value: "Development"
- name: ASPNETCORE_URLS
value: "http://+:8080"
- name: ConnectionStrings__DefaultConnection
value: "Server=你的SQLServer Connection;Initial Catalog=WADREQM;Persist Security Info=False;User ID=你的SQLServer帳號;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=true;Connection Timeout=30;"
- name: Connection__Key
value: "我是密碼"
- name: HostUrl__RemoteHost
value: "http://192.168.1.34:8080"
- name: TZ
value: "Asia/Taipei"
volumeMounts:
- name: fileupload
mountPath: /app/upload
ports:
- containerPort: 8080
name: http
volumes:
- name: fileupload
hostPath:
path: /run/desktop/mnt/host/d/Kubernetes/fileupload
type: DirectoryOrCreate
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: wadweb-service
spec:
type: NodePort
selector:
app: wadweb
ports:
- name: wadwebapp-port
port: 80
targetPort: 80
nodePort: 30014
- name: wadapiapp-port
port: 8080
targetPort: 8080
nodePort: 30015
- spec.type:這裡有多種模式:「ClusterIP」、「NodePort」、「LoadBalancer」、「ExternalName」
- ClusterIP:預設設定,只會在集群內部暴露一個IP地址,用於集群內部通信。這個IP地址只能在集群內部進行訪問,對外部不可見。💡 適合場景:內部Pod服務有相關聯並且需要互相溝通時可以使用
- NodePort:在每個節點上暴露一個固定的Port,用於從集群外部訪問這個 Service,缺點是Service數量很多時,管理Port會變得麻煩💡 適合場景:Demo用,臨時的服務等等
- LoadBalancer:在集群外部使用一個負載均衡器,用於實現外部訪問這個 Service,是讓外部連線到Pod服務的標準方式,前提是要使用雲端以及其外部的負載平衡器💡 適合場景:適合在雲端,並且雲端提供外部的負載平衡器時
- ExternalName:是一個命名代理,用於將K8s中的服務命名映射到集群外部的服務💡 適合場景:需要訪問集群外部的服務時,例如外部的資料庫、API 服務等等
- ClusterIP:預設設定,只會在集群內部暴露一個IP地址,用於集群內部通信。這個IP地址只能在集群內部進行訪問,對外部不可見。
- spec.selector:讓Service選擇到指定的Pod(這裡設定的是Pod的Label)💡 如果沒有設置selector屬性,它仍然可以將請求轉發到相應的Pod,但是它只能通過設置spec.clusterIP=None的方式實現。這種方式創建的Service稱為Headless Service,它不提供負載均衡和故障轉移的功能,而是將請求直接轉發到相應的 Pod,從而實現直接的訪問。這裡就不詳細介紹什麼是Headless Service了因為很少有機會用到,我自己也沒有用過XD
- spec.ports[].port:服務的外部接收Port
- spec.ports[].targetPort:Pod的Port(spec.containers[].ports.containerPort)
- spec.ports[].nodePort:當type設定為NodePort時才有效,如果沒設定K8s會隨機指定一個Port(範圍是30000 ~ 32767)
💡 Service主要是通過kube-proxy實現的。kube-proxy是K8s的一個核心組件,它負責實現Service的負載均衡和故障轉移功能,每個Node都會運行一個kube-proxy進程。kube-proxy接收來自Service的流量,然後根據Service的類型(ClusterIP、NodePort、LoadBalancer或ExternalName)進行處理
執行Service
設定好Service後就可以部署上去,然後使用指令來查看Service的情況,可以看到Cluster內部通信的Port和外部通信的NodePort
kubectl get service
Service的NodePort設定是不是很方便簡單呢!不!在真實的環境可不是一個NodePort就可以解決的呢XD,還有其它的如:「ClusterIP」、「LoadBalancer」、「ExternalName」等等加上後面還有延伸的「Ingress」,所以在實戰中還是會根據不同的需求選擇不同的 Service 類型,從而實現不同的功能哦!
儘管NodePort是一個很方便的方式,但也存在一些缺點:
- 安全性:由於NodePort公開了一個範圍的端口到集群節點上,這可能會增加攻擊面。攻擊者可以直接通過節點IP和NodePort來進行攻擊,並且可以使用暴力攻擊的方式來猜測NodePort的值。
- 擴展性:使用NodePort需要開放一定範圍的端口,如果Kubernetes集群中有多個服務需要公開,可能會出現端口不足的情況。而且當Kubernetes集群擴展到多個節點時,需要管理和維護多個節點上的NodePort。
- 設置困難:在NodePort模式下,需要手動配置防火牆規則以允許對NodePort的流量進行轉發。這可能需要一些網絡和安全方面的知識,對於一些新手來說可能比較困難。
- 辨識度不高:使用NodePort你的URL勢必會變成http://192.168.1.1:xxxxx,服務一旦很多時,也不容易從URL去辨識這個服務在幹嘛
0 Comments
張貼留言