Jenkins / DinD 3-1. K8S & K8S Cloud Agent

Flexyz·2024년 1월 18일
0

Jenkins

목록 보기
6/11

현황 & 목표

지금까지 우리는 도커가 설치된 리눅스 호스트나 도커 실행환경에 젠킨스를 설치한 후 파이프라인을 이용하여 git 레포지토리에서 소스 파일을 체크아웃하고 Dockerfile을 도커 이미지로 빌드한 후 별도의 레지스트리로 push 한 후, 아르고를 이용하여 쿠버네티스 클러스터에 해당 도커 이미지를 배포하였습니다. (길다...)

정석적인 방법이기는 하지만 쿠버네티스 배포를 위해 별도의 환경에 의존해야 하는 점, 젠킨스의 호스트 도커 의존성 등이 한계로 남아있습니다. 쿠버네티스 관리 클러스터에서 컨테이너의 배포와 관리를 자동화하는 것을 목표로 보면 개선이 필요한 상황입니다.

문제 해결을 위해 일단 젠킨스를 관리 클러스터의 쿠버네티스 환경에 설치하고 에이전트의 호스트 의존을 최소화 하도록 에이전트를 동적으로 생성하고 에이전트 내에 사이드 컨테이너로 dind 컨테이너(도커 유틸리티가 기본 설치되어 있는 도커에서 공식지원하는 이미지의 태그인 dind로 생성하는 컨테이너)를 통해 젠킨스 파이프라인 상에서 dind 컨테이너의 도커를 사용하도록 합니다.

참고

k8s는 1.20 버전부터 docker의 컨테이너 런타임 기본 지원을 중단하였습니다. 따라서 젠킨스 파드에서 직접 도커 런타임을 사용하였던 기존 방식과 다르게, 1.20 버전부터는 젠킨스 컨테이너에서 도커를 사용하려면 다른 방식을 적용해야 합니다. 여러가지 방식이 있지만 최근 공부한 DinD 방식을 적용하여 보기로 합시다.


실습

  1. 설치할 쿠버네티스 클러스터의 컨텍스트로 전환합니다.
k config get-clusers # 컨텍스트 확인
k config use-contexts <컨텍스트명>

  1. 헬름을 설치합니다.
    https://helm.sh/ko/docs/intro/install/
# Mac
brew install kubernetes-helm

# Linux
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 && \
chmod 700 get_helm.sh && ./get_helm.sh

  1. 헬름에 젠킨스 차트를 추가합니다.
helm repo add jenkins https://charts.jenkins.io
helm repo update

  1. 젠킨스 설치 시 필요한 설정의 모음인 values.yaml 를 다운받은 후 에이젠트에 dind 사이드 컨테이너를 추가하도록 수정합니다.
    젠킨스 버전 업데이트되면서 values.yaml 형식이 달라질 수 있으니 수정본은 참고용으로 이용하시기 바랍니다.
# 원본 (계속 업데이트)
curl -LO https://raw.githubusercontent.com/jenkinsci/helm-charts/main/charts/jenkins/values.yaml

# 수정본 (Jenkins Ver.2.426.3)
https://github.com/codelab-kr/microservices-starter/blob/feature/infra/mgmt/jenkins/values.yaml

  1. 핼름을 사용하여 젠킨스를 설치합니다.
❯ helm install jenkins jenkins/jenkins --namespace jenkins --create-namespace -f values.yaml

Release "jenkins" does not exist. Installing it now.
NAME: jenkins
LAST DEPLOYED: Thu Jan 18 14:36:56 2024
NAMESPACE: jenkins
STATUS: deployed
REVISION: 1
NOTES:
1. Get your 'admin' user password by running:
  kubectl exec --namespace jenkins -it svc/jenkins -c jenkins -- /bin/cat /run/secrets/additional/chart-admin-password && echo
2. Get the Jenkins URL to visit by running these commands in the same shell:
  echo http://127.0.0.1:8080
  kubectl --namespace jenkins port-forward svc/myjenkins 8080:8080

3. Login with the password from step 1 and the username: admin
4. Configure security realm and authorization strategy
5. Use Jenkins Configuration as Code by specifying configScripts in your values.yaml file, see documentation: http://127.0.0.1:8080/configuration-as-code and examples: https://github.com/jenkinsci/configuration-as-code-plugin/tree/master/demos

