5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

annotationではなくIngressClassリソースを使う(nginx-ingress)

Last updated at Posted at 2021-07-21

経緯

kubernetesのバージョンが1.18以降でIngressリソースにおけるIngress.Classというアノテーションが非推奨になる、
ということで調査しておく必要があるという話になったため。

Ingressとはなにかがよくわかる図が載っている記事
https://qiita.com/MahoTakara/items/cdfa379f2280a58fdd6d

調査

k8s公式にはIngress.Classのアノテーションはもう非推奨だしIngressClassリソースつかえやみたいなの書いてます。
https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/
https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class
いまは公式のマニュアルにもIngressClassのことが書かれている
https://kubernetes.github.io/ingress-nginx/user-guide/multiple-ingress/

Deplicationガイド
https://kubernetes.io/docs/reference/using-api/deprecation-guide/

環境固有の前提

  • AKSを使っている
  • helmチャートでの更新(helm 3.2.0)
  • 使っているイングレスはGoogleのingress-nginx
  • helmチャートは一つでingressのチャートはchartsのなかに入れてるし2つのコントローラのためにディレクトリコピーして名前変えてる
  • 本体チャートのvalues.yamlやhelm upgrade時の--valuesオプションで指定するenv名yamlとかでcharts内の依存チャートの変数を上書きしている
  • LoadbalancerIPを固定するためにAzureポータルでPublicIPのserviceラベルを剝がしている

AKS1.20, ingress-nginx4.0.6のケース

ぼんやりしてたらクラスタとチャートのバージョンが結構上がってしまって検証がやりなおしに。
kubernetes関連は半年もたつとEOLになりがちなのでカスタマイズと新機能上等で大規模に色々やりたいのでないならECSとかContainer Instancesにするほうが人件費が減るのかも。

変更があったファイルとパラメータなど

おおざっぱな変更点はchartをpullしてきてCHANGELOG.mdから辿れるのでみるとよさそう。
あとは上書きしているvalues.yamlのパラメータが変わってないかどうかをガン見するとよさそう。
ここでいう変更点とは、ingress-nginxのhelmチャートのバージョン3.33.0から4.0.6に変えた場合のことを指す。

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx  #only once at initial
helm repo update
helm pull ingress-nginx/ingress-nginx --untar --version 4.0.6 --untar
view ingress-nginx/CHANGELOG.md
  • values.yaml(アプリ側のチャートの直下のやつ)
values.yaml
ingress-nginx-internal:
  controller:
    electionID: ingress-internal-controller-leader #※1
    ingressClassByName: true #※2
    ingressClassResource:#※3
      name: nginx-internal#※3
      enabled: true
      controllerValue: "k8s.io/ingress-nginx-internal" #※4
    config:
      server-tokens: "false"
    service:
      annotations:
        service.beta.kubernetes.io/azure-load-balancer-internal: "true"
    admissionWebhooks: #※5
      enabled: false #※5

ingress-nginx:
  controller:
    electionID: ingress-controller-leader
    ingressClassByName: true
    ingressClassResource:
      name: nginx
      enabled: true
      controllerValue: "k8s.io/ingress-nginx"
    config:
      server-tokens: "false"
    admissionWebhooks:
      enabled: false
  defaultBackend:
    enabled: "true"
akv2k8s:
  env_injector:
  # -- Whether to install the env-injector
    enabled: false

※1: electionID
--election-id はHPAやreplica数を増やした場合にリーダー選出するためのidである。
https://blog.sakamo.dev/post/ingress-nginx/#leader-election
Leaderとなった Pod は Ingress のステータスを毎秒同期している。
client-go で実装されていて、 ConfigMap を使いロックをしている。
Leaderが落ちたりして renewTime の更新ができなかった場合は他の Pod が renewTime と holderIdentity を更新しLeaderに昇格する。
→default値のままでどうせ定義されるので、それよりはinternalだけは変えたほうがいいんだろうと思われる
 定義しなくてもイングレスコントローラのPodが1つのケースだと特に問題は確認できなかったがテスト以外で1つのケースはそんなに無さそう。

