大致背景:
本人今天有一个需求要上线,于是部署了2个服务,因为公司用的是k8s+阿里云镜像,所以在公司的流程是部署完服务之后用生成的阿里云服务镜像地址去k8s管理平台直接替换对应服务的镜像地址,k8s部署完成即为完成上线。部署2个服务2个镜像地址,然后本人分别把2个服务去k8s管理平台去更换镜像地址的时候发现k8s一直运行不完,然后发现实际容器节点启动失败,报错原因是公司的阿里云镜像拉取失败,2个服务各自有2个节点,因为服务加了健康检查所以服务的另外一个容器节点没有被替换镜像地址(个人感觉是这样)即另外一个k8s节点没有被重启,因此线上的服务还是正常可以运行,即即使2个服务各自有一个容器没有启动成功,也不影响线上使用。重点来了,这个项目的线上前端服务只有一个节点,而我的同事不小心把这个服务的容器节点重启了,这也直接导致k8s的前端服务容器节点在运行时拉取镜像失败,所以k8s容器节点启动失败,前端服务直接宕机,使用系统的人直接登录不上系统,线上马上开始在群里反馈。
临时解决思路:
因为后来询问公司网络那边的人得到的结论是,装k8s节点的那几台linux服务器可能被人更改过网络策略,导致这几台装k8s的服务器拉取不了公司的阿里云镜像地址(具体原因可能还得询问一下)。但是这个人现在联系不上,最快也得明天,所以我就提出了把前端服务的镜像文件从阿里云下载下来然后上传到前端服务的k8s节点服务器,再把k8s部署容器的拉取镜像策略改成从本地拉取试试,开始我小组长说没弄过,本人实际也没弄过,小组长他们也没咋搭理我,但是后来我那个把前端服务容器节点重启的同事应该是悄悄弄了,然后我就跟着协助弄了下,最终成功。
大致流程:
因为实际命令不是本人执行的,所以我也只能记下一个大概步骤,如下是按照k8s单机节点执行的,如果一个服务多个k8s节点不知道行不行
环境:
前端服务、linux服务器、k8s单机节点、linux服务器上没装docker
1.把阿里云镜像上的镜像地址文件下载下来放到不能拉取阿里云镜像地址的服务所在的k8s节点的linux服务器上。
以下方法任取一种:
方法1:假如有linux服务器可以拉取阿里云镜像。首先要在可以连接阿里云镜像的服务器上登录阿里云镜像仓库,再把镜像地址对应镜像文件通过docker pull或者nerdctl pull拉取下来,然后把镜像打成tar包再通过服务器之间的scp命令把打成tar包的镜像文件复制到不能连接阿里云镜像的服务器上。
(PS:我记得当时除了前端服务+我上线的2个服务的某个节点不能拉取阿里云镜像之外,还剩一台服务器在登录上服务器了之后是可以正常拉取阿里云镜像的,所以我同事当时应该是用可以拉取镜像的服务器把已经宕机的前端服务的镜像拉取下来了)
方法2:如果本地windows电脑装了docker,可以在本地登录阿里云镜像仓库,然后使用docker命令把镜像地址对应镜像文件拉取到本地并打成tar包。然后再用xshell+xftp工具(其他工具也可)登录拉取不了阿里云镜像地址的linux服务器,把tar包镜像文件上传到linux服务器
2.在不能拉取阿里云镜像的k8s所在的linux服务器上把传输过来的tar包镜像解压到k8s自己的镜像空间内,解压完成后查询k8自己镜像空间内是否有该指定镜像
3.修改k8s空运行产生的yaml文件中的镜像拉取策略为Never,即改成从本地拉取,并核对好yaml文件中的拉取镜像的名称和实际步骤2中的镜像名称相同
4.登录k8s管理平台重新部署容器或者在linux服务器上直接用kubectl命令重新运行容器服务
具体流程中的命令如下:
(步骤1中使用的是方法1即在可拉取阿里云镜像的linux服务器上执行命令。因为这台linux服务器上没安装docker所以不能使用docker命令拉取,转而使用nerdctl,有安装docker可以使用docker命令,具体问题具体分析)
1. 登录阿里云镜像仓库 命令格式和 Docker 一致,替换仓库域名和账号: bash nerdctl login [阿里云镜像仓库域名] -u [阿里云账号] 输入密码后提示 Login Succeeded 即登录成功。 2. 拉取镜像 直接使用 pull 命令,传入完整的阿里云镜像地址: bash nerdctl pull [完整阿里云镜像地址] 示例: bash nerdctl pull registry.cn-hangzhou.aliyuncs.com/my-namespace/my-service:v1.0 3. 导出镜像为 tar 包(用于迁移) 若需要将镜像导出到无网服务器,命令和 Docker 也一致: bash nerdctl save -o [镜像包名].tar [完整阿里云镜像地址] 示例: bash docker save -o my-service.tar registry.cn-hangzhou.aliyuncs.com/my-namespace/my-service:v1.0 4. 传输 tar 包到目标 Linux 服务器 可通过 scp 命令直接传输(替换对应参数): bash scp [自定义镜像包名].tar [服务器用户名]@[服务器IP]:[目标存放路径] 示例: bash scp my-service.tar root@192.168.1.100:/home 5.将镜像导入 k8s.io 命名空间 bash # 导入到k8s.io命名空间 nerdctl -n k8s.io images load -i my-service.tar 6. 查看 k8s.io 命名空间下的镜像 执行命令确认镜像是否存在: bash nerdctl -n k8s.io images ls //如果执行命令后没有指定镜像地址的镜像,说明k8s镜像空间内没有该镜像,那启动容器一定启动不成功,如果有了该镜像看步骤7 7. 核对 YAML 配置,修改yaml文件拉取镜像策略为Never 确保 image 字段与 nerdctl -n k8s.io images ls 显示的标签完全一致,且 imagePullPolicy: Never 配置在 container 层级。 8. 重建 Pod //也可以不用执行步骤8,因为有k8s管理平台,当把前7个步骤执行完之后直接去k8s管理平台重启控制器就行 bash kubectl delete pod <pod-name> kubectl apply -f your-deploy.yaml如上命令所示,实际在执行了前7个步骤之后,k8s中的宕机的前端服务已经正常运行了。
排查思路:
因此在遇到k8s部署容器服务拉取阿里云镜像拉取不下来的时候先确定k8s部署执行的yaml文件中的镜像名称是否和打包服务生成的镜像名称一致,如果一致那一版就是网络问题,即是否对镜像地址的域名访问有限制,这个要找网络那边的人。
另:在把阿里云镜像文件放到linux服务器本地时,开始直接重新在k8s管理平台部署容器镜像发现还是找不到本地镜像,后来才知道k8s运行的是自己镜像空间内的镜像,如果k8s自己镜像空间内的镜像没有运行的镜像话也是没有用的,所以如果k8s部署找不到本地镜像先执行nerdctl -n k8s.io images ls命令去查看k8s镜像空间内有没有自己所需要的镜像,如果没有去解压tar包的镜像文件到k8s镜像空间内
大体思路如上,如果有命令有问题大家再自行去搜索一下。。。。。。