経緯
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(アプリ側のチャートの直下のやつ)
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の下にあるやつ)
{{- 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オプションに指定してるファイル。特に何も変えていないが一応貼っておく
# 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 get po,ing,ingressClass,service,deploy #-o wideつけるとPodのIPとかもでる
$ kubectl describe ing <イングレス名>
$ kubectl logs -f --tail=20 <イングレスコントローラのPod名>
ログをtailしておいて別窓で一時的にたてた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するドメインは内部イングレスコントローラの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 ./ -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のケース
古い情報はたたんでおきます
ベースチャートにしてる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チャートをアップデートしました。
---
apiVersion: networking.k8s.io/v1beta1
kind: IngressClass
metadata:
name: nginx
# annotations:
# ingressclass.kubernetes.io/is-default-class: "true"
spec:
controller: nginx.org/ingress-controller
{{- 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と同じ働きで複数人プロジェクトで各個人のローカル環境とパイプラインの環境の依存パッケージのバージョンを合わせる目的で使われるものと思われ、ビルド時に自動生成されるファイルなので、バージョン変えたいときは消すか戻すときのために退避するもののようです。つまり要らないファイル。
ベース側じゃなくて本体チャート側のを消します。
- Chart.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/
マルチイングレスクラス関連
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/