[k8s] ingress resource
=======
###### tags: `kubernetes`

:::info
+ manages external access to the services in a cluster, typically HTTP.
+ 可設定每一個endpoint的規則,以及對應的路徑,如果要有***basic-auth***或者是***TLS***,也是在這設定
:::
:::warning
Ingress 本身並沒有提供負載平衡的功能,還需要透過 Ingress Controller 來實現。Ingress 目前主要支援兩種型別 ***GCE*** 與 ***Nginx***。
> 負載平衡(Load Balancing):以往我們可以透過外部的資源,像是 AWS ELB 來實現,將流量分配給不同的機器。而 Kubernetes 現在也提供了一個內部工具 Ingress Controller ,讓我們自己可以在 Kubernetes Cluster 中實現 Load Balancing 而無需透過外部資源。
:::

# annotations
`Ingress-Controller` 會去讀取 Ingress 的設定,然後來進行後續的動作。假想一個情況,系統內同時有多個 Ingress-Controller 的實現,使用者要==如何指派該 Ingress 要使用哪一個 Ingress-Controller 來使用?==
並由各個 Ingress-Controller 自行決定看到什麼樣的資訊來進行什麼處理。
此外,不同的 Ingress-Server 提供的功能與使用方式都不同,基本上 Ingress Resource ***很難有一個完美的介面來滿足所有的實現***,因此大部分的情況下,不同的 Ingress-Controller/Ingress-Server 都會要求使用者在 Annotation 的部分使用特定的字眼來描述額外的功能
```yaml=
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /
```
```yaml=
# 設定ingress的auth型態、對應的secret,auth-realm 其實就是瀏覽器會顯示給用戶的內容
metada:
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: "Authentication Required - foo"
```
## What is the rewrite-target
### if without `rewrite-target`
`http://<ingress-service>:<ingress-port>/watch` --> `http://<watch-service>:<port>/watch`
`http://<ingress-service>:<ingress-port>/wear` --> `http://<wear-service>:<port>/wear`
### example 1
> `replace("/path","/")`
```yaml=
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
namespace: critical-space
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /pay
backend:
serviceName: pay-service
servicePort: 8282
```
### example 2 (better one)

```yaml=
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: rewrite
namespace: default
spec:
rules:
- host: rewrite.bar.com
http:
paths:
- backend:
serviceName: http-svc
servicePort: 80
path: /something(/|$)(.*)
```
# best practices
## example 1: 將不同路徑的請求對應到不同的 Service 物件
```yaml=
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "false"
name: ingress-wear-watch
namespace: app-space
spec:
rules:
- http:
paths:
- backend:
service:
name: wear-service
port:
number: 8080
path: /wear
pathType: Prefix
- backend:
service:
name: video-service
port:
number: 8080
path: /stream
pathType: Prefix
```
### how to create
```shell=
kubectl create -f ./ingress-example-1.yaml
kubectl get ing
```
## example 2: 將不同 domain name 的請求對應到不同的 Service 物件
```yaml=
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: example-2
spec:
rules:
- host: helloworld-v1.example.com
http:
paths:
- path: /
backend:
serviceName: hellworld-v1
servicePort: 80
- host: helloworld-v2.example.com
http:
paths:
- path: /
backend:
serviceName: helloworld-v2
servicePort: 80
```
+ ***rules***: 代表這個 Ingress 的轉發規則
+ ***host***: 設定可以連接到 Service 物件的網域名稱
+ ***path***: 設定可以連接到 Service 物件的路徑名稱
+ ***serviceName***: 設定欲連接到的 Service 名稱,這裡要填寫的就是 Service 中在 metadata 內寫上的 name
+ ***servicePort***: 設定要經由哪個 port 連接到 Service 物件
## example 3:支援終止 SSL (SSL termination)

```yaml=
apiVersion: v1
kind: Secret
metadata:
name: ssh-secret
namespace: default
type: Opaque
data:
tls.crt: base64_encoded_cert
tls.key: base64_encoded_key
```
```yaml=
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: web
namespace: whale
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
tls:
- hosts:
- ar-remoteassist.ddns.net
secretName: ssh-secret
rules:
- host: blue.demo.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: blue-service
port:
number: 8080
```