RAKUS Developers Blog | ラクス エンジニアブログ

株式会社ラクスのITエンジニアによる技術ブログです。

【k8s】kindを使って開発環境にArgoWorkflowsを構築

はじめに

はじめまして、disk-bugと申します。
今回は、k8s初心者な私が開発環境にkindを利用してk8sクラスタを構築し、そのクラスタ上でArgoWorkflowsを動かすことができましたので、k8s上にArgoWorkflowsが構築できるまでのお話をしたいと思います。

目次

k8sとは?

Kubernetes(k8s)は、デプロイやスケーリングを自動化したり、コンテナ化されたアプリケーションを管理したりするための、オープンソースのシステムです。
Kubernetesを利用することで、手動デプロイを無くし、高負荷状態になった時のスケーリングやヘルスチェックによる自動復旧などができるようになります。
そもそもKubernetesの読み方についてですが、
「クバネティス」「クバネテス」「クーベネティス」、色々と読み方があるようです。
他にもk8sやkubeとも呼ばれていますが、本記事ではk8s(ケーエイツ、ケーハチエス)と以下呼ぶようにします。
なぜk8sなのかというと、K+8文字+sだからなんだそうです。

kindとは?

k8sが便利そうなのはわかったけど、実際どんな感じか動かしてみたいですよね。
k8sの公式ドキュメントに各種ツールが紹介されており、ローカル上で実行するツールも紹介されています。
Minikubekindが紹介されていますが、kindの説明に1種類のコンテナランタイム上で動作との記載があり軽量に動かせそうなのかなと思いました。
よって、今回はkindを選択しました。
kindの公式ドキュメントの説明でも、

Dockerコンテナのノードを利用して、ローカル上でk8sクラスタを実行するためのツールになります。

と紹介されているのでDocker上でk8sクラスタが構築できるようです。

ArgoWorkflowsとは?

k8s上で何か動かしたいですよね。
もともとチーム内で新しいPipelineツールの検討を行っていたので、k8s上で動かせるArgoWorkflowsに目をつけました。
ArgoWorkflowsとは、k8sでジョブを調整するためのOSSのコンテナーネイティブワークフローエンジンです。
Argoと聞くとArgoCDを思い浮かべる方が多いと思いますが、ワークフローエンジンも提供しています。
今までPipelineやJobを実行するツールと言えばJenkinsくらいしか使ってこなかったので、k8sに加えてArgoWorkflowsという新しい技術への挑戦となりました。

kindを使ってk8sクラスタを構築してみる

では実際にkindを使って、k8sクラスタを構築してみます。

kindのQuickStartを参照して、まずは自身の端末にkindコマンドをインストールします。
MacOSを使っていますので、以下コマンドでインストールしました。

$ brew install kind

$ kind --version
kind version 0.14.0

シングルノークラスタ作成

kindコマンドがインストールできましたので、k8sクラスタを構築してみます。
以下コマンドでk8sクラスタが構築できるようですが、エラーが発生しました。

$ kind create cluster
ERROR: failed to create cluster: failed to list nodes: command "docker ps -a --filter label=io.x-k8s.kind.cluster=kind --format '{{.Names}}'" failed with error: exit status 1
Command Output: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

初歩的なミス・・・Dockerを起動してませんでした。
DockerDesktopを起動して、再度コマンド実行します。

$ kind create cluster
Creating cluster "kind" ...
...
Set kubectl context to "kind-kind"

k8sクラスタが構築できたので確認します。

$ kind get clusters
kind

kindというk8sクラスタが作成されました。

k8sクラスタを制御できるkubectlというコマンドがあるので、インストールして作成したk8sクラスタを確認してみましょう。

$ brew install kubectl
...

$ kubectl cluster-info --context kind-kind
Kubernetes control plane is running at ...
...

kubectlコマンドでk8sクラスタが確認できました。

ここで、今更ながらk8sクラスタとは何でしょうか?
k8sクラスタとは、コンテナ化されたアプリケーションを実行するためのサーバー群のことです。
そしてサーバー(VMや物理的なマシン)のことをノードと呼びます。
ノードは以下2種類です。

  • ワーカーノード:コンテナ化されたアプリケーションを実行する環境
  • マスターノード:コンテナ化されたアプリケーション環境を管理する環境

