Kubernetes 學習11 kubernetes ingress及ingress controller


一、上集回顧

  1、Service 3種模型:userspace,iptables,ipvs

  2、Service類型

    ClusterIP,NodePort

      NodePort:client -> NodeIP:NodePort -> ClusterIP:ServicePort -> PodIP:containerPort

      LoadBalancer

      ExternelName

    No ClusterIP: Hedless Service

      serviceName -> PodIP

二、ingress

  1、在客戶端訪問我們k8s服務時,四層調度器本身是沒有辦法解除ssl會話的,這就意味着客戶端必須與后端服務器(pod)之間直接建立ssl會話,這里還有個顯著的問題在於如果調度器在ssl會話建立以后的下一個請求被調度到第二台服務器上那么這個ssl還要重新建立,因此我們只要認為內部網絡是安全的那么我們可以把會話在前端調度器上卸載,但是四層調度是不能卸載的,因此我們需要七層的負載均衡機制。因此如果他們是http服務我們又期望構建https,那么我們只需要他在互聯網上這個不安全的網絡中傳輸實現https,內網中使用http,因此我們需要使用卸載器,但是我們Service調度時,無論是iptables還是ipvs都只是四層調度,因此也就意味着如果你想要在k8s上運行一個應用基於https提供服務,我們就必須得在后端每一個pod上配置https,因為只有這樣他們才會建立起https聯系,所以我們現在也期望在接入那一層上就能夠卸載ssl,向內部調度時就不再是ssl了。對這種需求,k8s采用一種很獨特的方式來實現,我們在整個集群中,在進行調度時后端被代理的pod資源是不配置https的,就是明文的http,但是我使用一個獨特的調度器(運行在pod中),對於此pod來講,其是一個運行在七層(用戶空間)的正常的應用程序,比如nginx,haproxy等,當用戶試圖訪問某一服務時,我們不讓他先去到達前端的service,而是先到這個pod,然后pod與pod之間不需要service而是直接通信來完成反向代理,我們用一個pod來反代至后端我們真正提供服務的pod,此前我們用service代理的,現在用pod,而這個pod如果需要被訪問到那么還是需要經過service,因此客戶端經過此pod的service調度以后,與我們專門配置了https的此pod進行交互,這里的service我們定義成nodePort,依然沒有什么問題,依然老路徑還是存在的,但是等到達這個pod以后由此pod直接代理至兩個明文的pod,因此此pod就成為https的會話卸載器了。如果這種方式進行調度那么調度方式如下:  client --> LB --> nodePort --> service -->會話卸載器pod --> 后端pod  這種方式性能肯定會非常非常差,如圖。

    

  2、其實我們還可以這樣干,可以讓我們pod直接共享我們節點的網絡名稱空間,於是,上述中的會話卸載器pod我們可以直接讓他共享節點網絡名稱空間,這就意味着其監聽着宿主機的地址,這樣我們客戶端的請求就可以之間到達這個pod,然后再由他進行調度。

    

  3、在一個節點上運行的容器,容器可以使用自己的虛擬網絡,也可以共享宿主機的網絡,如果這個容器共享宿主機的網絡也就意味着這個容器內的進程一旦監聽套接字時它監聽的是宿主機的地址,相當於一個進程運行在宿主機上一樣的,這樣一來這個pod在每個節點上就只能運行一個了,一般來講集群中只有一個,那么其只需要運行在集群的某一個節點即可,但是如果 監聽在節點的端口時就會有問題,service時無論訪問哪一個節點的端口都行,因為你訪問哪一個節點的nodePort他都能通過它的ip地址送達到后端pod上,但是現在這個Pod要監聽節點的網絡名稱空間,並且通過這個節點的網絡名稱空間直達這個pod,那么如果運行這種類型的pod那么就一定只能運行在一個節點上,訪問時客戶端就只能訪問這個節點,並且如果這個節點掛了呢?

  4、要解決這個問題,我們可以用DaemonSet控制器,它可以在每個節點上都運行相應的pod 副本並且只運行一個,這樣假如我們有三個節點那么我們三個節點上都可以運行這個pod。這樣就都能實現代理和負載均衡,但是又回到了調度到哪一個節點都可以的問題,這樣無論哪個節點掛掉了都還是可以訪問到,但是如果我們有太多的節點那么每個節點都運行一個這樣的pod就太占資源。daemonset還可以讓pod運行在有限的節點的范圍上(部分節點),於是再將來做k8s集群時可以這樣干,比如我們有三千個節點,那么我們專門拿三個節點出來做pod的接入式的負載均衡的專用主機,並且給這三個節點打上污點讓其它pod無法調度上來,然后我們就定義這個DaemonSet控制器上的pod只運行在這三個節點上各自運行一份並且能容忍這些污點,所以這三個主機在集群中只允許這一個類型的pod,專門負責為集群接入外部的七層調度的流量。而這個pod在k8s中有個專門的稱呼叫 Ingress Controller。這個Ingress Controller比較獨特,之前講的DaemonSet,deployment,replacSet等控制器都不一樣,DaemonSet deployment,replaciSet等等都是作為Controller manager的一部分存在,眾多控制器都是作為Controller manager的一個子組件作為其組成部分組成的。而Ingress Controller卻是自己獨立運行的一個或一組pod資源,它通常就是一個應用程序,這個應用程序就是擁有七層代理能力和調度能力的應用程序,目前k8s上的選擇有四種,其中最不受待見的就是Haproxy,一般默認是nginx,現在在服務網格中大家比較傾向Envoy,當然還有其它與nginx相競爭的據說本來就是為微服務而生的Traefik,所以用Ingress Controller時會發現我們有三種選擇:

    a、nginx:這是后來改造的

    b、Traefik:這種設計就是為微服務這種動態生成而生的

    c、Envoy :去做微服務的大家都比較傾向於Envoy

    

  5、作為調度器,有時候要調度不只一個后端服務,假如有一個調度器pod,后端有一組pod提供電商服務,第二組pod提供了社交服務,第三組pod提供了論壇服務,第四組pod提供了網關服務。那么我們這四組http服務怎么能夠分別調度呢?

    

    a、從nginx的角度來講,接入服務端時我們通過uptream_server即可,但是接入客戶端時我們應該如何標識這四種不同的請求呢,首先我們可以在nginx上做四個虛擬主機,在四個主機名上做四個主機,每一個主機名對應一組后端的pod。那萬一我們沒那么多主機名呢?此時我們可以通過不同的路徑來做url映射,然后每一組路徑就映射到一組后端pod上,但是pod存在生命周期,隨時都可能掛掉替換為一個新pod,新pod的ip就會變了,另外我們pod的應用的規模也可以動態伸縮的,我們簡單改一下副本數其數量也會變,這種一變前面代理的配置也就無效了,我們service通過關聯標簽來解決這個問題,而且service隨時 watch着api server上的api時刻來關注自己關聯的slector的資源是否變動了,只要變動我們api server就會立即通知service然后service立即改變。 所以service通過label selector始終關聯着對應label能適配的后端pod,無論怎么變都能應付而且能及時作出反應,那么此處nginx運行在pod中也就意味着這個配置是在pod內部並且后端pod隨時還會發生變動,Ingress 也會時刻watch着api 中的后端pod資源的改變。那它怎么知道這是哪個pod資源呢?Ingress Controller自己沒有這個能力,它並不知道目前符合自己條件關聯的被代理的pod資源有哪些,它必須借助於service來實現,我們要想定義一個這種調度能力功能其實還是需要建service,這個service通過label selector關聯至后端的pod上來,但這個service不是被當做被代理時的中間節點,它僅僅是幫忙分類的,這個service 關聯了幾個pod那么我們就將這幾個pod配置寫在這個upstream中,調度時是不會經過service的,service在此處僅僅是幫忙分組的,分完組以后我們需要得到的也不是service的IP,而是pod的ip,因此此時可以使用headless service,但是這個service卻沒有用,是不是headless都無所謂,它只要幫忙完成分組知道找哪幾個pod就可以了,pod一變,service對應的資源也就變了,問題是變了后這個結果怎么反應到這個配置文件中來,此時需要依賴於一個專門的資源 Ingress。

  6、在k8s上有一種特殊的資源叫Ingress,Ingress 和Ingress Controller是兩回事,我們定義一個Ingress 時就是說了它其實就是定義我們期望這個Ingress Controller是如何給我們建一個前端(可能是一個虛擬主機,也可能是一個url映射)接入層,同時又給我們定義一個后端upstream_server,這個upstream_server中有幾個主機 Ingress是通過這個service 得到的,並且Ingress有一個特點,作為資源來講他可以通過編輯注入到Ingress Controller里面來,直接把它注入並保存為配置文件,而且一旦Ingress發現Service選定的后端的pod資源發生改變了,這個改變一定會及時返回到Ingress中,這個Ingress會及時注入到這個前端調度器pod中,就是注入到upstream配置文件中,而且還能觸發這個pod中的主容器中的進程重載配置文件。所以我們要想使用這個功能我們需要在集群中:

    a、要有個service去對后端某一個特定類型的pod資源進行分類,這個service只是起分類作用的。

    b、Ingress基於這個分類識別出有幾個pod,並且識別其ip地址是什么,並且將這個ip地址返回的結果生成配置信息注入到upstream_server(以nginx為例),但是nginx又不是特別適用這個場景,每次變動都在重載,如果是Traefik和Envoy 等天生就是為這種場景而生的,只要動了就加載生效,不需要重載。(它可以監控這個配置文件發生變化,只要發生變化就會動態重載)。

  7、如果我們想要使用代理,我們應該怎么做?

    a、需要先部署一個Ingress Controller,然后部署一個pod進來,這個pod可能本來是空的,沒有什么有效的東西,接下來我們要根據自己的需要 通過虛擬主機的方式或者通過url代理的方式來配置一個前端,然后再根據我們Service收集到的后端pod的IP定義成upstream_server,把這些信息反應在Ingress當中由Ingress動態注入到Ingress Controller中才可以

    

    

    b、從圖中我們可以看到,當訪問我們服務時首先由外部的負載均衡器將請求調度到我們nodePort的Service上,而nodePort上的Service再將請求調度至我們內部的一個pod 叫IngressController上來,Ingress Controller根據Ingress中的定義(虛擬主機或url),每一個主機名對應后面的一組pod資源(通過service分組),因此此處用到兩組Service,第一個Service是幫集群接入外部流量的(當然也可以不用,可以把這個Ingress Controller pod運行為共享網絡節點網絡名稱空間方式並且將其定義為Dameset方式運行在特定節點上就可以了),那么我們在定義pod資源時只需要在pod的一個配置選項中加入hostnetwork即可。第二個Service只用來做pod歸組不被調度時使用。

    c、接下來我們要使用ingress的功能得先去安裝部署Ingress Controller 這個pod,而后再定義Ingress,而后再定義后端pod生成Service,然后再建立關聯關系。

