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에서 Jenkins 사용에 대해 자세히 알아보려면 YouTube에서 Next 2018 talk를 확인하세요.

Helm을 사용하여 Jenkins 마스터 배포

Helm을 사용하여 Charts 저장소에서 Jenkins를 배포할 수 있습니다. Helm은 Kubernetes 앱을 구성 및 배포하는 데 사용할 수 있는 패키지 관리자입니다.

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

Jenkins 및 Kubernetes 아키텍처

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

Jenkins 서비스 만들기

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

  • 포트 8080의 외부 노출 NodePort 서비스는 Pod와 외부 사용자가 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 마스터 pod가 종료되거나 실행 중인 노드가 종료되면 Kubernetes는 클러스터의 다른 위치에서 pod를 다시 시작합니다.

요청 및 한도를 Helm 배포 과정에서 설정하여 컨테이너가 예약되기 전에 클러스터 내에서 일정량의 CPU와 메모리 리소스가 보장되도록 해야 합니다. 그렇지 않으면 CPU 또는 메모리 부족으로 마스터가 다운될 수 있습니다.

Jenkins 홈 볼륨은 구성을 이루는 XML 구성 파일과 플러그인 JAR 파일을 저장합니다. 이 데이터는 GKE 클러스터에서 관리하는 Persistent Disk에 저장되고 Jenkins가 다시 시작되어도 데이터가 유지됩니다. 영구 디스크의 크기를 변경하려면 Helm과 Jenkins를 설치할 때 Persistence.Size 값을 수정합니다.

Jenkins에 연결

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

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

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

Jenkins 구성

Jenkins 보안

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

플러그인 설치

Jenkins와 Kubernetes Engine 간의 상호작용을 강화하려면 다음 플러그인을 설치하면 됩니다.

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

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

Helm 차트를 사용하여 플러그인을 추가하려면 Helm 설치 또는 업그레이드 명령어에 전달한 값 파일에서 플러그인 목록을 수정합니다.

Jenkins Agent Docker 이미지 맞춤설정

pod 템플릿을 만들 때 기존 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

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

gcr.io/[PROJECT]/[IMAGE_NAME]

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

Jenkins에 Docker 이미지 빌드

Jenkins 작업 내에서 Cloud Build를 사용하면 자체 Docker 데몬을 호스팅하지 않고 Docker 이미지를 빌드할 수 있습니다. Jenkins 작업에는 cloudbuild.builds.editor 역할이 부여된 사용 가능한 서비스 계정 사용자 인증 정보가 있어야 합니다.

Jenkins 파이프라인 파일 예시는 이 GitHub 저장소를 참조하세요.

Kaniko는 클러스터 내부에 컨테이너를 빌드하려는 사용자를 위한 또 다른 옵션입니다. Kaniko에서는 이미지를 빌드하여 원격 레지스트리에 내보내기 위해 Docker 데몬이 있을 필요가 없습니다.

Jenkins에서 Kaniko를 사용하는 예시는 이 GitHub 저장소를 참조하세요.

다음 단계