何を管理するのかというと、

  • 目的の状態になっているのか?
  • 具体的にはアプリケーションが生きているか?
  • 必要なアプリケーション数になっているか?

などなど、現在の状態から目的の状態になるように管理します。
kindで構築したk8sクラスタのノードを確認してみましょう。

$ kubectl get node
NAME                 STATUS   ROLES           AGE    VERSION
kind-control-plane   Ready    control-plane   5m6s   v1.24.0

$ kubectl describe node kind-control-plane
Name:               kind-control-plane
...

$ docker container ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED              STATUS              PORTS                       NAMES
118df6a43f45   kindest/node:v1.24.0   "/usr/local/bin/entr…"   About a minute ago   Up About a minute   127.0.0.1:54251->6443/tcp   kind-control-plane

今回はマスターノードだけが構築されたので、シングルノークラスタが構築されました。
(1つのノードだけなのでシングルクラスタ、そのままですね)
kindはコンテナをノードとして扱うツールですので、dockerコマンドでもノードの確認が可能です。

一旦、k8sクラスタをお掃除します。

$ kind delete cluster

マルチノードクラスタ作成

マスターノードだけのシングルノークラスタが構築できたので、次はワーカーノードもあるマルチノードクラスタを構築しましょう。
(複数のノードがあるからマルチノード、単純ですね)
ドキュメントを参照するとymlファイルを使って構築できそうです。
以下の内容でymlファイルを作成し、

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker

kindコマンドにて先程のymlファイルを指定し、k8sクラスタを構築します。

$ kind create cluster --config cluster.yml
Creating cluster "kind" ...
...
Set kubectl context to "kind-kind"

$ kubectl get nodes -o wide
NAME                 STATUS   ROLES           AGE    VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE       KERNEL-VERSION      CONTAINER-RUNTIME
kind-control-plane   Ready    control-plane   34s   v1.24.0   172.24.0.4    <none>        Ubuntu 21.10   5.10.104-linuxkit   containerd://1.6.4
kind-worker          Ready    <none>          11s   v1.24.0   172.24.0.3    <none>        Ubuntu 21.10   5.10.104-linuxkit   containerd://1.6.4
kind-worker2         Ready    <none>          11s   v1.24.0   172.24.0.2    <none>        Ubuntu 21.10   5.10.104-linuxkit   containerd://1.6.4

$ docker container ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED              STATUS          PORTS                       NAMES
b101e316a8ff   kindest/node:v1.24.0   "/usr/local/bin/entr…"   About a minute ago   Up 55 seconds   127.0.0.1:54512->6443/tcp   kind-control-plane
7e18515677be   kindest/node:v1.24.0   "/usr/local/bin/entr…"   About a minute ago   Up 55 seconds                               kind-worker2
913b69d58e62   kindest/node:v1.24.0   "/usr/local/bin/entr…"   About a minute ago   Up 55 seconds                               kind-worker

kubectlコマンド・dockerコマンド、それぞれでマスターノード1つとワーカーノード2つが作成されていることが確認できました。
(Ubuntuが動いているみたいですね)

アプリケーションをデプロイしてみる

アプリケーションの実行環境であるワーカーノードができたので、実際にアプリケーションをワーカーノード上で動かしてみましょう。
k8sクラスタ上のワーカーノードにアプリケーションをデプロイするには、Podを作成してデプロイします。
Podとは、k8sオブジェクトモデルであり、実行できるアプリケーションの単位で、作成またはデプロイする最小かつ最も単純な単位になります。
今回は理解を単純にするために、1Pod1コンテナでPodを作成します。

では、Podを作成してデプロイするため、Podをymlで定義してみましょう。

apiVersion: v1
kind: Pod
metadata:
  name: hoge-pod
  labels:
    component: hoge-nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest

specにて何のDockerイメージを取得するのか、定義しています。
(今回はnginxのlatest)

Podをデプロイしてみましょう。

$ kubectl apply -f hoge-pod.yml
hoge-pod created

$ kubectl get pods -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP           NODE          NOMINATED NODE   READINESS GATES
hoge-pod   1/1     Running   0          13s   10.244.1.5   kind-worker   <none>           <none>

