Harbor 镜像仓库可以添加描述信息,像 Docker Hub 那样,浏览镜像仓库,就能大致了解镜像的用途及使用方法。但是手动维护描述信息会很麻烦,更好的方案是直接将代码仓库的 README.md
文件自动更新到描述信息。本文记录了一种在 Drone CI 中通过定制 kaniko 插件来自动更新 Harbor 仓库描述信息的方案。
Contents
方案
使用 Go 语言,新建 desc.go
,代码如下:
package main
import (
"encoding/json"
"net/http"
"io/ioutil"
"fmt"
"flag"
"bytes"
"strings"
"os"
)
// Generated by curl-to-Go: https://mholt.github.io/curl-to-go
type Payload struct {
Description string `json:"description"`
}
func main () {
api := flag.String("api", "http://harbor-api-proxy.intra.xx.com/api/repositories", "harbor api for repo description")
desc := flag.String("desc", "README.md", "description filename")
repo := flag.String("repo", "", "repo name")
flag.Parse()
if *repo == "" {
fmt.Println("must provide repo name")
os.Exit(1)
}
repository := strings.Replace(*repo, "/", "%2F", -1)
// read description from desc file
b, err := ioutil.ReadFile(*desc)
if err != nil {
fmt.Print(err)
}
str := string(b)
data := Payload{Description: str}
payloadBytes, err := json.Marshal(data)
if err != nil {
fmt.Print(err)
}
body := bytes.NewReader(payloadBytes)
url := *api + "/" + repository
req, err := http.NewRequest("PUT", url, body)
if err != nil {
fmt.Print(err)
}
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Print(err)
}
fmt.Println(resp.Status)
defer resp.Body.Close()
}
编译
CGO_ENABLED go build -o bin/desc desc.go
将 bin/desc
添加到镜像中:
ADD bin/desc /kaniko/desc
desc
工具的用法:
# ./bin/desc -h
Usage of ./bin/desc:
-api string
harbor api for repo description (default "http://harbor-api-proxy.intra.xx.com/api/repositories")
-desc string
description filename (default "README.md")
-repo string
repo name
在 plugin.sh
中使用 desc
:
# update repo description. use harbor api. Should run after image push. Otherwise in first build harbor api will return 404 Not Found
/kaniko/desc -api "${PLUGIN_DESC_API:-http://harbor-api-proxy.intra.xx.com/api/repositories}" -desc "${PLUGIN_DESC_FILE:-README.md}" -repo "${PLUGIN_REPO:-}"
更进一步,还可以考虑在此步骤中将代码仓库的自动信息附加到 README.md
的结尾,方便从镜像仓库快速跳转到代码仓库查看 Dockerfile 等需求。
# update repo description. use harbor api. Should run after image push. Otherwise in first build harbor api will return 404 Not Found
echo -e "\n\n# Additional Info\n\n| Item | Value |\n|-|-|\n|Source Code|${DRONE_GIT_HTTP_URL}|\n|Commit SHA|${DRONE_COMMIT_SHA}|\n|Commit Author|${DRONE_COMMIT_AUTHOR_NAME}|\n|Commit Branch|${DRONE_COMMIT_BRANCH}|\n|Build Link|${DRONE_BUILD_LINK}|\n\n" >> ${PLUGIN_DESC_FILE:-README.md}
echo "Update repository description: "
/kaniko/desc -api "${PLUGIN_DESC_API:-http://harbor-api-proxy.intra.xx.com/api/repositories}" -desc "${PLUGIN_DESC_FILE:-README.md}" -repo "${PLUGIN_REPO:-}"
用法
通过 kaniko 参数可以设置 DESC_API
及 DESC_FILE
:
kind: pipeline
name: default
steps:
- name: publish
image: ops/drone-kaniko
settings:
registry: registry.example.com # if not provided index.docker.io is supposed
repo: registry.example.com/example-project
desc_api: https://harbor-proxy.com
desc_file: README.md
tags: ${DRONE_COMMIT_SHA}
cache: true
skip_tls_verify: false # set to true for testing registries ONLY with self-signed certs
build_args:
- COMMIT_SHA=${DRONE_COMMIT_SHA}
- COMMIT_AUTHOR_EMAIL=${DRONE_COMMIT_AUTHOR_EMAIL}
username:
from_secret: docker-username
password:
from_secret: docker-password
更好的方式是定制 desc
工具,使用符合自身业务的 DESC_API
和 DESC_FILE
默认值,这样就可以不用在 yaml
中指定了。
演示
Harbor 中的效果如图所示。
harbor proxy
上文 desc
中调用的 DESC_API
是没有认证的,实际上是一个代理。在我的场景下,使用 OIDC 登录 Harbor,没有理解 OIDC 方式下调用 API 的方法,所以就弄了个代理,用 admin 账号调用 API,并且限制只能 CI 服务器的 IP 调用。应该还有更好的方案来调用 Harbor API。
Harbor Proxy 通过 Nginx 实现,核心配置如下:
# need resolver
resolver 169.169.0.2;
upstream harbor-core {
server cr-harbor-core.intra.svc.cluster.local:80;
keepalive 512;
}
server {
listen 80;
set_real_ip_from 0.0.0.0/0; #真实服务器上一级代理的IP地址或者IP段,可以写多行。
real_ip_header X-Forwarded-For; #从哪个header头检索出要的IP地址。
real_ip_recursive on; #递归的去除所配置中的可信IP。
include allow.conf;
location ~ /api/repositories {
if ($request_method !~ ^(PUT)$) {return 403;}
proxy_set_header Authorization $http_authorization;
proxy_pass http://harbor-core;
}
location ~ /api {
return 403;
}
}
完整项目请参考 Github。
参考资料
1. https://github.com/banzaicloud/drone-kaniko/issues/18
2. https://github.com/ops-itop/harbor-proxy
发表回复