DigitalOceanスペースの上にプライベートDockerレジストリを設定し、DigitalOceanKubernetesで使用する方法
序章
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_domain
とk8s-test.your_domain
.注:このチュートリアルで使用するドメイン名は、 DigitalOceanKubernetes前提条件チュートリアルでNginxIngressを設定する方法で使用するドメイン名とは異なる必要があります。
ステップ1—Dockerレジストリの構成とインストール
このステップでは、レジストリ展開用の構成ファイルを作成し、Helmパッケージマネージャーを使用して、指定された構成でレジストリをクラスターにインストールします。
このチュートリアルの過程で、次のような構成ファイルを使用します。 chart_values.yaml
DockerレジストリHelmchartのデフォルト設定の一部を上書きします。 ヘルムはそのパッケージをチャートと呼んでいます。 これらは、関連するKubernetesリソースの選択の概要を示すファイルのセットです。 設定を編集して、基盤となるストレージシステムとしてDigitalOcean Spacesを指定し、Let’sEncryptTLS証明書を接続してHTTPSアクセスを有効にします。
Nginx Ingress Controllerの前提条件の一部として、サンプルのサービスとイングレスを作成しました。 このチュートリアルではそれらは必要ないため、次のコマンドを実行して削除できます。
- kubectl delete -f hello-kubernetes-first.yaml
- kubectl delete -f hello-kubernetes-second.yaml
- kubectl delete -f hello-kubernetes-ingress.yaml
kubectl delete
コマンドは、渡されたときに削除するファイルを受け入れます -f
パラメータ。
S3ストレージプロバイダーで問題が発生する公式のDockerレジストリを使用する代わりに、GitLabの Container Registry フォークを使用します。これは、ダウンロードしてビルドする必要があります。
ワークスペースとして機能するフォルダーを作成します。
- mkdir ~/k8s-registry
次のコマンドを実行して移動します。
- cd ~/k8s-registry
を使用してコンテナレジストリリポジトリをダウンロードします git
次のコマンドを実行します。
- git clone https://gitlab.com/gitlab-org/container-registry.git
出力は次のようになります。
OutputCloning into 'container-registry'...
remote: Enumerating objects: 1706, done.
...
Resolving deltas: 100% (13955/13955), done.
リポジトリは現在、 container-registry
ディレクトリ。 そこに移動します:
- cd container-registry
これで、コンテナレジストリのソースコードができました。 クラスタから使用するには、そこからDockerイメージを構築し、DockerHubなどのパブリックレジストリにプッシュする必要があります。
次のコマンドを実行して、最新の安定バージョンのブランチに切り替えます。
- git checkout v2.13.1-gitlab
次のコマンドを実行して、レジストリのDockerイメージを作成し、置き換えます your_dockerhub_username
Docker Hubユーザー名を使用:
- docker build -t your_dockerhub_username/registry:dev .
このコマンドは、完了するまでに時間がかかる場合があります。 出力は長くなり、次のようになります。
Output...
Successfully built 27322ec15cf7
Successfully tagged your_dockerhub_username/registry:dev
イメージが作成されたので、それをアカウントにプッシュするには、最初にログインする必要があります。
- docker login
プロンプトが表示されたら、DockerHubのユーザー名とパスワードを入力します。 出力の終わりは次のようになります。
Output...
Login Succeeded
これで、画像をプッシュできます。
- docker push your_dockerhub_username/registry:dev
最終的な出力は次のようになります。
OutputThe 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
レジストリを作成してプッシュしたので、ワークスペースに戻ります。
- cd ~/k8s-registry
あなたの chart_values.yaml
お気に入りのテキストエディタを使用したファイル:
- nano 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トラフィックを受け入れる安全なホストを定義するリスト。 ThesecretName
(ここではdocker-registry-prod
)は、証明書が保存されるシークレットの名前を指定します。通常、作成または展開するIngressごとに異なる必要があります。
次に、ファイルシステムストレージをに設定します s3
—他の利用可能なオプションは filesystem
. ここ s3
DigitalOceanSpacesが満たす業界標準のAmazonS3APIと互換性のあるリモートストレージシステムを使用していることを示します。
次のブロックでは、 secrets
、DOスペースにアクセスするためのキーを設定します。 s3
サブカテゴリ。 最後に、 s3
ブロックでは、スペースを指定するパラメーターを構成します。
ファイルの最後で、プッシュしたレジストリイメージを、公式のDockerレジストリではなく、デプロイするレジストリイメージとして指定します。
ファイルを保存して閉じます。
ここで、まだ行っていない場合は、前提条件のチュートリアルでNginxIngressControllerのインストールの一部として作成したロードバランサーを指すようにAレコードを設定します。 DigitalOceanでDNSを設定する方法については、DNSレコードの管理方法を参照してください。
Dockerレジストリーをデプロイするチャートは、twuniリポジトリーにあります。 次のコマンドを実行して、Helmに追加します。
- helm repo add twuni https://helm.twun.io
そこから何かをインストールする前に、キャッシュを更新する必要があります。 これにより、チャートリポジトリに関する最新情報が更新されます。 これを行うには、次のコマンドを実行します。
- helm repo update
次に、次のコマンドを実行して、Helmを介してこのカスタム構成でDockerレジストリチャートをデプロイします。
- helm install docker-registry twuni/docker-registry -f chart_values.yaml
次の出力が表示されます。
OutputNAME: 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から:
- docker pull mysql
出力は次のようになります。
OutputUsing 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にプッシュする場所を通知するには、次のようにホスト名でタグ付けする必要があります。
- docker tag mysql registry.your_domain/mysql
次に、イメージを新しいレジストリにプッシュします。
- docker push registry.your_domain/mysql
このコマンドは正常に実行され、新しいレジストリが適切に構成され、新しいイメージのプッシュを含むトラフィックを受け入れていることを示します。 エラーが表示された場合は、手順1と2に対して手順を再確認してください。
レジストリからのプルをきれいにテストするには、最初にローカルを削除します mysql
次のコマンドを使用した画像:
- docker rmi registry.your_domain/mysql && docker rmi mysql
次に、レジストリからプルします。
- docker pull registry.your_domain/mysql
このコマンドは、完了するまでに数秒かかります。 正常に実行された場合は、レジストリが正しく機能していることを意味します。 エラーが表示された場合は、前のコマンドに対して入力した内容を再確認してください。
次のコマンドを実行して、ローカルで使用可能なDockerイメージを一覧表示できます。
- docker images
ローカルマシンで使用可能なイメージと、それらのIDおよび作成日を一覧表示する出力が表示されます。
Dockerレジストリが構成されています。 画像をプッシュして、プルダウンできることを確認しました。 次に、認証を追加して、特定の人だけが画像にアクセスできるようにします。
ステップ3—アカウント認証の追加とKubernetesアクセスの設定
このステップでは、を使用してレジストリのユーザー名とパスワードの認証を設定します。 htpasswd
効用。
The htpasswd
ユーティリティはApacheWebサーバーから提供され、HTTPユーザーの基本認証用のユーザー名とパスワードを格納するファイルを作成するために使用できます。 のフォーマット htpasswd
ファイルは username:hashed_password
(1行に1つ)。これは、他のプログラムでも使用できるように十分に移植可能です。
Dockerizedバリアントを使用します htpasswd
簡単にするために。 次のコマンドを実行して、ログインの組み合わせをに追加します htpasswd_file
、交換 username
と password
希望する資格情報を使用して:
- docker run --rm -ti xmartlabs/htpasswd username password >> htpasswd_file
Dockerでは、 bcrypt アルゴリズムを使用してパスワードをハッシュする必要があります。これは、ここで暗黙的に使用されています。 bcryptアルゴリズムは、Blowfishブロック暗号に基づくパスワードハッシュ関数であり、 work factor パラメーターを使用して、ハッシュ関数のコストを指定します。
追加したい数のユーザーに対してこのコマンドを繰り返すことができます。
完了したら、の内容を表示します htpasswd_file
次のコマンドを実行します。
- cat htpasswd_file
表示されている内容を選択してコピーします。
Dockerレジストリに認証を追加するには、編集する必要があります chart_values.yaml
の内容を追加します htpasswd_file
の中に htpasswd
変数。
開ける chart_values.yaml
編集用:
- nano chart_values.yaml
次のような行を見つけます。
htpasswd: ""
以下に一致するように編集し、置き換えます htpasswd\_file\_contents
からコピーした内容で htpasswd_file
:
htpasswd: |-
htpasswd_file_contents
インデントに注意してください。ファイルの内容の各行の前には4つのスペースが必要です。 空白行がある場合は、削除できます。
コンテンツを追加したら、ファイルを保存して閉じます。
変更をクラスターに伝達するには、次のコマンドを実行します。
- helm upgrade docker-registry twuni/docker-registry -f chart_values.yaml
出力は、Dockerレジストリを最初にデプロイしたときに表示されるものと同様になります。
OutputRelease "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
ファイル。
ここで、レジストリからイメージを再度プルしてみます。
- docker pull registry.your_domain/mysql
出力は次のようになります。
OutputUsing default tag: latest
Error response from daemon: Get https://registry.your_domain/v2/mysql/manifests/latest: no basic auth credentials
クレデンシャルを指定しなかったため、正しく失敗しました。 これは、Dockerレジストリがリクエストを正しく承認することを意味します。
レジストリにログインするには、次のコマンドを実行します。
- docker login registry.your_domain
交換することを忘れないでください registry.your_domain
あなたのドメインアドレスで。 ユーザー名とパスワードの入力を求められます。 エラーが表示された場合は、何を再確認してください htpasswd_file
が含まれています。 からユーザー名とパスワードの組み合わせを指定する必要があります htpasswd_file
、このステップの前半で作成しました。
ログインをテストするには、次のコマンドを実行して、プルを再試行できます。
- docker pull registry.your_domain/mysql
出力は次のようになります。
OutputUsing default tag: latest
latest: Pulling from mysql
Digest: sha256:f2dc118ca6fa4c88cde5889808c486dfe94bccecd01ca626b002a010bb66bcbe
Status: Image is up to date for registry.your_domain/mysql:latest
これでDockerが構成され、安全にログインできます。 レジストリにログインするようにKubernetesを設定するには、次のコマンドを実行します。
- 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_username
と your_password
.
次の出力が表示されます。
Outputsecret/regcred created
使用した htpasswd
ログイン設定ファイルを作成し、リクエストを認証するようにレジストリを設定し、ログイン認証情報を含むKubernetesシークレットを作成します。 次に、Kubernetesクラスターとレジストリ間の統合をテストします。
ステップ4—サンプルデプロイメントを実行してKubernetes統合をテストする
このステップでは、クラスタ内レジストリに保存されているイメージを使用してサンプルデプロイを実行し、Kubernetesクラスタとレジストリ間の接続をテストします。
最後のステップで、あなたはと呼ばれる秘密を作成しました regcred
、プライベートレジストリのログイン資格情報が含まれています。 複数のレジストリのログイン資格情報が含まれている場合があります。その場合は、それに応じてシークレットを更新する必要があります。
ポッド定義でコンテナをプルするときにKubernetesが使用するシークレットを指定するには、 imagePullSecrets
. この手順は、Dockerレジストリで認証が必要な場合に必要です。
次に、サンプルのHelloWorldイメージをプライベートDockerレジストリからクラスターにデプロイします。 まず、プッシュするために、次のコマンドを実行してマシンにプルします。
- docker pull paulbouwer/hello-kubernetes:1.8
次に、次のコマンドを実行してタグを付けます。
- docker tag paulbouwer/hello-kubernetes:1.8 registry.your_domain/paulbouwer/hello-kubernetes:1.8
最後に、それをレジストリにプッシュします。
- docker push registry.your_domain/paulbouwer/hello-kubernetes:1.8
ローカルで不要になったため、マシンから削除します。
- docker rmi registry.your_domain/paulbouwer/hello-kubernetes:1.8
次に、サンプルのHelloWorldアプリケーションをデプロイします。 まず、新しいファイルを作成します。 hello-world.yaml
、テキストエディタを使用して:
- nano 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
レジストリにあるものとして設定します 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レコード)に移動できます。 k8s-test.your_domain
このチュートリアルでは。 Kubernetes Hello world!ページが表示されます。
Hello Worldページには、Linuxカーネルのバージョンやリクエストが提供されたポッドの内部IDなど、いくつかの環境情報が一覧表示されます。 Webインターフェイスを介してスペースにアクセスし、このチュートリアルで使用した画像を確認することもできます。
テスト後にこのHelloWorldデプロイメントを削除する場合は、次のコマンドを実行します。
- kubectl delete -f hello-world.yaml
このステップでは、サンプルのHello Worldデプロイメントを作成して、Kubernetesがプライベートレジストリからイメージを適切にプルしているかどうかをテストします。
結論
これで、DigitalOcean Spacesを下のストレージレイヤーとして使用して、独自のプライベートDockerレジストリをDigitalOceanKubernetesクラスターに正常にデプロイできました。 保存できる画像の数に制限はありません。Spacesは無限に拡張でき、同時に同じセキュリティと堅牢性を提供します。 ただし、本番環境では、Dockerイメージを可能な限り最適化するよう常に努力する必要があります。本番環境用にDockerイメージを最適化する方法チュートリアルをご覧ください。