
Windows 11 Pro マシン上の Docker Desktop + WSL2 環境にある Kubernetes クラスターに認証サービスをセットアップしました。
たとえば、同じ Windows マシン (WSL2 レイヤーの外部) から CURL および PostMan リクエストを介してアクセスできます。
しかし、ここで問題となるのは、同じ LAN ネットワーク内の Linux マシンから REST エンドポイントにアクセスできないことです。
その認証サービスへの接続が実際に機能することを確認するために、タイプ「NodePort」のサービスをセットアップしました。「kubectl get svc」から取得した外部ポートを使用すると、Windows マシンと Linux マシンの両方から curl 要求が正常に機能し、サービスは適切な応答で応答します。
ただし、NodePort サービスは偽の証明書が付属する K8s イングレスの TSL/SSL を完全に回避するため、リクエストは成功しても HTTP 経由のリクエストに対してのみ機能することに注意してください。
認証サービスからの応答で Cookie を操作する必要があるため、HTTPS 経由のリクエストが重要ですが、K8s Ingress は応答をまったく送信しません。
Windows マシンでは、関連するポート 80、443 (念のため 22 も) を開き、Windows ファイアウォールの接続ルールで Linux マシンを信頼できるコンピューターに追加しました。また、実際に接続試行をブロックしているかどうかを確認するために、一時的に無効にしてみました。しかし、それでも、リクエストは黙ってドロップされます (おそらく Ingress による)。
しかし、仮定に入る前に、マシン間の POST リクエストと関連するすべての K8s yaml ファイルを含む LAN の概要を示したいと思います。
認証デプロイメントとサービスは次のように定義されます。
apiVersion: apps/v1
kind: Deployment
metadata:
name: gts-auth-depl
spec:
replicas: 1
selector:
matchLabels:
app: gts-auth
template:
metadata:
labels:
app: gts-auth
spec:
containers:
- name: gts-auth
image: creativewarlock/gts-auth
imagePullPolicy: IfNotPresent
env:
- name: MONGO_URI
value: 'mongodb://gts-auth-mongo-srv:27017/auth'
- name: JWT_KEY
valueFrom:
secretKeyRef:
name: gts-jwt-secret
key: JWT_KEY
imagePullSecrets:
- name: docker-hub
---
apiVersion: v1
kind: Service
metadata:
name: gts-auth-srv
spec:
type: ClusterIP
selector:
app: gts-auth
ports:
- name: gts-auth
protocol: TCP
port: 3000
targetPort: 3000
認証と Web クライアントのイングレス (関連はありませんが、表示のみです):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gts-ingress-srv
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: 'true'
spec:
rules:
- host: gts.dev # Entry in System32/etc/hosts: 127.0.0.1 gts.dev (alternatively: localhost)
http:
paths:
- path: /api/users/?(.*) # will match /api/users/signin
pathType: Prefix
backend:
service:
name: gts-auth-srv
port:
number: 3000
- path: /?(.*) # map all other requests to web client
pathType: Prefix
backend:
service:
name: gts-client-srv
port:
number: 8080
認証サービスへの外部/直接アクセス用の NodePort サービス:
apiVersion: v1
kind: Service
metadata:
name: gts-auth-srv-ext
spec:
type: NodePort
selector:
app: gts-auth
ports:
- name: gts-auth-srv
protocol: TCP
port: 3000
targetPort: 3000
Kubernetes では Ingress を次のように説明しています。
k describe pod ingress-nginx-controller-6bf7bc7f94-krv2c -n ingress
-nginx
Name: ingress-nginx-controller-6bf7bc7f94-krv2c
Namespace: ingress-nginx
Priority: 0
Node: docker-desktop/192.168.65.4
Start Time: Thu, 11 Aug 2022 12:31:42 +0200
Labels: app.kubernetes.io/component=controller
app.kubernetes.io/instance=ingress-nginx
app.kubernetes.io/name=ingress-nginx
pod-template-hash=6bf7bc7f94
Annotations: <none>
Status: Running
IP: 10.1.28.235
IPs:
IP: 10.1.28.235
Controlled By: ReplicaSet/ingress-nginx-controller-6bf7bc7f94
Containers:
controller:
Container ID: docker://0cef9bec68d309011a32e18bf4f3a2a7ec7050b3db6cc7bafd87565e370f6695
Image: registry.k8s.io/ingress-nginx/controller:v1.3.0@sha256:d1707ca76d3b044ab8a28277a2466a02100ee9f58a86af1535a3edf9323ea1b5
Image ID: docker-pullable://registry.k8s.io/ingress-nginx/controller@sha256:d1707ca76d3b044ab8a28277a2466a02100ee9f58a86af1535a3edf9323ea1b5
Ports: 80/TCP, 443/TCP, 8443/TCP
Host Ports: 0/TCP, 0/TCP, 0/TCP
Args:
/nginx-ingress-controller
--publish-service=$(POD_NAMESPACE)/ingress-nginx-controller
--election-id=ingress-controller-leader
--controller-class=k8s.io/ingress-nginx
--ingress-class=nginx
--configmap=$(POD_NAMESPACE)/ingress-nginx-controller
--validating-webhook=:8443
--validating-webhook-certificate=/usr/local/certificates/cert
--validating-webhook-key=/usr/local/certificates/key
State: Running
Started: Sun, 19 Feb 2023 11:50:07 +0100
Last State: Terminated
Reason: Error
Exit Code: 255
Started: Sat, 18 Feb 2023 11:44:18 +0100
Finished: Sun, 19 Feb 2023 11:49:36 +0100
Ready: True
Restart Count: 132
Requests:
cpu: 100m
memory: 90Mi
Liveness: http-get http://:10254/healthz delay=10s timeout=1s period=10s #success=1 #failure=5
Readiness: http-get http://:10254/healthz delay=10s timeout=1s period=10s #success=1 #failure=3
Environment:
POD_NAME: ingress-nginx-controller-6bf7bc7f94-krv2c (v1:metadata.name)
POD_NAMESPACE: ingress-nginx (v1:metadata.namespace)
LD_PRELOAD: /usr/local/lib/libmimalloc.so
Mounts:
/usr/local/certificates/ from webhook-cert (ro)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-hpxhw (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
webhook-cert:
Type: Secret (a volume populated by a Secret)
SecretName: ingress-nginx-admission
Optional: false
kube-api-access-hpxhw:
ConfigMapOptional: <nil> DownwardAPI: true
QoS Class: Burstable
Node-Selectors: kubernetes.io/os=linux
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal RELOAD 54m (x3 over 95m) nginx-ingress-controller NGINX reload triggered due to a change in configuration
以下は Ingress コントローラーのログです。最後の行は、Windows マシンからの curl 要求に対する応答を示しています。
k logs -f ingress-nginx-controller-6bf7bc7f94-krv2c -n ingress-nginx
W0219 10:50:08.009613 7 client_config.go:617] Neither --kubeconfig nor --master was specified. Using the inClusterConfig. This might not work.
I0219 10:50:08.010796 7 main.go:230] "Creating API client" host="https://10.96.0.1:443"
W0219 10:50:30.162337 7 main.go:271] Initial connection to the Kubernetes API server was retried 1 times.
I0219 10:50:30.162386 7 main.go:274] "Running in Kubernetes cluster" major="1" minor="24" git="v1.24.1" state="clean" commit="3ddd0f45aa91e2f30c70734b175631bec5b5825a" platform="linux/amd64"
I0219 10:50:30.278395 7 main.go:104] "SSL fake certificate created" file="/etc/ingress-controller/ssl/default-fake-certificate.pem"
I0219 10:50:30.299891 7 ssl.go:531] "loading tls certificate" path="/usr/local/certificates/cert" key="/usr/local/certificates/key"
I0219 10:50:30.314983 7 nginx.go:258] "Starting NGINX Ingress controller"
I0219 10:50:30.321843 7 event.go:285] Event(v1.ObjectReference{Kind:"ConfigMap", Namespace:"ingress-nginx", Name:"ingress-nginx-controller", UID:"407f816e-98b9-4ab6-a08f-95efafa21ddc", APIVersion:"v1", ResourceVersion:"612", FieldPath:""}): type: 'Normal' reason: 'CREATE' ConfigMap ingress-nginx/ingress-nginx-controller
I0219 10:50:31.516611 7 nginx.go:301] "Starting NGINX process"
I0219 10:50:31.516698 7 leaderelection.go:248] attempting to acquire leader lease ingress-nginx/ingress-controller-leader...
I0219 10:50:31.517522 7 nginx.go:321] "Starting validation webhook" address=":8443" certPath="/usr/local/certificates/cert" keyPath="/usr/local/certificates/key"
I0219 10:50:31.517893 7 controller.go:167] "Configuration changes detected, backend reload required"
I0219 10:50:31.543621 7 leaderelection.go:258] successfully acquired lease ingress-nginx/ingress-controller-leader
I0219 10:50:31.543648 7 status.go:84] "New leader elected" identity="ingress-nginx-controller-6bf7bc7f94-krv2c"
I0219 10:50:31.610775 7 controller.go:184] "Backend successfully reloaded"
I0219 10:50:31.610910 7 controller.go:195] "Initial sync, sleeping for 1 second"
192.168.65.4 - - [19/Feb/2023:13:09:46 +0000] "POST /api/users/signin/ HTTP/1.1" 200 150 "-" "curl/7.83.1" 259 0.054 [default-gts-auth-srv-3000] [] 10.1.28.246:3000 150 0.050 200 5b8761d90f76b4c160b0a2effc980b85
私の Linux マシン「Kaspar」からの curl HTTPS リクエストは Ingress ポッドに記録されず、送信者は NGINX から 404 HTML ドキュメントを受信します。
Blacky@Kaspar:~$ curl -k -H 'Content-Type: application/json' https://192.168.0.57/api/users/signin/ -X POST -d '{ "email": "[email protected]", "password": "iHhRCF9Dm3wKT" }'
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
Windows ファイアウォールでは、信頼できるコンピューターに Linux マシンを追加し、PowerShell スクリプトを使用してこれらのルールを明示的に設定しました。
$wsl_ip = (ubuntu.exe -c "ifconfig eth0 | grep 'inet '").trim().split()| where {$_}
$regex = [regex] "\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b"
$ip_array = $regex.Matches($wsl_ip) | %{ $_.value }
$wsl_ip = $ip_array[0]
Write-Host "WSL Machine IP: ""$wsl_ip"""
New-NetFireWallRule -DisplayName 'WSL SSL' -Direction Outbound -LocalPort 443 -Action Allow -Protocol TCP
New-NetFireWallRule -DisplayName 'WSL SSL' -Direction Inbound -LocalPort 443 -Action Allow -Protocol TCP
#### ------------ Clear all portproxy rules ------------ ####
netsh int portproxy reset all
#### ------------ SSH rule - port 22 ------------ ####
netsh interface portproxy add v4tov4 listenport=22 listenaddress=0.0.0.0 connectport=22 connectaddress=$wsl_ip
#### ------------ Webserver SSL rule - port 443 ------------ ####
netsh interface portproxy add v4tov4 listenport=443 listenaddress=0.0.0.0 connectport=443 connectaddress=$wsl_ip
#### ------------ Webserver SSL rule - port 80 ------------ ####
netsh interface portproxy add v4tov4 listenport=80 listenaddress=0.0.0.0 connectport=80 connectaddress=$wsl_ip
私の主な質問は次のとおりです。
Kubernetes 内の (自己署名の) 偽の証明書が問題の原因でしょうか? LAN 内での使用には適切な letsEncrypt 証明書を使用する必要がありますか?
curl/postman リクエストは Windows マシン (WSL2 レイヤーの外側) から機能するため、まず Windows ファイアウォールの構成の問題だと考えましたが、リクエストは K8s Ingress によって適切に応答されていないようです。ただし、Ingress 内で何が起こっているかを分析するためのツールがありません。'kubectl logs -f <ingress...> -n ingress-nginx' 以外に手段はありますか?
LAN 内の別のマシンから HTTPS リクエストを機能させる方法についての提案があれば、ぜひお聞かせください。