著者はhttps://www.brightfunds.org/funds/foss-nonprofits [無料およびオープンソース基金]を選択して、https://do.co/w4do-cta [Donationsのために書く]の一部として寄付を受け取りましたプログラム。

前書き

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

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

このチュートリアルでは、DigitalOceanによってバックアップされたhttps://helm.sh/[Helm]を使用して、プライベートDockerレジストリをhttps://www.digitalocean.com/products/kubernetes/[DigitalOcean Kubernetes]クラスターにデプロイします。データを保存するためのスペース。 指定されたスペースのAPIキーを作成し、カスタム構成でクラスターにDockerレジストリをインストールし、Kubernetesで適切に認証するように構成し、クラスターでサンプルデプロイを実行してテストします。 このチュートリアルの最後に、DigitalOcean Kubernetesクラスターに安全なプライベートDockerレジストリをインストールします。

前提条件

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

  • クラスターにアクセスするマシンにインストールされたDocker。 Ubuntu 18.04については、https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-18-04 [Ubuntu 18.04にDockerをインストールして使用する方法]にアクセスしてください。 最初のステップを完了するだけです。 それ以外の場合は、他のディストリビューションについてDockerのhttps://docs.docker.com/install/[website]にアクセスしてください。

  • 接続設定が `+ kubectl `デフォルトとして設定されたDigitalOcean Kubernetesクラスター。 ` kubectl +`の設定方法については、クラスターを作成するときに表示される[クラスターに接続]ステップの下に表示されます。 DigitalOceanでKubernetesクラスターを作成する方法については、https://www.digitalocean.com/docs/kubernetes/quickstart/ [Kubernetes Quickstart]を参照してください。

  • APIキー(アクセスおよびシークレット)を持つDigitalOcean Space。 DigitalOceanスペースとAPIキーを作成する方法については、https://www.digitalocean.com/community/tutorials/how-to-create-a-digitalocean-space-and-api-key [DigitalOceanを作成する方法]を参照してください。スペースとAPIキー]。

  • ローカルマシンにインストールされたHelmパッケージマネージャー、およびクラスターにインストールされたTiller。 https://www.digitalocean.com/community/tutorials/how-to-install-software-on-kubernetes-clusters-with-the-helm-package-manager [ソフトウェアのインストール方法]のステップ1と2を完了します。 Helm Package Managerを使用したKubernetesクラスター]。 最初の2つのステップを完了するだけで済みます。

  • クラスタにインストールされたNginx Ingress ControllerおよびCert-Manager。 これを行う方法のガイドについては、https://www.digitalocean.com/community/tutorials/how-to-set-up-an-nginx-ingress-with-cert-manager-on-digitalocean-kubernetes [ DigitalOcean KubernetesでCert-Managerを使用してNginx Ingressをセットアップする方法]。

  • Ingressが使用するDigitalOceanロードバランサーを指す2つのDNS Aレコードを持つドメイン名。 DigitalOceanを使用してドメインのDNSレコードを管理している場合は、https://www.digitalocean.com/docs/networking/dns/how-to/manage-records/ [DNSレコードの管理方法]でAレコードを作成してください。 このチュートリアルでは、Aレコードを「」および「」と呼びます。

手順1-Dockerレジストリの構成とインストール

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

このチュートリアルの過程で、 `+ chart_values.yaml +`という設定ファイルを使用して、DockerレジストリHelm _chart_のデフォルト設定の一部をオーバーライドします。 Helmはそのパッケージをチャートと呼びます。これらは、Kubernetesリソースの関連する選択を概説するファイルのセットです。 設定を編集して、DigitalOcean Spacesを基になるストレージシステムとして指定し、TLS証明書を暗号化することでHTTPSアクセスを有効にします。

前提条件の一部として、テストのために「+ echo1 」および「 echo2 」サービスと「 echo_ingress +」イングレスを作成しました。このチュートリアルではこれらは必要ないので、削除できます。

次のコマンドを実行して、イングレスを削除することから始めます。

