创建一个用于学习的Kubernetes环境,在Kubernetes上构建Kubernetes专用的私有Docker注册表Harbor环境,并使用Docker和containerd来使用HTTP协议的Docker注册表

首先

请注意:本次创建的环境是为初学者设计的学习用途。
绝对不能按照原来的步骤直接在正式环境或其他外部环境中公开。
此外,存在不安全的配置和违反最佳实践的操作部分。

创建Kubernetes环境的学习是第三部分。

Part 1 学習用Kubernetes環境を作る1 Ubuntu 20.04 LTS+kubeadm+containerd+CalicoなKubernetes環境をHyper-V上にTailscaleの固定IPで構築

Part 2 学習用Kubernetes環境を作る2 動的PVが使えない環境でKubernetes管理WebUIのPortainer環境を作る/データ永続化/NodePortについて

第三部分 创建用于学习的Kubernetes环境:在Kubernetes上构建适用于Kubernetes的私有Docker注册表Harbor环境,使用HTTP的Docker注册表并在Docker和containerd中使用它。

KubernetesでDockerコンテナを利用出来るようにローカルにプライベートDockerレジストリーを作成します.

Kubernetesの環境は,第1回,第2回で構築した環境を前提としています.

创建一个Harbor私有仓库的PV。

在使用Helm之前安装Harbor之前,需要创建Harbor使用的持久卷(PV)。

今回は,個人的に管理しやすいという都合上,全てのPVC毎にSCを作成します.

在创建PV之前,创建PV的实际存储位置。

cd /mnt/kubernetes

sudo mkdir harbor

cd harbor

sudo mkdir chartmuseum  database  jobservice  redis  registry  trivy

chmod 777 chartmuseum  database  jobservice  redis  registry  trivy

PVを作成するymlをharbor-vol.ymlという名前で作成します.

内容如下。

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: harbor-registry
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: harbor-registry-pv
spec:
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: harbor-registry
  local:
    path: /mnt/kubernetes/harbor/registry
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
            - key: kubernetes.io/hostname
              operator: In
              values:
                - ノード名
---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: harbor-chartmuseum
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: harbor-chartmuseum-pv
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: harbor-chartmuseum
  local:
    path: /mnt/kubernetes/harbor/chartmuseum
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
            - key: kubernetes.io/hostname
              operator: In
              values:
                - ノード名
---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: harbor-jobservice
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: harbor-jobservice-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: harbor-jobservice
  local:
    path: /mnt/kubernetes/harbor/jobservice
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
            - key: kubernetes.io/hostname
              operator: In
              values:
                - ノード名
---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: harbor-database
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: harbor-database-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: harbor-database
  local:
    path: /mnt/kubernetes/harbor/database
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
            - key: kubernetes.io/hostname
              operator: In
              values:
                - ノード名
---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: harbor-redis
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: harbor-redis-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: harbor-redis
  local:
    path: /mnt/kubernetes/harbor/redis
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
            - key: kubernetes.io/hostname
              operator: In
              values:
                - ノード名
---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: harbor-trivy
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: harbor-trivy-pv
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: harbor-trivy
  local:
    path: /mnt/kubernetes/harbor/trivy
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
            - key: kubernetes.io/hostname
              operator: In
              values:
                - ノード名

レジストリのPVは,PVCデフォルトの5GBだと少ない気がしたので,20GBに増やしています.

除了注册表的PV以外,指定了PVC所指定的容量。

我将应用此yml文件。

kubectl apply -f harbor-vol.yml

接下来,我们需要添加Harbor的Helm仓库。

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

实际上,将安装Harbor。

helm install --create-namespace -n harbor-system harbor harbor/harbor \
  --set expose.type=nodePort --set expose.tls.enabled=false \
  --set persistence.persistentVolumeClaim.registry.storageClass=harbor-registry --set persistence.persistentVolumeClaim.registry.size=20Gi \
  --set persistence.persistentVolumeClaim.chartmuseum.storageClass=harbor-chartmuseum \
  --set persistence.persistentVolumeClaim.jobservice.storageClass=harbor-jobservice \
  --set persistence.persistentVolumeClaim.database.storageClass=harbor-database \
  --set persistence.persistentVolumeClaim.redis.storageClass=harbor-redis \
  --set persistence.persistentVolumeClaim.trivy.storageClass=harbor-trivy \
  --set externalURL=http://tailscaleのmagicDNS(小文字):30002 --set harborAdminPassword=パスワード

命名空间是harbor-system。

Portainerと同じくデフォルトSCを使用する場合は,persistence.persistentVolumeClaimをセットする必要はありません.

また,レジストリのサイズをデフォルトの5GBにした場合,persistence.persistentVolumeClaim.registry.sizeの指定は不要です.

ブラウザで,

http://tailscaleのmagicDNS(小文字):30002

当您打开时,您可以使用用户名admin和设置的密码进行登录。

テスト用プロジェクトを作成します

登录后,从“+新项目”创建一个用于操作测试的项目。

今回は,認証のテストをしたいので,Privateなレジストリをtestという名前で作成します.

使私有Docker注册表可用于Docker。

