1. 项目概述:从零到一掌握Azure Kubernetes服务
最近在帮团队做容器化与云原生架构的迁移,Azure Kubernetes Service (AKS) 成了我们技术栈里的核心组件。在学习和落地过程中,我发现了一个宝藏级的开源学习资源——HoussemDellai/aks-course。这不仅仅是一个简单的代码仓库,更是一套结构清晰、由浅入深的实战教程,它完美地填补了官方文档与生产实践之间的鸿沟。对于任何想要系统掌握AKS,从创建第一个集群到部署生产级应用的朋友来说,这个课程都是一个绝佳的起点。它避开了枯燥的理论堆砌,直接带你上手操作,在动手中理解核心概念,特别适合开发者、运维工程师和架构师。
这个课程仓库的内容编排非常“接地气”,它模拟了一个真实的项目演进路径:从最基础的集群搭建,到应用部署、配置管理、安全加固,再到监控、扩缩容等高级主题。你会发现,作者Houssem Dellai的讲解方式就像一位经验丰富的同事在旁边指导,把复杂的云原生概念拆解成一个个可执行的任务。接下来,我将结合自己实际使用AKS的经验,为你深度拆解这个课程的核心内容,并补充大量官方教程里不会明说的实操细节和避坑指南。
2. 课程核心模块与学习路径解析
2.1 模块化学习地图:循序渐进掌握AKS全貌
HoussemDellai/aks-course的课程结构设计得非常科学,遵循了“学以致用”的原则。整个课程可以看作一张技能地图,我们按图索骥就能建立起完整的AKS知识体系。
第一部分:基础入门与环境搭建。这部分会带你快速创建一个AKS集群。但课程的高明之处在于,它不止步于az aks create这条命令。它会详细解释每个参数的意义,比如节点大小(Node Size)的选择:为什么测试环境可以用Standard_DS2_v2,而生产环境可能需要Standard_D4s_v3或更高?这背后是vCPU、内存以及临时SSD磁盘性能的权衡。课程还会引导你配置命令行工具(Azure CLI和kubectl),并验证连接。一个我经常提醒新手的细节是:创建集群后,务必使用az aks get-credentials命令来合并kubeconfig文件,而不是覆盖,这样可以优雅地管理多个集群的上下文。
第二部分:应用部署与基础运维。从这里开始,真正的“游戏”开始了。课程会教你如何将容器镜像部署到AKS。它通常从最简单的kubectl run命令开始,但很快会过渡到使用YAML清单文件部署Deployment和Service。这是关键的一跃。课程会解释Pod、Deployment、Service、ReplicaSet这些核心对象的关系。例如,Deployment如何确保指定数量的Pod副本始终运行?Service的ClusterIP、NodePort和LoadBalancer三种类型分别适用于什么场景?这部分会通过一个简单的Web应用示例让你有直观的感受。
第三部分:配置、存储与网络进阶。掌握了部署,就要解决实际需求:如何管理敏感配置(如数据库连接字符串)?这就是ConfigMap和Secret的用武之地。课程会演示如何创建它们,并以环境变量或卷挂载的方式注入Pod。存储方面,会介绍Azure Disk和Azure Files这两种主要的持久卷(Persistent Volume)类型,以及何时该用哪种。网络部分则会深入Ingress控制器(通常使用NGINX Ingress)的配置,让你理解如何通过一个公网IP和域名来暴露集群内的多个服务。
第四部分:安全、监控与自动化。这是通向生产就绪的关键环节。课程会涵盖服务账户(Service Account)、角色(Role)和角色绑定(RoleBinding),即Kubernetes的RBAC授权模型。在监控方面,它会介绍如何集成Azure Monitor for containers,从集群和Pod两个层面收集日志与指标。最后,自动化部分会触及CI/CD流水线的概念,如何用GitHub Actions或Azure DevOps将代码变更自动构建、推送镜像并部署到AKS。
2.2 为什么这个课程设计有效?对比传统学习方式
很多人在学习云服务时容易陷入两个极端:要么只看理论概念,云里雾里;要么直接照抄生产配置,不明就里。这个课程的成功在于它采用了“任务驱动学习法”。
首先,它以终为始。每个模块都有一个明确的目标,比如“部署一个高可用的Web应用”。为了达到这个目标,你需要依次学习集群创建、镜像构建、YAML编写、服务暴露等技能。这种学习方式动力足,成就感强。
其次,它提供了完整的上下文。不同于官方文档孤立地介绍某个功能,这个课程会把相关功能串联起来。比如在讲Ingress时,一定会回顾之前创建的Deployment和Service,让你明白Ingress是在Service之上的一层路由抽象。
再者,它鼓励动手和试错。课程中的代码和配置都是可运行的。我强烈建议你在学习时,不要只是阅读,而是跟着每一步操作。在Azure门户上观察资源的变化,用kubectl get、kubectl describe命令查看对象状态。遇到错误时,尝试根据错误信息去排查,这个过程本身就是极佳的学习。
注意:在Azure上操作会产生实际费用。对于学习用途,务必在完成练习后及时删除资源组(使用
az group delete --name <资源组名>),这是控制成本最有效的方式。可以利用Azure的免费额度或创建一个专门用于学习、设置好预算警报的订阅。
3. 核心实操环节深度拆解与经验注入
3.1 集群创建:参数选择背后的成本与性能权衡
创建AKS集群是第一步,但az aks create命令背后的一串参数,每一个都关乎着集群的性能、可用性和月度账单。课程会给出示例命令,但我想分享一些更深层的选型经验。
节点池(Node Pool)配置:这是集群的“工作肌肉”。--node-count和--node-vm-size是核心。
- 节点数量:对于学习和开发,2个节点足以提供高可用基础。生产环境则需要根据应用负载和故障域来规划,通常至少3个节点分布在不同的更新域(Update Domain)和容错域(Fault Domain)中。
- 虚拟机大小:
Standard_DS2_v2(2 vCPU,7GB内存)是常见的入门选择。但你需要评估你的容器需求。一个Java应用可能至少需要1-2GB内存,而一个Node.js应用可能只需要512MB。使用kubectl top pod/node命令监控资源使用情况是调整大小的依据。对于有大量临时数据读写(如日志处理)的应用,带“DS”或“LS”系列的VM(配备本地SSD)性能更好。
网络模型选择(--network-plugin):课程可能会提到kubenet和Azure CNI。
- kubenet:简单,Azure管理子网,Pod IP由Kubernetes管理,与集群虚拟网络(VNet)不同。适合入门和Pod数量较少(<400)的场景。
- Azure CNI:高级模式,Pod直接获得VNet中的IP地址,与Azure其他服务(如VM、数据库)通信无需额外路由,性能更好,但需要提前规划大规模的子网地址空间。对于大多数计划将AKS集成到现有企业网络或需要大量Pod的生产环境,Azure CNI是更推荐的选择。
身份与访问管理(--aad-server-app-id等):课程后期会涉及Azure Active Directory (AAD) 集成,这是企业级安全的核心。它允许你使用公司的AAD账户和组来控制对Kubernetes集群的RBAC访问,而不是共享一个静态的kubeconfig文件。即便在学习阶段,也建议你了解这个选项,因为它代表了生产环境的最佳实践。
一个被我忽略过的重要参数:--enable-managed-identity。现在创建AKS集群,务必使用系统分配或用户分配的托管标识(Managed Identity),而不是服务主体(Service Principal)。托管标识由Azure自动管理密钥轮换,安全性更高,管理更简单。这已经是当前Azure的默认推荐方式。
3.2 应用部署清单:YAML文件里的“魔鬼细节”
课程会提供部署应用的YAML示例。读懂并修改这些YAML文件,是掌握Kubernetes的关键。我们以一个典型的Deployment YAML为例,拆解几个容易出错的点。
apiVersion: apps/v1 kind: Deployment metadata: name: my-webapp spec: replicas: 3 # 副本数 selector: matchLabels: app: my-webapp template: metadata: labels: app: my-webapp spec: containers: - name: main image: myregistry.azurecr.io/myapp:v1.0 # 镜像地址 ports: - containerPort: 80 resources: requests: # 资源请求,调度依据 memory: "256Mi" cpu: "250m" limits: # 资源上限,防止失控 memory: "512Mi" cpu: "500m" livenessProbe: # 存活探针 httpGet: path: /healthz port: 80 initialDelaySeconds: 30 # 关键参数! periodSeconds: 10replicas:副本数决定了Pod实例的数量。设置为3,意味着Deployment会努力维持3个相同的Pod运行。如果某个Pod所在的节点故障,控制器会在其他节点上重新调度一个新的Pod。这是实现无状态应用高可用的基础。selector与template.labels:这二者必须严格匹配。selector告诉Deployment如何查找它管理的Pod,而template里定义了Pod的标签。如果标签不匹配,Deployment将无法关联到它创建的Pod,导致副本数永远达不到预期。这是一个常见的配置错误。resources.requests/limits:这是资源管理的核心,也是课程会强调的重点。requests:是容器启动时向集群“申请”的资源量。调度器(Scheduler)会根据节点的剩余可分配资源(Allocatable)来决定将Pod放在哪个节点。不设置requests,可能导致Pod被调度到资源不足的节点,引发运行时问题。limits:是容器所能使用的资源上限。如果容器内存使用超过limits,它会被OOM Killer终止;如果CPU超过limits,会被 throttled(限制)。生产环境必须设置合理的limits,防止单个异常Pod拖垮整个节点。
livenessProbe:存活探针,用于判断容器是否“活着”。initialDelaySeconds至关重要。它定义了容器启动后,等待多少秒才开始执行第一次探针检查。对于Java等启动较慢的应用,这个值必须设置得足够长(比如60秒以上),否则容器还在启动时就被探针判定为失败,从而陷入不断重启的死循环。这是我早期踩过的一个大坑。
3.3 服务暴露与Ingress:从集群内到公网访问
部署好应用后,如何在集群内或从公网访问它?课程会逐步引导你理解Service和Ingress。
Service:为Pod提供一个稳定的网络端点。创建Service后,它会获得一个集群内固定的ClusterIP(虚拟IP)和一个DNS名称(格式为<service-name>.<namespace>.svc.cluster.local)。
- ClusterIP:默认类型,仅在集群内部可访问。
- NodePort:在每个节点上开放一个静态端口(30000-32767),通过
<NodeIP>:<NodePort>可以从集群外部访问。适用于临时测试或无法使用LoadBalancer的场景。 - LoadBalancer:最常用的对外暴露方式。在Azure上,这会自动创建一个Azure公有负载均衡器,并分配一个公网IP。所有流量先到负载均衡器,再分发到各节点的NodePort,最终到达Pod。这是将服务暴露到互联网的标准方式。
Ingress:当你有多个服务需要对外暴露时,为每个服务都创建一个LoadBalancer代价高昂(每个LB都有独立的IP和成本)。Ingress登场了,它相当于一个“智能路由层”。
- 你需要先部署一个Ingress控制器(如NGINX Ingress Controller)。在AKS上,这通常通过一个Helm Chart轻松完成。
- 然后,创建Ingress资源,定义路由规则。例如,将所有访问
/app1的流量导向app1-service,将访问/app2的流量导向app2-service,并且都使用同一个LoadBalancer的公网IP和80/443端口。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / # 常用的重写注解 spec: ingressClassName: nginx rules: - host: app.mydomain.com # 你的域名 http: paths: - path: /app1 pathType: Prefix backend: service: name: app1-service port: number: 80 - path: /app2 pathType: Prefix backend: service: name: app2-service port: number: 80关键经验:配置Ingress后,你需要将域名的A记录指向Azure LoadBalancer的公网IP。此外,Ingress控制器提供了丰富的注解(annotations)来配置行为,如SSL终止、连接超时、速率限制等,这是进阶学习的宝库。
4. 生产就绪进阶:安全、监控与CI/CD实战
4.1 安全加固:不止于RBAC
课程会介绍Kubernetes RBAC,这是控制“谁(用户/服务账户)能做什么(动词)在什么资源上”的基础。但生产环境的安全是分层、纵深防御的。
1. Pod安全上下文(Security Context):在Pod或容器级别限制权限。永远不要以root用户运行容器。
spec: securityContext: # Pod级别安全上下文 runAsUser: 1000 runAsGroup: 3000 fsGroup: 2000 containers: - name: sec-ctx-demo securityContext: # 容器级别安全上下文 allowPrivilegeEscalation: false capabilities: drop: - ALL # 丢弃所有Linux CapabilitiesrunAsNonRoot: true可以强制要求容器以非root用户运行。allowPrivilegeEscalation: false防止权限提升。capabilities.drop: [“ALL”]移除所有Linux特权能力,这是最小权限原则的体现。
2. 网络策略(NetworkPolicy):默认情况下,Kubernetes集群内的所有Pod是互通的。网络策略允许你定义Pod之间、Pod与外部之间的网络流量规则,实现网络层面的隔离。例如,你可以规定只有前端的Pod才能访问后端的数据库Pod。
3. 密钥管理:虽然Kubernetes有Secret对象,但它只是Base64编码,并非加密。对于生产环境的敏感信息(如数据库密码、API密钥),应使用Azure Key Vault。通过AKS与Key Vault的集成(如使用Azure Key Vault Provider for Secrets Store CSI Driver),可以将密钥安全地注入到Pod中作为卷或环境变量,实现密钥的集中管理和自动轮换。
4.2 监控与日志:洞察集群与应用健康
“可观测性”是生产系统的生命线。课程会引导你启用Azure Monitor for containers,这是最便捷的集成方案。
启用监控:在创建集群时添加--enable-addons monitoring参数,或通过门户启用。它会自动在集群中部署一个DaemonSet来收集所有节点和Pod的指标与日志。
你能看到什么?
- 集群视图:节点CPU/内存使用率、节点数量、活动Pod数。
- 工作负载视图:每个Deployment/StatefulSet的Pod状态、CPU/内存使用量。
- 容器视图:单个容器的实时指标和日志流。
- 日志查询:使用强大的Kusto查询语言(KQL)跨所有Pod和节点进行日志检索和分析。例如,查询过去5分钟内所有错误级别的日志:
ContainerLog | where LogLevel == “err”。
经验之谈:除了平台提供的监控,应用自身也应该暴露Prometheus格式的指标,并定义有业务意义的仪表盘。同时,合理设置日志级别(INFO, WARN, ERROR),避免日志泛滥,并确保日志是结构化的(如JSON格式),便于后续解析。
4.3 CI/CD自动化:让部署流水线化
手动执行kubectl apply只适用于早期测试。课程最后会引入CI/CD概念。其核心思想是:代码提交触发自动化流程,完成构建、测试、推送镜像、更新部署。
一个基于GitHub Actions的简化流水线示例(.github/workflows/deploy.yml):
name: Build and Deploy to AKS on: push: branches: [ main ] jobs: build-and-deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 # 1. 登录到容器注册表(如ACR) - name: Log in to Azure Container Registry uses: azure/docker-login@v1 with: login-server: ${{ secrets.ACR_LOGIN_SERVER }} username: ${{ secrets.ACR_USERNAME }} password: ${{ secrets.ACR_PASSWORD }} # 2. 构建并推送Docker镜像 - name: Build and push image run: | docker build -t ${{ secrets.ACR_LOGIN_SERVER }}/myapp:${{ github.sha }} . docker push ${{ secrets.ACR_LOGIN_SERVER }}/myapp:${{ github.sha }} # 3. 设置Kubectl上下文(连接到AKS) - name: Set up kubectl context uses: azure/aks-set-context@v1 with: creds: ${{ secrets.AZURE_CREDENTIALS }} cluster-name: my-aks-cluster resource-group: my-resource-group # 4. 更新K8s部署清单中的镜像标签并应用 - name: Deploy to AKS run: | sed -i ‘s|image: .*|image: ${{ secrets.ACR_LOGIN_SERVER }}/myapp:${{ github.sha }}|’ k8s/deployment.yaml kubectl apply -f k8s/这个流程的关键在于将镜像标签与每次代码提交的SHA关联,实现了每次部署的唯一性和可追溯性。所有敏感信息(如ACR密码、Azure凭证)都存储在GitHub Secrets中,保证了安全。
5. 常见问题排查与运维技巧实录
5.1 集群与节点级别问题
问题1:节点状态显示“NotReady”
- 排查思路:
kubectl describe node <node-name>:查看节点的详细事件,常见原因是kubelet进程异常或网络插件故障。kubectl get pods -n kube-system:检查kube-proxy,azure-cni-networkmonitor等系统Pod是否全部运行正常。- 登录Azure门户,查看虚拟机规模集(VMSS)中对应节点的状态,是否正在进行平台更新或出现了硬件故障。
- 经验技巧:AKS节点由Azure平台管理,对于非临时性的节点故障,最直接的方法是通过Azure门户或CLI对节点进行“重置”。这会安全地驱逐该节点上的所有Pod(在其他节点上重建),然后重新初始化节点。
问题2:Pod无法调度,提示“Insufficient cpu/memory”
- 排查思路:
kubectl describe pod <pod-name>:查看Events部分,确认调度失败的具体原因。kubectl top node:查看各节点的资源请求和剩余可分配资源。- 检查Pod的
resources.requests是否设置得过高,或者节点上是否存在大量未设置requests的“资源黑洞”Pod。
- 解决方案:
- 调整Pod的资源请求,使其更符合实际需求。
- 清理或优化其他Pod的资源请求。
- 如果长期资源不足,考虑纵向扩展(升级节点VM大小)或横向扩展(增加节点数量)。AKS支持集群自动缩放器(Cluster Autoscaler),可以根据Pending状态的Pod自动增加节点。
5.2 应用部署与运行时问题
问题3:Pod状态为“CrashLoopBackOff”这是最常见的错误之一,意味着容器启动后立即退出,Kubernetes不断尝试重启它。
- 排查步骤:
kubectl logs <pod-name> --previous:查看上一个崩溃容器的日志,这是定位启动问题的首要方法。- 检查应用配置:环境变量、配置文件、连接的数据库/服务地址是否正确。
- 检查存活探针(livenessProbe)配置:
initialDelaySeconds是否太短?探针路径/端口是否正确?应用在启动初期可能无法立即响应健康检查。 - 检查资源限制(limits):是否内存设置过小,导致应用启动时即被OOM Killer终止?
- 一个经典案例:一个Spring Boot应用,
initialDelaySeconds设为10秒,但应用在20秒后才能完全启动。结果就是应用还在加载时,存活探针检查失败,Pod被重启,陷入死循环。将initialDelaySeconds调整为30秒以上,问题解决。
问题4:服务无法从外部访问(LoadBalancer/Ingress)
- 排查路径:
- 确认Pod本身正常:
kubectl get pods查看Pod是否为Running状态,kubectl logs查看应用日志。 - 确认Service正确关联Pod:
kubectl describe service <service-name>,查看Endpoints列表是否包含正确的Pod IP。如果没有Endpoints,说明Service的selector与Pod的labels不匹配。 - 确认LoadBalancer就绪:
kubectl get service,查看EXTERNAL-IP是否从<pending>变成了一个实际的公网IP。如果一直是pending,可能是Azure订阅配额(如公网IP数量)不足。 - 确认Ingress控制器工作:
kubectl get pods -n ingress-nginx查看Ingress控制器Pod状态。kubectl describe ingress <ingress-name>查看Ingress资源的事件和状态。 - 检查网络规则:在Azure门户中,查看负载均衡器或节点网络安全组(NSG)的入站规则,是否允许了目标端口(如80、443)的流量。
- 确认Pod本身正常:
5.3 配置与存储问题
问题5:ConfigMap或Secret更新后,Pod内的配置未生效
- 原因:Kubernetes不会自动将更新后的ConfigMap或Secret同步到已运行的Pod中。
- 解决方案:
- 重启Pod:最简单粗暴的方式是删除Pod,让Deployment重建它。
- 使用不可变ConfigMap/Secret:更新时创建一个新版本(如
app-config-v2),然后更新Pod模板引用新版本,触发滚动更新。 - 使用Sidecar容器监控文件变化:更复杂的方案是使用像Reloader这样的工具,但增加了运维复杂度。
- 最佳实践:将配置视为不可变基础设施的一部分。每次配置变更,都通过更新Deployment的镜像标签或环境变量引用来触发一次新的发布。这更符合GitOps的理念。
问题6:Pod无法挂载持久卷(Persistent Volume)
- 排查:
kubectl describe pod:查看Events,常见错误是“failed to attach volume”或“timeout waiting for volume”。kubectl get pv, pvc:查看持久卷(PV)和持久卷声明(PVC)的状态。PVC是否处于Pending状态?- 如果是Azure Disk:检查磁盘是否已被其他Pod挂载(Azure Disk是ReadWriteOnce模式,只能被一个节点挂载)。检查节点是否与磁盘在同一个可用区(Availability Zone)。
- 如果是Azure Files:检查存储账户的防火墙规则是否允许了AKS节点所在虚拟网络的访问。
5.4 日常运维效率技巧
技巧1:使用别名和kubectl插件
- 在
~/.bashrc或~/.zshrc中添加别名:alias k=‘kubectl’,alias kgp=‘kubectl get pods’,alias kd=‘kubectl describe’,能极大提升输入效率。 - 安装
kubectl-ctx和kubectl-ns插件,快速切换集群上下文和命名空间。 - 安装
kubectl-neat插件,清理kubectl get输出中的冗余信息,让输出更清晰。
技巧2:善用kubectl describe和kubectl logs
kubectl describe <resource-type> <resource-name>是排查任何资源问题的第一把钥匙,它提供了资源的详细配置和最近的事件(Events),事件里往往藏着问题的根源。kubectl logs除了查看当前日志,--previous参数对于查看已崩溃容器的日志至关重要,-f参数用于实时跟踪日志流,-c参数用于指定Pod中的某个容器(多容器Pod时)。
技巧3:使用命名空间进行环境隔离不要把所有应用都部署在default命名空间。为开发(dev)、测试(staging)、生产(prod)创建独立的命名空间。这样可以通过RBAC和网络策略进行更精细的权限和网络控制,也便于资源管理和查看。使用kubectl config set-context --current --namespace=<namespace>可以设置当前上下文的默认命名空间。
技巧4:定期清理资源
- 定期删除失败的Pod:
kubectl delete pod --field-selector=status.phase=Failed - 清理已完成的Job:
kubectl delete jobs --field-selector=status.successful=1 - 对于开发集群,养成习惯:离开时,使用
az group delete --name <资源组名> --yes --no-wait删除整个资源组,这是避免产生意外费用的最有效方法。
学习HoussemDellai/aks-course的过程,就像在一位经验丰富的向导带领下,系统性地探索AKS这片大陆。从搭建营地(创建集群)、制造工具(部署应用)、建立规则(配置与安全),到绘制地图(监控)和修建高速公路(CI/CD),每一步都扎实而必要。我自己的体会是,云原生技术的掌握没有捷径,就是在理解核心概念的基础上,通过反复的动手实践和问题排查来积累经验。这个课程提供了绝佳的实践场,而你在实践中遇到的每一个错误和其解决方案,都将成为你知识体系中最牢固的部分。当你能够流畅地运用这些工具和概念,设计并维护一个健壮、可扩展的AKS集群时,你会发现,当初那些令人头疼的YAML文件和复杂命令,都已内化为一种清晰的运维直觉。