K8S入门真不难,把这篇文章看完就够了

K8S入门真不难,把这篇文章看完就够了
不少兄弟问我K8S怎么学这事儿说来话长。之前我们公司搞大促一个传统部署的Java服务突然挂了。运维同事手忙脚乱登上服务器进程还在但就是接不进请求。最后排查下来是机器负载太高了想扩容行去申请机器、走审批流程、等IDC上架一套下来活动都结束了。后来上了K8S同样的场景再发生怎么办HPA自动扩容五分钟不到新Pod就起来了流量切过去稳稳当当。从那之后我才真正意识到K8S这东西不是锦上添花是雪中送炭。今天就把我这几年踩过的坑、总结的经验毫无保留地分享给大家。把K8S当成包工头来理解很多新手一上来就去看官方文档看到Pod、Deployment、Service这些名词直接就懵了。我跟你说别那么正经地去学它你就把它想象成一个包工头。包工头管什么呢管工人Pod、管工地Node、管图纸Deployment、管门牌号Service。这么一想是不是就接地气多了具体到技术层面K8S集群里有两种角色。控制节点Master相当于包工头的大脑负责调度、决策、监控集群状态。一般包括API Server、etcd、Scheduler、Controller Manager这几个组件。etcd是存储集群所有数据的数据库别小看它集群挂了它都不能挂。工作节点Node是真正干活的工人每个Node上跑着kubelet、kube-proxy、容器运行时一般是containerd或者docker。Pod就是在这个上面实际运行的。我们生产环境用的是3个Master节点 10个Worker节点的配置高可用方面至少Master得保证3个不然一个挂了集群就出问题了。环境搭建先别上来就搭生产集群新手最常犯的错误是什么一上来就要搭生产级K8S集群。兄弟你连Pod是啥都没搞清楚搭什么生产集群我强烈建议入门阶段就用minikube或者kind来练手。这两个工具能在你本机起一个单节点的K8S集群特别适合学习。minikube安装Mac为例brewinstallminikube minikube start--driverdocker kubectl get nodes看到节点状态变成Ready恭喜你你已经有了第一个K8S集群。kubectl是K8S的命令行工具记住它后面要天天用。建议配置上自动补全source(kubectl completionbash)echosource (kubectl completion bash)~/.bashrczsh用户就把bash换成zsh这能给你省下大量时间。PodK8S里最小的调度单位很多人以为Pod就是容器其实不完全对。Pod可以理解成一个盒子里面可以装一个或多个紧耦合的容器。这些容器共享网络、存储命运也连在一起——一个挂了整个Pod都会被重启。举个真实的例子我们有个业务是数据采集需要一个主程序加一个日志收集的sidecar。这种场景下把它们放在同一个Pod里就很合适。Sidecar模式也是K8S里非常推荐的做法。apiVersion:v1kind:Podmetadata:name:my-app-podspec:containers:-name:appimage:nginx:1.21ports:-containerPort:80-name:log-collectorimage:log-collector:v1volumeMounts:-name:log-volumemountPath:/var/log/appvolumes:-name:log-volumeemptyDir:{}Deployment管Pod的包工头光有Pod不够因为Pod挂了就没了不能自动恢复。Deployment就是来解决这个问题的——它负责保证你指定数量的Pod始终在运行。apiVersion:apps/v1kind:Deploymentmetadata:name:web-deploymentspec:replicas:3selector:matchLabels:app:webtemplate:metadata:labels:app:webspec:containers:-name:nginximage:nginx:1.21ports:-containerPort:80这个Deployment会保证集群里始终有3个nginx Pod在跑。Pod挂了自动拉起新的。机器挂了把Pod调度到其他机器上。我们生产上一个核心服务配置的是replicas5然后配合HPA根据CPU使用率自动扩缩容平时5个够用大促的时候能自动扩到20多个挺省心的。Service给Pod一个稳定的门牌号Pod的IP是不固定的今天是10.244.1.5明天可能就变成10.244.1.8了。那别的服务怎么找到它Service就是来解决这个问题的。最常用的Service类型是ClusterIP只能在集群内部访问。如果要从外部访问用NodePort或者LoadBalancer。云上一般用LoadBalancer会自动创建SLB。apiVersion:v1kind:Servicemetadata:name:web-servicespec:type:ClusterIPselector:app:webports:-port:80targetPort:80这个Service会监听所有标签是appweb的Pod然后把请求转发过去。Service的IP是固定的Pod再怎么变Service IP都不变。Namespace给集群分房间当集群里跑了成百上千个服务时全部堆在一起肯定乱。Namespace就是用来隔离资源的相当于给集群分了不同的房间。我们生产上是这么分的按环境分dev、test、staging、prod按业务线分user、order、pay。这样资源配额也能分开管理避免某个环境的测试Pod把生产资源吃满。kubectl create namespace production kubectl get ns生产环境实战一个完整的部署流程光说不练假把式。下面我带大家走一遍生产上部署一个服务的完整流程包含我们踩过的坑。Dockerfile编写FROM openjdk:11-jre-slim WORKDIR /app COPY target/myapp.jar /app/ EXPOSE 8080 ENTRYPOINT [java, -jar, myapp.jar]这里有个坑基础镜像别用latest标签版本要固定死。我们之前有个服务用openjdk:latest结果某天构建的时候拉了最新版本JDK 8和JDK 11不兼容服务起不来了。血的教训。K8S部署文件apiVersion:apps/v1kind:Deploymentmetadata:name:myappnamespace:productionlabels:app:myappspec:replicas:3selector:matchLabels:app:myapptemplate:metadata:labels:app:myappspec:containers:-name:myappimage:registry.company.com/myapp:v1.0.0ports:-containerPort:8080resources:requests:memory:512Micpu:500mlimits:memory:1Gicpu:1000mlivenessProbe:httpGet:path:/healthport:8080initialDelaySeconds:30periodSeconds:10readinessProbe:httpGet:path:/readyport:8080initialDelaySeconds:5periodSeconds:5env:-name:DB_HOSTvalueFrom:configMapKeyRef:name:app-configkey:db.host重点说一下几个配置resources这块requests是K8S调度时给Pod分配的最低资源limits是Pod能用的最大资源。不设limits的话Pod可能把整个节点资源吃满影响其他Pod。我们之前就遇到过这种情况一个有内存泄漏的服务把整个节点搞挂了。健康检查也很关键livenessProbe判断容器是不是活着不健康就重启。readinessProbe判断容器能不能接流量不健康就不接流量。这两个一定都要配不然滚动更新的时候新版本可能还没起来流量就切过去了导致服务短暂不可用。环境变量这块配置和镜像分离不要把配置写死在代码里。生产上我们用ConfigMap管理配置用Secret管理敏感信息。应用配置并验证kubectl apply-fdeployment.yaml kubectl get pods-nproduction kubectl describe pod pod-name-nproduction kubectl logs-fpod-name-nproduction kubectlexec-itpod-name-nproduction -- /bin/bash如果Pod一直起不来describe命令是你的救命稻草它会把Pod的详细信息都列出来包括事件、状态、配置等等。那次差点让我丢工作的故障讲个真实案例希望大家能引以为戒。去年有个周五下午我们上线一个新版本。开发那边说就改了个小功能让运维直接发。流程是这样的先灰度10%流量观察10分钟没问题再全量。结果灰度上去之后监控系统告警了错误率飙升到15%。我第一反应是版本有问题赶紧回滚。回滚之后错误率下来了但是有用户反馈数据不一致。我慌了赶紧看日志、看监控、看链路追踪。最后发现回滚的时候K8S是先创建新Pod再删除旧Pod的滚动更新策略。那10%灰度的Pod虽然被回滚了但已经处理了一部分用户请求这些请求触发的数据变更在新版本里有特殊处理逻辑他们改的小功能回滚之后这部分数据就出问题了。教训任何发版都要有回滚预案。这次幸亏灰度比例小要是全量发布后果不堪设想。灰度发布要多观察一会儿。我们只观察了10分钟就全量了有些问题在长时间运行后才会暴露。开发说小改动也要走完整测试流程。别问问就是被坑过。后来我们调整了发布流程灰度发布最低观察30分钟配置回滚时自动保留新Pod数据快照重要业务必须蓝绿发布。流程虽然复杂了但再没出过类似的事故。入门到进阶你还需要学这些K8S入门之后往哪些方向深入我列几个我们生产上用得最多的Helm包管理工具必须学。手写YAML文件管理少量服务还行服务一多就乱套了。Helm相当于K8S的软件包管理器能让你像apt、yum一样管理K8S应用。我们生产上所有服务都用Helm管理模板统一配置抽离省了大量重复劳动。ConfigMap和Secret是基本功。配置和代码分离是基本操作。ConfigMap存普通配置Secret存敏感信息密码、token等。注意Secret默认是base64编码的不是加密的敏感信息一定要开启加密存储。**持久化存储PV/PVC**也得懂。Pod里的数据是临时的Pod一删数据就没了。有状态服务数据库、文件存储需要持久化存储。我们用的是云厂商提供的块存储CSI插件PVC声明存储需求K8S自动创建PV。**自动扩缩容HPA/VPA**这个对业务很有用。HPAHorizontal Pod Autoscaler根据CPU、内存或者自定义指标自动调整Pod数量。VPAVertical Pod Autoscaler自动调整Pod的资源配置。这两个配合用效果更佳。**监控和日志Prometheus Grafana ELK**是生产必备。生产环境没有监控就是裸奔。Prometheus采集指标Grafana做可视化ELK或者Loki做日志聚合。我们自建了完整的监控告警体系每个服务上线必须接入监控否则不允许上线。**服务网格Istio**等有基础了再看。微服务多了之后服务间调用关系复杂流量管理、熔断限流、链路追踪这些需求自然就出来了。Istio就是解决这些问题的。不过Istio复杂度比较高建议有一定K8S基础之后再学习。给新手的几条掏心窝子的话别光看文档一定要动手。K8S是个实操性很强的东西光看文档是学不会的。自己搭个环境从部署一个Nginx开始慢慢深入遇到问题就去查、去解决这个过程比看十遍文档都管用。先会用再懂原理。很多人陷入了一个误区非要搞懂K8S每个组件的原理才开始用。兄弟先把集群搭起来把服务跑起来再回头看原理事半功倍。我们公司新来的运维都是先培训基本操作再讲原理。生产环境慎之又慎。学习环境随便折腾删库也没事。生产环境每一个操作都要三思而后行。我们生产操作都有严格的审批流程重要操作要双人复核。多看官方文档多逛社区。K8S官方文档kubernetes.io是最权威的学习资料遇到问题先查文档。社区推荐CNCF、Stack Overflow、GitHub Issues。加入一个学习社群。一个人学容易放弃找几个志同道合的兄弟一起学互相分享经验能走得更远。好了今天的分享就到这里。这篇文章涵盖了我从生产事故中总结出来的K8S核心概念、环境搭建、部署流程、真实案例以及后续学习方向。K8S这个东西会了不难难了不会。关键是要迈出第一步先把环境搭起来把第一个Pod跑起来。跑起来了你就有信心继续深入了。如果觉得这篇文章对你有帮助欢迎点赞、在看、转发三连支持一波。你的支持是我持续创作的最大动力后续会持续分享更多运维干货、生产实战经验、各种踩坑指南。咱们一起在运维这条路上走得更远、更稳。