kubectl delete -f echo_ingress.yaml

次に、2つのテストサービスを削除します。

kubectl delete -f echo1.yaml && kubectl delete -f echo2.yaml

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

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

mkdir ~/k8s-registry

以下を実行してナビゲートします。

cd ~/k8s-registry

次に、テキストエディターを使用して、 `+ chart_values.yaml +`ファイルを作成します。

nano chart_values.yaml

次の行を追加し、強調表示された行を詳細に置き換えます。

chart_values.yaml

ingress:
 enabled: true
 hosts:
   -
 annotations:
   kubernetes.io/ingress.class: nginx
   certmanager.k8s.io/cluster-issuer: letsencrypt-prod
   nginx.ingress.kubernetes.io/proxy-body-size: "30720m"
 tls:
   - secretName: letsencrypt-prod
     hosts:
       -

storage: s3

secrets:
 htpasswd: ""
 s3:
   accessKey: ""
   secretKey: ""

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

最初のブロック「+ ingress +」は、ヘルムチャート展開​​の一部として作成されるKubernetes Ingressを構成します。 Ingressオブジェクトは、外部HTTP / HTTPSルートがクラスター内の内部サービスを指すようにし、外部からの通信を許可します。 オーバーライドされる値は次のとおりです。

  • + enabled +:Ingressを有効にするために `+ true +`に設定します。

  • + hosts +:イングレスがトラフィックを受け入れるホストのリスト。

  • + annotations +:イングレスの処理方法に関するKubernetesの他の部分へのさらなる指示を提供するメタデータのリスト。 Ingress Controllerを + nginx +`に設定し、Let’s Encryptクラスター発行者をプロダクションバリアント( `+ letsencrypt-prod +)に設定し、 `+ nginx +`コントローラーに最大サイズが30 GBのファイルを受け入れるように指示します。最大のDockerイメージでも合理的な制限です。

  • + tls +:このサブカテゴリは、Let’s Encrypt HTTPSを設定します。 このイングレスがサンプルのドメイン名を持つHTTPSトラフィックを受け入れるセキュアホストを定義する `+ hosts +`リストを作成します。

次に、ファイルシステムのストレージを「+ s3 」に設定します-他の利用可能なオプションは「 filesystem 」です。 ここで、「 s3 +」は、DigitalOcean Spacesが満たす業界標準のAmazon S3 APIと互換性のあるリモートストレージシステムを使用することを示します。

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

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

ここで、まだ行っていない場合は、前提条件のチュートリアルでNginx Ingress Controllerのインストールの一部として作成したロードバランサーを指すようにAレコードを設定します。 DigitalOceanでDNSを設定する方法については、https://www.digitalocean.com/docs/networking/dns/how-to/manage-records/ [DNSレコードの管理方法]を参照してください。

次に、スペースが空でないことを確認します。 スペースにファイルがない場合、Dockerレジストリはまったく実行されません。 これを回避するには、ファイルをアップロードします。 [スペース]タブに移動してスペースを見つけ、[*ファイルのアップロード]ボタンをクリックして、必要なファイルをアップロードします。 作成した構成ファイルをアップロードできます。

image:https://assets.digitalocean.com/articles/registry_spaces_k8s/step2.png [空のスペースにアップロードされた空のファイル]

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

helm repo update

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

helm install  -f chart_values.yaml --name

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

OutputNAME:   docker-registry
...
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/ConfigMap
NAME                    DATA  AGE
docker-registry-config  1     1s

==> v1/Pod(related)
NAME                              READY  STATUS             RESTARTS  AGE
docker-registry-54df68fd64-l26fb  0/1    ContainerCreating  0         1s

==> v1/Secret
NAME                    TYPE    DATA  AGE
docker-registry-secret  Opaque  3     1s

==> v1/Service
NAME             TYPE       CLUSTER-IP      EXTERNAL-IP  PORT(S)   AGE
docker-registry  ClusterIP  10.245.131.143  <none>       5000/TCP  1s

