K8s Ingress

什么是Ingress

Ingress是k8s以http或https的方式,使用nginx,根據URL規則(這些URL可在集群外訪問),將請求轉發給對應的service。

使用Ingress的前置條件

需要在k8s中運行ingress controller。使用RKE安裝的K8s集群已經支持使用Ingress。

Ingress的描述文件

一個Ingress描述文件的例子如下:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /testpath
        backend:
          serviceName: test
          servicePort: 80

此時,我們訪問集群節點的/testpath這個URL,k8s會把請求轉發給test服務。

Ingress規則

每一條Ingress規則包含如下信息:

  • host(可選):需要填寫域名。如果配置了此項,Ingress規則僅對這個host生效。如果沒有配置,這條規則對所有的host生效。這里判斷標準是Request header里頭HOST的值。
  • paths列表:列出了所有URL路徑和后臺service以及端口的對應關系。
  • backend:需要指明和path對應的服務和端口號,這樣訪問這個path的時候,請求會被轉發到backend服務中。

查看Ingress的信息

執行

[root@k8s ~]# kubectl get ingress
NAME           HOSTS   ADDRESS           PORTS   AGE
test-ingress   *       192.168.100.128   80      97m

可以得到類似的輸出。我們可以通過ADDRESS一欄的地址訪問ingress對應的服務。

Ingress使用例子

單服務Ingress

單服務的Ingress只有一個backend。甚至我們可以不用寫rules,僅僅指定一個default backend。例子如下:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
spec:
  backend:
    serviceName: testsvc
    servicePort: 80

在這個例子中,testsvc是一個default backend。

不匹配所有規則的請求會被轉發到default backend。因此使用這種配置方式配置單服務Ingress比較簡便。

多服務Ingress

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: simple-fanout-example
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - path: /foo
        backend:
          serviceName: service1
          servicePort: 4200
      - path: /bar
        backend:
          serviceName: service2
          servicePort: 8080

配置達到的效果解釋如下:

  • 一個請求頭HOST為foo.bar.com到達該節點,如果請求URL為/foo,請求會被轉發給service1的4200端口。
  • 一個請求頭HOST為foo.bar.com到達該節點,如果請求URL為/bar,請求會被轉發給service2的8080端口。

基于域名的虛擬主機

Ingress使用多個host的例子:

spec:
  rules:
  - host: foo.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: foo
          servicePort: 80
  - host: bar.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: bar
          servicePort: 80

k8s會判斷請求頭的host的內容。如果是foo.example.com訪問foo服務,如果是bar.example.com則訪問bar服務。

下面這個例子和上述的類似,只是如果請求頭沒有HOST,會被轉發給service3。

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: name-virtual-host-ingress
spec:
  rules:
  - host: first.bar.com
    http:
      paths:
      - backend:
          serviceName: service1
          servicePort: 80
  - host: second.foo.com
    http:
      paths:
      - backend:
          serviceName: service2
          servicePort: 80
  - http:
      paths:
      - backend:
          serviceName: service3
          servicePort: 80

TLS支持

Ingress支持加密鏈接的訪問模式。

配置步驟如下:

  1. 生成TLS證書。
$ openssl genrsa -out tls.key 2048
$ openssl req -new -x509 -key tls.key -out tls.cert -days 360 -subj /CN=kubia.example.com
  1. 創建一個Secret
kubectl create secret tls tls-secret --cert=tls.cert --key=tls.key
  1. 創建一個Ingress,使用上一步創建出的Secret
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kubia
spec:
  tls:
  - hosts:
    - kubia.example.com
    secretName: tls-secret
  rules:
    - host: kubia.example.com
      http:
        paths:
        - path: /
          backend:
            serviceName: kubia-nodeport
            servicePort: 80

注意:tls配置的hosts需要和TLS證書中CN的值一致。

Ingress Path Rewrite

通常來說訪問service內部的URL和它對應的Ingress入口URL是不同的。為了滿足這個要求,Kubernetes提供了Path Rewrite(路徑重寫)。可以通過正則表達式語法,配置Ingress入口URL和訪問service URL的對應關系。

配置Path Rewrite的方法為在Ingress中的annotations配置項中,增加如下配置:

nginx.ingress.kubernetes.io/rewrite-target: rewrite規則

下面講解幾個path rewrite規則示例:

apiVersion: networking.extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-echo-with-rewrite
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: rewrite.example
    http:
      paths:
      - path: /svc1/
        backend:
          serviceName: svc1
          servicePort: 80

這個配置會將http://rewrite.example/svc1/xxx重寫為訪問svc1的/路徑。/svc1/xxx會全被改寫為/,即原始URL/svc1后面的東西統統會被丟掉。

如何在訪問svc1的時候去掉/svc1前綴,但又不會丟掉前綴之后的內容呢?下面的例子可以滿足這個要求:

apiVersion: networking.extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-echo-with-rewrite
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
  - host: rewrite.example
    http:
      paths:
      - path: /svc1/(.*)
        backend:
          serviceName: svc1
          servicePort: 80

上面的rewrite規則將http://rewrite.example/svc1/xxx重寫為訪問svc1的/xxx

其中$1path中的第一個捕獲組的內容。意思為將URL/svc1部分去掉,剩下的部分保留,用于訪問svc1。

按照官方文檔的說法,我們可以在rewrite規則中使用$1$2$n來獲取path配置項中的第1個,第二個乃至第n個捕獲組。

參考鏈接

使用OpenSSL生成自簽名SSL證書
Ingress Path Rewrite官網示例

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容