Kubernetes Engine에서 Jenkins 사용

이번 주제에서는 Google Kubernetes Engine으로 Jenkins를 사용하기 위한 권장사항을 설명합니다. 이 솔루션을 구현하려면 Kubernetes Engine에서 Jenkins 설정을 참조하세요.

Jenkins는 빌드, 테스트, 배포 파이프라인을 유연하게 조정할 수 있는 오픈소스 자동화 서버입니다. Kubernetes Engine은 컨테이너를 위한 강력한 클러스터 관리자 및 조정 시스템인 Kubernetes의 호스팅 버전입니다.

CD(지속적 배포) 파이프라인을 설정해야 하는 경우 Jenkins를 Kubernetes Engine에 배포하면 표준 VM 기반 배포 대비 상당한 이점을 얻을 수 있습니다.

  • 빌드 프로세스에서 컨테이너를 사용하는 경우 하나의 가상 호스트로 여러 운영체제에서 작업이 가능합니다.

  • Kubernetes Engine은 임시 빌드 실행자를 제공하여 각 빌드가 이전 빌드와 동일한 정리된 환경에서 실행되도록 합니다.

    • 빌드 실행자가 갖는 임시적 성격으로 인해 Kubernetes Engine 클러스터는 빌드가 활발하게 실행될 때만 사용되므로 일괄 처리 작업과 같은 다른 클러스터 작업에 그대로 리소스를 사용할 수 있습니다.

    • 빌드 실행자가 몇 초 안에 시작됩니다.

  • Kubernetes Engine은 Google 글로벌 부하 분산기를 활용하여 웹 트래픽을 사용자의 인스턴스로 라우팅합니다. 부하 분산기는 SSL 종료를 처리하고, Google 백본 네트워크를 통해 사용자의 현재 위치에서 가장 가까운 지점으로부터 가장 빠른 경로를 활용하여 사용자를 웹 프런트엔드로 라우팅하는 글로벌 IP 주소를 제공합니다.

Kubernetes Engine 클러스터 배포

Kubernetes Engine 클러스터를 배포할 때 다음 서비스에 대한 인증 범위를 사용 설정합니다.

  • Google Cloud Storage — storage-rw

    • Jenkins는 Cloud Storage에 콘텐츠를 저장하는 서비스인 Google Container Registry에 액세스해야 합니다.
  • Google Cloud Source Repositories — projecthosting

    • Cloud Source Repositories는 소스 코드에 사용할 수 있는 비공개 저장소를 제공합니다. Jenkins는 이러한 저장소로부터 코드를 가져와서 최대한 빨리 빌드, 테스트, 배포할 수 있습니다.

예를 들어 클러스터를 만들 때 다음과 유사한 코드를 사용할 수 있습니다.

gcloud container clusters create jenkins-cd \
         --network jenkins \
         --scopes "https://www.googleapis.com/auth/projecthosting,storage-rw"

다른 Google 서비스를 활용하려는 경우 추가 범위를 추가할 수 있습니다.

Jenkins 마스터 배포

다음 이미지는 다중 노드 Kubernetes 클러스터에 Jenkins를 배포하기 위한 아키텍처를 설명합니다.

Jenkins 및 Kubernetes 아키텍처

Jenkins 마스터를 Kubernetes 클러스터의 별도 네임스페이스에 배포합니다. 네임스페이스를 사용하면 Jenkins 배포에 대한 할당량을 만들 수 있으며 Jenkins를 클러스터 내의 다른 배포와 논리적으로 구분할 수 있습니다.

Kubernetes 네임스페이스를 만들려면 다음 명령어를 입력합니다.

kubectl create namespace jenkins

Jenkins 서비스 만들기

Jenkins는 클러스터가 액세스해야 하는 2가지 서비스를 제공합니다. 개별적으로 관리하고 이름을 지정할 수 있도록 이러한 서비스를 별도로 배포합니다.

  • 포드 8080의 외부 노출 NodePort 서비스는 포드를 허용하고 외부 사용자가 Jenkins 사용자 인터페이스에 액세스할 수 있도록 합니다. 이 유형의 서비스는 HTTP 부하 분산기에 의해 부하 분산을 수행할 수 있습니다.

  • 포트 50000의 내부, 비공개 ClusterIP 서비스는 Jenkins 실행자가 클러스터 내부에서 Jenkins 마스터와 통신하는 데 사용합니다.