ステータスがRunnningとなっていれば、正常に作成されアプリケーションが稼働している状態です。
もしRunningになっていない場合は、以下コマンドで詳細が確認できます。

$ kubectl describe pods hoge-pod
...

Eventsにエラー内容が記載されているので、そこを確認しましょう。
次に問題なくnginxが動いているのか、Podに入って確認します。

$ kubectl exec -it hoge-pod -- bash
root@hoge-pod:/# curl -v localhost:80
HTTP/1.1 200 OK
...

localhost:80curlすると、nginxのWelcomeページが返却されます。
なぜわざわざPodに入って確認したのかというと、Podはk8sクラスタの内部に閉じているためです。
外部に公開する方法については、後項で紹介いたします。

一旦、k8sクラスタのPodをお掃除します。

$ kubectl delete pod hoge-pod

アプリケーションをスケールする

前項では手動でPodをデプロイしましたが、同じ状態のPodを1つ2つと増やすにはどうしたら良いのでしょうか?
k8sには、ReplicaSetとDeploymentという機能があります。
ReplicaSetは、設定したレプリカ数分のPodを利用可能な状態で維持してくれる機能になります。
Deploymentは、ReplicaSetの上位レベルの概念でPodのローリングアップデート機能を提供しています。

Podをスケールするために、Deplymentをymlで定義してみましょう。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hoge-deployment
  labels:
    component: hoge-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      component: hoge-nginx
  template:
    metadata:
      labels:
        component: hoge-nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
          - containerPort: 80

replicasでPodの数、selectorで管理するPodのラベルを定義しています。
なお、Podのラベルはtemplace.metadata.labelsに定義されているものになります。
templateで作成するPodを定義しています。

Deploymentを適用してみましょう。

$ kubectl apply -f hoge-deployment.yml
deployment.apps/hoge-deployment created

$ kubectl get deployments
NAME              READY   UP-TO-DATE   AVAILABLE   AGE
hoge-deployment   3/3     3            3           37s

$ kubectl get pods -o wide
NAME                              READY   STATUS    RESTARTS   AGE   IP           NODE           NOMINATED NODE   READINESS GATES
hoge-deployment-664bf7b75-2zvfm   1/1     Running   0          7s    10.244.2.7   kind-worker2   <none>           <none>
hoge-deployment-664bf7b75-4fdw8   1/1     Running   0          7s    10.244.1.6   kind-worker    <none>           <none>
hoge-deployment-664bf7b75-5k8s7   1/1     Running   0          7s    10.244.1.7   kind-worker    <none>           <none>

Deploymentを適用すると、replicasで指定された数のPodが作成されます。
試しにPodを1つ削除してみましょう。

$ kubectl delete pods hoge-deployment-664bf7b75-2zvfm
pod "hoge-deployment-664bf7b75-2zvfm" deleted

$ kubectl get pods -o wide
NAME                              READY   STATUS    RESTARTS   AGE   IP           NODE           NOMINATED NODE   READINESS GATES
hoge-deployment-664bf7b75-4fdw8   1/1     Running   0          88s   10.244.1.6   kind-worker    <none>           <none>
hoge-deployment-664bf7b75-5k8s7   1/1     Running   0          88s   10.244.1.7   kind-worker    <none>           <none>
hoge-deployment-664bf7b75-vgb9k   1/1     Running   0          19s   10.244.2.8   kind-worker2   <none>           <none>

1つ削除しましたが、Podを確認すると3つになっています。
AGEから見るに1番下のPodが新規に作成されたようです。便利ですね。
これでアプリケーションのスケールアウト・スケールインが可能となりました。

一旦、k8sクラスタをお掃除します。

$ kind delete cluster

アプリケーションに外部から接続する(NodePort Service)

前項にてDeploymentでPodを複数作成しましたが、IPアドレスが動的なことにお気づきでしょうか?。

