序章

自動展開プロセスを持つことは、スケーラブルで復元力のあるアプリケーションの要件であり、 GitOpsまたはGitベースのDevOpsは、Gitを使用してCI/CDを整理する一般的な方法に急速になりました。 「信頼できる唯一の情報源」としてのリポジトリ。 CircleCI などのツールはGitHubリポジトリと統合されているため、リポジトリに変更を加えるたびにコードを自動的にテストしてデプロイできます。 この種のCI/CDをKubernetesインフラストラクチャの柔軟性と組み合わせると、需要の変化に合わせて簡単に拡張できるアプリケーションを構築できます。

この記事では、CircleCIを使用して、サンプルアプリケーションをDigitalOcean Kubernetes(DOKS)クラスターにデプロイします。 このチュートリアルを読むと、これらの同じ手法を適用して、Dockerイメージとしてビルド可能な他のCI/CDツールをデプロイできるようになります。

前提条件

このチュートリアルに従うには、次のものが必要です。

このチュートリアルでは、Kubernetesバージョンを使用します 1.22.7kubectl バージョン 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 このようなコマンド:

  1. kubectl --kubeconfig ~/Desktop/kubernetes-deployment-tutorial-kubeconfig.yaml get pods

これにより、次の出力が生成されます。

Output
No resources found.

これは、クラスターにアクセスしたことを意味します。 The No resources found. クラスタにポッドがないため、メッセージは正しいです。

他のKubernetesクラスタを維持していない場合は、kubeconfigファイルをホームディレクトリの次のフォルダにコピーできます。 .kube. 存在しない場合に備えて、そのディレクトリを作成します。

  1. mkdir -p ~/.kube

次に、設定ファイルを新しく作成したファイルにコピーします .kube ディレクトリと名前を変更します config:

  1. cp current_kubernetes-deployment-tutorial-kubeconfig.yaml_file_path ~/.kube/config

これで、構成ファイルにパスが含まれるはずです。 ~/.kube/config. これは kubectl コマンドを実行するとデフォルトで読み取るため、渡す必要はありません --kubeconfig もう。 次を実行します。

  1. kubectl get pods

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

Output
No resources found in default namespace.

次に、次のコマンドでクラスターにアクセスします。

  1. kubectl get nodes

クラスタ上のノードのリストを受け取ります。 出力は次のようになります。

Output
NAME 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 それに:

  1. mkdir ~/do-sample-app
  2. cd ~/do-sample-app

次に、次のコマンドを使用して、このフォルダーに新しいGitリポジトリを作成します。

  1. git init .

このリポジトリ内に、という名前の空のフォルダを作成します kube:

  1. mkdir ~/do-sample-app/kube/

これは、クラスタにデプロイするサンプルアプリケーションに関連するKubernetesリソースマニフェストを保存する場所になります。

次に、という別のフォルダを作成します kube-general、ただし今回は作成したGitリポジトリの外です。 ホームディレクトリ内に作成します。

  1. mkdir ~/kube-general/

このフォルダーは、クラスター上の単一のデプロイメントに固有ではなく、複数のデプロイメントに共通のマニフェストを格納するために使用されるため、Gitリポジトリーの外部にあります。 これにより、これらの一般的なマニフェストをさまざまな展開で再利用できるようになります。

フォルダーを作成し、サンプルアプリケーションのGitリポジトリーを配置したら、DOKSクラスターの認証と承認を調整します。

ステップ3—サービスアカウントを作成する

通常、デフォルトの admin ユーザーを使用して、他のServicesからKubernetesクラスターへの認証を行うことはお勧めしません。 外部プロバイダーのキーが危険にさらされると、クラスター全体が危険にさらされます。

代わりに、RBACKubernetes認証モデルの一部である特定のロールを持つ単一のサービスアカウントを使用します。

この承認モデルは、ロールおよびリソースに基づいています。 基本的にクラスター上のユーザーであるサービスアカウントを作成することから始め、次に、クラスター上でアクセスできるリソースを指定するロールを作成します。 最後に、 Role Binding を作成します。これは、ロールと以前に作成したサービスアカウント間の接続を確立するために使用され、ロールがアクセスできるすべてのリソースへのアクセスをサービスアカウントに付与します。

作成する最初のKubernetesリソースは、CI/CDユーザーのサービスアカウントです。このチュートリアルではこの名前を付けます。 cicd.

