三十一、K8s供应链安全2 - 镜像的检测及优化与yaml文件安全

一、镜像的检测

镜像中包含程序,其中也可能包含漏洞,所以我们需要检查镜像中是否存在漏洞。

首先,准备一台装有docker的设备,提前拉取nginx和redis镜像做检查。

docker pull nginx
docker pull redis

接着下载Trivy这个工具。Trivy是一个简单而全面的扫描器,用于检测容器镜像、文件系统和 Git 存储库中的漏洞,以及配置问题。 Trivy检测操作系统包(Alpine、RHEL、CentOS 等)和特定语言包(Bundler、Composer、npm、yarn 等)的漏洞。此外,Trivy扫描基础设施即代码 (IaC) 文件,例如 Terraform、Dockerfile 和 Kubernetes,以检测可能使我们的部署面临攻击风险的潜在配置问题。 Trivy易于使用。只需安装二进制文件,我们就可以开始扫描了。安装步骤具体请参考:https://aquasecurity.github.io/trivy/v0.18.3/installation/
在这里插入图片描述
这里以Centos宿主机为例子。将仓库设置添加到/etc/yum.repos.d

[trivy]
name=Trivy repository
baseurl=https://aquasecurity.github.io/trivy-repo/rpm/releases/$releasever/$basearch/
gpgcheck=0
enabled=1

安装trivy:

yum -y update
yum -y install trivy

Trivy工作的原理如下:读取互联网上CVE(Common Vulnerabilities and Exposures)库,CVE中记录了漏洞的信息。然后Trivy会下载这些信息到本地数据库中。然后当我们检测时,Trivy会读取其中的信息,并且与本地的数据库进行对比,从而判断出此程序是否存在漏洞。接下来,我们分别使用trivy检查下载的两个镜像:

首先检查nginx镜像:

trivy image nginx

部分截图,可以看到其中存在83个low risk漏洞,6个medium risk,6个high risk和4个critical的漏洞:
在这里插入图片描述
检查redis镜像:

trivy image redis

高危的漏洞不多,主要是56个low risk的漏洞。那么可以看到,redis相对于nginx,漏洞会少一些。
在这里插入图片描述
我们后续可以根据检测的结果,决定哪些漏洞需要进行修补。

二、DockerFile的优化

DcokerFileke可以帮助我们在原始镜像上进行自定义修改或者更新原有镜像。DockerFile的原理和语法请参考:官网文档https://docs.docker.com/develop/develop-images/dockerfile_best-practices/或总结的笔记https://blog.youkuaiyun.com/tushanpeipei/article/details/115837183

DockerFile的优化原则:越小越好、提高安全性。具体的方式有:

1.减少层数:
尽量减少镜像中的层数以确保它们的性能非常重要。添加了以下功能以减少此限制:只有指令RUN, COPY,ADD创建层。其他指令会创建临时中间镜像,并且不会增加构建的大小,也就是说多个命令放在一个RUN 里写,比多个RUN要小。

2.清理无用数据:
清理缓存可以有效减少镜像的大小。例如我们可以可以构建镜像是加上如下命令:

