1. 程式人生 > >Kubernetes 實踐之 service

Kubernetes 實踐之 service

請求分發 tps spec eat 直接 sele 服務 節點 emp

service是k8s最核心的概念。通過創建service,可以為一組具有相同功能的容器應用提供一個統一的入口地址,並且將請求負載分發到後端的各個容器應用上去

service定義詳解

ymal格式的service定義文件的完整內容如下

apiVersion: v1            #必須
kind: Service              #必須
matadata:               #必須,元數據
  name: string             #必須,service的名稱
  namespace: string          #非必須,指定的namespace名稱,與rc在同一個namespace即可
labels:                #非必須,service的標簽 - name: string annotations:             #非必須,service的註解屬性信息 - name: string spec:                  #必須,詳細描述 selector: []             #必須,lable selector設置,選擇具有執行lable標簽的pod作為管理範文 type: string             #必須,service的類型,指定service的訪問方式,默認為cluster ip,用於k8s內部的pod訪問, node上的kube-proxy通過設置iptables 轉發
                     nodePort,使用 宿主機的端口,是能夠訪問各node的外部客戶通過node的ip地址和端口就能訪問服務
loadbalancer: 使用外接負載均衡完成服務到負載的分發,需要在spec.status.loadBalancer字段指定負載均衡器的ip,並同時定義nodePort和clusterIP
clusterIP:
string          #非必須,虛擬服務器ip地址 sessionAffinity: string       #非必須,是否支持session,可選值為cluster ip
ports:                 #端口        - name: string            #端口名稱   protocol: string          #協議類型 port: int              #服務監聽的端口號,service clusterip的端口 targetPort: int           #需要轉發到後端pod的端口 nodePort: int            #container port 映射到宿主機的端口 status:                 #當type 為loadBalancer時,說這負載均衡的地址 loadBalancer: ingress:              #外部負載均衡 ip: string           #負載均衡器的ip地址 hostname: string        #外部負載均衡的主機名

  • 一、service的基本用法

創建一個包含兩個tomcat副本rc,並為其創建一個service

[root@k8s_master tomcat-service-rc]# cat webapp-rc.yaml 
apiVersion: v1
kind: ReplicationController 
metadata: 
    name: webapp
    labels:
        name: webapp
spec: 
    replicas: 2
    selector:
        name: webapp
    template: 
        metadata: 
            labels: 
                name: webapp
        spec: 
            containers: 
            - name: webapp
              image: tomcat
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 8080

[root@k8s_master tomcat-service-rc]# kubectl create -f webapp-rc.yaml  


#創建service並查看
[root@k8s_master tomcat-service-rc]# kubectl expose rc webapp    #通過命令行快速創建,一般不采用
service "webapp" exposed

[root@k8s_master tomcat-service-rc]# kubectl get svc
NAME         CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
kubernetes   10.254.0.1       <none>        443/TCP    272d
webapp       10.254.185.154   <none>        8080/TCP   12s
[root@k8s_master tomcat-service-rc]# kubectl describe svc webapp
Name:            webapp
Namespace:        default
Labels:            name=webapp
Selector:        name=webapp
Type:            ClusterIP
IP:            10.254.185.154
Port:            <unset>    8080/TCP
Endpoints:        10.1.20.2:8080,10.1.34.2:8080
Session Affinity:    None
No events.

此時在兩個node 上通過clusterip:8080 均可以訪問 tomcat服務,service將請求分發到兩臺容器上,默認采用了RoundRobin(輪訓rr)模式,
  SessionAffinity : 基於客戶端ip地址進行會話保持的模式,即第一次訪問哪個pod,以後的請求都訪問這個pod
#通過yaml文件的方式創建自定義的service [root@k8s_master tomcat
-service-rc]# cat webapp-service.yaml apiVersion: v1 kind: Service metadata: name: webapp1 labels: name: webapp spec: ports: - port: 8081 targetPort: 8081 selector: name: webapp [root@k8s_master tomcat-service-rc]# kubectl create -f webapp-service.yaml #查看兩個service [root@k8s_master tomcat-service-rc]# kubectl describe svc webapp webapp1 Name: webapp Namespace: default Labels: name=webapp Selector: name=webapp Type: ClusterIP IP: 10.254.185.154 Port: <unset> 8080/TCP Endpoints: 10.1.20.2:8080,10.1.34.2:8080 Session Affinity: None No events. Name: webapp1 Namespace: default Labels: name=webapp Selector: name=webapp Type: ClusterIP IP: 10.254.179.138 Port: <unset> 8081/TCP Endpoints: 10.1.20.2:8080,10.1.34.2:8080 Session Affinity: None No events.

創建一個不帶標簽選擇器的service,即無法選擇後端pod,系統不會自動創建endpoint,因此需要手動創建一個和該service同名的endpoint,用於指向實際的後端訪問地址,如下:

