序章

Dockerレジストリは、コンテナ化されたアプリケーションの業界標準である名前付きDockerイメージのストレージおよびコンテンツ配信システムです。 プライベートDockerレジストリを使用すると、パブリックのものと比較して、チームまたは組織内でイメージをより柔軟に制御して安全に共有できます。 プライベートDockerレジストリをKubernetesクラスタで直接ホストすることで、レジストリを制御しながら、より高速、低レイテンシ、より優れた可用性を実現できます。

基盤となるレジストリストレージは、外部ドライバに委任されます。 デフォルトのストレージシステムはローカルファイルシステムですが、これをクラウドベースのストレージドライバーと交換できます。 DigitalOcean Spaces は、大量のデータを保存および提供するためのスケーラブルでシンプルかつ手頃な方法を求める開発者チームや企業向けに設計されたS3互換のオブジェクトストレージであり、Dockerイメージの保存に非常に適しています。 CDNネットワークが組み込まれているため、画像に頻繁にアクセスする際の待ち時間を大幅に短縮できます。

このチュートリアルでは、データを保存するためにDigitalOceanSpacesによってバックアップされたHelm を使用して、プライベートDockerレジストリを DigitalOceanKubernetesクラスターにデプロイします。 指定したスペースのAPIキーを作成し、カスタム構成を使用してDockerレジストリをクラスターにインストールし、Kubernetesを適切に認証するように構成し、クラスターでサンプルデプロイメントを実行してテストします。 このチュートリアルを終了すると、DigitalOceanKubernetesクラスターに安全なプライベートDockerレジストリがインストールされます。

前提条件

このチュートリアルを開始する前に、次のものが必要です。

  • クラスタにアクセスするマシンにインストールされているDocker。 Ubuntu 18.04については、 Ubuntu18.04にDockerをインストールして使用する方法をご覧ください。 ステップ1ステップ2を完了するだけです。 それ以外の場合は、Dockerのウェブサイトにアクセスして他のディストリビューションを入手してください。

  • このチュートリアルで作成するDockerイメージを保存するためのDockerHubのアカウント。

  • クラスターへのアクセスに使用するマシンにGitがインストールされています。 Ubuntu 18.04の場合は、 Ubuntu18.04チュートリアルにGitをインストールする方法のステップ1に従ってください。 その他のプラットフォームについては、公式ウェブサイトにアクセスしてください。

  • 接続構成が次のように構成されたDigitalOceanKubernetesクラスター kubectl デフォルト。 設定方法の説明 kubectl は、クラスターの作成時に表示されるクラスターへの接続ステップの下に表示されます。 DigitalOceanでKubernetesクラスタを作成する方法については、 KubernetesQuickstartをご覧ください。

  • APIキー(アクセスとシークレット)を備えたDigitalOceanスペース。 DigitalOceanスペースとAPIキーを作成する方法については、DigitalOceanスペースとAPIキーを作成する方法を参照してください。

  • ローカルマシンにインストールされているHelmパッケージマネージャー。 これを行うには、Helm3パッケージマネージャーを使用してKubernetesクラスターにソフトウェアをインストールする方法チュートリアルのステップ1を完了します。

  • クラスターにインストールされているNginxIngressControllerとCert-Manager。 これを行う方法のガイドについては、Helmを使用してDigitalOceanKubernetesでNginxIngressを設定する方法を参照してください。

  • Ingressが使用するDigitalOceanロードバランサーを指す2つのDNSAレコードを持つドメイン名。 DigitalOceanを使用してドメインのDNSレコードを管理している場合は、DNSレコードの管理方法を参照してAレコードを作成してください。 このチュートリアルでは、Aレコードを次のように参照します。 registry.your_domaink8s-test.your_domain.

    注:このチュートリアルで使用するドメイン名は、 DigitalOceanKubernetes前提条件チュートリアルでNginxIngressを設定する方法で使用するドメイン名とは異なる必要があります。

ステップ1—Dockerレジストリの構成とインストール

このステップでは、レジストリ展開用の構成ファイルを作成し、Helmパッケージマネージャーを使用して、指定された構成でレジストリをクラスターにインストールします。

このチュートリアルの過程で、次のような構成ファイルを使用します。 chart_values.yaml DockerレジストリHelmchartのデフォルト設定の一部を上書きします。 ヘルムはそのパッケージをチャートと呼んでいます。 これらは、関連するKubernetesリソースの選択の概要を示すファイルのセットです。 設定を編集して、基盤となるストレージシステムとしてDigitalOcean Spacesを指定し、Let’sEncryptTLS証明書を接続してHTTPSアクセスを有効にします。