三、Ingress 定義

  1、Ingress 也是標准的kubernetes資源對象,因此也擁有相應的對象屬性。

[root@k8smaster ~]# kubectl explain ingress.spec
KIND:     Ingress
VERSION:  extensions/v1beta1

RESOURCE: spec <Object>

DESCRIPTION:
     Spec is the desired state of the Ingress. More info:
     https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status

     IngressSpec describes the Ingress the user wishes to exist.

FIELDS:
   backend    <Object> #定義后端主機,定義后端有哪幾個pod,其屬性有serviceName和sericePort
     A default backend capable of servicing requests that don't match any rule.
     At least one of 'backend' or 'rules' must be specified. This field is
     optional to allow the loadbalancer controller or defaulting logic to
     specify a global default.

   rules    <[]Object>  #定義規則,分為主機和http,http又有paths路徑定義調度到哪兒去。 (即主機調度和路徑調度兩種方式)
     A list of host rules used to configure the Ingress. If unspecified, or no
     rule matches, all traffic is sent to the default backend.

   tls    <[]Object>
     TLS configuration. Currently the Ingress only supports a single TLS port,
     443. If multiple members of this list specify different hosts, they will be
     multiplexed on the same port according to the hostname specified through
     the SNI TLS extension, if the ingress controller fulfilling the ingress
     supports SNI.
