Jenkins 구축 (On Kubernetes)

NOHHYEONGJUN·2025년 6월 26일

CI/CD

목록 보기
12/15
post-thumbnail

Jenkins

Jenkins는 오픈소스 자동화 서버로,
주로 지속적인 통합(CI: Continuous Integration) 및 지속적인 배포(CD: Continuous Delivery/Deployment) 파이프라인을 구현하는 데 사용된다.

 

  • 지속적 통합 및 배포(CI/CD)를 자동화하는 오픈소스 도구이다.

  • 코드 변경사항을 자동으로 빌드, 테스트하고 배포 파이프라인을 구축하여 개발 프로세스를 효율화한다.

 

간단하게 Kubernetes 위에 Jenkins를 배포하고 사용하는 방법을 정리해보았다.

추가로, keycloak OpenID Connect 연동도 함께 정리하였다.


 

 


1. values.yaml

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

 

 


2. Secret 및 Ingress 설정

Secret

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

 

Ingress

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

 

 


3. Agent 생성 설정

Kubernetes에 배포한 Jenkins는 파이프라인을 위한 yaml을 직접 작성하고, Pod로 생성해 빌드할 수 있다.
이 과정에서 권한 상승, 과도한 리소스 사용 등 여러 문제가 발생할 수 있으므로 이를 차단하기 위한 설정이 필요하다.

namespace 생성

agent 파드가 생성될 namespace를 생성한다.

k create ns jenkins-agents

 

Role & RoleBinding 생성

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

 

LimitRange 생성

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

 

Jenkins namespace Pod 생성 제한 설정

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
~             

 

Kubernetes Namespace 변경

 

Kaniko 사용

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

이를 대신해 Kaniko를 사용해 빌드한다.


 

 


4. 배포

Jenkins Helm repository 추가

 

values.yaml 추가 및 배포


 

 


5. 추가 설정

Login Theme & Simple Theme

Login Theme

  1. Branding
# github 등 이미지 주소를 넣는다.
https://github.com/example/jenkins-logos/blob/main/jenkins/jenkins-logo.png?raw=true

 

  1. CustomCSS
<style>
.login-header {
    text-align: center;
    padding: 20px;
    background-color: #f0f0f0;
}

.login-header h1 {
    margin: 0;
    font-size: 24px;
    color: #333;
}
</style>

 

  1. Footer
<h3 style="display: inline;">contact : <span style="color: purple">ex)email 등</span></h3>

 

 

Simple Theme

  1. Logo Image
/* 젠킨스 로고 변경 */
#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);
}

 

  1. Nav Color
/* 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;
}

 

  1. Title Logo
/* 기존 로고 숨기기 */
#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; /* 텍스트 색을 흰색으로 설정 */
}

 

system 설정

Jenkins URL을 설정해준다.

 

TimeZone 설정

사용자별 설정

사용자 정보Account → 최 하단 Time Zone 설정

시스템 설정

Jenkins 관리 -> Jenkins Script Consol

System.setProperty('org.apache.commons.jelly.tags.fmt.timeZone', 'Asia/Seoul')

 

Pod Template 설정

CloudskubernetesPod Template 에서 설정이 가능하다.
예시 Pod Template의 일부분이다.

 

Global Build Discarders 설정

 

동시 빌드 설정

CloudskubernetesConfigureConcurrency Limit에서 설정이 가능하다.

 

Keycloak 연동


 

 


결론

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


profile
Cloud/DevOps & Network Virtualization에 관심 있는 대학생입니다. 🐳

0개의 댓글