writing-skills
writing-skills
Use when creating new skills, editing existing skills, or verifying skills work before deployment
configure-ingress-networkingNGINXイングレスコントローラー、自動TLS証明書管理のためのcert-manager、 パスベースルーティング、レート制限、SSLターミネーションとロードバランシングによる マルチドメインホスティングでKubernetes Ingressネットワークを設定します。 単一のロードバランサーで複数のKubernetesサービスを公開する場合、パスベースまたは ホストベースのルーティングを実装する場合、Let's EncryptでTLS証明書を自動発行する場合、 またはトラフィック分割によるブルーグリーンやカナリアデプロイをセットアップする場合に使用します。
Independent GitHub snapshot · Automated classification · Original documentation governs
NGINXコントローラー、自動TLS証明書、および高度なルーティング機能を備えた本番グレードのKubernetes Ingressをセットアップします。
完全な設定ファイルとテンプレートについては拡張例を参照してください。
HelmでNGINX Ingressコントローラーをデプロイし、クラウドプロバイダー統合を設定します。
# Add NGINX Ingress Helm repository
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
# Create namespace
kubectl create namespace ingress-nginx
# Install for cloud providers (AWS, GCP, Azure)
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--set controller.service.type=LoadBalancer \
--set controller.metrics.enabled=true \
--set controller.metrics.serviceMonitor.enabled=true \
--set controller.podAnnotations."prometheus\.io/scrape"=true \
--set controller.podAnnotations."prometheus\.io/port"=10254
# Or install for bare-metal with NodePort
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--set controller.service.type=NodePort \
--set controller.service.nodePorts.http=30080 \
--set controller.service.nodePorts.https=30443
# AWS-specific configuration with NLB
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--set controller.service.annotations."service\.beta\.kubernetes\.io/aws-load-balancer-type"=nlb \
--set controller.service.annotations."service\.beta\.kubernetes\.io/aws-load-balancer-backend-protocol"=tcp \
--set controller.service.annotations."service\.beta\.kubernetes\.io/aws-load-balancer-cross-zone-load-balancing-enabled"=true
# Verify installation
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx
# Wait for LoadBalancer external IP
kubectl get svc ingress-nginx-controller -n ingress-nginx -w
# Get external IP/hostname
INGRESS_IP=$(kubectl get svc ingress-nginx-controller -n ingress-nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
INGRESS_HOST=$(kubectl get svc ingress-nginx-controller -n ingress-nginx -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
echo "Ingress IP: $INGRESS_IP"
echo "Ingress Hostname: $INGRESS_HOST"
# Test controller
curl http://$INGRESS_IP
# Should return 404 (no backend configured yet)
期待結果: NGINX IngressコントローラーのPodがingress-nginx Namespaceで稼働中。LoadBalancerサービスに外部IPが割り当て済み。メトリクスエンドポイントがポート10254でアクセス可能。/healthzのヘルスチェックが200 OKを返す。
失敗時: LoadBalancerがPendingの場合はクラウドプロバイダーの統合とサービスクォータを確認。CrashLoopBackOffはkubectl logs -n ingress-nginx -l app.kubernetes.io/component=controllerでコントローラーのログを確認。Webhookエラーはアドミッションwebhook証明書が有効か確認。ベアメタルで外部IPがない場合はMetalLBをインストールするかNodePortサービスタイプを使用。
cert-managerをデプロイしてLet's EncryptのClusterIssuerを設定します。
# Install cert-manager CRDs
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.crds.yaml
# Add cert-manager Helm repository
helm repo add jetstack https://charts.jetstack.io
helm repo update
# Install cert-manager
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.13.0 \
--set prometheus.enabled=true \
--set webhook.timeoutSeconds=30
# Verify installation
kubectl get pods -n cert-manager
kubectl get apiservice v1beta1.webhook.cert-manager.io -o yaml
# Create Let's Encrypt staging issuer (for testing)
cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: admin@example.com
privateKeySecretRef:
name: letsencrypt-staging-account-key
solvers:
- http01:
ingress:
class: nginx
EOF
# Create Let's Encrypt production issuer
cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@example.com
privateKeySecretRef:
name: letsencrypt-prod-account-key
solvers:
- http01:
ingress:
class: nginx
- dns01:
route53:
region: us-east-1
hostedZoneID: Z1234567890ABC
# IAM role for EKS with IRSA
role: arn:aws:iam::123456789012:role/cert-manager
EOF
# Verify ClusterIssuer ready
kubectl get clusterissuer
kubectl describe clusterissuer letsencrypt-prod
期待結果: cert-managerのPodがcert-manager Namespaceで稼働中。ClusterIssuerがReadyステータスで作成済み。Let's EncryptにACMEアカウントが登録済み。Webhookが証明書リクエストに応答。
失敗時: Webhookタイムアウトエラーはwebhook.timeoutSecondsを増加するかcert-managerからAPIサーバーをブロックするネットワークポリシーを確認。ACME登録の失敗はメールが有効でサーバーURLが正しいか確認。DNS01の失敗はRoute53のIAM権限がroute53:ChangeResourceRecordSetsを許可しているか確認。dig +short _acme-challenge.example.com TXTでDNS伝播をテスト。
アプリケーションをデプロイし、自動証明書発行付きのIngressで公開します。
# Deploy sample application
kubectl create deployment web --image=nginx:alpine
kubectl expose deployment web --port=80 --target-port=80
# Create Ingress resource with TLS
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-staging" # Use staging for testing
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- web.example.com
secretName: web-tls-secret # cert-manager will create this
rules:
- host: web.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
EOF
# Watch certificate creation
kubectl get certificate -w
kubectl describe certificate web-tls-secret
# Verify certificate issued
kubectl get secret web-tls-secret
kubectl get secret web-tls-secret -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -text -noout
# Check cert-manager logs if issues
kubectl logs -n cert-manager -l app=cert-manager -f
# Test HTTP to HTTPS redirect
curl -I http://web.example.com
# Should return 308 Permanent Redirect to https://
# Test HTTPS
curl -v https://web.example.com
# Should return 200 OK with valid certificate
# Once tested successfully, switch to production issuer
kubectl patch ingress web-ingress -p '{"metadata":{"annotations":{"cert-manager.io/cluster-issuer":"letsencrypt-prod"}}}'
kubectl delete certificate web-tls-secret
kubectl delete secret web-tls-secret
# cert-manager will recreate with production certificate
期待結果: Ingressリソースが作成済み。cert-managerがアノテーションを検出してCertificateリソースを作成。HTTP-01チャレンジが正常に完了。有効な証明書でTLSシークレットが作成済み。有効な証明書でHTTPSリクエストが成功。HTTPがHTTPSにリダイレクト。
失敗時: チャレンジ失敗はDNSがIngress LoadBalancer IPに解決されているかdig web.example.comで確認。レート制限エラーは設定が正しくなるまでステージングイシュアーを使用。証明書が発行されない場合はkubectl describe certificate web-tls-secretとkubectl get challengesでイベントを確認。「too many certificates」エラーはLet's Encryptのレート制限(週50証明書/ドメイン)に達している。待つかステージングを使用。
パスベースルーティング、ヘッダーベースルーティング、トラフィック分割を設定します。
# Deploy multiple services
kubectl create deployment api --image=hashicorp/http-echo --replicas=3 -- -text="API Service"
kubectl create deployment admin --image=hashicorp/http-echo --replicas=2 -- -text="Admin Service"
kubectl expose deployment api --port=5678
kubectl expose deployment admin --port=5678
# Create Ingress with path-based routing
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/rewrite-target: /\$2
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: app-tls
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
- path: /api(/|$)(.*)
pathType: Prefix
backend:
service:
name: api
port:
number: 5678
- path: /admin(/|$)(.*)
pathType: Prefix
backend:
service:
name: admin
port:
number: 5678
EOF
# Canary deployment with traffic splitting
kubectl create deployment api-v2 --image=hashicorp/http-echo -- -text="API Service v2"
kubectl expose deployment api-v2 --port=5678
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-canary
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "20" # 20% traffic to v2
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-v2
port:
number: 5678
EOF
# Header-based canary routing (for testing)
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-canary-header
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "X-Canary"
nginx.ingress.kubernetes.io/canary-by-header-value: "always"
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-v2
port:
number: 5678
EOF
# Test routing
curl https://app.example.com/ # -> web service
curl https://app.example.com/api/ # -> 80% api, 20% api-v2
curl https://app.example.com/admin/ # -> admin service
curl -H "X-Canary: always" https://app.example.com/api/ # -> api-v2 (100%)
期待結果: 単一のIngressがパスに基づいて複数のサービスにルーティング。rewrite-targetがパスプレフィックスを除去。カナリアIngressが重みでトラフィックを分割。ヘッダーベースルーティングが特定のリクエストをカナリアに送信。TLSがIngressで終端し、バックエンドはHTTPを使用。
失敗時: 404エラーはサービス名とポートが一致しているか確認。rewriteの問題はnginx.ingress.kubernetes.io/rewrite-targetデバッガーで正規表現をテスト。カナリアが機能しない場合は1つのIngressだけがcanary: "false"(メイン)で他がcanary: "true"であることを確認。トラフィックの不均衡はバックエンドのPod数とreadinessプローブを確認。
レート制限、基本認証、OAuth2認証を実装します。
# Rate limiting by IP
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ratelimit
# ... (see EXAMPLES.md for complete configuration)
期待結果: レート制限が過剰なリクエストを503 Service Temporarily Unavailableでブロック。基本認証がクレデンシャルを求め、未認証リクエストを拒否。OAuth2がプロバイダーのログインページにリダイレクトし、認証Cookieを設定。
失敗時: レート制限が機能しない場合はアノテーション構文を確認してIngressコントローラーのPodを再起動。基本認証の500エラーはkubectl get secret basic-auth -o yaml | grep auth:でシークレット形式を確認。OAuth2の失敗はクライアントID/シークレットとコールバックURLがプロバイダーに登録されているか確認。詳細なエラーメッセージはoauth2-proxyのログを確認。
カスタムエラーページ、CORS、リクエスト/レスポンスヘッダーを設定します。
# Create ConfigMap with custom error pages
kubectl create configmap custom-errors --from-file=404.html --from-file=503.html -n ingress-nginx
# Configure NGINX to use custom error pages
cat <<EOF | kubectl apply -f -
apiVersion: v1
# ... (see EXAMPLES.md for complete configuration)
期待結果: デフォルトのNGINXページの代わりにカスタム404と503ページが表示。CORSヘッダーが指定されたオリジンとメソッドを許可。セキュリティヘッダーがXSSとクリックジャッキングを防止。リクエストボディサイズ制限が大容量ファイルのアップロードを許可。タイムアウト設定が早期の接続切断を防止。
失敗時: カスタムエラーページが表示されない場合はConfigMapがコントローラーのPodにマウントされデフォルトバックエンドがデプロイされているか確認。CORSプリフライトの失敗はバックエンドサービスでOPTIONSリクエストが許可されているか確認。413 Request Entity Too Largeはproxy-body-sizeアノテーションを増加。タイムアウトエラーは3つのタイムアウトアノテーションをすべて一緒に増加。
ingressClassNameなし: IngressがコントローラーにピックアップされてされていないKubernetes 1.19+では常にingressClassName: nginxを指定する。
証明書チャレンジの失敗: DNSがIngress LoadBalancerを指していない。証明書をリクエストする前にdig yourdomain.comで確認。
HTTP-01チャレンジのタイムアウト: ファイアウォールがポート80をブロック。Let's Encryptは検証のためにhttp://domain/.well-known/acme-challenge/に到達する必要がある。
レート制限がグローバルに適用: limit-rpsアノテーションはパスではなくIngress単位で適用される。異なるレート制限には別々のIngressを作成する。
rewrite-targetの正規表現が間違い: キャプチャがパスパターンと一致しない。echo "/api/users" | sed 's|/api(/\|$)\(.*\)|/\2|'でテスト。
カナリーの重みが無視: 同じホスト/パスに複数のカナリアIngressが競合。1つのルートにつき1つのカナリアIngressのみ作成する。
IPによる認証バイパス: 認証がIngressのみで、バックエンドサービスがClusterIP経由でアクセス可能。ネットワークポリシーまたはサービスメッシュを実装する。
configuration-snippetインジェクションのリスク: ユーザー入力をconfiguration-snippetに使用するとNGINX設定のインジェクションが可能。全アノテーションを検証してサニタイズする。
deploy-to-kubernetes - IngressがルーティングするServiceの作成manage-kubernetes-secrets - シークレットとしてのTLS証明書の管理implement-gitops-workflow - Argo CDによる宣言的なIngress管理setup-service-mesh - Istio/Linkerdによる高度なトラフィック管理build-ci-cd-pipeline - CI/CDでのIngressの自動更新