IBM Cloud Docs
Container Registry 和 Vulnerability Advisor 工作流程教程

Container Registry 和 Vulnerability Advisor 工作流程教程

请使用本教程了解 IBM Cloud® Container Registry 和 Vulnerability Advisor 的基本功能。

这两个服务是预集成的,可在 IBM Cloud 中无缝地协同工作,其功能为容器用户提供了一个稳健而简单的工作流程。 可以使用这两个服务来存储容器映像,确保映像和 Kubernetes 集群的安全性,控制可用于部署到集群的映像,等等。

本教程提供的许多信息在文档的“如何操作”部分有更详细的介绍。 本教程将所有这些任务整合到一个工作流程中,帮助您使用 IBM Cloud Container Registry 和 Vulnerability Advisor。 要了解每个任务的更多信息,请单击相关链接。

目标

本教程有以下目标。

  • 了解 IBM Cloud Container Registry 和 Vulnerability Advisor 的核心功能。
  • 使用这些服务的功能创建工作流程。

使用的服务

本教程使用以下 IBM Cloud 服务:

准备工作

在开始之前,请完成以下任务:

从代码到运行中的容器

使用 IBM Cloud Container Registry 来存储容器映像,是通过 IBM Cloud Kubernetes Service 启动和运行应用程序的最简单方法。 以下步骤将向您展示如何创建容器镜像、将其存储在 IBM Cloud Container Registry 中,以及创建使用该镜像的 Kubernetes 部署。

创建名称空间

创建一个命名空间,以便在 IBM Cloud Container Registry 中存储容器映像。 命名空间是在 资源组环境以及所包含资源实例遵循的约束。 用户可以与资源组相关联以启用协作。中创建的。 更多信息,请参阅 规划命名空间

  1. 要登录 IBM Cloud 并以 us-south 区域为目标,请运行以下命令。

    ibmcloud login -r us-south [--sso]
    

    如果拥有的是联合标识,请使用 ibmcloud login -r us-south --sso 登录。 输入用户名,并在 CLI 输出中使用提供的 URL 获取一次性密码。 如果您有联合标识,那么不使用 --sso 会登录失败,使用 --sso 选项会登录成功。

  2. us-south 设置为 IBM Cloud Container Registry 命令的目标区域。

    ibmcloud cr region-set us-south
    
  3. 通过运行以下命令,创建名称空间。 为命名空间选择一个名称,并将 MY_NAMESPACE 替换为该名称。 在本教程中,请将 MY_NAMESPACE 替换为您选择的命名空间。

    名称空间在同一区域的所有 IBM Cloud 帐户中必须唯一。 名称空间必须具有 4 到 30 个字符,并且只能包含小写字母、数字、连字符 (-) 和下划线 (_)。 名称空间必须以字母或数字开头和结尾。

    如果您想在特定资源组中创建命名空间,请参阅 设置命名空间。 如果您在添加命名空间时遇到问题,请参阅 “为什么我不能添加命名空间?” 以获取帮助。

    ibmcloud cr namespace-add MY_NAMESPACE
    

构建和推送映像

构建容器镜像并将其推送到 IBM Cloud Container Registry,需要一个应用程序和一个 Dockerfile一种文本文件,包含用于构建 Docker 映像的指令。。 要获取应用程序和 Dockerfile 以及所需的其他工件,请克隆与本教程相关的 GitHub 仓库。 对于本教程的其余部分,请确保从克隆的存储库所在的目录运行所有命令。

  1. 要构建映像,请运行以下命令:

    docker build -t us.icr.io/MY_NAMESPACE/hello-world:1 .
    

    Docker 您的计算机必须运行,否则 命令将失败。支持其他客户端,也是如此。docker IBM Cloud Container Registry Docker 要使用其他客户端登录,请参阅 交互式访问您的命名空间

  2. Docker IBM Cloud Container Registry 通过运行 ibmcloud cr login 命令:

    ibmcloud cr login
    

    如果您在登录时遇到问题,请参阅 “为什么我无法登录 Container Registry?” 以获取帮助。

  3. 通过运行以下命令来推送映像:

    docker push us.icr.io/MY_NAMESPACE/hello-world:1
    
  4. 通过运行以下命令,确认映像是否已成功上传:

    ibmcloud cr images
    

    您可以使用 API密钥用于验证和授权API请求的唯一代码。 代码被传递给应用程序接口(API),用于识别调用应用程序或用户,并跟踪和控制API的使用情况。 自动访问 IBM Cloud Container Registry,并使用IAM 授予对 IBM Cloud Container Registry 资源的访问权限

