ローリングコンバットピッチなう!

AIとか仮想化とかペーパークラフトとか

microk8sでNodePortサービスやIngress-Controllerを試してみる

概要

前々回エントリーでkubernetes内で2個のreplicasetを持ったpod及びpodにアクセスするためのserviceを立ち上げました。
rc30-popo.hatenablog.com

また前回エントリーでClusterネットワーク内の他podから立ち上げたserviceがDNS検索出来る事を確認しました。
rc30-popo.hatenablog.com

前回までは立ち上げたservice及びpodにはClusterネットワーク内のCluster IPを使ってpodにアクセスしました。また2個立ち上げたpodへのロードバランシングはランダムでした。

今回は下記の流れの中で③④を試します。ただしmicrok8sでシングルノードで動作させているので外部ロードバランサーは動作させていません。

①podが複数起動する様にdeploymentとreplicasetを定義、podが落ちても自動的に一定数のpodが起動し続ける様にする。
②serviceを定義し、replicasetで定義されたpod群をservice nameで(DNSを使い)検索可能とすると共に、serviceへのアクセスを自動的に各podにロードバランスされる様にする。
③serviceをノードの外部に公開し、External IPでアクセス可能とする。その際も自動的に各podにロードバランスさせる。
④外部のクライアントからpod上のWebアプリへのアクセス時に、同一クライアントからは同一podにアクセスする様にセッション維持(sticky session)を行う。

flask-helloアプリを改造

sticky sessionの実験を行う前にpod内で動かすflask-helloアプリを改造して、アプリから取れる情報量を増やします。前回まではpod自身のCluster IPを表示させていましたが、今回からはpodから見えるクライアントのIPアドレスや、podに渡されたHTTPリクエストヘッダを表示し、proxy等を通した際のヘッダの見え方等も確認出来る様にしておきます。

flask-helloアプリのソース(hello.py)は以下の通りです。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Loadbalancer debug application using flask and python3
# Copyright (C) RC30-popo 2022

from flask import Flask
from flask import request
import socket

PORT=5000
my_host = socket.gethostname()
my_ip = socket.gethostbyname(my_host)

app = Flask(__name__)

@app.route('/')
def hello():
    global myhost,my_ip
    mes = 'Hello World!!\n' + 'My Hostname='+my_host+',My IP='+my_ip+'\n'
    client_ip = request.remote_addr
    mes += 'Client IP='+client_ip + '\n'
    mes += '**Request Headers**\n'
    for header_key in request.headers.keys():
        mes += header_key + ':' + request.headers.get(header_key) + '\n'
    return mes

if __name__ == '__main__':
    app.run(host='0.0.0.0',port=PORT)

このソースを用いてdocker imageを作るためのDockerfileは以下の通りです。ubuntu18.04ベースにしていますが、20.04等でも動くと思います。

# Dockerfile for flask-hello application
# Copyright (C) 2022, RC30-popo


FROM ubuntu:18.04

EXPOSE 5000

RUN apt -y update
RUN apt -y upgrade
RUN apt -y install python3
RUN apt -y install python3-pip
RUN pip3 install flask


ENV APPDIR /flaskapp
RUN mkdir -p ${APPDIR}
COPY ./hello.py ${APPDIR}/hello.py
RUN chmod +x ${APPDIR}/hello.py
WORKDIR ${APPDIR}

ENTRYPOINT ["./hello.py" ]

ビルドしたdocker imageのmicrok8sへの登録方法は以下のエントリを参照願います。
rc30-popo.hatenablog.com

NodePort Serviceを立ち上げる

serviceを外部公開する場合、type:LoadBalancerとtype:NodePortというものが使えるのですが、今回はシングルノードのためNodePortを使います。
NodePortというのは、ノードに外部IPに対してservice用のPortを割り当てるものです。
自分の実験環境では192.168.11.252がノードIPでこれに適当なポート番号でserviceにアクセスするための穴を空けます。

svc-nodeport-flaskhello.yamlというファイル名で、service,deployment,replicaset,podの定義を下記の通り作成しました。

apiVersion: v1
kind: Service
metadata:
        name: flask-hello
spec:
        type: NodePort
        ports:
                - protocol: TCP
                  port: 5000
                  targetPort: 5000
        selector:
                app: flask-hello

---

