k8s使用nginx-controller的時候出現404

最近再研究怎麼自己搭建HA k8s的集群

一個意外令我花了不少時間研究的問題是在於怎麼裝k8s的ingress-controller

一般來說要開放k8s上的服務給外邊的人使用的時候

簡單方法可以直接起一個NodePort的service把服務開放給別人

但這樣有一個麻煩一來不知道service會被部署到哪台伺服器,二來不知道會用哪個port

因此有個變通的方法是使用ingress

直接使用NodePort在存取服務的時候是使用

http://某個節點:某個port

這樣一個方式

而使用ingress的話,可以簡單變成

http://ingress-controller-url/某個路徑

這樣的好處是當服務一多的時候,有個統一的出口,只是配著不同的路徑

可以減少設定防火牆還是VIP等等時候的負擔

而一個ingress是個設定檔,單純描述服務跟path的映射像是下面這樣

...
    http:
      paths:
      - path: /app
        backend:
          serviceName: appsvc1
          servicePort: 80

除此之外還需要一個ingress-controller的角色,實際去擔任開放服務給外邊的任務

我這邊是使用nginx-ingress-controller去充當這任務
https://github.com/kubernetes/ingress-nginx

nginx-ingress-controller的簡化安裝方法如下

初始化nginx-ingress-controller環境

  1. 設定ingress-controller用的namespace
  2. 安裝default-backend
  3. 設定config
curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/namespace.yaml              | kubectl apply -f -
curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/default-backend.yaml        | kubectl apply -f -
curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/configmap.yaml              | kubectl apply -f -
curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/tcp-services-configmap.yaml | kubectl apply -f -
curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/udp-services-configmap.yaml | kubectl apply -f 

安裝nginx-ingress-controller

curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/rbac.yaml      | kubectl apply -f -
curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/with-rbac.yaml | kubectl apply -f -
curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/provider/baremetal/service-nodeport.yaml | kubectl apply -f -

上面裝完之後,nginx-ingress-controller會被安裝在某個node上並用NodePort的方式開放(測試時先這樣裝)

讓我卡住的地方是我在設定ingress的時候只能使用root path,如果使用其他path會回傳404的訊息

ingress設定如下

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
  - host: ingress-controller-url
    http:
      paths:
      - path: /app   #失敗
        backend:
          serviceName: appsvc1
          servicePort: 80
      - path: /      #成功
        backend:
          serviceName: appsvc1
          servicePort: 80

一模一樣的設定,root path以外卻會失敗

後來我用下面方法登入了nginx-controller去看config

 $ get pod -n ingress-nginx
 ...
 nginx-ingress-controller-9fbd7596d-p8svz   1/1       Running   0          21h
 
 $ kubectl exec  nginx-ingress-controller-9fbd7596d-p8svz -n ingress-nginx  -i -t -- bash
 $ cat /etc/nginx/nginx.conf

兩者設定也是除了path之外一模一樣

後來重新看了官方的文件
https://kubernetes.io/docs/concepts/services-networking/ingress/

原來那些ingress-controller可以從annotations去設定參數

我的ingress少設定了一些參數,所以有些奇怪的狀況

更新後的ingress設定如下

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: ingress-controller-url
    http:
      paths:
      - path: /app 
        backend:
          serviceName: appsvc1
          servicePort: 80
      - path: /     
        backend:
          serviceName: appsvc1
          servicePort: 80

nginx.ingress.kubernetes.io/rewrite-target設定進去後就ok了這邊紀錄一下

題外話
ingress的host設定似乎可以把ingress-controller的endpoint設定到任一node上

還不暸解這之間的關係,似乎是kube-proxy把他導過去的

之後再來研究

comments powered by Disqus