ファイルを作成する cicd-service-account.yml~/kube-general フォルダを開き、お気に入りのテキストエディタで開きます。

  1. nano ~/kube-general/cicd-service-account.yml

その上に次の内容を書いてください。

〜/ 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、次のように:

  1. kubectl apply -f ~/kube-general/

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

Output
serviceaccount/cicd created

サービスアカウントが機能していることを確認するには、それを使用してクラスターにログインしてみてください。 これを行うには、最初にそれぞれのアクセストークンを取得し、それを環境変数に格納する必要があります。 すべてのサービスアカウントには、KubernetesがSecretとして保存するアクセストークンがあります。

次のコマンドを使用して、このシークレットを取得できます。

  1. 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 (クラスター用にダウンロードした構成ファイル)。 このコマンドは、このチュートリアルの後半で学習する特定のエラーを表示します。

  1. 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 構成ファイルと資格情報を読み取るのではなく、提供されたトークンを使用します。

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

Output
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:cicd" cannot list resource "pods" in API group "" in the namespace "default"

これはエラーですが、トークンが機能したことを示しています。 受け取ったエラーは、サービスアカウントにリソースを一覧表示するために必要な認証がないことに関するものです secrets、しかし、サーバー自体にアクセスすることができました。 トークンが機能しなかった場合、エラーは次のようになります。

Output
error: You must be logged in to the server (Unauthorized)

認証が成功したので、次のステップはサービスアカウントの認証エラーを修正することです。 これを行うには、必要な権限を持つロールを作成し、それをサービスアカウントにバインドします。

ステップ4—ロールとロールバインディングの作成

Kubernetesには、ロールを定義する2つの方法があります。 Role または ClusterRole 資源。 前者と後者の違いは、最初の名前空間は単一の名前空間に適用され、もう1つはクラスター全体に有効であるということです。

このチュートリアルでは単一の名前空間を使用しているため、 Role.

ファイルを作成する ~/kube-general/cicd-role.yml お気に入りのテキストエディタで開きます。

  1. nano ~/kube-general/cicd-role.yml

基本的な考え方は、Kubernetesのほとんどのリソースに関連するすべてのことを実行するためのアクセスを許可することです。 default 名前空間。 君の Role このようになります:

〜/ kube-general / cicd-role.yml
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、作成したのと同じ名前空間に作成します ServiceAccountdefault 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 そしてそれを開きます:

  1. nano ~/kube-general/cicd-role-binding.yml

次の行をファイルに追加します。

〜/ 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クラスターにこれらの新しいリソースを作成します。

  1. kubectl apply -f ~/kube-general/

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

Output
rolebinding.rbac.authorization.k8s.io/cicd created role.rbac.authorization.k8s.io/cicd created serviceaccount/cicd unchanged

ここで、前に実行したコマンドを試してください。

  1. kubectl --insecure-skip-tls-verify --kubeconfig="/dev/null" --server=server-from-kubeconfig-file --token=$TOKEN get pods

ポッドがないため、次の出力が生成されます。

Output
No resources found in default namespace.

このステップでは、CircleCIで使用するサービスアカウントに、リソースの一覧表示、作成、更新など、クラスターで意味のあるアクションを実行するために必要な承認を与えました。 次に、サンプルアプリケーションを作成します。

ステップ5—サンプルアプリケーションの作成

注:これ以降に作成されるすべてのコマンドとファイルは、フォルダーから開始されます ~/do-sample-app 以前に作成しました。 これは、クラスターにデプロイするサンプルアプリケーションに固有のファイルを作成しているためです。

Kubernetes Deployment 作成するのはNginxイメージをベースとして使用し、アプリケーションは単純な静的HTMLページになります。 Nginxから直接HTMLを提供することでデプロイメントが機能するかどうかをテストできるため、これは素晴らしいスタートです。 後で見るように、ローカルに来るすべてのトラフィックをリダイレクトすることができます address:port クラスター上のデプロイメントに接続して、クラスターが機能しているかどうかをテストします。

以前に設定したリポジトリ内に、新しいリポジトリを作成します Dockerfile ファイルを作成し、選択したテキストエディタで開きます。

  1. nano ~/do-sample-app/Dockerfile

その上に次のように書いてください。

