広告

kubernetes – Ingress

infrastructure as code

Ingressの概要

manifestのリソース指定:
kind: Ingress

Ingressはk8sクラスタにL7のロードバランシングなどの機能を提供します。

IngressはIngressを提供するIngress Controllerを使う必要があります。
よく使われているのは、GKE Ingress ControllerとNginx Ingress Controllerです。

  • GKE Ingress Controller(外部リソース)
    • k8sクラスタ外のロードバランサーを利用
      • 裏では、GCEを作成され、Ingress Controllerの役割になるみたい
  • Nginx Ingress Controller(内部リソース)
    • k8sクラスタ内にIngress用Podをデプロイして利用
      • Nginx Ingress
      • Nghttpx Ingress

それぞれの動きが異なります。

  • 外部リソース(GCPクラウド):クライアント → 外部L7ロードバランサー → 転送先Pod
    • この場合、Ingressの立場はLoadBalancer Serviceとほとんど変わらない
    • k8sのServiceではないため、NodePort Service は事前に作成する必要がある
  • 内部リソース(Nginx):クライアント → LoadBalancer(L4) → Nginx Pod → 転送先Pod

トラフィックの流れは文字だけではわかりにくいので、GCPのIngress場合のイメージ図を作成しました。

GCP-Ingress

Ingressの機能

Ingressが実現できる機能は以下になります。

  • URLのpathベースのトラフィック転送
    • 例:www.bar.com/site01www.bar.com/site02/site0X部分で違うNodePortへ転送させる
    • manifest設定:spec.roles[].http.paths[].path
  • URLのhost名ベースのトラフィック転送:DNSの登録が必要
    • 例:www.bar.com/site01www.foo.com/site01www.XXX.com部分で違うNodePortへ転送させる
    • manifest設定:spec.roles[].host
  • TLS(SSL)の実装:
    • 証明書を持たせることが可能(暗号化通信)
      • 証明書はsecretとして作成し、Ingressに関連付けます。
    • 複数証明書搭載可能
    • ポート443(HTTPS)のみサポート
    • HTTPのブロッキング機能
      • annotationsの設定でHTTPを受け付けさせないことが可能
        • 設定:annotations.kubernetes.io/ingress.allow-http: "false"
        • アクセスすると、404で返ってくる
  • ロードバランサー
  • ヘルスチェック

Ingressの実装

IngressはLoadbalancerと違って、NodePortは自動的に作成してくれません。
そのため、Ingressと紐づくためのNodePortを作成する必要があります。

IngressとNodePortを紐づく条件

  • Ingressのspec.rules[].http.paths[].backend.servicePortが、NodePortのspec.ports[].portが一致であること
  • Ingressのspec.rules[].http.paths[].backend.serviceNameが、NodePortのmetadata.nameが一致であること

IngressはkubernetesのService(NodePort)と紐づくことで使用します。

Ingressのmanifest例

# NodePort作成
apiVersion: v1
kind: Service
metadata:
  name: my-nodeport-01
spec:
  type: NodePort
  selector:
    app: MyApp
  ports:
    - port: 8080
      targetPort: 80
      nodePort: 30080
---
# NodePort作成
apiVersion: v1
kind: Service
metadata:
  name: my-nodeport-02
spec:
  type: NodePort
  selector:
    app: MyApp
  ports:
    - port: 8081
      targetPort: 80
      nodePort: 30081
---
# Ingress作成
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
  - host: foo-bar.com  # hostは、公開用のFQDN、証明書などと併用の場合に使う、持ってない場合省略しよう
    http:
      paths:
      - path: /foo
        backend:  # NodePortと紐づく
          serviceName: my-nodeport-01  # NodePort名を指定
          servicePort: 8080  # NodePortのPortを指定
      - path: /bar
        backend:  # NodePortと紐づく
          serviceName: my-nodeport-02
          servicePort: 8081

参考:

Set up an external Application Load Balancer with Ingress  |  Kubernetes Engine  |  Google Cloud

GCPでIngressに静的IP降りたい場合

以下を満たす必要があります。

  • IngressのapiVersion:extensions/v1beta1にする
  • annotations.kubernetes.io/ingress.global-static-ip-nameに事前に作成した静的IP(Global IP)のリソース名を指定する
  • リージョン IP アドレスは Ingress では機能しませんので、グローバルで作成する必要がある(プレミアム)

参考

Ingressのbackend

Ingressのbackendは2種類あります。

  • rulesで定義するbackend:ルールに従って転送する
  • デフォルトのbackend:ルールに書いていないトラフィックの転送先
    • デフォルトbackendを定義しない場合:
      • GCPの場合、勝手にbackendが作成されるが、そのbackendは404が返ってくるように作成される

なので、GCPでIngressを作成する際に、backendは1個しか定義していないのに、2個作成されたときに仕様通りなので、ご安心ください。

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  backend:  # デフォルトのbackendの定義。※ GCPの場合、省略しても作成される
    serviceName: def-backend
    servicePort: 80
  rules:  # rulesで定義するbackend
  - host:
    http:
      paths:
      - path: /foo
        backend:
          serviceName: my-nodeport-01
          servicePort: 8080
      - path: /bar
        backend:
          serviceName: my-nodeport-02
          servicePort: 8081

Ingressのヘルスチェック

ここは結構ハマったところでした。

Loadbalancerは基本200~399の範囲のステータスコードは全部健全(ヘルス)と判断してくれますが、Ingressは200しか受け付けません。
しかも、デフォルトではサイトの/ディレクトリにリクエストを投げます。

多くのアプリはサイトの/ディレクトリはリダイレクトするようになるので、302が返ってくることが多いですが、これはIngressでは通信不可と判断してしまいます。

参考情報

対処方法については、Podに事前にヘルスチェックのファイルを置いて(例えば/healthz)、Podのヘルスチェック(readinessProbe)をIngress作成する前に用意することです。

ポイントは:

  • Podに200で応答してくるページを用意
  • Podのヘルスチェック定義を入れる:readinessProbehttpGet
  • Ingress作成する前に上記を済ませる(或いはIngress再作成でも可)

最後に

今回は以前説明できなかったIngressについて、更新しました。
実際に作ってみて、色々調査しながら、この記事を成し遂げました。
作ってみたものも記事にしているので、興味ある方はぜひ参考にしていただければと思います。

Discovery & LBリソースの中でも、あんまり使わないものがあります。
個人的によく使うのは以下ですかね。

  • Service
    • ClusterIP
    • NodePort(Ingressと併用するために)
    • LoadBalancer
    • Headless(None)(StatefulSetと併用するために)
    • ExternalName
  • Ingress

ここまで読んでいただいて、お疲れ様でした。

コメント

タイトルとURLをコピーしました