For more information on running Jenkins on Kubernetes, visit:
https://cloud.google.com/solutions/jenkins-on-container-engine

For more information about Jenkins Configuration as Code, visit:
https://jenkins.io/projects/jcasc/


NOTE: Consider using a custom image with pre-installed plugins

  1. 설치를 확인합니다. (시간이 좀 걸립니다.)
❯ k get all -n jenkins
NAME            READY   STATUS    RESTARTS   AGE
pod/jenkins-0   2/2     Running   0          2m8s

NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)     AGE
service/jenkins         ClusterIP   10.96.234.211   <none>        8080/TCP    2m8s
service/jenkins-agent   ClusterIP   10.96.76.209    <none>        50000/TCP   2m8s

NAME                       READY   AGE
statefulset.apps/jenkins   1/1     2m8s

  1. 로컬로 포워딩하여 브라우저로 대시보드가 실행되는지 확인합니다.
echo http://127.0.0.1:8080
  kubectl --namespace jenkins port-forward svc/jenkins 8080:8080

5번까지만 해도 일단 사용은 가능하지만 로컬호스트로 연결하는 것은 왠지 프로답지 않습니다. :)
ssl을 적용하고 도메인을 연결해 봅시다.
여기서부터는 NLB 설치 및 nginx-ingress, cert-manager 등이 설치되어 있고 상용 도메인을 소유하고 있다는 가정하여 진행됩니다.

상세 사항은 관련 포스팅을 참고하시기 바랍니다.
https://velog.io/@codelab/multi-cluster-2-Ingress-Nginx

해당내용을 스킵하실 분은 바로 10번으로 건너가시기 바랍니다.


  1. 도메인을 관리하는 사이트(클라우드 플레이어 등)에 접속해서 jenkins 도메인을 cname으로 등록합니다.

  1. ingress-jenkins-prod.yaml 을 작성합니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: jenkins-prod
  namespace: jenkins
  annotations:
    acme.cert-manager.io/http01-ingress-class: nginx
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/proxy-body-size: 999m
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - jenkins.code-lab.kr
    secretName: jenkins-prod-tls
  rules:
  - host: jenkins.code-lab.kr
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: jenkins
            port:
              number: 8080                                 

  1. 적용하고 확인합니다.
❯  k apply -f ingress-jenkins-prod.yaml -n jenkins

❯ k get certificate -n jenkins
NAME               READY   SECRET             AGE
jenkins-prod-tls   True    jenkins-prod-tls   5m46s


❯ k get ingress -n jenkins
NAME           CLASS   HOSTS                 ADDRESS                      PORTS     AGE
jenkins-prod   nginx   jenkins.code-lab.kr   10.0.20.108,146.56.188.188   80, 443   6m52s

  1. 접속해 봅니다.
# 비번 확인
❯ kubectl exec --namespace jenkins -it svc/jenkins -c jenkins -- /bin/cat /run/secrets/additional/chart-admin-password && echo 

이런 화면이 뜨면 성공입니다.

  1. 마지막으로 젠킨스에서 파이프라인 실행 시 에이전트를 동적으로 생성하고 dind 컨테이너의 도커환경을 사용할 수 있는지 테스트 합니다.
  • 젠킨스 대시보드 > + 새로운 아이템 > 파이프라인 > 맨 하단의 파이프라인 > Definition은 파이프라인 스크립트로 선택 >
    스크립트에 아래 구문을 입력합니다.
node {
    stage('Build UI Docker Image') {
        container('dind') {
          sh "docker --version"
        }
    }
}
  • dind 컨테이너를 이용하여 docker 버전을 출력하는 간단한 스크립트입니다.
  • 지금 빌드를 눌러서 파이프라인을 실행합니다.
    실행중인 빌드를 클릭하고 콘솔 출력을 확인합니다.

  • 에이젠트 생성 시 dind 컨테이너가 포함되어 있는 것을 확인할 수 있습니다.

  • 도커 버전을 올바르게 출력하고 결과도 성공으로 나옵니다.

  • 좀 더 상세한 로그는 아래와 같이 확인할 수 있습니다.

❯ k logs -f pod/jenkins-0 -n jenkins
profile
Think about a better architecture

0개의 댓글