
Jenkins는 오픈소스 자동화 서버로,
주로 지속적인 통합(CI: Continuous Integration) 및 지속적인 배포(CD: Continuous Delivery/Deployment) 파이프라인을 구현하는 데 사용된다.
지속적 통합 및 배포(CI/CD)를 자동화하는 오픈소스 도구이다.
코드 변경사항을 자동으로 빌드, 테스트하고 배포 파이프라인을 구축하여 개발 프로세스를 효율화한다.
간단하게 Kubernetes 위에 Jenkins를 배포하고 사용하는 방법을 정리해보았다.
추가로, keycloak OpenID Connect 연동도 함께 정리하였다.
Helm을 사용해 배포하므로, values.yaml을 작성한다.
controller:
serviceType: ClusterIP
servicePort: 80
targetPort: 8080
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
admin:
# 직접 비밀번호 설정 대신 Secret 참조
existingSecret: "jenkins-admin-secret"
userKey: "username"
passwordKey: "password"
image:
registry: "docker.io"
repository: "jenkins/jenkins"
tag: "2.492.2-jdk17"
pullPolicy: "Always"
installPlugins:
- eddsa-api:0.3.0.1-19.vc432d923e5ee
- trilead-api:2.209.v0e69b_c43c245
- mina-sshd-api-common:2.14.0-143.v2b_362fc39576
- mina-sshd-api-core:2.14.0-143.v2b_362fc39576
- jsch:0.2.16-95.v3eecb_55fa_b_78
- git-client:6.1.3
- ssh-credentials:355.v9b_e5b_cde5003
- kubernetes:4324.vfec199a_33512
- git:5.7.0
- configuration-as-code:1932.v75cb_b_f1b_698d
- cloudbees-folder:6.1012.v79a_86a_1ea_c1f
- matrix-auth:3.2.4
- role-strategy:756.v978cb_392eb_d3
- workflow-aggregator:600.vb_57cdd26fdd7
- keycloak:2.3.2
- blueocean:1.27.19
- docker-workflow:611.v16e84da_6d3ff
- docker-plugin:1.10.0
- pipeline-model-definition:2.2254.v2a_978de46f35
- generic-webhook-trigger:2.3.1
- maven-plugin:3.25
- gradle:2.14.1
- nodejs:1.6.4
- sonar:2.18
- ssh-agent:384.ve275343791a_6
- simple-theme-plugin:202.v6367d3dea_73b_
- login-theme:262.vb_4ce39d5279f
- prometheus:819.v50953a_c560dd
numExecutors: 30
JCasC:
enabled: true
configScripts:
jenkins: |
jenkins:
securityRealm:
local:
allowsSignup: false
users:
- id: "${ADMIN_USER}"
password: "${ADMIN_PASSWORD}"
authorizationStrategy:
projectMatrix:
permissions:
- "Overall/Administer:${ADMIN_USER}"
containerEnv:
- name: CASC_JENKINS_CONFIG
value: "/var/jenkins_config"
- name: ADMIN_USER
valueFrom:
secretKeyRef:
name: jenkins-admin-secret
key: username
- name: ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: jenkins-admin-secret
key: password
javaOpts: >-
-Xmx6g
-Xms4g
-XX:+UseG1GC
-XX:+ExplicitGCInvokesConcurrent
-XX:+ParallelRefProcEnabled
-Dhudson.model.DirectoryBrowserSupport.CSP=
-Djenkins.install.runSetupWizard=false
-Dcasc.jenkins.config.apply=once
-Dio.jenkins.plugins.casc.ConfigurationAsCode.initialDelay=300000
-Dcasc.jenkins.reload.token=false
resources:
requests:
cpu: "2000m"
memory: "4Gi"
limits:
cpu: "8000m"
memory: "16Gi"
probes:
startupProbe:
failureThreshold: 12
periodSeconds: 10
initialDelaySeconds: 60
livenessProbe:
failureThreshold: 5
periodSeconds: 10
initialDelaySeconds: 60
readinessProbe:
failureThreshold: 3
periodSeconds: 10
initialDelaySeconds: 60
persistence:
enabled: true
storageClass: "longhorn"
size: 100Gi
accessMode: ReadWriteMany
annotations:
"helm.sh/resource-policy": keep
serviceAccount:
create: true
rbac:
create: true
Admin계정에 사용할 ID, Password를 포함한 Secret을 설정한다.
kubectl create secret generic jenkins-admin-secret \
--from-literal=username=admin \
--from-literal=password='Secret' \
-n jenkins
apiVersion: v1
data:
password: base64Secret
username: base64admin
kind: Secret
metadata:
creationTimestamp: null
name: jenkins-admin-secret
namespace: jenkins
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: jenkins-ingress
namespace: jenkins
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
nginx.ingress.kubernetes.io/proxy-connect-timeout: "30"
nginx.ingress.kubernetes.io/proxy-buffer-size: "32k"
nginx.ingress.kubernetes.io/proxy-buffering: "on"
spec:
ingressClassName: nginx
rules:
- host: ex)www.myjenkins.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: jenkins
port:
number: 80
Kubernetes에 배포한 Jenkins는 파이프라인을 위한 yaml을 직접 작성하고, Pod로 생성해 빌드할 수 있다.
이 과정에서 권한 상승, 과도한 리소스 사용 등 여러 문제가 발생할 수 있으므로 이를 차단하기 위한 설정이 필요하다.
agent 파드가 생성될 namespace를 생성한다.
k create ns jenkins-agents
agent 파드가 생성될 namespace에 jenkins가 agent를 생성할 수 있도록 역할을 할당한다.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: jenkins-agents-role
namespace: jenkins-agents
rules:
- apiGroups: [""]
resources: ["pods", "pods/exec", "pods/log", "persistentvolumeclaims", "events"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["secrets", "configmaps"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
# Jenkins 서비스 계정과 Role을 연결하는 RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: jenkins-agents-rolebinding
namespace: jenkins-agents
subjects:
- kind: ServiceAccount
name: jenkins
namespace: jenkins
roleRef:
kind: Role
name: jenkins-agents-role
apiGroup: rbac.authorization.k8s.io
agent 파드가 정해진 리소스 사용량을 넘지 못하도록 제한을 설정한다.
apiVersion: v1
kind: LimitRange
metadata:
name: jenkins-agent-max-limits
namespace: jenkins-agents
spec:
limits:
- type: Container
max:
cpu: "8000m"
memory: "16Gi"
agent 파드가 권한 상승을 요청 시 실행되지 않도록 설정한다.
k label namespace jenkins-agents pod-security.kubernetes.io/enforce=restricted
k edit role -n jenkins jenkins-schedule-agents
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
annotations:
...
...
rules:
- apiGroups:
- ""
resources:
- pods
- pods/exec
- pods/log
- persistentvolumeclaims
- events
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods
- pods/exec
- persistentvolumeclaims
verbs:
## Create 제거 ##
- delete
- deletecollection
- patch
- update
~

권한 상승을 제한하여 Docker를 사용해 빌드할 수 없다.
이를 대신해 Kaniko를 사용해 빌드한다.


Login Theme
# github 등 이미지 주소를 넣는다.
https://github.com/example/jenkins-logos/blob/main/jenkins/jenkins-logo.png?raw=true
<style>
.login-header {
text-align: center;
padding: 20px;
background-color: #f0f0f0;
}
.login-header h1 {
margin: 0;
font-size: 24px;
color: #333;
}
</style>
<h3 style="display: inline;">contact : <span style="color: purple">ex)email 등</span></h3>
Simple Theme
/* 젠킨스 로고 변경 */
#jenkins-home-link img {
content: url
width: 60px; /* 원하는 크기로 조절 */
height: auto;
}
/* 웰컴 문구 변경 */
#loginIntro {
display: none; /* 기존 웰컴 문구 숨기기 */
}
#loginIntro::after {
content: "원하는 웰컴 문구를 입력하세요";
display: block;
font-size: 16px;
margin-bottom: 20px;
color: #333;
}
/* 추가적인 로그인 페이지 스타일링 (선택사항) */
.simple-page {
background-color: #f5f5f5;
}
.login-container {
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
/* Jenkins 2.x 버전용 네비게이션 바 스타일 */
#header {
background-color: #2C3E50 !important;
border-bottom: 1px solid #233140 !important;
}
/* 추가적인 네비게이션 바 요소들의 스타일 */
.jenkins-header {
background-color: #2C3E50 !important;
}
/* 네비게이션 메뉴 스타일 */
.page-header {
background-color: #4A235A !important;
}
/* 기존 로고 숨기기 */
#jenkins-name-icon {
display: none; /* 기존 로고 숨기기 */
}
/* 새로운 텍스트 로고 스타일 */
.logo:after {
content: 'myJenkins'; /* 타이틀을 'myJenkins'로 변경 */
font-weight: bold;
font-size: 30px;
font-family: 'Helvetica Neue', Arial, sans-serif; /* 기본 글꼴 지정 */
margin-left: 20px; /* 이미지와 텍스트 간의 간격 좁히기 */
margin-right: 12px;
color: white; /* 텍스트 색을 흰색으로 설정 */
line-height: 40px; /* 줄 높이 조정 */
vertical-align: middle; /* 텍스트가 수평 중앙에 위치하도록 조정 */
}
/* 로고 텍스트 클릭 가능하게 만들기 */
#logo a {
display: flex; /* 로고와 텍스트를 가로로 나열하기 위한 flexbox 설정 */
align-items: center; /* 로고와 텍스트를 세로로 정렬 */
text-decoration: none; /* 링크의 밑줄 제거 */
color: white; /* 링크 텍스트 색상 */
}
/* 로고 텍스트 호버 시 스타일 */
#logo a:hover .logo:after {
text-decoration: underline; /* 텍스트에 밑줄 추가 (마우스 오버 시) */
}
/* 로고 텍스트 색상 */
#logo a .logo:after {
color: white; /* 텍스트 색을 흰색으로 설정 */
}
Jenkins URL을 설정해준다.
사용자별 설정
사용자 정보 → Account → 최 하단 Time Zone 설정

시스템 설정
Jenkins 관리 -> Jenkins Script Consol
System.setProperty('org.apache.commons.jelly.tags.fmt.timeZone', 'Asia/Seoul')
Clouds→kubernetes→Pod Template에서 설정이 가능하다.
예시 Pod Template의 일부분이다.


Clouds→kubernetes→Configure의Concurrency Limit에서 설정이 가능하다.


모든 설정 후, 사용자가 접속할 때마다 각 사용자가 격리된 폴더가 생성된다.
