kubernetes——Service與Ingress詳解

為什么需要 Service

在 kubernetes 中淮阐,當(dāng)創(chuàng)建帶有多個(gè)副本的 deployment 時(shí),kubernetes 會創(chuàng)建出多個(gè) pod刁品,此時(shí)即一個(gè)服務(wù)后端有多個(gè)容器泣特,那么在 kubernetes 中負(fù)載均衡怎么做,容器漂移后 ip 也會發(fā)生變化挑随,如何做服務(wù)發(fā)現(xiàn)以及會話保持状您?這就是 Service 的作用,service 是一組具有相同 label pod 集合的抽象镀裤,集群內(nèi)外的各個(gè)服務(wù)可以通過 Service 進(jìn)行互相通信竞阐,當(dāng)創(chuàng)建一個(gè) Service 對象時(shí)也會對應(yīng)創(chuàng)建一個(gè) endpoint 對象,endpoint 是用來做容器發(fā)現(xiàn)的暑劝,Service 只是將多個(gè) pod 進(jìn)行關(guān)聯(lián),實(shí)際的路由轉(zhuǎn)發(fā)都是由 kubernetes 中的 kube-proxy 組件來實(shí)現(xiàn)颗搂,因此担猛,Service 必須結(jié)合 kube-proxy 使用,kube-proxy 組件可以運(yùn)行在 kubernetes 集群中的每一個(gè)節(jié)點(diǎn)上也可以只運(yùn)行在單獨(dú)的幾個(gè)節(jié)點(diǎn)上丢氢,其會根據(jù) service 和 endpoints 的變動來改變節(jié)點(diǎn)上 iptables 或者 ipvs 中保存的路由規(guī)則傅联。

Service 的工作原理

endpoints controller 是負(fù)責(zé)生成和維護(hù)所有 endpoints 對象的控制器,監(jiān)聽 Service 和對應(yīng) pod 的變化疚察,更新對應(yīng) Service 的 endpoints 對象蒸走。當(dāng)用戶創(chuàng)建 Service 后 endpoints controller 會監(jiān)聽 pod 的狀態(tài),當(dāng) pod 處于 running 且準(zhǔn)備就緒時(shí)貌嫡,endpoints controller 會將 pod ip 記錄到 endpoints 對象中比驻,因此该溯,service 的容器發(fā)現(xiàn)是通過 endpoints 來實(shí)現(xiàn)的。而 kube-proxy 會監(jiān)聽 service 和 endpoints 的更新并調(diào)用其代理模塊在主機(jī)上刷新路由轉(zhuǎn)發(fā)規(guī)則别惦。

Service介紹

在kubernetes中狈茉,pod是應(yīng)用程序的載體,我們可以通過pod的ip來訪問應(yīng)用程序掸掸,但是pod的ip地址不是固定的氯庆,這也就意味著不方便直接采用pod的ip對服務(wù)進(jìn)行訪問。

為了解決這個(gè)問題扰付,kubernetes提供了Service資源堤撵,Service會對提供同一個(gè)服務(wù)的多個(gè)pod進(jìn)行聚合,并且提供一個(gè)統(tǒng)一的入口地址羽莺。通過訪問Service的入口地址就能訪問到后面的pod服務(wù)实昨。

Service在很多情況下只是一個(gè)概念,真正起作用的其實(shí)是kube-proxy服務(wù)進(jìn)程禽翼,每個(gè)Node節(jié)點(diǎn)上都運(yùn)行著一個(gè)kube-proxy服務(wù)進(jìn)程屠橄。當(dāng)創(chuàng)建Service的時(shí)候會通過api-server向etcd寫入創(chuàng)建的service的信息,而kube-proxy會基于監(jiān)聽的機(jī)制發(fā)現(xiàn)這種Service的變動闰挡,然后它會將最新的Service信息轉(zhuǎn)換成對應(yīng)的訪問規(guī)則锐墙。