[root@k8smaster ~]# kubectl explain ingress.spec.backend
KIND:     Ingress
VERSION:  extensions/v1beta1

RESOURCE: backend <Object>

DESCRIPTION:
     A default backend capable of servicing requests that don't match any rule.
     At least one of 'backend' or 'rules' must be specified. This field is
     optional to allow the loadbalancer controller or defaulting logic to
     specify a global default.

     IngressBackend describes all endpoints for a given service and port.

FIELDS:
   serviceName    <string> -required-   #backend正是靠我們service的定義來找到我們后端相關聯的有哪幾個pod資源的,一旦pod資源發生變化這個service就發生變化,service變化Ingress就變化,
Ingress變化就開始注入到Ingress Controller中去。
     Specifies the name of the referenced service.

   servicePort    <string> -required-
     Specifies the port of the referenced service.

   2、部署Ingress,k8s集群由master,node和附件組成,一共有四個核心附件:

    a、dns

    b、Heapster

    c、Dashboard

    d、Ingress Controller

四、Ingress創建

  1、首先下載github上對應的yaml文件

[root@k8smaster ingress-nginx]# for file in namespace.yaml configmap.yaml rbac.yaml tcp-services-configmap.yaml with-rbac.yaml udp-services-configmap.yaml default-backend.yaml; \
> do wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.17.1/deploy/$file; done
...

  2、將下載yaml文件創建使用

