はじめに
ConoHa VPSの2ノード構成バニラKubernetes環境に、Nginx Ingress Controllerを導入した際の手順とトラブルシューティングをまとめます。クラウドマネージドKubernetesと異なり、ベアメタル環境特有のハマりどころが多いため、同じ構成を試みる方の参考になれば幸いです。
環境
- ConoHa VPS × 2ノード(コントロールプレーン1台、ワーカー1台)
- バニラKubernetes(kubeadmで構築)
- Nginx Ingress Controller
1. Nginx Ingress Controllerのインストール
⚠️ ポイント:baremetal 用マニフェストを使う
クラウド環境向けの cloud 用マニフェストを使うと、ServiceタイプがLoadBalancerになり、EXTERNAL-IPがPendingのまま永遠に解決しません。ConoHaのようなベアメタル環境では必ず baremetal 用を使いましょう。
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.12.1/deploy/static/provider/baremetal/deploy.yaml
インストール後に確認:
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx
Serviceタイプが NodePort になっていればOKです。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
ingress-nginx-controller NodePort 10.x.x.x <none> 80:3xxxx/TCP,443:3xxxx/TCP
2. externalIPsの設定(80/443で直接受けるために)
NodePortの高ポート番号(30000番台)ではなく、標準の80/443番ポートで受けたい場合は externalIPs を設定します。
kubectl edit svc ingress-nginx-controller -n ingress-nginx
spec:
externalIPs:
- xxx.xxx.xxx.xxx # コントロールプレーンのグローバルIP
- xxx.xxx.xxx.xxx # ワーカーノードのグローバルIP
type: NodePort # NodePortのまま維持
3. テスト用アプリとIngressのデプロイ
# test-app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-app
spec:
replicas: 2
selector:
matchLabels:
app: hello
template:
metadata:
labels:
app: hello
spec:
containers:
- name: hello
image: hashicorp/http-echo
args: ["-text=Hello from Ingress!"]
ports:
- containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
name: hello-svc
spec:
selector:
app: hello
ports:
- port: 80
targetPort: 5678
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: xxx.xxx.xxx.xxx.nip.io # ← 自分のIPに置き換える(後述)
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: hello-svc
port:
number: 80
kubectl apply -f test-app.yaml
トラブルシューティング
❌ ハマりポイント1:IngressのhostにIPアドレスを直打ちするとエラー
The Ingress "hello-ingress" is invalid: spec.rules[0].host: Invalid value:
"xxx.xxx.xxx.xxx": must be a DNS name, not an IP address
KubernetesのIngress仕様では spec.rules[0].host にIPアドレスを直接指定できません。
解決策A:host フィールドを削除する(最もシンプル)
spec:
ingressClassName: nginx
rules:
- http: # host行を丸ごと削除
paths:
...
解決策B:nip.io を使う(ドメインなしでDNS名として使える)
nip.io はIPアドレスをそのままDNS名として扱える無料サービスです。
rules:
- host: xxx.xxx.xxx.xxx.nip.io
http://xxx.xxx.xxx.xxx.nip.io/ にアクセスすると、自動的にそのIPに名前解決されます。ドメインを持っていないテスト環境で非常に便利です。
❌ ハマりポイント2:コントロールプレーンノードにPodが展開されない
2ノード構成なのにPodが全てワーカーにしかスケジュールされない場合、コントロールプレーンの状態を確認します。
kubectl describe node <コントロールプレーンのノード名> | grep -A5 Taints
原因A:cordon(スケジュール停止)状態になっている
Taints: node.kubernetes.io/unschedulable:NoSchedule
Unschedulable: true
kubectl drain や kubectl cordon を過去に実行した場合、ノードがスケジュール不可状態になります。
解決策:
kubectl uncordon <コントロールプレーンのノード名>
原因B:control-plane TaintによりPodがスケジュールされない
Taints: node-role.kubernetes.io/control-plane:NoSchedule
2ノードの小規模構成でリソースを有効活用したい場合はTaintを削除します。
kubectl taint nodes <コントロールプレーンのノード名> \
node-role.kubernetes.io/control-plane:NoSchedule-
注意:
NoSchedule-の末尾-がTaint削除の意味です。
❌ ハマりポイント3:curlでは成功するがブラウザからアクセスできない
curl http://xxx.xxx.xxx.xxx.nip.io/ は成功するのに、ブラウザからアクセスするとタイムアウトする場合があります。
原因:ConoHaのセキュリティグループで80番ポートが開放されていない
VPS内部(ローカルホスト)からのcurlは成功しても、外部からのアクセスはセキュリティグループで遮断されているため、ブラウザ(外部)からはタイムアウトします。
解決策:ConoHaコントロールパネルでセキュリティグループを設定する
- ConoHaコントロールパネル → 対象VPS → 「ネットワーク情報」→「セキュリティグループ」
-
IPv4v6-Webセキュリティグループを追加する
IPv4v6-Web はHTTP(80)/HTTPS(443)の外部アクセスを許可するConoHa提供のプリセットです。カスタムグループを作成している場合は、TCP 80/443のインバウンドルールを手動で追加してください。
| プロトコル | ポート | 方向 |
|---|---|---|
| TCP | 80 | インバウンド |
| TCP | 443 | インバウンド |
❌ ハマりポイント4:curlのHostヘッダーとIngressのhost設定が不一致
# ❌ これはマッチしない
curl -H "Host: hello.example.com" http://xxx.xxx.xxx.xxx/
# ✅ Ingressのhostと一致させる
curl -H "Host: xxx.xxx.xxx.xxx.nip.io" http://xxx.xxx.xxx.xxx/
# ✅ または nip.io のURLに直接アクセス
curl http://xxx.xxx.xxx.xxx.nip.io/
Nginx IngressはHostヘッダーでルーティングを判断します。host: xxx.xxx.xxx.xxx.nip.io と設定している場合、Host: hello.example.com では404になります。
動作確認
kubectl get ingress
# NAME CLASS HOSTS ADDRESS PORTS AGE
# hello-ingress nginx xxx.xxx.xxx.xxx.nip.io ... 80 Xm
curl http://xxx.xxx.xxx.xxx.nip.io/
# Hello from Ingress!
ブラウザから http://xxx.xxx.xxx.xxx.nip.io/ にアクセスして Hello from Ingress! が表示されれば完成です。
まとめ:ハマりポイント一覧
| # | ハマりポイント | 原因 | 解決策 |
|---|---|---|---|
| 1 | IngressのhostにIPを直打ちするとエラー | KubernetesのIngress仕様 |
hostを削除 or nip.ioを使う |
| 2 | コントロールプレーンにPodが展開されない | cordon状態 or Taint |
uncordon or Taint削除 |
| 3 | ブラウザからアクセスできない(タイムアウト) | セキュリティグループで80番未開放 | ConoHaでIPv4v6-Webを追加 |
| 4 | curlで404になる | Hostヘッダーの不一致 | Ingressのhostと合わせる |
次のステップ
- cert-managerの導入:Let's EncryptによるTLS証明書の自動取得でHTTPS化
- MetalLBの導入:ベアメタル環境でLoadBalancerタイプのServiceを使えるようにする
- 複数サービスへのルーティング:pathやhostベースで複数のバックエンドに振り分ける