1
0

More than 1 year has passed since last update.

学習用Kubernetes環境を作る3 Kubernetes上にKubernetes用プライベートDockerレジストリHarbor環境を作る/httpなDockerレジストリをDocker・containerdで使う

Last updated at Posted at 2021-09-02

はじめに

注意:今回作る環境は,初心者が学習用に作成したものです.
決して本番環境等,外部に公開するような重要な環境ではそのままの手順通りで行わないで下さい.
また,insecureな設定やベストプラクティスから外れた運用をしている箇所があります.

学習用Kubernetes環境を作るの第3回です.

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について

Part 3 学習用Kubernetes環境を作る3 Kubernetes上にKubernetes用プライベートDockerレジストリHarbor環境を作る/httpなDockerレジストリをDocker・containerdで使う

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

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

Harbor用PVを作成

HarborをHelmでインストールする前に,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をapplyします.

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=パスワード

namespaceは,harbor-systemです.

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

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

ブラウザで,

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

を開けば,ユーザー名adminと設定したパスワードでログインできます.

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

ログイン後,+NEW PROJECTから動作テスト用のプロジェクトを作成します.

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

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

今回,NodePortのhttpでデプロイしましたが,Dockerはデフォルトでは,httpsでないとLoginしたり,Pullしたり出来ません.

なので,今回作ったレジストリを使用できるように設定する必要があります.

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"を設定し,Apply&Restartを選択すれば良い.

Windows Server等の場合は,C:\ProgramData\docker\config\に,上記と同内容のdaemon.jsonを作成して下さい(動作未確認).

Dockerでログイン

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

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

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

Login Successとなれば,成功です.

テスト用イメージをPush

適当にnginxのイメージをPullします.

docker pull nginx

Pushする先のtagをつけます(自分のコンテナイメージを使う時は,ビルド時に指定すれば良い).

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

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

Pushします.

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

問題なく,Pull出来れば,Pullしたイメージを削除します.

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

Kubernetesでレジストリの認証情報を持ったsecretを作成

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

また,secretは使用するnamespace毎に,作成する必要があります.

Dockerの認証情報を用いる場合は,以下の通りです.

デフォルトnamespaceに作成する場合,『-n namespace名』の部分は不要です(以降).

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 .
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0