kind環境でIngressを動かす
はじめに
Kubernetesの勉強の一環としてkind(Kubernetes in Docker)でIngressを使ってみたので、その際にうまくいった手順やつまづいたことを記録しておく。
前提知識
- Dockerが使える
- kubectlでdeploymentとserviceを作れる
- KubernetesのNamespaceの概念が分かる
- kindを使える
- Ingressの概要が分かる
環境
- WSL上のUbuntu 24.04.1 LTS
- Docker Desktop, kubectl, kindをインストール済み
手順
手順1. kindでクラスターを作成する
kind create cluster --config=./cluster-manifest.yaml
# ./cluster-manifest.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 80
hostPort: 8080
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
クラスターなどと言っておきながら、ノード数は1つだけである。最終的にはIngressを使ってノード(実体はホスト上で動く1つのDockerコンテナ)の80番ポートでアプリケーションを公開するので、ホストの8080番ポートとノードの80番ポートを接続する。ちなみにノード数を2つ以上にする場合、「ホストのポートと接続されたノード」と「Ingressが動いているノード」が一致する必要があり、そのためには追加の設定が必要になる。詳細はkindの公式サイトを参照。
手順2. deploymentを作成
ここでは、使用するコンテナイメージは自分で用意することとする。
まずはアプリケーションで使用するコンテナイメージをビルドする。
docker build . -t prac/api
通常であれば使用するコンテナイメージはDocker Hubなどにアップロードしてから参照させるのだが、今回はローカルでビルドしたコンテナイメージをローカルで使うだけであり、それなのにDocker Hubなどを経由するのは明らかに非効率である。以下のコマンドを実行することで、ローカルに保存されているprac/apiというコンテナイメージをkindクラスターに読み込ませることができる。ちなみに意外と時間がかかる。
kind load docker-image prac/api
deploymentを作成する。
kubectl apply -f ./deployment-manifest.yaml
# ./deployment-manifest.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: api
name: api-dep
spec:
replicas: 1
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- image: prac/api
name: api
imagePullPolicy: Never #注意!
resources: {}
注意すべきなのはimagePullPolicy: Neverの部分。これを設定すると、インターネット上からコンテナイメージをpullしなくなる。今回のように事前にkindクラスタに読み込ませておいたコンテナイメージを使いたい場合はこの設定が必要になる。逆に、普通にDocker Hubなどからコンテナイメージをpullしたい場合はこの設定は記述してはならない。
手順3. Serviceの作成
kubectl apply -f ./service-manifest.yaml
# ./service-manifest.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: api
name: api-service
spec:
type: ClusterIP
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: api
シンプルなService設定である。なお、今回使用するコンテナイメージでは、コンテナを作成すると自動的に80番ポートでアプリケーションを公開するようになっている。
このServiceは直接外部に公開するわけではない(Ingress経由で公開する)ので、typeはClusterIPとする。Ingressの設定がうまくいかないときに上記ServiceのtypeをNodePortなどに変更すると外部からアクセスできるようになって成功したように感じるかもしれないが、ServiceをIngressを介さずに公開してしまっただけであるので浮かれてはならない。
手順4. Ingressの設定
Ingress Controllerを作成
ここが一番つまづいた部分。通常であればIngress ControllerはHelmを使って作成することが多いようだが、kindではHelmを使ってIngress Controllerをインストールしてもうまく動かなかった(理由は不明)。代わりに、kindの公式サイトに書いてあるコマンドでIngress Controllerを作成する。
kubectl apply -f https://kind.sigs.k8s.io/examples/ingress/deploy-ingress-nginx.yaml
これで、ingress-nginxというNamespaceにIngressのdeploymentやらServiceやらが良い感じに作成され、80番ポートと443ポートで公開される。
Ingressリソースを作成
kubectl apply -f ./ingress-manifest.yaml
# ./ingress-manifest.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
シンプルなIngressの設定。全てのhttpリクエストを、先ほど作っておいたapi-serviceの80番ポートに投げる。
ちなみに、Ingress Controllerの作成が終わってからコマンドを実行しないとエラーが起きるので注意。
手順5. 結果を確認
http://localhost:8080にアクセス。正常にレスポンスが返ってくれば成功。
Discussion