〜/ do-sample-app / Dockerfile
FROM nginx:1.21

COPY index.html /usr/share/nginx/html/index.html

これにより、Dockerにアプリケーションコンテナをビルドするように指示します。 nginx 画像。

今すぐ新しいを作成します index.html ファイルを開いて開きます。

  1. nano ~/do-sample-app/index.html

次のHTMLコンテンツを記述します。

〜/ do-sample-app / index.html
<!DOCTYPE html>
<title>DigitalOcean</title>
<body>
  Kubernetes Sample Application
</body>

このHTMLは、アプリケーションが機能しているかどうかを知らせる簡単なメッセージを表示します。

イメージをビルドして実行することで、イメージが正しいかどうかをテストできます。

まず、次のコマンドでイメージをビルドします。 dockerhub-username 独自のDockerHubユーザー名を使用します。 ここでユーザー名を指定する必要があります。これにより、後でDockerHubにプッシュしたときに機能します。

  1. docker build ~/do-sample-app/ -t dockerhub-username/do-kubernetes-sample-app

次に、イメージを実行します。 次のコマンドを使用して、イメージを開始し、ポート上のローカルトラフィックを転送します 8080 港へ 80 画像内では、Nginxがデフォルトでリッスンするポートは次のとおりです。

  1. 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をフェッチするコマンド:

  1. curl localhost:8080

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

Output
<!DOCTYPE html> <title>DigitalOcean</title> <body> Kubernetes Sample Application </body>

コンテナを停止します(CTRL + C 実行中のターミナルで)、このイメージをDockerHubアカウントに送信します。 これを行うには、最初にDockerHubにログインします。

  1. docker login

Docker Hubアカウントに関する必要な情報を入力してから、次のコマンドでイメージをプッシュします(忘れずに dockerhub-username あなた自身で):

  1. 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 テキストエディタで開きます。

  1. nano ~/do-sample-app/kube/do-sample-deployment.yml

ファイルに次の内容を書き込み、必ず置き換えてください dockerhub-username Docker Hubユーザー名を使用:

〜/ do-sample-app / kube / do-sample-deployment.yml
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 お気に入りのエディターで開きます。

  1. nano ~/do-sample-app/kube/do-sample-service.yml

次に、ファイルに次の行を追加します。

〜/ 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 同じ名前でも、コンテナのものとは異なるポート/名前の組み合わせを使用できた可能性があります。

あなたと ServiceDeployment マニフェストファイルが作成されました。これで、Kubernetesクラスターでこれらのリソースを作成できます。 kubectl:

  1. kubectl apply -f ~/do-sample-app/kube/

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

Output
deployment.apps/do-kubernetes-sample-app created service/do-kubernetes-sample-app created

マシンの1つのポートを、サービスがKubernetesクラスター内で公開しているポートに転送して、これが機能しているかどうかをテストします。 あなたはそれを使ってそれをすることができます kubectl port-forward:

  1. 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、シェルはインタラクティブでなくなり、代わりにクラスターにリダイレクトされたリクエストを出力します。

Output
Forwarding from 127.0.0.1:8080 -> 80 Forwarding from [::1]:8080 -> 80

オープニング localhost:8080 どのブラウザでも、コンテナをローカルで実行したときに表示されたのと同じページがレンダリングされますが、現在はKubernetesクラスタから取得されています。 以前と同様に、 curl 新しいターミナルウィンドウで、機能しているかどうかを確認します。

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

  1. cd ~/do-sample-app/
  2. git remote add origin https://github.com/your-github-account-username/digital-ocean-kubernetes-deploy.git

前のコマンドからの出力はありません。

次に、これまでに作成したすべてのファイルをGitHubリポジトリにコミットします。 まず、ファイルを追加します。

  1. git add --all

次に、ファイルをリポジトリにコミットします。コミットメッセージは引用符で囲みます。

  1. 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にプッシュします。

  1. git push -u origin master

ユーザー名とパスワードの入力を求められます。 これを入力すると、次のような出力が表示されます。

Output
Counting 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_USERNAMEDOCKERHUB_PASS、後でイメージをDockerHubにプッシュするために必要になります。 値をそれぞれDockerHubのユーザー名とパスワードに設定します。

次に、さらに3つ追加します。 KUBERNETES_TOKEN, KUBERNETES_SERVER、 と KUBERNETES_CLUSTER_CERTIFICATE.