# 10.97.97.97:80 是service提供的訪問入口
# 當(dāng)訪問這個(gè)入口的時(shí)候,可以發(fā)現(xiàn)后面有三個(gè)pod的服務(wù)在等待調(diào)用长酗,
# kube-proxy會基于rr(輪詢)的策略溪北,將請求分發(fā)到其中一個(gè)pod上去
# 這個(gè)規(guī)則會同時(shí)在集群內(nèi)的所有節(jié)點(diǎn)上都生成,所以在任何一個(gè)節(jié)點(diǎn)上訪問都可以夺脾。
[root@node1 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.97.97.97:80 rr
  -> 10.244.1.39:80               Masq    1      0          0
  -> 10.244.1.40:80               Masq    1      0          0
  -> 10.244.2.33:80               Masq    1      0          0

kube-proxy目前支持三種工作模式:

userspace 模式

userspace模式下之拨,kube-proxy會為每一個(gè)Service創(chuàng)建一個(gè)監(jiān)聽端口,發(fā)向Cluster IP的請求被Iptables規(guī)則重定向到kube-proxy監(jiān)聽的端口上咧叭,kube-proxy根據(jù)LB算法選擇一個(gè)提供服務(wù)的Pod并和其建立鏈接蚀乔,以將請求轉(zhuǎn)發(fā)到Pod上。

該模式下菲茬,kube-proxy充當(dāng)了一個(gè)四層負(fù)責(zé)均衡器的角色吉挣。由于kube-proxy運(yùn)行在userspace中,在進(jìn)行轉(zhuǎn)發(fā)處理時(shí)會增加內(nèi)核和用戶空間之間的數(shù)據(jù)拷貝婉弹,雖然比較穩(wěn)定睬魂,但是效率比較低。

在 userspace 模式下镀赌,訪問服務(wù)的請求到達(dá)節(jié)點(diǎn)后首先進(jìn)入內(nèi)核 iptables氯哮,然后回到用戶空間,由 kube-proxy 轉(zhuǎn)發(fā)到后端的 pod商佛,這樣流量從用戶空間進(jìn)出內(nèi)核帶來的性能損耗是不可接受的喉钢,所以也就有了 iptables 模式姆打。

為什么 userspace 模式要建立 iptables 規(guī)則,因?yàn)?kube-proxy 監(jiān)聽的端口在用戶空間出牧,這個(gè)端口不是服務(wù)的訪問端口也不是服務(wù)的 nodePort穴肘,因此需要一層 iptables 把訪問服務(wù)的連接重定向給 kube-proxy 服務(wù)。

iptables 模式

iptables模式下舔痕,kube-proxy為service后端的每個(gè)Pod創(chuàng)建對應(yīng)的iptables規(guī)則评抚,直接將發(fā)向Cluster IP的請求重定向到一個(gè)Pod IP。

該模式下kube-proxy不承擔(dān)四層負(fù)責(zé)均衡器的角色伯复,只負(fù)責(zé)創(chuàng)建iptables規(guī)則慨代。該模式的優(yōu)點(diǎn)是較userspace模式效率更高,但不能提供靈活的LB策略啸如,當(dāng)后端Pod不可用時(shí)也無法進(jìn)行重試侍匙。

iptables 模式是目前默認(rèn)的代理方式,基于 netfilter 實(shí)現(xiàn)叮雳。當(dāng)客戶端請求 service 的 ClusterIP 時(shí)想暗,根據(jù) iptables 規(guī)則路由到各 pod 上,iptables 使用 DNAT 來完成轉(zhuǎn)發(fā)帘不,其采用了隨機(jī)數(shù)實(shí)現(xiàn)負(fù)載均衡说莫。

iptables 模式與 userspace 模式最大的區(qū)別在于,iptables 模塊使用 DNAT 模塊實(shí)現(xiàn)了 service 入口地址到 pod 實(shí)際地址的轉(zhuǎn)換寞焙,免去了一次內(nèi)核態(tài)到用戶態(tài)的切換储狭,另一個(gè)與 userspace 代理模式不同的是,如果 iptables 代理最初選擇的那個(gè) pod 沒有響應(yīng)捣郊,它不會自動重試其他 pod辽狈。

iptables 模式最主要的問題是在 service 數(shù)量大的時(shí)候會產(chǎn)生太多的 iptables 規(guī)則,使用非增量式更新會引入一定的時(shí)延呛牲,大規(guī)模情況下有明顯的性能問題刮萌。

ipvs 模式

ipvs模式和iptables類似,kube-proxy監(jiān)控Pod的變化并創(chuàng)建相應(yīng)的ipvs規(guī)則娘扩。ipvs相對iptables轉(zhuǎn)發(fā)效率更高尊勿。除此以外,ipvs支持更多的LB算法畜侦。