技術分享圖片

  • 二、集群外部訪問pod或者service

  pod和service是集群內的虛擬概念,所有集群外的客戶端系統無法通過pod的ip地址或者service的虛擬ip地址和端口訪問到他們,為了讓客戶端能夠訪問到他們,需要將pod或者service的地址和端口映射到宿主機。

①、將容器應用的端口映射到物理機

容器級別映射

apiVersion: v1
kind: Pod
metadata:
  name: webapp
  labels:
    name: webapp
spec:
  containers:
  - name: webapp
    image: tomcat
    ports:
    - containerPort: 8080       #容器端口
      hostPort: 8081          #宿主機端口(物理機)

  pod級別的設置,hostNetwork=true,該pod中所有容器的端口號都被直接映射到物理機上使用此設置的時候要註意,如果該容器的ports定義部分不指定hostPort(物理機端口),則默認hostPort等於containerPort,如果指定了hostPort,則hostPort必須等於containerPort的值

apiVersion: v1
kind: Pod
metadata:
  name: webapp
  labels:
    name: webapp
spec:
  hostNetwork: true
  containers:
  - name: webapp
    image: tomcat
    ports:
    - containerPort: 8080

此時會將tomcat容器運行的所有端口映射到創建pod的物理機上

②、將service的端口號映射到物理機

  • A、設置NodePort映射到物理機,同時設置service的類型為NodePort
[root@k8s_master tomcat-service-rc]# cat webapp-rc.yaml     #創建一個rc
apiVersion: v1
kind: ReplicationController 
metadata: 
    name: webapp
    labels:
        name: webapp
spec: 
    replicas: 2
    selector:
        name: webapp
    template: 
        metadata: 
            labels: 
                name: webapp
        spec: 
            containers: 
            - name: webapp
              image: tomcat
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 8080

[root@k8s_master tomcat-service-rc]# cat webapp-service.yaml
apiVersion: v1
kind: Service
metadata: 
    name: webapp
    labels:
        name: webapp
spec: 
    type: NodePort
    ports:
      - port: 8080          #service虛擬端口
        targetPort: 8080      #容器端口
        nodePort: 30001        #各node節點開啟的端口,端口範圍 3000-32767
    selector:
        name: webapp

查看

[root@k8s_master tomcat-service-rc]# kubectl get svc -o wide
NAME         CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE       SELECTOR
kubernetes   10.254.0.1      <none>        443/TCP          273d      <none>
webapp       10.254.44.190   <nodes>       8080:30001/TCP   24s       name=webapp

  • B、設置LoadBalancer映射到公網雲服務商(或nginx/lvs/harpoxy)提供的LoadBalancer地址,對該service的訪問請求將會通過LoadBalancer轉發到後端pod上,分發機制依賴於LoadBalancer的實現機制,僅供格式參考
apiVersion: v1
kind: Service
metadata:
    name: my-webapp
    labels:
        name: my-webapp
spec:
    ports:
      - protocol: TCP
        port: 8080
        targetPort: 8080
        nodePort: 30001
    clusterIP: 10.254.44.191
    LoadBalancerIP: 10.20.203.100
    type: LoadBalancer
    selector:
        name: webapp
status:
    LoadBalancer:
        ingress:
        - ip: 10.20.203.100

  • 三、DNS服務搭建

  為了實現通過服務的名字在集群內部進行服務的相互訪問,需要創建虛擬DNS服務來完成服務名到clusterip的解析

k8s提供的虛擬dns服務名為skydns,由四個組件構成

  • (1) etcd: DNS存儲
  • (2) kube2sky: 將k8s master中的service 註冊到etcd
  • (3) skydns: 提供skydns的解析服務
  • (4) healthz:提供對skydns服務的健康檢查功能

工作原理解析

  • 1、kube2sky容器應用通過調用k8s master的api獲得集群中所有srvice的信息,並持續監控新service的生成,然後寫入etcd中
  • 2、根據kubelet啟動參數設置(--cluster-dns),kubectl會在每個新創建的pod中設置dns域名解析配置文件/etc/resolv.conf,在其中增加一條nameserver和一條search
  • 3、最後應用程序就能夠像訪問網站域名一樣,通過服務的名字就能訪問到服務器了

具體搭建信息看 kubernetes DNS

  • 四、Ingress: HTTP 7層路由

  service的表現形式為IP.Port,工作在tcp/ip層,對於基於http的服務來說,不同的url地址要對應到不同的後端服務或者虛擬服務器上去,這些要求通過service機制無法實現,k8s 1.1以後增加的ingress 可以將不同的url訪問請求轉發到後端不同的service,實現http的業務路由機制,在k8s中需要ingress的定義和ingress controller的定義結合起來,才能形成完整的http負載分發能力

示例: 暫時略過

Kubernetes 實踐之 service