KongのKubernetes Ingress Controllerを試す
はじめに
久しぶりにKongをちょっとお勉強したい気になってきたので、ドキュメントを眺めていたらKubernetes Ingress Controllerなるものを見つけました。面白そうだったので、とりあえず、動かすまでやってみようかと思います。
Kongの基本的なところとプラグインの書き方も以前まとめたので興味がある人はよかったら見てみてください。
KongのIngress Controllerについて
KubernetesのIngress Controllerでクラスター内でIngressリソースとして動くKongに対して設定と管理を行います。クラスター内のスケーリング、設定の変更、エラーなどのイベントによってKongをアップデートしてくれます。
以下の2つのコンポーネントからなります。
- Kong本体
- Controller、Kongの設定を同期する
プラグインを反映させることももちろん可能で、Kongができることは基本的になんでもできるようです。
カスタムリソースについて
いくつかのカスタムリソースが用意されおり、Kongの宣言的な設定を用いてKongの機能を利用することができます。
- KongPlugin: KongのPluginエンティティ相当の設定を行なうリソース
- KongIngress: ルーティング、ロードバランシング、ヘルスチェックなど細かなルーティングの設定等を行なうためのリソース
- KongConsumer: KongのCunsumerエンティティへのマッピング
- TCPIngress: TCPベースのルーティングを行なうためのリソース。non-HTTPベースのサービスに対して利用可能
使ってみる
今回はMinikube(driver none)にIngressControllerをインストールして、サンプルアプリにプロキシしてみたいと思います。
環境
$ minikube version minikube version: v1.16.0 commit: 9f1e482427589ff8451c4723b6ba53bb9742fbb1 $ kubectl version -o yaml clientVersion: buildDate: "2021-01-13T13:28:09Z" compiler: gc gitCommit: faecb196815e248d3ecfb03c680a4507229c2a56 gitTreeState: clean gitVersion: v1.20.2 goVersion: go1.15.5 major: "1" minor: "20" platform: linux/amd64 serverVersion: buildDate: "2020-12-08T17:51:19Z" compiler: gc gitCommit: af46c47ce925f4c4ad5cc8d1fca46c7b77d13b38 gitTreeState: clean gitVersion: v1.20.0 goVersion: go1.15.5 major: "1" minor: "20" platform: linux/amd64 $ docker version (クライアント略) Server: Docker Engine - Community Engine: Version: 20.10.2 API version: 1.41 (minimum version 1.12) Go version: go1.13.15 Git commit: 8891c58 Built: Mon Dec 28 16:15:19 2020 OS/Arch: linux/amd64 Experimental: true containerd: Version: 1.4.3 GitCommit: 269548fa27e0089a8b8278fc4fc781d7f65a939b runc: Version: 1.0.0-rc92 GitCommit: ff819c7e9184c13b7c2607fe6c30ae19403a7aff docker-init: Version: 0.19.0 GitCommit: de40ad0 $ uname -srvmpio Linux 5.4.0-62-generic #70-Ubuntu SMP Tue Jan 12 12:45:47 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux $ lsb_release -a LSB Version: core-11.1.0ubuntu2-noarch:security-11.1.0ubuntu2-noarch Distributor ID: Ubuntu Description: Ubuntu 20.04.1 LTS Release: 20.04 Codename: focal
アップストリームを作っておく
下準備として、Kongがプロキシすする先のアップストリームを作って置きます。
アップストリームはNginxを用いて2つ作成し、それぞれが自分自身のhostname
を返すようにしておきます。
--dry-run
オプションと使ってリソースを作ります。
# deployment.yamlの作成 $ kubectl create deployment nginx-first --image=nginx:1.19.6 --dry-run=client -o yaml > deployment.yaml $ echo --- >> deployment.yaml $ kubectl create deployment nginx-second --image=nginx:1.19.6 --dry-run=client -o yaml >> deployment.yaml # service.yamlの作成 $ kubectl create service clusterip nginx-first --tcp=8081:80 --dry-run=client -o yaml > service.yaml $ echo --- >> service.yaml $ kubectl create service clusterip nginx-second --tcp=8082:80 --dry-run -o yaml > service.yaml
それぞれできたリソースはここに置いておくので興味があれば確認してみてください。
作成したリソースをApplyしてします。
$ kubectl --context=minikube apply -f deployment.yaml $ kubectl --context=minikube get po NAME READY STATUS RESTARTS AGE nginx-first-d6db6c668-wtmwh 1/1 Running 0 84s nginx-second-6b8d5c9696-2cj25 1/1 Running 0 84s $ kubectl --context=minikube apply -f service.yaml service/nginx-first created service/nginx-second created $ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 92m nginx-first ClusterIP 10.109.148.241 <none> 8081/TCP 44s nginx-second ClusterIP 10.105.0.182 <none> 8082/TCP 44s
最後に、それぞれが自分自身のhostname
を返すようにしておきます。
$ kubectl --context=minikube exec -it nginx-first-d6db6c668-wtmwh -- cp /etc/hostname /usr/share/nginx/html/index.html $ kubectl --context=minikube exec -it nginx-second-6b8d5c9696-2cj25 -- cp /etc/hostname /usr/share/nginx/html/index.html
テストのためにポートフォワードしてそれぞれのNginxにつないで見ます。
# First $ kubectl --context=minikube port-forward service/nginx-first 8081:8081 $ curl localhost:8081 nginx-first-d6db6c668-wtmwh # Second $ kubectl --context=minikube port-forward service/nginx-second 8082:8082 $ curl localhost:8082 nginx-second-6b8d5c9696-2cj25
無事、それぞれのNginxがhostname
を返してくれていますね。
これで準備完了です。
Kubernetes Ingress Controllerのインストール
Minikubeで作ったクラスタにKongのKubernetes Ingress Controllerをインストールします。
ドキュメントに寄るとHelmを使った方法やここからダウンロードしたYamlファイルをアプライスル方法があるみたいです。
今回は後者の方で行こうと思います。
$ kubectl create -f https://bit.ly/k4k8s namespace/kong created Warning: apiextensions.k8s.io/v1beta1 CustomResourceDefinition is deprecated in v1.16+, unavailable in v1.22+; use apiextensions.k8s.io/v1 CustomResourceDefinition customresourcedefinition.apiextensions.k8s.io/kongclusterplugins.configuration.konghq.com created customresourcedefinition.apiextensions.k8s.io/kongconsumers.configuration.konghq.com created customresourcedefinition.apiextensions.k8s.io/kongingresses.configuration.konghq.com created customresourcedefinition.apiextensions.k8s.io/kongplugins.configuration.konghq.com created customresourcedefinition.apiextensions.k8s.io/tcpingresses.configuration.konghq.com created serviceaccount/kong-serviceaccount created Warning: rbac.authorization.k8s.io/v1beta1 ClusterRole is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 ClusterRole clusterrole.rbac.authorization.k8s.io/kong-ingress-clusterrole created Warning: rbac.authorization.k8s.io/v1beta1 ClusterRoleBinding is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 ClusterRoleBinding clusterrolebinding.rbac.authorization.k8s.io/kong-ingress-clusterrole-nisa-binding created service/kong-proxy created service/kong-validation-webhook created deployment.apps/ingress-kong created
むー、Kubernetesのバージョン1.20.xを使ってると、betaじゃなくなったリソースがいくつかあって警告がいくつか出てしまうみたいですね。
まぁ、この辺は一旦気にせずに先に進めようと思います。
デプロイされたコングにアクセスするためのIPを取得して環境変数(KONG_PROXY_IP
)にセットしておきます。
この、今後この環境変数を使ってKongにアクセスします。
export KONG_PROXY_IP=$(minikube service -n kong kong-proxy --url | head -1)
デプロイされたKongにアクセスしてみます。
$ curl -i $PROXY_IP HTTP/1.1 404 Not Found Date: Sun, 24 Jan 2021 06:20:54 GMT Content-Type: application/json; charset=utf-8 Connection: keep-alive Content-Length: 48 X-Kong-Response-Latency: 0 Server: kong/2.2.1 {"message":"no Route matched with those values"}
Kongから無事レスポンスが返ってきました。
まだなにもKongの設定を行っていないので、NotFoundを返してきますね。
プロキシの設定を記述する
プロキシの設定を記述するには、普通の(?)Ingressのリソースを記述すれば良さそうです。
以下のようなYamlを記述します。
ingress.yaml
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: demo annotations: kubernetes.io/ingress.class: kong konghq.com/strip-path: "true" spec: rules: - http: paths: - path: /first backend: serviceName: nginx-first servicePort: 8081 - path: /second backend: serviceName: nginx-second servicePort: 8082
今回ちょっとだけトリッキーなのはnginxのコンテキストルートはも問題で、/first
などのパスがそのままアップストリームにプロキシされると困るのでkonghq.com/strip-path: "true"
を付与しました。
早速、リソースをApplyしてアクセスしてみます。
$ kubectl apply -f ingress.yaml $ curl -i $PROXY_IP/first HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 Content-Length: 28 Connection: keep-alive Server: nginx/1.19.6 Date: Sun, 24 Jan 2021 07:11:05 GMT Last-Modified: Sun, 24 Jan 2021 05:57:51 GMT ETag: "600d0c5f-1c" Accept-Ranges: bytes X-Kong-Upstream-Latency: 1 X-Kong-Proxy-Latency: 0 Via: kong/2.2.1 nginx-first-d6db6c668-wtmwh $ curl -i $PROXY_IP/second HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 Content-Length: 30 Connection: keep-alive Server: nginx/1.19.6 Date: Sun, 24 Jan 2021 07:11:06 GMT Last-Modified: Sun, 24 Jan 2021 05:59:05 GMT ETag: "600d0ca9-1e" Accept-Ranges: bytes X-Kong-Upstream-Latency: 1 X-Kong-Proxy-Latency: 0 Via: kong/2.2.1 nginx-second-6b8d5c9696-2cj25
それぞれ、きちんとプロキシされているようですね。