Kubernetes 中的 Service 是用于暴露應用服務的核心抽象,為 Pod 提供穩定的訪問入口、負載均衡和服務發現機制。Service在Kubernetes中代表了一組Pod的邏輯集合,通過創建一個Service,可以為一組具有相同功能的容器應用提供一個統一的入口地址,并將請求負載分發到后端的各個容器應用上。
流量轉發流程
1、客戶端訪問 Service 的 ClusterIP 或 DNS 名稱。
2、kube-proxy 根據 Service 規則將請求轉發到后端 Pod。
3、請求到達 Pod 后由應用處理。
ExternalName類型
在Kubernetes(k8s)中,創建一個ExternalName類型的Service可以讓你將集群內部的服務通過DNS CNAME機制映射到一個外部域名上。這樣,集群內部的Pod就可以通過內部服務名訪問外部服務,而無需知道外部服務的真實域名。以下是創建ExternalName類型Service的步驟:
定義YAML文件
首先,你需要定義一個YAML文件來描述Service的屬性。以下是一個示例YAML文件,用于創建一個ExternalName類型的Service:
apiVersion: v1
kind: Service
metadata:name: my-externalname-servicenamespace: default # 或者你指定的其他命名空間
spec:type: ExternalNameexternalName: www.example.com # 外部服務的域名
指定IP地址
apiVersion: v1
kind: Service
metadata:name: web-nodeport
spec:type: NodePortselector:app: webports:- port: 80targetPort: 80nodePort: 31000 # 手動指定節點端口(可選)ClusterIP: IP地址
HeadLess Service
apiVersion: v1
kind: Service
metadata:name: web-nodeport
spec:type: NodePortselector:app: webports:- port: 80targetPort: 80nodePort: 31000 # 手動指定節點端口(可選)ClusterIP: None
# nginx 部署的yaml文件
---
apiVersion: apps/v1
kind: Deployment
metadata:name: nginxweb
spec:selector:matchLabels:app: nginxweb1replicas: 2template:metadata:labels:# 容器標簽的名字,發布 Service時,selector 需要和這里對應app: nginxweb1spec:# 配置容器,數組類型,說明可以配置多個容器containers:# 容器名稱- name: nginxwebc# 容器鏡像image: nginx:latestimagePullPolicy: IfNotPresent# 暴露端口ports:- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: nginxweb-service
spec:externalTrafficPolicy: Clusterselector:# 選擇哪一個容器標簽作為服務, labels:》》 app:》》 nginxweb1 通過容器標簽關聯的 # 上面 Deployment可以單獨一個yaml文件 只有知道 label標簽就可以了 ,不需要知道 pod的ip地址。 相當于面對服務名不是IP地址app: nginxweb1ports:- protocol: TCP# Service 暴露的端口port: 80# Pod上的端口 這里是將 Service 暴露的端口 轉發到 Pod 端口上targetPort: 80nodePort: 30080type: NodePort
K8S 分配給Service一個固定IP,這是一個虛擬IP(也稱為 ClusterIP),并不是一個真實存在的IP,而是由K8S虛擬出來的,外部是尋址不到的。在K8S系統中,實際上是由kubernetes Proxy 組件負責實現虛擬IP路由和轉發的。所以說在K8s node中我們都運行了Kubernetest Proxy,從而在容器覆蓋網絡之上又實現了Kubernetes層級的虛擬轉發網絡。
通過服務名訪問》要在Pod內部才能通過服務名訪問
# 同一命名空間內的 Service 訪問
域名格式:<service-name>
# 跨命名空間的 Service 訪問
域名格式:<service-name>.<namespace>.svc.cluster.local
# nginx 部署的yaml文件
---
apiVersion: apps/v1
kind: Deployment
metadata:name: nginxweblabels:app: niginx-l1
spec:selector:matchLabels:app: nginxweb1replicas: 2template:metadata:labels:# 容器標簽的名字,發布 Service時,selector 需要和這里對應app: nginxweb1spec:# 配置容器,數組類型,說明可以配置多個容器containers:# 容器名稱- name: nginxwebc# 容器鏡像image: nginx:latestimagePullPolicy: IfNotPresent# 暴露端口ports:- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: nginxweb-servicelabels:app: niginx-s
spec:selector:app: nginxweb1ports:- protocol: TCP# Service 暴露的端口port: 80# Pod上的端口 這里是將 Service 暴露的端口 轉發到 Pod 端口上targetPort: 80type: ClusterIP
創建Service會自動創建同名的Endpoint
Service 不僅可以代理Pod,還可以代理任意其他后端。
比如代理K8s外部的服務。
雖然不常見,但Endpoint也可以手動創建。這通常用于特殊情況,比如需要顯式指定Endpoint的IP地址和端口,例如在與外部非K8s管理的服務進行集成時,可能需要手動創建Endpoint來定義服務的訪問信息,以便將其納入K8s的服務管理體系中。
apiVersion: v1
kind: Endpoints
metadata:name: my-endpoint
subsets:- addresses:- ip: 地址ports:- port: 2020protocol: TCP
---
apiVersion: v1
kind: Service
metadata:name: my-endpoint
spec:ports:- protocol: TCPport: 80targetPort: 2020nodePort: 30100type: NodePort