Kubernetes 實踐之 service
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 ipports: #端口 - 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