當(dāng)集群規(guī)模比較大時(shí),iptables 規(guī)則刷新會非常慢躯保,難以支持大規(guī)模集群旋膳,因其底層路由表的實(shí)現(xiàn)是鏈表,對路由規(guī)則的增刪改查都要涉及遍歷一次鏈表途事,ipvs 的問世正是解決此問題的验懊,ipvs 是 LVS 的負(fù)載均衡模塊擅羞,與 iptables 比較像的是,ipvs 的實(shí)現(xiàn)雖然也基于 netfilter 的鉤子函數(shù)义图,但是它卻使用哈希表作為底層的數(shù)據(jù)結(jié)構(gòu)并且工作在內(nèi)核態(tài)减俏,也就是說 ipvs 在重定向流量和同步代理規(guī)則有著更好的性能,幾乎允許無限的規(guī)模擴(kuò)張碱工。

ipvs 支持三種負(fù)載均衡模式:DR模式(Direct Routing)娃承、NAT 模式(Network Address Translation)、Tunneling(也稱 ipip 模式)怕篷。三種模式中只有 NAT 支持端口映射历筝,所以 ipvs 使用 NAT 模式。linux 內(nèi)核原生的 ipvs 只支持 DNAT廊谓,當(dāng)在數(shù)據(jù)包過濾梳猪,SNAT 和支持 NodePort 類型的服務(wù)這幾個(gè)場景中ipvs 還是會使用 iptables。

此外蒸痹,ipvs 也支持更多的負(fù)載均衡算法春弥,例如:

  • rr:round-robin/輪詢
  • lc:least connection/最少連接
  • dh:destination hashing/目標(biāo)哈希
  • sh:source hashing/源哈希
  • sed:shortest expected delay/預(yù)計(jì)延遲時(shí)間最短
  • nq:never queue/從不排隊(duì)

userspace、iptables叠荠、ipvs 三種模式中默認(rèn)的負(fù)載均衡策略都是通過 round-robin 算法來選擇后端 pod 的匿沛,在 service 中可以通過設(shè)置 service.spec.sessionAffinity 的值實(shí)現(xiàn)基于客戶端 ip 的會話親和性,service.spec.sessionAffinity 的值默認(rèn)為”None”蝙叛,可以設(shè)置為 “ClientIP”俺祠,此外也可以使用 service.spec.sessionAffinityConfig.clientIP.timeoutSeconds 設(shè)置會話保持時(shí)間。kernelspace 主要是在 windows 下使用的借帘,本文暫且不談蜘渣。