다음 섹션은 샘플 서비스 정의를 보여줍니다.

---
  kind: Service
  apiVersion: v1
  metadata:
    name: jenkins-ui
    namespace: jenkins
  spec:
    type: NodePort
    selector:
      app: master
    ports:
      - protocol: TCP
        port: 8080
        targetPort: 8080
        name: ui
---
  kind: Service
  apiVersion: v1
  metadata:
    name: jenkins-discovery
    namespace: jenkins
  spec:
    selector:
      app: master
    ports:
      - protocol: TCP
        port: 50000
        targetPort: 50000
        name: slaves

Jenkins 배포 만들기

Jenkins 마스터를 복제본 개수가 1인 배포로 배포합니다. 이렇게 하면 항상 클러스터에 단일 Jenkins 마스터가 실행됩니다. Jenkins 마스터 포드가 종료되거나 실행중인 노드가 종료되면 Kubernetes는 클러스터의 다른 위치에서 포드를 다시 시작합니다.

배포 정의의 일부로 요청 및 제한을 설정하여 컨테이너가 예약되기 전에 일정량의 CPU 및 메모리 리소스가 보장되도록 하는 것은 중요합니다. 그렇지 않으면 CPU 또는 메모리 부족으로 마스터가 다운될 수 있습니다.

Jenkins 홈 볼륨은 구성을 이루는 XML 구성 파일과 플러그인 JAR 파일을 저장합니다. 다음 권장사항을 살펴보세요.

  • Jenkins 마스터를 실행하는 포드가 다운된 경우에도 중요한 구성 데이터가 유지되도록 홈 디렉토리를 저장할 영구 디스크를 만듭니다.

  • 디스크는 10GB 이상이어야 합니다.

  • 볼륨을 만든 후에 가상 머신에 볼륨을 연결하여 포맷해야 합니다. 그런 다음 모든 가상 머신에서 볼륨을 마운트 해제하고 분리합니다. 그런 다음 배포에서 볼륨을 사용할 수 있습니다.

다음 코드는 배포를 정의하는 예를 보여줍니다.

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: jenkins
  namespace: jenkins
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: master
    spec:
      containers:
      - name: master
        image: jenkins/jenkins:2.67
        ports:
        - containerPort: 8080
        - containerPort: 50000
        readinessProbe:
          httpGet:
            path: /login
            port: 8080
          periodSeconds: 10
          timeoutSeconds: 5
          successThreshold: 2
          failureThreshold: 5
        env:
        - name: JENKINS_OPTS
          valueFrom:
            secretKeyRef:
              name: jenkins
              key: options
        - name: JAVA_OPTS
          value: '-Xmx1400m'
        volumeMounts:
        - mountPath: /var/jenkins_home
          name: jenkins-home
        resources:
          limits:
            cpu: 500m
            memory: 1500Mi
          requests:
            cpu: 500m
            memory: 1500Mi
      volumes:
      - name: jenkins-home
        gcePersistentDisk:
          pdName: jenkins-home
          fsType: ext4
          partition: 1

Jenkins에 연결

Kubernetes 클러스터의 모든 포드는 호스트 이름으로 master.jenkins.svc를 사용하고 포트에 8080을 사용하여 Jenkins 사용자 인터페이스에 액세스할 수 있습니다.

Jenkins 포드가 생성되면 부하 분산기 엔드포인트를 만들어 Cloud Platform 외부에서 연결할 수 있습니다. 다음 권장사항을 살펴보세요.

  • SSL 종료 기능을 갖춘 구성하기 쉬운 L7 부하 분산기에 Kubernetes 수신 리소스를 사용합니다.

  • Kubernetes 비밀번호를 사용하여 부하 분산기에 SSL 인증서를 제공합니다. tls.certtls.key 값을 사용하고 수신 리소스 구성의 값을 참조합니다.