# 1Pod削除前
$ kubectl get pods -o wide
NAME                              READY   STATUS    RESTARTS   AGE   IP           NODE           NOMINATED NODE   READINESS GATES
hoge-deployment-664bf7b75-2zvfm   1/1     Running   0          7s    10.244.2.7   kind-worker2   <none>           <none>
hoge-deployment-664bf7b75-4fdw8   1/1     Running   0          7s    10.244.1.6   kind-worker    <none>           <none>
hoge-deployment-664bf7b75-5k8s7   1/1     Running   0          7s    10.244.1.7   kind-worker    <none>           <none>

# 1Pod削除後
$ kubectl get pods -o wide
NAME                              READY   STATUS    RESTARTS   AGE   IP           NODE           NOMINATED NODE   READINESS GATES
hoge-deployment-664bf7b75-4fdw8   1/1     Running   0          88s   10.244.1.6   kind-worker    <none>           <none>
hoge-deployment-664bf7b75-5k8s7   1/1     Running   0          88s   10.244.1.7   kind-worker    <none>           <none>
hoge-deployment-664bf7b75-vgb9k   1/1     Running   0          19s   10.244.2.8   kind-worker2   <none>           <none>

新しく作成されたPodのIPアドレスが、削除されたPodとは異なるIPアドレスが設定されています。
(10.244.2.7から10.244.2.8に)
k8sクラスタは動的な環境となっています。
例えばIPアドレス指定でPodにアクセスしていると、バージョンアップ等でPodが再作成された場合にアクセスできなくなってしまいます。
また、IPアドレス指定でのアクセスですと、1つのPodにしかアクセスされず負荷分散ができていません。
そこで登場するのがServiceになります。
Serviceは、Podの集合で実行されているアプリケーションをネットワークサービスとして公開してくれる機能です。
特定のラベルを持ったPodのどれかにアクセスできるようエンドポイントを提供してくれます。

Podにアクセスできるようにするために、Serviceをymlで定義してみましょう。

apiVersion: v1
kind: Service
metadata:
  name: hoge-service
spec:
  type: NodePort
  selector:
    component: hoge-nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30080

今回はNodePortタイプのServiceを定義しています。
NodePortタイプにすることで、ノードの対象ポートへの通信をServiceへ転送するようになります。
selectorでPodのラベルを指定しPodの集合体を形成し、portはServiceのポートになります。
また、targetPortはPodが待ち受けているポート、nodePortはノードからSerivceへ通信を転送するポートになります。

Serviceにアクセスできるようにk8sクラスタを構築し直します。
新しいk8sクラスタをymlで定義します。

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
  extraPortMappings:
  - containerPort: 30080
    hostPort: 30080
    protocol: TCP

ワーカーノードのポート:30080と自端末のポート:30080を紐付けています。

k8sクラスタを作成しましょう。

$ kind create cluster --config cluster.yml
...

$ docker container ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED         STATUS         PORTS                       NAMES
e8c8938d96a7   kindest/node:v1.24.0   "/usr/local/bin/entr…"   2 minutes ago   Up 2 minutes   0.0.0.0:30080->30080/tcp    kind-worker
c901092d5858   kindest/node:v1.24.0   "/usr/local/bin/entr…"   2 minutes ago   Up 2 minutes   127.0.0.1:58099->6443/tcp   kind-control-plane

ワーカーノードのポート:30080と自端末のポート:30080が紐付けられています。

k8sクラスタができたので、DeploymentとServiceを適用しましょう。

$ kubectl apply -f hoge-deployment.yml
deployment.apps/hoge-deployment created

$ kubectl apply -f hoge-service.yml
service/hoge-service created

$ kubectl get pods,deployments,services -o wide
NAME                                  READY   STATUS    RESTARTS   AGE     IP           NODE          NOMINATED NODE   READINESS GATES
pod/hoge-deployment-664bf7b75-scclb   1/1     Running   0          6m47s   10.244.1.3   kind-worker   <none>           <none>
pod/hoge-deployment-664bf7b75-x4gzc   1/1     Running   0          6m47s   10.244.1.2   kind-worker   <none>           <none>
pod/hoge-deployment-664bf7b75-xdm4j   1/1     Running   0          6m47s   10.244.1.4   kind-worker   <none>           <none>

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES         SELECTOR
deployment.apps/hoge-deployment   3/3     3            3           6m47s   nginx        nginx:latest   component=hoge-nginx

NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE   SELECTOR
service/hoge-service   NodePort    10.96.122.115   <none>        80:30080/TCP   6s    component=hoge-nginx
service/kubernetes     ClusterIP   10.96.0.1       <none>        443/TCP        11m   <none>

全て正常に動いていることが確認できたら、自端末からcurlもしくはブラウザでlocalhost:30080にアクセスしてみましょう。

$ curl -i localhost:30080
HTTP/1.1 200 OK
...

Serviceのselectorに誤りがなければ、nginxのWelcomeページが返却されます。
これで、k8sクラスタ内のアプリケーションにアクセスできるようになりました。

一旦、k8sクラスタをお掃除します。

$ kind delete cluster

アプリケーションに外部から接続する(Ingress)

マイクロサービス化に伴い、URLのパスによって異なるアプリケーションを参照したいとなった場合はどうすればよいでしょうか?
Ingressが解決してくれます。
Ingressとは、k8sクラスタ内のServiceに対する外部からのアクセスを管理するAPIオブジェクトです。

  • hoge.example.com/hogeへのリクエストは、hogeアプリがデプロイされているPod群のhoge-service
  • hoge.example.com/fugaへのリクエストは、fugaアプリがデプロイされているPod群のfuga-service

Ingressがルーティングしてくれます。
ルーティングするために、Ingressをymlで定義してみましょう。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hoge-fuga-ingress
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: nginx-service
            port:
              number: 80
      - pathType: Prefix
        path: "/hoge"
        backend:
          service:
            name: hoge-service
            port:
              number: 80
      - pathType: Prefix
        path: "/fuga"
        backend:
          service:
            name: fuga-service
            port:
              number: 80
  • localhostにアクセスすると、nginx-service
  • localhost/hogeにアクセスすると、hoge-service
  • localhost/fugaにアクセスすると、fuga-service

それぞれルーティングする定義となります。
3アプリケーションのDeploymentの定義は以下になります。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    component: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      component: nginx
  template:
    metadata:
      labels:
        component: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
          - containerPort: 80

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hoge-deployment
  labels:
    component: hoge-echo
spec:
  replicas: 3
  selector:
    matchLabels:
      component: hoge-echo
  template:
    metadata:
      labels:
        component: hoge-echo
    spec:
      containers:
      - name: nginx
        image: hashicorp/http-echo:latest
        args:
        - "-text=hoge"
        ports:
        - containerPort: 5678

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: fuga-deployment
  labels:
    component: fuga-echo
spec:
  replicas: 3
  selector:
    matchLabels:
      component: fuga-echo
  template:
    metadata:
      labels:
        component: fuga-echo
    spec:
      containers:
      - name: nginx
        image: hashicorp/http-echo:latest
        args:
        - "-text=fuga"
        ports:
        - containerPort: 5678

3アプリケーションのServiceの定義は、以下になります。

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    component: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: hoge-service
spec:
  selector:
    component: hoge-echo
  ports:
  - protocol: TCP
    port: 80
    targetPort: 5678

---
apiVersion: v1
kind: Service
metadata:
  name: fuga-service
spec:
  selector:
    component: fuga-echo
  ports:
  - protocol: TCP
    port: 80
    targetPort: 5678

kindでIngressを利用するにあたって、k8sクラスタを定義したymlを修正します。

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  kubeadmConfigPatches:
  - |
    kind: InitConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-labels: "ingress-ready=true"
  extraPortMappings:
  - containerPort: 80
    hostPort: 80
    protocol: TCP

上記定義はkindのドキュメントに記載されているものを利用しています。
k8sクラスタを構築し、Deployment・Service・Ingressを適用しましょう。

$ kind create cluster --config cluster.yml
Creating cluster "kind" ...
Set kubectl context to "kind-kind"

$ kubectl apply -f hoge-fuga-deployment.yml
deployment.apps/nginx-deployment created
deployment.apps/hoge-deployment created
deployment.apps/fuga-deployment created

$ kubectl apply -f service/hoge-fuga-service.yml
service/nginx-service created
service/hoge-service created
service/fuga-service created

$ kubectl apply -f ingress/hoge-fuga-ingress.yml
ingress.networking.k8s.io/hoge-fuga-ingress created

