Kubernetes部署(十二):helm部署harbor企業級鏡像倉庫

相關內容:

Kubernetes部署(一):架構及功能說明
Kubernetes部署(二):系統環境初始化
Kubernetes部署(三):CA證書製作
Kubernetes部署(四):ETCD集羣部署
Kubernetes部署(五):Haproxy、Keppalived部署
Kubernetes部署(六):Master節點部署
Kubernetes部署(七):Node節點部署
Kubernetes部署(八):Flannel網絡部署
Kubernetes部署(九):CoreDNS、Dashboard、Ingress部署
Kubernetes部署(十):儲存之glusterfs和heketi部署
Kubernetes部署(十一):管理之Helm和Rancher部署
Kubernetes部署(十二):helm部署harbor企業級鏡像倉庫

harbor簡介

harbor官方githubhttps://github.com/goharbor
Harbor是一個用於存儲和分發Docker鏡像的企業級Registry服務器。Harbor通過添加用戶通常需要的功能(如安全性,身份和管理)來擴展開源Docker Distribution。使registry更接近構建和運行環境可以提高圖像傳輸效率。Harbor支持在registry之間複製映像,還提供高級安全功能,如用戶管理,訪問控制和活動審計。

特徵

  • 雲原生註冊表:Harbour 支持容器鏡像和Helm chart,可用作本地雲環境(如容器運行和業務流程平臺)的註冊表。
  • 基於角色的訪問控制:用戶和存儲庫通過“項目”進行組織,用戶可以對項目下的鏡像擁有不同的權限。
  • 基於策略的映像複製:可以基於具有多個過濾器(存儲庫,標記和標籤)的策略在多個註冊表實例之間複製(同步)映像。如果遇到任何錯誤,Harbor將自動重試進行復制。非常適合負載平衡,高可用性,多數據中心,混合和多雲場景。
  • 漏洞掃描:Harbor定期掃描鏡像並警告用戶漏洞。
  • LDAP / AD支持:Harbor與現有企業LDAP / AD集成以進行用戶身份驗證和管理,並支持將LDAP組導入Harbor併爲其分配適當的項目角色。
  • 鏡像刪除和垃圾收集:可以刪除圖像,並可以回收它們的空間。
  • 公證:可以確保鏡像的真實性。
  • 圖形用戶門戶:用戶可以輕鬆瀏覽,搜索存儲庫和管理項目。
  • 審計:跟蹤存儲庫的所有操作。
  • RESTful API:適用於大多數管理操作的RESTful API,易於與外部系統集成。
  • 易於部署:提供在線和離線安裝程序。

    先決條件

  • Kubernetes集羣 1.10+
  • helm 2.8.0+

Harbor部署

1. 添加域名解析。

h.cnlinux.clubn.cnlinux.club的A記錄解析到我的負載均衡IP 10.31.90.200,用於創建ingress。

2. 下載harbor的chart包

[root@node-01 harbor]# wget https://github.com/goharbor/harbor-helm/archive/1.0.0.tar.gz -O harbor-helm-v1.0.0.tar.gz

3. 修改配置文件

  • 提取harbor-helm-v1.0.0.tar.gz文件中的values.yaml文件,並放到和harbor-helm-v1.0.0.tar.gz同一級的目錄中。
  • 修改values.yaml,我的配置修改瞭如下幾個字段:

    需要說明的是如果k8s集羣中存在storageclass就可以直接用storageclass,在幾個persistence.persistentVolumeClaim.XXX.storageClass中指定storageclass名就可以了,會自動創建多個pvc,但是我這裏爲了防止創建多個pvc增加管理難度,我在部署前創建了一個pvc,harbor下所有的服務都使用這一個pvc,具體每個字段的作用請查看官方文檔https://github.com/goharbor/harbor-helm

    • expose.ingress.hosts.core
    • xpose.ingress.hosts.notary
    • externalURL
    • persistence.persistentVolumeClaim.registry.existingClaim
    • persistence.persistentVolumeClaim.registry.subPath
    • persistence.persistentVolumeClaim.chartmuseum.existingClaim
    • persistence.persistentVolumeClaim.chartmuseum.subPath
    • persistence.persistentVolumeClaim.jobservice.existingClaim
    • persistence.persistentVolumeClaim.jobservice.subPath
    • persistence.persistentVolumeClaim.database.existingClaim
    • persistence.persistentVolumeClaim.database.subPath
    • persistence.persistentVolumeClaim.redis.existingClaim
    • persistence.persistentVolumeClaim.redis.subPath
