{"id":7711,"date":"2026-08-21T13:57:30","date_gmt":"2026-08-21T05:57:30","guid":{"rendered":"https:\/\/i007.cc\/wordpress\/?p=7711"},"modified":"2026-08-21T14:01:58","modified_gmt":"2026-08-21T06:01:58","slug":"k8s%e6%95%b4%e6%9d%a1%e9%93%be%e8%b7%af","status":"publish","type":"post","link":"https:\/\/i007.cc\/wordpress\/archives\/7711","title":{"rendered":"k8s\u6574\u6761\u94fe\u8def"},"content":{"rendered":"<p>\u6574\u6761\u94fe\u8def\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">curl http:\/\/10.0.0.8\r\n  \u2192 \u672c\u5730 nginx (Host: fleet.local)\r\n    \u2192 172.18.0.2:32305 (Kind node NodePort)\r\n      \u2192 ingress-nginx controller pod\r\n        \u2192 \u5339\u914d Ingress \u89c4\u5219 (fleet.local \u2192 fleet-api Service)\r\n          \u2192 fleet-api Service (\u8d1f\u8f7d\u5747\u8861)\r\n            \u2192 fleet-api pod (\u4efb\u610f\u4e00\u4e2a\u526f\u672c)<\/pre>\n<p>&nbsp;<\/p>\n<p>Nginx\u628aLoadBalancer\u8f6c\u53d1\u523010.0.0.0\/24\u7f51\u6bb5<\/p>\n<p>vim \/etc\/nginx\/sites-available\/fleet.local<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">server {\r\n    listen 80;\r\n    server_name localhost;\r\n\r\n    location \/ {\r\n        proxy_pass http:\/\/172.18.0.2:32305;\r\n        proxy_set_header Host fleet.local;\r\n        proxy_set_header X-Real-IP $remote_addr;\r\n    }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>\u67e5\u770bKind\u914d\u7f6e\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">(.venv)  will@ubuntu24 \ue0b0 ~\/fleet-api\/app \ue0b0 \ue0a0 master \u00b1 \ue0b0 k get nodes -A\r\nNAME                 STATUS   ROLES           AGE   VERSION\r\nkind-control-plane   Ready    control-plane   46h   v1.36.1\r\n(.venv)  will@ubuntu24 \ue0b0 ~\/fleet-api\/app \ue0b0 \ue0a0 master \u00b1 \ue0b0 kubectl get nodes -o wide\r\nNAME                 STATUS   ROLES           AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                       KERNEL-VERSION              CONTAINER-RUNTIME\r\nkind-control-plane   Ready    control-plane   46h   v1.36.1   172.18.0.2    &lt;none&gt;        Debian GNU\/Linux 13 (trixie)   6.8.0-134-generic (amd64)   containerd:\/\/2.3.1\r\n(.venv)  will@ubuntu24 \ue0b0 ~\/fleet-api\/app \ue0b0 \ue0a0 master \u00b1 \ue0b0<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>\u67e5\u770bingress\u914d\u7f6e\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">(.venv)  \u2718 will@ubuntu24 \ue0b0 ~ \ue0b0 k describe service\/ingress-nginx-controller -n ingress-nginx\r\nName:                     ingress-nginx-controller\r\nNamespace:                ingress-nginx\r\nLabels:                   app.kubernetes.io\/component=controller\r\n                          app.kubernetes.io\/instance=ingress-nginx\r\n                          app.kubernetes.io\/name=ingress-nginx\r\n                          app.kubernetes.io\/part-of=ingress-nginx\r\n                          app.kubernetes.io\/version=1.15.1\r\nAnnotations:              &lt;none&gt;\r\nSelector:                 app.kubernetes.io\/component=controller,app.kubernetes.io\/instance=ingress-nginx,app.kubernetes.io\/name=ingress-nginx\r\nType:                     LoadBalancer\r\nIP Family Policy:         SingleStack\r\nIP Families:              IPv4\r\nIP:                       10.96.209.119\r\nIPs:                      10.96.209.119\r\nPort:                     http  80\/TCP\r\nTargetPort:               http\/TCP\r\nAppProtocol:              http\r\nNodePort:                 http  32305\/TCP\r\nEndpoints:                10.244.0.28:80\r\nPort:                     https  443\/TCP\r\nTargetPort:               https\/TCP\r\nAppProtocol:              https\r\nNodePort:                 https  32608\/TCP\r\nEndpoints:                10.244.0.28:443\r\nSession Affinity:         None\r\nExternal Traffic Policy:  Cluster\r\nInternal Traffic Policy:  Cluster\r\nEvents:                   &lt;none&gt;\r\n(.venv)  will@ubuntu24 \ue0b0 ~ \ue0b0<\/pre>\n<p>ingress\u5bf9\u5916\u66b4\u9732\u7684IP\u662f10.244.0.28\uff0c\u7aef\u53e3\u53f7\u662f32305\uff0c\u5bf9\u5185\u662f80\u7aef\u53e3<\/p>\n<p>ingress-nginx-controller\u662f\u4e00\u4e2aLoadBalancer\uff0c\u628a\u5185\u90e8\u7684ingress 80\u7aef\u53e3\u8f6c\u53d1\u7ed932305<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">(.venv)  will@ubuntu24 \ue0b0 ~ \ue0b0 k get services -A\r\nNAMESPACE           NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE\r\ncrossplane-system   crossplane-apollo-metrics            ClusterIP      10.96.238.61    &lt;none&gt;        8085\/TCP                     45h\r\ncrossplane-system   crossplane-webhooks                  ClusterIP      10.96.115.220   &lt;none&gt;        9443\/TCP                     45h\r\ncrossplane-system   provider-azure-management            ClusterIP      10.96.122.90    &lt;none&gt;        9443\/TCP                     45h\r\ncrossplane-system   spaces-apollo                        ClusterIP      10.96.122.242   &lt;none&gt;        8080\/TCP                     45h\r\ncrossplane-system   upbound-controller-manager           ClusterIP      10.96.6.7       &lt;none&gt;        8082\/TCP                     45h\r\ncrossplane-system   upbound-provider-family-azure        ClusterIP      10.96.33.199    &lt;none&gt;        9443\/TCP                     45h\r\ncrossplane-system   webui                                ClusterIP      10.96.80.132    &lt;none&gt;        80\/TCP                       45h\r\ndefault             kubernetes                           ClusterIP      10.96.0.1       &lt;none&gt;        443\/TCP                      45h\r\nfleet               fleet-api                            ClusterIP      10.96.174.44    &lt;none&gt;        80\/TCP                       11h\r\ningress-nginx       ingress-nginx-controller             LoadBalancer   10.96.209.119   &lt;pending&gt;     80:32305\/TCP,443:32608\/TCP   10h\r\ningress-nginx       ingress-nginx-controller-admission   ClusterIP      10.96.199.180   &lt;none&gt;        443\/TCP                      10h\r\nkube-system         kube-dns                             ClusterIP      10.96.0.10      &lt;none&gt;        53\/UDP,53\/TCP,9153\/TCP       45h\r\n(.venv)  will@ubuntu24 \ue0b0 ~ \ue0b0<\/pre>\n<p>&nbsp;<\/p>\n<p>\u5bf9\u5185\u768480\u4f1a\u6620\u5c04\u5230backends\u4e2d\u7684\u67d0\u4e00\u4e2a8080\u7aef\u53e3<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">(.venv)  will@ubuntu24 \ue0b0 ~ \ue0b0 k describe ingress -n fleet\r\nName:             fleet-ingress\r\nLabels:           &lt;none&gt;\r\nNamespace:        fleet\r\nAddress:          localhost\r\nIngress Class:    nginx\r\nDefault backend:  &lt;default&gt;\r\nRules:\r\n  Host         Path  Backends\r\n  ----         ----  --------\r\n  fleet.local  \r\n               \/   fleet-api:80 (10.244.0.2:8080,10.244.0.5:8080)\r\nAnnotations:   &lt;none&gt;\r\nEvents:        &lt;none&gt;\r\n(.venv)  will@ubuntu24 \ue0b0 ~ \ue0b0<\/pre>\n<p>&nbsp;<\/p>\n<p>\u5230\u4e86pods\u5185\u90e8\uff0c8080\u7aef\u53e3\u7531container serve<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">(.venv)  \u2718 will@ubuntu24 \ue0b0 ~ \ue0b0 k describe pod\/fleet-api-6958d5465d-655t5 -n fleet\r\nName:             fleet-api-6958d5465d-655t5\r\nNamespace:        fleet\r\nPriority:         0\r\nService Account:  default\r\nNode:             kind-control-plane\/172.18.0.2\r\nStart Time:       Fri, 21 Aug 2026 02:40:59 +0800\r\nLabels:           app=fleet-api\r\n                  pod-template-hash=6958d5465d\r\nAnnotations:      &lt;none&gt;\r\nStatus:           Running\r\nIP:               10.244.0.5\r\nIPs:\r\n  IP:           10.244.0.5\r\nControlled By:  ReplicaSet\/fleet-api-6958d5465d\r\nContainers:\r\n  fleet-api:\r\n    Container ID:   containerd:\/\/df208381beca730d792566791c1b786550a65ccb1a5dac2d7ef5deb5e35a0bb2\r\n    Image:          fleet-api:v1\r\n    Image ID:       docker.io\/library\/import-2026-08-20@sha256:8488112d8e902c9303747cb64cf0eae5a155747bb8062465f11a5b0a2d599de3\r\n    Port:           8080\/TCP\r\n    Host Port:      0\/TCP\r\n    State:          Running\r\n      Started:      Fri, 21 Aug 2026 03:06:43 +0800\r\n    Last State:     Terminated\r\n      Reason:       Unknown\r\n      Exit Code:    255\r\n      Started:      Fri, 21 Aug 2026 02:41:00 +0800\r\n      Finished:     Fri, 21 Aug 2026 03:06:34 +0800\r\n    Ready:          True\r\n    Restart Count:  1\r\n    Limits:\r\n      cpu:     200m\r\n      memory:  128Mi\r\n    Requests:\r\n      cpu:      100m\r\n      memory:   64Mi\r\n    Liveness:   http-get http:\/\/:8080\/health delay=30s timeout=1s period=10s #success=1 #failure=3\r\n    Readiness:  http-get http:\/\/:8080\/health delay=10s timeout=1s period=5s #success=1 #failure=3\r\n    Environment Variables from:\r\n      fleet-config  ConfigMap  Optional: false\r\n    Environment:    &lt;none&gt;\r\n    Mounts:\r\n      \/var\/run\/secrets\/kubernetes.io\/serviceaccount from kube-api-access-52mp9 (ro)\r\nConditions:\r\n  Type                        Status\r\n  PodReadyToStartContainers   True \r\n  Initialized                 True \r\n  Ready                       True \r\n  ContainersReady             True \r\n  PodScheduled                True \r\nVolumes:\r\n  kube-api-access-52mp9:\r\n    Type:                    Projected (a volume that contains injected data from multiple sources)\r\n    TokenExpirationSeconds:  3607\r\n    ConfigMapName:           kube-root-ca.crt\r\n    Optional:                false\r\n    DownwardAPI:             true\r\nQoS Class:                   Burstable\r\nNode-Selectors:              &lt;none&gt;\r\nTolerations:                 node.kubernetes.io\/not-ready:NoExecute op=Exists for 300s\r\n                             node.kubernetes.io\/unreachable:NoExecute op=Exists for 300s\r\nEvents:                      &lt;none&gt;\r\n(.venv)  will@ubuntu24 \ue0b0 ~ \ue0b0<\/pre>\n<p>&nbsp;<\/p>\n<p>8080\u7aef\u53e3\u7531\u8fd9\u4e2apy\u6587\u4ef6serve<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">FROM python:3.11-slim\r\n\r\nARG VERSION=unknown\r\nENV VERSION=${VERSION}\r\n\r\nWORKDIR \/app\r\n\r\nCOPY requirements.txt .\r\nRUN pip install --no-cache-dir -r requirements.txt\r\n\r\nCOPY main.py .\r\nRUN useradd --create-home appuser &amp;&amp; chown -R appuser \/app\r\nUSER appuser\r\n\r\nEXPOSE 8080\r\nENV PYTHONUNBUFFERED=1\r\n\r\nCMD [\"uvicorn\", \"main:app\", \"--host\", \"0.0.0.0\", \"--port\", \"8080\"]<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>Python\u6587\u4ef6\u5185\u5bb9\uff1a<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">import os\r\nimport subprocess\r\nfrom typing import List\r\n\r\nfrom fastapi import FastAPI, HTTPException, Query\r\nfrom pydantic import BaseModel\r\n\r\n\r\ndef get_git_version() -&gt; str:\r\n    version = os.getenv(\"VERSION\")\r\n    if version:\r\n        return version\r\n    try:\r\n        repo_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), \"..\"))\r\n        return subprocess.check_output(\r\n            [\"git\", \"rev-parse\", \"--short\", \"HEAD\"], cwd=repo_dir, text=True\r\n        ).strip()\r\n    except Exception:\r\n        return \"unknown\"\r\n\r\n\r\nclass Settings:\r\n    def __init__(self) -&gt; None:\r\n        self.max_vehicles = int(os.getenv(\"MAX_VEHICLES\", \"100\"))\r\n        self.version = os.getenv(\"VERSION\", \"unknown\")\r\n\r\n\r\nclass Vehicle(BaseModel):\r\n    id: str\r\n    battery: int\r\n    online: bool\r\n\r\n\r\nclass HealthResponse(BaseModel):\r\n    status: str\r\n    service: str\r\n    version: str\r\n\r\n\r\nsettings = Settings()\r\nif settings.version == \"unknown\":\r\n    settings.version = get_git_version()\r\n\r\napp = FastAPI(title=\"fleet-api\", version=settings.version)\r\n\r\n\r\n@app.get(\"\/health\", response_model=HealthResponse)\r\ndef health() -&gt; HealthResponse:\r\n    return HealthResponse(\r\n        status=\"healthy\", service=\"fleet-api\", version=settings.version\r\n    )\r\n\r\n\r\nVEHICLES: List[Vehicle] = [\r\n    Vehicle(id=\"v001\", battery=85, online=True),\r\n    Vehicle(id=\"v002\", battery=42, online=False),\r\n    Vehicle(id=\"v003\", battery=97, online=True),\r\n]\r\n\r\n\r\n@app.get(\"\/vehicles\/{vid}\", response_model=Vehicle)\r\ndef get_vehicle(vid: str) -&gt; Vehicle:\r\n    for vehicle in VEHICLES:\r\n                                                                                                                                                                                                                       1,1           Top<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u6574\u6761\u94fe\u8def\uff1a curl http:\/\/10<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"colormag_page_container_layout":"default_layout","colormag_page_sidebar_layout":"default_layout","footnotes":""},"categories":[24],"tags":[],"class_list":["post-7711","post","type-post","status-publish","format-standard","hentry","category-value_docs"],"_links":{"self":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts\/7711","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/comments?post=7711"}],"version-history":[{"count":2,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts\/7711\/revisions"}],"predecessor-version":[{"id":7713,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts\/7711\/revisions\/7713"}],"wp:attachment":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/media?parent=7711"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/categories?post=7711"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/tags?post=7711"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}