$ kubectl get pods,deployments,services,ingress -o wide
NAME                                   READY   STATUS    RESTARTS   AGE    IP            NODE                 NOMINATED NODE   READINESS GATES
pod/fuga-deployment-65bf9f9c78-kngtk   1/1     Running   0          104s   10.244.0.9    kind-control-plane   <none>           <none>
pod/fuga-deployment-65bf9f9c78-nmv2g   1/1     Running   0          104s   10.244.0.12   kind-control-plane   <none>           <none>
pod/fuga-deployment-65bf9f9c78-wmqwr   1/1     Running   0          104s   10.244.0.11   kind-control-plane   <none>           <none>
pod/hoge-deployment-7df96b5f86-84kpt   1/1     Running   0          104s   10.244.0.10   kind-control-plane   <none>           <none>
pod/hoge-deployment-7df96b5f86-8l5fr   1/1     Running   0          104s   10.244.0.13   kind-control-plane   <none>           <none>
pod/hoge-deployment-7df96b5f86-t9dpd   1/1     Running   0          104s   10.244.0.6    kind-control-plane   <none>           <none>
pod/nginx-deployment-f78754554-7hkmw   1/1     Running   0          104s   10.244.0.7    kind-control-plane   <none>           <none>
pod/nginx-deployment-f78754554-dmnc4   1/1     Running   0          104s   10.244.0.5    kind-control-plane   <none>           <none>
pod/nginx-deployment-f78754554-rw2lb   1/1     Running   0          104s   10.244.0.8    kind-control-plane   <none>           <none>

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE    CONTAINERS   IMAGES                       SELECTOR
deployment.apps/fuga-deployment    3/3     3            3           104s   nginx        hashicorp/http-echo:latest   component=fuga-echo
deployment.apps/hoge-deployment    3/3     3            3           104s   nginx        hashicorp/http-echo:latest   component=hoge-echo
deployment.apps/nginx-deployment   3/3     3            3           104s   nginx        nginx:latest                 component=nginx

NAME                    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE     SELECTOR
service/fuga-service    ClusterIP   10.96.94.98    <none>        80/TCP    72s     component=fuga-echo
service/hoge-service    ClusterIP   10.96.24.225   <none>        80/TCP    72s     component=hoge-echo
service/kubernetes      ClusterIP   10.96.0.1      <none>        443/TCP   4m58s   <none>
service/nginx-service   ClusterIP   10.96.128.45   <none>        80/TCP    72s     component=nginx

NAME                                          CLASS   HOSTS   ADDRESS   PORTS   AGE
ingress.networking.k8s.io/hoge-fuga-ingress   nginx   *                 80      41s

Ingressは作成するのみでは利用できず、IngressControllerが必要となります。
今回はNGINX IngressControllerを利用します。
kindのドキュメントで紹介されている手順で導入します。

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
...
$ kubectl wait --namespace ingress-nginx \
  --for=condition=ready pod \
  --selector=app.kubernetes.io/component=controller \
  --timeout=90s
pod/ingress-nginx-controller-86b6d5756c-s2sn4 condition met
$ kubectl get pods -o wide -n ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE    IP            NODE                 NOMINATED NODE   READINESS GATES
ingress-nginx-admission-create-jjqjf        0/1     Completed   0          2m6s   10.244.0.15   kind-control-plane   <none>           <none>
ingress-nginx-admission-patch-9wzgg         0/1     Completed   0          2m6s   10.244.0.14   kind-control-plane   <none>           <none>
ingress-nginx-controller-86b6d5756c-s2sn4   1/1     Running     0          2m6s   10.244.0.16   kind-control-plane   <none>           <none>

ingress-nginx-controllerがRunningとなっていれば、正常に稼働しています。
全て正常に動いていることが確認できたら、自端末からcurlもしくはブラウザでlocalhostlocalhost/hogelocalhost/fugaにアクセスしてみましょう。

$ curl -i localhost
...
<h1>Welcome to nginx!</h1>
...

$ curl -i localhost/hoge
...
hoge

$ curl -i localhost/fuga
...
fuga

URLのパスによって、異なるアプリケーションが呼ばれていることが確認できました。