# 此模式必須安裝ipvs內(nèi)核模塊,否則會降級為iptables
# 開啟ipvs
[root@master ~]# kubectl edit cm kube-proxy -n kube-system
[root@master ~]# kubectl delete pod -l k8s-app=kube-proxy -n kube-system
[root@node1 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.97.97.97:80 rr
  -> 10.244.1.39:80               Masq    1      0          0
  -> 10.244.1.40:80               Masq    1      0          0
  -> 10.244.2.33:80               Masq    1      0          0

Service類型

service 支持的類型也就是 kubernetes 中服務(wù)暴露的方式肺然,默認(rèn)有四種 ClusterIP蔫缸、NodePort、LoadBalancer际起、ExternelName拾碌,此外還有 Ingress,下面會詳細(xì)介紹每種類型 service 的具體使用場景街望。

Service的資源清單文件:

kind: Service  # 資源類型
apiVersion: v1  # 資源版本
metadata: # 元數(shù)據(jù)
  name: service # 資源名稱
  namespace: dev # 命名空間
spec: # 描述
  selector: # 標(biāo)簽選擇器校翔,用于確定當(dāng)前service代理哪些pod
    app: nginx
  type: # Service類型,指定service的訪問方式
  clusterIP:  # 虛擬服務(wù)的ip地址
  sessionAffinity: # session親和性灾前,支持ClientIP防症、None兩個(gè)選項(xiàng)
  ports: # 端口信息
    - protocol: TCP 
      port: 3017  # service端口
      targetPort: 5003 # pod端口
      nodePort: 31122 # 主機(jī)端口
  • ClusterIP:默認(rèn)值,它是Kubernetes系統(tǒng)自動分配的虛擬IP,只能在集群內(nèi)部訪問蔫敲。
  • NodePort:將Service通過指定的Node上的端口暴露給外部饲嗽,通過此方法,就可以在集群外部訪問服務(wù)奈嘿。
  • LoadBalancer:使用外接負(fù)載均衡器完成到服務(wù)的負(fù)載分發(fā)貌虾,注意此模式需要外部云環(huán)境支持。
  • ExternalName: 把集群外部的服務(wù)引入集群內(nèi)部裙犹,直接使用尽狠。

Service使用

實(shí)驗(yàn)環(huán)境準(zhǔn)備

在使用service之前,首先利用Deployment創(chuàng)建出3個(gè)pod伯诬,注意要為pod設(shè)置app=nginx-pod的標(biāo)簽

創(chuàng)建deployment.yaml晚唇,內(nèi)容如下:

apiVersion: apps/v1
kind: Deployment      
metadata:
  name: pc-deployment
  namespace: dev
spec: 
  replicas: 3
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.20.1
        ports:
        - containerPort: 80
[root@master ~]# kubectl create -f deployment.yaml
deployment.apps/pc-deployment created

# 查看pod詳情
[root@master ~]# kubectl get pods -n dev -o wide --show-labels
NAME                             READY   STATUS     IP            NODE     LABELS
pc-deployment-66cb59b984-8p84h   1/1     Running    10.244.1.40   node1    app=nginx-pod
pc-deployment-66cb59b984-vx8vx   1/1     Running    10.244.2.33   node2    app=nginx-pod
pc-deployment-66cb59b984-wnncx   1/1     Running    10.244.1.39   node1    app=nginx-pod

# 為了方便后面的測試,修改下三臺nginx的index.html頁面(三臺修改的IP地址不一致)
# kubectl exec -it pc-deployment-66cb59b984-8p84h -n dev /bin/sh
# echo "10.244.1.40" > /usr/share/nginx/html/index.html

#修改完畢之后盗似,訪問測試
[root@master ~]# curl 10.244.1.40
10.244.1.40
[root@master ~]# curl 10.244.2.33
10.244.2.33
[root@master ~]# curl 10.244.1.39
10.244.1.39

ClusterIP類型的Service

ClusterIP 類型的 service 是 kubernetes 集群默認(rèn)的服務(wù)暴露方式哩陕,它只能用于集群內(nèi)部通信,可以被各 pod 訪問赫舒,其訪問方式為:

pod ---> ClusterIP:ServicePort --> (iptables)DNAT --> PodIP:containePort

創(chuàng)建service-clusterip.yaml文件

apiVersion: v1
kind: Service
metadata:
  name: service-clusterip
  namespace: dev
spec:
  selector:
    app: nginx-pod
  clusterIP: 10.97.97.97 # service的ip地址悍及,如果不寫,默認(rèn)會生成一個(gè)
  type: ClusterIP
  ports:
  - port: 80  # Service端口       
    targetPort: 80 # pod端口
# 創(chuàng)建service
[root@master ~]# kubectl create -f service-clusterip.yaml
service/service-clusterip created

# 查看service
[root@master ~]# kubectl get svc -n dev -o wide
NAME                TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE   SELECTOR
service-clusterip   ClusterIP   10.97.97.97   <none>        80/TCP    13s   app=nginx-pod

# 查看service的詳細(xì)信息
# 在這里有一個(gè)Endpoints列表接癌,里面就是當(dāng)前service可以負(fù)載到的服務(wù)入口
[root@master ~]# kubectl describe svc service-clusterip -n dev
Name:              service-clusterip
Namespace:         dev
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx-pod
Type:              ClusterIP
IP:                10.97.97.97
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.39:80,10.244.1.40:80,10.244.2.33:80
Session Affinity:  None
Events:            <none>

# 查看ipvs的映射規(guī)則
[root@master ~]# ipvsadm -Ln
TCP  10.97.97.97:80 rr
  -> 10.244.1.39:80               Masq    1      0          0
  -> 10.244.1.40:80               Masq    1      0          0
  -> 10.244.2.33:80               Masq    1      0          0

# 訪問10.97.97.97:80觀察效果
[root@master ~]# curl 10.97.97.97:80
10.244.2.33

Endpoint

Endpoint是kubernetes中的一個(gè)資源對象心赶,存儲在etcd中,用來記錄一個(gè)service對應(yīng)的所有pod的訪問地址缺猛,它是根據(jù)service配置文件中selector描述產(chǎn)生的缨叫。

一個(gè)Service由一組Pod組成,這些Pod通過Endpoints暴露出來荔燎,Endpoints是實(shí)現(xiàn)實(shí)際服務(wù)的端點(diǎn)集合耻姥。換句話說,service和pod之間的聯(lián)系是通過endpoints實(shí)現(xiàn)的有咨。

負(fù)載分發(fā)策略

對Service的訪問被分發(fā)到了后端的Pod上去琐簇,目前kubernetes提供了兩種負(fù)載分發(fā)策略:

  • 如果不定義,默認(rèn)使用kube-proxy的策略座享,比如隨機(jī)婉商、輪詢

  • 基于客戶端地址的會話保持模式,即來自同一個(gè)客戶端發(fā)起的所有請求都會轉(zhuǎn)發(fā)到固定的一個(gè)Pod上渣叛,此模式可以使在spec中添加sessionAffinity:ClientIP選項(xiàng)

# 查看ipvs的映射規(guī)則【rr 輪詢】
[root@master ~]# ipvsadm -Ln
TCP  10.97.97.97:80 rr
  -> 10.244.1.39:80               Masq    1      0          0
  -> 10.244.1.40:80               Masq    1      0          0
  -> 10.244.2.33:80               Masq    1      0          0

# 循環(huán)訪問測試
[root@master ~]# while true;do curl 10.97.97.97:80; sleep 5; done;
10.244.1.40
10.244.1.39
10.244.2.33
10.244.1.40
10.244.1.39
10.244.2.33

# 修改分發(fā)策略----sessionAffinity:ClientIP

# 查看ipvs規(guī)則【persistent 代表持久】
[root@master ~]# ipvsadm -Ln
TCP  10.97.97.97:80 rr persistent 10800
  -> 10.244.1.39:80               Masq    1      0          0
  -> 10.244.1.40:80               Masq    1      0          0
  -> 10.244.2.33:80               Masq    1      0          0

# 循環(huán)訪問測試
[root@master ~]# while true;do curl 10.97.97.97; sleep 5; done;
10.244.2.33
10.244.2.33
10.244.2.33
  
# 刪除service
[root@master ~]# kubectl delete -f service-clusterip.yaml
service "service-clusterip" deleted

HeadLiness類型的Service

在某些場景中丈秩,開發(fā)人員可能不想使用Service提供的負(fù)載均衡功能,而希望自己來控制負(fù)載均衡策略淳衙,針對這種情況癣籽,kubernetes提供了HeadLiness Service挽唉,這類Service不會分配Cluster IP,如果想要訪問service筷狼,只能通過service的域名進(jìn)行查詢。

創(chuàng)建service-headliness.yaml

apiVersion: v1
kind: Service
metadata:
  name: service-headliness
  namespace: dev
spec:
  selector:
    app: nginx-pod
  clusterIP: None # 將clusterIP設(shè)置為None匠童,即可創(chuàng)建headliness Service
  type: ClusterIP
  ports:
  - port: 80    
    targetPort: 80
# 創(chuàng)建service
[root@master ~]# kubectl create -f service-headliness.yaml
service/service-headliness created

# 獲取service埂材, 發(fā)現(xiàn)CLUSTER-IP未分配
[root@master ~]# kubectl get svc service-headliness -n dev -o wide
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
service-headliness   ClusterIP   None         <none>        80/TCP    11s   app=nginx-pod

# 查看service詳情
[root@master ~]# kubectl describe svc service-headliness  -n dev
Name:              service-headliness
Namespace:         dev
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx-pod
Type:              ClusterIP
IP:                None
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.39:80,10.244.1.40:80,10.244.2.33:80
Session Affinity:  None
Events:            <none>

# 查看域名的解析情況
[root@master ~]# kubectl exec -it pc-deployment-66cb59b984-8p84h -n dev /bin/sh
/ # cat /etc/resolv.conf
nameserver 10.96.0.10
search dev.svc.cluster.local svc.cluster.local cluster.local

[root@master ~]# dig @10.96.0.10 service-headliness.dev.svc.cluster.local
service-headliness.dev.svc.cluster.local. 30 IN A 10.244.1.40
service-headliness.dev.svc.cluster.local. 30 IN A 10.244.1.39
service-headliness.dev.svc.cluster.local. 30 IN A 10.244.2.33

NodePort類型的Service

在之前的樣例中,創(chuàng)建的Service的ip地址只有集群內(nèi)部才可以訪問汤求,如果希望將Service暴露給集群外部使用俏险,那么就要使用到另外一種類型的Service,稱為NodePort類型扬绪。NodePort的工作原理其實(shí)就是將service的端口映射到Node的一個(gè)端口上竖独,然后就可以通過NodeIp:NodePort來訪問service了。

創(chuàng)建service-nodeport.yaml

apiVersion: v1
kind: Service
metadata:
  name: service-nodeport
  namespace: dev
spec:
  selector:
    app: nginx-pod
  type: NodePort # service類型
  ports:
  - port: 80
    nodePort: 30002 # 指定綁定的node的端口(默認(rèn)的取值范圍是:30000-32767), 如果不指定挤牛,會默認(rèn)分配
    targetPort: 80
# 創(chuàng)建service
[root@master ~]# kubectl create -f service-nodeport.yaml
service/service-nodeport created

# 查看service
[root@master ~]# kubectl get svc -n dev -o wide
NAME               TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)       SELECTOR
service-nodeport   NodePort   10.105.64.191   <none>        80:30002/TCP  app=nginx-pod

