こんにちは、テクマトリックスの酒井です。

前回の記事では minikubeArgo CD を利用して、ローカル環境でコンテナを Kubernetes クラスターにデプロイする仕組みを構築しました。今回はこの環境で、ローカルの Kubernetes クラスターにアプリケーションをデプロイしてみます。

振り返りとこれからやること

これまでに、ローカル PC に Kubernetes クラスターを作成することから始め、 Gitea を利用した Git リポジトリの作成、 JenkinsKaniko を利用してコンテナイメージをビルドする CI 環境の構築、Argo CD を利用して Kubernetes クラスター上にアプリケーションをデプロイする仕組みの構築を行ってきました。

今回は、 CI 環境でコンテナイメージがビルドされたと仮定して、アプリケーションをデプロイする仕組みを利用してコンテナイメージを Kubernetes クラスターで実行してみます。

以上を図にすると次のようになります。

ローカル PC でアプリケーションがデプロイされるまでの流れ

構成

前回の記事で構築したローカル PC 上の Kubernetes クラスターにウェブサーバーをデプロイします。ウェブサーバーとして、 Docker Hub にある digitalocean/flask-helloworld イメージを利用します。このイメージは、アクセスすると単に「Hello, World!」と表示するだけのウェブサーバーです。これに伴い、 Kubernetes 上のコンテナレジストリの代わりに Docker Hub を利用します。

ウェブサーバーをデプロイする方法は、話を単純にするために YAML 形式の Kubernetes マニフェストを作成することにします。マニフェストファイルを保存する Gitea のリポジトリを用意し、 Argo CD でこのリポジトリを参照するアプリケーションを作成します。これにより、マニフェストファイルを Gitea のリポジトリにプッシュすると、ウェブサーバーが Kubernetes クラスターにデプロイされます。

デプロイ用 Git リポジトリを作成

まずは Kubernetes マニフェストを保存する Git リポジトリを作成します。アプリケーション本体のソースコードや Dockerfile などを保存するリポジトリと区別するため、今回作成するリポジトリを「デプロイ用 Git リポジトリ」と呼ぶことにします。 Windows Powershell にて次のスクリプトを実行します。

$RepoName      = 'flask-helloworld' # リポジトリ名
$GiteaDomain   = "git.$(minikube ip).nip.io" # Gitea のドメイン
$GiteaUsername = 'gitea_admin'      # Gitea の初期ユーザー名
$GiteaPassword = 'r8sA8CPHD9!bt6d'  # Gitea の初期ユーザーのパスワード

# Gitea API にアクセスするための認証情報
$Headers = @{ Authorization = "Basic "+ [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("${GiteaUsername}:${GiteaPassword}")) }

# リポジトリ flask-helloworld を作成。 README を自動生成
$Repo = Invoke-RestMethod -Method 'POST' `
  -Uri "http://${GiteaDomain}/api/v1/user/repos" `
  -Headers ${Headers} `
  -ContentType 'application/json' `
  -Body $(ConvertTo-Json @{ name = ${RepoName}; auto_init = $True })

echo ('クローン URL: ' + $Repo.clone_url)

リポジトリが作成できたら、このリポジトリをクローンします。

git clone $Repo.clone_url
cd $RepoName

Kubernetes マニフェストファイルを作成

クローンしたディレクトリに、デプロイメントを定義するマニフェストファイル flask-deployment.yaml を作成します。このファイルの内容は以下のとおりです。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask-dep
  labels:
    app: flask-helloworld
spec:
  replicas: 2
  selector:
    matchLabels:
      app: flask-helloworld
  template:
    metadata:
      labels:
        app: flask-helloworld
    spec:
      containers:
      - name: flask
        image: digitalocean/flask-helloworld:latest
        ports:
        - containerPort: 5000

もう一つ、サービスのマニフェストファイル flask-service.yaml を作成します。

apiVersion: v1
kind: Service
metadata:
  name: flask-svc
  labels:
    app: flask-helloworld