※2: ingressClassByName
https://kubernetes.github.io/ingress-nginx/#how-to-easily-install-multiple-instances-of-the-ingress-nginx-controller-in-the-same-cluster
https://github.com/kubernetes/ingress-nginx/blob/main/cmd/nginx/flags.go#L72
IngressControllerがControllerClassと一緒に名前でIngressClassを監視するかどうかを定義します。
イングレスコントローラのPodが起動するときに、そのIngressClass名で指定したものとPodの.spec.controller((上のオプションの説明によるとこれはControllerClassにあたると思われる)が一致するのを監視してくれる模様
https://github.com/kubernetes/ingress-nginx/pull/7609

$ kubectl get po tttest-chart-ingress-nginx-internal-controller-659dccf475-jxndm -o yaml|grep class
    - --controller-class=k8s.io/ingress-nginx-internal
    - --ingress-class-by-name=true

この値がfalseだと複数イングレスの内部側が404になるがtrueだと404にならずに目的のServiceのPodに到達できていた。

※3: ingressClassResource.name
これは昔のチャートにおいては、「ingressClass」というパラメータだった。それをこれに変えたみたいですね。

※4: ingressClassResource.controllerValue
ingressClassリソースをgetでみたときのCONTROLLERに表示される値で複数IngressClassの手順にかかれていて必要なパラメータ
https://kubernetes.github.io/ingress-nginx/#how-to-easily-install-multiple-instances-of-the-ingress-nginx-controller-in-the-same-cluster
https://kubernetes.github.io/ingress-nginx/user-guide/multiple-ingress/

※5: admissionWebhooks
事例がかかれていた:https://logmi.jp/tech/articles/323444#s7
有効になってる場合は有用らしいようなことが公式にはかかれている
https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#validatingadmissionwebhook
詳しく書いてる人によると、https://blog.sakamo.dev/post/ingress-nginx/
nginx -tとかvalidationしてくれるらしい
https://github.com/kubernetes/ingress-nginx/blob/ingress-nginx-2.7.0/internal/ingress/controller/controller.go#L201
けど具体的な使い方がよくわからないのでとりあえず止めている(オプション有効なままほったらかして大丈夫なやつかどうか確認できてない)

  • ingress.yaml(アプリ側のチャートのtemplatesの下にあるやつ)
${chartname}/templates/ingress.yaml
{{- if or (eq .Values.env "tmp") (eq .Values.env "stg") }}
---
#apiVersion: extensions/v1beta1
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress
  labels:
    app: ingress
  annotations:
    #kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/whitelist-source-range: {{ .Values.publicWhitelist }}
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "60"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
    nginx.ingress.kubernetes.io/custom-http-errors: 502,503,504,405
    #nginx.ingress.kubernetes.io/enable-rewrite-log: "true"
    #nginx.ingress.kubernetes.io/configuration-snippet: |
    #  recursive_error_pages on;
    nginx.ingress.kubernetes.io/server-snippet: |
      error_page 405 = @custom_custom-default-backend-tttest-ingress-error_405;
    nginx.ingress.kubernetes.io/default-backend: tttest-ingress-error
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    #kubernetes.io/ingress.class: addon-http-application-routing
spec:
  ingressClassName: nginx
  rules:
    - http:
        {{ include "tttest.public-ingress" . | indent 8 }}
{{- end }}
---
#apiVersion: extensions/v1beta1
apiVersion: networking.k8s.io/v1 #※7
kind: Ingress
metadata:
  name: ingress-internal
  labels:
    app: ingress-internal
  annotations:
    #kubernetes.io/ingress.class: nginx-internal
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
#    nginx.ingress.kubernetes.io/default-backend: tttest-ingress-error
spec:
  ingressClassName: nginx-internal #※7
  rules:
    - host: tttest-static-int.default.svc.cluster.local #※6
      http:
        paths:
          - path: /(.*)
            pathType: ImplementationSpecific #※7
            backend:
#              serviceName: tttest-static-int
#              servicePort: 80
              service: #※7
                name: tttest-static-int #※7
                port: #※7
                  number: 80 #※7

※6: host
host指定しないとingressリソースをgetでみたときのADDRESSがおかしなことになって内部イングレスコントローラを介して裏にいるサービスに到達できなくてhttpエラーコード404でていた(アノテーションだと到達できる)
あと404はルートが存在しないと出るということでサービス名かポートかパスかDNSのどれかがダメというのを調べていく感じで、古い方のイングレスでTopの/しか表示しないようなサービスでpath: /(.*)だと404 でたりしていた。
https://github.com/nginxinc/kubernetes-ingress/issues/966

※7: apiVersionとingressClassNameとservice.nameとservice.port
これらはAKS1.19かつhelmチャートバージョンが3.33で対応したときとおなじように変えるだけ
https://kubernetes.io/ja/docs/concepts/services-networking/ingress/#%E3%83%91%E3%82%B9%E3%81%AE%E3%82%BF%E3%82%A4%E3%83%97

  • networkpolicy.yaml
    イングレスコントローラのPodのラベルが変わるからfromのイングレスからtoのアプリのPodのラベルめがけて接続許可しているルールのfromのラベル変える必要があった

  • ingressClass.yaml
    helmチャートのtemplatesのあたりにIngressClassリソースのマニフェストのテンプレートが同梱されていて勝手にIngressClassリソースが作られるっぽいので自分でかかなくてよくなってたので消した

  • env/${environment}.yaml
    環境毎に変える必要があるパラメータをvalues.yamlとは別に定義していてhelmのdiffとかupgrade打つときの--valuesオプションに指定してるファイル。特に何も変えていないが一応貼っておく

env/${environment}.yaml
# Public Nginx ingress
ingress-nginx:
#nginx-ingress:
  defaultBackend:
    replicaCount: 1
  controller:
    replicaCount: 1
    config:
      log-format-upstream: '$http_x_forwarded_for - $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time [$proxy_upstream_name] [$proxy_alternative_upstream_name] $upstream_addr $upstream_response_length $upstream_response_time $upstream_status $req_id'
    service:
      loadBalancerIP: '*******' ##test-je-cluster2-ing-pip
      externalTrafficPolicy: "Local"

# Internal Nginx ingress defaults
ingress-nginx-internal:
#nginx-ingress-internal:
  defaultBackend:
    replicaCount: 1
  controller:
    replicaCount: 1
    config:
      log-format-upstream: '$http_x_forwarded_for - $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time [$proxy_upstream_name] [$proxy_alternative_upstream_name] $upstream_addr $upstream_response_length $upstream_response_time $upstream_status $req_id'
    service:
      loadBalancerIP: '100.98.0.35'
      externalTrafficPolicy: "Local"

# Ingress values
## - Front Door ref: https://docs.microsoft.com/en-us/azure/frontdoor/front-door-faq#how-do-i-lock-down-the-access-to-my-backend-to-only-azure-front-door
## - Special IP ref: https://docs.microsoft.com/ja-jp/azure/virtual-machines/windows/instance-metadata-service
publicWhitelist: "****"
publicHost: '****.japaneast.azmk8s.io'

確認コマンド

意図したとおりにリソースができててLoadbalancerIPがサービスについてるかなどなどをザっと見るのとログ見る

kubectlっぽいの
$ kubectl get po,ing,ingressClass,service,deploy  #-o wideつけるとPodのIPとかもでる
$ kubectl describe ing <イングレス名> 
$ kubectl logs -f --tail=20 <イングレスコントローラのPod名>

ログをtailしておいて別窓で一時的にたてたcurl打つだけ用のPodからcurlで内部コントローラ越しに目的のPodにたどり着いてログが出るかを確認する。

到達を確認するcurl
$ kubectl run curl-komi --image=radial/busyboxplus:curl -i --tty --rm --labels=app.kubernetes.io/name=ingress-nginx-internal
$ curl http://tttest-chart-ingress-nginx-internal-controller.default.svc.cluster.local

curlするドメインは内部イングレスコントローラのLoadbalancerIPがついてるサービス名+default.svc.cluster.localをつかってるが、ingress.yamlのhostに定義したドメインでいいはず。

更新時のコマンド

更新するとき、イングレスコントローラのPodが作り直される系の更新の場合(IngressClass使うようにする更新だとそうなる)、消してから追加する感じにしたほうが余計なものが残らなくていいと思います。(要メンテだけども)
helmでもkubectlでも消せるけどkubectlで消すとhelm diffで確認ができないので急いでるとか検証とかじゃないければhelmチャート内のマニフェストを消す感じになる。

#diff
## helm plugin install https://github.com/databus23/helm-diff --version e186caafe744378a6059f9b70084b49daf196ede ##初回のみ
## リリース済みと未リリースの比較
helm diff upgrade tttest-chart tttest-chart -C 3 --allow-unreleased --values env/${environment}.yaml
## revisionの比較
helm diff revision tttest-chart 8 10

#install/upgrade
helm list
helm upgrade --install tttest-chart tttest-chart --values=env/${environment}.yaml

非推奨APIが無いかを確認する

使っているhelmチャートのディレクトリでdeplicationGuideに基づいて以下を実施

find+grep参考
$ find ./ -type f |xargs grep admissionregistration.k8s.io/v1beta
$ find ./ -type f |xargs grep apiextensions.k8s.io/v1beta
$ find ./ -type f |xargs grep authorization.k8s.io/v1beta1
$ find ./ -type f |xargs grep extensions/v1beta1
$ find ./ -type f |xargs grep networking.k8s.io/v1beta1
$ find ./ -type f |xargs grep rbac.authorization.k8s.io/v1beta1

AKS1.19,ingress-nginx3.33.0のケース

古い情報はたたんでおきます
#### 成功した設定(singleのIngress Controllerの場合)

:warning: ベースチャートにしてるingress-nginxのチャートのappVersion: が1.8以上でないとIngressClassリソースを使って複数のコントローラを制御することができなさそうであることがわかった。(IngressClassが一つなら大丈夫。)
https://www.nginx.co.jp/blog/announcing-nginx-ingress-controller-for-kubernetes-release-1-8-0/

NGINX IngressとHelmチャートにおける複数のIngress Controllerのサポート
これまでのリリースでは、NGINX Ingress Controllerの複数のインスタンスを
同一クラスター上に共存させることが可能でしたが、標準のKubernetes Ingressリソースで
kubernetes.io/ingress.classアノテーションを使用して対象のNGINX Ingress Controller
デプロイメントを指定した場合に限られていました。
リリース1.8では、VirtualServer/VirtualServerRouteリソースにingressClassNameフィールド
を追加して、これらのリソースでも同じことができるようにしました。また、複数のNGINX Ingress
Controllerデプロイメントをサポートするように、Helmチャートをアップデートしました。

ingressclass.yaml
---
apiVersion: networking.k8s.io/v1beta1
kind: IngressClass
metadata:
  name: nginx
# annotations:
# ingressclass.kubernetes.io/is-default-class: "true"
spec:
  controller: nginx.org/ingress-controller
ingress.yaml
{{- if eq .Values.env "test" }}
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress
  labels:
    app: ingress
  annotations:
    #kubernetes.io/ingress.class: nginx    ##★コメントイン
    nginx.ingress.kubernetes.io/whitelist-source-range: {{ .Values.publicWhitelist }}
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "60"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
    nginx.ingress.kubernetes.io/custom-http-errors: 502,503,504,405
    nginx.ingress.kubernetes.io/enable-rewrite-log: "true"
    nginx.ingress.kubernetes.io/server-snippet: |
      error_page 405 = @custom_custom-default-backend-test-ingress-error_405;
    nginx.ingress.kubernetes.io/default-backend: test-ingress-error
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  ingressClassName: nginx   ##★IngressClassリソースのname指定追加
  rules:
    - http:
#~略~
$ kubectl get ingress
NAME      CLASS          HOSTS   ADDRESS   PORTS   AGE
ingress   nginx          *                 80      3d8h
$ kubectl get ingressclass
NAME           CONTROLLER                     PARAMETERS   AGE
nginx          nginx.org/ingress-controller   <none>       76s
$ kubectl get service
NAME                                         TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)                      AGE
kubernetes                                   ClusterIP      1xx.xx.16.1     <none>           443/TCP                      4d7h
test-chart-nginx-ingress-controller          LoadBalancer   1xx.xx.17.253   20.xxx.xxx.xxx   80:30125/TCP,443:31458/TCP   3d8h
test-chart-nginx-ingress-default-backend     ClusterIP      1xx.xx.16.47    <none>           80/TCP                       3d8h
test-ingress-error                           ClusterIP      1xx.xx.17.160   <none>           80/TCP                       3d8h
test-static                                  ClusterIP      1xx.xx.18.149   <none>           80/TCP                       3d8h