apiVersion: apps/v1
kind: Deployment
metadata:
        name: flask-hello-deploy
spec:
        selector:
                matchLabels:
                        app: flask-hello
                spec:
                        containers:
                        - name: hello-flask
                          image: myubuntu:flask-hello
                          imagePullPolicy: Never
                          ports:
                          - containerPort: 5000

kubectlコマンドでservice,replicaset,podを生成・起動します。

$ sudo microk8s kubectl create -f svc-nodeport-flaskhello.yaml
service/flask-hello created
deployment.apps/flask-hello-deploy created
$ sudo microk8s kubectl get service,deployment,replicaset,pod --output=wide
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE     SELECTOR
service/kubernetes    ClusterIP   10.152.183.1    <none>        443/TCP          232d    <none>
service/flask-hello   NodePort    10.152.183.36   <none>        5000:32338/TCP   2m34s   app=flask-hello

NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS    IMAGES                 SELECTOR
deployment.apps/flask-hello-deploy   2/2     2            2           2m34s   hello-flask   myubuntu:flask-hello   app=flask-hello

NAME                                           DESIRED   CURRENT   READY   AGE     CONTAINERS    IMAGES                 SELECTOR
replicaset.apps/flask-hello-deploy-5465d8d8b   2         2         2       2m33s   hello-flask   myubuntu:flask-hello   app=flask-hello,pod-template-hash=5465d8d8b

NAME                                     READY   STATUS    RESTARTS   AGE     IP           NODE       NOMINATED NODE   READINESS GATES
pod/flask-hello-deploy-5465d8d8b-pvfwz   1/1     Running   0          2m33s   10.1.3.243   ubuntu01   <none>           <none>
pod/flask-hello-deploy-5465d8d8b-tmcbr   1/1     Running   0          2m33s   10.1.3.241   ubuntu01   <none>           <none>

service/flask-helloを見るとPORT(S)として「5000:32338/TCP」と記載されています。
これはClusterネットワーク内ではserviceのCluster IP=10.152.183.36:5000、ノード外からはノードIP:32338にアクセスすることでservice/flask-helloにアクセス出来るという事です。
何回かserviceのCluster IP=10.152.183.36でHTTPアクセスしてみます。

$ curl http://10.152.183.36:5000
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-tmcbr,My IP=10.1.3.241
Client IP=192.168.11.252
**Request Headers**
Host:10.152.183.36:5000
User-Agent:curl/7.61.0
Accept:*/*
$ curl http://10.152.183.36:5000
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-tmcbr,My IP=10.1.3.241
Client IP=192.168.11.252
**Request Headers**
Host:10.152.183.36:5000
User-Agent:curl/7.61.0
Accept:*/*
$ curl http://10.152.183.36:5000
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-tmcbr,My IP=10.1.3.241
Client IP=192.168.11.252
**Request Headers**
Host:10.152.183.36:5000
User-Agent:curl/7.61.0
Accept:*/*
$ curl http://10.152.183.36:5000
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-pvfwz,My IP=10.1.3.243
Client IP=192.168.11.252
**Request Headers**
Host:10.152.183.36:5000
User-Agent:curl/7.61.0
Accept:*/*

2つのpod(10.1.3.241,10.1.3.243)にロードバランシングされていること、HTTPのHost:ヘッダにはserviceのCluster IP:Port番号が入っています。
次にノードのPort番号32338にアクセスしてみると、同じ様に2つのpodにロードバランシングしながら到達している事が判ります。

$ curl http://localhost:32338
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-pvfwz,My IP=10.1.3.243
Client IP=192.168.11.252
**Request Headers**
Host:localhost:32338
User-Agent:curl/7.61.0
Accept:*/*
$ curl http://localhost:32338
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-tmcbr,My IP=10.1.3.241
Client IP=192.168.11.252
**Request Headers**
Host:localhost:32338
User-Agent:curl/7.61.0
Accept:*/*

さて、ここでmicrok8sのノードとは別のマシンからアクセスしてみます。