ここまでやると何となくですが、k8sの雰囲気が掴めたかなと思います。
アカウントや認証周りについてはまだまだ勉強中なので、今回は割愛します。

一旦、k8sクラスタをお掃除します。

$ kind delete cluster

ArgoWorkflowsの導入

ArgoWorkflowsの導入です。
ArgoWorkflowsのクイックスタートを参照すると、ポートフォワードでの手順となっています。
せっかくIngressが使えるようになったので、今回はIngress経由でArgoWorkflowsを覗けるようにしてみましょう。

まずは、k8sクラスターの構築です。
Ingressを利用するので前項のymlを利用します。

$ kind create cluster --config cluster.yml
Creating cluster "kind" ...
Set kubectl context to "kind-kind"

k8sクラスタが構築できたので、ArgoWorkflowsを導入します。
まずは、ArgoWorkflows用にNamespaceを作成します。
Namespaceは、k8sクラスターリソースを分割する方法であり、プロジェクト毎にパーティションを切るようなイメージです。

$ kubectl create namespace argo

$ kubectl get namespace
NAME                 STATUS   AGE
argo                 Active   150m
default              Active   178m
ingress-nginx        Active   147m
kube-node-lease      Active   179m
kube-public          Active   179m
kube-system          Active   179m
local-path-storage   Active   178m

Namepspaceを明示しなかった場合は、基本的にdefaultが利用されます。

ArgoWorkflowsのインストールですが、k8sのControllerとして動かしたいので、リリースノート(v3.3.8)から以下コマンドでインストールします。

$ kubectl apply -n argo -f https://github.com/argoproj/argo-workflows/releases/download/v3.3.8/install.yaml

ArgoWorkflowsのIngressを、ymlで定義してみましょう。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argo-server-ingress
  namespace: argo
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: argo-server
            port:
              number: 2746

公式ドキュメントを参照すると色々書いてありますが、今回は簡単な定義にしています。
Ingressを適用しましょう。

$ kubectl apply -f argo-ingress.yml
ingress.networking.k8s.io/argo-server-ingress created

Ingressを定義しただけではまだ利用できないので、前項でも利用したNGINX IngressControllerを導入します。

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
...
$ kubectl wait --namespace ingress-nginx \
  --for=condition=ready pod \
  --selector=app.kubernetes.io/component=controller \
  --timeout=90s
pod/ingress-nginx-controller-86b6d5756c-s2sn4 condition met

ArgoWorkflowsの導入はできたのですが、ArgoWorkflowsはHTTPSで待ち受ける設定となっています。
今回はIngress配下にArgoWorkflowsを構築しているので、HTTPで待ち受ける設定に変更します。

$ kubectl edit deployment/argo-server --namespace=argo
# 1. vim(デフォルトエディタ)が起動されるので、
#    template.spec.containers.argsに2項目(--secure, --auth-mode)を追加
    spec:
      containers:
      - args:
        - server
        - --secure=false # HTTPでの通信に変更
        - --auth-mode=server # ArgoWorkflowsを動かしたいだけなので認証なしモード

# 2. HTTPSと定義されている部分をHTTPで一括置換(vim)
:%s/HTTPS/HTTP/g
# 3. 保存
:wq

deployment.apps/argo-server edited

変更を保存すると変更内容が反映されます。
それではブラウザでアクセスしてみましょう。

open http://localhost

ArgoWorkflowsの画面が表示されれば成功です。
試しにワークフローを動かしてみましょう。
まずは、WorkflowTemplateの作成です。
左メニューのWorkflow Template -> CREATE NEW WORKFLOW TEMPLATE -> CREATE これでテンプレのワークフローが作成されます。
作成されたワークフローのSUBMITを押下し、パラメータ設定画面のSUBMITを押下します。
ワークフロー実行画面に遷移し、少し待つと成功します。

まとめ

以上、kindを使ってk8sの雰囲気を掴みながら、ArgoWorkflowsの構築までできました。
k8s初心者からほんの少しわかるくらいにはなれたのではないでしょうか。
本記事がk8s理解の一助となれたら幸いです。

最後までお読みいただきありがとうございました。


◆TECH PLAY
techplay.jp

◆connpass
rakus.connpass.com

Copyright © RAKUS Co., Ltd. All rights reserved.