(O+P)ut

アウトプット



(O+P)ut

エンジニアのアウトプット

【Nginx/Ingress】Endpointに紐づくPodのIP変更を検知する流れ

スポンサーリンク

確認したいこと

NGINX Ingress ControllerはService/Endpointに紐づくPodのIPが変更されるとそれを検知します。
今回はDeploymentでNGINX Ingress Controllerが動作している環境で、変更検知の流れをログから調査しました。

環境情報
  • NGINX Ingress controller Release: v0.48.1
  • Kubernetes: v1.23

確認方法/結果

Nginx Ingress Controllerにはでバックログ(Debug Logging)機能があり、デプロイメント起動時に--v=5を指定することでログレベルを上げることができます。この状態でEndpoint上の1つのPodを削除した際のNginx Ingress Controllerのログは以下。

まずはPodの削除をイベントとして検知した上で

... nginx.go:345] "Event received" type=UPDATE object="&Endpoints{ObjectMeta:{testnginx  default  ... <nil> <nil> map[app:testnginx] map[] [] []  [{kube-controller-manager Update v1... FieldsV1 {\"f:metadata\":{\"f:labels\":{\".\":{},\"f:app\":{}}},\"f:subsets\":{}} }]},Subsets:[]EndpointSubset{EndpointSubset{Addresses:[]EndpointAddress{EndpointAddress{IP:xx2,TargetRef:&ObjectReference{Kind:Pod,Namespace:default,Name:xx,APIVersion:,ResourceVersion:,FieldPath:,},...

同Endpointの最新状態を取得することで削除したPodを宛先から除外します。具体的には「Endpoints found for Service」の箇所には削除されたPod以外の宛先の記載があります。

... controller.go:975] Creating upstream "xx"
... controller.go:1083] Obtaining ports information for Service "xx"
... endpoints.go:77] Getting Endpoints for Service "xx" and port &ServicePort{Name:,Protocol:TCP,Port:80,TargetPort:{0 80 },NodePort:0,AppProtocol:nil,}
... endpoints.go:129] Endpoints found for Service "XX": [{AAA 80 &ObjectReference{Kind:Pod,Namespace:default,Name:xx:,ResourceVersion:,FieldPath:,}} {BB 80 &ObjectReference{Kind:Pod,Namespace:default,Name:xxa,APIVersion:,ResourceVersion:,FieldPath:,}}]
... controller.go:711] Replacing location "/" for server "_" with upstream "upstream-default-backend" to use upstream "default-xx-80" (Ingress "default/test-ingress")
...

逆にPodが増えた場合は同じようにEventを受信して以下のように新たなエンドポイントとして宛先を追加。Endpoints found for Serviceには新たなIPで起動されたPodのIPも表示されています。

... nginx.go:345] "Event received" type=UPDATE object="&Endpoints{ObjectMeta:{xx  default  ... <nil> <nil> map[app:testnginx] map[endpoints.kubernetes.io/last-change-trigger-time:xx] [] []  [{kube-controller-manager Update v1 ... UTC FieldsV1 {\"f:metadata\":{\"f:annotations\":{\".\":{},\"f:endpoints.kubernetes.io/last-change-trigger-time\":{}},\"f:labels\":{\".\":{},\"f:app\":{}}},\"f:subsets\":{}} }]},Subsets:[]EndpointSubset{EndpointSubset{Addresses:[]EndpointAddress{EndpointAddress{IP:AA,TargetRef:&ObjectReference{Kind:Pod,Namespace:default,Name:...,APIVersion:,ResourceVersion:,FieldPath:,},Hostname:,NodeName:*xx,},EndpointAddress{IP:CC,TargetRef:&ObjectReference{Kind:Pod,Namespace:default,Name:xx,APIVersion:,ResourceVersion:,FieldPath:,},Hostname:,NodeName:*xx,},EndpointAddress{IP:BB,TargetRef:&ObjectReference{Kind:Pod,Namespace:default,Name:xx,APIVersion:,ResourceVersion:,FieldPath:,},Hostname:,NodeName:*xx,},},NotReadyAddresses:[]EndpointAddress{},Ports:[]EndpointPort{EndpointPort{Name:,Port:80,Protocol:TCP,AppProtocol:nil,},},},},}"

以下、補足です。

補足

endpoint.goにて指定されたサービス/ポートの組み合わせに対するEndpointのリストを取得していますが

func getEndpoints(s *corev1.Service, port *corev1.ServicePort, proto corev1.Protocol,	getServiceEndpoints func(string) (*corev1.Endpoints, error)) []ingress.Endpoint {
...

その中でupsServersとしてPodのIPを取得しています。

この仕様はスティッキーセッション等で利用される必要な流れですが

NGINX Ingress Controllerに不具合が発生してしまうと、Endpoint側の更新が検知できずに通信エラーが起きる原因にもなっています。

以上。