yum clean all && rm -rf /var/cache/yum/*

3.多阶段构建:
多阶段构建能够帮助我们大幅减少最终镜像的大小,而无需费力减少中间层和文件的数量。因为镜像是在构建过程的最后阶段构建的,所以我们可以通过利用构建缓存来最小化镜像层。例如,如果我们的构建包含多个层,可以将它们从更改较不频繁(以确保构建缓存可重用)到更改较频繁的排序:

  1. 安装构建应用程序所需的工具;
  2. 安装或更新库依赖项;
  3. 生成我们的应用程序。

Go 应用程序的 Dockerfile 可能如下所示:

# syntax=docker/dockerfile:1
FROM golang:1.16-alpine AS build

# Install tools required for project
# Run `docker build --no-cache .` to update dependencies
RUN apk add --no-cache git
RUN go get github.com/golang/dep/cmd/dep

# List project dependencies with Gopkg.toml and Gopkg.lock
# These layers are only re-built when Gopkg files are updated
COPY Gopkg.lock Gopkg.toml /go/src/project/
WORKDIR /go/src/project/
# Install library dependencies
RUN dep ensure -vendor-only

# Copy the entire project and build it
# This layer is rebuilt when a file changes in the project directory
COPY . /go/src/project/
RUN go build -o /bin/project

# This results in a single layer image
FROM scratch
COPY --from=build /bin/project /bin/project
ENTRYPOINT ["/bin/project"]
CMD ["--help"]

其中涉及到2个镜像的构建。我们将第一个临时镜像命名为build。最终镜像使用–from=build,从第一个临时的镜像中拷贝信息到本地目录。那么最终镜像其实就这由COPY创建的一层镜像。构建完成后,我们只需要删除第一个临时镜像即可。

4.利用构建缓存:
构建镜像时,Docker 会逐步执行 Dockerfile 中的指令,并按照指定的顺序执行每个指令。在检查每条指令时,Docker 会在其缓存中查找可以重用的现有镜像,而不是创建新的(重复)镜像。

对于 ADD 和 COPY 指令,检查镜像中文件的内容并计算每个文件的校验和。这些校验和不考虑文件的最后修改和最后访问时间。在缓存查找期间,校验和与现有镜像中的校验和进行比较。如果文件中的任何内容(例如内容和元数据)发生了更改,则缓存将失效。

除了 ADD 和 COPY 命令之外,缓存检查不会查看容器中的文件来确定缓存匹配。例如,在处理 RUN apt-get -y update 命令时,不会检查容器中更新的文件以确定是否存在缓存命中。在这种情况下,仅使用命令字符串本身来查找匹配项。

5.尽量避免使用root登录
保证容器运行所使用的权限不要超过其需要使用的需要。因此,我们需要创建一个新的用户,然后赋予它有限的权限。在构建镜像时,我们可以还有USER XXX指定默认使用什么用户。

6.不要安装多余的包
了减少复杂性、依赖性、文件大小和构建时间,避免安装额外或不必要的包。例如,我们不需要在数据库镜像中包含文本编辑器。

7.对多行参数进行排序
只要有可能,通过按字母数字顺序对多行参数进行排序来简化以后的更改。这有助于避免包重复并使列表更易于更新。这也使 PR 更易于阅读和审查。在反斜杠 (\) 前添加一个空格也有帮助。以下是来自 buildpack-deps 镜像的示例:

RUN apt-get update && apt-get install -y \
  bzr \
  cvs \
  git \
  mercurial \
  subversion \
  && rm -rf /var/lib/apt/lists/*

三、yaml文件安全

很多时候我们都以最简单的方式来应用yaml文件,而忽略了yaml文件中存在的很多安全设置,例如securityContext等。那么,如何检查我们的yaml文件是否安全?可以使用kubsec这个工具来帮助我们完成这个任务。下载地址:https://github.com/controlplaneio/kubesec/releases

下载适合自己的版本即可。我这里下载的是kubesec_linux_amd64.tar。在master设备上解压后,扫描如下的pod2.yaml文件:

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod2
  name: pod2
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: pod2
    resources: {}
    env:
    - name: aa
      value: xxx
    - name: bb
      value: '999'
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

扫描的命令:

./kubesec scan pod2.yaml

扫描结果:结果中给我们了很多相关的修改建议,例如在spec下添加ServiceAccountName字段可以严格控制kubernets API的访问。
在这里插入图片描述
我们可以按照它给的提示和实际的需求修改我们的yaml文件。

四、使用Secret拉取镜像

很多私有镜像仓库,都必须要求客户端登陆后才能拉取镜像,无法匿名拉取。所以在K8s中我们可以设置一个Secret,保存镜像仓库的账号和密码,例如:

kubectl create secret docker-registry mysec1(secret名称) --docker-server=x.x.x.x(仓库地址) --docker-username=yyy(仓库用户名) --docker-password=zzz(仓库密码)

然后再创建pod的yaml文件中使用此secret即可,例如:

root@vms71:~/yaml_sec# cat pod1.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod1
  name: pod1
spec:
  terminationGracePeriodSeconds: 0
  imagePullSecrets:
  - name: mysec1
  containers:
  - image: x.x.x.x/nginx
    imagePullPolicy: IfNotPresent
    name: pod1
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

仅需在原始的yaml文件中,与containers对其,添加如下参数即可:

  imagePullSecrets:
  - name: mysec1 # secret名称

这样设置的话,当我们使用此yaml文件创建pod时,如果pod本地不存在,则会使用secret中的账号密码登录到我们的私人仓库拉取镜像了。

整理资料来源:
《老段CKS课程》
trivy github:https://github.com/aquasecurity/trivy
DockerFile:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

<think>嗯,用户问能不能基于Kubernetes(k8s)搭建云原生平台。这个问题我需要详细回答,确保覆盖到关键点。首先,得确认用户对k8s和云原生的基本概念是否了解,可能需要先简要解释这两个术语。不过用户可能已经有一定基础,所以直接切入正题。 首先,应该明确回答:是的,可以基于k8s搭建云原生平台。接下来需要解释为什么k8s是云原生的核心。云原生的关键要素包括容器化、微服务、持续交付、动态调度等,而k8s作为容器编排工具,天然支持这些特性。可能需要分点说明k8s在云原生中的作用,比如容器编排、服务发现、自动扩缩容、声明式配置等。 然后,需要考虑搭建云原生平台的具体步骤。这部分需要结构化,可能分为几个步骤,比如容器化应用、部署k8s集群、配置网络和存储、集成CI/CD工具链、监控日志、服务网格、安全管理等。每个步骤需要简要说明,但不需要太深入,因为用户可能只需要一个概述。 另外,用户可能想知道这样做的好处,比如弹性伸缩、高可用性、资源利用率提升、快速迭代等。这部分可以作为优势部分单独列出,帮助用户理解价值。 同时,可能存在的挑战也需要提及,比如学习曲线陡峭、网络配置复杂、维护成本等,这样回答会更全面,让用户有心理准备。 最后,总结一下,强调k8s作为基石的重要性,并建议结合其他云原生技术,比如Prometheus、Istio、Jenkins等,构建完整的平台。可能还要提到一些云服务商的托管k8s服务,减轻运维压力。 需要检查是否符合之前的系统级指令:使用中文,数学公式正确(虽然这个问题可能用不上太多公式,但如果有的话要用$符号),结构清晰,分点说明。避免使用Markdown格式,所以用数字或项目符号的话要用文字描述,比如“第一步”,“其次”等。 现在组织语言,确保逻辑连贯,每个部分自然过渡。可能先回答“可以”,然后解释原因,接着步骤,优势,挑战,最后总结。这样用户能一步步理解如何实现以及注意事项。</think>可以,基于Kubernetes(k8s)搭建云原生平台是当前主流的解决方案。以下是具体说明: **1. 为什么选择k8s作为云原生基石** - 容器编排能力: 原生支持容器化应用的部署、调度和生命周期管理 - 声明式API: 通过yaml清单$f(x)=manifest\_file$定义基础设施状态 - 自动化运维: 内置滚动更新、自动修复、水平扩展等机制 - 云中立特性: 支持跨多云/混合云部署,避免供应商锁定 **2. 构建云原生平台的关键步骤** (1) 容器化改造 - 使用Docker将应用打包为标准化镜像$image:tag$ - 建立容器仓库(如Harbor)管理镜像版本 (2) 部署k8s集群 - 选择部署模式: 托管服务(EKS/GKE/AKS)或自建集群(kubeadm/kops) - 配置网络插件(Calico/Flannel)和存储方案(CSI驱动) (3) 集成关键组件 - 服务网格: Istio实现流量管理$traffic\_weight = [A:80%, B:20%]$ - CI/CD: ArgoCD实现GitOps持续部署 - 可观测性: Prometheus+Grafana监控指标,EFK日志体系 **3. 典型云原生技术栈** ``` +---------------+ | Serverless | +---------------+ | Service Mesh | +-------+-------+ | CI/CD Pipeline | +-------+-------+ | Kubernetes | +-------+-------+ | Container Engine| +---------------+ ``` **4. 优势挑战** ✓ 优势: - 弹性伸缩: 根据$QPS = \frac{requests}{second}$自动扩缩 - 故障自愈: Pod健康检查+自动重启机制 - 灰度发布: 通过Ingress实现金丝雀部署 ⚠️ 挑战: - 学习曲线: 需掌握etcd/API Server等核心组件原理 - 网络复杂性: CNI插件选择策略配置需要专业知识 - 安全加固: 需配置RBAC、Pod安全策略等 建议从中小规模集群开始实践,逐步构建完整的云原生生态。可参考CNCF技术全景图选择合适工具,初期推荐使用托管k8s服务降低运维复杂度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

格洛米爱学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值