の値 KUBERNETES_TOKEN は、サービスアカウントユーザーを使用してKubernetesクラスターで認証するために以前に使用したローカル環境変数の値になります。 ターミナルを閉じた場合は、いつでも次のコマンドを実行してターミナルを再度取得できます。

  1. 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 サンプルアプリケーションリポジトリ内:

  1. mkdir ~/do-sample-app/.circleci/

このディレクトリ内に、という名前のファイルを作成します config.yml お気に入りのエディターで開きます。

  1. nano ~/do-sample-app/.circleci/config.yml

次のコンテンツをファイルに追加し、必ず置き換えてください dockerhub-username Docker Hubユーザー名を使用:

〜/ 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 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:

〜/ do-sample-app / .circleci / config.yml
. . .
      - 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.

新しいファイルをリポジトリにコミットし、変更をアップストリームにプッシュします。

  1. cd ~/do-sample-app/
  2. git add .circleci/
  3. git commit -m "add CircleCI config"
  4. 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 ファイル。 ファイルを開きます。

  1. nano ~/do-sample-app/.circleci/config.yml

次に、強調表示された行を Push Docker Image ステップ:

〜/ do-sample-app / .circleci / config.yml
...
      - 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/:

  1. mkdir ~/do-sample-app/scripts/

そのフォルダ内に、という新しいbashスクリプトを作成します ci-deploy.sh お気に入りのテキストエディタで開きます。

  1. nano ~/do-sample-app/scripts/ci-deploy.sh

その中に次のbashスクリプトを記述します。

〜/ do-sample-app / scripts / ci-deploy.sh
#! /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 フォルダ。

ファイルを保存し、実行可能であることを確認します。

  1. chmod +x ~/do-sample-app/scripts/ci-deploy.sh

今、編集 ~/do-sample-app/kube/do-sample-deployment.yml:

  1. nano ~/do-sample-app/kube/do-sample-deployment.yml

コンテナイメージ値のタグを次のように変更します。

〜/ 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 お気に入りのテキストエディタで:

  1. nano ~/do-sample-app/.circleci/config.yml

次の新しい仕事を、すぐ下に書いてください build 以前に作成したジョブ:

〜/ do-sample-app / .circleci / config.yml
...
          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 仕事:

〜/ do-sample-app / .circleci / config.yml
...
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 これで次のようになります。

〜/ 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を次のような別のものに変更します。

〜/ do-sample-app / index.html
<!DOCTYPE html>
<title>DigitalOcean</title>
<body>
  Automatic Deployment is Working!
</body>

上記の変更を保存したら、変更したすべてのファイルをリポジトリにコミットし、変更をアップストリームにプッシュします。

  1. cd ~/do-sample-app/
  2. git add --all
  3. git commit -m "add deploy script and add new steps to circleci config"
  4. git push

新しいビルドがCircleCIで実行され、Kubernetesクラスターに変更が正常にデプロイされていることがわかります。

ビルドが完了するのを待ってから、前に実行したのと同じコマンドを実行します。

  1. 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が表示されます。

  1. curl localhost:8080

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

Output
<!DOCTYPE html> <title>DigitalOcean</title> <body> Automatic Deployment is Working! </body>

これは、CircleCIを使用して自動展開を正常にセットアップしたことを意味します。

結論

これは、CircleCIを使用してDigitalOceanKubernetesにデプロイする方法に関する基本的なチュートリアルでした。 ここから、さまざまな方法でパイプラインを改善できます。 あなたが最初にできることは、シングルを作成することです build それぞれが異なるKubernetesクラスターまたは異なる名前空間にデプロイする複数のデプロイのジョブ。 これは、開発/ステージング/本番環境に異なるGitブランチがあり、デプロイメントが常に分離されていることを確認する場合に役立ちます。

使用する代わりに、CircleCIで使用する独自のイメージを作成することもできます buildpack-deps. この画像はそれに基づいている可能性がありますが、すでに持っている可能性があります kubectlenvsubst インストールされている依存関係。

KubernetesのCI/CDの詳細については、Kubernetes WebinarSeriesCI/ CDのチュートリアルをご覧ください。また、Kubernetesのアプリの詳細については、アプリケーションの最新化をご覧ください。 Kubernetes