这次我们在NodePort上部署了HTTP,但是默认情况下,Docker需要使用HTTPS才能进行登录和拉取操作。

因此,需要设定以便能够使用本次创建的注册表。

Linux上のDockerであれば以下の通りです.

/etc/docker/daemon.jsonを以下のように編集し,Dockerデーモンの設定を変更します.

既に設定がある場合,前の要素の末尾に『,』を追加して次の行に”insecure-registries”の要素を記述して下さい.

{
    "insecure-registries": [
        "tailscaleのmagicDNS(小文字):30002"
    ]
}

重新启动Docker守护程序。

sudo systemctl restart docker

如果使用Docker Desktop,可以点击齿轮图标->进入Docker Engine,然后在现有的insecure-registries上设置”tailscale的magicDNS(小写):30002″,选择应用并重新启动即可。

如果是Windows Server等服务器,请在C:\ProgramData\docker\config\目录下创建与上述相同内容的daemon.json文件(未经验证)。

使用Docker登录

Dockerでログインし,認証が必要なプロジェクトのレジストリにPush出来るようにします.

以下のようなコマンドでログインします.

docker login -u admin -p Helmでインストール時に設定したパスワード http://tailscaleのmagicDNS(小文字):30002

当成功登录时,表示登录成功。

推送测试图像

隨意拉取一個nginx的映像。

docker pull nginx

在指定Push的tag之前(当使用自己的容器映像时,只需在构建时进行指定即可)。

先程,作成したtestプロジェクトのタグを付けます.

docker tag nginx tailscaleのmagicDNS(小文字):30002/test/nginx

按下按钮。

docker push tailscaleのmagicDNS(小文字):30002/test/nginx

Kubernetes(containerd)でもプライベートDockerレジストリを使えるようにする

KubernetesのCRIとして採用したcontainerdも,デフォルトではhttpsでないとPull出来ないので,今回作ったレジストリを使用できるようにcontainerdを,設定する必要があります.

请按照以下方式编辑/etc/containerd/config.toml。

只有使用tailscale的magicDNS部分进行了补充。

                            (前略)
    [plugins."io.containerd.grpc.v1.cri".registry]
      [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
          endpoint = ["https://registry-1.docker.io"]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."tailscaleのmagicDNS(小文字):30002"]
          endpoint = ["http:/tailscaleのmagicDNS(小文字):30002"]
                            (後略)

如果更改设置,将重新启动containerd。

sudo systemctl restart containerd

我将通过containerd来确认是否可以使用私有注册表。

sudo ctr image pull -u admin:パスワード tailscaleのmagicDNS(小文字):30002/test/nginx

如果能够无问题地解决,我会删除已进行的图像推送。

sudo ctr image rm tailscaleのmagicDNS(小文字):30002/test/nginx

使用Kubernetes创建一个具有注册表认证信息的密钥。

HarborはPullに認証が必要なPrivateと不要なPublicレジストリがありますが,認証が必要な場合は以下のようにして,secretを作る必要があります.

此外,在每个使用的命名空间中,需要创建一个名为“secret”的对象。

如果使用Docker的身份验证信息,则如下所示。

如果在默认命名空间中创建,不需要” -n 命名空间名称”的部分(后文)。

kubectl -n namespace名 create secret generic secret名 \
  --from-file=.dockerconfigjson=$HOME/.docker/config.json \
  --type=kubernetes.io/dockerconfigjson

创建一个包含其他注册表的认证信息和多个认证信息的secret是最佳方法。

Docker環境で,サーバーのkubectlが使えない場合や,secretの認証情報を単一にしたい場合は,以下の通りです.

kubectl -n namespace名 create secret docker-registry secret名 \
  --docker-server=http://tailscaleのmagicDNS(小文字):30002  \
  --docker-username=admin \
  --docker-password=パスワード

プライベートレジストリのイメージを使用したアプリケーションを実際にデプロイ

テスト用のアプリケーションとして,以下のようなymlをtest.ymlという名前で作成します.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test
  template:
    metadata:
      labels:
        app: test
    spec:
      containers:
        - name: nginx
          image: tailscaleのmagicDNS(小文字):30002/test/nginx
      imagePullSecrets:
        - name: secret名
---
apiVersion: v1
kind: Service
metadata:
  name: test-service
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      nodePort: 32767
      protocol: TCP
  selector:
    app: test

前回のymlのイメージ取得先を変更しています.

kubectl apply -f test.yml

如果与上次确认的情况相同,并且没有问题的话,那么就算成功了。

Pod的状态不是ErrImagePull或ImagePullBackOff是很重要的。

余談:DockerでマルチCPUアーキテクチャ対応のイメージをPushする

Harborは,マルチCPUアーキテクチャ対応のDockerレジストリですが,上記のDockerデーモンの設定変更は,マルチCPUアーキテクチャ対応のイメージについては無意味です.

在使用push命令时,需要设置registry.insecure=true选项。

docker buildx build --platform linux/amd64,linux/arm64 -t tailscaleのmagicDNS(小文字):30002/プロジェクト名/イメージ名 --output=type=image,push=true,registry.insecure=true .
bannerAds