# 接下來可以通過電腦主機(jī)的瀏覽器去訪問集群中任意一個(gè)nodeip的30002端口莹痢,即可訪問到pod

LoadBalancer類型的Service

LoadBalancer和NodePort很相似,目的都是向外部暴露一個(gè)端口墓赴,區(qū)別在于LoadBalancer會在集群的外部再來做一個(gè)負(fù)載均衡設(shè)備竞膳,而這個(gè)設(shè)備需要外部環(huán)境支持的,外部服務(wù)發(fā)送到這個(gè)設(shè)備上的請求诫硕,會被設(shè)備負(fù)載之后轉(zhuǎn)發(fā)到集群中坦辟。

ExternalName類型的Service

ExternalName類型的Service用于引入集群外部的服務(wù),它通過externalName屬性指定外部一個(gè)服務(wù)的地址章办,然后在集群內(nèi)部訪問此service就可以訪問到外部的服務(wù)了锉走。

apiVersion: v1
kind: Service
metadata:
  name: service-externalname
  namespace: dev
spec:
  type: ExternalName # service類型
  externalName: www.baidu.com  #改成ip地址也可以
# 創(chuàng)建service
[root@master ~]# kubectl  create -f service-externalname.yaml
service/service-externalname created

# 域名解析
[root@master ~]# dig @10.96.0.10 service-externalname.dev.svc.cluster.local
service-externalname.dev.svc.cluster.local. 30 IN CNAME www.baidu.com.
www.baidu.com.          30      IN      CNAME   www.a.shifen.com.
www.a.shifen.com.       30      IN      A       39.156.66.18
www.a.shifen.com.       30      IN      A       39.156.66.14

