Service
介紹:
實現方式:
1. userspace: 用戶空間
用戶的請求到達對應節點之上的iptables or ipvs規則(Service的規則),由Service先將他轉爲本地監聽在某個套接字上的用戶空間的kube-proxy進行處理,處理完成後再轉給Service IP,最終代理至後端Pod.
2. iptables: 直接調度
用戶請求到達iptables後直接進行調度,無需進入用戶空間處理;
3. ipvs: 直接調度
用ipvs進行調度,與iptables類似
kube-proxy
始終監視着master上的api server服務中有關Service的變動信息;
api server上有關Service對象的變動比如創建、刪除,kube-proxy都要將其轉化爲當前節點上能夠實現將用戶請求調度到後端特定Pod資源之上的規則(iptables or ipvs)取決於Service實現方式
通過YAML文件創建Service:
1. 類型介紹
# 可手動指定Service的虛擬IP地址
svc.spec.clusterIP <string>
# 標籤選擇器,用於關聯後端的Pod
svc.spec.selector <map[string]string>
# 關聯後端Pod的端口
svc.spec.ports <[]Object>
# service的類型(ExternalName, ClusterIP, NodePort, LoadBalancer)
svc.spec.type <string>
ClusterIP: 默認爲此類型,僅用於集羣內通信
NodePort: 接入機器外部的流量,客戶端直接通過節點的IP+NodePort暴露出來的端口就可訪問
LoadBalancer: 比如在雲環境上搭建了K8S集羣(阿里雲、AWS雲),使用此種類型的Service會自動創建負載均衡器(阿里雲的SLB)
ExternalName: 需要被kube-dns能夠解析,用於將Service關聯至外圍服務以供Pod訪問,外圍服務將處理結果轉交個Node,Node再返回給Service,Service再返回給Pod client,從而讓Pod訪問外圍的服務(集羣內不存在的服務)
資源記錄格式(CoreDns):
SVC_NAME.NS_NAME.DOMAIN.LTD.
svc.cluster.local.
redis.default.svc.cluster.local.
2.創建ClusterIP類型的Service.
$ vim svc-demo.yaml apiVersion: v1 kind: Service metadata: name: redis namespace: default spec: clusterIP: 10.97.97.97 type: ClusterIP selector: app: redis role: logstor ports: - name: redis port: 6479 targetPort: 6379 protocol: TCP $ kubectl apply -f svc-demo.yaml
$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE redis ClusterIP 10.97.97.97 <none> 6379/TCP 2m52s # 後端的Pod是之前創建的一個redis $ kubectl describe svc redis Name: redis Namespace: default Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"redis","namespace":"default"},"spec":{"clusterIP":"10.97.97.97","... Selector: app=redis,role=logstor Type: ClusterIP IP: 10.97.97.97 Port: redis 6379/TCP TargetPort: 6379/TCP Endpoints: 10.244.1.63:6379 Session Affinity: None Events: <none> # 下列的Pod是之前搞Deployment的時候創建的,現在要把這些發佈出去. $ kubectl get pods --show-labels NAME READY STATUS RESTARTS AGE LABELS deploy-demo-f5dfc4cf4-cb58r 1/1 Running 1 20h app=myapp,pod-template-hash=f5dfc4cf4,release=canary deploy-demo-f5dfc4cf4-mm27c 1/1 Running 1 20h app=myapp,pod-template-hash=f5dfc4cf4,release=canary deploy-demo-f5dfc4cf4-p7zvp 1/1 Running 1 20h app=myapp,pod-template-hash=f5dfc4cf4,release=canary deploy-demo-f5dfc4cf4-rbqnh 1/1 Running 1 20h app=myapp,pod-template-hash=f5dfc4cf4,release=canary deploy-demo-f5dfc4cf4-wz8tr 1/1 Running 1 20h app=myapp,pod-template-hash=f5dfc4cf4,release=canary
3.創建NodePort類型的Service.
$ vim svc-np-demo.yaml apiVersion: v1 kind: Service metadata: name: redis namespace: default spec: type: NodePort selector: app: myapp release: canary ports: - name: myapp-port nodePort: 30001 port: 80 targetPort: 80 $ kubectl apply -f svc-np-demo.yaml $ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 14d myapp NodePort 10.97.65.55 <none> 80:30001/TCP 61s redis ClusterIP 10.97.97.97 <none> 6379/TCP 20m $ kubectl describe svc myapp Name: myapp Namespace: default Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"myapp","namespace":"default"},"spec":{"ports":[{"name":"myapp-por... Selector: app=myapp,release=canary Type: NodePort IP: 10.97.65.55 Port: myapp-port 80/TCP TargetPort: 80/TCP NodePort: myapp-port 30001/TCP Endpoints: 10.244.1.64:80,10.244.1.65:80,10.244.1.66:80 + 2 more... Session Affinity: None External Traffic Policy: Cluster Events: <none> # 集羣外部機器一直訪問此Service,會發現返回的結果中包含所有Pod. $ while true;do curl http://192.168.222.100:30001/hostname.html;sleep 1; done deploy-demo-f5dfc4cf4-wz8tr deploy-demo-f5dfc4cf4-p7zvp deploy-demo-f5dfc4cf4-p7zvp deploy-demo-f5dfc4cf4-cb58r deploy-demo-f5dfc4cf4-wz8tr deploy-demo-f5dfc4cf4-cb58r deploy-demo-f5dfc4cf4-rbqnh deploy-demo-f5dfc4cf4-rbqnh deploy-demo-f5dfc4cf4-wz8tr deploy-demo-f5dfc4cf4-rbqnh deploy-demo-f5dfc4cf4-p7zvp deploy-demo-f5dfc4cf4-rbqnh deploy-demo-f5dfc4cf4-cb58r .....
小功能:如果啓用下面這個功能的話那麼來自同一客戶端的請求始終發送給第一次接收請求的Pod
svc.spec.sessionAffinity <string>
string:
ClientIP
None(默認值)
# 打補丁更新配置,也可以使用"kubectl edit -f xxx"或直接vim文件,隨後使用"kubectl apply -f xxx"也可以.
$ kubectl patch svc myapp -p '{"spec":{"sessionAffinity":{"ClientIP"}}}' # 再次查看,會發現多了"**"那一行. $ kubectl describe svc myapp Name: myapp Namespace: default Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"myapp","namespace":"default"},"spec":{"ports":[{"name":"myapp-por... Selector: app=myapp,release=canary Type: NodePort IP: 10.97.65.55 Port: myapp-port 80/TCP TargetPort: 80/TCP NodePort: myapp-port 30001/TCP Endpoints: 10.244.1.64:80,10.244.1.65:80,10.244.1.66:80 + 2 more... ** Session Affinity: ClientIP External Traffic Policy: Cluster Events: <none> # 而且客戶端訪問這個Service的結果永遠都是一樣的
4. headless Service(無頭Service)
說明:
之前的Service的工作過程我想大家應該都知道,當客戶端訪問Service的時候,實際是會有kube-dns進行解析Service的名稱,將名稱解析爲ClusterIP,隨後根據算法調度後端Pod以便響應客戶端請求,這個headless Service無需配置ClusterIP
要設爲"None",那麼當客戶端請求過來的時候會將Service Name直接解析爲後端Pod的地址以便提供響應.
4.1 使用YAML文件創建的方法
$ vim myapp-svc-headless.yaml apiVersion: v1 kind: Service metadata: name: myapp-headless namespace: default spec: clusterIP: None type: ClusterIP selector: app: myapp release: canary ports: - port: 80 targetPort: 80 $ kubectl apply -f myapp-svc-headless.yaml # 會發現"**"標記的那一行中的ClusterIP爲None,不用慌,這是正常現象. $ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 15d myapp NodePort 10.97.65.55 <none> 80:30001/TCP 160m ** myapp-headless ClusterIP None <none> 80/TCP 15m redis ClusterIP 10.97.97.97 <none> 6379/TCP 179m # 隨後我們手動解析這個沒有ClusterIP的Service,查看結果(answer上邊的和下邊的省略了),發現解析結果爲後端的所有Pod的地址. $ dig -t A myapp-headless.default.svc.cluster.local @10.96.0.10 ..... ;; ANSWER SECTION: myapp-headless.default.svc.cluster.local. 30 IN A 10.244.1.64 myapp-headless.default.svc.cluster.local. 30 IN A 10.244.1.66 myapp-headless.default.svc.cluster.local. 30 IN A 10.244.1.65 myapp-headless.default.svc.cluster.local. 30 IN A 10.244.2.67 myapp-headless.default.svc.cluster.local. 30 IN A 10.244.2.68 ......