使用IngressClass资源而不是注解(nginx-ingress)

经历/经验

因为 Kubernetes 版本 1.18 以后将不再推荐使用 Ingress 资源中的 Ingress.Class 注解,所以需要进行调查准备。

這篇文章中有一張清楚解釋Ingress是什麼的圖片。

调查

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/。

废弃指南: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或容器实例会减少人力成本。

存在变更的文件和参数等。

大致的更改点可以通过拉取chart并从CHANGELOG.md中追踪来查看,所以看起来很好。另外,值得留意是否有覆盖的values.yaml参数被改变了。在这里,所说的更改点是指将ingress-nginx的helm chart版本从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(アプリ側のチャートの直下のやつ)
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 或副本数时选择出 Leader 的 id。
https://blog.sakamo.dev/post/ingress-nginx/#leader-election
成为 Leader 的 Pod 每秒都在同步 Ingress 的状态。
它是使用 client-go 实现的,并使用 ConfigMap 进行锁定。
如果 Leader 落下或无法更新 renewTime,其他 Pod 将更新 renewTime 和 holderIdentity,并升级为 Leader。
→ 既然默认值都已经定义了,不如只修改 internal 部分会更好。虽然在仅有一个 Ingress Controller Pod 的情况下没有发现特别的问题,但在测试以外的情况下几乎不会只有一个 Pod 的情况。

※2:通过名称获取IngressClass的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会监视IngressClass名称以及ControllerClass名称,以确定是否匹配。

当IngressController的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,那么多个Ingress的内部部分将返回404,但是如果为true,则可以到达目标Service的Pod而不是返回404。

※3:ingressClassResource.name
在以前的图表中,这个参数被称为 “ingressClass”。看起来现在已经改变为这个了。

※4:ingressClassResource.controllerValue

当使用 get 命令查看 ingressClass 资源时,在 CONTROLLER 中显示的值是多个 IngressClass 的步骤中所需的参数。
请参考以下链接获取如何在同一集群中轻松安装多个 ingress-nginx controller 的详细说明:
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
如果启用了 admissionWebhooks,官方似乎在这里提到了它的一些用处:https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#validatingadmissionwebhook
根据一些详细的描述,可以在这里找到更多信息:https://blog.sakamo.dev/post/ingress-nginx/
似乎它可以执行 “nginx -t” 或验证操作
在这个链接中可以找到相关的代码:https://github.com/kubernetes/ingress-nginx/blob/ingress-nginx-2.7.0/internal/ingress/controller/controller.go#L201
但是由于不太了解具体的使用方法,所以暂时停止了使用(还没有确认该选项启用的情况下是否可以安全地不管它)

    ingress.yaml(アプリ側のチャートのtemplatesの下にあるやつ)
{{- 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号:主持者
当没有指定主持时,使用get命令查看ingress资源的地址时会出现异常情况,无法通过内部Ingress控制器访问到后台服务,会出现HTTP错误代码404(但使用注释可以访问)。
另外,关于404错误,说明没有找到路径存在,需要检查服务名称、端口、路径或DNS中的哪个可能存在问题。例如,在旧版本的Ingress中,对于只显示顶级路径“/”的某些服务,使用path: /(.*)时会出现404错误。
https://github.com/nginxinc/kubernetes-ingress/issues/966

※7: apiVersion、ingressClassName、service.name、service.port这四个参数需要按照 AKS 1.19 和 Helm Chart 版本 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オプションに指定してるファイル。特に何も変えていないが一応貼っておく
# 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'

确认指令

我想要检查资源是否按照预期的方式生成,并查看负载均衡器IP是否已经应用到服务上,还有其他一些快速查看日志的操作。

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

在另一个窗口中,通常用于仅执行临时的curl命令的Pod上查看日志,通过内部控制器使用curl访问目标Pod,以确认日志是否能够输出。

$ 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访问的域名应该是使用内部Ingress控制器的LoadbalancerIP加上服务名+default.svc.cluster.local,但应该使用在ingress.yaml中定义的域名作为host。

更新时的指令 shí de

当进行对Ingress Controller 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 chart的目录中,根据重复指南执行以下操作。

$ 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の場合)

ベースチャートにしてるingress-nginxのチャートのappVersion: が1.8以上でないとIngressClassリソースを使って複数のコントローラを制御することができなさそうであることがわかった。(IngressClassが一つなら大丈夫。)

KubernetesでNGINXIngress Controllerを使うメリットとは

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 76s
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 1xx.xx.16.1 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 80/TCP 3d8h
test-ingress-error ClusterIP 1xx.xx.17.160 80/TCP 3d8h
test-static ClusterIP 1xx.xx.18.149 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
kubectl describe po

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

错误总结
    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])?)*')

另外,在助手中未被引用的代码块,如果保持原样,将会导致helm upgrade出现类似于缺少apiVersion的错误提示。

请参考以下网站

Kubernetes 应用调试方法
https://qiita.com/tkusumi/items/a62c209972bd0d4913fc

Ingress公式手册
https://kubernetes.io/zh/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/
在1.8版本的发布说明中提到支持多个ingress-controller

KubernetesでNGINXIngress Controllerを使うメリットとは

使用Helm在AKS上安装Ingress/Nginx的步骤可以参考以下链接:
https://docs.microsoft.com/zh-cn/azure/aks/ingress-basic

使用Helm安装ingress-nginx的官方步骤
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

有一篇相当真实的详细文章,详细介绍了一个名叫乔纳森的熟悉Azure Kubernetes Service(AKS)的专家所写,涉及不同的入口选项。文章链接:https://jonathan18186.medium.com/azure-kubernetes-service-aks-with-different-ingress-options-part1-835a9d09a057

我们正在努力重新创建多个nginx ingress控制器,但是在这个重要问题上缺少了决定性的信息。
https://github.com/kubernetes/ingress-nginx/issues/5996

这是一篇残念的文章,只是提及了多个IngressClass,并且仅以注释的形式存在。

对于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 依赖管理

要求.yaml文件的helm2版本或Chart版本过低。

如何制作详细的Helm入门指南和图表等
https://knowledge.sakura.ad.jp/23603/
https://qiita.com/thinksphere/items/5f3e918015cf4e63a0bc
https://qiita.com/HaraShun/items/cd7735d82b87770292e4

Helm图表开发最佳实践

Helm Chartの実践的活用法


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

Ingress控制器的一般内容。

在Ingress主机定义中,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/#路径类型

多Ingress类相关
https://kubernetes.github.io/ingress-nginx/#如何在同一集群中轻松安装多个Ingress-NGINX控制器
https://kubernetes.github.io/ingress-nginx/user-guide/multiple-ingress/

命令行参数列表
https://kubernetes.github.io/ingress-nginx/user-guide/cli-arguments/

bannerAds