安全性是在任何环境中运行的最重要的考虑因素之一,使用开源软件是在不超出您的公司环境或家庭设置预算的情况下处理安全性的好方法。 很容易谈论安全性的概念,但了解可以帮助您实现目标的工具是另一回事。 本教程解释了如何使用 Jenkins 和 Anchore 设置安全性。
有很多方法可以运行 Kubernetes。 使用 Minikube(一种专为本地测试而设计的预先打包的虚拟机 (VM) 环境)降低了运行环境的复杂性。
技术 | 它是什么? |
---|---|
Jenkins | 一个开源自动化服务器 |
Anchore | 用于容器镜像的检查、分析和认证的集中式服务 |
Minikube | VM 内的单节点 Kubernetes 集群 |
在本教程中,您将学习如何将 Jenkins 和 Anchore 添加到 Kubernetes,并为新的容器镜像和注册表配置扫描管道。
注意:为了在本教程中获得最佳性能,Minikube 至少需要四个 CPU。
基本要求
知识
- Docker(包括 Docker Hub 帐户)
- Minikube
- Jenkins
- Helm
- Kubectl
软件
- Minikube
- Helm
- Kubectl 客户端
- 在本地安装 Anchore CLI
设置环境
安装 Minikube,使用对您的环境有意义的任何方法。 如果您有足够的资源,我建议为您的 VM 提供比默认内存和 CPU 功率更多的资源
$ minikube config set memory 8192
⚠️ These changes will take effect upon a minikube delete and then a minikube start
$ minikube config set cpus 4
⚠️ These changes will take effect upon a minikube delete and then a minikube start
如果您已经在运行 Minikube 实例,您必须在使用 **minikube delete** 继续之前将其删除。
接下来,安装 Helm,这是标准的 Kubernetes 包管理器,使用对您的操作系统有意义的任何方法。
现在您可以安装应用程序了。
安装和配置 Anchore 和 Jenkins
首先,启动 Minikube 及其仪表板。
$ minikube start
? minikube v1.1.0 on darwin (amd64)
? Tip: Use 'minikube start -p <name>' to create a new cluster, or 'minikube delete' to delete this one.
? Restarting existing virtualbox VM for "minikube" ...
⌛ Waiting for SSH access ...
? Configuring environment for Kubernetes v1.14.2 on Docker 18.09.6
? Relaunching Kubernetes v1.14.2 using kubeadm ...
⌛ Verifying: apiserver proxy etcd scheduler controller dns
? Done! kubectl is now configured to use "minikube"
$ minikube dashboard
? Enabling dashboard ...
? Verifying dashboard health ...
? Launching proxy ...
? Verifying proxy health ...
? Opening http://127.0.0.1:52646/api/v1/namespaces/kube-system/services/http:kubernetes-dashboard:/proxy/ in your default browser...
只要您保持连接到此终端会话,您就可以在 127.0.0.1:52646 访问 Minikube 的可视仪表板。