Nginx Ingress Controllerの前提条件の一部として、サンプルのサービスとイングレスを作成しました。 このチュートリアルではそれらは必要ないため、次のコマンドを実行して削除できます。

  1. kubectl delete -f hello-kubernetes-first.yaml
  2. kubectl delete -f hello-kubernetes-second.yaml
  3. kubectl delete -f hello-kubernetes-ingress.yaml

kubectl delete コマンドは、渡されたときに削除するファイルを受け入れます -f パラメータ。

S3ストレージプロバイダーで問題が発生する公式のDockerレジストリを使用する代わりに、GitLabの Container Registry フォークを使用します。これは、ダウンロードしてビルドする必要があります。

ワークスペースとして機能するフォルダーを作成します。

  1. mkdir ~/k8s-registry

次のコマンドを実行して移動します。

  1. cd ~/k8s-registry

を使用してコンテナレジストリリポジトリをダウンロードします git 次のコマンドを実行します。

  1. git clone https://gitlab.com/gitlab-org/container-registry.git

出力は次のようになります。

Output
Cloning into 'container-registry'... remote: Enumerating objects: 1706, done. ... Resolving deltas: 100% (13955/13955), done.

リポジトリは現在、 container-registry ディレクトリ。 そこに移動します:

  1. cd container-registry

これで、コンテナレジストリのソースコードができました。 クラスタから使用するには、そこからDockerイメージを構築し、DockerHubなどのパブリックレジストリにプッシュする必要があります。

次のコマンドを実行して、最新の安定バージョンのブランチに切り替えます。

  1. git checkout v2.13.1-gitlab

次のコマンドを実行して、レジストリのDockerイメージを作成し、置き換えます your_dockerhub_username Docker Hubユーザー名を使用:

  1. docker build -t your_dockerhub_username/registry:dev .

このコマンドは、完了するまでに時間がかかる場合があります。 出力は長くなり、次のようになります。

Output
... Successfully built 27322ec15cf7 Successfully tagged your_dockerhub_username/registry:dev

イメージが作成されたので、それをアカウントにプッシュするには、最初にログインする必要があります。

  1. docker login

プロンプトが表示されたら、DockerHubのユーザー名とパスワードを入力します。 出力の終わりは次のようになります。

Output
... Login Succeeded

これで、画像をプッシュできます。

  1. docker push your_dockerhub_username/registry:dev

最終的な出力は次のようになります。

Output
The push refers to repository [docker.io/your_dockerhub_username/registry] c3baf7582a54: Pushed bc49969a328b: Pushed 0694fbf8288a: Pushed 3e207b409db3: Mounted from library/alpine dev: digest: sha256:02399157107a1d72312fb4f383f4c8c53a08f3e206d787a9c9380f446b008184 size: 1156

レジストリを作成してプッシュしたので、ワークスペースに戻ります。

  1. cd ~/k8s-registry

あなたの chart_values.yaml お気に入りのテキストエディタを使用したファイル:

  1. nano chart_values.yaml

次の行を追加して、強調表示された行を詳細に置き換えてください。

chart_values.yaml
ingress:
  enabled: true
  hosts:
    - registry.your_domain
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/proxy-body-size: "30720m"
  tls:
    - secretName: docker-registry-prod
      hosts:
        - registry.your_domain

storage: s3

secrets:
  htpasswd: ""
  s3:
    accessKey: "your_space_access_key"
    secretKey: "your_space_secret_key"

s3:
  region: your_space_region
  regionEndpoint: your_space_region.digitaloceanspaces.com
  secure: true
  bucket: your_space_name

image:
  repository: your_dockerhub_username/registry
  tag: dev

最初のブロック、 ingress、Helmチャートのデプロイの一部として作成されるKubernetesIngressを設定します。 Ingressオブジェクトは、外部HTTP / HTTPSルートがクラスター内の内部サービスを指すようにするため、外部からの通信が可能になります。 オーバーライドされる値は次のとおりです。

  • enabled: に設定 true 入力を有効にします。
  • hosts:Ingressがトラフィックを受け入れるホストのリスト。
  • annotations:イングレスの処理方法に関するKubernetesの他の部分へのさらなる方向性を提供するメタデータのリスト。 IngressControllerをに設定します nginx、Let’s Encryptクラスター発行者を本番バリアントに(letsencrypt-prod)、そして nginx 最大サイズが30GBのファイルを受け入れるコントローラー。これは、最大のDockerイメージでも適切な制限です。
  • tls:このサブカテゴリは、Let’sEncryptHTTPSを構成します。 あなたは hosts このIngressがサンプルドメイン名でHTTPSトラフィックを受け入れる安全なホストを定義するリスト。 The secretName (ここでは docker-registry-prod)は、証明書が保存されるシークレットの名前を指定します。通常、作成または展開するIngressごとに異なる必要があります。

