这是一个前端 第一次涉及到集群 可能有很多不成熟的地方 也走了很多弯路 这篇就是现总结下目前成功部署需要注意的 

本文的环境是使用阿里云ACK托管集群,项目结构是ecs中台管理器,ecs前端+mongodb数据库,集群中目前暂时一个节点服务器 后台服务集群

基本环境搭建:

中台连接集群,~/.kube/config 下面配置文件 单集群 (如果后期要多集群切换的话 --kubeConfig指定配置文件切换集群 或者其他方案 这个后续研究~)

安全组配置 :

集群的安全组入方向开启VPC内网 6443 和 中台管理器内网IP 6443

前置条件:

中台服务器 集群 集群节点需要在同一个VPC下面 集群节点添加到集群中 需要在被添加的节点服务器上 运行云厂商命令 成功后 使用kubelet 查看 

基本上查看当前集群 服务器节点运行 和 节点服务器是否正常

kubectl get nodes -o wide 查看集群下所有服务器节点的状态
kubectl get pods -n kube-system -o wide 查看集群下核心组件的状态 核心组件一般都在kube-system 下面
terway网络插件的状态
kubectl get pods -n kube-system -l app=terway-eniip
查看 Terway DaemonSet 状态
kubectl get ds -n kube-system terway-eniip
部署结构 :

1. 后端sh自动化脚本打包镜像 推送ACR镜像服务地址 需要在ACR里提前建好命名空间和镜像仓库 并注意推送的时候写好版本号 可以在sh中使用变量${version} 每次执行时 动态传入变量 sh xxx.sh 版本号

后续更新部署的时候 sh更新版本号  ACR控制台看到新版本镜像 

中台管理器运行  滚动部署

kubectl set image deployment/你的部署名 你的容器名=新镜像地址:新版本 -n 你的命名空间
kubectl rollout status deployment/你的部署名 -n 你的命名空间 查看当前滚动更新的状态

2. 后端集群部署的deploy +svc 里 连接 ACR地址 要注意 个人版的ACR 拉取镜像 最好配置VPC内网地址 

业务连通:
1. 集群需要访问外部服务 mongodb

实际链路:流量走向 pod ------->节点 -----------> VPC------------>目标ecs

mongodb安全组入方向

1)放行集群pod 交换机网段

2)VPC内网网段

并且要在worker节点上配置好 addroute mongodb 内网ip via VPC子网默认网关

安全组是为了开启mongodb接受访问的入口

addroute增加路由表 是因为pod访问外部服务terway 网络 将worker配置eni 走策略路由 但是外部的内网ip不在路由表里 需要在pod-->worker对应的路由表下

 kubectl get pods -o wide -n 查看pod-ip

ip rule show 查看每个流量对应的路由表 (根据当前的pod ip找到对应路由表)

ip route show table [] 查看指定的路由表

同时也要增加安全组配置 mongod服务器 入方向 允许  terway默认子网网关的访问  pod虚拟交换机的ipv4网段 如果有多个虚拟交换机需要配置多条  

# 查看 Terway ConfigMap
kubectl describe cm -n kube-system eni-config 可以查看下面的vswitches字段 交换机id 根据交换机id 查看pod网段 

后期就算replicas设置成多个 pod ip依然会在网段内

策略路由时为了告诉pod 流量从哪块网卡发出 

放行mongodb的接受通路

2. 外部ecs服务器访问pod内部服务

请求的链路:

前端-》默认网关-》VPC网络-》worker节点-》kube-proxy--》pod节点

外部到cluster ip 关键节点

VPC路由表里是否有 集群 service CIDR  下一跳 worker ecs节点的路由 (因为集群cluster ip在 service CIDR网段里 外部访问cluster ip -------------->worker ) 将访问集群的流量直接转发worker通路 是为了打通实际流量走的通路 明确访问集群的走worker ( 为什么pod访问外部不需要 因为pod访问外部的ecs ecs ip是具体存在的ip  terway知道通路在哪 外部访问集群 cluster ip事是虚拟ip地址 再service CIDR网关范围内 所以需要通过路由表指定流量走向 请求到目标为service CIDR的 就直接请求到worker ecs ip 并且目前使用的cluster ip模式 这样处理是正确的 关于网络暴露模式请见下文 )

排查外部访问集群内部pod 走不通 可以根据下面几个方向:

1. 排查集群内部的网络是否正常

kube-proxy组件是否正常运行 服务分发 将cluster-ip 转为pod-ip 到达pod内部

iptables-save -t nat | grep 【pod-ip】 如果返回为空 说明流量规则没有走到pod kube-proxy运行不正常 则重启kube-proxy组件

pod-ip是 kubectl get pods -o wide -n [命名空间] 查看

打通前端出方向--》集群 cluster ip cluster ip只要不重启service 就不变

查看worker节点到pod的通路

ip route show table 1004 | grep service 网段 查看 是否有service网段到默认网关的规则 一般是Terway CNI 组件自动生成的 

“去往 192.168.0.0/16(Service 网段,Pod IP 属于此范围)的流量,从 eth0 网卡发出,下一跳发给网关 172.23.239.253。”

kube-proxy不是用于外部访问集群内部的 而是用于pod之间的访问 比如一个pod服务访问另一个pod上的服务 这个后期将mongodb迁移到集群内部的时候在进行详细分析

2.集群入方向《--------前端 内网ip

排查方向:抓包工具tcpdump的妙用

前端访问集群

可以在前端执行telnet请求 前端进行 抓包 如果有包 说明前端出方向正常

sudo tcpdump -i eth0 host cluster ip and port 3300 -n

在worker节点抓包 

抓service ip的包 看请求是否到达了worker节点

抓pod ip的包 看请求是否kube-proxy转发正常 

