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
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를 의미합니다.
테스트한 기능
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와 그것들을 확인해 나간 과정에 대해 정리해보겠습니다.