次に、ファイルシステムストレージをに設定します s3 —他の利用可能なオプションは filesystem. ここ s3 DigitalOceanSpacesが満たす業界標準のAmazonS3APIと互換性のあるリモートストレージシステムを使用していることを示します。

次のブロックでは、 secrets、DOスペースにアクセスするためのキーを設定します。 s3 サブカテゴリ。 最後に、 s3 ブロックでは、スペースを指定するパラメーターを構成します。

ファイルの最後で、プッシュしたレジストリイメージを、公式のDockerレジストリではなく、デプロイするレジストリイメージとして指定します。

ファイルを保存して閉じます。

ここで、まだ行っていない場合は、前提条件のチュートリアルでNginxIngressControllerのインストールの一部として作成したロードバランサーを指すようにAレコードを設定します。 DigitalOceanでDNSを設定する方法については、DNSレコードの管理方法を参照してください。

Dockerレジストリーをデプロイするチャートは、twuniリポジトリーにあります。 次のコマンドを実行して、Helmに追加します。

  1. helm repo add twuni https://helm.twun.io

そこから何かをインストールする前に、キャッシュを更新する必要があります。 これにより、チャートリポジトリに関する最新情報が更新されます。 これを行うには、次のコマンドを実行します。

  1. helm repo update

次に、次のコマンドを実行して、Helmを介してこのカスタム構成でDockerレジストリチャートをデプロイします。

  1. helm install docker-registry twuni/docker-registry -f chart_values.yaml

次の出力が表示されます。

Output
NAME: docker-registry LAST DEPLOYED: ... NAMESPACE: default STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: 1. Get the application URL by running these commands: https://registry.your_domain/

これで、前に指定したドメイン名からレジストリにアクセスできます。

KubernetesクラスタにDockerレジストリを設定してデプロイしました。 次に、新しくデプロイされたDockerレジストリの可用性をテストします。

ステップ2—プッシュとプルのテスト

このステップでは、イメージをプッシュおよびプルして、新しくデプロイされたDockerレジストリをテストします。 現在、レジストリは空です。 何かをプッシュするには、作業しているマシンで画像を利用できるようにする必要があります。 を使ってみましょう mysql その目的のためのDockerイメージ。

引っ張ることから始めます mysql Docker Hubから:

  1. docker pull mysql

出力は次のようになります。

Output
Using default tag: latest latest: Pulling from library/mysql 27833a3ba0a5: Pull complete ... e906385f419d: Pull complete Digest: sha256:9643e9fbd6330d10686f8922292dcb20995e7b792c17d4e94ddf95255f1d5449 Status: Downloaded newer image for mysql:latest docker.io/library/mysql:latest

これで、画像をローカルで利用できるようになりました。 Dockerにプッシュする場所を通知するには、次のようにホスト名でタグ付けする必要があります。

  1. docker tag mysql registry.your_domain/mysql

次に、イメージを新しいレジストリにプッシュします。

  1. docker push registry.your_domain/mysql

このコマンドは正常に実行され、新しいレジストリが適切に構成され、新しいイメージのプッシュを含むトラフィックを受け入れていることを示します。 エラーが表示された場合は、手順1と2に対して手順を再確認してください。

レジストリからのプルをきれいにテストするには、最初にローカルを削除します mysql 次のコマンドを使用した画像:

  1. docker rmi registry.your_domain/mysql && docker rmi mysql

次に、レジストリからプルします。

  1. docker pull registry.your_domain/mysql

このコマンドは、完了するまでに数秒かかります。 正常に実行された場合は、レジストリが正しく機能していることを意味します。 エラーが表示された場合は、前のコマンドに対して入力した内容を再確認してください。

次のコマンドを実行して、ローカルで使用可能なDockerイメージを一覧表示できます。

  1. docker images

ローカルマシンで使用可能なイメージと、それらのIDおよび作成日を一覧表示する出力が表示されます。

Dockerレジストリが構成されています。 画像をプッシュして、プルダウンできることを確認しました。 次に、認証を追加して、特定の人だけが画像にアクセスできるようにします。

ステップ3—アカウント認証の追加とKubernetesアクセスの設定