[root@k8smaster ingress-nginx]# ls
configmap.yaml  namespace.yaml  rbac.yaml  tcp-services-configmap.yaml  udp-services-configmap.yaml  with-rbac.yaml
[root@k8smaster ingress-nginx]# kubectl apply -f namespace.yaml 
namespace/ingress-nginx created
[root@k8smaster ingress-nginx]# kubectl apply -f ./
configmap/nginx-configuration created
namespace/ingress-nginx configured
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-role created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
configmap/tcp-services created
configmap/udp-services created
deployment.extensions/nginx-ingress-controller created

  也可直接使用一次性部署yaml文件

  kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
[root@k8smaster ingress-nginx]# kubectl get pods -n ingress-nginx -o wide
NAME                                       READY     STATUS    RESTARTS   AGE       IP            NODE
default-http-backend-846b65fb5f-ggwwp      1/1       Running   0          29m       10.244.1.77   k8snode1
nginx-ingress-controller-d658896cd-nqt4b   1/1       Running   21         2h        10.244.2.76   k8snode2

  3、嘗試創建Ingress,為了讓某個Ingress能顯現真正的效果來我們要做一些前提准備,比如我們要部署幾個后端被代理的應用

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations: #此屬性至關重要,因為在annotations中我們必須指明ingress controller類型是nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /testpath
        backend:
          serviceName: test
          servicePort: 80

  4、直接部署在裸機上時要額外加上一項叫做service-nodeport.yaml,如果不加上這一項會發現ingress controller部署完以后在集群內部可以被訪問,在集群外部是無法被訪問到的,因為ingress controller無法接入外部的流量,如果要接入流量則需要再部署一個nodePort的service,或者也可以將ingress controller部署為直接共享節點網絡名稱空間的方式,但這個時候我們需要手動改造with-rbac.yaml這個文件中的kind 類型由Deployent改為DaemonSet,然后去掉replicas,然后在pod template上的spec中加一項hostnetwork用於共享宿主機的網絡名稱空間,當然需要保證監聽的端口不被沖突。 

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/baremetal/service-nodeport.yaml
  5、接下來可以嘗試使用ingress規則來應用
    a、首先創建一組應用pod和對應的service
