什么是ingress
通俗來講,ingress 和Service、Deployment 都是 kubernetes 的資源類型,Ingress 用于實現用域名的方式訪問K8s 內部應用。
Ingress 安裝
首先安裝 helm 管理工具:https://helm.sh/docs/intro/install/
使用 helm 安裝Ingress:https://kubernetes.github.io/ingress-nginx/deploy/
1.添加 Ingress 的 helm 倉庫
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
2.下載 ingress 的 helm 包至本地
helm pull ingress-nginx/ingress-nginx
3.更改對應的配置
tar xf ingress-nginx-3.6.0.tgz
cd ingress-nginx
vim values.yaml
4.需要修改的位置
- Controller 和 admissionWebhook 的鏡像地址,需要將公網鏡像同步至公司內網鏡像倉庫。
- hostNetwork 設置為true
- dnsPolicy 設置為 ClusterFirstWithHostNet
- NodeSelector 添加 ingress:“true” 部署至指定節點
- 類型更改為kind:DaemonSet
5.部署 ingress
給需要部署ingress 的節點上打標簽
$ kubectl label node k8s-master03 ingress=true
$ kubectl create ns ingress-nginx
$ helm install ingress-nginx -n ingress-nginx
Ingress 使用
一個Ingress 資源示例:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: "/"
pathType: Prefix
backend:
service:
name: nginx-svc
port:
number: 80
Ingress 需要指定 apiVersion
、kind
、 metadata
和 spec
字段。 Ingress 對象的命名必須是合法的 DNS 子域名名稱。
service 和 deployment YAML 如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
labels:
app: nginx
spec:
selector:
app: nginx
ports:
- port: 80
使用 kubectl apply -f
創建
$ kubectl apply -f nginx-ingress.yaml -f nginx-svc.yaml
http://foo.bar.com
轉發到集群內的服務 nginx-svc
上,完整的URL為http://nginx-svc:80/
。
配置 /etc/hosts
文件,如下所示:
192.168.31.217 foo.bar.com
在瀏覽器上訪問foo.bar.com
,就可以看到內容了
默認后端
沒有設置規則的 Ingress 將所有流量發送到同一個默認后端,.spec.defaultBackend 則是在這種情況下處理請求的那個默認后端。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-resource-backend
spec:
defaultBackend:
resource:
apiGroup: k8s.example.com
kind: StorageBucket
name: static-assets
rules:
- http:
paths:
- path: /icons
pathType: ImplementationSpecific
backend:
resource:
apiGroup: k8s.example.com
kind: StorageBucket
name: icon-assets
路徑類型
Ingress 中的每個路徑都需要有對應的路徑類型(Path Type)。未明確設置 pathType 的路徑無法通過合法性檢查。當前支持的路徑類型有三種:
ImplementationSpecific:對于這種路徑類型,匹配方法取決于 IngressClass。 具體實現可以將其作為單獨的 pathType 處理或者與 Prefix 或 Exact 類型作相同處理。
Exact:精確匹配 URL 路徑,且區分大小寫。
Prefix:基于以 / 分隔的 URL 路徑前綴匹配。匹配區分大小寫,并且對路徑中的元素逐個完成。 路徑元素指的是由 / 分隔符分隔的路徑中的標簽列表。
類型 | 路徑 | 請求路徑 | 匹配與否? |
---|---|---|---|
Prefix | / |
(所有路徑) | 是 |
Exact | /foo |
/foo |
是 |
Exact | /foo |
/bar |
否 |
Exact | /foo |
/foo/ |
否 |
Exact | /foo/ |
/foo |
否 |
Prefix | /foo |
/foo , /foo/
|
是 |
Prefix | /foo/ |
/foo , /foo/
|
是 |
Prefix | /aaa/bb |
/aaa/bbb |
否 |
Prefix | /aaa/bbb |
/aaa/bbb |
是 |
Prefix | /aaa/bbb/ |
/aaa/bbb |
是,忽略尾部斜線 |
Prefix | /aaa/bbb |
/aaa/bbb/ |
是,匹配尾部斜線 |
Prefix | /aaa/bbb |
/aaa/bbb/ccc |
是,匹配子路徑 |
Prefix | /aaa/bbb |
/aaa/bbbxyz |
否,字符串前綴不匹配 |
Prefix |
/ , /aaa
|
/aaa/ccc |
是,匹配 /aaa 前綴 |
Prefix |
/ , /aaa , /aaa/bbb
|
/aaa/bbb |
是,匹配 /aaa/bbb 前綴 |
Prefix |
/ , /aaa , /aaa/bbb
|
/ccc |
是,匹配 / 前綴 |
Prefix | /aaa |
/ccc |
否,使用默認后端 |
混合 |
/foo (Prefix), /foo (Exact) |
/foo |
是,優選 Exact 類型 |
主機名通配符
主機名可以是精確匹配(例如 foo.bar.com
),也可以使用通配符匹配(例如 *.bar.com
)。精確匹配要求 HTTP host 頭部字段與 host 字段一致,通配符匹配要求 HTTP host 頭部字段與通配符規則中的后綴部分相同。
主機 | host 頭部 | 匹配與否? |
---|---|---|
*.foo.com |
bar.foo.com |
基于相同的后綴匹配 |
*.foo.com |
baz.bar.foo.com |
不匹配,通配符僅覆蓋了一個 DNS 標簽 |
*.foo.com |
foo.com |
不匹配,通配符僅覆蓋了一個 DNS 標簽 |
將同一域名的不同 URL 路徑轉發到不同的服務(Simple Fanout)
根據請求的 HTTP URI 將來自同一 IP 地址的流量路由到多個 Service。
Ingress 配置如下:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: simple-fanout-example
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
pathType: Prefix
backend:
service:
name: service1
port:
number: 4200
- path: /bar
pathType: Prefix
backend:
service:
name: service2
port:
number: 8080
使用 kubectl apply -f
創建 Ingress
$ kubectl apply -f ingress.yaml
查看 Ingress 詳細信息
$ kubectl describe ingress simple-fanout-example
Name: simple-fanout-example
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo service1:4200 (10.8.0.90:4200)
/bar service2:8080 (10.8.0.91:8080)
Annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 22s loadbalancer-controller default/test
將不同的域名轉發到不同的服務
基于名稱的虛擬主機支持將針對多個主機名的 HTTP 流量路由到同一 IP 地址上。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: foo.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service1
port:
number: 80
- host: bar.foo.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80
HTTPS 配置
通過設定包含 TLS 私鑰和證書的 Secret 來保護 Ingress。 Ingress 只支持單個 TLS 端口 443。 TLS Secret 的數據中必須包含用于 TLS 的以鍵名 tls.crt
保存的證書和以鍵名 tls.key
保存的私鑰。
apiVersion: v1
kind: Secret
metadata:
name: testsecret-tls
namespace: default
data:
tls.crt: base64 編碼的證書
tls.key: base64 編碼的私鑰
type: kubernetes.io/tls
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-example-ingress
spec:
tls:
- hosts:
- https-example.foo.com
secretName: testsecret-tls
rules:
- host: https-example.foo.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service1
port:
number: 80
更新 Ingress
可以使用 kubectl edit
更新 Ingress ,也可以使用 kubectl replace -f
更新 ingress.yaml 文件。