1. Service 的概念:
- k8s中Service定義了這樣一種抽象:一個pod的邏輯分組,一種可以訪問他們的策略—通常稱為微服務(wù)。這一組pod能夠被Service訪問到,通常是通過Label Selector
-
Service能夠提供負載均衡的能力,但是在使用上有以下限制:
- 只提供4層負載均衡能力,而沒有7層功能,但有時我們可能需要更多的匹配規(guī)則來轉(zhuǎn)發(fā)請求,這點上4層負載均衡不支持的。
2. Service的類型:
-
Service在k8s中有以下四種類型:
- ClusterIp:默認類型,自動分配一個僅Cluster內(nèi)部可以訪問的虛擬IP。
- NodePort:在ClusterIp基礎(chǔ)上為Service在每臺機器上綁定一個端口,這樣就可以通過 NodeIP:NodePort來訪問該服務(wù)。
- LoadBalancer:在NodePort的基礎(chǔ)上,借助Cluster Provider創(chuàng)建一個外部負載均衡器,并將請求轉(zhuǎn)發(fā)到NodeIP:NodePort
- ExternalName:把集群外部的服務(wù)引入到集群內(nèi)部來,在集群內(nèi)部直接使用,沒有任何類型代理被創(chuàng)建,這里只有k8s1.7或更高版本的kube-dns才支持。
3. Vip和Service代理
- 在k8s集群中,每個Node運行一個kube-proxy進程。kube-proxy負責(zé)為service實現(xiàn)一種VIP(虛擬IP)的形式,而不是ExternalName的形式。在k8s V1.0版本,代理完全在userspace。在k8s V1.1版本,新增了Iptables代理 ,但不是默認的運行模式。從k8s V1.2版本起,默認就是Iptables代理,在k8s V1.8.0-beta.0中,添加了ipvs代理。在k8s V1.14版本開始模式使用ipvs代理。
- 在k8s v1.0版本,Service是“4層”(TCP/UDP over IP)概念。在K8s v1.1版本,新增了Ingress API(beta版),用來表示“7層”(HTTP)服務(wù)
4. 代理模式的分類:
4.1. userspace代理模式:
4.2. iptables代理模式:
4.3. Ipvs代理模式
-
這種模式,kube-proxy會監(jiān)視k8s service對象和Endpoints,調(diào)用netlink接口以相應(yīng)的創(chuàng)建ipvs規(guī)則并定期與k8s service對象和Endpoints對象同步ipvs規(guī)則,以確保ipvs狀態(tài)與期望一致。訪問服務(wù)時,流量將重定向到后端pod。
-
與iptables類似,ipvs與netfilter的hook功能,但使用哈希表作為底層數(shù)據(jù)結(jié)構(gòu)并在內(nèi)核空間工作。這意味著ipvs可以更快的重定向流量,并且在同步代理規(guī)則時具有更好的性能。此外ipvs為負載均衡算法提供了更多選項,例如:
- rr:輪詢調(diào)度
- lc:最小連接數(shù)
- dh:目標哈希
- sh:源哈希
- sed:最短期望延遲
- nq:不排隊調(diào)度
-
注意:ipvs模式假定在運行kube-proxy之前在節(jié)點上都已經(jīng)安裝了ipvs內(nèi)核模塊。當kube-proxy以ipvs代理模式啟動時,kube-proxy將驗證節(jié)點是否安裝ipvs模塊,如果未安裝,則kube-proxy 將退到iptables代理模式。
5. ClusterlP
- clusterlP主要在每個node節(jié)點使用iptables,將發(fā)向clusterlP對應(yīng)端口的數(shù)據(jù),轉(zhuǎn)發(fā)到kube-proxy中。然后kube-proxy自己內(nèi)部實現(xiàn)有負載均衡的方法,并可以查詢到這個service下對應(yīng)pod的地址和端口,進而把數(shù)據(jù)轉(zhuǎn)發(fā)給對應(yīng)的pod的地址和端口
-
為了實現(xiàn)圖上的功能,主要需要以下幾個組件的協(xié)同工作:
- apiserver用戶通過kubectl命令向apiserver發(fā)送創(chuàng)建service的命令,apiserver接收到情求后將數(shù)據(jù)存儲到etcd中
- kube-proxy kubernetesl的每個節(jié)點中都有一個叫做kube-porxy的進程,這個進程負責(zé)感知service,pod的變化,并將變化的信息寫入本地的iptables規(guī)則中
- iptables使用NAT等技術(shù)將virtuallP的流量轉(zhuǎn)至endpoint中
5.1. 實例:
vim nginx.yaml
apiVersion: apps/v1 #指定使用的API版本
kind: Deployment #指定對象類型為Deployment
metadata: #元數(shù)據(jù)部分,包含名稱和命名空間等信息
name: nginx-deployment #定義deployment的名稱為nginx-deployment
namespace: default #指定創(chuàng)建所在的命名空間
spec: #指定 deployment 對象的配置信息
selector: #選擇器,用于選擇要部署的Pod
matchLabels: #匹配標簽,選擇具有指定標簽的Pod
app: nginx
release: stabel
replicas: 3 #指定要創(chuàng)建的Pod副本數(shù)量
template: #Pod的模板,定義了要創(chuàng)建的Pod的規(guī)范
metadata: #Pod元數(shù)據(jù)部分,包含標簽等信息
labels: #Pod 標簽
app: nginx
release: stabel
spec: #Pod 配置信息
containers: #容器列表信息
- name: nginx #容器名稱
image: nginx:latest #指定容器的鏡像
imagePullPolicy: IfNotPresent #指定容器拉取鏡像策略,本地不存在鏡像時才嘗試拉取新鏡像
ports: #容器暴露的端口列表
- name: http #端口名稱
containerPort: 80 #容器的端口號
---
apiVersion: v1 #指定使用的API版本
kind: Service #指定對象類型為Service
metadata: #元數(shù)據(jù)部分,包含名稱和命名空間等信息
name: nginx-service #定義service的名稱為nginx-service
namespace: default #指定service創(chuàng)建所在的命名空間
spec: #指定 service對象的配置信息
type: ClusterIP #指定Service類型為ClusterIP,即集群內(nèi)部訪問
selector: #選擇器,用于選擇要關(guān)聯(lián)的Pod
app: nginx #匹配具有指定標簽的Pod
release: stabel #匹配具有指定標簽的Pod
ports: #Service暴露的端口列表
- name: http #端口名稱
protocol: TCP #端口協(xié)議
port: 80 #Service的端口號
targetPort: 80 #將流量轉(zhuǎn)發(fā)到Pod的端口號
- 這個示例中,Deployment創(chuàng)建了3個副本的nginx Pod,并將它們的標簽設(shè)置為app: nginx和release: stabel。Service使用相同的標簽選擇與這些Pod關(guān)聯(lián),并在集群內(nèi)部暴露端口80,以便其他Pod可以通過nginx-service:80的方式訪問這些Pod。
5.2. 創(chuàng)建
[root@master1 yaml]# kubectl apply -f nginx.yaml
[root@master1 yaml]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.10.0.1 <none> 443/TCP 8h
nginx-service ClusterIP 10.10.156.191 <none> 80/TCP 12s
[root@master1 yaml]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-77fd88977b-2rlkk 1/1 Running 0 3m3s
nginx-deployment-77fd88977b-979tp 1/1 Running 0 3m3s
nginx-deployment-77fd88977b-g57b5 1/1 Running 0 3m3s
[root@master1 yaml]# curl 10.10.156.191
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
6. Headless Service
- 有時不需要或不想要負載均衡,以及單獨的Service IP。遇到這種情況,可以通過指定ClusterIP(spec.clusterlP)的值為"None"來創(chuàng)建Headless Service。這類Service并不會分配ClusterIP,kube-proxy不會處理它們,而且平臺也不會為它們進行負載均衡和路由
vim nginx-service-headless.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-headless-service
namespace: default
spec:
selector:
app: nginx
release: stabel
clusterIP: "None"
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
6.1. 創(chuàng)建
targetPort: 80
[root@master1 yaml]# kubectl apply -f nginx-service-headless.yaml
service/nginx-headless-service created
[root@master1 yaml]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.10.0.1 <none> 443/TCP 29h
nginx-headless-service ClusterIP None <none> 80/TCP 8s ---可以看的出來clusterIP是空的
nginx-service ClusterIP 10.10.196.214 <none> 80/TCP 42m
6.2. 驗證:
[root@master1 yaml]# yum -y install bind-utils.x86_64
用dns服務(wù)解析nginx-headless-service.default.svc.cluster.local.這個域名下是不是有三個pod的IP地址
[root@master1 yaml]# dig -t A nginx-headless-service.default.svc.cluster.local. @10.244.0.6
7. NodePort
- nodePort的原理在于在node上開了一個端口,將向該端口的流量導(dǎo)入到kube-proxy,然后由kube-proxy進一步到給對應(yīng)的pod
vim nginx-service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport-service
namespace: default
spec:
type: NodePort
selector:
app: nginx
release: stabel
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
nodePort: 30080
7.1. 創(chuàng)建:
[root@master1 yaml]# kubectl apply -f nginx-service-nodeport.yaml
service/nginx-nodeport-service created
[root@master1 yaml]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.10.0.1 <none> 443/TCP 30h
nginx-headless-service ClusterIP None <none> 80/TCP 26m
nginx-nodeport-service NodePort 10.10.113.141 <none> 80:30080/TCP 7s
nginx-service ClusterIP 10.10.196.214 <none> 80/TCP 68m
7.2. 驗證:
8. LoadBalancer
- loadBalancer和nodePort其實是同一種方式。區(qū)別在于loadBalancer比nodePor片多了一步,就是可以調(diào)用cloud provider去創(chuàng)建LB來向節(jié)點導(dǎo)流
文章來源:http://www.zghlxwxcb.cn/news/detail-642935.html
9. ExternalName
- 這種類型的Service通過返回CNAME和它的值,可以將服務(wù)映射到externalName字段的內(nèi)容(例如:hub.atguigu.com)。ExternalName Service是Service的特例,它沒有selector,也沒有定義任何的端口和Endpoint。相反的,對于運行在集群外部的服務(wù),它通過返回該外部服務(wù)的別名這種方式來提供服務(wù)
vim externalname-service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-external-service
namespace: default
spec:
type: ExternalName
externalName: example.com
9.1. 創(chuàng)建:
[root@master1 yaml]# kubectl apply -f externalname-service.yaml
service/my-external-service created
[root@master1 yaml]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.10.0.1 <none> 443/TCP 31h
my-external-service ExternalName <none> example.com <none> 4s
nginx-headless-service ClusterIP None <none> 80/TCP 86m
nginx-nodeport-service NodePort 10.10.113.141 <none> 80:30080/TCP 60m
nginx-service ClusterIP 10.10.196.214 <none> 80/TCP 129m
9.2. 驗證:
[root@master1 yaml]# dig -t A my-external-service.default.svc.cluster.local. @10.244.0.6
文章來源地址http://www.zghlxwxcb.cn/news/detail-642935.html
- 當查詢主機my-external-service.default.svc.cluster.local(SVC_NAME.NAMESPACE.svc.cluster.local)時,集群的DNS服務(wù)將返回一個值my.database.example.com的CNAME記錄。訪問這個服務(wù)的工作方式和其他的相同,唯一不同的是重定向發(fā)生在DNS層,而且不會進行代理或轉(zhuǎn)發(fā)
到了這里,關(guān)于k8s Service服務(wù)詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!