Small Changes

Docker・Kubernetes 実践コンテナ開発入門@26日目


Metadata


前回は、k8sのリソースのServiceについて学習しました。

Serviceは基本的にはPod→Podへの経路を指定するためのものでした。

今回はIngressについてやっていきます。

5.10 Ingress

NodePortはL4層レベルまでのため、HTTP/HTTPSのようにL7層レベルの制御ができない

これを解決するのがIngress

素のローカルk8s環境では使えない。

そのため、nginx_ingress_controllerをデプロイします。

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.16.2/deploy/mandatory.yaml
namespace/ingress-nginx created
service/default-http-backend created
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-role created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
unable to recognize "https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.16.2/deploy/mandatory.yaml": no matches for kind "Deployment" in version "extensions/v1beta1"
unable to recognize "https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.16.2/deploy/mandatory.yaml": no matches for kind "Deployment" in version "extensions/v1beta1"
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.16.2/deploy/provider/cloud-generic.yaml
service/ingress-nginx created

テキストが古いためかエラーが出ている。

  • no matches for kind "Deployment" in version "extensions/v1beta1"

k8sのバージョンは1.18.8(DockerのSettingsのk8sの項目から確認できる)

1.18.8が対応するAPIを確認

$  kubectl api-resources | grep deployment
deployments                       deploy       apps                           true         Deployment

公式を見ながらやる方法もあるけど、、いったんテキストのyamlを書き換える方法でやってみる。

mandatory.yamlをローカルに落として、extensions/v1beta1をapps/v1に置換して再実行

いけたー!!!

$ kubectl apply -f mandatory.yaml 
namespace/ingress-nginx created
deployment.apps/default-http-backend created
service/default-http-backend created
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-role created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
deployment.apps/nginx-ingress-controller created

さっきはPodが起動してなかったけど、ちゃんとPodも起動してくれた

これでIngressリソースを利用する準備が整った

$ kubectl -n ingress-nginx get service,pod
NAME                           TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
service/default-http-backend   ClusterIP      10.108.154.236   <none>        80/TCP                       93s
service/ingress-nginx          LoadBalancer   10.104.144.30    localhost     80:30719/TCP,443:31795/TCP   11s
NAME                                           READY   STATUS    RESTARTS   AGE
pod/default-http-backend-57fb4c77b4-zxq6b      1/1     Running   0          93s
pod/nginx-ingress-controller-7bfbcc484-ql2m8   1/1     Running   0          93s

5.10.1 Ingressを通じたアクセス

Ingressを通してServiceにアクセス

simple-service.yaml

  • spec.typeが未指定のときはClusterIP Serviceで作成される

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

マニフェストファイルの変更を反映

$ kubectl apply -f simple-service.yaml
The Service "echo" is invalid: spec.ports[0].nodePort: Forbidden: may not be used when `type` is 'ClusterIP'

エラーが出るので一旦Service削除

$ kubectl delete -f simple-service.yaml
service "echo" deleted

再度実行

$ kubectl apply -f simple-service.yaml
service/echo created

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   CLASS    HOSTS              ADDRESS     PORTS   AGE
echo   <none>   ch05.gihyo.local   localhost   80      42s

Ingeressのspec.rules.host属性に合致するのでバックエンドのServiceにリクエストが委譲されるようだ。

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

他にも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

モバイルに偽装してリクエストを飛ばすとリダイレクトされることがわかる。

$ curl http://localhost -H 'Host: ch05.gihyo.local' -H 'User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1'
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.13.12</center>
</body>$ curl http://localhost -H 'Host: ch05.gihyo.local' -H 'User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1'
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.13.12</center>
</body>

バックエンドのWebサーバやアプリケーションがこのような制御から解放される

IngressはパブリッククラウドにおいてはそのプラットフォームのL7ロードバランサーを利用可能

  • GCP

    • Cloud Load Balancing

  • AWS

    • Application Load Balancer

コラム freshpodでイメージの更新を検知し,Podを自動更新する

freshpod

  • イメージの更新を検知し、Podを自動更新する

  • webpackerのdev-serverとかに近いイメージを持った!

コラム kube-prompt

kube-prompt

  • macOS/Linux向け

  • kubectlのコマンドや、リソース名の候補を補完してくれるツール

コラム Kubernetes API

k8sのリソースの作成・更新・削除はk8sクラスタにデプロイされているAPIによって実行される

apiVersionはリソースの操作に利用するAPIの種別

k8sクラスタで利用できるAPIの確認方法

$ kubectl api-versions

各種リソースがどのAPIに対応しているかはリポジトリを見る。

v1

  • Service、Pod

apps/v1

  • Deployment

extenxionx/v1beta1

  • Ingress

今日の学び

Ingressは外部からのHTTP/HTTPSリクエストを受けることができ、Serviceに委譲することができる。

設定次第では、Webサーバやアプリケーション層のL7層の役割を担うことができる。

最初はテキスト通りにうまくいかずどうなるかと思ったけど、なんとか動いてくれてよかった!

References