部署使用映像的容器

现在您已经拥有存储在 IBM Cloud Container Registry 中的镜像,您可以在 IBM Cloud Kubernetes Service 上运行一个使用该镜像的容器,请参阅 使用CLI部署应用程序

在本教程中,请将 MY_CLUSTER 替换为免费 Kubernetes 集群的名称。

  1. 运行以下命令:

    ibmcloud ks cluster-config MY_CLUSTER --export
    

    此命令会生成 export 命令,用于设置 KUBECONFIG 环境变量。

  2. 通过复制并粘贴由上一个命令生成的 export 命令来运行 export 命令。

  3. 更新 hello-world.yaml 文件中的以下一行,将 MY_NAMESPACE 替换为您的命名空间:

    image: us.icr.io/MY_NAMESPACE/hello-world:1
    
  4. 将映像作为部署运行,并创建通过工作程序节点的 IP 地址访问的服务来公开该映像:

    kubectl apply -f hello-world.yaml
    
  5. 通过运行以下命令来检查新服务,以查找工作程序节点上使用的端口:

    kubectl describe service hello-world
    

    记下 NodePort: 行上的端口号。 在本教程中,请使用数字替换变量 NODE_PORT

  6. 记下以下命令输出中的公共 IP 地址。 在本教程中,请用 IP 地址替换变量 PUBLIC_IP

    ibmcloud ks workers MY_CLUSTER
    
  7. 通过运行以下命令来访问服务。 还可以使用 Web 浏览器。

    curl PUBLIC_IP:NODE_PORT
    

    如果看到“Hello, world!”,就说明一切正常。

保护映像和集群

将映像推送到名称空间时,Vulnerability Advisor 会自动扫描该映像,以查找潜在漏洞。 如果发现漏洞,系统会提供指示信息,以帮助修复所报告的漏洞。

为了演示这些功能,您必须推送故意包含漏洞的映像。

映像会持断更新,并且会发现新的 CVE。 结果,您可能会在映像中看到存在更多的漏洞。 如果是这样,请使用 Vulnerability Advisor 提供的信息来修复这些漏洞。

查看映像的漏洞报告

在其中一个映像中发现漏洞时,系统会生成报告,其中为您提供有关该漏洞的更多信息以及解决该漏洞的步骤。

  1. 塑造并强化脆弱形象:

    1. 运行以下命令,生成易受攻击的映像:

      docker build -t us.icr.io/MY_NAMESPACE/hello-world:2 -f Dockerfile-vulnerable .
      
    2. 运行以下命令推送易受攻击的映像:

      docker push us.icr.io/MY_NAMESPACE/hello-world:2
      

    您可以阅读 Dockerfile 以更好地了解如何使此映像变得有漏洞。 简而言之,使用 Debian 基本镜像,并将 apt 软件包回滚到易受 CVE-2019-3462 影响的版本。

  2. 通过运行以下命令来列出映像,并记录 SECURITY STATUS 列:

    ibmcloud cr images --va
    

    此列提供映像中存在的问题数。 由于问题数不为零,说明此映像有漏洞。

  3. 运行 ibmcloud cr vulnerability-assessment(别名为 ibmcloud cr va)命令来获取有关漏洞的更多信息:

    ibmcloud cr va us.icr.io/MY_NAMESPACE/hello-world:1
    

    此外,此输出还包含该漏洞的标识(如果适用)、受影响的包以及解决此问题的步骤。

