CircleCIを使用してDigitalOceanKubernetesへのデプロイを自動化する方法
序章
自動展開プロセスを持つことは、スケーラブルで復元力のあるアプリケーションの要件であり、 GitOpsまたはGitベースのDevOpsは、Gitを使用してCI/CDを整理する一般的な方法に急速になりました。 「信頼できる唯一の情報源」としてのリポジトリ。 CircleCI などのツールはGitHubリポジトリと統合されているため、リポジトリに変更を加えるたびにコードを自動的にテストしてデプロイできます。 この種のCI/CDをKubernetesインフラストラクチャの柔軟性と組み合わせると、需要の変化に合わせて簡単に拡張できるアプリケーションを構築できます。
この記事では、CircleCIを使用して、サンプルアプリケーションをDigitalOcean Kubernetes(DOKS)クラスターにデプロイします。 このチュートリアルを読むと、これらの同じ手法を適用して、Dockerイメージとしてビルド可能な他のCI/CDツールをデプロイできるようになります。
前提条件
このチュートリアルに従うには、次のものが必要です。
-
DigitalOceanアカウント。DigitalOceanアカウントのサインアップのドキュメントに従って設定できます。
-
ワークステーションにインストールされたDocker、およびDockerイメージの構築、削除、実行方法に関する知識。 Ubuntu 20.04にDockerをインストールして使用する方法のチュートリアルに従って、Ubuntu20.04にDockerをインストールできます。
-
Kubernetesがどのように機能し、その上にデプロイとサービスを作成する方法に関する知識。 Kubernetesの概要の記事を読むことを強くお勧めします。
-
クラスターを制御するコンピューターにインストールされているkubectlコマンドラインインターフェイスツール。
-
サンプルアプリケーションイメージの保存に使用されるDockerHubのアカウント。
-
GitHubアカウントとGitの基本に関する知識。 チュートリアルシリーズGitの概要:インストール、使用法、ブランチおよび GitHubでプルリクエストを作成する方法に従って、この知識を構築できます。
このチュートリアルでは、Kubernetesバージョンを使用します 1.22.7
と kubectl
バージョン 1.23.5
.
ステップ1—DigitalOceanKubernetesクラスターを作成する
注:すでにDigitalOcean Kubernetesクラスターを実行している場合は、このセクションをスキップできます。
この最初のステップでは、サンプルアプリケーションをデプロイするDigitalOcean Kubernetes(DOKS)クラスターを作成します。 The kubectl
ローカルマシンから実行されるコマンドは、Kubernetesクラスターから直接情報を変更または取得します。
DigitalOceanアカウントのKubernetesページに移動します。
Kubernetesクラスターの作成をクリックするか、ページの右上にある緑色の Create ボタンをクリックして、ドロップダウンメニューからKubernetesを選択します。
次のページでは、クラスターの詳細を指定します。 でKubernetesバージョンを選択バージョン1.22.7-do.0を選択します。 これが利用できない場合は、最新の推奨バージョンを選択してください。
データセンターリージョンの選択の場合、最も近いリージョンを選択します。 このチュートリアルでは、 SanFranciscoを使用します。
次に、ノードプールを構築するオプションがあります。 Kubernetesでは、ノードはワーカーマシンであり、ポッドの実行に必要なサービスが含まれています。 DigitalOceanでは、各ノードはドロップレットです。 ノードプールは、単一の基本ノードで構成されます。 1GB / 1vCPU 構成を選択し、ノード数を1ノードに変更します。
必要に応じてタグを追加できます。 これは、 DigitalOcean API を使用する場合、またはノードプールをより適切に整理する場合に役立ちます。
名前を選択で、このチュートリアルでは、 kubernetes-deployment-tutorial
. これにより、次のセクションを読みながら、全体を簡単に理解できるようになります。 最後に、緑色のクラスターの作成ボタンをクリックしてクラスターを作成します。 クラスタの作成が完了するまで待ちます。
クラスタの作成後、クラスタに接続するための手順が表示されます。 自動(推奨)タブの指示に従うか、手動タブでkubeconfigファイルをダウンロードします。 これは、認証に使用するファイルです。 kubectl
クラスタに対して実行するコマンド。 あなたにそれをダウンロードしてください kubectl
機械。
そのファイルを使用するデフォルトの方法は、常に --kubeconfig
で実行するすべてのコマンドのフラグとそのフラグへのパス kubectl
. たとえば、構成ファイルをにダウンロードした場合 Desktop
、あなたは実行します kubectl get pods
このようなコマンド:
- kubectl --kubeconfig ~/Desktop/kubernetes-deployment-tutorial-kubeconfig.yaml get pods
これにより、次の出力が生成されます。
OutputNo resources found.
これは、クラスターにアクセスしたことを意味します。 The No resources found.
クラスタにポッドがないため、メッセージは正しいです。
他のKubernetesクラスタを維持していない場合は、kubeconfigファイルをホームディレクトリの次のフォルダにコピーできます。 .kube
. 存在しない場合に備えて、そのディレクトリを作成します。
- mkdir -p ~/.kube
次に、設定ファイルを新しく作成したファイルにコピーします .kube
ディレクトリと名前を変更します config
:
- cp current_kubernetes-deployment-tutorial-kubeconfig.yaml_file_path ~/.kube/config
これで、構成ファイルにパスが含まれるはずです。 ~/.kube/config
. これは kubectl
コマンドを実行するとデフォルトで読み取るため、渡す必要はありません --kubeconfig
もう。 次を実行します。
- kubectl get pods
次の出力が表示されます。
OutputNo resources found in default namespace.
次に、次のコマンドでクラスターにアクセスします。
- kubectl get nodes
クラスタ上のノードのリストを受け取ります。 出力は次のようになります。
OutputNAME STATUS ROLES AGE VERSION
pool-upkissrv3-uzm8z Ready <none> 12m v1.22.7
このチュートリアルでは、 default
すべての名前空間 kubectl
コマンドとマニフェストファイルは、Kubernetesでの作業のワークロードと操作パラメーターを定義するファイルです。 名前空間は、単一の物理クラスター内の仮想クラスターのようなものです。 他の任意の名前空間に変更できます。 常にそれを使用して渡すようにしてください --namespace
フラグを立てる kubectl
、および/またはKubernetesマニフェストメタデータフィールドで指定します。 これらは、チームとその実行環境の展開を整理するための優れた方法です。 それらの詳細については、Namespacesに関するKubernetesの公式概要をご覧ください。
このステップを完了すると、実行できるようになります kubectl
クラスタに対して。 次のステップでは、サンプルアプリケーションを格納するために使用するローカルGitリポジトリを作成します。
ステップ2—ローカルGitリポジトリを作成する
次に、ローカルGitリポジトリでサンプルデプロイメントを構造化します。 また、クラスターで実行するすべてのデプロイに対してグローバルになるいくつかのKubernetesマニフェストを作成します。
注:このチュートリアルはUbuntu 20.04でテストされており、個々のコマンドはこのOSに一致するようにスタイル設定されています。 ただし、ここでのコマンドのほとんどは、変更をほとんどまたはまったく必要とせずに、他のLinuxディストリビューションに適用できます。 kubectl
プラットフォームに依存しません。
まず、後でGitHubにプッシュする新しいGitリポジトリをローカルに作成します。 と呼ばれる空のフォルダを作成します do-sample-app
ホームディレクトリと cd
それに:
- mkdir ~/do-sample-app
- cd ~/do-sample-app
次に、次のコマンドを使用して、このフォルダーに新しいGitリポジトリを作成します。
- git init .
このリポジトリ内に、という名前の空のフォルダを作成します kube
:
- mkdir ~/do-sample-app/kube/
これは、クラスタにデプロイするサンプルアプリケーションに関連するKubernetesリソースマニフェストを保存する場所になります。
次に、という別のフォルダを作成します kube-general
、ただし今回は作成したGitリポジトリの外です。 ホームディレクトリ内に作成します。
- mkdir ~/kube-general/
このフォルダーは、クラスター上の単一のデプロイメントに固有ではなく、複数のデプロイメントに共通のマニフェストを格納するために使用されるため、Gitリポジトリーの外部にあります。 これにより、これらの一般的なマニフェストをさまざまな展開で再利用できるようになります。
フォルダーを作成し、サンプルアプリケーションのGitリポジトリーを配置したら、DOKSクラスターの認証と承認を調整します。
ステップ3—サービスアカウントを作成する
通常、デフォルトの admin ユーザーを使用して、他のServicesからKubernetesクラスターへの認証を行うことはお勧めしません。 外部プロバイダーのキーが危険にさらされると、クラスター全体が危険にさらされます。
代わりに、RBACKubernetes認証モデルの一部である特定のロールを持つ単一のサービスアカウントを使用します。
この承認モデルは、ロールおよびリソースに基づいています。 基本的にクラスター上のユーザーであるサービスアカウントを作成することから始め、次に、クラスター上でアクセスできるリソースを指定するロールを作成します。 最後に、 Role Binding を作成します。これは、ロールと以前に作成したサービスアカウント間の接続を確立するために使用され、ロールがアクセスできるすべてのリソースへのアクセスをサービスアカウントに付与します。
作成する最初のKubernetesリソースは、CI/CDユーザーのサービスアカウントです。このチュートリアルではこの名前を付けます。 cicd
.
ファイルを作成する cicd-service-account.yml
中 ~/kube-general
フォルダを開き、お気に入りのテキストエディタで開きます。
- nano ~/kube-general/cicd-service-account.yml
その上に次の内容を書いてください。
apiVersion: v1
kind: ServiceAccount
metadata:
name: cicd
namespace: default
これはYAMLファイルです。 すべてのKubernetesリソースは1つを使用して表されます。 この場合、このリソースはKubernetesAPIバージョンからのものであると言っています v1
(初めの kubectl
Kubernetes HTTP APIを呼び出してリソースを作成します)、これは ServiceAccount
.
The metadata
フィールドは、このリソースに関する詳細情報を追加するために使用されます。 この場合、あなたはこれを与えています ServiceAccount
名前 cicd
、およびでそれを作成します default
名前空間。
これで、を実行してクラスター上にこのサービスアカウントを作成できます。 kubectl apply
、次のように:
- kubectl apply -f ~/kube-general/
次のような出力が表示されます。
Outputserviceaccount/cicd created
サービスアカウントが機能していることを確認するには、それを使用してクラスターにログインしてみてください。 これを行うには、最初にそれぞれのアクセストークンを取得し、それを環境変数に格納する必要があります。 すべてのサービスアカウントには、KubernetesがSecretとして保存するアクセストークンがあります。
次のコマンドを使用して、このシークレットを取得できます。
- TOKEN=$(kubectl get secret $(kubectl get secret | grep cicd-token | awk '{print $1}') -o jsonpath='{.data.token}' | base64 --decode)
このコマンドが何をしているのかについての説明:
$(kubectl get secret | grep cicd-token | awk '{print $1}')
これは、私たちに関連する秘密の名前を取得するために使用されます cicd
サービスアカウント。 kubectl get secret
デフォルトの名前空間のシークレットのリストを返す場合は、 grep
あなたに関連する行を検索するには cicd
サービスアカウント。 次に、名前を返します。これは、から返される1行の最初のものだからです。 grep
.
kubectl get secret preceding-command -o jsonpath='{.data.token}' | base64 --decode
これにより、サービスアカウントトークンのシークレットのみが取得されます。 次に、を使用してトークンフィールドにアクセスします jsonpath
、結果をに渡します base64 --decode
. トークンはBase64文字列として保存されるため、これが必要です。 トークン自体はJSONWebトークンです。
これで、ポッドを取得してみることができます。 cicd
サービスアカウント。 次のコマンドを実行して、置き換えます server-from-kubeconfig-file
後に見つけることができるサーバーのURLで server:
の ~/.kube/config
(クラスター用にダウンロードした構成ファイル)。 このコマンドは、このチュートリアルの後半で学習する特定のエラーを表示します。
- kubectl --insecure-skip-tls-verify --kubeconfig="/dev/null" --server=server-from-kubeconfig-file --token=$TOKEN get pods
--insecure-skip-tls-verify
テストしているだけで、これを検証する必要がないため、サーバーの証明書を検証する手順をスキップします。 --kubeconfig="/dev/null"
確認することです kubectl
構成ファイルと資格情報を読み取るのではなく、提供されたトークンを使用します。
出力は次のようになります。
OutputError from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:cicd" cannot list resource "pods" in API group "" in the namespace "default"
これはエラーですが、トークンが機能したことを示しています。 受け取ったエラーは、サービスアカウントにリソースを一覧表示するために必要な認証がないことに関するものです secrets
、しかし、サーバー自体にアクセスすることができました。 トークンが機能しなかった場合、エラーは次のようになります。
Outputerror: You must be logged in to the server (Unauthorized)
認証が成功したので、次のステップはサービスアカウントの認証エラーを修正することです。 これを行うには、必要な権限を持つロールを作成し、それをサービスアカウントにバインドします。
ステップ4—ロールとロールバインディングの作成
Kubernetesには、ロールを定義する2つの方法があります。 Role
または ClusterRole
資源。 前者と後者の違いは、最初の名前空間は単一の名前空間に適用され、もう1つはクラスター全体に有効であるということです。
このチュートリアルでは単一の名前空間を使用しているため、 Role
.
ファイルを作成する ~/kube-general/cicd-role.yml
お気に入りのテキストエディタで開きます。
- nano ~/kube-general/cicd-role.yml
基本的な考え方は、Kubernetesのほとんどのリソースに関連するすべてのことを実行するためのアクセスを許可することです。 default
名前空間。 君の Role
このようになります:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: cicd
namespace: default
rules:
- apiGroups: ["", "apps", "batch", "extensions"]
resources: ["deployments", "services", "replicasets", "pods", "jobs", "cronjobs"]
verbs: ["*"]
このYAMLは、以前に作成したものといくつかの類似点がありますが、ここでは、このリソースは Role
、KubernetesAPIからのものです rbac.authorization.k8s.io/v1
. あなたは自分の役割に名前を付けています cicd
、作成したのと同じ名前空間に作成します ServiceAccount
、 default
1。
次に、 rules
フィールド。このロールがアクセスできるリソースのリストです。 Kubernetesでは、リソースは、それらが属するAPIグループ、リソースの種類自体、および動詞で表されるそのときに実行できるアクションに基づいて定義されます。 これらの動詞はHTTPの動詞に似ています。
この場合、あなたはあなたの Role
すべてを行うことが許可されています、 *
、次のリソースについて: deployments
, services
, replicasets
, pods
, jobs
、 と cronjobs
. これは、次のAPIグループに属するリソースにも当てはまります。 ""
(空の文字列)、 apps
, batch
、 と extensions
. 空の文字列は、ルートAPIグループを意味します。 使用する場合 apiVersion: v1
リソースを作成するときは、このリソースがこのAPIグループの一部であることを意味します。
A Role
それ自体は何もしません。 また、RoleBindingを作成する必要があります。 Role
何かに、この場合、 ServiceAccount
.
ファイルを作成する ~/kube-general/cicd-role-binding.yml
そしてそれを開きます:
- nano ~/kube-general/cicd-role-binding.yml
次の行をファイルに追加します。
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: cicd
namespace: default
subjects:
- kind: ServiceAccount
name: cicd
namespace: default
roleRef:
kind: Role
name: cicd
apiGroup: rbac.authorization.k8s.io
君の RoleBinding
このチュートリアルではまだカバーされていない特定のフィールドがいくつかあります。 roleRef
それは Role
何かにバインドしたい。 この場合、それは cicd
以前に作成した役割。 subjects
自分の役割をバインドしているリソースのリストです。 この場合、それは単一です ServiceAccount
と呼ばれる cicd
.
注:を使用した場合 ClusterRole
、作成する必要があります ClusterRoleBinding
の代わりに RoleBinding
. ファイルはほとんど同じです。 唯一の違いは、 namespace
内部のフィールド metadata
.
これらのファイルを作成すると、次のように使用できるようになります。 kubectl apply
また。 次のコマンドを実行して、Kubernetesクラスターにこれらの新しいリソースを作成します。
- kubectl apply -f ~/kube-general/
次のような出力が表示されます。
Outputrolebinding.rbac.authorization.k8s.io/cicd created
role.rbac.authorization.k8s.io/cicd created
serviceaccount/cicd unchanged
ここで、前に実行したコマンドを試してください。
- kubectl --insecure-skip-tls-verify --kubeconfig="/dev/null" --server=server-from-kubeconfig-file --token=$TOKEN get pods
ポッドがないため、次の出力が生成されます。
OutputNo resources found in default namespace.
このステップでは、CircleCIで使用するサービスアカウントに、リソースの一覧表示、作成、更新など、クラスターで意味のあるアクションを実行するために必要な承認を与えました。 次に、サンプルアプリケーションを作成します。
ステップ5—サンプルアプリケーションの作成
注:これ以降に作成されるすべてのコマンドとファイルは、フォルダーから開始されます ~/do-sample-app
以前に作成しました。 これは、クラスターにデプロイするサンプルアプリケーションに固有のファイルを作成しているためです。
Kubernetes Deployment
作成するのはNginxイメージをベースとして使用し、アプリケーションは単純な静的HTMLページになります。 Nginxから直接HTMLを提供することでデプロイメントが機能するかどうかをテストできるため、これは素晴らしいスタートです。 後で見るように、ローカルに来るすべてのトラフィックをリダイレクトすることができます address:port
クラスター上のデプロイメントに接続して、クラスターが機能しているかどうかをテストします。
以前に設定したリポジトリ内に、新しいリポジトリを作成します Dockerfile
ファイルを作成し、選択したテキストエディタで開きます。
- nano ~/do-sample-app/Dockerfile
その上に次のように書いてください。
FROM nginx:1.21
COPY index.html /usr/share/nginx/html/index.html
これにより、Dockerにアプリケーションコンテナをビルドするように指示します。 nginx
画像。
今すぐ新しいを作成します index.html
ファイルを開いて開きます。
- nano ~/do-sample-app/index.html
次のHTMLコンテンツを記述します。
<!DOCTYPE html>
<title>DigitalOcean</title>
<body>
Kubernetes Sample Application
</body>
このHTMLは、アプリケーションが機能しているかどうかを知らせる簡単なメッセージを表示します。
イメージをビルドして実行することで、イメージが正しいかどうかをテストできます。
まず、次のコマンドでイメージをビルドします。 dockerhub-username
独自のDockerHubユーザー名を使用します。 ここでユーザー名を指定する必要があります。これにより、後でDockerHubにプッシュしたときに機能します。
- docker build ~/do-sample-app/ -t dockerhub-username/do-kubernetes-sample-app
次に、イメージを実行します。 次のコマンドを使用して、イメージを開始し、ポート上のローカルトラフィックを転送します 8080
港へ 80
画像内では、Nginxがデフォルトでリッスンするポートは次のとおりです。
- docker run --rm -it -p 8080:80 dockerhub-username/do-kubernetes-sample-app
コマンドの実行中は、コマンドプロンプトのインタラクティブ機能が停止します。 代わりに、Nginxアクセスログが表示されます。 開いたら localhost:8080
どのブラウザでも、次のコンテンツを含むHTMLページが表示されます。 ~/do-sample-app/index.html
. 利用可能なブラウザがない場合は、新しいターミナルウィンドウを開いて、次を使用できます。 curl
WebページからHTMLをフェッチするコマンド:
- curl localhost:8080
次の出力が表示されます。
Output<!DOCTYPE html>
<title>DigitalOcean</title>
<body>
Kubernetes Sample Application
</body>
コンテナを停止します(CTRL
+ C
実行中のターミナルで)、このイメージをDockerHubアカウントに送信します。 これを行うには、最初にDockerHubにログインします。
- docker login
Docker Hubアカウントに関する必要な情報を入力してから、次のコマンドでイメージをプッシュします(忘れずに dockerhub-username
あなた自身で):
- docker push dockerhub-username/do-kubernetes-sample-app
これで、サンプルアプリケーションイメージがDockerHubアカウントにプッシュされました。 次のステップでは、このイメージからDOKSクラスターにデプロイメントを作成します。
ステップ6—Kubernetesのデプロイとサービスを作成する
Dockerイメージを作成して機能させたら、クラスター上でDockerイメージからDeploymentを作成する方法をKubernetesに指示するマニフェストを作成します。
YAMLデプロイメントファイルを作成します ~/do-sample-app/kube/do-sample-deployment.yml
テキストエディタで開きます。
- nano ~/do-sample-app/kube/do-sample-deployment.yml
ファイルに次の内容を書き込み、必ず置き換えてください dockerhub-username
Docker Hubユーザー名を使用:
apiVersion: apps/v1
kind: Deployment
metadata:
name: do-kubernetes-sample-app
namespace: default
labels:
app: do-kubernetes-sample-app
spec:
replicas: 1
selector:
matchLabels:
app: do-kubernetes-sample-app
template:
metadata:
labels:
app: do-kubernetes-sample-app
spec:
containers:
- name: do-kubernetes-sample-app
image: dockerhub-username/do-kubernetes-sample-app:latest
ports:
- containerPort: 80
name: http
KubernetesのデプロイはAPIグループからのものです apps
、だから apiVersion
マニフェストの apps/v1
. の上 metadata
以前に使用したことのない新しいフィールドを追加しました。 metadata.labels
. これは、展開を整理するのに役立ちます。 フィールド spec
デプロイメントの動作仕様を表します。 デプロイメントは、1つ以上のポッドを管理する責任があります。 この場合、それは単一のレプリカを持つことになります spec.replicas
分野。 つまり、単一のポッドを作成して管理します。
ポッドを管理するには、デプロイメントが担当するポッドを認識している必要があります。 The spec.selector
フィールドは、その情報を提供するフィールドです。 この場合、展開はタグ付きのすべてのポッドを担当します app=do-kubernetes-sample-app
. The spec.template
フィールドには、の詳細が含まれます Pod
この展開により作成されます。 テンプレート内には、 spec.template.metadata
分野。 The labels
このフィールド内は、で使用されているものと一致する必要があります spec.selector
. spec.template.spec
ポッド自体の仕様です。 この場合、それはと呼ばれる単一のコンテナを含みます do-kubernetes-sample-app
. そのコンテナのイメージは、以前にビルドしてDockerHubにプッシュしたイメージです。
このYAMLファイルは、このコンテナがポートを公開していることもKubernetesに通知します 80
、このポートに名前を付けます http
.
によって公開されたポートにアクセスするには Deployment
、サービスを作成します。 名前の付いたファイルを作成します ~/do-sample-app/kube/do-sample-service.yml
お気に入りのエディターで開きます。
- nano ~/do-sample-app/kube/do-sample-service.yml
次に、ファイルに次の行を追加します。
apiVersion: v1
kind: Service
metadata:
name: do-kubernetes-sample-app
namespace: default
labels:
app: do-kubernetes-sample-app
spec:
type: ClusterIP
ports:
- port: 80
targetPort: http
name: http
selector:
app: do-kubernetes-sample-app
このファイルはあなたに Service
デプロイメントで使用されるのと同じラベル。 これは必須ではありませんが、Kubernetesでアプリケーションを整理するのに役立ちます。
サービスリソースには、 spec
分野。 The spec.type
フィールドはサービスの動作に責任があります。 この場合、それは ClusterIP
、これは、サービスがクラスター内部IPで公開され、クラスター内からのみ到達可能であることを意味します。 これがデフォルトです spec.type
サービスのため。 spec.selector
このサービスで公開するポッドを選択するときに使用するラベルセレクターの基準です。 ポッドにタグがあるので app: do-kubernetes-sample-app
、ここで使用しました。 spec.ports
このサービスから公開するポッドのコンテナによって公開されるポートです。 ポッドには、ポートを公開する単一のコンテナがあります 80
、名前付き http
、ここでは次のように使用しています targetPort
. サービスはそのポートをポートに公開します 80
同じ名前でも、コンテナのものとは異なるポート/名前の組み合わせを使用できた可能性があります。
あなたと Service
と Deployment
マニフェストファイルが作成されました。これで、Kubernetesクラスターでこれらのリソースを作成できます。 kubectl
:
- kubectl apply -f ~/do-sample-app/kube/
次の出力が表示されます。
Outputdeployment.apps/do-kubernetes-sample-app created
service/do-kubernetes-sample-app created
マシンの1つのポートを、サービスがKubernetesクラスター内で公開しているポートに転送して、これが機能しているかどうかをテストします。 あなたはそれを使ってそれをすることができます kubectl port-forward
:
- kubectl port-forward $(kubectl get pod --selector="app=do-kubernetes-sample-app" --output jsonpath='{.items[0].metadata.name}') 8080:80
サブシェルコマンド $(kubectl get pod --selector="app=do-kubernetes-sample-app" --output jsonpath='{.items[0].metadata.name}')
に一致するポッドの名前を取得します app
使用したタグ。 それ以外の場合は、を使用してポッドのリストから取得できます。 kubectl get pods
.
実行した後 port-forward
、シェルはインタラクティブでなくなり、代わりにクラスターにリダイレクトされたリクエストを出力します。
OutputForwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
オープニング localhost:8080
どのブラウザでも、コンテナをローカルで実行したときに表示されたのと同じページがレンダリングされますが、現在はKubernetesクラスタから取得されています。 以前と同様に、 curl
新しいターミナルウィンドウで、機能しているかどうかを確認します。
- curl localhost:8080
次の出力が表示されます。
Output<!DOCTYPE html>
<title>DigitalOcean</title>
<body>
Kubernetes Sample Application
</body>
次に、作成したすべてのファイルをGitHubリポジトリにプッシュします。 これを行うには、最初にGitHubにリポジトリを作成する必要があります digital-ocean-kubernetes-deploy
.
デモンストレーションの目的でこのリポジトリを単純に保つために、新しいリポジトリを次のように初期化しないでください。 README
, license
、 また .gitignore
GitHubUIで尋ねられたときにファイル。 これらのファイルは後で追加できます。
リポジトリを作成したら、ローカルリポジトリをGitHub上のリポジトリにポイントします。 これを行うには、を押します CTRL
+ C
止まる kubectl port-forward
コマンドラインを元に戻し、次のコマンドを実行して、という新しいリモコンを追加します。 origin
:
- cd ~/do-sample-app/
- git remote add origin https://github.com/your-github-account-username/digital-ocean-kubernetes-deploy.git
前のコマンドからの出力はありません。
次に、これまでに作成したすべてのファイルをGitHubリポジトリにコミットします。 まず、ファイルを追加します。
- git add --all
次に、ファイルをリポジトリにコミットします。コミットメッセージは引用符で囲みます。
- git commit -m "initial commit"
これにより、次のような出力が得られます。
Output[master (root-commit) db321ad] initial commit
4 files changed, 47 insertions(+)
create mode 100644 Dockerfile
create mode 100644 index.html
create mode 100644 kube/do-sample-deployment.yml
create mode 100644 kube/do-sample-service.yml
最後に、ファイルをGitHubにプッシュします。
- git push -u origin master
ユーザー名とパスワードの入力を求められます。 これを入力すると、次のような出力が表示されます。
OutputCounting objects: 7, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (7/7), done.
Writing objects: 100% (7/7), 907 bytes | 0 bytes/s, done.
Total 7 (delta 0), reused 0 (delta 0)
To github.com:your-github-account-username/digital-ocean-kubernetes-deploy.git
* [new branch] master -> master
Branch master set up to track remote branch master from origin.
GitHubリポジトリページに移動すると、そこにあるすべてのファイルが表示されます。 プロジェクトをGitHubに設定すると、CircleCIをCI/CDツールとして設定できるようになります。
ステップ7—CircleCIの構成
このチュートリアルでは、CircleCIを使用して、コードが更新されるたびにアプリケーションのデプロイを自動化するため、GitHubアカウントを使用してCircleCIにログインし、リポジトリを設定する必要があります。
まず、彼らのホームページ https://circleci.com にアクセスし、サインアップを押します。
GitHubを使用しているので、緑色のGitHubでサインアップボタンをクリックします。
CircleCIはGitHubの認証ページにリダイレクトします。 CircleCIは、プロジェクトの構築を開始できるようにするために、アカウントにいくつかの権限が必要です。 これにより、CircleCIは電子メールを取得し、キーとアクセス許可をデプロイしてリポジトリにフックを作成し、SSHキーをアカウントに追加できます。 CircleCIがデータをどのように処理するかについての詳細が必要な場合は、GitHub統合に関するドキュメントを確認してください。
CircleCIを承認すると、プロジェクトページにリダイレクトされます。 ここで、CircleCIでGitHubリポジトリを設定できます。 のエントリでプロジェクトのセットアップを選択します digital-ocean-kubernetes-deploy
レポ。 次に、 Faster:スターターCIパイプラインを新しいブランチオプションにコミットするを選択します。 これにより、プロジェクトの新しいcircleci-project-setupブランチが作成されます。
次に、CircleCI設定でいくつかの環境変数を指定します。 プロジェクトの設定を確認するには、ページの右上にあるプロジェクト設定ボタンを選択し、環境変数を選択します。 環境変数の追加を押して、新しい環境変数を作成します。
まず、という2つの環境変数を追加します DOCKERHUB_USERNAME
と DOCKERHUB_PASS
、後でイメージをDockerHubにプッシュするために必要になります。 値をそれぞれDockerHubのユーザー名とパスワードに設定します。
次に、さらに3つ追加します。 KUBERNETES_TOKEN
, KUBERNETES_SERVER
、 と KUBERNETES_CLUSTER_CERTIFICATE
.
の値 KUBERNETES_TOKEN
は、サービスアカウントユーザーを使用してKubernetesクラスターで認証するために以前に使用したローカル環境変数の値になります。 ターミナルを閉じた場合は、いつでも次のコマンドを実行してターミナルを再度取得できます。
- kubectl get secret $(kubectl get secret | grep cicd-token | awk '{print $1}') -o jsonpath='{.data.token}' | base64 --decode
KUBERNETES_SERVER
として渡した文字列になります --server
フラグを立てる kubectl
でログインしたとき cicd
サービスアカウント。 あなたは後にこれを見つけることができます server:
の中に ~/.kube/config
ファイル、またはファイル内 kubernetes-deployment-tutorial-kubeconfig.yaml
Kubernetesクラスターの初期設定時にDigitalOceanダッシュボードからダウンロードされます。
KUBERNETES_CLUSTER_CERTIFICATE
あなたの ~/.kube/config
ファイル。 それは certificate-authority-data
上のフィールド clusters
クラスタに関連するアイテム。 長い文字列である必要があります。 必ずすべてコピーしてください。
これらの環境変数のほとんどには機密情報が含まれており、CircleCI YAML構成ファイルに直接配置するのは安全ではないため、これらの環境変数をここで定義する必要があります。
CircleCIがリポジトリの変更をリッスンし、環境変数が構成されたら、構成ファイルを作成します。
と呼ばれるディレクトリを作成します .circleci
サンプルアプリケーションリポジトリ内:
- mkdir ~/do-sample-app/.circleci/
このディレクトリ内に、という名前のファイルを作成します config.yml
お気に入りのエディターで開きます。
- nano ~/do-sample-app/.circleci/config.yml
次のコンテンツをファイルに追加し、必ず置き換えてください dockerhub-username
Docker Hubユーザー名を使用:
version: 2.1
jobs:
build:
docker:
- image: circleci/buildpack-deps:bullseye
environment:
IMAGE_NAME: dockerhub-username/do-kubernetes-sample-app
working_directory: ~/app
steps:
- checkout
- setup_remote_docker
- run:
name: Build Docker image
command: |
docker build -t $IMAGE_NAME:latest .
- run:
name: Push Docker Image
command: |
echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin
docker push $IMAGE_NAME:latest
workflows:
version: 2
build-deploy-master:
jobs:
- build:
filters:
branches:
only: master
これでワークフローが設定されます build-deploy-master
、現在、という単一の仕事があります build
. このジョブは、 master
ブランチ。
The build
仕事は画像を使用しています circleci/buildpack-deps:bullseye
公式に基づいたCircleCIからの画像であるそのステップを実行する buildpack-deps
Dockerイメージですが、Dockerバイナリ自体など、いくつかの追加ツールがインストールされています。
ワークフローには4つのステップがあります。
checkout
GitHubからコードを取得します。setup_remote_docker
ビルドごとにリモートの分離された環境をセットアップします。 これは、使用する前に必要ですdocker
ジョブステップ内のコマンド。 これが必要なのは、ステップがDockerイメージ内で実行されているためです。setup_remote_docker
そこでコマンドを実行するために別のマシンを割り当てます。- 最初
run
stepは、ローカル環境で以前に行ったように、イメージをビルドします。 そのためには、で宣言した環境変数を使用していますenvironment:
,IMAGE_NAME
. - 最後
run
step pushes the image to Docker Hub, using the environment variables you configured on the project settings to authenticate.
There are other registries besides Docker Hub that you can use to store container images and collaborate on them with others. For instance, DigitalOcean has its own container registry to which you can push container images.
To push an image to the DigitalOcean Container Registry, you could replace the second run
step with one like the following:
. . .
- run: |
docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD registry.digitalocean.com/your_registry
docker push registry.digitalocean.com/your_registry/do-kubernetes-sample-app
. . .
This assumes you’ve securely set $DOCKER_USERNAME
と $DOCKER_PASSWORD
as environment variables previously in the file, as this will avoid exposing them in the CircleCI job output. Also, note that both of these values should be set to the same DigitalOcean API token.
To learn more about the DigitalOcean container registry, check out our product documentation.
新しいファイルをリポジトリにコミットし、変更をアップストリームにプッシュします。
- cd ~/do-sample-app/
- git add .circleci/
- git commit -m "add CircleCI config"
- git push
これにより、CircleCIで新しいビルドがトリガーされます。 CircleCIワークフローは、イメージを正しくビルドしてDockerHubにプッシュします。
CircleCIワークフローを作成してテストしたので、Docker Hubから最新のイメージを取得し、変更が加えられたときに自動的にデプロイするようにDOKSクラスターを設定できます。
ステップ8—Kubernetesクラスターでのデプロイの更新
これで、アプリケーションイメージがビルドされ、変更をプッシュするたびにDockerHubに送信されます。 master
GitHubのブランチでは、Kubernetesクラスターのデプロイを更新して、新しいイメージを取得し、デプロイのベースとして使用できるようにします。
これを行うには、最初にデプロイに関する1つの問題を修正します。現在、イメージに依存しています。 latest
鬼ごっこ。 このタグは、使用している画像のバージョンを示していません。 新しいイメージをDockerHubにプッシュするたびに上書きされるため、デプロイをそのタグに簡単にロックすることはできません。そのように使用すると、コンテナー化されたアプリケーションの再現性が失われます。
これについて詳しくは、 Vladislav Supalovの記事で、最新のタグに依存することがアンチパターンである理由について読むことができます。
これを修正するには、最初にいくつかの変更を加える必要があります Push Docker Image
のビルドステップ ~/do-sample-app/.circleci/config.yml
ファイル。 ファイルを開きます。
- nano ~/do-sample-app/.circleci/config.yml
次に、強調表示された行を Push Docker Image
ステップ:
...
- run:
name: Push Docker Image
command: |
echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin
docker tag $IMAGE_NAME:latest $IMAGE_NAME:$CIRCLE_SHA1
docker push $IMAGE_NAME:latest
docker push $IMAGE_NAME:$CIRCLE_SHA1
...
CircleCIには、デフォルトでいくつかの特別な環境変数が設定されています。 それらの1つは CIRCLE_SHA1
、構築しているコミットのハッシュが含まれています。 行った変更 ~/do-sample-app/.circleci/config.yml
この環境変数を使用して、ビルド元のコミットでイメージにタグを付け、常に最新のビルドに最新のタグをタグ付けします。 そうすれば、リポジトリに新しいものをプッシュするときにそれらを上書きすることなく、常に特定のイメージを利用できます。
ファイルを保存して終了します。
次に、デプロイメントマニフェストファイルをそのファイルを指すように変更します。 内部の場合、これは小さな変更になります ~/do-sample-app/kube/do-sample-deployment.yml
画像を次のように設定できます dockerhub-username/do-kubernetes-sample-app:$COMMIT_SHA1
、 しかし kubectl
使用するときにマニフェスト内で変数置換を行いません kubectl apply
. これを説明するために、envsubstを使用できます。 envsubst
GNU gettextプロジェクトの一部であるCLIツールです。 テキストを渡すことができ、テキスト内で一致する環境変数を持つ変数が見つかった場合は、その変数をそれぞれの値に置き換えます。 結果のテキストは、出力として返されます。
これを使用するには、デプロイメントを担当するbashスクリプトを作成します。 と呼ばれる新しいフォルダを作成します scripts
中身 ~/do-sample-app/
:
- mkdir ~/do-sample-app/scripts/
そのフォルダ内に、という新しいbashスクリプトを作成します ci-deploy.sh
お気に入りのテキストエディタで開きます。
- nano ~/do-sample-app/scripts/ci-deploy.sh
その中に次のbashスクリプトを記述します。
#! /bin/bash
# exit script when any command ran here returns with non-zero exit code
set -e
COMMIT_SHA1=$CIRCLE_SHA1
# Export it so it's available for envsubst
export COMMIT_SHA1=$COMMIT_SHA1
# Since the only way for envsubst to work on files is using input/output redirection,
# it's not possible to do in-place substitution, so you will save the output to another file
# and overwrite the original with that one.
envsubst <./kube/do-sample-deployment.yml >./kube/do-sample-deployment.yml.out
mv ./kube/do-sample-deployment.yml.out ./kube/do-sample-deployment.yml
echo "$KUBERNETES_CLUSTER_CERTIFICATE" | base64 --decode > cert.crt
./kubectl \
--kubeconfig=/dev/null \
--server=$KUBERNETES_SERVER \
--certificate-authority=cert.crt \
--token=$KUBERNETES_TOKEN \
apply -f ./kube/
ファイル内のコメントを使用して、このスクリプトを実行してみましょう。 まず、次のとおりです。
set -e
この行は、失敗したコマンドがbashスクリプトの実行を停止することを確認します。 そうすれば、1つのコマンドが失敗しても、次のコマンドは実行されません。
COMMIT_SHA1=$CIRCLE_SHA1
export COMMIT_SHA1=$COMMIT_SHA1
これらの行はCircleCIをエクスポートします $CIRCLE_SHA1
新しい名前の環境変数。 を使用してエクスポートせずに変数を宣言したばかりの場合 export
、それは表示されません envsubst
指図。
envsubst <./kube/do-sample-deployment.yml >./kube/do-sample-deployment.yml.out
mv ./kube/do-sample-deployment.yml.out ./kube/do-sample-deployment.yml
envsubst
インプレース置換はできません。 つまり、ファイルの内容を読み取ったり、変数をそれぞれの値に置き換えたり、出力を同じファイルに書き戻したりすることはできません。 したがって、出力を別のファイルにリダイレクトしてから、元のファイルを新しいファイルで上書きします。
echo "$KUBERNETES_CLUSTER_CERTIFICATE" | base64 --decode > cert.crt
環境変数 $KUBERNETES_CLUSTER_CERTIFICATE
CircleCIのプロジェクト設定で以前に作成したのは、実際にはBase64でエンコードされた文字列です。 で使用するには kubectl
その内容をデコードしてファイルに保存する必要があります。 この場合、あなたはそれをという名前のファイルに保存しています cert.crt
現在の作業ディレクトリ内。
./kubectl \
--kubeconfig=/dev/null \
--server=$KUBERNETES_SERVER \
--certificate-authority=cert.crt \
--token=$KUBERNETES_TOKEN \
apply -f ./kube/
最後に、あなたは走っています kubectl
. このコマンドには、サービスアカウントをテストしたときに実行したものと同様の引数があります。 あなたが呼んでいる apply -f ./kube/
、CircleCIでは、現在の作業ディレクトリがプロジェクトのルートフォルダであるため。 ./kube/
ここにあなたがいます ~/do-sample-app/kube
フォルダ。
ファイルを保存し、実行可能であることを確認します。
- chmod +x ~/do-sample-app/scripts/ci-deploy.sh
今、編集 ~/do-sample-app/kube/do-sample-deployment.yml
:
- nano ~/do-sample-app/kube/do-sample-deployment.yml
コンテナイメージ値のタグを次のように変更します。
...
containers:
- name: do-kubernetes-sample-app
image: dockerhub-username/do-kubernetes-sample-app:$COMMIT_SHA1
ports:
- containerPort: 80
name: http
ファイルを保存して閉じます。 ここで、CI構成ファイルにいくつかの新しいステップを追加して、Kubernetesでのデプロイを更新する必要があります。
開ける ~/do-sample-app/.circleci/config.yml
お気に入りのテキストエディタで:
- nano ~/do-sample-app/.circleci/config.yml
次の新しい仕事を、すぐ下に書いてください build
以前に作成したジョブ:
...
command: |
echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin
docker tag $IMAGE_NAME:latest $IMAGE_NAME:$CIRCLE_SHA1
docker push $IMAGE_NAME:latest
docker push $IMAGE_NAME:$CIRCLE_SHA1
deploy:
docker:
- image: circleci/buildpack-deps:bullseye
working_directory: ~/app
steps:
- checkout
- run:
name: Install envsubst
command: |
sudo apt-get update && sudo apt-get -y install gettext-base
- run:
name: Install kubectl
command: |
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
chmod u+x ./kubectl
- run:
name: Deploy Code
command: ./scripts/ci-deploy.sh
...
新しいの最初の2つのステップ deploy
ジョブは最初にいくつかの依存関係をインストールしています envsubst
その後 kubectl
. The Deploy Code
ステップは、デプロイスクリプトを実行する責任があります。
次に、このジョブをに追加します build-deploy-master
以前に作成したワークフロー。 内部 build-deploy-master
ワークフロー構成では、の既存のエントリの直後に次の新しいエントリを書き込みます build
仕事:
...
workflows:
version: 2
build-deploy-master:
jobs:
- build:
filters:
branches:
only: master
- deploy:
requires:
- build
filters:
branches:
only: master
これにより、 deploy
に仕事 build-deploy-master
ワークフロー。 The deploy
ジョブは、へのコミットに対してのみ実行されます master
、および build
ジョブが完了しました。
の内容 ~/do-sample-app/.circleci/config.yml
これで次のようになります。
version: 2.1
jobs:
build:
docker:
- image: circleci/buildpack-deps:bullseye
environment:
IMAGE_NAME: dockerhub-username/do-kubernetes-sample-app
working_directory: ~/app
steps:
- checkout
- setup_remote_docker
- run:
name: Build Docker image
command: |
docker build -t $IMAGE_NAME:latest .
- run:
name: Push Docker Image
command: |
echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin
docker tag $IMAGE_NAME:latest $IMAGE_NAME:$CIRCLE_SHA1
docker push $IMAGE_NAME:latest
docker push $IMAGE_NAME:$CIRCLE_SHA1
deploy:
docker:
- image: circleci/buildpack-deps:bullseye
working_directory: ~/app
steps:
- checkout
- run:
name: Install envsubst
command: |
sudo apt-get update && sudo apt-get -y install gettext-base
- run:
name: Install kubectl
command: |
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
chmod u+x ./kubectl
- run:
name: Deploy Code
command: ./scripts/ci-deploy.sh
workflows:
version: 2
build-deploy-master:
jobs:
- build:
filters:
branches:
only: master
- deploy:
requires:
- build
filters:
branches:
only: master
これで、ファイルを保存して終了できます。
変更がKubernetesのデプロイに実際に反映されるようにするには、 index.html
. HTMLを次のような別のものに変更します。
<!DOCTYPE html>
<title>DigitalOcean</title>
<body>
Automatic Deployment is Working!
</body>
上記の変更を保存したら、変更したすべてのファイルをリポジトリにコミットし、変更をアップストリームにプッシュします。
- cd ~/do-sample-app/
- git add --all
- git commit -m "add deploy script and add new steps to circleci config"
- git push
新しいビルドがCircleCIで実行され、Kubernetesクラスターに変更が正常にデプロイされていることがわかります。
ビルドが完了するのを待ってから、前に実行したのと同じコマンドを実行します。
- kubectl port-forward $(kubectl get pod --selector="app=do-kubernetes-sample-app" --output jsonpath='{.items[0].metadata.name}') 8080:80
URLでブラウザを開いて、すべてが機能していることを確認します localhost:8080
またはを作成することによって curl
それに要求します。 更新されたHTMLが表示されます。
- curl localhost:8080
次の出力が表示されます。
Output<!DOCTYPE html>
<title>DigitalOcean</title>
<body>
Automatic Deployment is Working!
</body>
これは、CircleCIを使用して自動展開を正常にセットアップしたことを意味します。
結論
これは、CircleCIを使用してDigitalOceanKubernetesにデプロイする方法に関する基本的なチュートリアルでした。 ここから、さまざまな方法でパイプラインを改善できます。 あなたが最初にできることは、シングルを作成することです build
それぞれが異なるKubernetesクラスターまたは異なる名前空間にデプロイする複数のデプロイのジョブ。 これは、開発/ステージング/本番環境に異なるGitブランチがあり、デプロイメントが常に分離されていることを確認する場合に役立ちます。
使用する代わりに、CircleCIで使用する独自のイメージを作成することもできます buildpack-deps
. この画像はそれに基づいている可能性がありますが、すでに持っている可能性があります kubectl
と envsubst
インストールされている依存関係。
KubernetesのCI/CDの詳細については、Kubernetes WebinarSeriesのCI/ CDのチュートリアルをご覧ください。また、Kubernetesのアプリの詳細については、アプリケーションの最新化をご覧ください。 Kubernetes。