k8s之Ingress-nginx基本原理及部署實戰

kubernetes服務暴露介紹

到目前爲止,kubernetes總共有三種暴露服務的方式:node

  • LoadBlancer Service
  • NodePort Service
  • Ingress

LoadBlancer Service

LoadBlancer Service是kubernetes結合雲平臺的組件,如國外的GCE,AWS,國內阿里雲等等。使用它項使用的底層雲平臺申請建立負載均衡器來實現,對使用雲平臺的集羣比較方便,但有侷限,費用高。nginx

NodePort Service

咱們以前博文中暴露服務時,用的都是nodeport,實質上就是經過在集羣的每一個節點上暴露一個端口,而後將這個端口映射到某個具體的service來實現的,比較直觀方便,雖然每一個node的端口有不少(0~65535),可是因爲安全和易用方面(服務多了就亂了,還有端口衝突問題)且對主機安全性存在必定風險(內網環境,問題不大),因此實際使用並很少,固然對於小規模的集羣服務,仍是比較不錯的。git

以上兩種服務從各方面看似都不太理想,因此經過狀況下,咱們會經過Ingress對象來實現(安全,方便統一管理)。github

Ingress概述

一,什麼是Ingress?

在kubernetes集羣中,咱們知道service和pod的ip僅在集羣內部訪問。若是外部應用要訪問集羣內的服務,集羣外部的請求須要經過負載均衡轉發到service在Node上暴露的NodePort上,而後再由kube-proxy組件將其轉發給相關的pod。web

而Ingress就是爲進入集羣的請求提供路由規則的集合,通俗點就是提供外部訪問集羣的入口,將外部的HTTP或者HTTPS請求轉發到集羣內部service上。
k8s之Ingress-nginx基本原理及部署實戰
k8s之Ingress-nginx基本原理及部署實戰
流程圖如上,其中Ingress代理的並非pod的service,而是pod,之因此在配置的時候是配置的service,是爲了經過service來獲取全部pod的信息。
.docker

二,Ingress-nginx組成

Ingress-nginx通常由三個組件組成:apache

  • 反向代理負載均衡器
  • Ingress Controller
  • Ingress
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文件便可。

三,Ingress-nginx的工做原理

1)ingress controller經過和kubernetes api交互,動態的去感知集羣中ingress規則變化。
2)而後讀取它,按照自定義的規則,規則就是寫明瞭那個域名對應哪一個service,生成一段nginx配置。
3)在寫到nginx-ingress-controller的pod裏,這個Ingress controller的pod裏運行着一個Nginx服務,控制器會把生成的nginx配置寫入/etc/nginx.conf文件中。
4)而後reload一下使配置生效,以此達到分配和動態更新問題。

四,ingress-nginx解決了生產環境中哪些問題?

1)動態配置服務:
若是按照傳統方式,當新增長一個服務時,咱們可能須要在流量入口加一個反向代理指向咱們新的服務,而使用ingress,只須要配置好ingress,當服務啓動時,會自動註冊到ingress當中,不須要額外的操做。vim

2)減小沒必要要的Port暴露(安全,端口容易管理)
咱們知道部署k8s時,是須要關閉防火牆的,主要緣由是k8s的不少服務會以nodeport方式映射出去,這樣對於宿主機來講是很是的不安全的,而ingress能夠避免這個問題,只須要將ingress自身服務映射出去,就可代理後端全部的服務,則後端服務不須要映射出去。windows

部署Ingress-nginx

本文經過如下配置示例來實踐ingress-nginx:後端

在本文部署ingress-nginx中全部用到的docker鏡像包,你們能夠從我GitHub中進行下載,鏡像包下載連接:https://github.com/sqm-sys/Ingress-nginx/releases

一,部署ingress-nginx前準備:

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

k8s之Ingress-nginx基本原理及部署實戰
k8s之Ingress-nginx基本原理及部署實戰
3)測試外部經過nodeport方式可否訪問到集羣內部應用:
k8s之Ingress-nginx基本原理及部署實戰
k8s之Ingress-nginx基本原理及部署實戰

能夠看到經過nodeport暴露的方式是沒有問題的,可是到該種方式在大規模的集羣服務中,有很大的缺陷,因此接下來經過ingress-nginx進行實現。

二,建立ingress-nginx

1)GitHub上下載yaml文件的網頁連接:https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md

進入後顯示如下頁面:

k8s之Ingress-nginx基本原理及部署實戰
#注意:網頁上完整的命令是直接執行該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
#添加如下字段:
k8s之Ingress-nginx基本原理及部署實戰

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文件:
k8s之Ingress-nginx基本原理及部署實戰

//查看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
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服務)
k8s之Ingress-nginx基本原理及部署實戰

##進入ingress容器查看nginx的配置文件:

[root@master ingress-nginx]# kubectl exec  -it -n ingress-nginx nginx-ingress-controller-685985b5b8-8mzjc  /bin/sh
/etc/nginx $ cat nginx.conf

k8s之Ingress-nginx基本原理及部署實戰
k8s之Ingress-nginx基本原理及部署實戰

經過查看nginx配置文件,咱們能夠清楚的知道以前所說的ingress-controller會根據咱們編寫的ingress規則(代理後端應用),動態的去更改nginx的配置文件。

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>

在windows主機上將node02的ip地址添加到hosts文件中,作域名解析:

修改路徑:C:\Windows\System32\drivers\etc\hosts(須要給予修改權限)
172.16.1.32 ingress.test.com  #添加該條內容

##訪問httpd:
k8s之Ingress-nginx基本原理及部署實戰
##訪問tomcat:
k8s之Ingress-nginx基本原理及部署實戰

6)建立ingress的service資源對象:
雖然上面經過ingress已經可以代理後端的應用了,可是咱們能夠發現只能經過指定運行節點的地址來作域名解析(訪問網頁),不能經過集羣中的其餘節點來訪問,若是該節點掛掉了,則會致使ingress沒法代理後端的應用,因此咱們須要爲ingress建立service資源。

GitHub上爲咱們提供了YAML文件:
k8s之Ingress-nginx基本原理及部署實戰
##咱們將其下載到本地:

[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:
k8s之Ingress-nginx基本原理及部署實戰
##訪問tomcat
k8s之Ingress-nginx基本原理及部署實戰

此時在windows主機中的host文件中,隨便綁定集羣中的任意節點的ip地址,都是能夠進行解析網頁的(你們可本身測試),從而解決了咱們以前所擔憂的問題,相比於以前nodeport方式,證實ingress能夠解決沒必要要的port暴露,只須要映射ingress的端口,就能夠代理後端全部的應用,從而知足了咱們的需求。

.

三,基於虛擬主機的ingress

搭建虛擬主機的目的:實現以不一樣的域名訪問同一個web界面
本文就僅基於上面的httpd服務,咱們爲該服務綁定兩個不一樣的域名來訪問:
##修改ingress規則文件(完整的yaml配置以下)

apiVersion: extensions/v1beta1
kind: Ingress
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

k8s之Ingress-nginx基本原理及部署實戰
k8s之Ingress-nginx基本原理及部署實戰
至此,實現了多個不一樣域名可以同時訪問後端的應用。
.

四,基於HTTPS的Ingress(443端口)

經過部署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/
k8s之Ingress-nginx基本原理及部署實戰基於HTTPS的ingress服務成功實現,至此,ingress-nginx部署完成。。。。。。。

相關文章
相關標籤/搜索