Ingress介紹

在上面已經(jīng)提到,Service對集群之外暴露服務(wù)的主要方式有兩種:NotePort和LoadBalancer藕届,但是這兩種方式挪蹭,都有一定的缺點(diǎn):

  • NodePort方式的缺點(diǎn)是會占用很多集群機(jī)器的端口,那么當(dāng)集群服務(wù)變多的時(shí)候翰舌,這個(gè)缺點(diǎn)就愈發(fā)明顯嚣潜。
  • LB方式的缺點(diǎn)是每個(gè)service需要一個(gè)LB,浪費(fèi)椅贱、麻煩懂算,并且需要kubernetes之外設(shè)備的支持。

基于這種現(xiàn)狀庇麦,kubernetes提供了Ingress資源對象计技,Ingress只需要一個(gè)NodePort或者一個(gè)LB就可以滿足暴露多個(gè)Service的需求。工作機(jī)制大致如下圖表示:

實(shí)際上山橄,Ingress相當(dāng)于一個(gè)7層的負(fù)載均衡器垮媒,是kubernetes對反向代理的一個(gè)抽象,它的工作原理類似于Nginx,可以理解成在Ingress里建立諸多映射規(guī)則睡雇,Ingress Controller通過監(jiān)聽這些配置規(guī)則并轉(zhuǎn)化成Nginx的反向代理配置 , 然后對外部提供服務(wù)撩轰。在這里有兩個(gè)核心概念:

  • ingress:kubernetes中的一個(gè)對象,作用是定義請求如何轉(zhuǎn)發(fā)到service的規(guī)則
  • ingress controller:具體實(shí)現(xiàn)反向代理及負(fù)載均衡的程序岸更,對ingress定義的規(guī)則進(jìn)行解析陕习,根據(jù)配置的規(guī)則來實(shí)現(xiàn)請求轉(zhuǎn)發(fā),實(shí)現(xiàn)方式有很多观蓄,比如Nginx, Contour, Haproxy等等

Ingress(以Nginx為例)的工作原理如下:

    1. 用戶編寫Ingress規(guī)則混移,說明哪個(gè)域名對應(yīng)kubernetes集群中的哪個(gè)Service
    1. Ingress控制器動態(tài)感知Ingress服務(wù)規(guī)則的變化,然后生成一段對應(yīng)的Nginx反向代理配置
    1. Ingress控制器會將生成的Nginx配置寫入到一個(gè)運(yùn)行著的Nginx服務(wù)中侮穿,并動態(tài)更新
    1. 到此為止歌径,其實(shí)真正在工作的就是一個(gè)Nginx了,內(nèi)部配置了用戶定義的請求轉(zhuǎn)發(fā)規(guī)則

