基于Traefik TLS反向代理Harbor

需求背景

基于TLS协议的harbor部署完成之后,我们可以正常通过https访问harbor并pull、push镜像一系列正常功能操作。但是我们需要发布到外网访问,对于很多机器没有外网IP来讲,我们需要一个全局的负载均衡通过虚拟主机形式暴露到外网访问。此文实现基于Traefik的方式通过TLS(letsencrypt)反向代理到后端Harbor(nginx TLS)。

架构图

整个操作流程看起来如下所示:

nginx (ssl,443) -> harbor(nginx,443,self-signed certs) -> harbor


image.png

因为我们ingress使用的Traefik,所以这里将Nginx替换,因为后端harbor-nginx我们使用的自签名证书,会校验ca签名证书,这里为了减少TLS的建立连接时间,所以在nginx或者traefik配置禁用对后端的证书检查即可。

Traefik

InsecureSkipVerify = true

Nginx

location /upstream {
    ....
    proxy_ssl_verify off;
}  

Harbor 自签名脚本

#!/bin/env bash

# 1. Create your own CA certificate
openssl req \
    -newkey rsa:4096 -nodes -sha256 -keyout ca.key \
    -x509 -days 365 -out ca.crt
# 2. Generate a Certificate Signing Request:
# If you use FQDN like reg.yourdomain.com to connect your registry host, then you must use reg.yourdomain.com as CN (Common Name). Othe
rwise, if you use IP address to connect your registry host, CN can be anything like your name and so on:

openssl req \
    -newkey rsa:4096 -nodes -sha256 -keyout yourdomain.com.key \
    -out yourdomain.com.csr

# 3.Generate the certificate of your registry host
# If you're using FQDN like reg.yourdomain.com to connect your registry host, then run this command to generate the certificate of your
 registry host:
openssl x509 -req -days 3650 -in yourdomain.com.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out yourdomain.com.
crt

将生成的秘钥和证书移动至存放证书文件中,比如/data/apps/harbor/data/cert/

cp yourdomain.com.crt /data/apps/harbor/data/cert/
cp yourdomain.com.key /data/apps/harbor/data/cert/

接下来,编辑文件harbor.cfg,更新主机名和协议,并更新属性ssl_cert和ssl_cert_key:

#set hostname
hostname = yourdomain.com
#set ui_url_protocol
ui_url_protocol = https
......
#The path of cert and key files for nginx, they are applied only the protocol is set to https 
ssl_cert = /data/apps/harbor/data/cert/yourdomain.com.crt
ssl_cert_key = /data/apps/harbor/data/cert/yourdomain.com.key

如果是初次安装harbor,我们只需要执行如下脚本安装即可

./install.sh

如果已经安装harbor,我们只需要重新生成配置文件即可:

./prepare

如果Harbor已经运行我们停止并删除现有的容器。容器数据保留在文件系统中,所以不必担心数据会丢失

docker-compose down 

然后我们启动harbor

docker-compose up -d

至此我们自签名完成了,Troubleshooting参考

配置Traefik

由于我们是基于Kubernetes Ingress对外提供服务,Harbor也没有部署在Kubernetes中,我们需要对Service和endpoint做一个关系映射绑定。

# vim harbor-ingress.yaml
---
kind: Service
apiVersion: v1
metadata:
  name: harbor
  namespace: kube-system
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      name: http
    - protocol: TCP
      port: 443
      targetPort: 443
      name: https
---
kind: Endpoints
apiVersion: v1
metadata:
  name: harbor
  namespace: kube-system
subsets:
  - addresses:
       # harbor机器IP
      - ip: 192.168.100.2
    ports:
      - port: 80
        name: http
      - port: 443
        name: https
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: harbor
  namespace: kube-system
  annotations:
    kubernetes.io/ingress.class: traefik
    traefik.ingress.kubernetes.io/redirect-entry-point: https
    # 这里不需要透传,设置之后traefik会返回404,有点问题
    #traefik.ingress.kubernetes.io/pass-tls-cert: "true"
spec:
  rules:
  - host: yourdomain.com
    http:
      paths:
      - backend:
          serviceName: harbor
          # proxy 到harbor nginx(tls)
          servicePort: 443

如果基于Kuberntes部署的harbor不需要做endpoint绑定,直接通过Ingres proxy过去就行。