在集群中强制实施安全性

尽管映像中存在漏洞,您仍可以使用此映像将容器部署到集群,而您可能并不希望这样做。 通过使用 Portieris,您可以通过多种方式加强安全性。 例如,可以阻止将有漏洞的映像用于集群的部署。

  1. 安装 Portieris

  2. Portieris 的默认策略 对于本教程来说限制性太强,因为它们涉及 图像签名。 因此,必须创建定制策略。 查看 GitHub 存储库中的 security.yaml 文件,阅读定制 政策,了解文件内容。 简而言之,此策略需要名称空间中的所有映像都没有 Vulnerability Advisor 报告的问题。

  3. 更新 security.yaml 文件中的以下文本,其中 MY_NAMESPACE 是您的命名空间:

    repositories:
      - name: us.icr.io/MY_NAMESPACE/*
    
  4. 应用定制策略:

    kubectl apply -f security.yaml
    
  5. 要更新 hello-world.yaml 以使其引用有漏洞的映像,请将标记从 1 更改为 2,如下所示:

    image: us.icr.io/MY_NAMESPACE/hello-world:2
    
  6. 通过运行以下命令,尝试对现有部署进行修补:

    kubectl apply -f hello-world.yaml
    

    您会看到以下错误消息:

    Deny "us.icr.io/MY_NAMESPACE/hello-world:2", the Vulnerability Advisor image scan assessment
    found issues with the container image that are not exempted. Refer to your image vulnerability
    report for more details by using the `ibmcloud cr va` command.
    

    Vulnerability Advisor 的判定受您创建的任何豁免策略的影响。 如果要使用被 Vulnerability Advisor 认为有漏洞的映像,那么可以豁免一个或多个漏洞,这样 Vulnerability Advisor 在其判定中就不会考虑这些漏洞。 您可以通过查看 ibmcloud cr va 命令输出中的 Policy Status 列来查看某个问题是否被豁免,也可以通过运行 ibmcloud cr exemption-list 命令来列出豁免情况。

解决映像中的漏洞

Vulnerability Advisor 提供了解决映像中存在的每个漏洞的步骤。 这些步骤显示在 How To Resolve 命令的输出的 ibmcloud cr va 列中。 如果执行这些步骤,就能解决映像中的问题。

由于会频繁发现并修补 CVE,所以此 Dockerfile 会包含一个人为漏洞,此漏洞通过将包回滚到已知的有漏洞版本而引入。 因此,要修复此漏洞,可以注释掉用于回滚 apt 的行。

  1. 要阻止 apt 回滚,请在 Dockerfile-vulnerable 中通过在以下行的开头添加井号 (#) 以注释掉该行,如下所示:

    # RUN apt-get install --allow-downgrades -y apt=1.4.8
    
  2. 再次构建和推送图像:

    1. 运行以下命令再次构建镜像:

      docker build -t us.icr.io/MY_NAMESPACE/hello-world:2 -f Dockerfile-vulnerable .
      
    2. 运行以下命令再次推送图像:

      docker push us.icr.io/MY_NAMESPACE/hello-world:2
      
  3. 等待扫描完成,然后运行以下命令以确保映像中不存在任何问题:

    ibmcloud cr images --va
    
  4. 要修补部署,请运行以下命令:

    kubectl apply -f hello-world.yaml
    
  5. 请等待部署完成。 要检查部署是否完成,请运行以下命令:

    kubectl rollout status deployment hello-world
    

    部署成功后,您就可以访问您的服务,并看到显示的 "Hello, world!"。

  6. 在继续操作之前,删除该部署和服务:

    kubectl delete -f hello-world.yaml
    

部署到非默认 Kubernetes 命名空间

IBM Cloud Kubernetes Service 集群可以自动将 IBM Cloud Container Registry 中的映像拉出到 default Kubernetes 名称空间。 但是,如果要部署到 default 以外的命名空间,则必须采取进一步的步骤。

Kubernetes 和 IBM Cloud Container Registry 名称空间不同。 有关 IBM Cloud Container Registry 命名空间的更多信息,请参阅 注册表命名空间。 有关 Kubernetes 命名空间的更多信息,请参阅 命名空间

  1. 在集群中,创建名为 test 的 Kubernetes 名称空间:

    kubectl create namespace test
    
  2. 要将部署和服务部署到此 Kubernetes 名称空间中,请在 hello-world.yaml 文件中,将部署和服务的 metadata.namespace 字段从 default 更改为 test。 以下片段在上下文中显示了 metadata.namespace 字段:

    metadata:
        name: hello-world
        namespace: test
    
  3. 应用配置。

    1. 通过运行以下命令,将配置应用到集群中仍然启用的 Portieris:

      kubectl apply -f hello-world.yaml
      

      由于 Portieris 仍在群集中启用,因此部署立即失败,您会看到以下消息:

      Error from server: error when creating "hello-world.yaml": admission webhook
      "va.hooks.securityenforcement.admission.cloud.ibm.com" denied the request:
      Deny "us.icr.io/MY_NAMESPACE/hello-world:2", no valid ImagePullSecret defined for us.icr.io
      

      出现此错误的原因是 Portieris 认为此部署无法成功,因为 test 命名空间无法从 IBM Cloud Container Registry 命名空间提取图像。 IBM Cloud Kubernetes Service 集群中的 default Kubernetes 命名空间预配置了 图像拉取密钥,可从 IBM Cloud Container Registry 拉取图像。 但是,这些私钥在新的名称空间中不存在。

    2. 在从仪表盘上移除 Portieris 后应用配置。

      1. 删除 Portieris

      2. 通过运行以下命令来应用配置:

        kubectl apply -f hello-world.yaml
        

        kubectl apply 命令成功完成。 但是,当你运行 kubectl describe pod POD_NAME -n test 命令(其中 POD_NAME 是 pod 的名称)检查部署的 pod在 Kubernetes 集群上运行的一组容器。 pod 是可运行的工作单元,它可以是独立应用程序或微服务。 时,事件日志显示群集没有获得拉取映像的授权。

        您可以通过运行 kubectl get pod -n test 来查找该 pod 的名称。

  4. 必须在名称空间中设置映像拉出私钥,这样才能将容器部署到该名称空间。 有多个选项可用,但本教程中执行的步骤是复制映像拉出私钥test 名称空间。 与其复制所有 icr.io 秘密,不如复制 us.icr.io 秘密,因为你的映像就在本地注册表中。 以下命令将 default-us-icr-io 私钥复制到 test 名称空间,并将其命名为 test-us-icr-io

    kubectl get secret default-us-icr-io -o yaml | sed 's/default/test/g' | kubectl -n test create -f -
    
  5. 有两个选项可用于使用映像拉出私钥。 本教程使用的选项是通过填充 spec.imagePullSecrets 字段,在部署 .yaml 文件中引用图像提取密文。 以下片段在上下文中显示了必需的行;您必须添加最后两行:

    spec:
        containers:
        - name: hello-world
        image: us.icr.io/MY_NAMESPACE/hello-world:1
        imagePullPolicy: Always
        imagePullSecrets:
        - name: test-us-icr-io
    
  6. 删除您的部署并重新应用配置:

    1. 运行以下命令删除部署:

      kubectl delete -f hello-world.yaml
      
    2. 运行以下命令重新应用配置:

      kubectl apply -f hello-world.yaml
      

    这次命令会成功,您可以使用 curl 命令或 Web 浏览器来访问容器。