概要
k8s で Service に対して外部からアクセスできるようにする場合は基本的には Ingress が必要になります
過去に minikube を使った Ingress の設定方法は紹介しました
今回は kubeadm で構築した環境に Ingress をデプロイしてみたいと思います
環境
- Ubuntu18.04
- kubernetes v1.20.4
Nginx Ingress Controller のデプロイ
今回は Nginx Ingress Controller を使います
Nginx Ingress Controller の取得
git clone https://github.com/nginxinc/kubernetes-ingress/
cd kubernetes-ingress/deployments
git checkout v1.10.0
RBAC のデプロイ
kubectl apply -f common/ns-and-sa.yaml
kubectl apply -f rbac/rbac.yaml
kubectl apply -f rbac/ap-rbac.yaml
namespace/nginx-ingress created
serviceaccount/nginx-ingress created
clusterrole.rbac.authorization.k8s.io/nginx-ingress created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-app-protect created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-app-protect created
nginx の共通設定のデプロイ
kubectl apply -f common/default-server-secret.yaml
kubectl apply -f common/nginx-config.yaml
kubectl apply -f common/ingress-class.yaml
secret/default-server-secret created
configmap/nginx-config created
ingressclass.networking.k8s.io/nginx created
カスタムリソースのデプロイ
kubectl apply -f common/crds/k8s.nginx.org_virtualservers.yaml
kubectl apply -f common/crds/k8s.nginx.org_virtualserverroutes.yaml
kubectl apply -f common/crds/k8s.nginx.org_transportservers.yaml
kubectl apply -f common/crds/k8s.nginx.org_policies.yaml
kubectl apply -f common/crds/k8s.nginx.org_globalconfigurations.yaml
kubectl apply -f common/global-configuration.yaml
customresourcedefinition.apiextensions.k8s.io/virtualservers.k8s.nginx.org created
customresourcedefinition.apiextensions.k8s.io/virtualserverroutes.k8s.nginx.org created
customresourcedefinition.apiextensions.k8s.io/transportservers.k8s.nginx.org created
customresourcedefinition.apiextensions.k8s.io/policies.k8s.nginx.org created
customresourcedefinition.apiextensions.k8s.io/globalconfigurations.k8s.nginx.org created
globalconfiguration.k8s.nginx.org/nginx-configuration created
Ingress Controller のデプロイ
kubectl apply -f deployment/nginx-ingress.yaml
kubectl apply -f daemon-set/nginx-ingress.yaml
deployment.apps/nginx-ingress created
daemonset.apps/nginx-ingress created
service のデプロイ
kubectl create -f service/nodeport.yaml
service/nginx-ingress created
これでホストのどこかのポートで待ち受けることできます
今回は 31451 と 30023 で LISTEN しています
kubectl get svc -n nginx-ingress
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-ingress NodePort 10.107.240.71 <none> 80:31451/TCP,443:30023/TCP 4m38s
Ingress Controller が動作しているか確認
kubectl get pods --namespace=nginx-ingress
AME READY STATUS RESTARTS AGE
nginx-ingress-f69f79478-5gl72 1/1 Running 0 55m
nginx-ingress-k29kh 1/1 Running 0 42m
今回は daemonSets もデプロイしているので 2 つあります
使ってみる
Pod と Service をデプロイします
そして Service に対して Ingress 経由でアクセスできるようにしてみます
vim apple.yml
kind: Pod
apiVersion: v1
metadata:
name: apple-app
labels:
app: apple
spec:
containers:
- name: apple-app
image: hashicorp/http-echo
args:
- "-text=apple"
---
kind: Service
apiVersion: v1
metadata:
name: apple-service
spec:
selector:
app: apple
ports:
- port: 5678
vim ingress.yml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: example-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: test.app.com
http:
paths:
- path: /apple
backend:
serviceName: apple-service
servicePort: 5678
kubectl apply -f apple.yml
kubectl create -f ingress.yml
最小構成の場合ワーカー側のノードの IP で LISTEN しています
なのでノードの IP にアクセスすればどの IP でもアクセスできます
アクセスする際は host ベースの振り分けをしていので Host を指定するようにしましょう
curl -H "Host: test.app.com" node1:31451/apple
もちろんノードの IP に DNS を設定して FQDN でアクセスすれば Host ヘッダなしでアクセスできるようになります
トラブルシューティング: うまく pods が起動しない
自分が遭遇したエラーは error retrieving k8s version: Get "https://10.96.0.1:443/version?timeout=32s": dial tcp 10.96.0.1:443: i/o timeout
というエラーで nginx-ingress-controller の pods から ClusterIP を経由して k8s の API をコールするところでエラーになりました
原因は k8s を構築する際の flannel の設定で --pod-network-cidr=10.244.0.0/16
を忘れていたのと指定したネットワークがホストのネットワークと被っていたせいでうまく通信できなかったのが原因でした
最後に
Nginx Ingress Controller をデプロイして外部から k8s 環境にデプロイしたアプリにアクセスできるようにしてみました
結構複雑なので使いこなすとなるとかなり大変かなと思います
今回のように master/node の 2 台最小構成なのであれば NodePort を使って外部からアクセスするようになります