在 Kubernetes 上部署你的第一个应用
用一份 Deployment 把容器跑起来,再用 Service 暴露访问,并掌握查日志、排错和扩缩容的基本操作。
当你已经在自己的服务器 / VPS 集群上装好 Kubernetes(K8s)后,部署应用不再是「登录机器手动起进程」,而是把「我想要什么状态」写进一份 YAML,交给集群自己维持。下面从零跑通第一个应用。
用 Deployment 描述你的应用
Deployment 负责「按你声明的副本数,持续保证有这么多 Pod 在运行」。新建 deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-web
labels:
app: hello-web
spec:
replicas: 2
selector:
matchLabels:
app: hello-web
template:
metadata:
labels:
app: hello-web
spec:
containers:
- name: hello-web
image: nginx:1.27
ports:
- containerPort: 80
几个关键字段:
- image:容器镜像,建议钉具体版本(如 nginx:1.27),别用 latest,否则重启后版本会漂。
- replicas:期望运行几个副本(实例),这里是 2 个。
- labels / selector.matchLabels:标签是 K8s 的「粘合剂」。Deployment 靠 selector 找到自己管的 Pod,二者必须一致。
- containerPort:容器内进程监听的端口。
应用并查看状态
kubectl apply -f deployment.yaml
kubectl get deploy hello-web
kubectl get pods -l app=hello-web -o wide
get deploy 里 READY 显示 2/2 就表示两个副本都就绪;get pods 能看到每个 Pod 的状态、所在节点和 IP。
用 Service 暴露访问
Pod 的 IP 会随重建而变,不能直接用。Service 给一组 Pod 提供稳定入口。集群内部访问用 ClusterIP(默认),想从集群外用节点 IP 访问就用 NodePort。新建 service.yaml:
apiVersion: v1
kind: Service
metadata:
name: hello-web
spec:
type: NodePort
selector:
app: hello-web
ports:
- port: 80
targetPort: 80
nodePort: 30080
Service 的 selector 同样靠标签匹配到上面的 Pod。应用它:
kubectl apply -f service.yaml
kubectl get svc hello-web
之后用「任一节点 IP + 30080」即可访问(NodePort 范围通常是 30000–32767)。若只在集群内部互相调用,把 type 去掉(默认 ClusterIP),按 Service 名 hello-web 访问即可。
排查问题
应用没起来时,先看日志和事件:
kubectl logs -l app=hello-web --tail=100
kubectl describe pod <pod-name>
logs 是容器进程的标准输出;describe 底部的 Events 最有价值,常见的 ImagePullBackOff(镜像拉不下来)、CrashLoopBackOff(进程反复退出)都会在这里给出原因。
扩缩容
流量变化时,直接调整副本数,集群会自动增删 Pod:
kubectl scale deployment hello-web --replicas=4
kubectl get pods -l app=hello-web
想固化就把 deployment.yaml 里的 replicas 改成 4 再 apply 一次,保证 YAML 与集群真实状态一致。
小结
部署应用的核心是「声明期望状态,让集群去维持」:用 Deployment 定义镜像、副本数和标签,用 Service(ClusterIP 内部 / NodePort 外部)提供稳定入口,用 kubectl logs 和 describe 排错,用 kubectl scale 弹性伸缩。把这几份 YAML 纳入版本管理,你的第一个应用就有了可复现、可回滚的部署基线。