expose:
  type: ingress
  tls:
    enabled: true
    secretName: ""
    notarySecretName: ""
    commonName: ""
  ingress:
    hosts:
      core: h.cnlinux.club
      notary: n.cnlinux.club
    annotations:
      ingress.kubernetes.io/ssl-redirect: "true"
      nginx.ingress.kubernetes.io/ssl-redirect: "true"
      ingress.kubernetes.io/proxy-body-size: "0"
      nginx.ingress.kubernetes.io/proxy-body-size: "0"
  clusterIP:
    name: harbor
    ports:
      httpPort: 80
      httpsPort: 443
      notaryPort: 4443
  nodePort:
    name: harbor
    ports:
      http:
        port: 80
        nodePort: 30002
      https: 
        port: 443
        nodePort: 30003
      notary: 
        port: 4443
        nodePort: 30004
externalURL: https://h.cnlinux.club
persistence:
  enabled: true
  resourcePolicy: "keep"
  persistentVolumeClaim:
    registry:
      existingClaim: "pvc-harbor"
      storageClass: ""
      subPath: "registry"
      accessMode: ReadWriteOnce
      size: 5Gi
    chartmuseum:
      existingClaim: "pvc-harbor"
      storageClass: ""
      subPath: "chartmuseum"
      accessMode: ReadWriteOnce
      size: 5Gi
    jobservice:
      existingClaim: "pvc-harbor"
      storageClass: ""
      subPath: "jobservice"
      accessMode: ReadWriteOnce
      size: 1Gi
    database:
      existingClaim: "pvc-harbor"
      storageClass: ""
      subPath: "database"
      accessMode: ReadWriteOnce
      size: 1Gi
    redis:
      existingClaim: "pvc-harbor"
      storageClass: ""
      subPath: "redis"
      accessMode: ReadWriteOnce
      size: 1Gi
  imageChartStorage:
    type: filesystem
    filesystem:
      rootdirectory: /storage
imagePullPolicy: IfNotPresent
logLevel: debug
harborAdminPassword: "Harbor12345"
secretKey: "not-a-secure-key"
nginx:
  image:
    repository: goharbor/nginx-photon
    tag: v1.7.0
  replicas: 1
  nodeSelector: {}
  tolerations: []
  affinity: {}
  podAnnotations: {}
portal:
  image:
    repository: goharbor/harbor-portal
    tag: v1.7.0
  replicas: 1
  nodeSelector: {}
  tolerations: []
  affinity: {}
  podAnnotations: {}
core:
  image:
    repository: goharbor/harbor-core
    tag: v1.7.0
  replicas: 1
  nodeSelector: {}
  tolerations: []
  affinity: {}
  podAnnotations: {}
adminserver:
  image:
    repository: goharbor/harbor-adminserver
    tag: v1.7.0
  replicas: 1
  nodeSelector: {}
  tolerations: []
  affinity: {}
  podAnnotations: {}
jobservice:
  image:
    repository: goharbor/harbor-jobservice
    tag: v1.7.0
  replicas: 1
  maxJobWorkers: 10
  jobLogger: file
  nodeSelector: {}
  tolerations: []
  affinity: {}
  podAnnotations: {}
registry:
  registry:
    image:
      repository: goharbor/registry-photon
      tag: v2.6.2-v1.7.0
  controller:
    image:
      repository: goharbor/harbor-registryctl
      tag: v1.7.0
  replicas: 1
  nodeSelector: {}
  tolerations: []
  affinity: {}
  podAnnotations: {}
chartmuseum:
  enabled: true
  image:
    repository: goharbor/chartmuseum-photon
    tag: v0.7.1-v1.7.0
  replicas: 1
  nodeSelector: {}
  tolerations: []
  affinity: {}
  podAnnotations: {}