创建命名空间并安装 Jenkins
下一步是启动并运行 Jenkins 构建环境。 首先,确保您的存储已配置为持久化,以便您可以稍后重复使用它。 在安装 Helm 之前,设置 **持久卷 ** 的存储类,以便其安装在重新启动后仍然保持持久性。
使用 CTRL+C 退出仪表板或打开一个新终端运行
$ minikube addons enable default-storageclass
✅ default-storageclass was successfully enabled
使用命名空间
我测试了很多不同的应用程序,并且我发现使用 Kubernetes 中的 命名空间 非常有帮助。 将所有内容都留在默认命名空间中可能会使其过于拥挤,并使卸载 Helm 安装的应用程序变得具有挑战性。 如果您坚持这样做 для Jenkins,您可以通过运行 helm del --purge jenkins --namespace jenkins,然后运行 kubectl delete ns jenkins 来将其删除。 这比手动搜索和翻找长长的容器列表容易得多。
安装 Helm
要使用 Kubernetes 的默认包管理器 Helm,请初始化环境并安装 Jenkins。
$ kubectl create ns jenkins
namespace "jenkins" created
$ helm init
helm init
Creating /Users/alleycat/.helm
Creating /Users/alleycat/.helm/repository
Creating /Users/alleycat/.helm/repository/cache
Creating /Users/alleycat/.helm/repository/local
Creating /Users/alleycat/.helm/plugins
Creating /Users/alleycat/.helm/starters
Creating /Users/alleycat/.helm/cache/archive
Creating /Users/alleycat/.helm/repository/repositories.yaml
Adding stable repo with URL: https://kubernetes-charts.storage.googleapis.com
Adding local repo with URL: http://127.0.0.1:8879/charts
$HELM_HOME has been configured at /Users/alleycat/.helm.
Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.
Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
To prevent this, run `helm init` with the --tiller-tls-verify flag.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation
$ helm install --name jenkins stable/jenkins --namespace jenkins
NAME: jenkins
LAST DEPLOYED: Tue May 28 11:12:39 2019
NAMESPACE: jenkins
STATUS: DEPLOYED
RESOURCES:
==> v1/ConfigMap
NAME DATA AGE
jenkins 5 0s
jenkins-tests 1 0s
==> v1/Deployment
NAME READY UP-TO-DATE AVAILABLE AGE
jenkins 0/1 1 0 0s
==> v1/PersistentVolumeClaim
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
jenkins Pending standard 0s
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
jenkins-7565554b8f-cvhbd 0/1 Pending 0 0s
==> v1/Role
NAME AGE
jenkins-schedule-agents 0s
==> v1/RoleBinding
NAME AGE
jenkins-schedule-agents 0s
==> v1/Secret
NAME TYPE DATA AGE
jenkins Opaque 2 0s
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
jenkins LoadBalancer 10.96.90.0 <pending> 8080:32015/TCP 0s
jenkins-agent ClusterIP 10.103.85.49 <none> 50000/TCP 0s
==> v1/ServiceAccount
NAME SECRETS AGE
jenkins 1 0s
NOTES:
1. Get your 'admin' user password by running:
printf $(kubectl get secret --namespace jenkins jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo
2. Get the Jenkins URL to visit by running these commands in the same shell:
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get svc --namespace jenkins -w jenkins'
export SERVICE_IP=$(kubectl get svc --namespace jenkins jenkins --template "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}")
echo http://$SERVICE_IP:8080/login
3. Login with the password from step 1 and the username: admin
For more information on running Jenkins on Kubernetes, visit:
https://cloud.google.com/solutions/jenkins-on-container-engine
请注意以 printf 开头的 Bash 单行代码; 它允许您查询 Jenkins 密码,并且如果不使用它,可能很难找到您的 默认 Jenkins 密码。 记下它并保存以备后用。
设置端口转发以登录到 UI
现在您已经安装了 Minikube 和 Jenkins,请登录以配置 Jenkins。 您将需要用于端口转发的 Pod 名称
$ kubectl get pods --namespace jenkins
NAME READY STATUS RESTARTS AGE
jenkins-7565554b8f-cvhbd 1/1 Running 0 9m
运行以下命令以设置端口转发(使用您的 Jenkins pod 名称,它将与下面的我的 pod 名称不同)
# verify your pod name from the namespace named jenkins
kubectl get pods --namespace jenkins
NAME READY STATUS RESTARTS AGE
jenkins-7565554b8f-cvhbd 1/1 Running 0 37m
# then forward it
$ kubectl port-forward jenkins-7565554b8f-cvhbd 8088:8080 -n jenkins
Forwarding from 127.0.0.1:8088 -> 8080
Forwarding from [::1]:8088 -> 8080
请注意,一旦您运行端口转发命令,您将需要在终端中使用多个选项卡。
继续打开此选项卡以保持您的端口转发会话。
通过转到 localhost:8088 在您喜欢的浏览器中导航到 Jenkins。 默认用户名为 admin,密码存储在 Kubernetes Secrets 中。 使用在 helm install jenkins 步骤结尾处的命令
$ printf $(kubectl get secret --namespace jenkins jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo
Jfstacz2vy
登录后,UI 将显示 欢迎使用 Jenkins!

从这里,我们将必须为 Jenkins 安装一些插件,以使我们的管道正常工作。 在主页上,选择左侧的 管理 Jenkins。
然后选择 管理插件
然后选择 可用
然后选择下面显示的这些插件旁边的复选框
选中这些框后,滚动到页面底部并选择 安装但不重新启动。
部署 Anchore
Anchore Engine “是一个开源项目,它提供了一个集中式服务,用于检查、分析和认证容器镜像。” 在 Minikube 中部署它以对您的 Jenkins 管道进行一些安全检查。 为 Helm 安装添加安全命名空间,然后运行安装
$ kubectl create ns security
namespace "security" created
$ helm install --name anchore-engine stable/anchore-engine --namespace security
NAME: anchore-engine
LAST DEPLOYED: Wed May 29 12:22:25 2019
NAMESPACE: security
STATUS: DEPLOYED
## And a lot more output
使用此命令确认该服务已启动并正在运行
kubectl run -i --tty anchore-cli --restart=Always --image anchore/engine-cli --env ANCHORE_CLI_USER=admin --env ANCHORE_CLI_PASS=${ANCHORE_CLI_PASS} --env ANCHORE_CLI_URL=http://anchore-engine-anchore-engine-api.security.svc.cluster.local:8228/v1/
If you don't see a command prompt, try pressing enter.
[anchore@anchore-cli-86d7fd9568-rmknw anchore-cli]$
如果您已登录到 Anchore 容器(类似于上面的容器),则系统已联机。 Anchore 的默认密码是 admin/foobar。 键入 exit 退出终端。
再次使用端口转发从您的主机系统访问 Anchore Engine API
$ kubectl get pods --namespace security
NAME READY STATUS RESTARTS AGE
anchore-engine-anchore-engine-analyzer-7cf5958795-wtw69 1/1 Running 0 3m
anchore-engine-anchore-engine-api-5c4cdb5587-mxkd7 1/1 Running 0 3m
anchore-engine-anchore-engine-catalog-648fcf54fd-b8thl 1/1 Running 0 3m
anchore-engine-anchore-engine-policy-7b78dd57f4-5dwsx 1/1 Running 0 3m
anchore-engine-anchore-engine-simplequeue-859c989f99-5dwgf 1/1 Running 0 3m
anchore-engine-postgresql-844dfcc468-s92c5 1/1 Running 0 3m
# Find the API pod name above and add it to the command below
$ kubectl port-forward anchore-engine-anchore-engine-api-5c4cdb5587-mxkd7 8228:8228 --namespace security
加入 Anchore 和 Jenkins
返回到 Jenkins UI,地址为 http://127.0.0.1:8088/。 在主菜单上,单击 管理 Jenkins > 管理插件。 选择 可用 选项卡,然后向下滚动或搜索 Anchore 容器镜像扫描器插件。 选中该插件旁边的复选框,然后选择 安装但不重新启动。

安装完成后,返回到 Jenkins 中的主菜单并选择 管理 Jenkins,然后选择 配置系统。 向下滚动到 Anchore 配置。 确认已选择 引擎模式 并且已输入 URL,该 URL 来自 Helm 安装的输出。 添加用户名和密码(默认 admin/foobar)。 出于调试目的,选中 启用调试日志记录。

现在已配置了插件,您可以设置 Jenkins 管道来扫描您的容器构建。
Jenkins 管道和 Anchore 扫描
此设置的目的是能够动态检查容器镜像,以确保它们满足安全要求。 为此,请使用 Anchore Engine 并授予其访问您的镜像的权限。 在此示例中,它们位于 Docker Hub 上,但它们也可以位于 Quay 或 Anchore 支持的任何其他 容器注册表 上。
为了在命令行上运行必要的命令,我们需要找到我们的 Anchore pod 名称,然后使用 kubectl exec SSH 进入它
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/anchore-cli-86d7fd9568-rmknw 1/1 Running 2 2d
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deployment.apps/anchore-cli 1 1 1 1 2d
NAME DESIRED CURRENT READY AGE
replicaset.apps/anchore-cli-86d7fd9568 1 1 1 2d
# Let’s connect to our anchore-cli pod
$ kubectl exec -it anchore-cli-86d7fd9568-rmknw -i -t -- bash
[anchore@anchore-cli-86d7fd9568-rmknw anchore-cli]$ anchore-cli --u admin --p foobar registry add index.docker.io <username> <password>
Registry: index.docker.io
User: jrepka
Type: docker_v2
Verify TLS: True
Created: 2019-05-14T22:37:59Z
Updated: 2019-05-14T22:37:59Z
Anchore Engine 现在可以与您的注册表一起使用了。 它可以通过 多种方式 来实现,包括
- 分析镜像
- 检查镜像内容
- 扫描存储库
- 查看安全漏洞
将 Anchore Engine 指向镜像,以根据您的策略对其进行分析。 对于我们的测试,我们将使用公开可用的 Cassandra 镜像
[anchore@anchore-cli-86d7fd9568-rmknw anchore-cli]$ anchore-cli --u admin --p foobar image add
docker.io/library/cassandra:latest
Image Digest: sha256:7f7afff84384e36593b085d62e087674029de9aced4482c7780f155d8ee55fad
Parent Digest: sha256:800084987d58c2a62daeea4662ecdd79fd4928d449279bd410ef7690ef482469
Analysis Status: not_analyzed
Image Type: docker
Analyzed At: None
Image ID: a34c036183d18527684cdb613fbb1c806c7e1bc26f6911dcc25e918aa7b093fc
Dockerfile Mode: None
Distro: None
Distro Version: None
Size: None
Architecture: None
Layer Count: None
Full Tag: docker.io/library/cassandra:latest
Tag Detected At: 2019-07-09T17:44:45Z
您还需要获取默认策略 ID 以针对您的管道进行测试。 (在以后的文章中,我将介绍如何自定义策略和白名单规则。)
运行以下命令以获取策略 ID
[anchore@anchore-cli-86d7fd9568-rmknw anchore-cli]$ anchore-cli --u admin --p foobar policy list
Policy ID Active Created Updated
2c53a13c-1765-11e8-82ef-23527761d060 True 2019-05-14T22:12:05Z 2019-05-14T22:12:05Z
现在您已经添加了注册表和所需的镜像,您可以构建一个管道来持续扫描它。
扫描按以下顺序进行:构建、推送、扫描。 为了防止不符合安全要求的镜像进入生产环境,我建议采用分层方法进行安全扫描:将容器镜像提升到单独的开发环境,并且仅在它通过 Anchore Engine 的扫描后才将其提升到生产环境。
在我们配置自定义策略之前,我们无法执行任何太令人兴奋的操作,因此我们将通过运行 Hello World 版本来确保扫描成功完成。 下面是用 Groovy 编写的工作流示例
node {
echo 'Hello World'
}
要运行此代码,请返回到 localhost:8088 的 Jenkins UI,选择新建项目,管道,然后将此代码块放置在“管道脚本”区域中。

由于我们正在构建上面添加的整个 Cassandra 镜像,因此需要一些时间才能完成。 在此期间,您会看到一个闪烁的红色图标。

它最终将完成并通过。 这意味着我们已正确设置所有内容。
总结
如果您已经做到了这一步,您将拥有一个运行中的 Minikube 配置,其中包含 Jenkins 和 Anchore Engine。 您还在容器注册表服务上托管了一个或多个镜像,并且 Jenkins 可以显示镜像不符合默认策略时的错误。 在下一篇文章中,我们将构建一个自定义管道,该管道验证由 Anchore Engine 设置的安全策略。
只要在 Jenkins 中正确配置了凭据,Anchore 还可以用于扫描大规模 Amazon Elastic Container Registries (ECR)。
其他资源
对于一篇文章来说,这是大量的信息。 如果您需要更多详细信息,以下链接(包括我的 GitHub 中本教程中的所有示例)可能会有所帮助
您希望我在下一个教程中构建哪些特定管道? 请在评论中告诉我。
2 条评论