文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

如何使用 Distroless 让你的容器更加安全

2024-12-03 02:45

关注
Photo by Michael Dziedzic on Unsplash

使用 Distroless 镜像来保护 Kubernetes 上的容器。

容器改变了我们看待技术基础设施的方式。这是我们运行应用程序方式的一次巨大飞跃。容器编排和云服务一起为我们提供了一种近乎无限规模的无缝扩展能力。

根据定义,容器应该包含 「应用程序」 及其 「运行时依赖项」。然而,在现实中,它们包含的远不止这些。标准容器基础映像包含标准 Linux 发行版中可以找到的包管理器、shell 和其他程序。

虽然这些都是构建容器镜像所必需的,但它们不应该成为最终镜像的一部分。例如,一旦你把包安装好了,就不再需要在容器中使用 apt 等包管理工具了。

这不仅使你的容器里充满了不必要的软件包和程序,而且还为网络罪犯提供了攻击特定程序漏洞的机会。

你应该始终了解容器运行时中存在什么,并且应该精确地限制其只包含应用程序所需的依赖项。

除了那些必要的,你不应该安装任何东西。一些领先的科技巨头,如谷歌,有多年在生产中运行容器的经验,已经采用了这种方法。

谷歌现在通过提供 Distroless 镜像向全世界开放这种能力。谷歌构建的这些镜像的目标是只包含你的应用程序及其依赖项,同时它们将没有常规 Linux 发行版的所有特性,包括 shell。

「这意味着虽然可以像以前一样运行应用程序的容器,但不能在容器运行的时候进入容器内」。这是一个重大的安全改进,因为你现在已经为黑客通过 shell 进入你的容器关上了大门。

Distroless 基础镜像

谷歌为大多数流行的编程语言和平台提供了 Distroless 的基础镜像。

以下基础镜像是正式发布的版本:

下面的基础镜像仍在实验阶段,不推荐用于生产环境:

构建 Distroless 镜像

谷歌在内部使用 Bazel 来构建容器映像,但是我们可以使用 Docker 来做同样的事情。关于使用 Distroless 镜像的一个有争议的问题是:当我们有一个 Distroless 镜像时,我们如何使用 Dockerfile 来构建我们的应用程序呢?

通常,Dockerfile 以一个标准的 OS 基础镜像开始,然后是创建适当的运行时构建所需执行的多个步骤。这包括包的安装,为此需要像 apt 或 yum 这样的包管理器。

有两种方法:

为了理解它是如何工作的,让我们使用多阶段构建流程进行一个实际操作练习。

必要条件

你需要具备以下内容:

GitHub 代码仓

作为实践练习,将 此代码仓 Fork 到你的 GitHub 帐号下,然后克隆 GitHub 代码仓并使用 cd 进入到项目目录下。

该代码仓包含一个 Python 的 Flask 应用程序,当你调用API时,该应用程序会响应 Hello World!。

