開発日報

窓際エンジニアの開発備忘。日報は嘘です。

【連載】Kubernates入門・GKEデプロイと発展的利用 第5回 ~ Ingressによるルーティング ~

はじめに

この連載ではコンテナオーケストレーションツールである、 Kubernatesの使い方を学びます。
今回はIngressについて学習します。

サンプルコード

こちらに順次アップしていきますー。

連載記事一覧

連載記事一覧

Ingress

NodePortを使用すればKubernetesクラスタ外にServiceを公開することができます。

ただし、この手法はあくまでもL4層レベルまでしか扱えないため、パスベースで転送先のServiceを切り替えるといったL7層レベルの制御はできません。

Ingressを使用すれば、ServiceのKubernetesクラスタの外への公開と、VirtualHostやパスベースでの高度なHTTPルーティングを両立します。

しかし、通常のローカルKubernetes環境ではIngressを使ったServiceの公開をすることはできません。

クラスタの外からのHTTPリクエストをServiceにルーティングするためのnginx_ingress_controllerを次のようにデプロイします。

$ kubectl apply -f \
https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.16.2/deploy/mandatory.yaml
$ kubectl apply -f \
https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.16.2/deploy/provider/cloud-generic.yaml

ingress-nginxというNamespace上に次のようなServiceとPodが作成されます.

$ kubectl -n ingress-nginx get service,pod
NAME                           TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
service/default-http-backend   ClusterIP      10.100.224.213   <none>        80/TCP                       54s
service/ingress-nginx          LoadBalancer   10.99.9.129      localhost     80:31361/TCP,443:30547/TCP   28s

NAME                                           READY   STATUS    RESTARTS   AGE
pod/default-http-backend-55b84578bf-pszn2      1/1     Running   0          53s
pod/nginx-ingress-controller-b5d545f8f-v5dmw   1/1     Running   0          54s

Ingressを通じたアクセス

実際にIngressを通してServiceにアクセスしてみましょう。simple-service-ingress.yamlを次のように定義します。spec.typeが未指定のときはClusterIP Serviceで作成されます。

# simple-service-ingress.yaml

apiVersion: v1
kind: Service
metadata:
  name: echo
spec:
  selector:
    app: echo
  ports:
    - name: http
      port: 80

マニフェストファイルの変更を反映します。

$ kubectl apply -f simple-service-ingress.yaml

Ingressを定義したマニフェストファイルsimple-ingress.yamlを作成・反映します。

# simple-ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: echo
spec:
  rules:
  - host: ch05.gihyo.local
    http:
      paths:
      - path: /
        backend:
          serviceName: echo
          servicePort: 80
$ kubectl apply -f simple-ingress.yaml
ingress.extensions/echo created

$ kubectl get ingress
NAME   HOSTS              ADDRESS     PORTS   AGE
echo   ch05.gihyo.local   localhost   80      7s

IngressはL7層のルーティングが可能なので、指定したホストやパスに合致したサービスにリクエストを委譲できます。

ローカルから次のようにHTTPリクエストを投げるとバックエンドに存在するecho Serviceから次のようにレスポンスが返ってきます。

$ curl http://localhost -H 'Host: ch05.gihyo.local'
Hello Docker!!

他にもHTTPリクエストをIngressの層で様々な制御をすることができます。例えば、simple-ingress.yamlに次のような変更を加えます。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: echo
  annotations:
    nginx.ingress.kubernetes.io/server-snippet: |
      set $agentflag 0;

      if ($http_user_agent ~* "(Mobile)" ){
        set $agentflag 1;
      }

      if ( $agentflag = 1 ) {
        return 301 http://gihyo.jp/;
      }

spec:
  rules:
  - host: ch05.gihyo.local
    http:
      paths:
      - path: /
        backend:
          serviceName: echo
          servicePort: 80

では反映してみます

$ kubectl apply -f simple-ingress.yaml
ingress.extensions/echo configured

では実際にアクセスしてみます。ここでは、User-AgentにMobileが含まれているリクエストを別のURLにリダイレクトしています。simple-ingress.yamlを反映し、User-AgentにMobileをリクエストを発行すると、301でリダイレクトされることがわかります。

$ curl -LI http://localhost \
    -H 'Host: ch05.gihyo.local' \
    -H 'User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X)a AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1'

IngressでHTTPリクエストの制御ができるため、バックエンドのWebサーバやアプリケーション側ではこのような処理を入れる必要はなくなります。

nginx-ingress-controllerでは他にも様々な機能があります。

IngressパブリッククラウドにおいてはそのプラットフォームのL7ロードバランサーを利用できます。GCPの場合はデフォルトでCloud Load Balancingを、AWSであればApplication Load Balancerを利用可能です。

まとめ

ここまでローカルKubernetes環境を利用してKubernetesの基本的な概念や操作を体験してきました。しかし、ローカルKubernetes環境ではKubernetesの全ての機能を備えてるわけではないためできることには限界があります。

次回以降ではパブリッククラウドを用いたより実践的なKubernetesでのアプリケーション構築、オンプレミスでのKubernetesクラスタの構築を紹介していきます。