Harbor与K8s的集成实践

Harbor提供了基于角色的访问控制机制,并通过项目来对镜像进行组织和访问权限的控制。kubernetes中通过namespace来对资源进行隔离,在企业级应用场景中,通过将两者进行结合可以有效将kubernetes使用的镜像资源进行管理和访问控制,增强镜像使用的安全性。尤其是在多租户场景下,可以通过租户、namespace和项目相结合的方式来实现对多租户镜像资源的管理和访问控制。

集成的核心概念和关键步骤

两者的集成,一个核心概念是k8s的secret。作为kubernetes中一个重要的资源secret,它的设计初衷是为了解决容器在访问外部网络或外部资源时验证的问题,例如访问一个Git仓库,连接一个数据库,设置一些密码配置等,需要额外验证的场景Secret存储了敏感数据,例如能允许容器接受请求的权限令牌。通过将Harbor的用户信息与K8s的Secret相关联,即达成了两者的集成。步骤如下:

在Harbor中创建创建用户,项目,将项目设置为私有。
将创建的用户加入到项目中,设置用户的角色为开发者或者为项目管理员。确保该账户具有拉取该仓库镜像的权限。
创建K8s下的Secret,其中secret中的用户名、密码和邮箱地址信息为在Harbor中创建的用户的信息。

在此过程中需要注意的是,第三步中创建的secret,对应的用户必须在Harbor的对应私库中有下载镜像的权限,否则应用部署时会报无法下载镜像。

举例来说

在Harbor中创建了用户,如userD
在Harbor中创建一个私有项目,如projectA
在Harbor中使用Docker命令行登陆并上传镜像至步骤2中的私有库
在K8s中创建Namespace
在K8s的Namespace中创建SecretC,该Secret对应Harbor中的用户账号userD

使用Harbor私库中的镜像在K8s的Namespace中部署应用,指定镜像下载时使用上面创建的SecretC
如果只需要能够拉取Harbor的镜像在K8s中部署应用,Harbor中的userD需要在projectA中有最低权限的访客成员角色。

Harbor与K8s集成的代码实践

imagePullSecret在K8s中用来保存镜像仓库的认证信息,以方便Kubelet在启动Pod时,能够获得镜像仓库的认证信息,确保能Kubelet够有权限从镜像仓库中下载Pod所需的镜像。
首先我们来看一下k8s中的ImagePull类型的Secret如何来创建。官方文档为:https://kubernetes.io/docs/user-guide/images/#specifying-imagepullsecrets-on-a-pod

以下代码实践Harbor版本是0.3.5。

首先,我们需要在harbor中选择一个用户,使用它的用户名与密码生成一个字符串,用户名与密码中间用冒号相连,然后使用base64对它进行加密,如下所示:[root@k8s-01 ~]# echo “test:tT001″|base64dGVzdDp0VDAwMQo=

然后,我们需要生成一个dockerconfig.json,需要使用上面生成的加密字符串,内容大致如下,假如对应的harbor库的地址为:hub.testharbor.com:

{
 "auths":{
 "hub.testharbor.com": {
 "auth": "dGVzdDp0VDAwMQo=",
 "email": ""
      }
   }
 }

我们需要把这整个json使用base64进行加密。生成的字符串可能比较长,需要加上 -w 0 参数,不让它换行。将上面的json保存成dockerconfig.json文件,然后执行命令:

[root@k8s-01 secret]# cat dockerconfig.json |base64 -w 0

ewogICJhdXRocyI6IHsKICAgICJodWIudGVzdGhhcmJvci5jb20iOiB7CiAgICAgICJhdXRoIjogImRHVnpkRHAwVkRBd01Rbz0iLAogICAgICAiZW1haWwiOiAiIgogICAgfQogIH0KfQo=

现在,我们可以来创建secret所需的yaml了。secret创建的时候,必须指定namespace。多个namespace中的secret可以同名。假如我们需要在名为hub中的namespace中创建名为testsecret的secret,对应的secret.yaml内容如下。需要使用上面生成的加密字符串。
此时在k8s中使用kubectl create 命令即可创建对应的secret:

kubectl create -f secret.yaml

最后,在部署应用的时候,我们需要为Pod指定下载镜像所需的secret名字,如下所示:


apiVersion: v1
 kind: Pod
 metadata:
 name: httpdpod
 namespace: hub
 spec:
 containers:
 - name: httpdpod
 image:hub.testharbor.com/project1/httpd:2.2
 imagePullSecrets:
 - name:testsecret

注意,要想部署成功,test用户必须为harbor中的project1项目中的成员,它才能有下载这个httpd:2.2的权限。

容器云的用户与集成

作为容器云运行时,Harbor的用户与K8s的Secret可以有更集约的整合方式。在我们的项目实践中,一个容器云的用户与一个Harbor中同名Project一一对应,但此用户可以在k8s中可以创建多个namespace。为了简化管理过程,目前我们的做法是:

在容器云启动过程中,自动在Harbor中创建一个专用用户,专门用来在各私库中下载镜像
每个在Harbor中新建的私库,都会将这个专用用户添加为它的访客成员角色 ,使这个专用用户拥有下载此库中镜像的权限
在K8s中,每创建一个新的namespace的同时,在此namespace下,使用上面的专用用户的信息创建固定名称的secret(多namespace中可存在同名secret)
部署应用时,指定imagePullSecrets下面的名称为上面固定的secret名称。

最后,再分享几个在Harbor(0.3.5)的使用过程中碰到的小坑:

在Harbor中创建用户时,密码必须为复杂密码。但是修改时,没有了此限制
用户更新密码的时候,原密码不能与新密码一致,否则报500内部错误
在为harbor的project添加成员的时候,成员角色没有相关API,需要给的id值也没有常量定义,目前来看,1为admin, 2为devlop,3为guest。

本文出自https://www.2cto.com/net/201703/616499.htm