Kubernetes DevOps: Harbor
Harbor 是一个 CNCF 基金会托管的开源的可信的云原生 docker registry 项目,可以用于存储、签名、扫描镜像内容,Harbor 通过添加一些常用的功能如安全性、身份权限管理等来扩展 docker registry 项目,此外还支持在 registry 之间复制镜像,还提供更加高级的安全功能,如用户管理、访问控制和活动审计等,在新版本中还添加了 Helm 仓库托管的支持。
Harbor 最核心的功能就是给 docker registry 添加上一层权限保护的功能,要实现这个功能,就需要我们在使用 docker login、pull、push 等命令的时候进行拦截,先进行一些权限相关的校验,再进行操作,其实这一系列的操作 docker registry v2 就已经为我们提供了支持,v2 集成了一个安全认证的功能,将安全认证暴露给外部服务,让外部服务去实现。
本章使用到的yaml文件地址:https://files.cnblogs.com/files/sanduzxcvbnm/harbor_yaml.zip?t=1654757668
Harbor 认证原理
上面我们说了 docker registry v2 将安全认证暴露给了外部服务使用,那么是怎样暴露的呢?我们在命令行中输入 docker login https://registry.qikqiak.com 为例来为大家说明下认证流程:
- docker client 接收到用户输入的 docker login 命令,将命令转化为调用 engine api 的 RegistryLogin 方法
- 在 RegistryLogin 方法中通过 http 盗用 registry 服务中的 auth 方法
- 因为我们这里使用的是 v2 版本的服务,所以会调用 loginV2 方法,在 loginV2 方法中会进行 /v2/ 接口调用,该接口会对请求进行认证
- 此时的请求中并没有包含 token 信息,认证会失败,返回 401 错误,同时会在 header 中返回去哪里请求认证的服务器地址
- registry client 端收到上面的返回结果后,便会去返回的认证服务器那里进行认证请求,向认证服务器发送的请求的 header 中包含有加密的用户名和密码
- 认证服务器从 header 中获取到加密的用户名和密码,这个时候就可以结合实际的认证系统进行认证了,比如从数据库中查询用户认证信息或者对接 ldap 服务进行认证校验
- 认证成功后,会返回一个 token 信息,client 端会拿着返回的 token 再次向 registry 服务发送请求,这次需要带上得到的 token,请求验证成功,返回状态码就是200了
- docker client 端接收到返回的200状态码,说明操作成功,在控制台上打印 Login Succeeded 的信息 至此,整个登录过程完成,整个过程可以用下面的流程图来说明:
要完成上面的登录认证过程有两个关键点需要注意:怎样让 registry 服务知道服务认证地址?我们自己提供的认证服务生成的 token 为什么 registry 就能够识别?
对于第一个问题,比较好解决,registry 服务本身就提供了一个配置文件,可以在启动 registry 服务的配置文件中指定上认证服务地址即可,其中有如下这样的一段配置信息:
......
auth:
token:
realm: token-realm
service: token-service
issuer: registry-token-issuer
rootcertbundle: /root/certs/bundle
......
其中 realm 就可以用来指定一个认证服务的地址,下面我们可以看到 Harbor 中该配置的内容。
关于 registry 的配置,可以参考官方文档:https://docs.docker.com/registry/configuration/
第二个问题,就是 registry 怎么能够识别我们返回的 token 文件?如果按照 registry 的要求生成一个 token,是不是 registry 就可以识别了?所以我们需要在我们的认证服务器中按照 registry 的要求生成 token,而不是随便乱生成。那么要怎么生成呢?我们可以在 docker registry 的源码中可以看到 token 是通过 JWT(JSON Web Token)来实现的,所以我们按照要求生成一个 JWT 的 token 就可以了。
对 golang 熟悉的同学可以去 clone 下 Harbor 的代码查看下,Harbor 采用 beego 这个 web 开发框架,源码阅读起来不是特别困难。我们可以很容易的看到 Harbor 中关于上面我们讲解的认证服务部分的实现方法。
安装
由于 Harbor 涉及的组件太多了,所以我们这里用更加便捷的 Helm 来进行安装。首先添加仓库地址:
$ helm repo add harbor https://helm.goharbor.io
"harbor" has been added to your repositories
在安装 Harbor 的时候有很多可以配置的参数,可以在 harbor-helm 项目上进行查看。
比如这里我们将主域名配置为 harbor.k8s.local,通过前面的 Ceph RBD 的 StorageClass 来提供存储,又因为前面我们在安装 GitLab 的时候就已经单独安装了 postgresql 和 reids 两个数据库,所以我们也可以配置 Harbor 使用这两个外置的数据库,这样可以降低资源的使用。但是使用外置的数据库我们需要提前手动创建数据库,比如我们这里使用的 GitLab 提供的数据库,则进入该 Pod 创建 registry、clair、notary_server、notary_signer 这4个数据库:
$ kubectl get pods -n kube-ops -l name=postgresql
NAME READY STATUS RESTARTS AGE
postgresql-6f494df48-frsvp 1/1 Running 0 5d3h
$ kubectl exec -it postgresql-6f494df48-frsvp /bin/bash -n kube-ops
root@postgresql-6f494df48-frsvp:~$ sudo su - postgres
postgres@postgresql-6f494df48-frsvp:~$ psql
psql (10.9 (Ubuntu 10.9-1.pgdg18.04+1))
Type "help" for help.
postgres=# CREATE DATABASE registry OWNER postgres; # 创建 registry 数据库
CREATE DATABASE
postgres=# GRANT ALL PRIVILEGES ON DATABASE registry to postgres; # 授权给 postgres 用户
GRANT
postgres=# GRANT ALL PRIVILEGES ON DATABASE registry to gitlab; # 授权给 gitlab 用户
GRANT
# Todo: 用同样的方式创建其他三个数据库:clair、notary_server、notary_signer
......
postgres-# \q # 退出
数据库准备过后,就可以使用我们自己定制的 values 文件来进行安装了,完整的定制的 values 文件如下所示:(harbor-values.yaml)
externalURL: https://harbor.k8s.local
harborAdminPassword: Harbor12345
logLevel: debug
expose:
type: ingress
tls:
enabled: true
ingress:
hosts:
core: harbor.k8s.local
notary: notary.k8s.local
persistence:
enabled: true
resourcePolicy: "keep"
persistentVolumeClaim:
registry:
# 如果需要做高可用,多个副本的组件则需要使用支持 ReadWriteMany 的后端,ceph rbd 是不支持的,可以使用 cephfs,可以换成前面我们使用的 rook-ceph-fs
storageClass: "rook-ceph-block"
# 如果是高可用的,多个副本组件需要使用 ReadWriteMany,默认为 ReadWriteOnce
accessMode: ReadWriteOnce
size: 50Gi
chartmuseum:
storageClass: "rook-ceph-block"
accessMode: ReadWriteOnce
size: 10Gi
jobservice:
storageClass: "rook-ceph-block"
accessMode: ReadWriteOnce
size: 2Gi
database:
type: external
external:
host: "postgresql.kube-ops.svc.cluster.local"
port: "5432"
username: "gitlab"
password: "passw0rd"
redis:
type: external
external:
#host: "redis.kube-ops.svc.cluster.local"
#port: "6379"
addr: "redis.kube-ops.svc.cluster.local:6379" # 不再使用host和port,否则使用host和port写法,不会采用配置,而是用默认的192.168.0.2:6379
# 默认为一个副本,如果要做高可用,只需要设置为 replicas >= 2 即可
portal:
replicas: 1
core:
replicas: 1
jobservice:
replicas: 1
registry:
replicas: 1
chartmuseum:
replicas: 1
clair:
replicas: 1
notary:
server:
replicas: 1
signer:
replicas: 1
这些配置信息都是根据 Harbor 的 Chart 包默认的 values 值进行覆盖的。现在我们直接安装即可:
$ helm install myharbor harbor/harbor -f values.yaml -n kube-ops
NAME: myharbor
LAST DEPLOYED: Tue May 12 15:23:15 2020
NAMESPACE: kube-ops
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Please wait for several minutes for Harbor deployment to complete.
Then you should be able to visit the Harbor portal at https://harbor.k8s.local.
For more details, please visit https://github.com/goharbor/harbor.
正常情况下隔一会儿就可以安装成功了:
$ helm ls -n kube-ops
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
myharbor kube-ops 1 2020-05-12 15:23:15.194263 +0800 CST deployed harbor-1.3.21.10.2
$ kubectl get pods -n kube-ops -l app=harbor
NAME READY STATUS RESTARTS AGE
myharbor-harbor-chartmuseum-95f9d9898-mqqnn 1/1 Running 0 40m
myharbor-harbor-clair-79fb8694b4-5dnk5 2/2 Running 10 40m
myharbor-harbor-core-c7bdc46d9-qw9hc 1/1 Running 0 79s
myharbor-harbor-jobservice-549d67dc87-j6hr8 1/1 Running 0 79s
myharbor-harbor-notary-server-9d57d5d9f-9fvbw 1/1 Running 10 40m
myharbor-harbor-notary-signer-658d7886-2ssrl 1/1 Running 10 40m
myharbor-harbor-portal-65588b87db-d7whd 1/1 Running 0 40m
myharbor-harbor-registry-5f7cc9d69d-89hkw 2/2 Running 0 40m
安装完成后,我们就可以将域名 harbor.k8s.local 解析到 Ingress Controller 所在的节点,我们这里使用的仍然是 Traefik,由于我们开启了 KubernetesIngress 支持的,所以我们只需要将域名解析到 Traefik 的 Pod 所在节点即可,然后就可以通过该域名在浏览器中访问了:
$ kubectl get ingress -n kube-ops
NAME HOSTS ADDRESS PORTS AGE
myharbor-harbor-ingress harbor.k8s.local,notary.k8s.local 80, 443 41m
用户名使用默认的 admin,密码则是上面配置的默认 Harbor12345:
登录过后即可进入 Harbor 的 Dashboard 页面:
我们可以看到有很多功能,默认情况下会有一个名叫 library 的项目,该项目默认是公开访问权限的,进入项目可以看到里面还有 Helm Chart 包的管理,可以手动在这里上传,也可以对该项目里面的镜像进行一些其他配置。
推送镜像
现在我们来测试下使用 docker cli 来进行 pull/push 镜像,直接使用 docker login 命令登录:
$ docker login harbor.k8s.local
Username: admin
Password:
INFO[0006] Error logging in to v2 endpoint, trying next endpoint: Get https://harbor.k8s.local/v2/: x509: certificat
e signed by unknown authority
Get https://harbor.k8s.local/v2/: x509: certificate signed by unknown authority
这是因为在使用 docker login 登录的时候会使用 https 的服务,而我们这里是自签名的证书,所以就报错了,我们可以将使用到的 CA 证书文件复制到 /etc/docker/certs.d/harbor.k8s.local 目录下面来解决这个问题(如果该目录不存在,则创建它)。ca.crt 这个证书文件我们可以通过 Ingress 中使用的 Secret 资源对象来提供:
$ kubectl get secret myharbor-harbor-ingress -n kube-ops -o yaml
apiVersion: v1
data:
ca.crt: <ca.crt>
tls.crt: <tls.crt>
tls.key: <tls.key>
kind: Secret
metadata:
creationTimestamp: "2020-05-12T07:23:20Z"
labels:
app: harbor
chart: harbor
heritage: Helm
release: myharbor
name: myharbor-harbor-ingress
namespace: kube-ops
resourceVersion: "67162075"
selfLink: /api/v1/namespaces/kube-ops/secrets/myharbor-harbor-ingress
uid: 10a9d22d-3889-4ac4-87c4-5cda7e701828
type: kubernetes.io/tls
其中 data 区域中 ca.crt 对应的值就是我们需要证书,不过需要注意还需要做一个 base64 的解码,这样证书配置上以后就可以正常访问了。
不过由于上面的方法较为繁琐,所以一般情况下面我们在使用 docker cli 的时候是在 docker 启动参数后面添加一个 --insecure-registry 参数来忽略证书的校验的,在 docker 启动配置文件 /usr/lib/systemd/system/docker.service 中修改ExecStart的启动参数:
ExecStart=/usr/bin/dockerd --insecure-registry harbor.k8s.local
或者在 Docker Daemon 的配置文件中添加:
$ cat /etc/docker/daemon.json
{
"insecure-registries" : [
"harbor.k8s.local"
],
"registry-mirrors" : [
"https://ot2k4d59.mirror.aliyuncs.com/"
]
}
然后保存重启 docker,再使用 docker cli 就没有任何问题了:
$ docker login harbor.k8s.local
Username: admin
Password:
Login Succeeded
比如我们本地现在有一个名为 busybox 的镜像,现在我们想要将该镜像推送到我们的私有仓库中去,应该怎样操作呢?首先我们需要给该镜像重新打一个具有 harbor.k8s.local 前缀的镜像,然后推送的时候就可以识别到推送到哪个镜像仓库:
$ docker tag busybox harbor.k8s.local/library/busybox
$ docker push harbor.k8s.local/library/busybox
The push refers to repository [harbor.k8s.local/library/busybox]
5b0d2d635df8: Pushed
latest: digest: sha256:a2490cec4484ee6c1068ba3a05f89934010c85242f736280b35343483b2264b6 size: 527
推送完成后,我们同样可以在 Portal 页面上看到这个镜像的信息:
镜像 push 成功,同样可以测试下 pull:
$ docker rmi harbor.k8s.local/library/busybox
Untagged: harbor.k8s.local/library/busybox:latest
Untagged: harbor.k8s.local/library/busybox@sha256:a2490cec4484ee6c1068ba3a05f89934010c85242f736280b35343483b2264b6
$ docker rmi busybox
Untagged: busybox:latest
Untagged: busybox@sha256:061ca9704a714ee3e8b80523ec720c64f6209ad3f97c0ff7cb9ec7d19f15149f
$ docker pull harbor.k8s.local/library/busybox:latest
latest: Pulling from library/busybox
e2334dd9fee4: Already exists
Digest: sha256:a2490cec4484ee6c1068ba3a05f89934010c85242f736280b35343483b2264b6
Status: Downloaded newer image for harbor.k8s.local/library/busybox:latest
harbor.k8s.local/library/busybox:latest
$ docker images |grep busybox
harbor.k8s.local/library/busybox latest be5888e67be6 3 weeks ago 1.22MB
到这里证明上面我们的私有 docker 仓库搭建成功了,大家可以尝试去创建一个私有的项目,然后创建一个新的用户,使用这个用户来进行 pull/push 镜像,Harbor还具有其他的一些功能,比如镜像复制,大家可以自行测试,感受下 Harbor 和官方自带的 registry 仓库的差别。
高可用
Harbor 的大部分组件都是无状态的应用,比如 portal、core 等只需要增加其相应的副本数量即可;在存储数据层面,需要提供高可用的 Postgresql、Redis 集群,另外针对镜像和 chart 服务也需要提供可持久的存储。
要做高可用的 Harbor,我们需要将数据库通过外置方式进行提供,当然也需要保证数据库是高可用的。然后存储需要允许跨节点数据共享,也就是要支持 ReadWriteMany 模式,我们这里使用 Ceph 的话就需要使用 CephFS。然后将其他组件副本数设置为大于等于2:portal.replicas、core.replicas、jobservice.replicas、registry.replicas、chartmuseum.replicas、clair.replicas、notary.server.replicas 以及 notary.signer.replicas。
然后重新使用 Helm 进行安装即可。
Kubernetes DevOps: Harbor的更多相关文章
- Kubernetes DevOps: Jenkins Pipeline (流水线)
要实现在 Jenkins 中的构建工作,可以有多种方式,我们这里采用比较常用的 Pipeline 这种方式.Pipeline,简单来说,就是一套运行在 Jenkins 上的工作流框架,将原来独立运行于 ...
- kubernetes搭建Harbor无坑及Harbor仓库同步
一.helm搭建harbor 1.安装helm 1.1.安装helm客户端 tar -zxvf helm-v2.14.3-linux-amd64.tar.gz mv linux-amd64/helm ...
- Kubernetes DevOps: Tekton
Tekton 是一款功能非常强大而灵活的 CI/CD 开源的云原生框架.Tekton 的前身是 Knative 项目的 build-pipeline 项目,这个项目是为了给 build 模块增加 pi ...
- 基于jenkins,tekton等工具打造kubernetes devops平台
本贴为目录贴,将不断更新 目录 1.Docker在centos下安装以及常见错误解决 2.使用kubernetes 官网工具kubeadm部署kubernetes(使用阿里云镜像) 3.无法访问gcr ...
- Windows下搭建Docker与Kubernetes(DevOps一)
Docker与Kubernetes (二)搭建 开通 Hyper-V 安装Docker for Windows 开通Kubernetes 3.关键概念 PodKubernetes 中的最小单元,一个 ...
- Kubernetes DevOps: Gitlab
Gitlab 官方提供了 Helm 的方式在 Kubernetes 集群中来快速安装,但是在使用的过程中发现 Helm 提供的 Chart 包中有很多其他额外的配置,所以我们这里使用自定义的方式来安装 ...
- Kubernetes DevOps: Jenkins
提到基于 Kubernete 的CI/CD,可以使用的工具有很多,比如 Jenkins.Gitlab CI 以及新兴的 drone 之类的,我们这里会使用大家最为熟悉的 Jenkins 来做 CI/C ...
- 使用Harbor配置Kubernetes私有镜像仓库
通常情况下,在私有云环境中使用kubernetes时,我们要从docker registry拉取镜像的时候,都会给docker daemo配置–insecure-registry属性来告诉docker ...
- kubernetes部署高可用Harbor
前言 本文Harbor高可用依照Harbor官网部署,主要思路如下,大家可以根据具体情况选择搭建. 部署Postgresql高可用集群.(本文选用Stolon进行管理,请查看文章<kuberne ...
随机推荐
- 今天安装了eclipse,myeclipse,满满的回忆
代码半生,编码半世,ideacode失效,安装了eclipse,那熟悉的界面,俨然又回到了从前,当初我们还在用structs,eclipse,webwork,那时候还在用jbuilder,但是算是老套 ...
- 运行Flutter时连接超时
这个墙不知道浪费了开发者多少的时间!!!!!!!!!!!!!!!!!!! 1.修改仓库地址为阿里仓库: 编辑android/build.gradle,把文件中的两处: google() jcenter ...
- 沁恒CH32V103C8T6(二): Linux RISC-V编译和烧录环境配置
目录 沁恒CH32V103C8T6(一): 核心板焊接和Windows开发环境配置 沁恒CH32V103C8T6(二): Linux RISC-V编译和烧录环境配置 硬件准备 CH32V103 开发板 ...
- 使用 Azure 静态 Web 应用服务免费部署 Hexo 博客
一.前言 最近在折腾 Hexo 博客,试了一下 Azure 的静态 Web 应用服务,发现特别适合静态文档类型的网站,而且具有免费额度,支持绑定域名.本文只是以 Hexo 作为示例,其他类型的框架也是 ...
- 2022-7-12 第五组 pan小堂 js
JavaScript Switch 语句 (熟悉掌握) 请使用 switch 语句来选择多个需被执行的代码块之一. 语法: switch(表达式){ case n: 代码块 break; case n ...
- YII总结学习7(在一个视图中显示另外一个视图)
controller\hello <?php namespace app\controllers; use yii\web\Controller; class helloController e ...
- Vue 样式绑定 && 条件渲染
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 & ...
- if条件控制语句和switch语句
if条件控制语句(判断范围,在一定区间内容进行判断) if 如果(第一个条件) else if 如果(第二个条件 可以无限加) else 否则(只能有一个 上面都不满足的情况下进入) if和else ...
- 【web自动化测试】Playwright快速入门,5分钟上手
我喜欢Playwright! 这是微软开源的一款非常强大的自动化工具,再过几年,他很有可能取代Selenium在浏览器自动化的通知地位.使用过一段时间,我没有找到很好的中文资料可以参考,导致很多问题无 ...
- 密码学系列之:PEM和PKCS7,PKCS8,PKCS12
目录 简介 PEM PKCS7 PKCS8 PKCS12 总结 简介 PEM是一种常见的保存key或者证书的格式,PEM格式的文件一般来说后缀是以.pem结尾的.那么PEM到底是什么呢?它和常用的证书 ...