app.py 文件如下所示:

  1. from flask import Flask 
  2.  
  3. app = Flask(__name__) 
  4.  
  5. @app.route("/"
  6. def hello(): 
  7.     return "Hello World!" 
  8.  
  9. if __name__ == '__main__'
  10.     app.run(host='0.0.0.0', debug=True

Dockerfile 包含两个阶段:

  1. FROM python:2.7-slim AS build 
  2. ADD . /app 
  3. WORKDIR /app 
  4. RUN pip install --upgrade pip 
  5. RUN pip install -r ./requirements.txt 
  6.  
  7. FROM gcr.io/distroless/python2.7 
  8. COPY --from=build /app /app 
  9. COPY --from=build /usr/local/lib/python2.7/site-packages /usr/local/lib/python2.7/site-packages 
  10. WORKDIR /app 
  11. ENV PYTHONPATH=/usr/local/lib/python2.7/site-packages 
  12. EXPOSE 5000 
  13. CMD ["app.py"

构建阶段:

Distroless 阶段:

由于 Disroless 镜像不包含 shell,所以应该在最后使用 CMD 指令。如果不这样做,Docker 将认为它是一个 shell CMD,并试图这样执行它,但这是不工作的。

构建镜像:

  1. $ docker build -t /flask-hello-world-distroless . 
  2. Sending build context to Docker daemon  95.74kB 
  3. Step 1/12 : FROM python:2.7-slim AS build 
  4.  ---> eeb27ee6b893 
  5. Step 2/12 : ADD . /app 
  6.  ---> a01dc81df193 
  7. Step 3/12 : WORKDIR /app 
  8.  ---> Running in 48ccf6b990e4 
  9. Removing intermediate container 48ccf6b990e4 
  10.  ---> 2e5e335be678 
  11. Step 4/12 : RUN pip install --upgrade pip 
  12.  ---> Running in 583be3d0b8cc 
  13. Collecting pip 
  14.   Downloading pip-20.1.1-py2.py3-none-any.whl (1.5 MB) 
  15. Installing collected packages: pip 
  16.   Attempting uninstall: pip 
  17.     Found existing installation: pip 20.0.2 
  18.     Uninstalling pip-20.0.2: 
  19.       Successfully uninstalled pip-20.0.2 
  20. Successfully installed pip-20.1.1 
  21. Removing intermediate container 583be3d0b8cc 
  22. ................................... 
  23. Successfully installed Jinja2-2.11.2 MarkupSafe-0.23 click-7.1.2 flask-1.1.2 itsdangerous-0.24 werkzeug-1.0.1 
  24. Removing intermediate container c4d00b1abf4a 
  25.  ---> 01cbadcc531f 
  26. Step 6/12 : FROM gcr.io/distroless/python2.7 
  27.  ---> 796952c43cc4 
  28. Step 7/12 : COPY --from=build /app /app 
  29.  ---> 92657682cdcc 
  30. Step 8/12 : COPY --from=build /usr/local/lib/python2.7/site-packages /usr/local/lib/python2.7/site-packages 
  31.  ---> faafd06edeac 
  32. Step 9/12 : WORKDIR /app 
  33.  ---> Running in 0cf545aa0e62 
  34. Removing intermediate container 0cf545aa0e62 
  35.  ---> 4c4af4333209 
  36. Step 10/12 : ENV PYTHONPATH=/usr/local/lib/python2.7/site-packages 
  37.  ---> Running in 681ae3cd51cc 
  38. Removing intermediate container 681ae3cd51cc 
  39.  ---> 564f48eff90a 
  40. Step 11/12 : EXPOSE 5000 
  41.  ---> Running in 7ff5c073d568 
  42. Removing intermediate container 7ff5c073d568 
  43.  ---> ccc3d211d295 
  44. Step 12/12 : CMD ["app.py"
  45.  ---> Running in 2b2c2f111423 
  46. Removing intermediate container 2b2c2f111423 
  47.  ---> 76d13d2f61cd 
  48. Successfully built 76d13d2f61cd 
  49. Successfully tagged /flask-hello-world-distroless:latest 

登录到 DockerHub 并推送镜像:

  1. docker login 
  2. docker push /flask-hello-world-distroless:latest 

登录到 DockerHub(或者你的私有镜像仓),你应该会看到容器镜像可以使用:

 

 

distroless-2

 

如果你看一下压缩后的大小,它只有 23.36 MB。如果你使用 slim 发行版作为基础镜像,它将占用 56 MB。

 

 

distroless-2

 

你已经减少了超过一半的容器占用空间。That’s amazing!

在 Kubernetes 中运行容器

为了测试构建是否有效,让我们在 Kubernetes 集群中运行容器。如果你没有 Kubernetes,你可以运行等价的 Docker 命令来做相同的活动,因为 Kubectl 和 Docker 命令是相似的。

我在代码仓中创建了一个 kubernetes.yaml 文件,该文件包含使用我们构建的镜像的 Deployment 和 负载均衡的 Service。

  1. --- 
  2. apiVersion: apps/v1 
  3. kind: Deployment 
  4. metadata: 
  5.   name: flask-deployment 
  6. spec: 
  7.   selector: 
  8.     matchLabels: 
  9.       app: flask 
  10.   replicas: 2 
  11.   template: 
  12.     metadata: 
  13.       labels: 
  14.         app: flask 
  15.     spec: 
  16.       containers: 
  17.       - name: flask 
  18.         image: bharamicrosystems/flask-hello-world-distroless 
  19.         ports: 
  20.         - containerPort: 5000 
  21. --- 
  22. apiVersion: v1 
  23. kind: Service 
  24. metadata: 
  25.   name: flask-service 
  26. spec: 
  27.   selector: 
  28.     app: flask 
  29.   ports: 
  30.     - port: 80 
  31.       targetPort: 5000 
  32.   type: LoadBalancer 

这是一个非常简单的设置。负载均衡器监听端口 80 并映射到目标端口 5000。这些 Pods 在默认的 5000 端口上监听 Flask 应用程序。

应用:

  1. $ kubectl apply -f kubernetes.yaml 
  2. deployment.apps/flask-deployment created 
  3. service/flask-service created 

我们查看一下所有的资源,看看我们已经创建了什么:

  1. $ kubectl get all 
  2. NAME                                    READY   STATUS    RESTARTS   AGE 
  3. pod/flask-deployment-576496558b-hnbxt   1/1     Running   0          47s 
  4. pod/flask-deployment-576496558b-hszpq   1/1     Running   0          73s 
  5.  
  6. NAME                    TYPE           CLUSTER-IP   EXTERNAL-IP      PORT(S)        AGE 
  7. service/flask-service   LoadBalancer   10.8.9.163   35.184.113.120   80:31357/TCP   86s 
  8. service/kubernetes      ClusterIP      10.8.0.1                443/TCP        26m 
  9.  
  10. NAME                               READY   UP-TO-DATE   AVAILABLE   AGE 
  11. deployment.apps/flask-deployment   2/2     2            2           88s 
  12.  
  13. NAME                                          DESIRED   CURRENT   READY   AGE 
  14. replicaset.apps/flask-deployment-576496558b   2         2         2       89s 

我们看到存在两个 Pods、一个 Deployment、一个带有外部 IP 的 LoadBalancer 服务和一个 ReplicaSet。

让我们访问应用程序:

  1. $ curl http://35.184.113.120 
  2. Hello World! 

我们得到了 Hello World!。这表明 Flask 应用程序在正常工作。

使用 Shell 对应用程序进行访问

正如我在引言中所描述的,Disroless 容器中没有 shell,因此不可能进入到容器内。然而,让我们试着在容器中执行 exec:

  1. $ kubectl exec -it flask-deployment-576496558b-hnbxt /bin/bash 
  2. OCI runtime exec failed: exec failed: container_linux.go:349: starting container process caused "exec: \"/bin/bash\": stat /bin/bash: no such file or directory": unknown 
  3. command terminated with exit code 126 

我们无法连接到容器上。

容器日志呢?如果拿不到容器日志,我们就失去了调试应用程序的方法。

让我们试着去拿日志:

  1. $ kubectl logs flask-deployment-576496558b-hnbxt 
  2.  * Running on http://0.0.0.0:5000/ 
  3.  * Restarting with reloader 
  4. 10.128.0.4 - - [31/May/2020 13:40:27] "GET / HTTP/1.1" 200 - 
  5. 10.128.0.3 - - [31/May/2020 13:42:01] "GET / HTTP/1.1" 200 - 

所以容器日志是可以被获取到的!

结论

使用 Distroless 作为基础镜像是一种令人兴奋的保护容器安全的方式。由于镜像小并且仅包含应用程序和依赖项,因此它为应用程序提供了最小的攻击面。它在更大程度上提高了应用程序的安全性,所以它是保护容器安全的好方法。

来源:今日头条内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