ブラウザからEXTERNAL-IPのサイトが見えるのを確認。特に問題なさそう。
IngressClassリソースを使ってるingressコントローラの数分複数書く場合はチャートのバージョンほかspec.controller等に注意。

IngressController/IngressClassを複数動かすために必要なこと

  • 簡単な前提

    • AKSのVersion1.19を利用(PublicIPのタグのあたりなど)
    • publicIngressコントローラ1つ, internalIngressコントローラ1つを必要とする環境
    • ingressのリポジトリから落としてきたソースアーカイブを解凍し複製してnameに手を入れて利用している
       (オプション指定でhelmコマンドだけで入れることも可能そうでMS公式だとそちらの手順しか出てこなかったがそれだと依存順序定めて自動で入れる動きじゃなくてパイプラインでコマンド書く感じになると思われる)
    • helmのバージョンは3.1のままでよさそう
    • charts/ディレクトリに置かれたベースチャートのアプリは本体チャートのアプリより先にインストールされる
    • chartsディレクトリを使わずにingressコントローラを準備する公式手順はこちら
       https://docs.microsoft.com/ja-jp/azure/aks/ingress-basic
  • nginx-ingressの1.25.0 -> ingress-nginxの3.33.0 にチャートのバージョンを上げる(潔く作業時の最新)
     (なぜかバージョン上げるとチャートの名前が微妙に変わる関係でコントローラ作り直しになる。名前戻してもいいけどどうせAPIバージョンやIngressClassに変わる関係で作り直しなのは変わらないのでそのままにしている)

    • Chart.lockを削除
       これを削除しないとhelm dependencyコマンドが打てない。rubyのGemfile.lockと同じ働きで複数人プロジェクトで各個人のローカル環境とパイプラインの環境の依存パッケージのバージョンを合わせる目的で使われるものと思われ、ビルド時に自動生成されるファイルなので、バージョン変えたいときは消すか戻すときのために退避するもののようです。つまり要らないファイル。
       ベース側じゃなくて本体チャート側のを消します。
