K8s Ingress筆記
阿新 • • 發佈:2018-05-20
K8s Ingress 一 要理解一個概念,首先要明白它是幹什麽用的,然後再去理解它是怎麽實現的。Ingress的作用就是提供一個集群外部訪問集群內部的入口。那麽它是怎麽實現的呢,我們知道,集群內部的Cluster IP外部是無法直接訪問到的,而在 K8s集群中,集群外部訪問內部pod中的應用大概有以下幾種形式:
1. 通過開啟proxy模式訪問Cluster IP。這種方式要求我們運行 kubectl 作為一個未認證的用戶,因此我們不能用 這種方式把服務暴露到 internet 或者在生產環境使用。 2. 直接訪問pod,pod中定義hostPort,並設置pod級別的hostwork=true,直接將pod中的端口映射到pod所在的物 理主機或者虛擬機上。通過訪問主機ip:hostPort即可訪問集群內部pod;這種方式只能非常少量使用,否則和直接 使用docker沒多大區別。 3. 先訪問Service,Service可以直接通過集群內部負載均衡至pod中的應用,而外部訪問集群中的Service可以通 過在Service中定義NodePort實現;這種方式在集群中的每臺主機上開放一個隨機的或指定的端口,且每個端口 只能提供一個服務,它是通過端口不同來區分不同應用,而不是通過域名,管理不便,不適合在大規模集群中部 署。 4. 通過LoadBlancer Service訪問Service,這個需要接入雲服務,每個服務都會由雲服務提供一個IP作為入口, 轉發相應的流量,但每個LoadBlancer Service都會產生費用,成本比較高。 5. Ingress,K8s中的API對象,定義了一組規則。Ingress本身只是定義了一組規則,需要配合Ingress controllor 才有意義,不理解Ingress controllor沒關系,繼續往下。
二 如果不通過Ingress,我們也可以手動在Service前部署一個反向代理,比如nginx或者haproxy。
1. nginx運行在集群中,所以可以訪問到集群內部的Service,只需在nginx配置中proxy_pass指向相應的Service Cluster IP或者dns即可,多一個服務也就是多配置一個nginx中的虛擬機主機。 2. 通過設置hostPort即可從外部訪問nginx,再通過nginx反向代理至後端應用的Service;或者不通過hostPort, 再在nginx前端再加一個Service,通過設置Service的NodePort來訪問nginx。
三 通過自己部署nginx反向代理這種方式好像就OK了啊,那一直說的Ingress又是什麽?
Ingress是K8s中的API對象,定義了一組規則,對應於nginx(或者haproxy,traefik等)的一段配置,可以 近似成一段虛擬主機的配置,其實Ingress和自己部署反向代理思路都是一樣的,只不過自己部署反向代理時, 如果新增加一個服務,你自己需要去增加nginx中的配置並重新加載配置,而在Ingress中你增加一個服務,你需 要增加一個Ingress的配置並運行,Ingress會自己去請求K8s的api以獲得新增應用的nds或者Cluster Ip,然後將 你寫的Ingress規則轉換成nginx配置,並修改到ngixn中,然後自動reload nginx。 簡單來說,兩者的區別就是:當新增後端應用時,一種需要增加nginx配置,另外一種需要增加Ingress規 則。你可以簡單的把Ingress理解為一段類似nginx虛擬主機的配置,因為它會自動為你轉換。
四 說道這裏,部署Ingress就很簡單了,不過在Ingress中有它自己的一些術語。一個完整的Ingress有以下幾個組件:
1. 反向代理,可以是nginx、traefik、Haproxy等。
2. Ingress controllor,即Ingress控制器,監聽apiserver,獲取服務新增,刪除等變化,並結合ingress規則動
態更新到反向代理負載均衡器上,並重載配置使其生效。
3. Ingress,K8s的一個資源對象,定義了一組規則,你可以簡單理解為一段對應nginx虛擬機主機的配置。而
實際上,Ingress controllor和反向代理,也就是上面的1,2兩個組件,都是結合在一起的。比如traefik,它同時
具備反向代理和Ingress controllor的功能;如果使用nginx,那麽你需要部署專用的nginx,它也集成了Ingress
controllor。
本文采用traefik來部署反向代理和Ingress controllor,有關traefik的詳細介紹可以參考官網。
五 實際部署。
本文從開始到現在,已經覆蓋了很多的背景和知識。你可能擔心現在會是最難的部分,但實際上它最簡單,
Ingress之所以比較復雜,唯一原因是因為“其他的一切”,而我們已經很好地學完了這些東西。
1. 如果K8s使用了rbac,而Ingress controllor需要訪問apiserver,所以需要先為traefik配置一個Service Account。
cat > traefik-ingress-rbac.yaml << EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-ingress
namespace: kube-system
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress
subjects:
- kind: ServiceAccount
name: traefik-ingress
namespace: kube-system
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
EOF
kubectl apply -f traefik-ingress-rbac.yaml
第一段配置定義了一個Service Account,第二段配置將定義的Service Account綁定到cluster-admin這個已經
存在的ClusterRole上,cluster-admin是具有訪問apiserver的權限的。
2. 然後需要部署一個traefik,並且將它暴露到集群外,它既是反向代理也是Ingress controllor。
cat > traefik-ingress-controller.yaml << EOF
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: traefik-ingress-controller
namespace: kube-system
labels:
k8s-app: traefik-ingress-lb
spec:
replicas: 1
selector:
matchLabels:
k8s-app: traefik-ingress-lb
template:
metadata:
labels:
k8s-app: traefik-ingress-lb
name: traefik-ingress-lb
spec:
terminationGracePeriodSeconds: 60
serviceAccountName: traefik-ingress
containers:
- image: traefik
name: traefik-ingress-lb
resources:
limits:
cpu: 200m
memory: 30Mi
requests:
cpu: 100m
memory: 20Mi
ports:
- containerPort: 80
hostPort: 80
- containerPort: 8080
args:
- --web
- --kubernetes
EOF
kubectl apply -f traefik-ingress-controller.yaml
這是traefik官方文檔的部署文件,我只是在它裏面加了個Service Account,可以看到,它采用設置pod的
hostPort方式來將80端口暴露到集群外,80端口可以看做是反向代理http的端口,接收並轉發所有的定義到Ingress
的流量。而它在pod中還對集群內部有一個8080端口,8080端口一個後端應用,提供了traefik-web-ui。8080端口
是traefik默認的webUI端口,8080端口定義為Pod的端口,集群外部是無法直接訪問到的,所以我們還需要部署一
個Service+Ingress。
3. 部署Service+Ingress
cat > traefik-web-ui.yaml << EOF
apiVersion: v1
kind: Service
metadata:
name: traefik-web-ui
namespace: kube-system
spec:
selector:
k8s-app: traefik-ingress-lb
ports:
- port: 80
targetPort: 8080
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traefik-web-ui
namespace: kube-system
spec:
rules:
- host: traefik-ui.com
http:
paths:
- backend:
serviceName: traefik-web-ui
servicePort: 80
EOF
kubectl apply -f traefik-web-ui.yaml
當你真正要訪問該traefik-ui.com時,你還需要將這個域名綁定到它對應的IP地址,也就是hostPort所在的主
機的IP。配置好hosts文件後,訪問traefik-ui.com。OK
1. 可以看到Ingress中,當訪問traefik-ui.com這個域名時,對應會訪問到名為traefik-web-ui的Service的80
端口中。而Service的80端口對應後端的traefik web UI的8080端口。到此為止,一個完整的Ingress就部署完成
了,它的訪問流程是這樣的:
集群外部訪問traefik-ui.com-->請求會到達traefik所在的主機的IP:hostPort上,也就是IP:80-->由於Ingress規
則此時被轉換成traefik中的反向代理配置,根據Ingress規則會被轉發往traefik-web-ui這個Service:80上-->
Service轉發到後端標簽為 traefik-ingress-lb的pod的8080端口中,實際上又回到了traefik,不過是8080端口。
簡單來說:請求域名---->traefik:80---->Ingress(只是Ingerss規則,實際還是由traefik完成)---->
後端Service:80---->traefik:8080
2. 部署其他後端服務時也是一樣,把上面的後端Service和應用換成相應的就行了。比如部署一個tomcat,那
麽 需要再部署3個K8s資源,分別是tomcat-deployment.yaml、tomcat-service.yaml、tomcat-Ingress.yaml,
你請求的域名為Ingress中的host配置的域名,你請求流程為:
請求域名---->traefik:80---->Ingress(只是Ingerss規則,實際還是由traefik完成)---->tomcat-Service
---->tomcat-deployment中的Pod。
3. 上面是通過hostPort暴露traefik,可以直接訪問80端口,如果需要在多臺node上部署,可以通過給相應
的node 設置lable,然後部署時指定nodeSelector。
我們同樣可以通過Service的NodePort暴露traefik,需要在traefik前再加一個Service,默認NodePort端口
範圍 為30000-32767,如果想直接暴露80端口,需要修改apiserver的配置,tomcat采用該方式的請求流程為:
請求---->traefik-service的Nodeport---->traefik---->Ingress(只是Ingerss規則,實際還是由traefik完成)
---->tomcat-Service---->tomcat-deployment中的Pod。
K8s Ingress筆記