--- lang: ja-jp tags: Infrastructure, Kubernetes title: Kubernetes Ingress --- # Kubernetes Ingress - [KubernetesにIngressを導入する方法](https://qiita.com/Hirata-Masato/items/8e6b4536b6f1b23c5270) - [learnk8s: A visual guide on troubleshooting Kubernetes deployments](https://learnk8s.io/troubleshooting-deployments) - [Ingress TLS](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls) - [Kubernetes docs: Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) ## Overview アプリケーションを構成するリソースは(基本的に)以下の通り: 1. **Pods**: 同一のIPアドレスが割り当てられた1つ以上のコンテナから構成される基本単位 2. **ReplicaSet**: Podの複製を作成し、サービスを構成するアプリケーションの個数を維持 3. **Deployment**: ReplicaSetを管理し、ローリングアップデートといったデプロイの機能を提供 クラスタに展開するDeploymentを、外部ネットワークに公開するには、基本的には**Service**リソースを利用することになる。`type=LoadBalancer`のServiceを作成することで、外部からのアクセスを受け付けることが可能になる。 しかし、Serviceリソースでは実現できない機能がいくつか存在する: - IPアドレスはServiceごとに生成されるため、アクセスポイントが変わりうる - HTTPSへのリダイレクトを実現できない - 同一Pod内に存在する(i.e. ローカルホストが同じ)コンテナに別々のルーティングを割り当てる場合に、Nginxのようなリバースプロキシを追加するひつようがある このような問題を解決するためのリソースとして、アプリケーションレイヤのロードバランスとして**Ingress**リソースが存在する。 ## Infra as Code: Service, Deployment - Serviceリソースの種類を`type=NodePort`にする - Deploymentの`spec.template.spec.containers.ports[]`にServiceの`spec.ports.targetPort`に一致するポート番号を入れる - Deploymentの`spec.template.metadata.labels`のラベル付けを正しく行う ```yaml= apiVersion: v1 kind: Service metadata: name: my-api-service namespace: my-namespace labels: app: my-api spec: type: NodePort ports: - port: 8080 targetPort: 8080 # コンテナのポート protocol: TCP selector: app: my-api-pod # どのラベルが割り当てられたPodと接続するかのセレクタ --- apiVersion: apps/v1beta kind: Deployment metadata: name: my-api-deployment namespace: my-namespace spec: replicas: 1 revisionHistoryLimit: 3 template: metadata: namespace: my-namespace labels: app: my-api-pod # このラベルをServiceリソースが探す version: latest spec: containers: - name: my-api image: gcr.io/moriaki3193/my-api:latest ports: - containerPort: 8080 # IngressとServiceの連携まで時間がかかるため # ヘルスチェックの設定をうまくやるには以下を参照 # https://qiita.com/Hirata-Masato/items/8e6b4536b6f1b23c5270#%E8%BF%BD%E8%A8%98201823 ``` ## Infra as Code: Ingress - `spec.rules[].http.paths[].<pathname>.serviceName`にServiceに割り当てた`metadata.name`の値を設定する ```yaml= apiVersion: extensions/v1beta1 kind: Ingress metadata: name: my-ingress namespace: my-namespace annotations: # optional kubernetes.io/ingress.global-static-ip-name: my-ipaddress spec: rules: - host: myapi.example.com http: paths: - <pathname>: serviceName: my-api servicePort: 8080 # Serviceのポートを指定 ``` **optional**な箇所については、Ingressを削除し、再設定した際にIPアドレスが変わりうるため、固定するようにするための設定となっている。 ## Terminology - **Node**: Kubernetesクラスタのワーカマシンのこと。 - **Cluster**: Kubernetesにより管理される、コンテナ化されたアプリケーションを実行するNodeの集合。クラスタに属するノードは外部ネットワークには接続されていない。 - **Edge Router**: クラスタのファイアウォールのポリシーを強制するルータのこと。クラウドベンダーにより管理されるゲートウェイであったり、物理的なハードウェアであったりする。 - **Cluster network**: クラスタ内部のやりとりを執り行う論理的あるいは物理的なリンクの集合のこと。詳細は[K8s networking model](https://kubernetes.io/docs/concepts/cluster-administration/networking/)を参考のこと。 - **Service**: ラベルセレクタを利用してPodの集合を識別するK8sのサービスのこと。特に他のリソースで指定されない限り、サービスはクラスタネットワーク内部でのみ接続可能な仮想IPアドレスを持つ。 ## What is Ingress? クラスタ外部からのHTTPやHTTPSによる通信をクラスタ内部のサービスに接続する役割を担うリソースのこと。**トラフィックルーティングはIngressリソースにより定義されるルールによってコントロールされる**。 ``` internet | [ Ingress ] --|-----|-- [ Services ] ``` IngressはServiceに外部からアクセス可能なURLを設定したり、トラフィックをロードバランシングしたり、SSL/TLS通信のエンドポイントとなったりするように設定できる。Ingress ControllerがIngressの実現に責務を負っていて、大抵の場合はロードバランサと合わせて利用される。 Ingressは任意のポートやプロトコルを公開することはない。HTTPとHTTPS以外の場合にインターネットにサービスを公開する際には、Serviceリソースがその責任を負う。`type=NodePort`または`type=LoadBalancer`が該当する。 ## Prerequisites Ingressリソースを立ち上げるには、`ingress controller`が必要になる。Ingressリソースを作成するだけでは、クラスタにはなんら影響はない。Ingress Controllerについては[こちら](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers)を参考にする。 `ingress-nginx`といったようなIngress Controllerをデプロイする必要があるかもしれない。種類は数多くあるので、用途にあったものを選択すればよい。 ## The Ingress Resource 最低限のIngressリソースの具体例は次の通り: ```yaml= apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: test-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - http: paths: - path: /testpath backend: serviceName: test servicePort: 80 ``` ### Service type: NodePort > NodePortは、全てのKubernetes Nodeの`ipaddr:port`で受信したトラフィックをコンテナに転送する形で、外部疎通性を確立します 内部的には、マシンワーカとしてのノードに割り当てられた仮想的なソケットを指定して、Pod内のコンテナに通信を引き渡す役割を担っている。 ### ingress-nginx [kuberntes/ingress-nginx](https://github.com/kubernetes/ingress-nginx/blob/master/docs/examples/rewrite/README.md)に詳細が記載されている。 #### ingress.class annotations - `nginx.ingress.kubernetes.io/rewrite-target` - トラフィックがリダイレクトされなければならないターゲットURIを指定できる - `nginx.ingress.kubernetes.io/app-root` - '/'コンテキストである場合にコントローラがリダイレクトしなければならないApplication Rootを定義できる #### Rewrite Target ```yaml= apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 name: rewrite namespace: default spec: rules: - host: rewrite.bar.com http: paths: - backend: serviceName: http-svc servicePort: 80 path: /something(/|$)(.*) ``` このIngressリソースの定義では、`(.*)`文字列でキャプチャされる文字がすべて`$2`プレースホルダに代入される。 このような設定を行うことで、次のような結果が得られる。 - `rewrite.bar.com/something` → `rewrite.bar.com/` - `rewrite.bar.com/something/` → `rewrite.bar.com/` - `rewrite.bar.com/something/new` → `rewrite.bar.com/new` #### App Root `spec.rules[].http.paths[].path`で指定されたパスのパターンに対してリダイレクトをかける。 ```yaml= apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/app-root: /app1 name: approot namespace: default spec: rules: - host: approot.bar.com http: paths: - backend: serviceName: http-svc servicePort: 80 path: / ``` - `http://approot.bar.com/` → 302 Moved Temporarily - `http://approot.bar.com/app1`になる ### メモ ``` # / にアクセスされたら3000番ポートに # /api にアクセスされたら、apiの文字列を削除して5000番ポートに # :80/api/estimate → :5000/estimate ということ # フロントエンドのアプリケーションの静的ファイルがすべてルーティングされていないので、Ingressを修正する # Flaskの方のエンドポイントを修正する ```
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up