CloudNative: Harbor - x893675/note GitHub Wiki

helm3搭建harbor

  1. helm repo add harbor https://helm.goharbor.io

  2. helm repo update

  3. helm pull harbor/harbor --version 1.4.1

  4. 自签https证书,内网访问,无域名,假使ip为172.20.149.141, 步骤如下:

    1. openssl genrsa -out ca.key 4096

    2. openssl req -x509 -new -nodes -sha512 -days 3650 -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=172.20.149.141" -key ca.key -out ca.crt, 注意此时CN的值为ip地址

    3. openssl genrsa -out tls.key 4096

    4. openssl req -sha512 -new -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=172.20.149.141" -key tls.key -out tls.csr, subj 的值同第2步

    5. 生成x509 v3扩展文件,因只使用ip:port访问, san的值要写成ip:

      cat > v3.ext <<-EOF
      authorityKeyIdentifier=keyid,issuer
      basicConstraints=CA:FALSE
      keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
      extendedKeyUsage = serverAuth
      subjectAltName = @alt_names
      
      [alt_names]
      IP=172.20.149.141
      EOF
      
    6. openssl x509 -req -sha512 -days 3650 -extfile v3.ext -CA ca.crt -CAkey ca.key -CAcreateserial -in tls.csr -out tls.crt

    7. tls.crt转换成docker client使用的格式: openssl x509 -inform PEM -in tls.crt -out tls.cert

    8. 查看证书详情: openssl x509 -in tls.crt -text -noout

  5. 创建证书secret,假如harbor即将安装在harbor namespa下

    1. kubectl create ns harbor
    2. kubectl create secret generic cert --from-file=./ca.crt --from-file=./tls.crt --from-file=./tls.key -n harbor
  6. 更改values.yaml(使用nodeport方式暴露服务,且使用自签tls证书, tls.secretName选项填写上个步骤创建的secret,externalURL需写成https形式的ip:port形式,根据实际情况更改storageclass的值):

    expose:
      # Set the way how to expose the service. Set the type as "ingress",
      # "clusterIP", "nodePort" or "loadBalancer" and fill the information
      # in the corresponding section
      type: nodePort
      tls:
        # Enable the tls or not. Note: if the type is "ingress" and the tls
        # is disabled, the port must be included in the command when pull/push
        # images. Refer to https://github.com/goharbor/harbor/issues/5291
        # for the detail.
        enabled: true
        # Fill the name of secret if you want to use your own TLS certificate.
        # The secret contains keys named:
        # "tls.crt" - the certificate (required)
        # "tls.key" - the private key (required)
        # "ca.crt" - the certificate of CA (optional), this enables the download
        # link on portal to download the certificate of CA
        # These files will be generated automatically if the "secretName" is not set
        secretName: "cert"
        # By default, the Notary service will use the same cert and key as
        # described above. Fill the name of secret if you want to use a
        # separated one. Only needed when the type is "ingress".
        notarySecretName: ""
        # The common name used to generate the certificate, it's necessary
        # when the type isn't "ingress" and "secretName" is null
        commonName: ""
      nodePort:
        # The name of NodePort service
        name: harbor
        ports:
          http:
            # The service port Harbor listens on when serving with HTTP
            port: 80
            # The node port Harbor listens on when serving with HTTP
            nodePort: 30002
          https:
            # The service port Harbor listens on when serving with HTTPS
            port: 443
            # The node port Harbor listens on when serving with HTTPS
            nodePort: 30003
          # Only needed when notary.enabled is set to true
          notary:
            # The service port Notary listens on
            port: 4443
            # The node port Notary listens on
            nodePort: 30004
    
    # If Harbor is deployed behind the proxy, set it as the URL of proxy
    externalURL: https://172.20.149.141:30003
    
    # The internal TLS used for harbor components secure communicating. In order to enable https
    # in each components tls cert files need to provided in advance.
    internalTLS:
      # If internal TLS enabled
      enabled: false
      # There are three ways to provide tls
      # 1) "auto" will generate cert automatically
      # 2) "manual" need provide cert file manually in following value
      # 3) "secret" internal certificates from secret
      certSource: "auto"
      # The content of trust ca, only available when `certSource` is "manual"
      trustCa: ""
      # core related cert configuration
      core:
        # secret name for core's tls certs
        secretName: ""
        # Content of core's TLS cert file, only available when `certSource` is "manual"
        crt: ""
        # Content of core's TLS key file, only available when `certSource` is "manual"
        key: ""
      # jobservice related cert configuration
      jobservice:
        # secret name for jobservice's tls certs
        secretName: ""
        # Content of jobservice's TLS key file, only available when `certSource` is "manual"
        crt: ""
        # Content of jobservice's TLS key file, only available when `certSource` is "manual"
        key: ""
      # registry related cert configuration
      registry:
        # secret name for registry's tls certs
        secretName: ""
        # Content of registry's TLS key file, only available when `certSource` is "manual"
        crt: ""
        # Content of registry's TLS key file, only available when `certSource` is "manual"
        key: ""
      # portal related cert configuration
      portal:
        # secret name for portal's tls certs
        secretName: ""
        # Content of portal's TLS key file, only available when `certSource` is "manual"
        crt: ""
        # Content of portal's TLS key file, only available when `certSource` is "manual"
        key: ""
      # chartmuseum related cert configuration
      chartmuseum:
        # secret name for chartmuseum's tls certs
        secretName: ""
        # Content of chartmuseum's TLS key file, only available when `certSource` is "manual"
        crt: ""
        # Content of chartmuseum's TLS key file, only available when `certSource` is "manual"
        key: ""
      # clair related cert configuration
      clair:
        # secret name for clair's tls certs
        secretName: ""
        # Content of clair's TLS key file, only available when `certSource` is "manual"
        crt: ""
        # Content of clair's TLS key file, only available when `certSource` is "manual"
        key: ""
      # trivy related cert configuration
      trivy:
        # secret name for trivy's tls certs
        secretName: ""
        # Content of trivy's TLS key file, only available when `certSource` is "manual"
        crt: ""
        # Content of trivy's TLS key file, only available when `certSource` is "manual"
        key: ""
    
    # The persistence is enabled by default and a default StorageClass
    # is needed in the k8s cluster to provision volumes dynamicly.
    # Specify another StorageClass in the "storageClass" or set "existingClaim"
    # if you have already existing persistent volumes to use
    #
    # For storing images and charts, you can also use "azure", "gcs", "s3",
    # "swift" or "oss". Set it in the "imageChartStorage" section
    persistence:
      enabled: true
      # Setting it to "keep" to avoid removing PVCs during a helm delete
      # operation. Leaving it empty will delete PVCs after the chart deleted
      resourcePolicy: "keep"
      persistentVolumeClaim:
        registry:
          # Use the existing PVC which must be created manually before bound,
          # and specify the "subPath" if the PVC is shared with other components
          existingClaim: ""
          # Specify the "storageClass" used to provision the volume. Or the default
          # StorageClass will be used(the default).
          # Set it to "-" to disable dynamic provisioning
          storageClass: "nfs"
          subPath: ""
          accessMode: ReadWriteOnce
          size: 5Gi
        chartmuseum:
          existingClaim: ""
          storageClass: "nfs"
          subPath: ""
          accessMode: ReadWriteOnce
          size: 5Gi
        jobservice:
          existingClaim: ""
          storageClass: "nfs"
          subPath: ""
          accessMode: ReadWriteOnce
          size: 1Gi
        # If external database is used, the following settings for database will
        # be ignored
        database:
          existingClaim: ""
          storageClass: "nfs"
          subPath: ""
          accessMode: ReadWriteOnce
          size: 1Gi
        # If external Redis is used, the following settings for Redis will
        # be ignored
        redis:
          existingClaim: ""
          storageClass: "nfs"
          subPath: ""
          accessMode: ReadWriteOnce
          size: 1Gi
        trivy:
          existingClaim: ""
          storageClass: "nfs"
          subPath: ""
          accessMode: ReadWriteOnce
          size: 5Gi
      # Define which storage backend is used for registry and chartmuseum to store
      # images and charts. Refer to
      # https://github.com/docker/distribution/blob/master/docs/configuration.md#storage
      # for the detail.
      imageChartStorage:
        # Specify whether to disable `redirect` for images and chart storage, for
        # backends which not supported it (such as using minio for `s3` storage type), please disable
        # it. To disable redirects, simply set `disableredirect` to `true` instead.
        # Refer to
        # https://github.com/docker/distribution/blob/master/docs/configuration.md#redirect
        # for the detail.
        disableredirect: false
        # Specify the "caBundleSecretName" if the storage service uses a self-signed certificate.
        # The secret must contain keys named "ca.crt" which will be injected into the trust store
        # of registry's and chartmuseum's containers.
        # caBundleSecretName:
    
        # Specify the type of storage: "filesystem", "azure", "gcs", "s3", "swift",
        # "oss" and fill the information needed in the corresponding section. The type
        # must be "filesystem" if you want to use persistent volumes for registry
        # and chartmuseum
        type: filesystem
        filesystem:
          rootdirectory: /storage
          #maxthreads: 100
        azure:
          accountname: accountname
          accountkey: base64encodedaccountkey
          container: containername
          #realm: core.windows.net
        gcs:
          bucket: bucketname
          # The base64 encoded json file which contains the key
          encodedkey: base64-encoded-json-key-file
          #rootdirectory: /gcs/object/name/prefix
          #chunksize: "5242880"
        s3:
          region: us-west-1
          bucket: bucketname
          #accesskey: awsaccesskey
          #secretkey: awssecretkey
          #regionendpoint: http://myobjects.local
          #encrypt: false
          #keyid: mykeyid
          #secure: true
          #v4auth: true
          #chunksize: "5242880"
          #rootdirectory: /s3/object/name/prefix
          #storageclass: STANDARD
        swift:
          authurl: https://storage.myprovider.com/v3/auth
          username: username
          password: password
          container: containername
          #region: fr
          #tenant: tenantname
          #tenantid: tenantid
          #domain: domainname
          #domainid: domainid
          #trustid: trustid
          #insecureskipverify: false
          #chunksize: 5M
          #prefix:
          #secretkey: secretkey
          #accesskey: accesskey
          #authversion: 3
          #endpointtype: public
          #tempurlcontainerkey: false
          #tempurlmethods:
        oss:
          accesskeyid: accesskeyid
          accesskeysecret: accesskeysecret
          region: regionname
          bucket: bucketname
          #endpoint: endpoint
          #internal: false
          #encrypt: false
          #secure: true
          #chunksize: 10M
          #rootdirectory: rootdirectory
    
    imagePullPolicy: IfNotPresent
    
    # Use this set to assign a list of default pullSecrets
    imagePullSecrets:
    #  - name: docker-registry-secret
    #  - name: internal-registry-secret
    
    # The update strategy for deployments with persistent volumes(jobservice, registry
    # and chartmuseum): "RollingUpdate" or "Recreate"
    # Set it as "Recreate" when "RWM" for volumes isn't supported
    updateStrategy:
      type: RollingUpdate
    
    # debug, info, warning, error or fatal
    logLevel: info
    
    # The initial password of Harbor admin. Change it from portal after launching Harbor
    harborAdminPassword: "Harbor12345"
    # The secret key used for encryption. Must be a string of 16 chars.
    secretKey: "not-a-secure-key"
    
    # The proxy settings for updating clair vulnerabilities from the Internet and replicating
    # artifacts from/to the registries that cannot be reached directly
    proxy:
      httpProxy:
      httpsProxy:
      noProxy: 127.0.0.1,localhost,.local,.internal
      components:
        - core
        - jobservice
        - clair
        - trivy
    
    # The custom ca bundle secret, the secret must contain key named "ca.crt"
    # which will be injected into the trust store for chartmuseum, clair, core, jobservice, registry, trivy components
    # caBundleSecretName: ""
    
    ## UAA Authentication Options
    # If you're using UAA for authentication behind a self-signed
    # certificate you will need to provide the CA Cert.
    # Set uaaSecretName below to provide a pre-created secret that
    # contains a base64 encoded CA Certificate named `ca.crt`.
    # uaaSecretName:
    
    # If expose the service via "ingress", the Nginx will not be used
    nginx:
      image:
        repository: goharbor/nginx-photon
        tag: v2.0.1
      # set the service account to be used, default if left empty
      serviceAccountName: ""
      replicas: 1
      # resources:
      #  requests:
      #    memory: 256Mi
      #    cpu: 100m
      nodeSelector: {}
      tolerations: []
      affinity: {}
      ## Additional deployment annotations
      podAnnotations: {}
    
    portal:
      image:
        repository: goharbor/harbor-portal
        tag: v2.0.1
      # set the service account to be used, default if left empty
      serviceAccountName: ""
      replicas: 1
    # resources:
    #  requests:
    #    memory: 256Mi
    #    cpu: 100m
      nodeSelector: {}
      tolerations: []
      affinity: {}
      ## Additional deployment annotations
      podAnnotations: {}
    
    core:
      image:
        repository: goharbor/harbor-core
        tag: v2.0.1
      # set the service account to be used, default if left empty
      serviceAccountName: ""
      replicas: 1
      ## Liveness probe values
      livenessProbe:
        initialDelaySeconds: 300
    # resources:
    #  requests:
    #    memory: 256Mi
    #    cpu: 100m
      nodeSelector: {}
      tolerations: []
      affinity: {}
      ## Additional deployment annotations
      podAnnotations: {}
      # Secret is used when core server communicates with other components.
      # If a secret key is not specified, Helm will generate one.
      # Must be a string of 16 chars.
      secret: ""
      # Fill the name of a kubernetes secret if you want to use your own
      # TLS certificate and private key for token encryption/decryption.
      # The secret must contain keys named:
      # "tls.crt" - the certificate
      # "tls.key" - the private key
      # The default key pair will be used if it isn't set
      secretName: ""
      # The XSRF key. Will be generated automatically if it isn't specified
      xsrfKey: ""
    
    jobservice:
      image:
        repository: goharbor/harbor-jobservice
        tag: v2.0.1
      replicas: 1
      # set the service account to be used, default if left empty
      serviceAccountName: ""
      maxJobWorkers: 10
      # The logger for jobs: "file", "database" or "stdout"
      jobLogger: file
    # resources:
    #   requests:
    #     memory: 256Mi
    #     cpu: 100m
      nodeSelector: {}
      tolerations: []
      affinity: {}
      ## Additional deployment annotations
      podAnnotations: {}
      # Secret is used when job service communicates with other components.
      # If a secret key is not specified, Helm will generate one.
      # Must be a string of 16 chars.
      secret: ""
    
    registry:
      # set the service account to be used, default if left empty
      serviceAccountName: ""
      registry:
        image:
          repository: goharbor/registry-photon
          tag: v2.0.1
        # resources:
        #  requests:
        #    memory: 256Mi
        #    cpu: 100m
      controller:
        image:
          repository: goharbor/harbor-registryctl
          tag: v2.0.1
    
        # resources:
        #  requests:
        #    memory: 256Mi
        #    cpu: 100m
      # set the service account to be used, default if left empty
      serviceAccountName: ""
      replicas: 1
      nodeSelector: {}
      tolerations: []
      affinity: {}
      ## Additional deployment annotations
      podAnnotations: {}
      # Secret is used to secure the upload state from client
      # and registry storage backend.
      # See: https://github.com/docker/distribution/blob/master/docs/configuration.md#http
      # If a secret key is not specified, Helm will generate one.
      # Must be a string of 16 chars.
      secret: ""
      # If true, the registry returns relative URLs in Location headers. The client is responsible for resolving the correct URL.
      relativeurls: false
      credentials:
        username: "harbor_registry_user"
        password: "harbor_registry_password"
        # If you update the username or password of registry, make sure use cli tool htpasswd to generate the bcrypt hash
        # e.g. "htpasswd -nbBC10 $username $password"
        htpasswd: "harbor_registry_user:$2y$10$9L4Tc0DJbFFMB6RdSCunrOpTHdwhid4ktBJmLD00bYgqkkGOvll3m"
    
      middleware:
        enabled: false
        type: cloudFront
        cloudFront:
          baseurl: example.cloudfront.net
          keypairid: KEYPAIRID
          duration: 3000s
          ipfilteredby: none
          # The secret key that should be present is CLOUDFRONT_KEY_DATA, which should be the encoded private key
          # that allows access to CloudFront
          privateKeySecret: "my-secret"
    
    chartmuseum:
      enabled: true
      # set the service account to be used, default if left empty
      serviceAccountName: ""
      # Harbor defaults ChartMuseum to returning relative urls, if you want using absolute url you should enable it by change the following value to 'true'
      absoluteUrl: false
      image:
        repository: goharbor/chartmuseum-photon
        tag: v2.0.1
      replicas: 1
      # resources:
      #  requests:
      #    memory: 256Mi
      #    cpu: 100m
      nodeSelector: {}
      tolerations: []
      affinity: {}
      ## Additional deployment annotations
      podAnnotations: {}
    
    clair:
      enabled: true
      # set the service account to be used, default if left empty
      serviceAccountName: ""
      clair:
        image:
          repository: goharbor/clair-photon
          tag: v2.0.1
        # resources:
        #  requests:
        #    memory: 256Mi
        #    cpu: 100m
      adapter:
        image:
          repository: goharbor/clair-adapter-photon
          tag: v2.0.1
        # resources:
        #  requests:
        #    memory: 256Mi
        #    cpu: 100m
      replicas: 1
      # The interval of clair updaters, the unit is hour, set to 0 to
      # disable the updaters
      updatersInterval: 12
      nodeSelector: {}
      tolerations: []
      affinity: {}
      ## Additional deployment annotations
      podAnnotations: {}
    
    trivy:
      # enabled the flag to enable Trivy scanner
      enabled: true
      image:
        # repository the repository for Trivy adapter image
        repository: goharbor/trivy-adapter-photon
        # tag the tag for Trivy adapter image
        tag: v2.0.1
      # set the service account to be used, default if left empty
      serviceAccountName: ""
      # replicas the number of Pod replicas
      replicas: 1
      # debugMode the flag to enable Trivy debug mode with more verbose scanning log
      debugMode: false
      # vulnType a comma-separated list of vulnerability types. Possible values are `os` and `library`.
      vulnType: "os,library"
      # severity a comma-separated list of severities to be checked
      severity: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL"
      # ignoreUnfixed the flag to display only fixed vulnerabilities
      ignoreUnfixed: false
      # insecure the flag to skip verifying registry certificate
      insecure: false
      # gitHubToken the GitHub access token to download Trivy DB
      #
      # Trivy DB contains vulnerability information from NVD, Red Hat, and many other upstream vulnerability databases.
      # It is downloaded by Trivy from the GitHub release page https://github.com/aquasecurity/trivy-db/releases and cached
      # in the local file system (`/home/scanner/.cache/trivy/db/trivy.db`). In addition, the database contains the update
      # timestamp so Trivy can detect whether it should download a newer version from the Internet or use the cached one.
      # Currently, the database is updated every 12 hours and published as a new release to GitHub.
      #
      # Anonymous downloads from GitHub are subject to the limit of 60 requests per hour. Normally such rate limit is enough
      # for production operations. If, for any reason, it's not enough, you could increase the rate limit to 5000
      # requests per hour by specifying the GitHub access token. For more details on GitHub rate limiting please consult
      # https://developer.github.com/v3/#rate-limiting
      #
      # You can create a GitHub token by following the instructions in
      # https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
      gitHubToken: ""
      # skipUpdate the flag to disable Trivy DB downloads from GitHub
      #
      # You might want to set the value of this flag to `true` in test or CI/CD environments to avoid GitHub rate limiting issues.
      # If the value is set to `true` you have to manually download the `trivy.db` file and mount it in the
      # `/home/scanner/.cache/trivy/db/trivy.db` path.
      skipUpdate: false
      resources:
        requests:
          cpu: 200m
          memory: 512Mi
        limits:
          cpu: 1
          memory: 1Gi
      ## Additional deployment annotations
      podAnnotations: {}
    
    notary:
      enabled: false
      server:
        # set the service account to be used, default if left empty
        serviceAccountName: ""
        image:
          repository: goharbor/notary-server-photon
          tag: v2.0.1
        replicas: 1
        # resources:
        #  requests:
        #    memory: 256Mi
        #    cpu: 100m
      signer:
        # set the service account to be used, default if left empty
        serviceAccountName: ""
        image:
          repository: goharbor/notary-signer-photon
          tag: v2.0.1
        replicas: 1
        # resources:
        #  requests:
        #    memory: 256Mi
        #    cpu: 100m
      nodeSelector: {}
      tolerations: []
      affinity: {}
      ## Additional deployment annotations
      podAnnotations: {}
      # Fill the name of a kubernetes secret if you want to use your own
      # TLS certificate authority, certificate and private key for notary
      # communications.
      # The secret must contain keys named ca.crt, tls.crt and tls.key that
      # contain the CA, certificate and private key.
      # They will be generated if not set.
      secretName: ""
    
    database:
      # if external database is used, set "type" to "external"
      # and fill the connection informations in "external" section
      type: internal
      internal:
        # set the service account to be used, default if left empty
        serviceAccountName: ""
        image:
          repository: goharbor/harbor-db
          tag: v2.0.1
        # the image used by the init container
        initContainerImage:
          repository: busybox
          tag: latest
        # The initial superuser password for internal database
        password: "changeit"
        # resources:
        #  requests:
        #    memory: 256Mi
        #    cpu: 100m
        nodeSelector: {}
        tolerations: []
        affinity: {}
      external:
        host: "192.168.0.1"
        port: "5432"
        username: "user"
        password: "password"
        coreDatabase: "registry"
        clairDatabase: "clair"
        notaryServerDatabase: "notary_server"
        notarySignerDatabase: "notary_signer"
        # "disable" - No SSL
        # "require" - Always SSL (skip verification)
        # "verify-ca" - Always SSL (verify that the certificate presented by the
        # server was signed by a trusted CA)
        # "verify-full" - Always SSL (verify that the certification presented by the
        # server was signed by a trusted CA and the server host name matches the one
        # in the certificate)
        sslmode: "disable"
      # The maximum number of connections in the idle connection pool.
      # If it <=0, no idle connections are retained.
      maxIdleConns: 50
      # The maximum number of open connections to the database.
      # If it <= 0, then there is no limit on the number of open connections.
      # Note: the default number of connections is 100 for postgre.
      maxOpenConns: 100
      ## Additional deployment annotations
      podAnnotations: {}
    
    redis:
      # if external Redis is used, set "type" to "external"
      # and fill the connection informations in "external" section
      type: internal
      internal:
        # set the service account to be used, default if left empty
        serviceAccountName: ""
        image:
          repository: goharbor/redis-photon
          tag: v2.0.1
        # resources:
        #  requests:
        #    memory: 256Mi
        #    cpu: 100m
        nodeSelector: {}
        tolerations: []
        affinity: {}
      external:
        host: "192.168.0.2"
        port: "6379"
        # The "coreDatabaseIndex" must be "0" as the library Harbor
        # used doesn't support configuring it
        coreDatabaseIndex: "0"
        jobserviceDatabaseIndex: "1"
        registryDatabaseIndex: "2"
        chartmuseumDatabaseIndex: "3"
        clairAdapterIndex: "4"
        trivyAdapterIndex: "5"
        password: ""
      ## Additional deployment annotations
      podAnnotations: {}
    
  7. helm install harbor harbor/harbor -f values.yaml -n harbor

  8. 更新values.yaml后升级harbor使用helm upgrade -f values.yaml harbor harbor/harbor -n harbor

docker client配置访问harbor

按照前文的配置搭建的harbor环境为:

  • 访问地址: https://172.20.149.141:30003
  • 证书文件为ca.crt, tls.crt, tls.key
  1. mkdir -pv /etc/docker/certs.d/172.20.149.141:30003
  2. cp ca.crt /etc/docker/certs.d/172.20.149.141:30003/
  3. cp tls.key /etc/docker/certs.d/172.20.149.141:30003/172.20.149.141.key
  4. cp tls.cert /etc/docker/certs.d/172.20.149.141:30003/172.20.149.141.cert
  5. systemctl daemon-reload && systemctl restart docker
  6. docker login -u admin -p Harbor12345 172.20.149.141:30003,若登录成功,则一切ojbk