Доступ к службе K8s в WSL2 + Docker Desktop с компьютера Linux через HTTPS

Я настроил службу аутентификации в кластере Kubernetes, который находится в среде Docker Desktop + WSL2 на компьютере с Windows 11 Pro.

Этого можно достичь, например, с помощью запросов CURL и PostMan с одного и того же компьютера Windows (за пределами этого уровня WSL2).

Однако вот в чем проблема: к этой конечной точке отдыха нельзя получить доступ с машины Linux в той же локальной сети.

Чтобы убедиться, что подключение к этой службе аутентификации действительно работает, я настроил службу с типом «NodePort». При использовании внешнего порта, полученного из «kubectl get svc», запросы на закручивание работают нормально как с компьютера с Windows, так и с Linux, и служба отвечает правильным ответом.

Однако обратите внимание, что служба NodePort полностью обходит TSL/SSL входа K8s, который поставляется с поддельным сертификатом, поэтому запрос - хотя и успешный - работает только для запросов через HTTP.

Поскольку мне нужно работать с файлами cookie в ответе службы аутентификации, запросы через HTTPS имеют решающее значение, однако вход K8s вообще не отправляет ответ.

На машине с Windows я открыл соответствующие порты 80, 443 (и 22 на всякий случай) и добавил машину с Linux к надежным компьютерам в правилах подключения брандмауэра Windows. Я также попытался временно отключить его, чтобы проверить, действительно ли он блокирует попытку подключения. Но тем не менее запрос просто молча отбрасывается (возможно, Ingress).

Но прежде чем вдаваться в какие-либо предположения, позвольте мне показать вам обзор моей локальной сети с запросами POST между машинами, а также все соответствующие файлы yaml K8s:

Развертывание и служба аутентификации определяются следующим образом:

      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

Вход для аутентификации и веб-клиента (хотя это не имеет значения, просто чтобы показать):

      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.

      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

HTTPS-запрос Curl с моей Linux-машины «Kaspar» не регистрируется в модуле Ingress, и отправитель получает HTML-документ 404 от NGINX:

      Blacky@Kaspar:~$ curl -k -H 'Content-Type: application/json' https://192.168.0.57/api/users/signin/ -X POST -d '{ "email": "DummyUser@dummies.com", "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 причиной проблемы? Должен ли я использовать правильный сертификат LetsEncrypt для использования в моей локальной сети?

  • Поскольку запросы Curl/Postman работают с компьютера Windows (вне уровня WSL2), сначала я настраиваю брандмауэр Windows, но, похоже, вход K8s не отвечает на запрос должным образом. Однако мне не хватает инструментов для анализа того, что происходит внутри Ingress. Есть ли какие-либо другие средства, кроме «kubectl logs -f <ingress...> -n ingress-nginx»?

Любые предложения о том, как заставить HTTPS-запрос работать с другого компьютера в моей локальной сети, очень приветствуются.


0 ответов