このステップでは、を使用してレジストリのユーザー名とパスワードの認証を設定します。 htpasswd 効用。

The htpasswd ユーティリティはApacheWebサーバーから提供され、HTTPユーザーの基本認証用のユーザー名とパスワードを格納するファイルを作成するために使用できます。 のフォーマット htpasswd ファイルは username:hashed_password (1行に1つ)。これは、他のプログラムでも使用できるように十分に移植可能です。

Dockerizedバリアントを使用します htpasswd 簡単にするために。 次のコマンドを実行して、ログインの組み合わせをに追加します htpasswd_file、交換 usernamepassword 希望する資格情報を使用して:

  1. docker run --rm -ti xmartlabs/htpasswd username password >> htpasswd_file

Dockerでは、 bcrypt アルゴリズムを使用してパスワードをハッシュする必要があります。これは、ここで暗黙的に使用されています。 bcryptアルゴリズムは、Blowfishブロック暗号に基づくパスワードハッシュ関数であり、 work factor パラメーターを使用して、ハッシュ関数のコストを指定します。

追加したい数のユーザーに対してこのコマンドを繰り返すことができます。

完了したら、の内容を表示します htpasswd_file 次のコマンドを実行します。

  1. cat htpasswd_file

表示されている内容を選択してコピーします。

Dockerレジストリに認証を追加するには、編集する必要があります chart_values.yaml の内容を追加します htpasswd_file の中に htpasswd 変数。

開ける chart_values.yaml 編集用:

  1. nano chart_values.yaml

次のような行を見つけます。

chart_values.yaml
  htpasswd: ""

以下に一致するように編集し、置き換えます htpasswd\_file\_contents からコピーした内容で htpasswd_file:

chart_values.yaml
  htpasswd: |-
    htpasswd_file_contents

インデントに注意してください。ファイルの内容の各行の前には4つのスペースが必要です。 空白行がある場合は、削除できます。

コンテンツを追加したら、ファイルを保存して閉じます。

変更をクラスターに伝達するには、次のコマンドを実行します。

  1. helm upgrade docker-registry twuni/docker-registry -f chart_values.yaml

出力は、Dockerレジストリを最初にデプロイしたときに表示されるものと同様になります。

Output
Release "docker-registry" has been upgraded. Happy Helming! NAME: docker-registry LAST DEPLOYED: ... NAMESPACE: default STATUS: deployed REVISION: 2 TEST SUITE: None NOTES: 1. Get the application URL by running these commands: https://registry.your_domain/

このコマンドはHelmを呼び出し、既存のリリースをアップグレードするように指示します。 docker-registry、で定義されたチャート stable/docker-registry チャートリポジトリで、適用後 chart_values.yaml ファイル。

ここで、レジストリからイメージを再度プルしてみます。

  1. docker pull registry.your_domain/mysql

出力は次のようになります。

Output
Using default tag: latest Error response from daemon: Get https://registry.your_domain/v2/mysql/manifests/latest: no basic auth credentials

クレデンシャルを指定しなかったため、正しく失敗しました。 これは、Dockerレジストリがリクエストを正しく承認することを意味します。

レジストリにログインするには、次のコマンドを実行します。

  1. docker login registry.your_domain

交換することを忘れないでください registry.your_domain あなたのドメインアドレスで。 ユーザー名とパスワードの入力を求められます。 エラーが表示された場合は、何を再確認してください htpasswd_file が含まれています。 からユーザー名とパスワードの組み合わせを指定する必要があります htpasswd_file、このステップの前半で作成しました。

ログインをテストするには、次のコマンドを実行して、プルを再試行できます。

  1. docker pull registry.your_domain/mysql

出力は次のようになります。

Output
Using default tag: latest latest: Pulling from mysql Digest: sha256:f2dc118ca6fa4c88cde5889808c486dfe94bccecd01ca626b002a010bb66bcbe Status: Image is up to date for registry.your_domain/mysql:latest

これでDockerが構成され、安全にログインできます。 レジストリにログインするようにKubernetesを設定するには、次のコマンドを実行します。

  1. sudo kubectl create secret docker-registry regcred --docker-server=registry.your_domain --docker-username=your_username --docker-password=your_password

このコマンドは、クラスター内に次の名前のシークレットを作成します regcred レジストリのログイン情報が含まれ、次のように解析されます dockerconfigjson、Kubernetesのレジストリクレデンシャルを定義します。

交換することを忘れないでください registry.your_domain レジストリドメインを使用して、前に作成したログインクレデンシャルの1つを代わりに配置します your_usernameyour_password.

