您好,登錄后才能下訂單哦!
到目前為止,kubernetes總共有三種暴露服務的方式:
LoadBlancer Service是kubernetes結合云平臺的組件,如國外的GCE,AWS,國內阿里云等等。使用它項使用的底層云平臺申請創建負載均衡器來實現,對使用云平臺的集群比較方便,但有局限,費用高。
我們之前博文中暴露服務時,用的都是nodeport,實質上就是通過在集群的每個節點上暴露一個端口,然后將這個端口映射到某個具體的service來實現的,比較直觀方便,雖然每個node的端口有很多(0~65535),但是由于安全和易用方面(服務多了就亂了,還有端口沖突問題)且對主機安全性存在一定風險(內網環境,問題不大),所以實際使用并不多,當然對于小規模的集群服務,還是比較不錯的。
以上兩種服務從各方面看似都不太理想,所以通過情況下,我們會通過Ingress對象來實現(安全,方便統一管理)。
在kubernetes集群中,我們知道service和pod的ip僅在集群內部訪問。如果外部應用要訪問集群內的服務,集群外部的請求需要通過負載均衡轉發到service在Node上暴露的NodePort上,然后再由kube-proxy組件將其轉發給相關的pod。
而Ingress就是為進入集群的請求提供路由規則的集合,通俗點就是提供外部訪問集群的入口,將外部的HTTP或者HTTPS請求轉發到集群內部service上。
流程圖如上,其中Ingress代理的并不是pod的service,而是pod,之所以在配置的時候是配置的service,是為了通過service來獲取所有pod的信息。
.
Ingress-nginx一般由三個組件組成:
1)反向代理負載均衡器:通常以service的port方式運行,接收并按照ingress定義的規則進行轉發,常用的有nginx,Haproxy,Traefik等,本文中使用的就是nginx。
2)ingress-nginx-Controller: 監聽APIServer,根據用戶編寫的ingress規則(編寫ingress的yaml文件),動態地去更改nginx服務的配置文件,并且reload重載使其生效,此過程是自動化的(通過lua腳本來實現)。
3)Ingress:將nginx的配置抽象成一個Ingress對象,當用戶每添加一個新的服務,只需要編寫一個新的ingress的yaml文件即可。
1)ingress controller通過和kubernetes api交互,動態的去感知集群中ingress規則變化。
2)然后讀取它,按照自定義的規則,規則就是寫明了那個域名對應哪個service,生成一段nginx配置。
3)在寫到nginx-ingress-controller的pod里,這個Ingress controller的pod里運行著一個Nginx服務,控制器會把生成的nginx配置寫入/etc/nginx.conf文件中。
4)然后reload一下使配置生效,以此達到分配和動態更新問題。
1)動態配置服務:
如果按照傳統方式,當新增加一個服務時,我們可能需要在流量入口加一個反向代理指向我們新的服務,而使用ingress,只需要配置好ingress,當服務啟動時,會自動注冊到ingress當中,不需要額外的操作。
2)減少不必要的Port暴露(安全,端口容易管理)
我們知道部署k8s時,是需要關閉防火墻的,主要原因是k8s的很多服務會以nodeport方式映射出去,這樣對于宿主機來說是非常的不安全的,而ingress可以避免這個問題,只需要將ingress自身服務映射出去,就可代理后端所有的服務,則后端服務不需要映射出去。
本文通過以下配置示例來實踐ingress-nginx:
在本文部署ingress-nginx中所有用到的docker鏡像包,大家可以從我GitHub中進行下載,鏡像包下載鏈接:https://github.com/sqm-sys/Ingress-nginx/releases/tag/v1
1,搭建私有倉庫(registry),并push測試鏡像(apache,tomcat)到倉庫中
#運行registry私有倉庫:
[root@master ~]# docker run -d --name registry --restart=always -p 5000:5000 -v /data/registry:/var/lib/registry registry
#修改docker配置文件:
[root@master ~]# vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H unix:// --insecure-registry 172.16.1.30:5000
#拷貝修改后的docker配置文件到集群其他節點中:
[root@master ~]# scp /usr/lib/systemd/system/docker.service node01:/usr/lib/systemd/system/
[root@master ~]# scp /usr/lib/systemd/system/docker.service node02:/usr/lib/systemd/system/
#集群中所有主機重新加載進程,并重啟docker服務:
[root@master ~]# systemctl daemon-reload
[root@master ~]# systemctl restart docker
#push測試鏡像至私有倉庫:
[root@master ~]# docker push 172.16.1.30:5000/apache:v1
[root@master ~]# docker push 172.16.1.30:5000/tomcat:v1
2,創建namespace
#創建yaml文件:
apiVersion: v1
kind: Namespace
metadata:
name: ingress-test
#創建并查看namespace:
[root@master ~]# kubectl create -f ns.yaml
namespace/ingress-nginx created
[root@master ~]# kubectl get ns
NAME STATUS AGE
default Active 92d
ingress-test Active 4s
3,創建deployment及service資源進行測試
1)創建httpd及service資源:
[root@master ~]# mkdir ingress-nginx
[root@master ~]# cd ingress-nginx/
[root@master ingress-nginx]# vim httpd.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: httpd
namespace: ingress-test
spec:
replicas: 3
template:
metadata:
labels:
name: httpd
spec:
containers:
- name: httpd
image: 172.16.1.30:5000/apache:v1 #鏡像從私有倉庫中進行拉取
---
apiVersion: v1
kind: Service
metadata:
name: httpd-svc
namespace: ingress-test
spec:
type: NodePort
selector:
name: httpd
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 32134
2)創建tomcat及service資源:
[root@master ingress-nginx]# vim tomcat.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: tomcat
namespace: ingress-test
spec:
replicas: 3
template:
metadata:
labels:
name: tomcat
spec:
containers:
- name: tomcat
image: 172.16.1.30:5000/tomcat:v1
---
apiVersion: v1
kind: Service
metadata:
name: tomcat-svc
namespace: ingress-test
spec:
type: NodePort
selector:
name: tomcat
ports:
- protocol: TCP
port: 8080
targetPort: 8080
nodePort: 32135
#創建以上兩個應用,并查看是否創建成功:
[root@master ingress-nginx]# kubectl create -f httpd.yaml
deployment.extensions/httpd created
service/httpd-svc create
[root@master ingress-nginx]# kubectl create -f tomcat.yaml
deployment.extensions/tomcat created
service/tomcat-svc created
3)測試外部通過nodeport方式能否訪問到集群內部應用:
可以看到通過nodeport暴露的方式是沒有問題的,但是到該種方式在大規模的集群服務中,有很大的缺陷,所以接下來通過ingress-nginx進行實現。
1)GitHub上下載yaml文件的網頁鏈接:https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md
進入后顯示以下頁面:
#注意:網頁上完整的命令是直接執行該yaml文件,我們先不要執行,先將該yaml文件下載到本地主機上。(復制命令即可)
[root@master ingress-nginx]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.28.0/deploy/static/mandatory.yaml
[root@master ingress-nginx]# ls
httpd.yaml mandatory.yaml tomcat.yaml
2)修改yaml文件:
[root@master ingress-nginx]# vim mandatory.yaml
#添加以下字段:
hostNetwork: true
如果使用此網絡參數,那么pod中運行的應用程序可以直接使用node節點端口,這樣node節點主機所在的網絡的其他主機,都可以通過訪問到此應用程序。
nodeSelector:
設置節點標簽選擇器,指定在哪臺節點上運行。(保持默認即可,讓它自己選擇,當然大家也可以自定義標簽并選擇運行對應的node)
.
上面鏡像包的版本可能會經常的更新,我用的是當前最新版本0.28.0,大家可以根據自己想用的版本進行下載。
注意:因為默認yaml文件中指定下載地址是國外的鏡像,由于國內網絡環境限制,我們不能直接從google的鏡像站下載鏡像,所以大家可以通過以下方式進行下載:
[root@master ingress-nginx]# docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:0.28.0
3)導入鏡像包-將nginx-ingress-controller.0.28.0鏡像包導入集群中的各個節點:
[root@node01 ~]# docker load < nginx-ingress-controller.0.28.0.tar
[root@node01 ~]# docker images | grep nginx-ingress
registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller 0.28.0 61de39f77f45 7 days ago 305MB
//在master上執行該yaml文件:
//查看ingress-nginx pod是否運行:
[root@master ingress-nginx]# kubectl get pod -n ingress-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-ingress-controller-685985b5b8-8mzjc 1/1 Running 0 43s 172.16.1.32 node02 <none> <none>
4)創建ingress規則(YAML文件)
yaml文件內容如下:
[root@master ingress-nginx]# vim ingress-rule.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
namespace: ingress-test
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: ingress.test.com #后端應用通過該域名進行訪問
http:
paths:
- path: / #apache的網頁根目錄:/
backend:
serviceName: httpd-svc
servicePort: 80
- path: /tomcat #tomcat的網頁更目錄:/tomcat
backend:
serviceName: tomcat-svc
servicePort: 8080
創建該規則就是用于分別代理后端的apache和tomcat服務。
//創建ingress,并查看綁定信息:
[root@master ingress-nginx]# kubectl create -f ingress-rule.yaml
ingress.extensions/test-ingress created
[root@master ingress-nginx]# kubectl get ingresses. -n ingress-test
NAME HOSTS ADDRESS PORTS AGE
test-ingress ingress.test.com 80 17s
#查看describe查看詳細信息(確保成功綁定后端得到apache和tomcat服務)
。
##進入ingress容器查看nginx的配置文件:
[root@master ingress-nginx]# kubectl exec -it -n ingress-nginx nginx-ingress-controller-685985b5b8-8mzjc /bin/sh
/etc/nginx $ cat nginx.conf
通過查看nginx配置文件,我們可以了解到ingress-controller會根據我們編寫的ingress規則(規則就是代理后端應用且會生成一段nginx配置),將nginx配置動態寫入到nginx的配置文件中,并使其reload生效。
5)通過域名訪問集群內的服務
##當前我們需要知道ingress運行在那個node上:
[root@master ingress-nginx]# kubectl get pod -o wide -n ingress-nginx
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-ingress-controller-685985b5b8-8mzjc 1/1 Running 0 31m 172.16.1.32 node02 <none> <none>
我們沒有搭建DNS服務器,所以需要在windows主機上將node02的ip地址添加到hosts文件中,做域名解析:
修改路徑:C:\Windows\System32\drivers\etc\hosts(需要給予修改權限)
172.16.1.32 ingress.test.com #添加該條內容
##訪問httpd:
##訪問tomcat:
6)創建ingress的service資源對象:
雖然上面通過ingress已經能夠代理后端的應用了,但是我們可以發現只能通過指定運行節點的地址來做域名解析(訪問網頁),不能通過集群中的其他節點來訪問,如果該節點掛掉了,則會導致ingress無法代理后端的應用,所以我們需要為ingress創建service資源。
。
GitHub上為我們提供了YAML文件:
##我們將其下載到本地:
[root@master ingress-nginx]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.28.0/deploy/static/provider/baremetal/service-nodeport.yaml
[root@master ingress-nginx]# cat service-nodeport.yaml #不需要我們做修改,這里只是查看下內容
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
- name: https
port: 443
targetPort: 443
protocol: TCP
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
//我們創建該service資源對象:
[root@master ingress-nginx]# kubectl create -f service-nodeport.yaml
service/ingress-nginx created
[root@master ingress-nginx]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.101.206.247 <none> 80:30842/TCP,443:32550/TCP 20s
#可以看到nodeport為我們映射出http和https的隨機端口30842/32550。我們通過此端口,就可指定集群中任意一臺節點的地址都可以代理后端的應用,即使集群中某一節點宕機也不會影響外部通過域名訪問。
##訪問apache:
##訪問tomcat
。
此時在windows主機中的host文件中,隨便綁定集群中的任意節點的ip地址,都是可以進行解析網頁的(大家可自己測試),從而解決了我們之前所擔心的問題,相比于之前nodeport方式,證明ingress可以解決不必要的port暴露,只需要映射ingress的端口,就可以代理后端所有的應用,從而滿足了我們的需求。
.
搭建虛擬主機的目的:實現以不同的域名訪問同一個web界面
本文就僅基于上面的httpd服務,我們為該服務綁定兩個不同的域名來訪問:
##修改ingress規則文件(完整的yaml配置如下)
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
namespace: ingress-test
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: ingress.test.com
http:
paths:
- path: /
backend:
serviceName: httpd-svc
servicePort: 80
- path: /tomcat
backend:
serviceName: tomcat-svc
servicePort: 8080
- host: ingress.test2.com #只需要在rules字段下添加另一個host字段即可,這里只實現httpd的,如果有需求可以添加上tomcat的。
http:
paths:
- path: /
backend:
serviceName: httpd-svc #注意,serviceName所有虛擬主機必須保持一致
servicePort: 80
//創建新的虛擬主機并查看:
[root@master ingress-nginx]# kubectl apply -f ingress-rule.yaml
ingress.extensions/test-ingress configured
[root@master ingress-nginx]# kubectl get ingresses. -n ingress-test
NAME HOSTS ADDRESS PORTS AGE
test-ingress ingress.test.com,ingress.test2.com 10.101.206.247 80 83m
//通過不同的域名進行訪問httpd網頁:
因為我們沒有搭建dns服務器,所以需要在windows hosts文件將新的域名進行綁定(地址可以綁定集群中任意一臺node):
172.16.1.31 ingress.test.com
172.16.1.32 ingress.test2.com
至此,實現了多個不同域名能夠同時訪問后端的應用。
.
通過部署ingress后,我們不必按照常規的,為后端所有的pod都頒發一個證書,只需為ingress代理的域名頒發證書就能夠實現。
1)創建CA證書:
[root@master HTTPS]# openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc" #參數可根據需求自定義
Generating a 2048 bit RSA private key
..............................+++
..+++
writing new private key to 'tls.key'
-----
#創建完成后,會在當前目錄下生成密鑰和證書文件:
[root@master HTTPS]# ls
tls.crt tls.key
2)創建deployment,service,ingress資源:(以nginx服務來實踐)
[root@master HTTPS]# vim nginx-ingress2.yaml
#完整的yaml文件內容如下:
apiVersion: extensions/v1beta1 #創建deployment
kind: Deployment
metadata:
name: web
namespace: ingress-test
spec:
template:
metadata:
labels:
name: test-web
spec:
containers:
- name: web
image: 172.16.1.30:5000/nginx:v1 #私有倉庫中的鏡像(已提供)
---
apiVersion: v1 #創建service,關聯上述deployment
kind: Service
metadata:
name: web-svc
namespace: ingress-test
spec:
selector:
name: test-web
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: extensions/v1beta1 #創建ingress規則
kind: Ingress
metadata:
name: test-ingress2
namespace: ingress-test
spec:
tls: #為域名頒發證書
- hosts:
- ingress.nginx.com
secretName: tls-secret
rules:
- host: ingress.nginx.com
http: #注意,此處字段為http,不支持https
paths:
- path: /
backend:
serviceName: web-svc
servicePort: 80
##創建基于https的ingress服務(nginx):
[root@master HTTPS]# kubectl create -f nginx-ingress2.yaml
deployment.extensions/web created
service/web-svc created
ingress.extensions/test-ingress2 created
##查看ingress資源和映射的service端口:
[root@master HTTPS]# kubectl get pod -n ingress-test | grep web
web-74cf864c58-rnvpx 1/1 Running 0 24s
[root@master HTTPS]# kubectl get ingresses. -n ingress-test
NAME HOSTS ADDRESS PORTS AGE
test-ingress ingress.test.com,ingress.test2.com 10.101.206.247 80 127m
test-ingress2 ingress.nginx.com 10.101.206.247 80, 443 5m32s
#可以看到新創建的ingress提供了80和443端口
//查看ingress的service映射的端口
[root@master HTTPS]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.101.206.247 <none> 80:30842/TCP,443:32550/TCP 86m
3)通過ingress代理的443端口訪問nginx服務:
#在hosts文件中綁定域名:
172.16.1.32 ingress.nginx.com
#訪問網址:https://ingress.nginx.com:32550/
基于HTTPS的ingress服務成功實現,至此,ingress-nginx部署完成。。。。。。。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。