$ curl http://192.168.11.252:32338
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-tmcbr,My IP=10.1.3.241
Client IP=192.168.11.252
**Request Headers**
Host:192.168.11.252:32338
User-Agent:curl/7.65.3
Accept:*/*

Client IPが192.168.11.252(microk8sをインストールしたubuntuマシンのIP)のままです。実際にアクセスに使ったのは別IPを持ったマシンですがどうやらkube-proxyがClient IPを書き換えてしまい、本来のクライアントのIPアドレスがpod内のアプリから見えなくなってしまう様です。

NodePort serviceのsticky sessionを使う

NodePort serviceではClient IPを利用したsticky sessionが使えるそうです。これを利用するとClient のIPアドレス毎に必ず決まったpodにアクセスする様になるはずです。
これを試してみます。

svc-nodeport-flaskhello.yamlを少し修正して svc-nodeport2-flaskhello.yamlを作成します。

apiVersion: v1
kind: Service
metadata:
        name: flask-hello
spec:
        type: NodePort
        sessionAffinity: ClientIP
        sessionAffinityConfig:
                clientIP:
                        timeoutSeconds: 60
        ports:
                - protocol: TCP
                  port: 5000
                  targetPort: 5000
        selector:
                app: flask-hello

---

apiVersion: apps/v1
kind: Deployment
metadata:
        name: flask-hello-deploy
spec:
        selector:
                matchLabels:
                        app: flask-hello
        replicas: 2
        template:
                metadata:
                        name: flask-hello
                        labels:
                                app: flask-hello
                spec:
                        containers:
                        - name: hello-flask
                          image: myubuntu:flask-hello
                          imagePullPolicy: Never
                          ports:
                          - containerPort: 5000

前回との違いはserviceのspecに

        sessionAffinity: ClientIP
        sessionAffinityConfig:
                clientIP:
                        timeoutSeconds: 60

という行を追加した事です。あるクライアントが60秒以内にアクセスすれば同じpodに接続されます。(60秒は実験のために短めにしてあります。)
再度service〜podを起動します。

$ sudo microk8s kubectl create -f svc-nodeport2-flaskhello.yaml
service/flask-hello created
deployment.apps/flask-hello-deploy created
$ sudo microk8s kubectl get service,deployment,replicaset,pod --output=wide
NAME                  TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE    SELECTOR
service/kubernetes    ClusterIP   10.152.183.1     <none>        443/TCP          232d   <none>
service/flask-hello   NodePort    10.152.183.179   <none>        5000:32166/TCP   13s    app=flask-hello

NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS    IMAGES                 SELECTOR
deployment.apps/flask-hello-deploy   2/2     2            2           13s   hello-flask   myubuntu:flask-hello   app=flask-hello

NAME                                           DESIRED   CURRENT   READY   AGE   CONTAINERS    IMAGES                 SELECTOR
replicaset.apps/flask-hello-deploy-5465d8d8b   2         2         2       12s   hello-flask   myubuntu:flask-hello   app=flask-hello,pod-template-hash=5465d8d8b

NAME                                     READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
pod/flask-hello-deploy-5465d8d8b-bm948   1/1     Running   0          12s   10.1.3.245   ubuntu01   <none>           <none>
pod/flask-hello-deploy-5465d8d8b-75p95   1/1     Running   0          12s   10.1.3.239   ubuntu01   <none>           <none>

今回は32166がNodePortです。
まずmicrok8sと同じマシンからアクセス。

$ curl http://192.168.11.252:32166
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-bm948,My IP=10.1.3.245
Client IP=192.168.11.252
**Request Headers**
Host:192.168.11.252:32166
User-Agent:curl/7.61.0
Accept:*/*
$ curl http://192.168.11.252:32166
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-bm948,My IP=10.1.3.245
Client IP=192.168.11.252
**Request Headers**
Host:192.168.11.252:32166
User-Agent:curl/7.61.0
Accept:*/*
$ curl http://192.168.11.252:32166
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-bm948,My IP=10.1.3.245
Client IP=192.168.11.252
**Request Headers**
Host:192.168.11.252:32166
User-Agent:curl/7.61.0
Accept:*/*
$ curl http://192.168.11.252:32166
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-bm948,My IP=10.1.3.245
Client IP=192.168.11.252
**Request Headers**
Host:192.168.11.252:32166
User-Agent:curl/7.61.0
Accept:*/*
$ curl http://192.168.11.252:32166
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-bm948,My IP=10.1.3.245
Client IP=192.168.11.252
**Request Headers**
Host:192.168.11.252:32166
User-Agent:curl/7.61.0
Accept:*/*
$ curl http://192.168.11.252:32166
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-bm948,My IP=10.1.3.245
Client IP=192.168.11.252
**Request Headers**
Host:192.168.11.252:32166
User-Agent:curl/7.61.0
Accept:*/*
$ curl http://192.168.11.252:32166
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-bm948,My IP=10.1.3.245
Client IP=192.168.11.252
**Request Headers**
Host:192.168.11.252:32166
User-Agent:curl/7.61.0
Accept:*/*
$ curl http://192.168.11.252:32166
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-bm948,My IP=10.1.3.245
Client IP=192.168.11.252
**Request Headers**
Host:192.168.11.252:32166
User-Agent:curl/7.61.0
Accept:*/*
$ curl http://192.168.11.252:32166
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-bm948,My IP=10.1.3.245
Client IP=192.168.11.252
**Request Headers**
Host:192.168.11.252:32166
User-Agent:curl/7.61.0
Accept:*/*
$ curl http://192.168.11.252:32166
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-bm948,My IP=10.1.3.245
Client IP=192.168.11.252
**Request Headers**
Host:192.168.11.252:32166
User-Agent:curl/7.61.0
Accept:*/*

10回アクセスしましたが、全て10.1.3.245のpodに接続しています。
別マシンから何回かアクセスすると、podから見えるClient IPは変らず192.168.11.252ですが、別のpodにずっと接続しています。

$ curl http://192.168.11.252:32166
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-75p95,My IP=10.1.3.239
Client IP=192.168.11.252
**Request Headers**
Host:192.168.11.252:32166
User-Agent:curl/7.65.3
Accept:*/*
$ curl http://192.168.11.252:32166
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-75p95,My IP=10.1.3.239
Client IP=192.168.11.252
**Request Headers**
Host:192.168.11.252:32166
User-Agent:curl/7.65.3
Accept:*/*
$ curl http://192.168.11.252:32166
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-75p95,My IP=10.1.3.239
Client IP=192.168.11.252
**Request Headers**
Host:192.168.11.252:32166
User-Agent:curl/7.65.3
Accept:*/*
$ curl http://192.168.11.252:32166
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-75p95,My IP=10.1.3.239
Client IP=192.168.11.252
**Request Headers**
Host:192.168.11.252:32166
User-Agent:curl/7.65.3
Accept:*/*
$ curl http://192.168.11.252:32166
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-75p95,My IP=10.1.3.239
Client IP=192.168.11.252
**Request Headers**
Host:192.168.11.252:32166
User-Agent:curl/7.65.3
Accept:*/*
$ curl http://192.168.11.252:32166
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-75p95,My IP=10.1.3.239
Client IP=192.168.11.252
**Request Headers**
Host:192.168.11.252:32166
User-Agent:curl/7.65.3
Accept:*/*
$ curl http://192.168.11.252:32166
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-75p95,My IP=10.1.3.239
Client IP=192.168.11.252
**Request Headers**
Host:192.168.11.252:32166
User-Agent:curl/7.65.3
Accept:*/*