clair:
  enabled: true
  image:
    repository: goharbor/clair-photon
    tag: v2.0.7-v1.7.0
  replicas: 1
  httpProxy:
  httpsProxy:
  updatersInterval: 12
  nodeSelector: {}
  tolerations: []
  affinity: {}
  podAnnotations: {}
notary:
  enabled: true
  server:
    image:
      repository: goharbor/notary-server-photon
      tag: v0.6.1-v1.7.0
    replicas: 1
  signer:
    image:
      repository: goharbor/notary-signer-photon
      tag: v0.6.1-v1.7.0
    replicas: 1
  nodeSelector: {}
  tolerations: []
  affinity: {}
  podAnnotations: {}
database:
  type: internal
  internal:
    image:
      repository: goharbor/harbor-db
      tag: v1.7.0
    password: "changeit"
    nodeSelector: {}
    tolerations: []
    affinity: {}
  podAnnotations: {}
redis:
  type: internal
  internal:
    image:
      repository: goharbor/redis-photon
      tag: v1.7.0
    nodeSelector: {}
    tolerations: []
    affinity: {}
  podAnnotations: {}

4. 創建存儲卷

因爲harbor需要使用到mysql,爲防止mysql在調度過程中造成數據丟失,我們需要將mysql的數據存儲在gluster的存儲卷裏。

[root@node-01 harbor]# vim pvc-harbor.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-harbor
spec:
  storageClassName: gluster-heketi
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 50Gi
[root@node-01 harbor]# kubectl apply -f pvc-harbor.yaml 

5. 安裝harbor

[root@node-01 harbor]# helm install  --name harbor harbor-helm-v1.0.0.tar.gz -f values.yaml 

如果安裝不成功可以用helm del --purge harbor刪除重新安裝。

6. 演示

在一段時間後可以看到harbor所有相關的pod都已經運行起來了,我們就可以訪問了,默認用戶密碼是admin/Harbor12345,可以通過修改values.yaml來更改默認的用戶名和密碼。

[root@node-01 ~]# kubectl get pod
NAME                                           READY     STATUS    RESTARTS   AGE
harbor-harbor-adminserver-7fffc7bf4d-vj845     1/1       Running   1          15d
harbor-harbor-chartmuseum-bdf64f899-brnww      1/1       Running   0          15d
harbor-harbor-clair-8457c45dd8-9rgq8           1/1       Running   1          15d
harbor-harbor-core-7fc454c6d8-b6kvs            1/1       Running   1          15d
harbor-harbor-database-0                       1/1       Running   0          15d
harbor-harbor-jobservice-7895949d6b-zbwkf      1/1       Running   1          15d
harbor-harbor-notary-server-57dd94bf56-txdkl   1/1       Running   0          15d
harbor-harbor-notary-signer-5d64c5bf8d-kppts   1/1       Running   0          15d
harbor-harbor-portal-648c56499f-g28rz          1/1       Running   0          15d
harbor-harbor-redis-0                          1/1       Running   0          15d
harbor-harbor-registry-5cd9c49489-r92ph        2/2       Running   0          15d

Kubernetes部署(十二):helm部署harbor企業級鏡像倉庫

  • 接下來我們創建test的私有項目用來測試。
    Kubernetes部署(十二):helm部署harbor企業級鏡像倉庫

  • 因爲我們創建的harbor倉庫是https的所以在docker pull或者push鏡像之前,需要先把證書加到docker對應的配置目錄裏,不然docker是無法登錄harbor的。
  • 進入test項目,點解“註冊證書”下載harbor的CA證書。
    Kubernetes部署(十二):helm部署harbor企業級鏡像倉庫
  • 在每個node節點創建目錄(以後可能會在master上傳鏡像,所以此次我的master節點也都一起創建了)
for n in `seq -w 01 06`;do ssh node-$n "mkdir -p /etc/docker/certs.d/h.cnlinux.club";done
#將下載下來的harbor CA證書拷貝到每個node節點的etc/docker/certs.d/h.cnlinux.club目錄下
for n in `seq -w 01 06`;do scp ca.crt node-$n:/etc/docker/certs.d/h.cnlinux.club/;done
  • 在node節點上功登錄harbor,登錄成功後的信息保存在當前用戶家目錄下的.docker/config.json裏。
