Argo Events Getting Start

Argo Event와 Argo Workflow 사용해보고, 몇가지 예제를 실행해봅니다.

Introduction

Kubernetes에서는 Batch성격의 Application들을 지원하고 있습니다.
Job, CronJob이라는 형태로 실행할 수 있습니다.
하지만 실행이력을 관리하거나, 여러 job들의 의존성을 설정하여 실행하기에는 기능이 부족합니다.
Argo Workflow와 Argo Event가 이러한 기능들을 충분히 지원하는지 확인하기 위해, 설치하여 테스트를 진행해보았습니다.

Install

Argo-Event

추후 사용을 고려해서, namespace단위 설치가 아닌 cluster-wide로 설치합니다.

namespace 생성

1
kubectl create namespace argo-events

Deploy Argo Events, SA, ClusterRoles, Sensor Controller, EventBus Controller and EventSource Controller.

1
2
3
kubectl apply -f https://raw.githubusercontent.com/argoproj/argo-events/stable/manifests/install.yaml
# Install with a validating admission controller
kubectl apply -f https://raw.githubusercontent.com/argoproj/argo-events/stable/manifests/install-validating-webhook.yaml

Deploy Eventbus

1
kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/stable/examples/eventbus/native.yaml

Argo-workflow

Controller And Server

1
2
kubectl create namespace argo
kubectl apply -n argo -f https://github.com/argoproj/argo-workflows/releases/download/v3.3.0/install.yaml

getting-started를 보고 설치를 진행하게되면, namespace에 한정되어 설치됩니다.
이는 argo-event 사용 불편을 초래하기에, 특별한 이유가 없다면 cluster-wide로 설치하는것을 추천합니다.

Install CLI

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Download the binary
curl -sLO https://github.com/argoproj/argo-workflows/releases/download/v3.3.0/argo-darwin-amd64.gz

# Unzip
gunzip argo-darwin-amd64.gz

# Make binary executable
chmod +x argo-darwin-amd64

# Move binary to path
mv ./argo-darwin-amd64 /usr/local/bin/argo

# Test installation
argo version

Port-Forwarding (local)

1
kubectl -n argo port-forward deployment/argo-server 2746:2746

Remote Cluster를 사용할경우 링크를 보고 Routing 설정을 해주면 됩니다.
Local에서는 Load Balancer타입으로 진행하면 됩니다.

Authorization

링크 방법을 응용해서 기존에 만들어진 token을 획득후, 로그인에 사용하면 됩니다.

Concept

Architecture

architecture

Event Source

외부에서 오는 이벤트를 처리하기위한 Resource입니다.

Sensor

센서는 Event Dependency Set을 Input으로, Trigger는 Output 정의합니다.
EventBus를 통해서 Event를 수신하여 처리하는 Event Dependency Manager로서 행동합니다. 그리고 Trigger를 실행합니다.

Eventbus

EventSources와 Sensor를 연결해주는 TransportLayer로서 수행합니다.
EventSources가 Event를 Publish하는반면, Sensor는 Event를 Subscribe하여 Trigger를 실행합니다.

Trigger

Sensor에 의해서 한번 Event Dependencies가 해결되면, 실행되는 Resource/Workload를 의미합니다.

테스트한 기능

  • calendar
  • webhook-workflow
  • webhook-k8s-object
  • cross-namespace
  • webhook-auth

RBAC 설정

argo-workflow와 argo-events를 사용한다는 전제하에 설명합니다.
argo-workflow에서 실행한 pod 상태, 로그를 확인하기 위해서 권한을 주어야합니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: workflow-role
  namespace: argo-events
rules:
  - apiGroups:
      - ""
    resources:
      - pods
    verbs:
      - get
      - watch
      - patch
  - apiGroups:
      - ""
    resources:
      - pods/log
    verbs:
      - get
      - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: workflow-role-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: workflow-role
subjects:
  - kind: ServiceAccount
    name: default

Argo Events에서 Trigger로서 Argo-Workflow를 사용하고자 한다면 필요한 설정입니다.
Trigger로 생성되는 객체가 Workflow이기 때문에, 해당 타입의 api-resource를 사용할수 있도록 권한이 필요합니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
apiVersion: v1
kind: ServiceAccount
metadata:
  name: operate-workflow-sa
  namespace: argo-events
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: operate-workflow-role
  namespace: argo-events
