介绍
之前的部署实验中使用的镜像均已存在于镜像仓库或集群缓存中。应用程序开发人员还需要了解本地镜像的工作流程:从应用程序文件构建镜像,使该镜像可供 Kubernetes 节点使用,并指示 Deployment 使用它。
在本实验中,你将使用 Minikube 在本地构建一个小型 Web 应用程序镜像,通过 imagePullPolicy: Never 进行部署,然后将应用程序重新构建为第二个镜像标签以进行滚动更新。这模拟了 CKAD 风格的常见任务:将应用程序制品与运行它的 Kubernetes 工作负载连接起来。
准备本地镜像工作区
在此步骤中,你将准备一个干净的命名空间,并确认镜像构建路径可用。
从 /home/labex/project 开始。你将在该目录中创建应用程序文件、镜像构建文件和 Kubernetes 清单。
mkdir -p /home/labex/project
cd /home/labex/project
检查 Kubernetes API 服务器是否可达。如果虚拟机刚启动且节点尚未就绪,请等待几秒钟后再运行该命令。
kubectl get nodes --request-timeout=5s
预期输出包括:
NAME STATUS ROLES AGE VERSION
labex-v135 Ready control-plane ... v1.35...
等待集群网络 Pod 就绪。由于应用程序将通过 Service 进行测试,因此网络必须处于健康状态。
kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s
预期输出:
pod/calico-node-... condition met
创建一个名为 ckad-prep-local-image 的命名空间,并将其设置为当前命名空间:
kubectl create namespace ckad-prep-local-image
kubectl config set-context --current --namespace=ckad-prep-local-image
确认命名空间并检查 Minikube 镜像命令。minikube image build 命令直接为 Minikube 配置文件构建镜像,因此 Pod 无需推送到镜像仓库即可使用它。
kubectl config view --minify --output 'jsonpath={..namespace}'; echo
minikube image build --help | sed -n '1,4p'
预期输出包括:
ckad-prep-local-image
Build a container image...
构建第一个本地镜像
在此步骤中,你将创建一个小型 Web 应用程序并将其构建为 local-message-app:v1。
该镜像将使用 BusyBox httpd 来提供一个静态文件。文件内容即为可见的应用程序版本,以便稍后验证 Kubernetes 中运行的是哪个镜像标签。
创建应用程序目录和第一个网页:
mkdir -p local-message-app/www
cat > local-message-app/www/index.html <<'EOF'
local-image-v1
EOF
创建 Dockerfile。COPY 指令将本地的 www/index.html 文件放入镜像中,CMD 指令在容器从该镜像运行时启动端口为 8080 的 BusyBox Web 服务器。
cat > local-message-app/Dockerfile <<'EOF'
FROM busybox:1.36
COPY www/index.html /www/index.html
EXPOSE 8080
CMD ["httpd", "-f", "-p", "8080", "-h", "/www"]
EOF
为活动的 Minikube 配置文件构建镜像。-t 选项为镜像指定一个本地标签,最后的路径是构建上下文目录。
minikube image build --profile labex-v135 -t local-message-app:v1 ./local-message-app
预期输出包括:
naming to docker.io/library/local-message-app:v1 done
列出 Minikube 已知的镜像并查找你的新标签:
minikube image ls --profile labex-v135 | grep local-message-app
预期输出:
docker.io/library/local-message-app:v1
部署本地镜像
在此步骤中,你将在 Kubernetes 中运行本地镜像。
由于 local-message-app:v1 没有推送到远程镜像仓库,因此 Deployment 使用 imagePullPolicy: Never。这会告知 kubelet 使用节点上已存在的镜像,而不是尝试从网络拉取。
创建 local-image-app.yaml:
cat > local-image-app.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: local-message-app
spec:
replicas: 2
selector:
matchLabels:
app: local-message-app
template:
metadata:
labels:
app: local-message-app
spec:
terminationGracePeriodSeconds: 0
containers:
- name: web
image: local-message-app:v1
imagePullPolicy: Never
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 1
periodSeconds: 2
---
apiVersion: v1
kind: Service
metadata:
name: local-message-app
spec:
selector:
app: local-message-app
ports:
- port: 80
targetPort: 8080
EOF
应用清单并等待 Deployment 就绪:
kubectl apply -f local-image-app.yaml
kubectl rollout status deployment/local-message-app --timeout=120s
预期输出包括:
deployment.apps/local-message-app created
service/local-message-app created
deployment "local-message-app" successfully rolled out
创建一个客户端 Pod 并测试 Service:
kubectl run image-client --image=busybox:1.36 --restart=Never --command -- sleep 3600
kubectl wait --for=condition=Ready pod/image-client --timeout=120s
kubectl exec image-client -- wget -qO- http://local-message-app
预期输出:
local-image-v1
重建并滚动更新新的本地镜像
在此步骤中,你将把应用程序重新构建为第二个镜像标签,并将 Deployment 滚动更新到该标签。
更改磁盘上的文件不会改变正在运行的镜像。你必须构建一个新的镜像标签并更新 Deployment,以便 Kubernetes 从该标签启动新的 Pod。这使得版本变更清晰可见,并避免依赖可变的本地镜像内容。
将网页内容替换为版本二:
cat > local-message-app/www/index.html <<'EOF'
local-image-v2
EOF
构建第二个镜像标签:
minikube image build --profile labex-v135 -t local-message-app:v2 ./local-message-app
预期输出包括:
naming to docker.io/library/local-message-app:v2 done
更新 Deployment 镜像并等待滚动更新完成:
kubectl set image deployment/local-message-app web=local-message-app:v2
kubectl rollout status deployment/local-message-app --timeout=120s
预期输出包括:
deployment.apps/local-message-app image updated
deployment "local-message-app" successfully rolled out
确认镜像标签和应用程序响应:
kubectl get deployment local-message-app -o jsonpath='{.spec.template.spec.containers[0].image}'; echo
kubectl exec image-client -- wget -qO- http://local-message-app
预期输出:
local-message-app:v2
local-image-v2
总结
你为 Minikube 配置文件构建了一个小型应用程序镜像,使用 imagePullPolicy: Never 进行了部署,通过 Kubernetes Service 进行了测试,然后将应用程序重新构建为新的镜像标签并执行了 Deployment 滚动更新。关键的工作流程是在期望 Pod 运行镜像之前,确保该镜像已在节点上可用。