Ingress-Controllerを使う(sticky session無し)

NodePort serviceを使えばクライアントのIPを見てsticky sessionが実現出来る事が分かりましたが、途中経路にNATやProxyサーバーがあるとクライアント端末の判定が正確にできなくなります。
これを回避する手段としてIngress-Controllerというものが使えます。
Ingress-Controllerはノード外からのアクセスをserviceに繋ぎ込むための制御を行います。

外部クライアント→Ingress-Controller→service→podという感じです。

microk8sの場合、

$ sudo microk8s.enable ingress

でnginx-ingress-controllerというものを有効化可能です。
有効化後、下記の様なコマンドでingressというnamespaceでnginx-ingress-microk8s-controllerが走行していることが判ります。

$ sudo microk8s kubectl get pod -A
NAMESPACE     NAME                                         READY   STATUS    RESTARTS   AGE
kube-system   metrics-server-8bbfb4bdb-4kwj6               1/1     Running   50         225d
kube-system   dashboard-metrics-scraper-6c4568dc68-xhgvb   1/1     Running   49         225d
kube-system   kubernetes-dashboard-7ffd448895-6zgt4        1/1     Running   50         225d
kube-system   coredns-86f78bb79c-qdk64                     1/1     Running   9          15d
kube-system   calico-kube-controllers-847c8c99d-ws2c2      1/1     Running   50         232d
kube-system   calico-node-6gcrg                            1/1     Running   50         232d
ingress       nginx-ingress-microk8s-controller-66rth      1/1     Running   3          6d8h