mv test-chart/Chart.lock /tmp/
  • helmリポジトリを登録しなおしてアップデートする
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
  • dependenciesをChart.yamlに書いてビルドしてcharts配下にパッケージを落としてくる
     ※requirement.yamlにdependenciesを書いてるのはhelmのバージョンが2かChart.yamlのapiVersionがv1の場合のようです。
     ※dependencies別にかかなくてもpullで取ってきて配置したほうが簡単かもしれない。
vi test-chart/Chart.yaml
--add↓-
dependencies:
- name: ingress-nginx
version: 3.33.0
repository: https://kubernetes.github.io/ingress-ngin
--add↑--
helm dependency build ./test-chart
helm dependency update ./test-chart

buildするとChart.lockが作られ、updateするとcharts/下にChart.yamlのdependenciesに書いたバージョンのtgzアーカイブがダウンロードされる

  • ダウンロードしたアーカイブを解凍して、旧バージョンとアーカイブはリポジトリの外にでも退避する(そうしないとinstall/upgrade時に余計なingressリソースが増える)

admission-webhooks/validating-wehook.yamlの中身を全コメントアウトする
  (admissionコントローラがwebhookによる更新を受け付ける体でhostの設定が別に要りそうであるのと不正な設定のIngressがデプロイされないようにバリデーション設定が存在するらしい。しかしそれがあることでデプロイができない。今までなかったものであるので今後の課題として全コメントアウトにするとデプロイできる。)
 →別のクラスタで再現できずコメントもせずに普通にアドミッションコントローラが動いている。前回はチャートとマニフェストの状態の微妙だったのかも
   

  • chartsの下に解凍したディレクトリ丸ごとコピーして別名で保存してその名前にChart.yamlのnameを修正する