集群访问前端

pod 内部 nc -zt 请求 

worker节点 tcpdump -i eth0 抓包

结果排查:1.没输出则服务没到worker VPC路由下一跳设置 或者 集群出方向安全组

2.只有SYN包 mongodb服务问题 没启动或者安全组入方向拦截

3. route unreachable 路由策略表问题

3.pod之前的相互访问

不能在策略路由里设置pod ip  via 默认网关 需要 pod ip 直连

ip neigh show查看ARP表是否正常 即 pod解析为mac地址是否正常

pod之间的访问主要通过veth 对于terway网络模式 如果pod之间访问不通 查看 pod内部的ip route 表  访问podip 是否通过指定的veth地址 而不是 eth0的默认网卡 而且得注意不能配置pod网段 via eth0导致访问的流量会批量错误处理 目前的方案是通过 configMap+daemonSet daemonSet会在worker节点启动的时候执行 定时任务自动刷新configMap 

daemonSet里配置指定configmap

volumes:

- name: pod-info

configMap:

  name: backend-pod-info

自动读取后端pod 获取pod 对应的veth 将 podip via veth 写入路由表 

ip route replace $POD_IP dev $veth table 1003 2>/dev/null

ip route replace $POD_IP dev $veth table 1004 2>/dev/null

ip neight show获取veth

目前 我mongodb部署的是headless + statefulSet(有状态应用)返回的是podIp 可以直接通过podIp访问或者是 podName?.[serviceName].[spaceName].svc.cluster.local 访问 如果后期想要以多副本 则会变成 mongodb-0 mongodb-1... 具体配置文件和前端,后端访问方法请见我另一篇文章 clusterIp 与 statefulSet+headless-CSDN博客

排查pod与pod间的通信问题也可以通过抓包工具tcpdump 抓请求podip的包 抓被请求的目标podip的包 看流量端在哪一步

关于网络暴露模式于后期维护

网络暴露模式规定的是如何让外部访问节点的服务

cluster ip

流量路径:

   客户端 → VPC 路由 → Worker 节点 (目标 IP 仍是 ClusterIP) → Pod    

目前使用的是cluster ip 即流量转发到指定的一个worker 在VPC路由里设置 下一跳到worker ip 即使后期多个replicas 也可以通过这种方式 安全组也不用调整 因为是流量-----》worker ----->kube-proxy分发 pod节点 所以入方向还是前端的ecs mongodb入方向还是pod网段 

loadBalancer 

流量路径

客户端 负载均衡 worker节点 pod

   客户端 → 负载均衡器 → Worker 节点 (目标 IP 已是节点 IP) → Pod    

所以不需要像cluster ip模式一样在 VPC路由里面配置service cidr下一跳指定worker节点 因为负载均衡已经自动分发到worker节点了

使用于多个worker节点 在集群入方向的安全组设置 原本设置的前端ecs 必须改为worker节点的ip 因为是通过外部负载均衡转发到worker 安全组校验的worker是否可以接受指定的外部流量 可以是worker 节点每个具体ip 或者整个VPC网段 因为loadBalancer安全组校验的是目标ip 当然从外部到worker worker到kube-proxy分配pod 有可能会分配到一个pod 配置 podAntiAffinity 防止挤在一个pod   sessionAffinity: ClientIP会话保持配置 反亲和性配置??

nodePort 

nodeip直连 安全组也是所有worker ip 负载均衡需要手动配置 可以在nginx转发里配 或者openresty lua脚本配置 也就是说  nodePort是到worker的直连 

cluster ip  service CIDR pod Ip 概念使用场景区分

cluster ip 是每次在apply service时 在 service CIDR范围内生成的IP  用于 集群外部 访问 集群  的地址 比如 前端访问后端集群 nginx配置的地址就是 cluster ip的地址

service CIDR是所有 cluster ip的段  所以用于在VPC路由里面设置下一跳 对流量走向进行统一约束

pod ip是每一个pod节点的ip  在pod 访问外部服务的时候 设置安全组使用 但是pod ip 每次随机生成的 不能直接设置pod ip 需要拓宽到pod 网段 即上面提到的交换机所在的网段 

关于滚动更新部署

当前项目的应用场景为,后端项目再ecs服务器上,需要每次推送到远程镜像库,并再另一个中台服务器上面部署集群,之前我们通过sh自动化脚本部署,现在再自动化脚本基础上,不是直接run运行镜像,而是再  tag push推送远程镜像结束后 ssh登录远程的中台服务器set image 更新集群镜像,rollout等待更新部署完成,并根据当前运行的最新的pod导出纯净 (不包含运行时参数的配置文件 保证集群镜像版本和配置文件的镜像版本同步 )导出文件直接覆盖原有的配置文件 即 apply -f的配置文件

配置文件更新的生效验证 

1.通过 grep image获取最新的镜像版本
kubectl get deployment vue3-office-server-deploy -n backend-space -o yaml | grep image

2.确认本地配置文件的镜像版本
grep image back-deploy.yaml

具体导出代码如下:

kubectl get deployment vue3-office-server-deploy -n backend-space -o yaml | \
  yq eval 'del(.metadata.annotations."kubectl.kubernetes.io/last-applied-configuration")' - | \
  yq eval 'del(.metadata.creationTimestamp)' - | \
  yq eval 'del(.metadata.generation)' - | \
  yq eval 'del(.metadata.resourceVersion)' - | \
  yq eval 'del(.metadata.uid)' - | \
  yq eval 'del(.status)' - > backend-deploy-clean.yaml

经过实践,通过yq识别去除 运行时配置导出的配置文件格式正确

关于集群配置文件 pod service statefulSet 等,请见笔者另一篇文章k8s配置文件-CSDN博客


未完。。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