Kong Ingress Controller環境でKong GatewayのWorkspaceを使う

Kong Ingress Controller(以下KIC)を使って`Ingress`経由でService/Routeを作成すると、設定を意識していなければ基本的にはdefaultのWorkspaceに作成されていく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/a31f49b7-2848-c434-9920-ced52b25e214.png)
ここではKIC利用時にdefaultとは別に意図したWorkspaceにKong Gatewayのリソースを展開する方法を確認する。

## KICでWorkspaceを使う際の前提知識

有益なドキュメントがあまり見つからず、[こちら](https://docs.konghq.com/kubernetes-ingress-controller/latest/guides/security/workspaces/)のドキュメントくらいしか見当たらなかった。
利用に関する条件は以下となる。
- KICをDBありモードでデプロイしている必要あり
- Workspace1つにつきKICのインスタンスが1つ必要。
- WorkspaceごとのKICのインスタンスを使い分けるために、KICのインスタンス毎に`IngressClass`が必要

また設定方法としてはHelmの`values.yaml`に以下を記載する。
```yaml
controller:
  ingressController:
    env:
      watch_namespace: <Namespace名>
      kong_workspace: <Workspace名>
```
`watch_namespace`は省略可能で、省略した場合は全Namespaceが対象となる。

## 検証
検証のシナリオとして、以下のようなシナリオで検証する。
- Namespace`my-httpbin`にデプロイした`Ingress`はWorkspace`httpbin-workspace`に紐づける
- その他のNamespaceにデプロイしたものはWorkspace`default`に紐づける

検証するにあたり、事前にKICとKong Gatewayをデプロイしておき、そこに追加する形でKICをデプロイする。
事前に用意するKICとKong Gatewayの説明は省略するが、手順が必要な人は[こちら](https://qiita.com/ipppppei/items/44c100412d4e484f4f6a)を参照するとよい。

最初に追加のKICを指定するための`IngressClass`を作成する。
```yaml
cat << EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: kic-ws
spec:
  controller: ingress-controllers.konghq.com/kong
EOF
```
次に追加のKICのデプロイに使うHelmの`values.yaml`を作成する。
```yaml
cat <<EOF > ./kic-workspace.yaml
deployment:
  test:
    enabled: false
controller:
  enabled: true
  ingressController:
    installCRDs: false
    ingressClass: kic-ws
    ingressClassAnnotations: kic-ws
    gatewayDiscovery:
      enabled: false
    env:
      publish_service: kong/kong-aws-kong-proxy
      watch_namespace: my-httpbin
      kong_workspace: httpbin-workspace
      kong_admin_tls_skip_verify: true
      kong_admin_token:
        valueFrom:
          secretKeyRef:
            key: password
            name: kong-config-secret
      kong_admin_url: https://kong-aws-kong-admin.kong.svc:8444
gateway:
  enabled: false
  deployment:
    kong:
      enabled: false
  admin:
    enabled: false
EOF
```
`controller.ingressController`セクションを少し説明する。
`ingressClass`はIngress Controllerが参照する`IngressClass`であり、これを指定することで`Ingress`側でコントローラの使い分けが出来るようになる。
`gatewayDiscovery.enabled: false`はKong GatewayのAdmin APIのアドレスを探すのに`kong_admin_url`を使うために指定している。
詳しくは[The gatewayDiscovery section](https://github.com/Kong/charts/blob/main/charts/kong/README.md#the-gatewaydiscovery-section)を参照のこと。
`publish_service`はKong GatewayのProxyの`Service`を指定していて、`<Namespace名>/<Service名>`で指定する。これがないとエラーになる。

作成した`values.yaml`を使ってKICをデプロイする。
```sh
helm upgrade -i kic-ws kong/ingress -f kic-workspace.yaml --debug -n kong
```
デプロイが完了すると、自動的に指定したWorkspaceが作成される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/5aa625eb-d27d-7a48-8697-cb566a39b990.png)
続いて`Ingress`をデプロイする。ここでは[httpbin](https://httpbin.org/)をサンプルとしてデプロイした。
`Ingress`の`IngressClass`に先程作成した`IngressClass`を指定するのを忘れないこと。

<details><summary>my-httpbin.yaml（クリックして表示）</summary><div>

```yaml:my-httpbin.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-httpbin
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: my-httpbin
  replicas: 1
  template:
    metadata:
      labels:
        app.kubernetes.io/name: my-httpbin
    spec:
      containers:
      - image: kennethreitz/httpbin
        name: my-httpbin
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: my-httpbin
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  type: ClusterIP
  selector:
    app.kubernetes.io/name: my-httpbin
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-httpbin
  annotations:
    cert-manager.io/issuer: my-httpbin-issuer
    kubernetes.io/tls-acme: "true"
spec:
  ingressClassName: kic-ws
  rules:
    - host: my-httpbin.eks.hogehoge.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name:  my-httpbin
                port:
                  number: 80
  tls:
  - secretName: my-httpbin-general-tls
    hosts:
    - my-httpbin.eks.hogehoge.com
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: my-httpbin-issuer
spec:
  acme:
    email: mymail@hogehoge.com
    privateKeySecretRef:
      name: my-httpbin-acme-key
    server: https://acme-v02.api.letsencrypt.org/directory
    solvers:
    - http01:
        ingress:
          class: kic-ws
```
</div></details>

```sh
kubectl create ns my-httpbin
kubectl apply -f ./my-httpbin.yaml -n 
```

デプロイが完了するとKong Managerの方から作成したWorkspaceの方にService/Routeが作成されていることが確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/d872332b-f0d4-b645-da76-3249cc0223c2.png)

触ってみると問題なく使えることも分かる。
```sh
$ curl my-httpbin.eks.hogehoge.com/ip
{
  "origin": "192.168.59.131"
}
```