[root@k8smaster ingress]# cat deploy-demo.yaml 
apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  selector: 
    app: myapp
    release: canary
  ports:
  - name: http
    targetPort: 80
    port: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 3
  selector: 
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata:
      labels:
        app: myapp
        release: canary
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v2
        ports: 
        - name: http
          containerPort: 80 

    b、創建nodePort service

[root@k8smaster ingress-nginx]# cat service-nodeport.yaml 
apiVersion: v1
kind: Service 
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
spec:
  type: NodePort
  ports:
    - name: http #服務為http
      port: 80   #service端口為80
      targetPort: 80 #容器端口為80
      protocol: TCP
      nodePort: 30080
    - name: https
      port: 443 #service 端口為443
      targetPort: 443 #容器端口為443
      protocol: TCP
      nodePort: 30443
  selector:
    app: ingress-nginx
---

[root@k8smaster ingress-nginx]# kubectl apply -f ./
configmap/nginx-configuration unchanged
deployment.extensions/default-http-backend unchanged
service/default-http-backend unchanged
namespace/ingress-nginx configured
serviceaccount/nginx-ingress-serviceaccount unchanged
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole configured
role.rbac.authorization.k8s.io/nginx-ingress-role unchanged
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding unchanged
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding configured
service/ingress-nginx created
configmap/tcp-services unchanged
configmap/udp-services unchanged
deployment.extensions/nginx-ingress-controller unchanged

  [root@k8smaster ingress]# kubectl get pods -n ingress-nginx -o wide --show-labels
  NAME READY STATUS RESTARTS AGE IP NODE LABELS
  default-http-backend-846b65fb5f-ggwwp 1/1 Running 1 1d 10.244.1.82 k8snode1 app=default-http-backend,pod-template-hash=4026219619
  nginx-ingress-controller-d658896cd-nqt4b 1/1 Running 22 1d 10.244.2.81 k8snode2 app=ingress-nginx,pod-template-hash=821445278

    此時訪問我們節點端口顯示  default backend - 404 ,此時表示我們調度器已經正常工作。

    c、此時將步驟a中創建的myapp Deploymet開始使用我們b中這個Service發布出去而不在我們里面同時創建的這個service上自己改成nodePort發布出去了

[root@k8smaster ingress]# cat ingress-myapp.yaml 
apiVersion: extensions/v1beta1
Kind: Ingress
metadata:
  name: ingress-myapp
  namespaces: default
  annotations: #進行說明我們接下來要用到的規則是nginx,就是靠annotations來識別類型的,只有進行注解了才能轉化為對應的與controller相匹配的規則
    kubernetes.io/ingress.class: "nginx"
spec:
  rules: #定義把誰轉到誰那兒去
  - host: myapp.wohaoshuai.com #要確保在外部通過互聯網訪問時能解析此主機名,並且解析結果剛好能到達我們Service nodePort映射的主機上去
    http: #定義前后端路徑
      paths: #不給默認為/
      - path: #前端路徑,空表示默認的/ 
        backend: #匹配后端service 
          serviceName: myapp
          servicePort: 80

[root@k8smaster ingress]# kubectl apply -f ingress-myapp.yaml 
ingress.extensions/ingress-myapp created
[root@k8smaster ingress]# kubectl get ingress
NAME            HOSTS                  ADDRESS   PORTS     AGE
ingress-myapp   myapp.wohaoshuai.com             80        10s
[root@k8smaster ingress]# kubectl describe ingress ingress-myapp
Name:             ingress-myapp
Namespace:        default
Address:          
Default backend:  default-http-backend:80 (<none>)
Rules:
  Host                  Path  Backends
  ----                  ----  --------
  myapp.wohaoshuai.com  
                           myapp:80 (<none>)
