KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA

04 · 让外面访问到它 — keel 龙骨

上一章结束时你把东西撤干净了。先把第 02 章那份 web.yaml 再交一次:

上一章结束时你把东西撤干净了。先把第 02 章那份 web.yaml 再交一次:

kubectl apply -f web.yaml

三章下来,它能在集群里自己活着、坏了会自己补。但你在自己电脑上打开浏览器,什么都看不到。
这一章解决这件事。

一、先试试直接用它自己的地址

kubectl get pods -o wide
NAME                  READY   STATUS    RESTARTS   AGE   IP           NODE
web-565bc6668-c9g8d   1/1     Running   0          2m   10.244.0.8   keel-lab-control-plane
web-565bc6668-wkm7t   1/1     Running   0          3m   10.244.0.7   keel-lab-control-plane

IP 那一列就是容器的地址。直接 curl 它试试:

curl http://10.244.0.8

(地址换成你屏幕上的)

等它在原地转圈,最后超时。 这不是你配错了——这些地址在集群自己的内部网络里,
你电脑上的路由表不认识它们。这是它的设计,不是故障。

另一个想法是"把这两个地址填进 nginx 配置",看上去更有道理,其实才是问题所在。
回到第 03 章:你删掉过一个 Pod,回来的那个是新名字——地址也换了:

被删掉的那个   web-565bc6668-t8bp4   10.244.0.6
回来的那个     web-565bc6668-c9g8d   10.244.0.8

Pod 的地址是一次性的,随它一起生、一起灭——写不进任何配置。既然地址会变,
就给它们一个不变的入口。

二、Service:一个不变的地址 + 一份成员名单

再写一份文件,叫 web-service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 80

只有两处是新的:selector 说哪些 Pod 收我的流量(跟 web.yaml 里的标签对上,所以选的
是那两个);ports 说对外端口 / 转发到容器里的哪个端口。交上去:

kubectl apply -f web-service.yaml
service/web created
kubectl get svc

(这一屏会多一行 kubernetes,那是集群自己用的,忽略它)

NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP   5m11s
web          ClusterIP   10.96.94.104   <none>        80/TCP    1s

CLUSTER-IP 那一列就是"不变的地址":10.96.94.104。它不随 Pod 的生灭而变。
再看一条命令,它把这个 Service 现在的成员列出来:

kubectl get endpoints web
NAME   ENDPOINTS                     AGE
web    10.244.0.7:80,10.244.0.8:80   2s

那两个地址就是刚才 get pods -o wide 里的那两个——不是巧合:Service 做的就是"盯着符合
selector 的 Pod,把它们的地址维护成这份名单"。Pod 换了名单跟着换,而 CLUSTER-IP 不动
——这就是你要的固定入口。

Warning: v1 Endpoints is deprecated in v1.33+; use discovery.k8s.io/v1 EndpointSlice?
这是提醒不是报错:返回类型在新版本里换了名字,结果照给。

三、真的打开它看一眼

浏览器看不到集群内部地址,但 kubectl 可以在你和集群之间架一条临时的线:

kubectl port-forward svc/web 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80

读法和上一门课的 -p 一样:左边是你电脑上的 8080,右边是转发到 Service 的 80。
这一行会一直占着你的终端(它得活着,那条线才在)。

另开一个终端,敲 curl http://localhost:8080,或者浏览器打开 http://localhost:8080:

HTTP/1.1 200 OK
Server: nginx/1.27.5
Content-Type: text/html

<!DOCTYPE html>
<html>
...

这一页是从集群里那两个 Pod 之一出来的。 看完回 port-forward 那个终端按 Ctrl+C,
那条线就断了——它是临时的,真正的对外暴露是另一件事(本课不展开)。

四、它不是什么

这几句报错在哪一步

报错 / 输出(结尾部分) 它在说什么
service/web created 之后 get svc 里没有 web 多半交错了文件。先 kubectl get svc -A 找一遍
curl: (28) Connection timed out 打 Pod 的 IP 正常。Pod 地址在集群内部网络里,你电脑不通
port-forward 报 error: lost connection to pod 那条线断了。Ctrl+C 重敲一次,它本来就是临时的
unable to listen on any of the requested ports: [{8080 8080}] 你电脑上的 8080 被占了。只改冒号左边,比如 8081:80

读完你能做什么

下一步:最后一章收口到一个更重要的问题:这套东西,你该不该用。

进入 keel 阅读