cd test-chart/charts
tar xzvf ingress-nginx-3.33.0.tgz
mv ingress-nginx-3.33.0.tgz /usr/local/src/
mv nginx-ingress /usr/local/src/
mv nginx-ingress-internal /usr/local/src/
sed -i 's/^/#/g' ingress-nginx/admission-webhooks/validating-webhook.yaml
cat ingress-nginx/admission-webhooks/validating-webhook.yaml
cp -rp ingress-nginx ingress-nginx-internal
vi ingress-nginx-internal/Chart.yaml
--modify↓-
name: ingress-nginx
↓
name: ingress-nginx-internal
--modify↑-

一応念のためディレクトリの差分をみてみる

$ diff -crN test-chart/charts/ingress-nginx{,-internal}
diff -crN test-chart/charts/ingress-nginx/Chart.yaml test-chart/charts/ingress-nginx-internal/Chart.yaml
*** test-chart/charts/ingress-nginx/Chart.yaml        2021-06-07 01:23:21.000000000 +0900
--- test-chart/charts/ingress-nginx-internal/Chart.yaml       2021-06-15 18:51:46.833348700 +0900
***************
*** 12,18 ****
  kubeVersion: '>=1.16.0-0'
  maintainers:
  - name: ChiefAlexander
! name: ingress-nginx
  sources:
  - https://github.com/kubernetes/ingress-nginx
  type: application
--- 12,18 ----
  kubeVersion: '>=1.16.0-0'
  maintainers:
  - name: ChiefAlexander
