什么是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支持加密鏈接的訪問模式。
配置步驟如下:
- 生成TLS證書。
$ openssl genrsa -out tls.key 2048
$ openssl req -new -x509 -key tls.key -out tls.cert -days 360 -subj /CN=kubia.example.com
- 創建一個Secret
kubectl create secret tls tls-secret --cert=tls.cert --key=tls.key
- 創建一個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
。
其中$1
為path
中的第一個捕獲組的內容。意思為將URL/svc1
部分去掉,剩下的部分保留,用于訪問svc1。
按照官方文檔的說法,我們可以在rewrite規則中使用$1
,$2
或$n
來獲取path配置項中的第1個,第二個乃至第n個捕獲組。