由于Traefik原生支持acme协议可以向letsencrypt服务器自动申请、续约证书请求,这里配置Traefik letsencrypt,以及配置禁用对后端的证书检查,kubernetes traefik ingress没有找到相关的annotation,只能对全局进行配置。

apiVersion: v1
kind: ConfigMap
metadata:
  name: traefik-conf
  namespace: kube-system
data:
  traefik.toml: |
    # traefik.toml
    defaultEntryPoints = ["http","https"]
    insecureSkipVerify = true
    [entryPoints]
      [entryPoints.http]
      address = ":80"
      [entryPoints.https]
      address = ":443"
      [entryPoints.https.tls]
    [acme]
    email = "fate1028@163.com"
    storageFile = "/acme/acme.json"
    entryPoint = "https"
    onDemand = true
    onHostRule = true
    [acme.httpChallenge]
      entryPoint = "http"
    [[acme.domains]]
    main = "*.yourdomain.com"

因为letsencrypt泛域名支持需要DNS nameserver的认证并且只支持1级统配,所以这里为每个子域名申请一个私钥和证书,并且将私钥和证书保存至/acme/acme.json文件中,此文件我们通过volume的形式挂载出去。
如下是traefik以daemonset的形式部署,参考配置如下:

# vim traefik-ds.yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: traefik-ingress-controller
  namespace: kube-system
---
kind: DaemonSet
apiVersion: extensions/v1beta1
metadata:
  name: traefik-ingress-controller
  namespace: kube-system
  labels:
    k8s-app: traefik-ingress-lb
spec:
  template:
    metadata:
      labels:
        k8s-app: traefik-ingress-lb
        name: traefik-ingress-lb
    spec:
      serviceAccountName: traefik-ingress-controller
      terminationGracePeriodSeconds: 60
      nodeSelector:
        edgenode: "true"
      hostNetwork: true
      containers:
      - image: traefik
        name: traefik-ingress-lb
        ports:
        - name: http
          containerPort: 80
          hostPort: 80
        - name: https
          containerPort: 443
          hostPort: 443
        - name: admin
          containerPort: 8080
          hostPort: 8080
        securityContext:
          capabilities:
            drop:
            - ALL
            add:
            - NET_BIND_SERVICE
        args:
        - --configfile=/config/traefik.toml
        - --api
        - --kubernetes
        - --logLevel=INFO
        volumeMounts:
          - mountPath: "/config"
            name: "config"
          - mountPath: "/acme"
            name: "acme"
      volumes:
        - name: config
          configMap:
            name: traefik-conf
        - name: acme
          hostPath:
            path: /srv/configs/acme
---
kind: Service
apiVersion: v1
metadata:
  name: traefik-ingress-service
  namespace: kube-system
spec:
  selector:
    k8s-app: traefik-ingress-lb
  ports:
    - protocol: TCP
      port: 80
      name: http
    - protocol: TCP
      port: 443
      name: https
    - protocol: TCP
      port: 8080
      name: admin
  type: NodePort

如上配置只是作为参考,生产环境我们可以基于etcd来存储我们的acme私钥证书,方便横向扩展我们的traefik。此时我们基于Traefik TLS 反向代理到 harbor(nginx,TLS)就完成了,docker login和docker pull,docker push测试没问题就完成。

参考文档:

github issue:

https://github.com/vmware/harbor/issues/3114

harbor自签名配置以及troubleshooting

https://github.com/vmware/harbor/blob/master/docs/configure_https.md#troubleshooting

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容

  • 简介 kubernetes 使用service和ingress共同构建了,外部访问k8s内部容器的通道。 Serv...
    梅_梅阅读 990评论 0 2
  • Kubernetes是Google开源的容器集群管理系统,其提供应用部署、维护、 扩展机制等功能,利用Kubern...
    devabel阅读 6,309评论 0 13
  • 最近两个月都在推进公司业务容器化,很少有时间来更新文章了。最近我们计划把业务方的代码发布改用通过Docker Re...
    魔哈Moha阅读 3,262评论 0 2
  • 妈妈昨天说有点难受,人不太舒服,可能是睡得太晚了,我想也有可能是累了。 自从怀孕后,妈妈总是不让我洗碗,怕我累着,...
    小丫屠阅读 252评论 2 2
  • 我从钟山脚下 我从玄武湖畔 我从秦淮河边 我从中华门前 捡起一块石头 一笔笔画上彩绘 送给你 亲爱的姑娘 听说你即...
    晨光笔记阅读 202评论 0 1