! name: ingress-nginx-internal
  sources:
  - https://github.com/kubernetes/ingress-nginx
  type: application
  • ベースチャートではなく本体チャート側のvalues.yamlにベースチャートのvalues.yamlに書かれてる上書きできる上書きしたい値を書く
       特に2つめ以降のingressClassの名前指定(これをingress/ingressClassリソースで定義する
       あとなぜか無効にされてるdefaultBackendを有効化(enabled:true)にするのと、
       Internal側のもともと設定されてるannotationなど。
        service.beta.kubernetes.io/azure-load-balancer-internal: "true"
vi values.yaml
ingress-nginx-internal:
  controller:
    ingressClass: "nginx-internal"
    config:
      server-tokens: "false"
    service:
      annotations:
        service.beta.kubernetes.io/azure-load-balancer-internal: "true"
  defaultBackend:
    enabled: "true"

ingress-nginx:
  controller:
    ingressClass: "nginx"
    config:
      server-tokens: "false"
  defaultBackend:
    enabled: "true"
  • ingressリソースのapiVersionを最新にする
    • apiVersionを修正する(ここを変えることでIngressリソースを作り直すことになる。または別名で作成する必要がある。AKSでIngressControllerに紐づいているPublicIPを保持することは可能で同じPublicIPを保持するためにはPublicIPについているタグ「service :~」を削除する必要がある。ただしリソースを消して作り直して新しいほうに既存のPublicIPを紐づける動きになり、断時間があるためメンテに入れる必要がある
    • pathTypeを書く、serviceの書き方を修正する
    • ingressClassNameはvalus.yamlで上書きしたものとデフォルトのingressClass名で定義
{{- if eq .Values.env "tmp" }}
---
#apiVersion: extensions/v1beta1
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress
  labels:
    app: ingress
  annotations:
    #kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/whitelist-source-range: {{ .Values.publicWhitelist }}
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "60"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
    nginx.ingress.kubernetes.io/custom-http-errors: 502,503,504,405
    #nginx.ingress.kubernetes.io/enable-rewrite-log: "true"
    #nginx.ingress.kubernetes.io/configuration-snippet: |
    #  recursive_error_pages on;
    nginx.ingress.kubernetes.io/server-snippet: |
      error_page 405 = @custom_custom-default-backend-test-ingress-error_405;
    nginx.ingress.kubernetes.io/default-backend: test-ingress-error
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  ingressClassName: nginx
  rules:
    - http:
        {{ include "test.public-ingress" . | indent 8 }}
{{- end }}
---
##apiVersion: extensions/v1beta1
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-internal
  labels:
    app: ingress-internal
  annotations:
    #kubernetes.io/ingress.class: nginx-internal
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/whitelist-source-range: {{ .Values.publicWhitelist }}
    nginx.ingress.kubernetes.io/default-backend: test-ingress-error
spec:
  ingressClassName: nginx-internal
  rules:
    - http:
        paths:
          - path: /(.*)
            pathType: ImplementationSpecific
            backend:
              service:
                name: test-static
                port:
                  number: 80
  • ingressClassをただしく設定する
    • apiVersionを新しいのにする
    • valus.yamlで上書きした、またはデフォルトのingressClass名でリソースを定義する
---
apiVersion: networking.k8s.io/v1
#apiVersion: networking.k8s.io/v1beta1
kind: IngressClass
metadata:
  name: nginx
# annotations:
# ingressclass.kubernetes.io/is-default-class: "true"
  labels:
    app.kubernetes.io/managed-by: Helm
spec:
  #controller: nginx.org/ingress-controller
  controller: k8s.io/ingress-nginx
---
apiVersion: networking.k8s.io/v1
#apiVersion: networking.k8s.io/v1beta1
kind: IngressClass
metadata:
  name: nginx-internal
# annotations:
# ingressclass.kubernetes.io/is-default-class: "true"
  labels:
    app.kubernetes.io/managed-by: Helm
spec:
  #controller: nginx.org/ingress-controller
  controller: k8s.io/ingress-nginx
  • publicIPについているserviceタグを消す

タグがついたままだとIngressコントローラが消されるまたは作り替えられる際にPublicIPもろとも消されてしまうのでタグを外します。

Azure Portal より [対象の AKS クラスター] - [プロパティ] と遷移し、[インフラストラクチャ リソース グループ (MC_***)] を開く
Ingress Controller 作成時に作られた [パブリック IP アドレス] を開き、[タグ(変更)] より Ingress Controller のタグ (service : ***) を削除する

  • networkpolicyを修正する

ingressコントローラのPodについているラベルを用いてnginxのingressコントローラのPodとupstreamのPodとの通信を許可していたが、
実はUpgradeしたことによりラベルの名前が異なるものに変わった。
ラベルを修正しないとingressからアプリのコンテナへの通信ができなくなってサービス断になるところだった。

$ kubectl get pods test-chart-ingress-nginx-internal-controller-774f98b778-tnmdx -o yaml|head -20
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2021-07-20T05:50:43Z"
  generateName: test-chart-ingress-nginx-internal-controller-774f98b778-
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: test-chart
    app.kubernetes.io/name: ingress-nginx-internal
    pod-template-hash: 774f98b778
  managedFields:
  - apiVersion: v1

なのでnginxのルールは以下のようになる。

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: nginx-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      nginx: allowed
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app.kubernetes.io/name: ingress-nginx
    - podSelector:
        matchLabels:
          app.kubernetes.io/name: ingress-nginx-internal

※元のラベルは「app: nginx-ingress」等でした。

  • helmコマンドは無かったら入れる(helm3は~/.kube/configあたりのクレデンシャルを見てK8sクラスタにつなぎに行っていてkubectl config current-contextでみえた現在つないでるクラスタの操作をすることになる)
wget https://get.helm.sh/helm-v3.2.4-linux-amd64.tar.gz && tar -zxvf helm-v3.2.4-linux-amd64.tar.gz && sudo mv linux-amd64/helm /usr/local/bin/helm
## plugin入れることで現在の未デプロイとインストール済みチャートを比較
helm plugin install https://github.com/databus23/helm-diff --version e186caafe744378a6059f9b70084b49daf196ede 
  • ipを保持したい場合一旦既存のingress関連のリソースを消す(PublicIPのタグを消すのも忘れない)

※既存リソースを消さないままIngressClassを作り替えるオペレーションをするとたぶんもういっこPublicIPができる
※移動したりコメントに入れたものはあとで元に戻す
※消して戻すまでの間はリソースがないので計画メンテにしないとサービスが止まる。
(許容できなければだいぶ手間はかかるがブルーグリーンupgradeにするとよさそう)
chartsの下のディレクトリ毎移動しつつvalues.yamlの関連部分をコメントに入れてhelm upgradeでingressコントローラをアンインストールする
chartsの下のディレクトリ毎移動

$ mv test-chart/charts/ingress-nginx ./ingress-nginx_20210721test
$ mv test-chart/charts/ingress-nginx-internal ./ingress-nginx-internal_20210721test

values.yamlのingress-nginxの依存chartの上書きしてる変数の部分をコメントイン

$ sed -i 's/^/#/g' test-chart/values.yaml 
$ cat test-chart/values.yaml 

ingress/ingressClassリソースをコメントイン

$ sed -i 's/^/#/g' test-chart/templates/ingress.yaml 
$ sed -i 's/^/#/g' test-chart/templates/ingress-class.yaml 
$ cat test-chart/templates/ingress.yaml 
$ cat test-chart/templates/ingress-class.yaml 

chartsの下のdependenciesの部分をコメントイン

$ vi test-chart/Chart.yaml
$ sed -i '4,7s/^/#/g' test-chart/Chart.yaml 
$ cat test-chart/Chart.yaml

ingress.yamlに取り込んでるhelperのルーティングブロックの部分をコメントイン

$ sed -i '1,12s/^/#/g' test-chart/templates/_helpers.tpl

消えるリソースをdiffで確認

$ helm diff upgrade test-chart test-chart -C 3 --allow-unreleased --values env/tmp.yaml|grep 'default,'
  • helmでインストールする(コメントに入れたリソースを消してる)
$ helm upgrade --install test-chart test-chart --values=env/tmp.yaml
  • helmで差分を確認する
helm diff upgrade test-chart test-chart -C 3 --allow-unreleased --values env/tmp.yaml
  • helmでdeployしたリソースが存在することを確認する
kubectl get all
kubectl get ingress
kubectl get ingressClass
kubectl get configmap
  • リソースを戻す(バージョン上がってる状態で戻す)

chartsの下に移動していたディレクトリをもどす。

$ mv ./ingress-nginx_20210721test test-chart/charts/ingress-nginx
$ mv ./ingress-nginx-internal_20210721test test-chart/charts/ingress-nginx-internal

values.yamlのingress-nginxの依存chartの上書きしてる変数の部分をコメントはずす

$ sed -i 's/^#//g' test-chart/values.yaml 
$ cat test-chart/values.yaml 

ingress/ingressClassリソースをコメントはずす

$ sed -i 's/^#//g' test-chart/templates/ingress.yaml 
$ sed -i 's/^#//g' test-chart/templates/ingress-class.yaml 
$ cat test-chart/templates/ingress.yaml 
$ cat test-chart/templates/ingress-class.yaml 

chartsの下のdependenciesの部分をコメントはずす

$ vi test-chart/Chart.yaml
$ sed -i '4,7s/^#//g' test-chart/Chart.yaml 
$ cat test-chart/Chart.yaml

ingress.yamlに取り込んでるhelperのルーティングブロックの部分をコメント外す

$ sed -i '1,12s/^#//g' test-chart/templates/_helpers.tpl
$ cat test-chart/templates/_helpers.tpl

増えるリソースをdiffで確認

$ helm diff upgrade test-chart test-chart -C 3 --allow-unreleased --values env/tmp.yaml|grep 'default,'
  • helmでインストールする(追加)
$ helm upgrade --install test-chart test-chart --values=env/tmp.yaml
  • helmでdeployしたリソースを確認する
kubectl get all
kubectl get ingress
kubectl get ingressClass
kubectl get configmap

もとのPublicIPが新しく作られたingress-nginxのServiceに紐づいてるのを確認する。

  • 変なエラーでてないかログやdescribeとかを確認する
kubectl get po
kubectl logs -f <ingress-controller-pod-name>
kubectl describe po <ingress-controller-pod-name>

あとサイトの表示も確認する。

エラーまとめ
  • IngressClassリソースのコントローラの指定の文字列を修正(kubectl logsでingressコントローラのpodのログを眺めると出ていた)
E0617 10:53:50.872817       6 main.go:134] Invalid IngressClass (Spec.Controller) value "nginx.org/ingress-controller". Should be "k8s.io/ingress-nginx"
F0617 10:53:50.872955       6 main.go:135] IngressClass with name nginx is not valid for ingress-nginx (invalid Spec.Controller)
  • pathType間違ってると出るエラー
