이번엔 Kubernetes 위에 Jenkins를 설치해보자.
가장 먼저 아래와 같이 Manifest 파일을 작성한다.
[jenkins-master.yaml]
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: jenkins
spec:
serviceName: jenkins
replicas: 1
selector:
matchLabels:
app: jenkins
template:
metadata:
labels:
app: jenkins
spec:
serviceAccountName: jenkins
containers:
- name: jenkins
image: jenkins/jenkins:lts
ports:
- name: http-port
containerPort: 8080
- name: jnlp-port
containerPort: 50000
volumeMounts:
- name: jenkins-vol
mountPath: /var/jenkins_home
volumes:
- name: jenkins-vol
hostPath:
path: /jenkins-data
type: Directory
---
apiVersion: v1
kind: Service
metadata:
name: jenkins
spec:
type: NodePort
ports:
- port: 8080
targetPort: 8080
selector:
app: jenkins
---
apiVersion: v1
kind: Service
metadata:
name: jenkins-jnlp
spec:
type: ClusterIP
ports:
- port: 50000
targetPort: 50000
selector:
app: jenkins
[jenkins-rbac.yaml]
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: jenkins
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get","list","watch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
- apiGroups: [""]
resources: ["events"]
verbs: ["get", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: jenkins
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: jenkins
subjects:
- kind: ServiceAccount
name: jenkins
테스트 환경이므로 Jenkins Volume을 hostPath로 설정하였다. 위 Pod이 생성될 Node의 '/jenkins-data' 디렉토리에 'chmod 0777' 명령어를 수행해야 정상적으로 진행할 수 있다. 실제 운영 환경에선 반드시 Persistent Volume(EBS, GlusterFS 등)을 통해 설정 및 빌드 이력 등을 잃어버리는 불상사를 피해야 한다. 그 외에 Health Check 등의 Probe 설정 등의 부가적인 요소들이 필요하다.
서비스를 통해 외부에서 NodePort로 웹에 접근할 수 있으며, Remote Agent는 50000번 포트로 연결할 수 있다. 그리고 k8s 클러스터에서 빌드를 위한 Remote Agent용 Pod을 제공하기 때문에 해당 리소스 관련 동작에 대한 권한이 필요하다.
이번엔 Jenkins를 배포할 네임스페이스를 생성한다.
kubectl create namespace ci
이제 다음 명령어로 Jenkins를 배포해보자.
kubectl apply -n ci -f jenkins-deployment.yaml
아래와 같이 리소스가 생성된다.
NodePort가 30771번에 할당되었으니, Jenkins 웹은 해당 포트를 통해 접근할 수 있다.
최초 접속시 Admin 비밀번호를 요구한다. Container 파일시스템에서 해당 정보를 가져와야 하므로 아래 명령어를 사용하자.
kubectl exec -it -n ci jenkins-0 -- cat /var/jenkins_home/secrets/initialAdminPassword
다음은 권장 플러그인 설치 여부를 묻는 메뉴다.
'Install suggeted plugins'를 선택하면 Jenkins가 알아서 Git, Pipeline, Mailer 등의 중요 플러그인들을 자동으로 설치해준다. 네트워크 사정에 따라 보통 5~10분 정도 소요된다.
플러그인 설치를 완료하면 이번엔 첫 관리자 계정을 추가하는 메뉴다. 원하는 계정 정보를 입력하여 생성을 완료하자.
Jenkins URL을 설정하는 후 확인을 누르면 기다리던 Jenkins 메인 화면이 나온다.
다음은 'Jenkins 관리' > '플러그인 관리' 항목으로 이동 후 설치 가능 탭에서 'Kubernetes', 'Docker Pipeline' 플러그인을 검색하여 설치한다.
모든 플러그인 설치가 완료되었으면, 현재 k8s 클러스터와 Jenkins를 연결하기 위한 설정이 필요하다.
'Jenkins 관리' > '시스템 설정' > Cloud 항목에서 아래 링크를 눌러서 Cloud 설정 메뉴로 이동하자.
'Add a new cloud' 버튼을 클릭하여 아래와 같이 Jenkins가 배포된 클러스터의 정보를 입력한다.
-
Name: 해당 클러스터를 구분할 수 있는 이름
-
Kubernetes URL: Jenkins가 k8s 내부에서 실행중이므로, API서버의 In-cluster URL을 입력
-
Kubernetes Namespace: Remote Agent 관련 리소스가 생성될 Namespace를 의미한다. RBAC 설정시 'ci' Namespace에만 유효하도록 정의하였으므로 ci를 입력
-
Jenkins URL: In-cluster의 Jenkins URL로 HTTP 관련 Service 이름과 Port를 명시
-
Jenkins tunnel: Remote Agent가 접근할 주소, jnlp 관련 Service 이름과 Port를 입력
나머지 항목은 입력하지 않고 비워두거나 기본값으로 설정한다. 이미 Service Accout가 Jenkins Pod에 추가된 상태이므로 k8s API 사용에 필요한 권한은 충분히 부여된 상태이다. 'Test Connection' 버튼을 눌러서 k8s 연결에 문제가 없는지 확인 후 Save 버튼을 눌러서 위 설정을 적용하자. 이제 가장 기본적인 Jenkins - K8s 연계는 완료한 셈이다.
다음 페이지는 Github의 Source Code를 Checkout하고 이를 Docker Image로 빌드한 뒤, Docker Hub에 Push를 자동화하는 방법에 대해서 설명할 예정이다.
'CI-CD' 카테고리의 다른 글
Jenkins Pipeline (0) | 2021.03.01 |
---|---|
kustomize를 활용한 Manifest 관리 (0) | 2021.02.24 |
CD를 위한 Jenkins, Argo CD 연계 (0) | 2021.02.21 |
CI를 위한 Jenkins, GitHub, Docker Hub 연계 (0) | 2021.02.20 |
ArgoCD: Kubernetes에 GitOps 적용하기 (2) | 2021.02.17 |