spec:
  type: LoadBalancer 
  ports:
  - port: 80
    targetPort: 5000
    protocol: TCP
  selector:
    app: flask-helloworld

なお、上記の 2 つの YAML ファイルの内容は、コンテナイメージのドキュメントに記載の GitHub リポジトリk8s ディレクトリに保存されているものと同一です。

必要なファイルを作成したので、これらをコミット、プッシュします。

# ファイルを追加
git add .

# 変更をコミット
git commit -m 'デプロイメントとサービスを追加'

# コミットを Gitea のリポジトリにプッシュ
git push
# ユーザー名 (gitea_admin) とパスワードを入力

Argo CD にアプリケーションを追加

続いて、 Argo CD にて flask-helloworld アプリケーションを追加します。前回の記事では GUI を操作して追加しましたが、今回は argocd CLI を利用して追加してみます。 Windows Powershell で 1 つのコマンドを実行するだけです。

argocd app create flask-helloworld `
  --repo "http://${GiteaDomain}/gitea_admin/flask-helloworld.git" `
  --path . `
  --dest-server https://kubernetes.default.svc `
  --dest-namespace flask-helloworld `
  --sync-policy automated `
  --sync-option CreateNamespace=true

コマンドが完了するとすぐに Argo CD の GUI に flask-helloworld アプリケーションが表示され、まもなくステータスが Progressing Synced になりました。

flask-helloworld アプリケーションを作成した直後

APP HEALTH がいつまでも Progressing のままなのが気になりますが、変わる気配がありませんし実害もなさそうなので、先に進みます。

GitOps してみる

ウェブサーバーはデプロイされたようですが、今の状態ではブラウザからウェブサーバーにアクセスできないため確認できません。そこでイングレスを追加してブラウザからアクセスできるようにします。

イングレスを追加するには、デプロイ用 Git リポジトリに flask-ingress.yaml を追加します。ファイルの内容は次のとおりですが、 ${IPADDR} は VM の IP アドレスに置き換えます。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: flask-helloworld
  namespace: flask-helloworld
spec:
  rules:
  - host: helloworld.${IPADDR}.nip.io
    http:
      paths:
      - backend:
          service:
            name: flask-svc
            port:
              number: 80
        path: /
        pathType: Prefix

そしてファイルの追加をコミット・プッシュします。

# ファイルを追加
git add .

# 変更をコミット
git commit -m 'イングレスを追加'

# コミットを Gitea のリポジトリにプッシュ
git push

ブラウザで flask-helloworld アプリケーションを見ていると、少し時間を置いて flask-helloworld イングレスが追加され、アプリケーションのステータスが Synced に変わります。

イングレスが追加され、同時にアプリケーションにもリンクが追加された

イングレス、または、一番左にあるアプリケーションに、右上向きの矢印アイコンが表示されています。このアイコンをクリックすると、新しいタブで「Hello, World!」と表示されます。これでGitOpsができていることが確認できました!

まとめ

ローカル環境の Kubernetes クラスターで Argo CD を利用して GitOps を体験しました。 Argo CD を利用することで、どうやってデプロイするかを気にする必要がなくなるため、 Git にプッシュすると環境が変わるという仕組みを簡単に構築でき、アプリケーションを簡単かつスムーズにデプロイできたと感じました。

今回はデプロイ用 Git リポジトリに YAML 形式の Kubernetes のマニフェストファイルを保存しました。いずれ Kubernetes に慣れてきたら、代わりに Kustomization ファイルや Helm チャートを作成しても良いと思います。

今回試した GitOps をコンテナイメージの CI 環境と組み合わせると、コンテナイメージがビルドされたら Kubernetes のマニフェストファイルを更新してテスト環境を作成することもできるでしょう。さらにエンドツーエンドテストを実行して、すべてのテストが成功したら……といったように、デリバリーパイプラインの自動化の範囲を広げ、開発とテストの効率をより高めることができそうです。

By tsakai

Jenkins関連のサービスやCloudBees製品を主に担当しています。 Certified CloudBees Jenkins Engineer (CCJE) および CloudBees CI DevOps Associate です。