Ingress使用

環(huán)境準(zhǔn)備

搭建ingress環(huán)境

# 創(chuàng)建文件夾
[root@master ~]# mkdir ingress-controller
[root@master ~]# cd ingress-controller/

# 獲取ingress-nginx亲茅,本次案例使用的是0.30版本
[root@master ingress-controller]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
[root@master ingress-controller]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml

# 修改mandatory.yaml文件中的倉庫
# 修改quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
# 為quay-mirror.qiniu.com/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
# 創(chuàng)建ingress-nginx
[root@master ingress-controller]# kubectl apply -f ./

# 查看ingress-nginx
[root@master ingress-controller]# kubectl get pod -n ingress-nginx
NAME                                           READY   STATUS    RESTARTS   AGE
pod/nginx-ingress-controller-fbf967dd5-4qpbp   1/1     Running   0          12h

# 查看service
[root@master ingress-controller]# kubectl get svc -n ingress-nginx
NAME            TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx   NodePort   10.98.75.163   <none>        80:32240/TCP,443:31335/TCP   11h

準(zhǔn)備service和pod

為了后面的實(shí)驗(yàn)比較方便回铛,創(chuàng)建如下圖所示的模型


創(chuàng)建tomcat-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: dev
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
        ports:
        - containerPort: 80

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-deployment
  namespace: dev
spec:
  replicas: 3
  selector:
    matchLabels:
      app: tomcat-pod
  template:
    metadata:
      labels:
        app: tomcat-pod
    spec:
      containers:
      - name: tomcat
        image: tomcat:8.5-jre10-slim
        ports:
        - containerPort: 8080

---

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: dev
spec:
  selector:
    app: nginx-pod
  clusterIP: None
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80

---

apiVersion: v1
kind: Service
metadata:
  name: tomcat-service
  namespace: dev
spec:
  selector:
    app: tomcat-pod
  clusterIP: None
  type: ClusterIP
  ports:
  - port: 8080
    targetPort: 8080
# 創(chuàng)建
[root@master ~]# kubectl create -f tomcat-nginx.yaml

# 查看
[root@master ~]# kubectl get svc -n dev
NAME             TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
nginx-service    ClusterIP   None         <none>        80/TCP     48s
tomcat-service   ClusterIP   None         <none>        8080/TCP   48s

Http代理

創(chuàng)建ingress-http.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-http
  namespace: dev
spec:
  rules:
  - host: nginx.yibo.com
    http:
      paths:
      - path: /
        backend:
          serviceName: nginx-service
          servicePort: 80
  - host: tomcat.yibo.com
    http:
      paths:
      - path: /
        backend:
          serviceName: tomcat-service
          servicePort: 8080
# 創(chuàng)建
[root@master ~]# kubectl create -f ingress-http.yaml
ingress.extensions/ingress-http created

# 查看
[root@master ~]# kubectl get ing ingress-http -n dev
NAME           HOSTS                                  ADDRESS   PORTS   AGE
ingress-http   nginx.yibo.com,tomcat.yibo.com             80      22s

# 查看詳情
[root@master ~]# kubectl describe ing ingress-http  -n dev
...
Rules:
Host                Path  Backends
----                ----  --------
nginx.yibo.com   / nginx-service:80 (10.244.1.96:80,10.244.1.97:80,10.244.2.112:80)
tomcat.yibo.com  / tomcat-service:8080(10.244.1.94:8080,10.244.1.95:8080,10.244.2.111:8080)
...

# 接下來,在本地電腦上配置host文件,解析上面的兩個(gè)域名到192.168.109.100(master)上
# 然后,就可以分別訪問tomcat.yibo.com:32240  和  nginx.yibo.com:32240 查看效果了

Https代理

創(chuàng)建證書

# 生成證書
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/C=CN/ST=BJ/L=BJ/O=nginx/CN=itheima.com"

# 創(chuàng)建密鑰
kubectl create secret tls tls-secret --key tls.key --cert tls.crt

創(chuàng)建ingress-https.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-https
  namespace: dev
spec:
  tls:
    - hosts:
      - nginx.yibo.com
      - tomcat.yibo.com
      secretName: tls-secret # 指定秘鑰
  rules:
  - host: nginx.yibo.com
    http:
      paths:
      - path: /
        backend:
          serviceName: nginx-service
          servicePort: 80
  - host: tomcat.yibo.com
    http:
      paths:
      - path: /
        backend:
          serviceName: tomcat-service
          servicePort: 8080