[root@node-06 ~]# docker login h.cnlinux.club
Username: admin
Password: 
Login Succeeded

[root@node-06 ~]# cat .docker/config.json 
{
        "auths": {
                "h.cnlinux.club": {
                        "auth": "YWRtaW46SGFyYm9yMTIzNDU="
                }
        }
}
  • 在官方docker倉庫pull一個nginx鏡像,任何打上tag,push到harbor倉庫,如下就可以看到harbor的test項目下已經有nginx的鏡像了
    [root@node-06 ~]# docker pull nginx:latest
    [root@node-06 ~]# docker tag nginx:latest h.cnlinux.club/test/nginx:latest
    [root@node-06 ~]# docker push h.cnlinux.club/test/nginx:latest

    Kubernetes部署(十二):helm部署harbor企業級鏡像倉庫

問題:如果我的k8s集羣很多的node節點是不是每個node節點都要上去登錄才能pull harbor倉庫的鏡像?這樣是不是就非常麻煩了?

  • 其實在k8s裏有一種secret的類型是kubernetes.io/dockerconfigjson就是用來解決這種問題的。
  • 首先將docker的登錄信息轉換成base64格式
[root@node-06 ~]# cat .docker/config.json |base64
ewoJImF1dGhzIjogewoJCSJoLmNubGludXguY2x1YiI6IHsKCQkJImF1dGgiOiAiWVdSdGFXNDZTR0Z5WW05eU1USXpORFU9IgoJCX0KCX0sCgkiSHR0cEhlYWRlcnMiOiB7CgkJIlVzZXItQWdlbnQiOiAiRG9ja2VyLUNsaWVudC8xOC4wNi4xLWNlIChsaW51eCkiCgl9Cn0=
  • 創建secret
    apiVersion: v1
    kind: Secret
    metadata:
    name: harbor-registry-secret
    namespace: default
    data:
    .dockerconfigjson: ewoJImF1dGhzIjogewoJCSJoLmNubGludXguY2x1YiI6IHsKCQkJImF1dGgiOiAiWVdSdGFXNDZTR0Z5WW05eU1USXpORFU9IgoJCX0KCX0sCgkiSHR0cEhlYWRlcnMiOiB7CgkJIlVzZXItQWdlbnQiOiAiRG9ja2VyLUNsaWVudC8xOC4wNi4xLWNlIChsaW51eCkiCgl9Cn0=
    type: kubernetes.io/dockerconfigjson
    [root@node-01 ~]# kubectl create -f harbor-registry-secret.yaml 
    secret/harbor-registry-secret created
  • 創建nginx demo並使用harbor上的nginx鏡像。並將nginx.cnlinux.club解析到負載均衡10.31.90.200
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template: 
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: h.cnlinux.club/test/nginx:latest
        ports:
        - containerPort: 80
      imagePullSecrets:
        - name: harbor-registry-secret
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  ports:
  - name: nginx
    protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP 

---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx
  annotations:
    # nginx.ingress.kubernetes.io/rewrite-target: /
    kubernetes.io/ingress.class: nginx
spec:
  rules:
    - host: nginx.cnlinux.club
      http:
        paths:
          - path: 
            backend:
              serviceName: nginx
              servicePort: 80
  • 可以看到3過node節點上的nginx已經運行,證明harbor上的鏡像已經成功pull下來。
    [root@node-01 ~]# kubectl get pod -o wide|grep nginx 
    deploy-nginx-647f9649f5-88mkt                  1/1     Running            0          2m41s   10.34.0.5      node-06   <none>           <none>
    deploy-nginx-647f9649f5-9z842                  1/1     Running            0          2m41s   10.40.0.5      node-04   <none>           <none>
    deploy-nginx-647f9649f5-w44ck                  1/1     Running            0          2m41s   10.46.0.6      node-05   <none>           <none>

    最後我們訪問http://nginx.cnlinux.club,至此所有的都已完成。
    Kubernetes部署(十二):helm部署harbor企業級鏡像倉庫

    後續會陸續更新所有的k8s相關文檔,如果你覺得我寫的不錯,希望大家多多關注點贊,如有問題可以在下面給我留言,非常感謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章