$ helm upgrade --install test-chart test-chart --values=env/tmp.yaml
Error: UPGRADE FAILED: failed to create resource: Ingress.extensions "ingress-internal" is invalid: spec.rules[0].http.paths[0].pathType: Required value: pathType must be specified
  • ingressリソースが見当たらない→if分岐でenvを限定してたことに気づかずにenv変えたせいで無かった
$ kubectl get ingress -A
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
No resources found
  • よくわからないパースエラー(予期しないEOF)だがgit checkoutして書き直したらなおった
$ helm upgrade --install test-chart test-chart --values=env/tmp.yaml
Error: UPGRADE FAILED: parse error at (test-chart/templates/ingress.yaml:72): unexpected EOF
  • IPアドレス間違えてnodePoolがあるリソースグループ内に生成されたPublicIPリソースではなくVMSSのIPを付けてた時に出たエラー
$ kubectl describe service test-chart-nginx-ingress-controller

Events:
  Type     Reason                  Age                  From                Message
  ----     ------                  ----                 ----                -------
  Normal   EnsuringLoadBalancer    34s (x6 over 3m10s)  service-controller  Ensuring load balancer
  Warning  SyncLoadBalancerFailed  34s (x6 over 3m10s)  service-controller  Error syncing load balancer: failed to ensure load balancer: user supplied IP Address 20.194.xxx.xxx was not found in resource group mc_ryoji-test_rc-test-je-cluster2-aks_japaneast
  • ingressClassの名前が重複しているため更新できないエラー(ingress作り直すとPublicIPを保持できない疑惑を確認中)
Error: UPGRADE FAILED: cannot patch "nginx" with kind IngressClass: IngressClass.networking.k8s.io "nginx" is invalid: spec.controller: Invalid value: "k8s.io/ingress-nginx": field is immutable
  • ingressClassの命名規則が間違ってるエラー