# 創(chuàng)建
[root@master ~]# kubectl create -f ingress-https.yaml
ingress.extensions/ingress-https created

# 查看
[root@master ~]# kubectl get ing ingress-https -n dev
NAME            HOSTS                                  ADDRESS         PORTS     AGE
ingress-https   nginx.yibo.com,tomcat.yibo.com   10.104.184.38   80, 443   2m42s

# 查看詳情
[root@master ~]# kubectl describe ing ingress-https -n dev
...
TLS:
  tls-secret terminates nginx.yibo.com,tomcat.yibo.com
Rules:
Host              Path Backends
----              ---- --------
nginx.yibo.com  /  nginx-service:80 (10.244.1.97:80,10.244.1.98:80,10.244.2.119:80)
tomcat.yibo.com /  tomcat-service:8080(10.244.1.99:8080,10.244.2.117:8080,10.244.2.120:8080)
...

# 下面可以通過瀏覽器訪問https://nginx.yibo.com:31335 和 https://tomcat.yibo.com:31335來查看了

參考:
https://blog.tianfeiyu.com/2019/10/31/k8s_service_theory/

https://segmentfault.com/a/1190000019376912

https://www.cnblogs.com/baishuchao/p/9429757.html

https://blog.csdn.net/waltonwang/article/details/55236300

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市芯急,隨后出現(xiàn)的幾起案子勺届,更是在濱河造成了極大的恐慌,老刑警劉巖娶耍,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件免姿,死亡現(xiàn)場離奇詭異,居然都是意外死亡榕酒,警方通過查閱死者的電腦和手機(jī)胚膊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來想鹰,“玉大人紊婉,你說我怎么就攤上這事〖希” “怎么了喻犁?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長何缓。 經(jīng)常有香客問我肢础,道長,這世上最難降的妖魔是什么碌廓? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任传轰,我火速辦了婚禮,結(jié)果婚禮上谷婆,老公的妹妹穿的比我還像新娘慨蛙。我一直安慰自己辽聊,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布期贫。 她就那樣靜靜地躺著跟匆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪唯灵。 梳的紋絲不亂的頭發(fā)上贾铝,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天,我揣著相機(jī)與錄音埠帕,去河邊找鬼。 笑死玖绿,一個(gè)胖子當(dāng)著我的面吹牛敛瓷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播斑匪,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼呐籽,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蚀瘸?” 一聲冷哼從身側(cè)響起狡蝶,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎贮勃,沒想到半個(gè)月后贪惹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡寂嘉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年奏瞬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泉孩。...
    茶點(diǎn)故事閱讀 38,605評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡硼端,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出寓搬,到底是詐尸還是另有隱情珍昨,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布句喷,位于F島的核電站镣典,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏脏嚷。R本人自食惡果不足惜骆撇,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望父叙。 院中可真熱鬧神郊,春花似錦肴裙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至夕晓,卻和暖如春宛乃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蒸辆。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工征炼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人躬贡。 一個(gè)月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓谆奥,卻偏偏與公主長得像,于是被迫代替她去往敵國和親拂玻。 傳聞我的和親對象是個(gè)殘疾皇子酸些,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 為什么需要 service 在 kubernetes 中,當(dāng)創(chuàng)建帶有多個(gè)副本的 deployment 時(shí)檐蚜,kub...
    田飛雨閱讀 1,470評論 0 9
  • 這段時(shí)間項(xiàng)目切換新的PaaS平臺魄懂,在新的架構(gòu)中需要使用Service,借此機(jī)會認(rèn)真學(xué)習(xí)了一下Service概念闯第,本...
    大哥你先走閱讀 2,307評論 0 50
  • Service 是為一組具有相同功能的Pod提供一個(gè)統(tǒng)一的入口地址市栗,并將請求進(jìn)行負(fù)載均衡地分發(fā)到各個(gè)Pod上。 S...
    伊凡的一天閱讀 2,428評論 0 2
  • Service 是Kubernetes 最核心的概念、通過創(chuàng)建 Service 可以為一組具有相同功能的容器應(yīng)用提...
    搬板凳嗑瓜子閱讀 2,470評論 0 1
  • Service的概念 kubernetes service定義了這樣一個(gè)抽象:一個(gè)pod的邏輯分組诲泌,一種可以訪問他...
    liu__chao閱讀 231評論 0 0