==> v1beta1/Deployment
NAME             READY  UP-TO-DATE  AVAILABLE  AGE
docker-registry  0/1    1           0          1s

==> v1beta1/Ingress
NAME             HOSTS                 ADDRESS  PORTS  AGE
docker-registry    80, 443  1s


NOTES:
1. Get the application URL by running these commands:
 https:///

Helmは、Dockerレジストリチャート展開​​の結果として作成したすべてのリソースを一覧表示します。 これで、以前に指定したドメイン名からレジストリにアクセスできます。

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

ステップ2-プッシュおよびプルのテスト

この手順では、新しく展開したDockerレジストリをテストし、そこに画像をプッシュおよびプルします。 現在、レジストリは空です。 プッシュするものを使用するには、作業元のマシンで画像を使用できるようにする必要があります。 + mysql Dockerイメージを使用しましょう。

Docker Hubから `+ mysql +`をプルすることから始めます。

sudo docker pull mysql

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

OutputUsing default tag: latest
latest: Pulling from library/mysql
27833a3ba0a5: Pull complete
...
e906385f419d: Pull complete
Digest: sha256:a7cf659a764732a27963429a87eccc8457e6d4af0ee9d5140a3b56e74986eed7
Status: Downloaded newer image for mysql:latest

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

sudo docker tag mysql /mysql

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

sudo docker push /mysql

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

レジストリからのプルをきれいにテストするには、最初に次のコマンドでローカルの `+ mysql +`イメージを削除します:

sudo docker rmi /mysql && sudo docker rmi mysql

次に、レジストリから取得します。

sudo docker pull /mysql

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

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

sudo docker images

ローカルマシンで使用可能な画像のリストと、IDおよび作成日が出力されます。

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

手順3-アカウント認証の追加とKubernetesアクセスの構成

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

+ htpasswd +`ユーティリティはApache Webサーバーから提供され、HTTPユーザーの基本認証用のユーザー名とパスワードを保存するファイルの作成に使用できます。 `+ htpasswd +`ファイルの形式は `+ username:hashed_pa​​ssword +(1行に1つ)で、他のプログラムでも同様に使用できるほど移植性があります。

システムで `+ htpasswd +`を使用できるようにするには、次を実行してインストールする必要があります。

sudo apt install apache2-utils -y

次のコマンドを実行して作成します。

touch

ユーザー名とパスワードの組み合わせを「++」に追加します。

htpasswd -B htpasswd_file

Dockerではhttps://en.wikipedia.org/wiki/Bcrypt[bcrypt]アルゴリズムを使用してパスワードをハッシュする必要があるため、 `+ -B +`パラメーターを渡します。 bcryptアルゴリズムは、Blowfishブロック暗号に基づくパスワードハッシュ関数であり、_work factor_パラメーターを使用して、ハッシュ関数のコストを指定します。

`+`を希望のユーザー名に置き換えてください。 実行すると、 ` htpasswd `は付随するパスワードを尋ね、その組み合わせを ` htpasswd_file +`に追加します。 追加するユーザーの数だけこのコマンドを繰り返すことができます。

次のコマンドを実行して、 `+ htpasswd_file +`の内容を表示します。

cat

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

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

編集のために `+ chart_values.yaml +`を開きます:

nano chart_values.yaml

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

chart_values.yaml

 htpasswd: ""

次のように編集して、「」を「」からコピーした内容に置き換えます。

chart_values.yaml

 htpasswd: |-

インデントに注意してください。ファイルの内容の各行の前には4つのスペースが必要です。

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

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

helm upgrade docker-registry stable/docker-registry -f chart_values.yaml

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

OutputRelease "docker-registry" has been upgraded. Happy Helming!
LAST DEPLOYED: ...
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/ConfigMap
NAME                    DATA  AGE
docker-registry-config  1     3m8s

==> v1/Pod(related)
NAME                              READY  STATUS   RESTARTS  AGE
docker-registry-6c5bb7ffbf-ltnjv  1/1    Running  0         3m7s

