🆒

K8s Gateway APIでクラスタ内サービスへのウェブアクセスの用意が簡単

2023/12/11に公開

以前、Kubernetes Gateway APIをNGINX Gateway Fabric (NGF) で利用するポストをしましたが、いろいろサービスを試す中で簡単にWeb GUIへのアクセスをセットアップできるので、以来、便利に利用しています。

セットアップ時のポストではNGFの例をそのまま走らせてみました。

また、TLS証明書を更新する機会があったのでTLSのsecretを差し替えるだけでスルッと通って簡単だったというポストもしました。

今回は他にこんなのセットアップしましたという紹介ポストです。なおHTTPRouteのルールとか細かいところは何もいじらず、ただただ新しく立ち上がったserviceに対してクラスタ外からアクセスするためのセットアップのみです。

Kubernetes Dashboard

https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/

1つ目はKubernetes Dashboardです。

Helmで導入しました。私のおうちKubernetesクラスタはGitLab + FluxのGitOpsで変更加えているので、以下Fluxのhelm source, helm release,あとはvalues.yamlの紹介です。

# flux helm source
flux create source helm dashboard \
  --url=https://kubernetes.github.io/dashboard \
  --interval=1h0m0s \
  --export > helmrepo.yaml

# flux hr
flux create helmrelease dashboard \
  --source=HelmRepository/dashboard \
  --chart=kubernetes-dashboard \
  --values=./values.yaml \
  --interval=10m \
  --target-namespace=kube-dashboard \
  --export > hr.yaml

values.yamlはhelm show valuesで取り出しています。

# prep values file
helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/
helm show values kubernetes-dashboard/kubernetes-dashboard > default-values.yaml
cp default-values.yaml values.yaml
# edit values.yaml

GatewayがTLS offloadしてくれるのでserviceはplain httpで作られるように変更加えています。

diff values.yaml default-values.yaml
44c44
< extraArgs:
---
> # extraArgs:
46,47c46,47
<   - --enable-insecure-login
<   - --system-banner="Welcome to Kubernetes"
---
> #   - --enable-insecure-login
> #   - --system-banner="Welcome to Kubernetes"
142c142
< protocolHttp: true
---
> protocolHttp: false
147c147
<   externalPort: 80
---
>   externalPort: 443

また、例によってクラスタ内でGatewayを利用できるnamespaceはlabelで制御しているので、kube-dashboardというnamespaceは以下を用意しました。

---
apiVersion: v1
kind: Namespace
metadata:
  name: kube-dashboard
  labels:
    gateway-enabled: yes

Gatewayのマニフェスト

参考までに、Gatewayのマニフェストは以下のような感じになります。

---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: my-gateway
  namespace: gateway
spec:
  gatewayClassName: nginx
  listeners:
  - name: https
    port: 443
    protocol: HTTPS
    tls:
      mode: Terminate
      certificateRefs:
        - kind: Secret
          name: tls-secret
          namespace: certificate
    allowedRoutes:
      namespaces:
        from: Selector
        selector:
          matchLabels:
            gateway-enabled: yes

Dashboard用HTTPRoute

サービスとしては以下のように立ち上がってきます。

❯ kubectl get svc -n kube-dashboard
NAME                                            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kube-dashboard-dashboard-kubernetes-dashboard   ClusterIP   10.106.138.59   <none>        80/TCP    79m

HTTPRouteはNGFの例で用意したものと比べても、ホスト名(.spec.hostnames)とバックエンド(.spec.rules[].backendRefs[].name, .port)の指定を変えるだけで完成です。

---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: dashboard
  namespace: kube-dashboard
spec:
  parentRefs:
  - name: my-gateway
    sectionName: https
    namespace: gateway
  hostnames:
  - "kube-dashboard.yourdomainname.here"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: kube-dashboard-dashboard-kubernetes-dashboard
      port: 80

セットアップについて触れませんが、おうちで使っているDNSサーバにレコードを用意すればhttps://kube-dashboard.yourdomainname.hereでアクセスできるようになります。

Kubernetes Dashboard on Web Browser

Minioでの例

