kubernetes
argo-workflow
misankim
2023. 3. 10. 00:44
argo-workflow
argo 프로젝트의 workflow 관리 도구
# argo workflow 배포
퀵스타트
최신 릴리즈 및 배포 커맨드
-> 릴리즈마다 매니페스트 경로가 다르니 릴리즈 페이지에서 배포 커맨드 확인
kubectl create namespace argo
kubectl apply -n argo -f https://github.com/argoproj/argo-workflows/releases/download/v3.3.10/install.yaml
# 인증 우회를 위해 인증 모드를 server 로 수정
kubectl patch deployment \
argo-server \
--namespace argo \
--type='json' \
-p='[{"op": "replace", "path": "/spec/template/spec/containers/0/args", "value": [
"server",
"--auth-mode=server"
]}]'
# 특정 네임스페이스 범위로 argo workflow 배포
# argo cli 설치
-> 릴리즈마다 매니페스트 경로가 다르니 릴리즈 페이지에서 배포 커맨드 확인
curl -sLO https://github.com/argoproj/argo-workflows/releases/download/v3.3.10/argo-darwin-amd64.gz
gunzip argo-darwin-amd64.gz
chmod +x argo-darwin-amd64
mv sudo ./argo-darwin-amd64 /usr/local/bin/argo
argo version
# 접속
kubectl -n argo port-forward deployment/argo-server 2746:2746
https://localhost:2746/
# 샘플 워크플로우 생성
argo submit -n argo --watch https://raw.githubusercontent.com/argoproj/argo-workflows/master/examples/hello-world.yaml
워크플로우 리스트 확인
argo list -n argo
가장 최근 실행된 워크플로우 확인
argo get -n argo @latest
가장 최근 실행된 워크플로우 로그 확인
argo logs -n argo @latest
# argo workflow 인증
## 토큰 인증
kubectl create sa jenkins
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: jenkins.service-account-token
annotations:
kubernetes.io/service-account.name: jenkins
type: kubernetes.io/service-account-token
EOF
ARGO_TOKEN="Bearer $(kubectl get secret jenkins.service-account-token -o=jsonpath='{.data.token}' | base64 --decode)"
echo $ARGO_TOKEN
## 권한 부여
-> argo workflow 배포 시 함께 배포되는 ClusterRole(argo-aggregate-to-admin, argo-aggregate-to-edit, argo-aggregate-to-view) 이 있기 때문에 ClusterRoleBinding 혹은 RoleBinding 만 생성해주면 됨
### 클러스터 레벨 권한 부여
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: argo-binding-jenkins
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: argo-aggregate-to-view
subjects:
- kind: ServiceAccount
name: jenkins
namespace: argo
EOF
### 네임스페이스 레벨 권한 부여
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: argo-binding-jenkins
namespace: argo
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: argo-aggregate-to-view
subjects:
- kind: ServiceAccount
name: jenkins
namespace: argo
EOF
## sso 설정
-> argocd 와 동일하게 sso 인증을 제공함
workflow-controller-configmap 샘플
### google oauth2 사용자 인증 정보 설정
유형 - 웹 애플리케이션
승인된 자바스크립트 원본 - https://localhost:2746
승인된 리디렉션 URI - https://localhost:2746/oauth2/callback
### configmap 수정
kubectl edit cm workflow-controller-configmap
data:
sso: |
issuer: https://accounts.google.com
sessionExpiry: 240h
clientId:
name: google-oauth2
key: client-id-key
clientSecret:
name: google-oauth2
key: client-secret-key
redirectUrl: https://localhost:2746/oauth2/callback
scopes:
- email
rbac:
enabled: true
insecureSkipVerify: true
### google oauth2 인증을 위한 클라이언트 아이디/시크릿 생성
echo -n '0000000000000-cifctdaeua2z1a8bf4udrc8hkediadzn.apps.googleusercontent.com' > client-id-key
echo -n '0000000000000s3TNdn0zEdYvIf-PfWjq7z' > client-secret-key
kubectl create secret -n argo generic google-oauth2 \
--from-file=./client-id-key \
--from-file=./client-secret-key
### argo-server 인증 방식을 sso 로 변경
kubectl patch deployment \
argo-server \
--namespace argo \
--type='json' \
-p='[{"op": "replace", "path": "/spec/template/spec/containers/0/args", "value": [
"server",
"--auth-mode=sso"
]}]'
configmap 수정하여 재적용 시
kubectl rollout restart deploy argo-server
(참고) sso 로그인 시 보여지는 항목
Issuer: argo-server
Subject: 126442351131619240018
Groups: -
Email: my-email@gmail.com
Email Verified:
Service Account: -
### 클러스터 레벨의 rbac 기본값 설정
-> rbac 의 경우 rbac-rule-precedence 값을 통해 우선 순위를 설정 가능하며, rbac-rule-precedence 값이 높을 수록 우선 순위가 높고, 0의 경우 적용되는 것이 하나도 없는 경우에 적용되는 기본 값
vim argo-sso-default.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: default-user
namespace: argo
annotations:
workflows.argoproj.io/rbac-rule: "true"
workflows.argoproj.io/rbac-rule-precedence: "0"
secrets:
- name: default-user.service-account-token
---
apiVersion: v1
kind: Secret
metadata:
name: default-user.service-account-token
namespace: argo
annotations:
kubernetes.io/service-account.name: default-user
type: kubernetes.io/service-account-token
기본 권한을 읽기 전용으로 주고 싶다면
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: argo-binding-default-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: argo-aggregate-to-view
subjects:
- kind: ServiceAccount
name: default-user
namespace: argo
### 클러스터 레벨 rbac 을 위한 설정
-> 특정 사용자에게 클러스터 전체 어드민 권한 부여
vim argo-sso-cluster.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: argo
annotations:
workflows.argoproj.io/rbac-rule: "email in ['my-email@gmail.com']"
workflows.argoproj.io/rbac-rule-precedence: "1"
secrets:
- name: admin-user.service-account-token
---
apiVersion: v1
kind: Secret
metadata:
name: admin-user.service-account-token
namespace: argo
annotations:
kubernetes.io/service-account.name: admin-user
type: kubernetes.io/service-account-token
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: argo-binding-admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: argo-aggregate-to-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: argo
### 네임스페이스 레벨 rbac 을 위한 설정
-> 네임스페이스 레벨로 rbac 적용을 위해서는 argo-server deployment 에 SSO_DELEGATE_RBAC_TO_NAMESPACE=true 환경변수 추가 필요
kubectl edit deploy argo-server
spec:
...
template:
labels:
app: argo-server
spec:
containers:
- args:
- server
- --auth-mode=sso
env:
- name: SSO_DELEGATE_RBAC_TO_NAMESPACE
value: "true"
image: quay.io/argoproj/argocli:v3.3.10
imagePullPolicy: IfNotPresent
name: argo-server
...
네임스페이스 레벨의 admin 권한을 부여할 네임스페이스가 default 인 경우 아래처럼 작성
vim argo-sso-ns.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: ns-admin-user
namespace: default
annotations:
workflows.argoproj.io/rbac-rule: "email in ['my-email@gmail.com']"
workflows.argoproj.io/rbac-rule-precedence: "1001"
secrets:
- name: ns-admin-user.service-account-token
---
apiVersion: v1
kind: Secret
metadata:
name: ns-admin-user.service-account-token
namespace: default
annotations:
kubernetes.io/service-account.name: ns-admin-user
type: kubernetes.io/service-account-token
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: argo-binding-ns-admin-user
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: argo-aggregate-to-admin
subjects:
- kind: ServiceAccount
name: ns-admin-user
namespace: default
## argocd dex 인증
-> arogcd 의 인증 서버인 dex 를 인증 수단으로 사용(okta 인증 등에 사용된다고 함)
# workflow pod 보안
-> 일반 사용자로 실행되도록 설정
-> 실행되는 스크립트 내용에 따라 에러가 발생할 수 있음
...
workflowSpec:
entrypoint: curl
securityContext:
runAsNonRoot: true
runAsUser: 1000
...
# k8s cronjob 을 cronworkflow 로 마이그레이션
-> 파드가 사라져도 workflow 는 남아있기 때문에 실행된 크론의 성공/실패 여부를 확인하기 용이함
-> 웹 ui 를 통해 배치성 작업을 관리할 수 있어 편리함
-> 파드는 로그를 확인하는 역할만 있기 때문에 클러스터에 컨테이너의 로그를 전송하는 로깅 설정(gcp logging 등)이 되어 있다면 남길 필요는 없음
workflow 정의에 사용되는 필드 참조
## cronjob 및 cronworkflow 에 사용되는 configmap 매니페스트
vim configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-curl
data:
check.sh: |
#!/bin/sh
apk update && apk add curl
echo '####################################'
echo 'url check'
echo '####################################'
for url in `cat /tmp/list.txt`
do echo $url
curl -s -o /dev/null -w "%{http_code}" $url
echo
echo
done
exit 0
list.txt: |
https://www.google.com/
https://google.com/
https://www.naver.com/
https://www.daum.net/
## 기존 cronjob 매니페스트
vim cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: curl
spec:
schedule: "* * * * *"
successfulJobsHistoryLimit: 5
failedJobsHistoryLimit: 5
jobTemplate:
spec:
template:
metadata:
annotations:
proxy.istio.io/config: |
holdApplicationUntilProxyStarts: true
spec:
containers:
- name: curl
image: alpine:latest
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- /check.sh
volumeMounts:
- name: curl
mountPath: /check.sh
subPath: check.sh
- name: curl
mountPath: /tmp/list.txt
subPath: list.txt
volumes:
- name: curl
configMap:
name: cm-curl
restartPolicy: Never
## cronworkflow 매니페스트
vim cronworkflow.yaml
apiVersion: argoproj.io/v1alpha1
kind: CronWorkflow
metadata:
name: curl
spec:
schedule: '* * * * *'
successfulJobsHistoryLimit: 30 # wf not pod
failedJobsHistoryLimit: 30 # wf not pod
workflowMetadata:
annotations:
proxy.istio.io/config: |
holdApplicationUntilProxyStarts: true
workflowSpec:
entrypoint: curl
ttlStrategy: # time to delete wf
secondsAfterSuccess: 3600
secondsAfterFailure: 3600
podGC: # pod delete policy
strategy: OnPodCompletion # success or fail
# strategy: OnPodSuccess # only success
templates:
- name: curl
retryStrategy:
limit: "2" # try total 3 times
metadata: {}
inputs: {}
outputs: {}
container:
name: main
image: alpine:latest
command:
- /bin/sh
- /check.sh
resources: {}
volumeMounts:
- name: curl
mountPath: /check.sh
subPath: check.sh
- name: curl
mountPath: /tmp/list.txt
subPath: list.txt
volumes:
- name: curl
configMap:
name: cm-curl
## cronworkflow 배포
-> cwf, wf 모두 네임스페이스 레벨의 리소스
-> cwf 를 삭제하면 wf, pod 도 함께 삭제됨
kubectl apply -f configmap.yaml
kubectl apply -f cronworkflow.yaml
kubectl get cwf
kubectl get wf