k8s系列---service


 

來源 : http://blog.itpub.net/28916011/viewspace-2214745/

 service是要通過coreDNS來管理pod的。 

    kube-proxy始終監視着apiserver,獲取與service資源的變動狀態。一旦發現有service資源發生變動,kube-proxy都要把它轉變為當前節點之上的,能夠實現service資源調度,包括將客戶端資源調度到pod的規則(iptables或者ipvs)。 

    service工作模式有三種:userspace(k8s 1.1版本之前),iptables(k8s 1.10版本之前)和ipvs(k8s 1.11版本之后)

    userspace模型:用戶空間模型。k8s 1.11版本用ipvs了,這個比iptables效率高。

 

[root@master ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP        16d
redis        ClusterIP   10.106.138.181   <none>        6379/TCP       23h

  

[root@master ~]# kubectl delete svc redis 
service "redis" deleted

  

    注意kubernetes這個service千萬別刪,因為K8s都是通過10.96.0.1這個地址聯系的。

 

[root@master ~]# kubectl explain svc

  

  service類型:

    a)、ExternalName:表示把集群外部的服務引入到集群內部中來,即實現了集群內部pod和集群外部的服務進行通信;

    b)、ClusterIP:只能在集群內部通訊;

    c)、NodePort:可以和集群外部通訊;

    d)、LoadBalancer:這個表示我們把k8s部署在虛擬機上,自動在外部創建負載均衡器。比如在阿里雲上,底層是LBAAS。

ClusterIP

    以前我們使用kubectl expose創建service,下面我們使用清單來創建service。

[root@master manifests]# cat redis-svc.yaml 
apiVersion: v1
kind: Service
metadata:
  name: redis
  namespace: default
spec:
  selector:
    app: redis
    role: logstor
  clusterIP: 10.97.97.97 #這個ip可以不指定,讓它自動分配
  type: ClusterIP
  ports:
  - port: 6379 #service ip中的端口
    targetPort: 6379 #容器ip中的端口

  

[root@master manifests]# kubectl apply -f redis-svc.yaml 
service/redis created

  

[root@master manifests]# kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP    16d
redis        ClusterIP   10.97.97.97   <none>        6379/TCP   1m

  

[root@master manifests]# 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","ports":[{"por...
Selector:          app=redis,role=logstor
Type:              ClusterIP
IP:                10.97.97.97
Port:              <unset>  6379/TCP
TargetPort:        6379/TCP
Endpoints:         10.244.2.65:6379  ##這是pod的ip
Session Affinity:  None
Events:            <none>

  

資源記錄:SVC_NAME.NAMESPACE_NAME.DOMAIN.LTD 

 集群默認后綴是svc.cluster.local 

比如我們創建的redis默認名稱就是redis.defalut.svc.cluster.local

NodePort 

訪問路徑:client---->NodeIP:NodePoint----->ClusterIP:ServerPort---->PodIP:containerPort

 

[root@master manifests]# cat myapp-svc.yaml 
apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  selector:
    app: myapp
    release: canary
  clusterIP: 10.99.99.99 #這個ip可以不指定,讓他自動分配
  type: NodePort
  ports:
  - port: 80 #service ip的端口
    targetPort: 80 #容器ip的端口
    nodePort: 30080 #node節點上端口,這個端口也可以不指定,會自動分配端口

  

[root@master manifests]# kubectl apply -f myapp-svc.yaml 
service/myapp created

  

[root@master manifests]# kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        16d
myapp        NodePort    10.99.99.99   <none>        80:30080/TCP   44s
redis        ClusterIP   10.97.97.97   <none>        6379/TCP       15m

  

[root@master manifests]# curl http://172.16.1.101:30080/hostname.html
myapp-deploy-69b47bc96d-79fqh
[root@master manifests]# curl http://172.16.1.101:30080/hostname.html
myapp-deploy-69b47bc96d-tc54k

  

注意:172.16.1.101是Node節點的Ip,並且可以看到訪問是做了負載均衡的

下面我們再把來自同一個客戶端會話請求用sessionAffinity粘滯到一個固定的pod上,這樣就不會出現負載均衡現象了,相當於nginx的 ip_hash功能,如下:

[root@master manifests]# kubectl patch svc myapp -p '{"spec":{"sessionAffinity":"ClientIP"}}'
service/myapp patched

  

上面打的補丁也可以直接用edit方法編輯。

 

[root@master manifests]# kubectl describe svc myapp
Session Affinity:         ClientIP

  

再改回負載均衡模式:
[root@master manifests]# kubectl patch svc myapp -p '{"spec":{"sessionAffinity":"None"}}'
service/myapp patched

  

 

無頭service 

    我們前面介紹的service是service name解析為cluster ip,然后cluster ip對應到后面的pod ip。 

    而無頭service是指service name 直接解析為后面的pod ip。 

    無頭就是沒有cluster ip牽頭了。 

 

[root@master manifests]# cat myapp-svc-headless.yaml 
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
  namespace: default
spec:
  selector:
    app: myapp #挑選的pod還是myapp。一個pod可以有多個service
    release: canary
  clusterIP: None #None表示是無頭service
  ports:
  - port: 80 #service ip中的端口
    targetPort: 80 #容器ip中的端口

  

[root@master manifests]# kubectl apply -f myapp-svc-headless.yaml 
service/myapp-svc created

  

[root@master manifests]# kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        16d
myapp        NodePort    10.99.99.99   <none>        80:30080/TCP   1h
myapp-svc    ClusterIP   None          <none>        80/TCP         28s
redis        ClusterIP   10.97.97.97   <none>        6379/TCP       1h

  

看到上面myapp-svc的cluster-ip是空,這就是無頭service。

 

[root@master manifests]# kubectl get svc -n kube-system
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP   16d

  

可以看到coreDNS的地址是10.96.0.10

 

[root@master manifests]# dig -t A myapp-svc.default.svc.cluster.local. @10.96.0.10
; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7_5.1 <<>> -t A myapp-svc.default.svc.cluster.local. @10.96.0.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10702
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;myapp-svc.default.svc.cluster.local. INA
;; ANSWER SECTION:
myapp-svc.default.svc.cluster.local. 5 IN A10.244.1.63
myapp-svc.default.svc.cluster.local. 5 IN A10.244.2.51
;; Query time: 0 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Mon Sep 24 00:22:07 EDT 2018
;; MSG SIZE  rcvd: 166

  

[root@master manifests]# kubectl get pods -o wide -l app=myapp
NAME                            READY     STATUS    RESTARTS   AGE       IP            NODE
myapp-deploy-69b47bc96d-79fqh   1/1       Running   0          1d        10.244.1.63   node1
myapp-deploy-69b47bc96d-tc54k   1/1       Running   0          1d        10.244.2.51   node2

  

上面看到無頭service name直接被解析到另個pod上的ip了。 

ExternalName

    我們可以用ExternalName對Service名稱和集群外部服務地址做一個映射,使之訪問Service名稱就是訪問外部服務。例如下面的例子是將 svc1 和 xxx.xxx.xxx.xxx 做了對等關系。

kind: Service
apiVersion: v1
metadata:
  name: svc1
  namespace: default
spec:
  type: ExternalName
  externalName: somedomain.org

  

 不過,ExternalName 類型的服務適用於外部服務使用域名的方式,缺點是不能指定端口。

    另外,要實現集群內訪問集群外服務的這個需求,也是非常簡單的。因為集群內的Pod會繼承Node上的DNS解析規則。因此只要Node可以訪問的服務,Pod中也可以訪問到

 

 

=========================================阿里雲上某個服務的svc文件例子和解釋===========================

apiVersion: v1
kind: Service
metadata:
  annotations:
    service.beta.kubernetes.io/alicloud-loadbalancer-address-type: intranet
    service.beta.kubernetes.io/alicloud-loadbalancer-force-override-listeners: 'false'
    service.beta.kubernetes.io/alicloud-loadbalancer-id: xxxxxxx
  labels:
    app: xxxx
  name: xxxx-inner
  namespace: xxxx-dev
spec:
  clusterIP: 10.129.16.253
  externalTrafficPolicy: Local
  healthCheckNodePort: 30265
  ports:
    - name: azvs-https
      nodePort: 32154
      port: 443
      protocol: TCP
      targetPort: 443
    - name: xxxx
      nodePort: 32470
      port: 80
      protocol: TCP
      targetPort: 8180
  selector:
    app: xxxx
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
      - ip: 10.250.7.77

 

externalTrafficPolicy: Local  表示此服務是否希望將外部流量路由到節點本地或集群范圍的端點。
有兩個可用選項:”Cluster”(默認)和 “Local”。
”Cluster” 隱藏了客戶端源 IP,可能導致第二跳到另一個節點,但具有良好的整體負載分布。
“Local” 保留客戶端源 IP 並避免 LoadBalancer 和 NodePort 類型服務的第二跳,但存在潛在的不均衡流量傳播風險
大白話就是:“Local 會在某個節點上把流量引過來,SLB上只能看到該端口通的那個節點,而Cluster把流量分到后面的所有work節點,阿里的SLB上能看到所有的work節點”


service.beta.kubernetes.io/alicloud-loadbalancer-address-type: intranet 表示內部,把intranet 改成internet就是外部
service.beta.kubernetes.io/alicloud-loadbalancer-force-override-listeners: 'false'  是否強制覆蓋的意思

service.beta.kubernetes.io/alicloud-loadbalancer-id: xxxxxxx 這個就是你的SLB的id
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM