Kubernetes ---- Service介紹

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
......

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章