Jenkins 구성

Jenkins 보안

Jenkins에 처음 연결한 후 Jenkins를 즉시 보호하는 것이 중요합니다. 내부 사용자 데이터베이스를 활용하는 간단한 절차는 Jenkins 표준 보안 설정 가이드를 참조하세요. 이 설정은 추가 인프라가 필요하지 않으며 익명 사용자를 차단하는 기능을 제공합니다.

플러그인 설치

Jenkins와 Kubernetes Engine 간의 상호작용을 향상하기 위해 다음 플러그인을 설치할 수 있습니다.

  • Kubernetes 플러그인을 사용하면 Kubernetes 서비스 계정을 인증에 사용하고 다른 기본 이미지로 라벨이 지정된 실행자 구성을 만들 수 있습니다. 이 플러그인은 실행자가 필요할 때 포드를 만들고 작업이 끝나면 포드를 삭제합니다.

  • Google Authenticated Source 플러그인을 사용하면 Cloud Source Repositories와 같은 Cloud Platform 서비스에 액세스할 때 서비스 계정 사용자 인증 정보를 사용할 수 있습니다.

이 안내에 따라 플러그인을 설치합니다.

Kubernetes Engine용 Jenkins 구성

빌드 실행자 구성, 사용자 인증 정보 추가 등을 비롯한 Kubernetes Engine용 Jenkins 구성 방법에 대한 단계별 지침은 Kubernetes Engine용 Jenkins 구성을 참조하세요.

Docker 이미지 맞춤설정

포드 템플릿을 만들 때 기존 Docker 이미지를 제공하거나 대부분의 빌드 시간 종속 항목이 설치된 커스텀 이미지를 만들 수 있습니다. 커스텀 이미지를 사용하면 전체 빌드 시간을 줄이고 더욱 일관성 있는 빌드 환경을 만들 수 있습니다.

커스텀 Docker 이미지는 Jenkins JNLP 슬레이브 에이전트를 설치하고 구성해야 합니다. JNLP 에이전트는 Jenkins 마스터와 통신하여 Jenkins 작업 실행 및 보고 작업 상태를 조정하는 소프트웨어입니다.

한 가지 옵션은 FROM jenkins/jnlp-slave를 이미지 구성에 추가하는 것입니다. 예를 들어, 애플리케이션 빌드 프로세스가 Go 런타임에 의존하는 경우 다음 Dockerfile을 만들어 기존 이미지를 자신의 종속 항목으로 확장하고 아티팩트를 빌드할 수 있습니다.

FROM jenkins/jnlp-slave
RUN apt-get update && apt-get install -y golang

그런 다음, 다음 명령어를 실행하여 프로젝트의 Container Registry 저장소에 이미지를 빌드하고 업로드합니다.

docker build -t gcr.io/[PROJECT]/my-jenkins-image .
gcloud docker -- push gcr.io/[PROJECT]/my-jenkins-image

포드 템플릿을 만들 때 Docker 이미지 필드를 다음 문자열로 설정할 수 있습니다. 여기서 [PROJECT]는 프로젝트 이름으로 [IMAGE_NAME]은 이미지 이름으로 바뀝니다.

gcr.io/[PROJECT]/[IMAGE_NAME]

위의 예에서는 Jenkins 작업이 시작될 때 Go 언어 런타임이 사전 설치되도록 합니다.

Jenkins 업그레이드

Jenkins 마스터를 업그레이드하려면 배포 매니페스트를 수정하고 이미지 속성의 태그 값을 업그레이드할 버전으로 변경합니다. 사용 가능한 버전 목록은 Docker의 Jenkins 이미지 태그 목록을 참조하세요.

파일을 수정한 후 다음 명령어를 사용하여 변경사항을 배포합니다.

kubectl apply -f jenkins.yaml

다음 단계

이 페이지가 도움이 되었나요? 평가를 부탁드립니다.

다음에 대한 의견 보내기...