nginx-ingress-controllerはOSSのnginxを利用したロードバランシングと、cookieベースのsession追跡を実現してくれます。
まずはsticky session無しでingress-controllerを動かしてみます。
ingress-flaskhello.yamlというファイル名で定義ファイルを作成します。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
        name: flask-hello-ingress
        annotations:
                nginx.ingress.kubernetes.io/rewrite-target: /
spec:
        rules:
        - http:
                  paths:
                  - path: /flask-hello
                    pathType: Prefix
                    backend:
                            service:
                                    name: flask-hello
                                    port:
                                            number: 5000

この定義はノードのPort 80にパス/flask-hello(今回の実験に使っているノードは192.168.11.252なので192.168.11.252/flask-hello)へのHTTPアクセスをflask-hello serviceのPort 5000に転送します。
flask-helloの定義はsvc-flaskhello.yaml(ClusterIPモードでflask-hello serviceを定義)を利用し、下記の通りingress-controllerと合わせて起動します。

$ sudo microk8s kubectl create -f svc-flaskhello.yaml
service/flask-hello created
deployment.apps/flask-hello-deploy created
$ sudo microk8s kubectl create -f ingress-flaskhello.yaml 
ingress.networking.k8s.io/flask-hello-ingress created
$ sudo microk8s kubectl get ing,svc,pod --output=wide
NAME                                            CLASS    HOSTS   ADDRESS     PORTS   AGE
ingress.networking.k8s.io/flask-hello-ingress   public   *       127.0.0.1   80      82s

NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE    SELECTOR
service/kubernetes    ClusterIP   10.152.183.1    <none>        443/TCP    232d   <none>
service/flask-hello   ClusterIP   10.152.183.56   <none>        5000/TCP   100s   app=flask-hello

NAME                                     READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
pod/flask-hello-deploy-5465d8d8b-xtrdb   1/1     Running   0          99s   10.1.3.231   ubuntu01   <none>           <none>
pod/flask-hello-deploy-5465d8d8b-kzvkx   1/1     Running   0          99s   10.1.3.232   ubuntu01   <none>           <none>

kubectlコマンドでget ingを実行すると起動したingress controllerの情報が取得できます。
ADDRESS 127.0.0.1 PORT 80なので、ノードのPort 80を開いている事が判ります。
ここにアクセスしてみます。
curlではなく、別マシンからchromeで192.168.11.252/flask-helloにアクセスしてみます。

Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-xtrdb,My IP=10.1.3.231
Client IP=10.1.3.251
**Request Headers**
Host:192.168.11.252
X-Request-Id:9dfe88e60a829a2cf43ff4255f3be6f7
X-Real-Ip:192.168.11.113
X-Forwarded-For:192.168.11.113
X-Forwarded-Host:192.168.11.252
X-Forwarded-Port:80
X-Forwarded-Proto:http
X-Forwarded-Scheme:http
X-Scheme:http
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding:gzip, deflate Accept-Language:ja,en-US;q=0.9,en;q=0.8

Client IPは10.1.3.251になっています。これはingress controllerを動作させているpodのCluster IPです。
HTTPヘッダを見るとX-Real-Ip:とX-Forwarded-For:に192.168.11.113というIPが記載されており。これがchromeを動かしたマシンのIPでクライアントマシンのIPアドレスがHTTPヘッダから取得可能になっています。

$ sudo microk8s kubectl get pod --namespace=ingress --output=wide
NAME                                      READY   STATUS    RESTARTS   AGE    IP           NODE       NOMINATED NODE   READINESS GATES
nginx-ingress-microk8s-controller-66rth   1/1     Running   3          6d8h   10.1.3.251   ubuntu01   <none>           <none>

Ingress-Controllerを使う(sticky session有り)


上記のIngress-Controllerの設定ではクライアントからのアクセスはランダムにpodに振られています。
Ingress-Controllerでsession cookieを発行し、クライアントから送信させる事で振り先のpodを固定することが出来ます。
この方法でクライアントIPが見えなくても問題はなく、また同じクライアントの別ブラウザを見分ける事も可能になるはずです。