HTTPRouteほぼコピペで別のサービスでも簡単にウェブアクセス用意できます簡単でした!ということでMinioとPostgreSQLの分も紹介させてください。

Minioでの用意も簡単でした。Helm (Flux経由) でOperatorとTenantを導入し、あとは例に倣って、ホスト名は使いたい名前を設定し、バックエンドの指定は対応するserviceの名称とポートを設定すればアクセスできます。

❯ kubectl get svc -n minio-tenant
NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
minio              ClusterIP   10.109.133.248   <none>        80/TCP     7d
mytenant-console   ClusterIP   10.101.178.223   <none>        9090/TCP   7d
mytenant-hl        ClusterIP   None             <none>        9000/TCP   7d
❯ kubectl get httproute -n minio-tenant
NAME            HOSTNAMES                      AGE
minio-console   ["tenant-mc.yourdomainname.here"]   7d
minio-service   ["s3.yourdomainname.here"]          7d
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: minio-console
  namespace: minio-tenant
spec:
  parentRefs:
  - name: my-gateway
    sectionName: https
    namespace: gateway
  hostnames:
  - "tenant-mc.yourdomainname.here"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: mytenant-console
      port: 9090
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: minio-service
  namespace: minio-tenant
spec:
  parentRefs:
  - name: my-gateway
    sectionName: http
    namespace: gateway
  hostnames:
  - "s3.yourdomainname.here"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: minio
      port: 80

PostgreSQL Operatorでの例

こちらも同様です。既存のHTTPRouteマニフェストのコピペで簡単にウェブアクセスが用意できます。

❯ kubectl get svc -n postgres-operator
NAME                                     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
mycluster                                ClusterIP   10.106.11.241    <none>        5432/TCP   4d2h
mycluster-config                         ClusterIP   None             <none>        <none>     4d2h
mycluster-repl                           ClusterIP   10.103.22.115    <none>        5432/TCP   4d2h
postgres-operator-postgres-operator      ClusterIP   10.96.44.10      <none>        8080/TCP   4d18h
postgres-operator-postgres-operator-ui   ClusterIP   10.105.174.205   <none>        80/TCP     4d18h
❯ kubectl get httproute -n postgres-operator
NAME                   HOSTNAMES                        AGE
postgres-operator-ui   ["postgres-ui.yourdomainname.here"]   4d13h
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: postgres-operator-ui
  namespace: postgres-operator
spec:
  parentRefs:
  - name: my-gateway
    sectionName: https
    namespace: gateway
  hostnames:
  - "postgres-ui.yourdomainname.here"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: postgres-operator-postgres-operator-ui
      port: 80

おわりに

というわけで、今回はGateway API利用を始めてこんなにウェブアクセスの用意が簡単になるんですねウレシイ!ということが言いたいポストでした。

あとは蛇足です。

ここまで環境が整うと、なにか新しいものを見つけて自分で試したいと思ったときのフットワークの軽さがかなり違ってきます。

自前のKubernetesクラスタを初めて用意して、ネットワークアドオンからお試しpod、deployment、あれこれ導入すると何がどうなっているのかトラックできなくなり、クラスタ作り直しということを何度もしました。GitLab + Fluxで用意したGitOps環境で、クラスタの状態が把握できなくなるという問題は解消しました。

あれこれ試しやすいけど、クラスタ外からのアクセスはできないの? → MetalLBを利用することによって、パブリッククラウドサービスでもないのにLoadBalancerサービスタイプでserviceを作成してクラスタ外、おうちのLAN上でサービスアクセスできるようになりました。

更に更に、MetalLBも十分簡単なのですが、Gatewayを導入したことによって更にウェブサービスへのアクセスに関しては便利になりました。Gatewayを使うことで一つのIPアドレスで複数のサービスにアクセスできるポイントができ、また特に嬉しいのは各サービス側でTLS設定をどうこうせずともGatewayにTLSオフロードさせる形でのHTTPSアクセスを用意できるようになりました。

こんなことができるんだスゴイ!自分でもできたヤッタ!という喜びを求めて引き続きあれこれ試して、可能であればポストもしていきたいです。

Discussion