随着K8s在生产和测试环境中用的越来越多,对安全性的关注也会越来越多,为了保证业务平稳运行,平台安全可控,可以参考如下集群应用规范,从最佳性能,最小权限,最大可用性等方面保证k8s集群和应用的服务质量。

一、镜像制作规范

1、基础镜像使用统一标准的基础镜像;

2、时区统一使用Asia/Shanghai时区;

3、容器内使用非root用户运行主进程;

4、容器内只能运行一个主进程,禁止使用systemd管理进程;

5、镜像内不能存储凭据密钥等敏感文件;

6、镜像内不能存储大量运行时临时文件,比如日志、调试文件;

7、应用镜像不可超过80层;

8、基础镜像以entrypoint执行结束;业务镜像以CMD结束(不建议以CMD[shellscript]结束);

二、应用部署  

1、必须使用规定的namespace部署服务

除特殊情况,不要占用defaultkube-system的namepace;

2、配置容器资源限额

根据容器运行时所需要的资源,对CPU内存设置资源上下限,即request和limit;

设置建议:

  • 正式环境可以将request和limit设置一样,开发测试环境,可以将request远小于limit;
  • 当配置了limitRange和resourceQuota,可以限制podlimit大小和namespace下的全部大小;

3、探针配置

正常应用服务需要配置liveness探针、readiness探针、startup三种探针,对于liveness探针、readiness探针是必须配置的,可以保证应用服务的健康性,辅助提高应用服务的高可用;

注:

  • liveness探针需要谨慎使用;
  • readiness探针首选http探测,尽量避免使用tcp探测;

4、configmap挂载

       使用configmap挂载应用的静态配置,动态配置需要应用服务自行管理,可以采用配置中心等方式来实现;

5、日志持久化配置

需要对日志进行持久化配置,并且可以制定规范来确保日志的保存路径,方便日志采集和查看,而且需要对日志进行定期滚动切割和删除,日志保留期限可以根据需求和安全规范自行确定;

6、集群内域名访问

集群内服务互相调用,需要使用{服务名}.{namespace}.svc.cluster.local:{服务内部端口}的方式,尽量不要使用IP+nodeport的方式;

7、设置多副本

无状态的应用服务设置副本数必须大于1,保证应用服务的高可用,并且合理使用调度策略,如反亲和性配置,确保应用服务调度都不落在同一个节点上,从而实现应用服务的高可用;

8、固定对外端口,不依赖主机名

标准的应用服务只提供一个对外的端口,有些应用服务在运行过程中可能产生一些服务端口,有可能是随机产生的,从而给管理带来不便,所以需要尽量避免使用主机名和服务端口信息绑定访问,如果必须使用,可以通过环境变量HOST和POR获取相关信息;

9、优雅关闭服务

到了微服务中,网关会把流量分配给每个Pod节点上,比如上线更新Pod时,如果直接将Pod杀死,那这部分流量就无法得到正确处理,会影响部分用户,通常网关或者注册中心将服务保持一个心跳,过了心跳超时之后会自动摘除服务,但是服务超时时间可能是30秒也可能是60秒,虽然不会影响系统,但会产生用户轻微抖动。

如果在停止前执行命令,通知网关或者注册中心这台主机进行下线,那么注册中心就会标记这台主机已经下线,不进行流量转发,用户不会有任何影响,这就是优雅停止,将滚动更新影响最小化。

具体配置可以参考下面说明:

(1)为容器内的进程设置正常关闭;

(2)添加preStopHook

(3)修改终止GracePeriodSeconds

具体可以参考下图的停止时间线

10、服务接口之间调用使用TCP和HTTP协议

服务之间调用如果使用非标准协议进行交互,可能无法使用负载均衡器进行有效负载,如果使用TCP和HTTP协议,就可以使用负载均衡器进行有效负载。

11、配置restartpolicy

由于容器内不建议使用systemd或者systemctl之类的工具来管理服务,而容器内的主进程都是应用服务进程,可以通过设置pod的restartpolicy来控制pod的失败行为,pod的重启策略包括Always、OnFailure、Never,默认是Always。

12、相关安全配置

(1)运行特权容器

Privileged-决定是否Pod中的某容器可以启用特权模式。默认情况下,容器是不可以访问宿主上的任何设备的,不过一个“privileged(特权的)”容器则被授权访问宿主上所有设备。这种容器几乎享有宿主上运行的进程的所有访问权限。对于需要使用Linux(如操控网络堆栈和访问设备)的容器而言是有用的。

下图显示情况不建议使用

(2)hostPID和hostIPC参数使用,会对主机的服务产生影响;

(3)hostNetwork参数,使用宿主机的network命名空间,会对主机产生影响;

13、对于Java类项目,需要配置-Xms、-Xmx

对于java类的应用,jdk9以下的镜像,JVM人机工程学会设置“最大堆大小”为物理内存的1/4。由于JVM不知道它在一个容器内执行,如果不设置xms,xmx限制,容器内jvm会占用宿主机25%的内存。如果容器这时设置了配额小于宿主机25%的内存,容器会持续报错起不来。如果配额设置大,也会在jvm占用较多非堆内存超过配额后被K8s杀死。

建议:通过java应用获取podENV(INI)配置,支持堆大小、gc释放时间、PodIP等等有效配置

三、应用优化建议  

1、应用服务高可用

应用服务应该支持高可用,单个pod的故障/迁移/升级不影响用户业务。

2、精简镜像

可以使用最小化的基础镜像,减少镜像层数,清理镜像构建过程中的缓存文件,多阶段构建生成精简镜像。

3、合理使用镜像拉取策略

生产环境建议配置IfNotPresent策略,测试环境配置Always策略。

4、日志级别

生产环境建议使用等级为INFO,测试环境为DEBUG级别。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