Ingress-Controllerの定義に下記の様にannotationを追加します。
これで初回アクセス時にk8s-ssという名称のcookieがクライアントにSet-Cookie:ヘッダで返却されます。

sticky session用ingress controller定義: ingress-flaskhello-ss.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
        name: flask-hello-ingress
        annotations:
                nginx.ingress.kubernetes.io/rewrite-target: /
                nginx.ingress.kubernetes.io/affinity: "cookie"
                nginx.ingress.kubernetes.io/session-cookie-name: "k8s-ss"
                nginx.ingress.kubernetes.io/session-cookie-hash: "sha1"

spec:
        rules:
        - http:
                  paths:
                  - path: /flask-hello
                    pathType: Prefix
                    backend:
                            service:
                                    name: flask-hello
                                    port:
                                            number: 5000

ingress controllerの設定を変更します。

$ sudo microk8s kubectl apply -f ingress-flaskhello-ss.yaml
Warning: resource ingresses/flask-hello-ingress is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
ingress.networking.k8s.io/flask-hello-ingress configured

curlを使い、cookieの受信と送信を行いつつ、アクセスしてみます。
curl実行(1回目): -c flask-cookie.datで受信したcookieを保存

$ curl -v -c flask-cookie.dat http://192.168.11.252/flask-hello
*   Trying 192.168.11.252...
* TCP_NODELAY set
* Connected to 192.168.11.252 (192.168.11.252) port 80 (#0)
> GET /flask-hello HTTP/1.1
> Host: 192.168.11.252
> User-Agent: curl/7.61.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Sun, 09 Jan 2022 14:36:35 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 388
< Connection: keep-alive
* Added cookie k8s-ss="1641738996.024.65.34468|842fe5bed140bc7b70ed2ca414fede98" for domain 192.168.11.252, path /flask-hello, expire 0
< Set-Cookie: k8s-ss=1641738996.024.65.34468|842fe5bed140bc7b70ed2ca414fede98; Path=/flask-hello; HttpOnly
< 
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-kzvkx,My IP=10.1.3.232
Client IP=10.1.3.251
**Request Headers**
Host:192.168.11.252
X-Request-Id:da6f9e972b2607fb4514836f536c0ab7
X-Real-Ip:192.168.11.252
X-Forwarded-For:192.168.11.252
X-Forwarded-Host:192.168.11.252
X-Forwarded-Port:80
X-Forwarded-Proto:http
X-Forwarded-Scheme:http
X-Scheme:http
User-Agent:curl/7.61.0
Accept:*/*
* Connection #0 to host 192.168.11.252 left intact

curl実行(2回目以降): -b flask-cookie.datで1回目に受信したcookieを送信

$ curl -v -b flask-cookie.dat http://192.168.11.252/flask-hello
*   Trying 192.168.11.252...
* TCP_NODELAY set
* Connected to 192.168.11.252 (192.168.11.252) port 80 (#0)
> GET /flask-hello HTTP/1.1
> Host: 192.168.11.252
> User-Agent: curl/7.61.0
> Accept: */*
> Cookie: k8s-ss=1641738996.024.65.34468|842fe5bed140bc7b70ed2ca414fede98
> 
< HTTP/1.1 200 OK
< Date: Sun, 09 Jan 2022 14:38:55 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 459
< Connection: keep-alive
< 
Hello World!!
My Hostname=flask-hello-deploy-5465d8d8b-kzvkx,My IP=10.1.3.232
Client IP=10.1.3.251
**Request Headers**
Host:192.168.11.252
X-Request-Id:a4945e9f7ba3ddf6342ad0f6a9e0d0bb
X-Real-Ip:192.168.11.252
X-Forwarded-For:192.168.11.252
X-Forwarded-Host:192.168.11.252
X-Forwarded-Port:80
X-Forwarded-Proto:http
X-Forwarded-Scheme:http
X-Scheme:http
User-Agent:curl/7.61.0
Accept:*/*
Cookie:k8s-ss=1641738996.024.65.34468|842fe5bed140bc7b70ed2ca414fede98
* Connection #0 to host 192.168.11.252 left intact

10回程度繰り返し、flask-helloが返すMy IPが10.1.3.232で変らない事を確認できました。

ソース、定義ファイル等

このエントリーで使用したテストアプリのソース、各種定義ファイル類はgithubに置いておきます。

github.com