rules:
  - apiGroups:
      - argoproj.io
    verbs:
      - "*"
    resources:
      - workflows
      - workflowtemplates
      - cronworkflows
      - clusterworkflowtemplates
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: operate-workflow-role-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: operate-workflow-role
subjects:
  - kind: ServiceAccount
    name: operate-workflow-sa

webhook-workflow

Webhook을 EventSource로 사용하며, Sensor는 argo-workflow를 Trigger로 사용합니다.
이에 따라, 동작을 시키기 위해서는 argo-workflow cluster wide로 사전 설치를 해야합니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
apiVersion: argoproj.io/v1alpha1
kind: EventSource
metadata:
  name: webhook
spec:
  service:
    ports:
      - port: 12000
        targetPort: 12000
  webhook:
    example:
      port: "12000"
      endpoint: /example
      method: POST
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
apiVersion: argoproj.io/v1alpha1
kind: Sensor
metadata:
  name: webhook
spec:
  template:
    serviceAccountName: operate-workflow-sa
  dependencies:
    - name: test-dep
      eventSourceName: webhook
      eventName: example
  triggers:
    - template:
        name: webhook-workflow-trigger
        k8s:
          operation: create
          source:
            resource:
              apiVersion: argoproj.io/v1alpha1
              kind: Workflow
              metadata:
                generateName: webhook-
              spec:
                entrypoint: whalesay
                arguments:
                  parameters:
                  - name: message
                    value: hello world
                templates:
                - name: whalesay
                  inputs:
                    parameters:
                    - name: message
                  container:
                    image: docker/whalesay:latest
                    command: [cowsay]
                    args: ["{{inputs.parameters.message}}"]
          parameters:
            - src:
                dependencyName: test-dep
                dataKey: body
              dest: spec.arguments.parameters.0.value

calendar

Timer, CronJob을 모두 구동시킬수 있는 형태의 EventSource입니다.

1
2
3
4
5
6
7
8
9
apiVersion: argoproj.io/v1alpha1
kind: EventSource
metadata:
  name: calendar
spec:
  calendar:
    example-with-interval:
      interval: 10s
#     schedule: "30 * * * *"
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
apiVersion: argoproj.io/v1alpha1
kind: Sensor
metadata:
  name: calendar
spec:
  template:
    serviceAccountName: operate-workflow-sa
  dependencies:
    - name: test-dep
      eventSourceName: calendar
      eventName: example-with-interval
  triggers:
    - template:
        name: calendar-workflow-trigger
        k8s:
          operation: create
          source:
            resource:
              apiVersion: argoproj.io/v1alpha1
              kind: Workflow
              metadata:
                generateName: calendar-workflow-
              spec:
                entrypoint: whalesay
                arguments:
                  parameters:
                  - name: message
                    value: hello world
                templates:
                - name: whalesay
                  inputs:
                    parameters:
                    - name: message
                  container:
                    image: docker/whalesay:latest
                    command: [cowsay]
                    args: ["{{inputs.parameters.message}}"]
          parameters:
            - src:
                dependencyName: test-dep
                dataKey: eventTime
              dest: spec.arguments.parameters.0.value
      retryStrategy:
        steps: 3

webhook-k8s-object

Webhook-Workflow와 유사합니다. 다른점은 Sensor에서 Trigger하는 대상이 k8s object 라는 점입니다.
Pod, Deployment, Job, CronJob와 같은 Custom Resources를 실행할 수 있습니다.
가능한 동작은 Create, Update, Patch, Delete입니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
apiVersion: argoproj.io/v1alpha1
kind: EventSource
metadata:
  name: k8s-webhook
spec:
  service:
    ports:
      - port: 12000
        targetPort: 12000
  webhook:
    example:
      port: "12000"
      endpoint: /example
      method: POST
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
apiVersion: argoproj.io/v1alpha1
kind: Sensor
metadata:
  name: k8s-webhook