Annotations:
  kubectl.kubernetes.io/last-applied-configuration:  {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{"kubernetes.io/ingress.class":"nginx"},"name":"ingress-my
app","namespace":"default"},"spec":{"rules":[{"host":"myapp.wohaoshuai.com","http":{"paths":[{"backend":{"serviceName":"myapp","servicePort":80},"path":null}]}}]}}
  kubernetes.io/ingress.class:  nginx
Events:
  Type    Reason  Age   From                      Message
  ----    ------  ----  ----                      -------
  Normal  CREATE  30s   nginx-ingress-controller  Ingress default/ingress-myapp

    d、上述創建完成的ingress一旦應用其會自動注入到ingress controller中去,也就是說其會自動轉換成nginx的配置文件(從下面信息中可看到),訪問myapp.wohaoshuai.com:30080即可

[root@k8smaster ingress]# kubectl get pods -n ingress-nginx
NAME                                       READY     STATUS    RESTARTS   AGE
default-http-backend-846b65fb5f-ggwwp      1/1       Running   0          1h
nginx-ingress-controller-d658896cd-nqt4b   1/1       Running   21         4h
[root@k8smaster ingress]# kubectl exec -it nginx-ingress-controller-d658896cd-nqt4b /bin/bash -n ingress-nginx
www-data@nginx-ingress-controller-d658896cd-nqt4b:/etc/nginx$ ls
fastcgi.conf          fastcgi_params.default  koi-win      mime.types.default  nginx.conf      owasp-modsecurity-crs  template           win-utf
fastcgi.conf.default  geoip              lua      modsecurity          nginx.conf.default  scgi_params         uwsgi_params
fastcgi_params          koi-utf              mime.types  modules          opentracing.json      scgi_params.default     uwsgi_params.default
www-data@nginx-ingress-controller-d658896cd-nqt4b:/etc/nginx$ cat nginx.conf|grep wohaoshuai
    ## start server myapp.wohaoshuai.com
        server_name myapp.wohaoshuai.com ;
    ## end server myapp.wohaoshuai.com

 

     從上面配置文件中可以看出svc只是起到了識別后端pod信息的作用而不起調度作用

五、創建一個真正可用的ingress 實例

  1、我們現在做這么一個東西,本來我們起了兩到三個tomcat pod,每個pod監聽自己的8080和8009端口,因此我們在三個pod之前做一個Service作為一個固定訪問端點代理,但是這個Service待會兒不會用到,它只是用來識別而已,我們Service對應的8080和8009端口對應后端pod的8080和8009端口。我們定義一個deployment來部署這三個tomcat,用來監聽8080和8009端口,然后定義一個Service把8080和8009暴露出去,但是沒有真正向集群外部暴露,因為其是cluster IP類型的,他只是用來被前端等會兒叫ingress  controller定義ingress規則向里面映射的時候所識別后端有哪幾個Pod而已。

    

  2、創建Deployment 和 Service,然后創建ingress

[root@k8smaster ingress]# cat tomcat-deploy.yaml 
apiVersion: v1
kind: Service
metadata:
  name: tomcat 
  namespace: default
spec:
  selector: 
    app: tomcat
    release: canary
  ports:
  - name: http
    targetPort: 8080
    port: 8080
  - name: ajp
    targetPort: 8009
    port: 8009
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-deploy
  namespace: default
spec:
  replicas: 3
  selector: 
    matchLabels:
      app: tomcat
      release: canary
  template:
    metadata:
      labels:
        app: tomcat
        release: canary
    spec:
      containers:
      - name: myapp
        image: tomcat:8.5.32-jre8-alpine
        ports: 
        - name: http
          containerPort: 8080
        - name: ajp
          containerPort: 8009

[root@k8smaster ingress]# kubectl apply -f tomcat-deploy.yaml 
service/tomcat created
deployment.apps/tomcat-deploy created
[root@k8smaster ingress]# cat ingress-tomcat.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-tomcat
  namespace: default
  annotations: #進行說明我們接下來要用到的規則是nginx,就是靠annotations來識別類型的,只有進行注解了才能轉化為對應的與controller相匹配的規則
    kubernetes.io/ingress.class: "nginx"
spec:
  rules: #定義把誰轉到誰那兒去
  - host: tomcat.wohaoshuai.com #要確保在外部通過互聯網訪問時能解析此主機名,並且解析結果剛好能到達我們Service nodePort映射的主機上去
    http: #定義前后端路徑
      paths: #不給默認為/
      - path: #前端路徑,空表示默認的/ 
        backend: #匹配后端service 
          serviceName: tomcat
          servicePort: 8080  #我們沒有指ingress所以默認ingress是80端口
[root@k8smaster ingress]# kubectl apply -f ingress-tomcat.yaml 
ingress.extensions/ingress-myapp configured

     創建完成后在各節點host文件添加tomcat.lwohaoshuai.com解析訪問 tomcat.wohaoshuai.com:30080即可

   3、如果我們想要創建https的虛擬主機就稍微要麻煩一點,第一,這個虛擬主機要工作為https服務的話在nginx上這個虛擬主機得是ssl虛擬主機配置為ssl虛擬主機則需要證書和私鑰,而這個證書和私鑰我們需要將其創建為特定格式才能提供給我們的ingress.那么現在我們做一組證書和私鑰並且把它們作為一個獨特的對象,這個叫secret。  

    a、創建私鑰和證書

[root@k8smaster ingress]# openssl genrsa -out tls.key 2048 #創建私鑰
Generating RSA private key, 2048 bit long modulus
..+++
........................................+++
e is 65537 (0x10001)
[root@k8smaster ingress]# ls
deploy-demo.yaml  ingress-myapp.yaml  ingress-tomcat.yaml  tls.key  tomcat-deploy.yaml
[root@k8smaster ingress]# openssl req -new -x509 -key tls.key -out tls.crt(自簽證書) -subj /C=CN/ST=Beijing/L=Beijing/O=DevOps/CN=tomcat.wohaoshuai.com(國家為CN,所在的省為北京,地址為北京,組織為DevOps,此外,證書中應該包含的名字應該和此前定義的域名一致,為tomcat.wohaoshuai.com) #創建自簽證書
[root@k8smaster ingress]# ls
deploy-demo.yaml  ingress-myapp.yaml  ingress-tomcat.yaml  tls.crt  tls.key  tomcat-deploy.yaml 

    b、注意生成的證書是不能直接貼到nginx的pod中去的,我們需要把它先轉成特殊格式,這個特殊格式叫secret,它也是標准的k8s集群對象,它可以直接注入到pod中被pod所引用。因此接下來我們需要把它做成secret

[root@k8smaster ingress]# kubectl create secret tls tomcat-ingress-secret --cert=tls.crt --key=tls.key
secret/tomcat-ingress-secret created
[root@k8smaster ingress]# kubectl get secret
NAME                    TYPE                                  DATA      AGE
default-token-jvtl7     kubernetes.io/service-account-token   3         36d
tomcat-ingress-secret   kubernetes.io/tls                     2         15s
[root@k8smaster ingress]# kubectl describe secret tomcat-ingress-secret
Name:         tomcat-ingress-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/tls

Data
====
tls.crt:  1306 bytes
tls.key:  1679 bytes

    c、創建完以后我們就可以拿這個secret在ingress.spec.rules中定義了

 

[root@k8smaster ingress]# kubectl explain ingress.spec.tls
KIND:     Ingress
VERSION:  extensions/v1beta1

RESOURCE: tls <[]Object>

DESCRIPTION:
     TLS configuration. Currently the Ingress only supports a single TLS port,
     443. If multiple members of this list specify different hosts, they will be
     multiplexed on the same port according to the hostname specified through
     the SNI TLS extension, if the ingress controller fulfilling the ingress
     supports SNI.

     IngressTLS describes the transport layer security associated with an
     Ingress.

FIELDS:
   hosts    <[]string> #表示把哪個主機做成tls格式的
     Hosts are a list of hosts included in the TLS certificate. The values in
     this list must match the name/s used in the tlsSecret. Defaults to the
     wildcard host setting for the loadbalancer controller fulfilling this
     Ingress, if left unspecified.

   secretName    <string> #用哪個secret來獲取證書,私鑰等相關信息
     SecretName is the name of the secret used to terminate SSL traffic on 443.
     Field is left optional to allow SSL routing based on SNI hostname alone. If
     the SNI host in a listener conflicts with the "Host" header field used by
     an IngressRule, the SNI host is used for termination and value of the Host
     header is used for routing.

 

[root@k8smaster ingress]# kubectl apply -f ingress-tomcat-tls.yaml 
ingress.extensions/ingress-tomcat-tls created
[root@k8smaster ingress]# cat ingress-tomcat-tls.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-tomcat-tls
  namespace: default
  annotations: #進行說明我們接下來要用到的規則是nginx,就是靠annotations來識別類型的,只有進行注解了才能轉化為對應的與controller相匹配的規則
    kubernetes.io/ingress.class: "nginx"
spec:
  tls: 
  - hosts:
    - tomcat.wohaoshuai.com
    secretName: tomcat-ingress-secret
  rules: #定義把誰轉到誰那兒去
  - host: tomcat.wohaoshuai.com #要確保在外部通過互聯網訪問時能解析此主機名,並且解析結果剛好能到達我們Service nodePort映射的主機上去
    http: #定義前后端路徑
      paths: #不給默認為/
      - path: #前端路徑,空表示默認的/ 
        backend: #匹配后端service 
          serviceName: tomcat
          servicePort: 8080  #我們沒有指ingress所以默認ingress是80端口
[root@k8smaster ingress]# kubectl get ingress
NAME                 HOSTS                   ADDRESS   PORTS     AGE
ingress-myapp        myapp.wohaoshuai.com              80        20h
ingress-tomcat       tomcat.wohaoshuai.com             80        18h
ingress-tomcat-tls   tomcat.wohaoshuai.com             80, 443   33s
[root@k8smaster ingress]# kubectl describe ingress ingress-tomcat-tls 
Name:             ingress-tomcat-tls
Namespace:        default
Address:          
Default backend:  default-http-backend:80 (<none>)
TLS:
  tomcat-ingress-secret terminates tomcat.wohaoshuai.com
Rules:
  Host                   Path  Backends
  ----                   ----  --------
  tomcat.wohaoshuai.com  
                            tomcat:8080 (<none>)
Annotations:
  kubectl.kubernetes.io/last-applied-configuration:  {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{"kubernetes.io/ingress.class":"nginx"},"name":"ingress-to
mcat-tls","namespace":"default"},"spec":{"rules":[{"host":"tomcat.wohaoshuai.com","http":{"paths":[{"backend":{"serviceName":"tomcat","servicePort":8080},"path":null}]}}],"tls":[{"hosts":["tomcat.wohaoshuai.com"],"secretName":"tomcat-ingress-secret"}]}}
  kubernetes.io/ingress.class:  nginx
Events:
  Type    Reason  Age   From                      Message
  ----    ------  ----  ----                      -------
  Normal  CREATE  1m    nginx-ingress-controller  Ingress default/ingress-tomcat-tls
[root@k8smaster ingress]# kubectl exec -it nginx-ingress-controller-d658896cd-nqt4b /bin/bash -n ingress-nginx
www-data@nginx-ingress-controller-d658896cd-nqt4b:/etc/nginx$ cat nginx.conf|grep ssl

      通過https://tomcat.wohaoshuai.com:30443訪問即可。可以看到我們ssl主機建立起來了,但是我們后端pod並沒有提供任何ssl功能

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM