0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ConoHa VPS バニラKubernetesにNginx Ingressを構築する

0
Posted at

はじめに

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 drainkubectl 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コントロールパネルでセキュリティグループを設定する

  1. ConoHaコントロールパネル → 対象VPS → 「ネットワーク情報」→「セキュリティグループ」
  2. 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ベースで複数のバックエンドに振り分ける
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?