K8s Gateway APIでクラスタ内サービスへのウェブアクセスの用意が簡単
以前、Kubernetes Gateway APIをNGINX Gateway Fabric (NGF) で利用するポストをしましたが、いろいろサービスを試す中で簡単にWeb GUIへのアクセスをセットアップできるので、以来、便利に利用しています。
セットアップ時のポストではNGFの例をそのまま走らせてみました。
また、TLS証明書を更新する機会があったのでTLSのsecretを差し替えるだけでスルッと通って簡単だったというポストもしました。
今回は他にこんなのセットアップしましたという紹介ポストです。なおHTTPRouteのルールとか細かいところは何もいじらず、ただただ新しく立ち上がったserviceに対してクラスタ外からアクセスするためのセットアップのみです。
Kubernetes 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
でアクセスできるようになります。
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