Error: UPGRADE FAILED: failed to create resource: Ingress.extensions "ingress" is invalid: spec.ingressClassName: Invalid value: "nginxPublic": a DNS-1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')

あと、helperにある引用されないブロックがそのままだとhelm upgradeでapiVersionがないみたいな内容のエラーが出る

参考サイト

k8sアプリデバッグ方法
https://qiita.com/tkusumi/items/a62c209972bd0d4913fc

ingress公式マニュアル
https://kubernetes.io/ja/docs/concepts/services-networking/ingress/

nginx公式側のhelmインストール手順(参考にはしたがつかっているのとは違うリポジトリ)
https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-helm/
https://github.com/nginxinc/kubernetes-ingress/tree/master/deployments/helm-chart#readme
nginx公式のingress-controllerのリリースノート
https://docs.nginx.com/nginx-ingress-controller/releases/
複数のingress-controllerをサポートしたとかかれている1.8のリリースノート
https://www.nginx.co.jp/blog/announcing-nginx-ingress-controller-for-kubernetes-release-1-8-0/

AKS公式のingress/nginxをhelmインストールしている手順
https://docs.microsoft.com/ja-jp/azure/aks/ingress-basic

ingress-nginx公式のhelmインストール手順
https://kubernetes.github.io/ingress-nginx/deploy/#using-helm
https://artifacthub.io/packages/helm/ingress-nginx/ingress-nginx
公式のChart.yaml
https://github.com/kubernetes/ingress-nginx/blob/master/charts/ingress-nginx/Chart.yaml

ジョナサンという野生のAKSに詳しい人が書いた割と真に迫っている詳しい記事
https://jonathan18186.medium.com/azure-kubernetes-service-aks-with-different-ingress-options-part1-835a9d09a057

複数のnginxingressコントローラを頑張って再現しようとしているが決定的な情報が欠けたissue
https://github.com/kubernetes/ingress-nginx/issues/5996

複数のIngressClassとかいってアノテーションでしかない残念な記事
https://aws.amazon.com/jp/premiumsupport/knowledge-center/eks-access-kubernetes-services/

ValidatingWebhookConfigurationについて理解が進んだ記事
https://qiita.com/gashirar/items/8dc7bd4886e82f7ffd73
https://github.com/kubernetes/ingress-nginx/issues/5401#issuecomment-662424306
https://sysdig.jp/blog/kubernetes-admission-controllers-2/

Helmのリリース
https://github.com/helm/helm/releases

helm dependency
https://helm.sh/docs/helm/helm_dependency/

requirement.yamlはhelm2かChartのバージョンが低い
https://www.skyarch.net/blog/?p=16621

だいぶ詳細なHelm入門とチャートのつくり方など
https://knowledge.sakura.ad.jp/23603/
https://qiita.com/thinksphere/items/5f3e918015cf4e63a0bc
https://qiita.com/HaraShun/items/cd7735d82b87770292e4

Helmチャート開発ベストプラクティス
https://jfrog.com/ja/blog/helm-charts-best-practices/
https://helm.sh/docs/chart_best_practices/

helmのバージョンを上げる場合にmanaged-byの推奨ラベルが必要そう
https://kubernetes.io/ja/docs/concepts/overview/working-with-objects/common-labels/

helmで分岐やループを定義する関連情報
https://golang.org/pkg/text/template/#hdr-Functions
https://stackoverflow.com/questions/49789867/can-we-use-or-operator-in-helm-yaml-files

ingress-nginxの強化ガイドで目的別に逆引きで設定が載ってる
https://kubernetes.github.io/ingress-nginx/deploy/hardening-guide/

苦しんでる人の記録
https://stackoverflow.com/questions/65165216/kubernetes-ingress-nginx-ingressclass-with-name-nginx-is-not-valid-for-ingress
https://stackoverflow.com/questions/69363123/not-found-404-nginx-unable-to-connect-through-ingress-ip-on-minikube
https://stackoverflow.com/questions/52021925/kubernetes-ingress-non-root-path-404-not-found

イングレスコントローラの一般的な内容
https://cstoku.dev/posts/2018/k8sdojo-22/

イングレスのhostの定義でADDRESSの中身がでる
https://www.webdevqa.jp.net/ja/kubernetes/%E7%A9%BA%E3%81%AE%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9kubernetes%E3%82%A4%E3%83%B3%E3%82%B0%E3%83%AC%E3%82%B9/806207987/

pathtypeの件
https://kubernetes.io/ja/docs/concepts/services-networking/ingress/#%E3%83%91%E3%82%B9%E3%81%AE%E3%82%BF%E3%82%A4%E3%83%97

マルチイングレスクラス関連
https://kubernetes.github.io/ingress-nginx/#how-to-easily-install-multiple-instances-of-the-ingress-nginx-controller-in-the-same-cluster
https://kubernetes.github.io/ingress-nginx/user-guide/multiple-ingress/

コマンドライン引数一覧
https://kubernetes.github.io/ingress-nginx/user-guide/cli-arguments/

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?