==> v1/Secret
NAME                    TYPE    DATA  AGE
docker-registry-secret  Opaque  4     3m8s

==> v1/Service
NAME             TYPE       CLUSTER-IP      EXTERNAL-IP  PORT(S)   AGE
docker-registry  ClusterIP  10.245.128.245  <none>       5000/TCP  3m8s

==> v1beta1/Deployment
NAME             READY  UP-TO-DATE  AVAILABLE  AGE
docker-registry  1/1    1           1          3m8s

==> v1beta1/Ingress
NAME             HOSTS                ADDRESS        PORTS    AGE
docker-registry    159.89.215.50  80, 443  3m8s


NOTES:
1. Get the application URL by running these commands:
 https:///

このコマンドはHelmを呼び出し、既存のリリース(あなたの場合は + docker-registry +)をアップグレードするように指示します。ファイル。

ここで、レジストリから画像をもう一度取得してみます。

sudo docker pull /mysql

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

OutputUsing default tag: latest
Error response from daemon: Get /v2/mysql/manifests/latest: no basic auth credentials

資格情報を提供しなかったため、正しく失敗しました。 これは、Dockerレジストリがリクエストを正しく承認することを意味します。

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

sudo docker login

`+`をドメインアドレスに置き換えることを忘れないでください。 ユーザー名とパスワードの入力を求められます。 エラーが表示された場合は、 ` htpasswd_file `の内容を再確認してください。 このステップの前半で作成した ` htpasswd_file +`でユーザー名とパスワードの組み合わせを定義する必要があります。

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

sudo docker pull /mysql

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

OutputUsing default tag: latest
latest: Pulling from mysql
Digest: sha256:f2dc118ca6fa4c88cde5889808c486dfe94bccecd01ca626b002a010bb66bcbe
Status: Image is up to date for registry.example.com/mysql:latest

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

sudo kubectl create secret generic regcred --from-file=.dockerconfigjson=/home//.docker/config.json --type=kubernetes.io/dockerconfigjson

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

Outputsecret/regcred created

このコマンドは、クラスターに「+ regcred 」という名前のシークレットを作成し、Dockerがクレデンシャルを保存するJSONファイルのコンテンツを取得し、それをKubernetesのレジストリクレデンシャルを定義する「 dockerconfigjson +」として解析します。

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

手順4-サンプル展開を実行してKubernetes統合をテストする

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

最後のステップでは、プライベートレジストリのログイン認証情報を含む、「+ regcred +」という名前のシークレットを作成しました。 複数のレジストリのログイン認証情報が含まれている場合があります。その場合、それに応じてシークレットを更新する必要があります。

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

次に、サンプルhttps://github.com/paulbouwer/hello-kubernetes/blob/master/Dockerfile[Hello World image]をプライベートDockerレジストリからクラスターにデプロイします。 まず、それをプッシュするには、次のコマンドを実行してマシンにプルします。

sudo docker pull paulbouwer/hello-kubernetes:1.5

次に、次を実行してタグを付けます。

sudo docker tag paulbouwer/hello-kubernetes:1.5 /paulbouwer/hello-kubernetes:1.5

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

sudo docker push /paulbouwer/hello-kubernetes:1.5

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

sudo docker rmi /paulbouwer/hello-kubernetes:1.5

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

nano hello-world.yaml

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

hello-world.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
 name: hello-kubernetes-ingress
 annotations:
   kubernetes.io/ingress.class: nginx
   nginx.ingress.kubernetes.io/rewrite-target: /
spec:
 rules:
 - host:
   http:
     paths:
     - path: /
       backend:
         serviceName: hello-kubernetes
         servicePort: 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: /paulbouwer/hello-kubernetes:1.5
       ports:
       - containerPort: 8080
     imagePullSecrets:
     - name: regcred

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

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

kubectl apply -f hello-world.yaml

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

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

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

image:https://assets.digitalocean.com/articles/registry_spaces_k8s/step5.png [Hello World page]

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

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

kubectl delete -f hello-world.yaml

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

結論

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