KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA

02 · 第一个应用 — keel 龙骨

上一章说"你写的是期望状态"。这一章把它写出来、交上去,然后看那句"它还没跑起来"是怎么发生的。

上一章说"你写的是期望状态"。这一章把它写出来、交上去,然后看那句"它还没跑起来"是怎么发生的。

一、写一份"想要什么"的文件

新建一个文件,叫 web.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: nginx:1.27-alpine

yaml 只有一条规则:缩进就是层级——同一层的左边对齐,属于上一层的往右缩两格。
只能用空格,不能用 Tab。

这份文件从头到尾在说一件事,逐段读:

片段 它在说什么
apiVersion / kind / metadata.name: web 交的是哪一种东西(这里叫 Deployment)以及它叫什么——这名字后面一直用来指代它
replicas: 2 我要 2 个副本
selector / template 里的 labels 这两处必须写成一样,不一样连交都交不上去(原文见下)
containers 里的 image 每个副本里跑哪个镜像。就是你上一门课学会的那个

Deployment 本课不展开它和别的对象怎么分工,读成**"份数 + 用什么镜像"的载体**就行。

二、交上去

kubectl apply -f web.yaml

apply 读作"把我这份期望状态交上去"。你会看到:

deployment.apps/web created

created 是"收下了"。紧接着敲这一行——这是本章最重要的一步:

kubectl get pods

你会看到(注意 STATUS 那一列):

NAME                  READY   STATUS              RESTARTS   AGE
web-565bc6668-t8bp4   0/1     ContainerCreating   0          1s
web-565bc6668-wkm7t   0/1     ContainerCreating   0          1s

两行都在,但没有一个在跑:0/1 是"需要的 1 个里起来了 0 个",
ContainerCreating 是"正在把它造出来"。

apply 返回 created 的那一刻和这一屏,是同一秒。 这不是失败,就是它的工作方式:
你说完"我要什么",然后由它自己去达成;达成需要时间。

名字里的 web-565bc6668- 是它自动拼的:前面是你的名字,中间那截是这份配置算出来的编号,
后面那截每次都是新的。第 03 章会用到这一点。

三、等到它真的在跑

再敲一次同一条命令(或者隔十几秒再看):

kubectl get pods
NAME                  READY   STATUS    RESTARTS   AGE
web-565bc6668-t8bp4   1/1     Running   0          11s
web-565bc6668-wkm7t   1/1     Running   0          11s

1/1 + Running,这时候才是真的在跑。另外两条命令值得一起看:

kubectl get deploy web      # 我要的那份期望状态,它认到了多少
kubectl get pods -o wide    # 多两列:Pod 在哪台机器上、地址是多少
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
web    2/2     2            2           55s
NAME                  READY   STATUS    RESTARTS   AGE   IP           NODE
web-565bc6668-t8bp4   1/1     Running   0          36s   10.244.0.6   keel-lab-control-plane
web-565bc6668-wkm7t   1/1     Running   0          57s   10.244.0.7   keel-lab-control-plane

-o wide 加出来的两列后面两章都会用到:NODE 是它落在哪台机器上,IP 是它的地址。

四、看它说了什么

容器里的程序打印的东西,可以用这条命令捞出来:

kubectl logs web-565bc6668-t8bp4

(名字换成你自己 get pods 里的一个)

/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
...

这就是 nginx 的启动日志。和上一门课的 docker logs 是同一份东西——
只是这个容器现在不归 Docker 直接管了。

提交失败的几句话说清楚

上面那份 YAML 少一个空格、错一个字母都交不上去,而且都会非零退出。新手最常撞上的
几句原文一次给全——它们都不是环境坏了,是文件写错了:

报错原文(结尾部分) 它在说什么
error: the path "web.yaml" does not exist 路径不对。先确认 cd 到了放文件的目录
error: must specify one of -f and -k 忘了写 -f web.yaml
error: error converting YAML to JSON: yaml: line 7: mapping values are not allowed in this context 第 7 行缩进错了(或者混进了 Tab)
no matches for kind "Deploymnet" in version "apps/v1" kind 拼错了
The Deployment "x" is invalid: … selector does not match template labels selector 那两处没写成一样

五、它不是什么

读完你能做什么

下一步:下一章去把它弄坏——你会看到一件用 Docker 时遇不到的事。

进入 keel 阅读