spec:
  template:
    serviceAccountName: operate-k8s-sa
  dependencies:
    - name: test-dep
      eventSourceName: k8s-webhook
      eventName: example
  triggers:
    - template:
        name: webhook-pod-trigger
        k8s:
          operation: create
          source:
            resource:
              apiVersion: v1
              kind: Pod
              metadata:
                generateName: hello-world-
              spec:
                containers:
                  - name: hello-container
                    args:
                      - "hello-world"
                    command:
                      - cowsay
                    image: "docker/whalesay:latest"
          parameters:
            - src:
                dependencyName: test-dep
                dataKey: body
              dest: spec.containers.0.args.0

Kubernetes Object를 배포하기 위해서는 추가적인 RBAC가 필요합니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
apiVersion: v1
kind: ServiceAccount
metadata:
  name: operate-k8s-sa
  namespace: argo-events
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: operate-k8s-role
  namespace: argo-events
rules:
  - apiGroups:
      - ""
    verbs:
      - "*"
    resources:
      - pods
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: operate-k8s-role-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: operate-k8s-role
subjects:
  - kind: ServiceAccount
    name: operate-k8s-sa

cross-namespace

지금까지 사용한 RBAC는 namespace 한정해서 사용가능합니다. 하지만 이는 사용자들이 모두 사용법을 알아야 하는 단점이 있어, 사용자로서는 불편할 수 밖에 없습니다.
Cross-Namespace로 사용하기 위해서는 기존에 Role로 정의되어있던 내용들을 모두 ClusteRole으로 변경해야 합니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
apiVersion: v1
kind: ServiceAccount
metadata:
  name: operate-k8s-cluster-sa
  namespace: argo-events
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: operate-k8s-clusterrole
  namespace: argo-events
rules:
  - apiGroups:
      - ""
    verbs:
      - "*"
    resources:
      - pods
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: operate-k8s-clusterrole-binding
  namespace: argo-events
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: operate-k8s-clusterrole
subjects:
  - kind: ServiceAccount
    name: operate-k8s-cluster-sa
    namespace: argo-events

예제로 첨부한 ClusterRole은 pod만 생성가능한데, 필요할 경우 다른 Resource를 추가한뒤 사용하면 됩니다.

webhook-auth

보안상의 문제로 Webhook을 호출하기 위해서 인증 토큰을 추가해야할 수 있습니다.
이 방법은 인증용 토큰을 생성한뒤, k8s object인 Secret으로 등록 후 사용하는 것입니다.
Secret 객체 이름을 지정해주면 Webhook에서 인증용도로 사용할 수 있습니다.

1
2
3
echo -n 'af3qqs321f2ddwf1e2e67dfda3fs' > ./token.txt

kubectl create secret generic my-webhook-token --from-file=my-token=./token.txt
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
apiVersion: argoproj.io/v1alpha1
kind: EventSource
metadata:
  name: secret-webhook
spec:
  webhook:
    example:
      port: "12000"
      endpoint: /example
      method: POST
      authSecret:
        name: my-webhook-token
        key: my-token
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
apiVersion: argoproj.io/v1alpha1
kind: Sensor
metadata:
  name: k8s-webhook
spec:
  template:
    serviceAccountName: operate-k8s-sa
  dependencies:
    - name: test-dep
      eventSourceName: secret-webhook
      eventName: example
  triggers:
    - template:
        name: webhook-pod-trigger
        k8s:
          operation: create
          source:
            resource:
              apiVersion: v1
              kind: Pod
              metadata:
                generateName: hello-world-
              spec:
                containers:
                  - name: hello-container
                    args:
                      - "hello-world"
                    command:
                      - cowsay
                    image: "docker/whalesay:latest"
          parameters:
            - src:
                dependencyName: test-dep
                dataKey: body
              dest: spec.containers.0.args.0

Summary

테스트 한 내용들을 보시면, 운영적인 요소보다는 기능적인 요소로서 지원여부를 위주로 확인하였습니다.
Batch를 사용하기위해 필요한 Resource들이 모두 yaml로 정의가 가능하기 때문에, GitOps로 운영이 가능했습니다.
그리고 Argo Event에서 다양한 Event Source를 지원하기 때문에, Webhook과 Cron을 필요한 만큼 충분히 사용가능 한 것을 확인하였습니다.
다음 글에서는 운영적인 요소에서 필요한 Needs와 그것들을 확인해 나간 과정에 대해 정리해보겠습니다.

Hugo로 만듦
JimmyStack 테마 사용 중