分类 运维日寄 下的文章

在写一个自动化处理工具,用zipfile解压文件的时候,发现解压出来的中文文件名全变成了乱码
windows中文默认编码gbk,与zipfile默认cp437冲突导致的
解决方案:
python3.11版本以下:
修改zipfile源码

if flags & 0x800:
                # UTF-8 file names extension
                filename = filename.decode('utf-8')
            else:
                # Historical ZIP filename encoding
                filename = filename.decode('cp437')
                filename = filename.encode('cp437').decode('gbk') #第一处


if fheader[_FH_GENERAL_PURPOSE_FLAG_BITS] & 0x800:
                # UTF-8 filename
                fname_str = fname.decode("utf-8")
            else:
                fname_str = fname.decode("cp437")
                fname_str = fname_str.encode("cp437").decode('gbk') #第二处

3.11以上
zipfile.ZipFile(file_path, 'r',metadata_encoding='gbk')

参考https://www.jb51.net/python/2957879by.htm

今天带两个供应商干活,以这俩人的踩坑记录把dockfile初学者可能会犯的错误罗举一下

  1. from,一定要写基础镜像(没错就是这么难绷
  2. run后面不要使用交互式的命令,如vim\不加-y的yum
  3. copy,复制的时候注意dockerfile和目标文件的层级关系,最好同级
  4. copy,如果想复制一整个文件夹,包括他自己本身,那么目的目录应该在结尾以这个文件夹的文件名为结尾,不然默认只复制文件夹里面的东西
  5. cmd,cmd是镜像启动的后执行的命令,把运行服务的命令写在run里面是没用的
  6. cmd或者run的时候要注意对应文件的权限问题,以及所使用的shell的区别
  7. 容器判断该容器是否结束退出,是通过cmd是否执行并打印0退出来判断的,不是通过后台是否有进程来决定的。如果cmd用java跑个程序那还好,如果是通过一个脚本来启动一个java程序,那么只要这个脚本被成功运行并退出了,哪怕java程序还在运行,容器也会觉得这个容器已经结束了。所以如果是通过脚本来启动服务,最好后面跟个死循环的命令,随你tail -f或者sleep睡个天荒地老都行
  8. 在cicd跑的时候注意代码文件有没有传全
  9. 最好把run一条用&&拼凑写完,run越多镜像的层数越多,构建出来的镜像越大
  10. 哪怕切了目录,也得用绝对路径

describe k8s pod的时候,会看到一行QoS Class,这玩意对于k8s里的应用,就好像oom_score_adj之于linux应用,决定着当资源紧张的时候,pod被驱逐的优先顺序
k8s不想oomscore一样可以直接通过调节数值来定义,他分成固定的三类:
Guaranteed
Burstable
BestEffort
决定一个应用的QoS Class是哪一类的,是他们对资源限制的配置,当你给应用配置了cpu及内存的request和limit并且两者值相等的时候,他的种类为Guaranteed,当你至少配置了一项cpu或者内存的request的时候,他的种类为Burstable,当你什么都没有配置的时候,他的种类为BestEffort

这三种类型的容器受到的待遇天差地别,他们的cgroupsPath不同,当然还有最重要的,他们初始化的oomscoreadj也完全不同,Guaranteed可能是-998,Burstable可能是998,BestEffort就可能是1000了

还记得之前那个悄悄给自己应用取消掉了资源限制,以为这样可以为所欲为的开发的例子,java+按比例吃资源启动+容器无资源上限,得到的结果就是他的应用不停的被缺少内存资源的宿主机驱逐,属于是自作聪明了

参考:https://zhuanlan.zhihu.com/p/126532976?utm_id=0

ps -ef | grep找出应用pid
echo -1000 > /proc/$pid/oom_score_adj
oom_score_adj是内核给应用打的一个分数,区间在-1000~1000,越大越优先被杀,-1000代表禁止oom杀该进程,可以用来保护一些重要的程序,比如ssh,免得服务挂了后连登录都登不进去
当发生oom的时候,dmesg打印出的消息里面可以看到被杀的进程的oom分数

核心进程:咦,内核,你手里拿的什么
内核(举起oom):是一会要用到的神奇妙妙工具

供应商反应测试环境里面自己的java应用频繁重启,排查之
kubectl describe pod,看了下重启了4次,Terminated,退出code 137
看到137基本心里有数了,登录top看了下,java进程吃了7个g内存,free看了下宿主机可用内存所剩无几,ps -ef看下java启动命令,-XX后面跟着一串按比例吃资源的参数
查看yaml,果然没设置资源上限,java进程直接按宿主条件去要资源,后面又持续新增内存要求,宿主机内存不够把他给砍了
配置4g资源上限后重启,对比监控数据可以看到,原本无上限启动后就占了5g,设置上限后重启应用只占了1g多,效果明显
使用java -XX:+PrintFlagsFinal -version | grep HeapSize查看堆内存情况,JVM 根据系统的内存总量,来自动管理堆内存,不明确配置堆内存的默认限制是物理内存的四分之一,这里看到MaxHeapSize换算下来是1g,正好是我们设置的4g的四分之一
ps:看到案例说容器可能会看不到外部设置的资源上限,不清楚这里是不是原生和云厂商平台的区别,如果出现这种情况,用JAVA_OPTS=’-Xmx512m -Xms512m’这个系统变量进行设置就行了