好的,各位学员,大家好!欢迎来到今天的进阶课程。我是你们的讲师。在接下来的40分钟里,我们将深入探讨“云原生技术栈与容器化”这个主题,帮助大家从理论走向实战,掌握现代云应用的核心构建方法。
---
# 云原生技术栈与容器化
在当今的软件开发领域,业务迭代速度要求越来越快,系统规模越来越大,传统的“单体应用 + 物理/虚拟机部署”模式已经捉襟见肘。云原生正是为了解决这些问题而生。
完成本次学习后,你将具备以下能力:
1. 独立容器化应用:能够熟练编写Dockerfile,将任何应用打包成标准化的Docker镜像。 2. 管理Kubernetes核心资源:能使用YAML文件定义并管理Pod、Service、Deployment等核心对象,实现应用的部署和对外暴露。 3. 搭建CI/CD流水线:能够设计并实现一套从代码提交到自动构建、测试、部署的自动化流程。 4. 进行基础的监控与排错:能够配置基本的监控和日志收集,并利用Kubernetes命令排查常见问题。 5. 理解服务网格价值:了解Istio等工具如何解决微服务通信的复杂性问题,为后续深入学习打下基础。
---
原理讲解:Docker通过镜像(Image)和容器(Container)实现应用与环境的解耦。镜像是一个只读的模板,包含了运行应用所需的一切(代码、运行时、库、环境变量、配置文件)。容器是镜像的运行实例。
核心对比:虚拟机 vs 容器。虚拟机虚拟化硬件,每个VM包含完整的操作系统,资源占用大、启动慢。容器虚拟化操作系统内核,共享宿主机内核,资源占用小、启动秒级。
实战示例:为一个简单的Python Flask应用编写Dockerfile。
# 1. 指定基础镜像,使用轻量级的Python 3.9-slim
FROM python:3.9-slim
# 2. 设置工作目录
WORKDIR /app
# 3. 将依赖文件复制到镜像中
COPY requirements.txt .
# 4. 安装Python依赖
RUN pip install --no-cache-dir -r requirements.txt
# 5. 将当前目录下的所有源代码复制到工作目录
COPY . .
# 6. 声明容器运行时监听的端口
EXPOSE 5000
# 7. 指定容器启动时执行的命令
CMD ["python", "app.py"]
关键命令:
# 构建镜像
docker build -t my-flask-app:v1 .
# 运行容器,映射宿主机8080端口到容器5000端口
docker run -d -p 8080:5000 --name my-app my-flask-app:v1
模块二:Kubernetes核心概念 - 你的“容器编排操作系统”
原理讲解:Kubernetes (K8s) 是一个自动化容器操作的开源平台。它负责容器的部署、伸缩和管理。核心思想是声明式管理:你告诉K8s你想要的最终状态(例如“运行5个Nginx实例”),K8s会持续工作,确保实际状态与期望状态一致。
核心概念:
- **Pod**:K8s中最小的部署单元,通常包含一个或多个紧密相关的容器(如应用容器 + Sidecar日志收集容器)。Pod内的容器共享网络和存储卷。
- **Service**:为一组Pod提供稳定的网络访问入口,实现服务发现和负载均衡。即使Pod的IP发生变化,Service的IP或DNS名称保持不变。
- **Deployment**:负责管理Pod的声明式更新和回滚。你可以通过Deployment描述应用的期望状态(如副本数、镜像版本),Deployment Controller会控制ReplicaSet来实现。
实战示例:部署一个Nginx服务。
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
---
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80 # Service端口
targetPort: 80 # Pod端口
type: ClusterIP # 集群内部访问
模块三:Helm包管理 - K8s的“apt-get/yum”
原理讲解:Kubernetes应用通常由多个YAML文件(Deployment, Service, ConfigMap, Secret等)组成。Helm将这一整套资源打包成一个Chart,并提供模板化(Template)功能,让你可以通过简单的参数化配置,为不同环境(开发、测试、生产)生成不同的YAML。
核心概念:
- **Chart**:一个Helm包,包含一个应用的所有K8s资源定义模板和默认值。
- **Release**:一个Chart在K8s集群中的一次运行实例。你可以使用同一个Chart,通过不同配置部署出多个Release。
实战示例:使用Helm安装一个WordPress。
# 1. 添加Bitnami仓库
helm repo add bitnami https://charts.bitnami.com/bitnami
# 2. 更新仓库
helm repo update
# 3. 安装WordPress,并自定义参数
helm install my-wordpress bitnami/wordpress \
--set wordpressUsername=admin \
--set wordpressPassword=password123 \
--set service.type=NodePort
# 4. 查看已安装的Release
helm list
模块四:CI/CD流水线与监控日志
原理讲解:
- **CI/CD**:持续集成/持续部署。CI指频繁地将代码合并到主干,并自动进行构建和测试。CD指在CI通过后,自动将应用部署到目标环境。常见工具链:GitLab CI, Jenkins, GitHub Actions。
- **监控**:核心是**Prometheus + Grafana**组合。Prometheus负责采集指标数据(如CPU、内存、请求数),Grafana负责可视化展示。
- **日志**:核心是**EFK/ELK** (Elasticsearch, Filebeat/Fluentd, Kibana) 或 **Loki**。Filebeat/Fluentd负责从各节点收集容器日志,发送到Elasticsearch/Loki存储,Kibana/Grafana用于搜索和分析。
实战示例:一个简化的GitLab CI流水线。
# .gitlab-ci.yml
stages:
- build
- test
- deploy
build-job:
stage: build
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
test-job:
stage: test
script:
- echo "Running unit tests..."
deploy-staging:
stage: deploy
script:
- kubectl set image deployment/my-app my-app=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA -n staging
environment:
name: staging
only:
- main
---
三、实操步骤
目标:将一个简单的“Hello World”应用从零部署到Kubernetes集群。
前置条件:已安装Docker、kubectl、minikube(用于本地测试)或拥有一个K8s集群。
步骤1:准备应用与Docker镜像
1. 创建一个 app 目录,并在其中创建 app.py 和 requirements.txt。
- `app.py`:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return "Hello, Cloud Native!"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
- `requirements.txt`:
Flask==2.3.2
2. 在该目录下创建 Dockerfile (内容见模块一)。
3. 构建并推送镜像:
docker build -t my-hello-app:v1 .
# 如果需要推送到远程仓库,请先docker login
# docker tag my-hello-app:v1 your-dockerhub-username/my-hello-app:v1
# docker push your-dockerhub-username/my-hello-app:v1
步骤2:创建Kubernetes部署资源
1. 创建一个 deployment.yaml 文件:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-deployment
spec:
replicas: 2
selector:
matchLabels:
app: hello
template:
metadata:
labels:
app: hello
spec:
containers:
- name: hello-app
image: my-hello-app:v1 # 如果是远程仓库,替换为 your-dockerhub-username/my-hello-app:v1
ports:
- containerPort: 5000
2. 创建一个 service.yaml 文件:
apiVersion: v1
kind: Service
metadata:
name: hello-service
spec:
selector:
app: hello
ports:
- protocol: TCP
port: 80
targetPort: 5000
type: NodePort # 在Minikube中方便访问
步骤3:部署到Kubernetes
1. 启动Minikube (如果使用本地环境):
minikube start
2. 应用YAML文件:
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
3. 验证部署:
kubectl get pods -l app=hello # 查看Pod状态,应显示2个Running
kubectl get service hello-service # 查看Service状态
4. 访问应用:
# 获取Minikube的访问URL
minikube service hello-service --url
打开浏览器访问返回的URL,你应该能看到 Hello, Cloud Native!。
---
四、常见问题与故障排查
问题1:Pod状态一直为 Pending
- **原因**:通常是因为集群资源不足(如CPU、内存),或无法调度到合适的节点。
- **排查**:
1. kubectl describe pod <pod-name> 查看Events部分,寻找失败原因。
2. kubectl get nodes 查看节点资源使用情况 (kubectl top nodes)。
3. 检查是否有节点污点(Taints)与Pod容忍度(Tolerations)不匹配。
问题2:Pod状态为 CrashLoopBackOff
- **原因**:容器启动后立即崩溃,K8s反复重启,导致进入回退状态。
- **排查**:
1. kubectl logs <pod-name> 查看容器日志,这是最直接的方法。
2. kubectl logs <pod-name> --previous 查看上次崩溃的日志。
3. 进入容器内部调试:kubectl exec -it <pod-name> -- /bin/sh,检查进程、配置文件等。
问题3:Service无法访问(Connection refused)
- **原因**:Service的 `selector` 没匹配到任何Pod,或者Pod的端口标签不匹配。
- **排查**:
1. kubectl describe service <service-name> 查看 Endpoints 字段。如果为空,说明没有后端Pod被选中。
2. 检查Service的 selector 和Pod的 labels 是否一致。
3. kubectl get pods --show-labels 查看Pod的标签。
问题4:镜像拉取失败(ImagePullBackOff)
- **原因**:镜像名称错误、标签不存在、私有仓库认证失败。
- **排查**:
1. kubectl describe pod <pod-name> 查看Events,会明确提示是 ErrImagePull 或 ImagePullBackOff,并给出错误原因。
2. 检查YAML中的 image 字段。
3. 如果是私有仓库,确认是否创建了 imagePullSecrets。
---
五、总结与扩展
重点知识回顾
1. 容器化是基石:Docker让应用和环境标准化,是云原生的“乐高积木”。
2. K8s是编排核心:Pod是最小单元,Deployment管理生命周期,Service提供稳定网络入口。声明式API是K8s的精髓。
3. Helm是组合工具:通过Chart管理复杂应用,实现参数化部署和环境隔离。
4. CI/CD是效率引擎:自动化从代码到部署的流程,是DevOps实践的关键一环。
5. 可观测性是保障:监控(Metrics)和日志(Logging)是理解系统状态、快速定位问题的眼睛。
实战中的最佳实践建议
- **镜像构建**:优先选择Alpine等小型基础镜像;利用多阶段构建(Multi-stage builds)减小镜像体积;使用 `.dockerignore` 文件排除无用文件。
- **资源声明**:始终为Pod设置 `resources.requests` 和 `resources.limits`,避免资源争抢。
- **配置管理**:将配置(如数据库地址)和敏感信息(如密码)分别放入ConfigMap和Secret中管理,不要硬编码在镜像里。
- **健康检查**:为Pod配置 `livenessProbe` (存活探针) 和 `readinessProbe` (就绪探针),让K8s自动管理Pod的健康状态和流量接入。
- **命名空间隔离**:使用Namespace(如 `dev`, `staging`, `prod`)隔离不同环境的应用。
推荐进一步学习的方向和资源
- **深入学习Kubernetes**:CNCF官方CKAD/CKA认证课程、Kubernetes官方文档。
- **服务网格(Service Mesh)**:学习Istio,理解流量管理、安全、可观测性在微服务层面的实现。
- **云原生存储**:了解Rook、Longhorn等云原生存储解决方案。
- **Serverless**:学习Knative,探索在K8s上实现无服务器架构。
- **GitOps**:学习ArgoCD或Flux,实现以Git仓库为单一事实来源的声明式部署。
今天的课程到这里就结束了。希望大家能将今天学到的知识应用到实际工作中,开始你的云原生之旅。谢谢大家!