次の出力が表示されます。

Output
secret/regcred created

使用した htpasswd ログイン設定ファイルを作成し、リクエストを認証するようにレジストリを設定し、ログイン認証情報を含むKubernetesシークレットを作成します。 次に、Kubernetesクラスターとレジストリ間の統合をテストします。

ステップ4—サンプルデプロイメントを実行してKubernetes統合をテストする

このステップでは、クラスタ内レジストリに保存されているイメージを使用してサンプルデプロイを実行し、Kubernetesクラスタとレジストリ間の接続をテストします。

最後のステップで、あなたはと呼ばれる秘密を作成しました regcred、プライベートレジストリのログイン資格情報が含まれています。 複数のレジストリのログイン資格情報が含まれている場合があります。その場合は、それに応じてシークレットを更新する必要があります。

ポッド定義でコンテナをプルするときにKubernetesが使用するシークレットを指定するには、 imagePullSecrets. この手順は、Dockerレジストリで認証が必要な場合に必要です。

次に、サンプルのHelloWorldイメージをプライベートDockerレジストリからクラスターにデプロイします。 まず、プッシュするために、次のコマンドを実行してマシンにプルします。

  1. docker pull paulbouwer/hello-kubernetes:1.8

次に、次のコマンドを実行してタグを付けます。

  1. docker tag paulbouwer/hello-kubernetes:1.8 registry.your_domain/paulbouwer/hello-kubernetes:1.8

最後に、それをレジストリにプッシュします。

  1. docker push registry.your_domain/paulbouwer/hello-kubernetes:1.8

ローカルで不要になったため、マシンから削除します。

  1. docker rmi registry.your_domain/paulbouwer/hello-kubernetes:1.8

次に、サンプルのHelloWorldアプリケーションをデプロイします。 まず、新しいファイルを作成します。 hello-world.yaml、テキストエディタを使用して:

  1. nano hello-world.yaml

次に、サービスと入力を定義して、クラスターの外部からアプリにアクセスできるようにします。 次の行を追加して、強調表示された行をドメインに置き換えます。

hello-world.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello-kubernetes-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - host: k8s-test.your_domain
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: hello-kubernetes
            port:
              number: 80
---
apiVersion: v1
kind: Service
metadata:
  name: hello-kubernetes
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: hello-kubernetes
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-kubernetes
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-kubernetes
  template:
    metadata:
      labels:
        app: hello-kubernetes
    spec:
      containers:
      - name: hello-kubernetes
        image: registry.your_domain/paulbouwer/hello-kubernetes:1.8
        ports:
        - containerPort: 8080
      imagePullSecrets:
      - name: regcred

最初に、Hello WorldデプロイメントのIngressを定義します。これは、NginxIngressControllerが所有するロードバランサーを介してルーティングされます。 次に、デプロイメントで作成されたポッドにアクセスできるサービスを定義します。 実際の展開仕様では、 image レジストリにあるものとして設定します imagePullSecretsregcred、前の手順で作成しました。

ファイルを保存して閉じます。 これをクラスターにデプロイするには、次のコマンドを実行します。

  1. kubectl apply -f hello-world.yaml

次の出力が表示されます。

Output
ingress.extensions/hello-kubernetes-ingress created service/hello-kubernetes created deployment.apps/hello-kubernetes created

これで、テストドメイン(2番目のAレコード)に移動できます。 k8s-test.your_domain このチュートリアルでは。 Kubernetes Hello world!ページが表示されます。

Hello Worldページには、Linuxカーネルのバージョンやリクエストが提供されたポッドの内部IDなど、いくつかの環境情報が一覧表示されます。 Webインターフェイスを介してスペースにアクセスし、このチュートリアルで使用した画像を確認することもできます。

テスト後にこのHelloWorldデプロイメントを削除する場合は、次のコマンドを実行します。

  1. kubectl delete -f hello-world.yaml

このステップでは、サンプルのHello Worldデプロイメントを作成して、Kubernetesがプライベートレジストリからイメージを適切にプルしているかどうかをテストします。

結論

これで、DigitalOcean Spacesを下のストレージレイヤーとして使用して、独自のプライベートDockerレジストリをDigitalOceanKubernetesクラスターに正常にデプロイできました。 保存できる画像の数に制限はありません。Spacesは無限に拡張でき、同時に同じセキュリティと堅牢性を提供します。 ただし、本番環境では、Dockerイメージを可能な限り最適化するよう常に努力する必要があります。本番環境用にDockerイメージを最適化する方法チュートリアルをご覧ください。