Study/CI&CD

로컬 kubernetes에 Spinnaker 설치해 보기

Bluesky_ 2022. 12. 18. 05:54
반응형

전체 글타래

2022.12.18 - [Study/CI&CD] - 로컬 kubernetes에 Spinnaker 설치해 보기

2022.12.22 - [Study/CI&CD] - spinnaker CD 연동해 보기 - jenkins, kubernetes 연동, pipeline 사용

2022.12.26 - [Study/CI&CD] - spinnaker CD 연동해 보기 (2) - deploy manifest artifact 사용, SpEL 사용

2023.01.01 - [Study/CI&CD] - spinnaker CD 연동해 보기 (3) - jenkins parameter 사용, kubernetes livenessProbe, readinessProbe 설정

2023.01.10 - [Study/CI&CD] - spinnaker CD 연동해 보기 (4) - pipeline template 사용해 보기

Spinnaker 소개

https://spinnaker.io/
개인적으로 CI (Continuous Integration)는 jenkins를 사용하는데 소스코드를 커밋하면 jar와 docker image까지 빌드하여 artifactory에 업로드하였다.
하지만 이렇게 올라간 이미지를 기준으로 배포를 하는 CD의 역할은 현재로선 spinnaker가 괜찮아 보여서 설치해보았다.
spinnaker는 application 관리 및 배포 기능을 제공하여 소프트웨어 변경 사항을 신속하고 확실하게 release 할 수 있도록 지원한다.
강력하고 유연한 파이프라인 관리 시스템과 주요 클라우드 공급자와의 통합을 결합한 오픈소스 멀티 클라우드 continuous delivery platform이다.
다음처럼 파이프라인을 사용자가 원하는 형태로 구성하여 배포 진행을 할 수 있도록 한다.

각 단계는 순차적으로 진행이 되며 수동으로 진행할 수도 있고 jenkins의 작업 완료, registry의 새 docker image, cron schedule이나 다른 pipeline의 단계 등을 통해서도 진행이 될 수 있다.
또한 파이프라인 실행 중 다양한 시점(pipeline 시작/완료/실패)에서 email이나 Slack, SMS를 통해 알림을 내보낼 수도 있다.
이렇게 jenkins가 지속적인 통합을 담당하고 spinnaker는 지속적인 배포를 담당하도록 구성하면 빌드/배포를 효율적으로 진행할 수 있다.

Spinnaker의 구조

https://spinnaker.io/docs/reference/architecture/microservices-overview/
spinnaker는 msa로 구성되어 있다.

설치를 진행할 경우 이 각각의 msa를 구성해야 한다.
내부적인 구성을 모두 알고 있을 필요는 없고 가장 끝단에 deck (ui를 담당)과 gate (api를 담당)가 있다는 것만 우선 인지하고 있으면 된다.

Spinnaker 설치하기

Halyard 소개

spinnaker가 여러 msa로 이루어진 구조이고 또한 다양한 provider, environment, storage를 지원하기 때문에 설정이 다양하다.
이러한 설정 과정을 간략하게 해 주기 위해 Halyard라는 command line 관리 도구를 제공한다.
Halyard를 통해 설정, 설치, 버전 관리, 배포를 할 수 있다.

설치 순서

https://spinnaker.io/docs/setup/install/
Spinnaker를 설치하기 위해서는 다음과 같은 단계를 거쳐야 한다.

  1. Halyard 설치
  2. Halyard로 spinnaker 환경을 구성하여 spinnaker 배포
    1. cloud provider 선택 (아래의 cloud provider를 지원함)
      1. App Engine
      2. Amazon Web Services
      3. Azure
      4. Cloud Foundry
      5. DC/OS
      6. Google Coupute Engine
      7. Kubernetes
      8. Oracle
    2. environment 선택
      1. Distributed installation
      2. Local Debian
      3. Local Git
    3. stroage service 선택 (아래의 storage를 지원함)
      1. Azure Storage
      2. Google Cloud Storage
      3. MinIO
      4. Redis
      5. S3
      6. Oracle Object Storage
    4. spinnaker 배포
    5. config backup
    6. 기타 설정들
    7. spinnaker 생산

마지막 5,6,7은 추가적인 단계이고 1~6까지의 단계를 halyard로 진행하면 spinnaker 설치가 된다.
내 경우 cloud provider와 environment는 모두 local pc의 kubernetes이고 storage의 경우 MinIO를 선택하였다.

MinIO storage server 설치 (로컬 개발용 kubernetes pod)

문서상에는 Redis를 지원한다고 하지만 프로덕션 환경에서 권장하지 않으며 심지어 테스트를 하지 않았다고 한다.
MinIO는 Amazon S3와 호환되는 OpenSource Storage Server이다.
MinIO로 개발을 한 경험은 그대로 S3에 적용된다고 한다.
내 경우 아래와 같이 9090, 9091 port를 사용하도록 k8s pod로 띄웠다.
https://gist.github.com/luversof/e52fc1133a22d5361a14a74d2eb40c29#file-minio-yaml

kubectl apply -f minio.yaml

Halyard 설치

https://spinnaker.io/docs/setup/install/halyard/
다양한 환경에 Halyard를 설치하는 방법을 문서에서 안내하고 있다.
내 경우 개인 PC의 docker에 설치를 진행하였다.

docker run --name halyard --rm -v F:\dev\data\halyard:/home/spinnaker/.hal -v  C:\Users\bluesky\.kube\config:/home/spinnaker/.kube/config -it us-docker.pkg.dev/spinnaker-community/docker/halyard:stable

docker container를 띄우며 설정 파일을 volume mount로 접근할 수 있도록 하였고 docker container 내에서 docker desktop의 kubectl 명령어를 사용할 수 있도록 설정하였다.
해당 container에 진입한다.

docker exec -it halyard /bin/bash

container 내에서 hal 명령어가 동작하는 것을 확인할 수 있다.

bash-5.0$ hal -v
1.51.0

또한 container 내에서 kubectl 명령도 잘 동작한다.

kubectl get pods

Choose Cloud Providers

https://spinnaker.io/docs/setup/install/providers/kubernetes-v2/

hal config provider kubernetes enable
hal config provider kubernetes account add my-k8s-account --context $(kubectl config current-context)

계정명을 딱히 고민하지 않아서 예제의 계정명 그대로 사용했다.

이후 설정을 변경할 때마다 /home/spinnaker/.hal/config 파일에 설정이 반영된다.

해당 파일을 확인하여 설정이 올바르게 적용되었는지 확인하면 된다.

Choose your environment

https://spinnaker.io/docs/setup/install/environment/

hal config deploy edit --type distributed --account-name my-k8s-account

배포할 환경에 대해 계정 설정을 해야 한다.
이를 설정하지 않으면 이후 배포 시 권한 관련 오류가 발생한다.

External Storage

로컬 kubernetes에 설치한 minio를 설정한다.
이 경우 --path-style-access 옵션을 추가해야 해당 kubernetes dns 주소를 올바르게 호출한다.
minio access 관련 설정을 할 수도 있지만 테스트를 위한 설정이라 생략하였다.
내 경우 내부 api port는 9091을 사용하였기 때문에 다음과 같이 설정하였다.

hal config storage s3 edit --endpoint http://minio-service.default:9091 --access-key-id minioadmin --secret-access-key minioadmin --path-style-access true
hal config storage edit --type s3

Deploy Spinnaker and Connect to the UI

사용할 spinnaker 버전을 선택하고

hal version list
hal config version edit --version 1.29.2

이제까지 진행한 설정을 적용한다.

hal deploy apply

이제까지 진행하면서 한 설정들은 halyard container를 띄울 때 설정했던 폴더 (내 경우 F:\dev\data\halyard)에 반영되었다.
이후 변경을 진행하고 다시 apply를 실행했는데 제대로 적용되지 않는 듯하면 아래와 같이 배포를 삭제하고 다시 반영을 하면 된다.

hal deploy clean

여기까지 진행을 하였으면 kubernetes에 spinnaker 관련 pod들이 뜬 것을 확인할 수 있다.
spinnaker의 경우 spinnaker라는 이름의 namespace에 해당 pod들이 뜬다.
다음과 같이 확인할 수 있다.

C:\Users\bluesky>kubectl get pods -n spinnaker
NAME                                READY   STATUS    RESTARTS   AGE
spin-clouddriver-6477bd7987-jrm7l   1/1     Running   0          4m34s
spin-deck-68b8f4d5c5-v2xf6          1/1     Running   0          4m34s
spin-echo-685c4b9c4d-lv8cs          1/1     Running   0          4m34s
spin-front50-6c47c488f4-knlxz       1/1     Running   0          4m33s
spin-gate-57bbc44849-24hnm          1/1     Running   0          4m34s
spin-orca-57f8644fd9-zq64g          1/1     Running   0          4m34s
spin-redis-6bcf6b49d5-zgdpk         1/1     Running   0          4m34s
spin-rosco-59bbb57944-bcwlf         1/1     Running   0          4m33s

다만 외부 노출이 되어 있지 않은 상태이다.

C:\Users\bluesky>kubectl get svc -n spinnaker
NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
spin-clouddriver   ClusterIP   10.100.122.182   <none>        7002/TCP   5m7s
spin-deck          ClusterIP   10.105.204.243   <none>        9000/TCP   5m7s
spin-echo          ClusterIP   10.99.88.100     <none>        8089/TCP   5m7s
spin-front50       ClusterIP   10.102.119.145   <none>        8080/TCP   5m7s
spin-gate          ClusterIP   10.107.242.217   <none>        8084/TCP   5m7s
spin-orca          ClusterIP   10.110.177.163   <none>        8083/TCP   5m7s
spin-redis         ClusterIP   10.102.147.120   <none>        6379/TCP   5m7s
spin-rosco         ClusterIP   10.97.247.39     <none>        8087/TCP   5m7s

이를 해결하기 위해 추가적인 설정을 진행해야 한다.
안내 문서상에는 "hal deploy connect"를 사용하여 연결을 진행하는 것으로 되어 있지만 k8s로 띄우고 난 후의

추가 설정 Custom Settings

https://spinnaker.io/docs/reference/halyard/custom/
여러 pod들이 msa로 구성되어 있지만 spinnaker를 사용하는 가장 앞단의 pod는 spin-deck과 spin-gate 이 두 개다.
이 두 개의 pod를 외부 노출 처리를 해주어야 한다.
관련한 설정에 대해 검색해보면 보통 아래의 방법을 알려주고 있다.

  1. kubernetes의 service에서 nodePort 수정
  2. hal config security로 overrideBaseUrl 설정

이 방식으로 설정하면 nodeport 설정이 halyard가 아닌 kubernetes의 설정 변경이기 때문에 이후 hal deploy clean후 다시 배포하면 해당 설정이 초기화된다.
spinnaker의 문서를 찾아보니 Custom Setting에 대한 지원이 있다.
hal 명령을 통해 설정이 다 지원되지 않지만 어느 정도 확장해서 설정이 가능하다.

kubernetes NodePort 설정 & overrideBaseUrl 설정

pod가 정상적으로 뜨는 것까지 확인하였으면 이제 접속을 할 수 있도록 접근할 port를 열어주어야 한다.
spin-deck과 spin-gate 두 개에 대해 설정하면 된다.
또한 기본 port가 아닌 nodePort (30000 ~ 32768)로 변경되었기 때문에 호출하는 주소도 변경된 것을 반영해주어야 한다.
처음 halyard container를 생성할 때 설정한 볼륨 마운트의 폴더를 가보면 진행한 설정에 대한 파일과 디렉터리가 만들어져 있다.
해당 위치의 /default/service-settings/ 아래에 다음과 같이 추가 설정 파일을 만들어준다.
(yaml이 아니고 yml 파일이다)
deck.yml 파일 :

overrideBaseUrl: http://localhost:30000
kubernetes:
  serviceType: NodePort
  nodePort: 30000

gate.yml 파일 :

overrideBaseUrl: http://localhost:30001
kubernetes:
  serviceType: NodePort
  nodePort: 30001

이렇게 만들어주고 hal deploy clean 후 다시 hal deploy appy를 하면 kubernetes 생성 시 nodeport가 설정된 port로 뜨게 된다.

C:\Users\bluesky>kubectl get svc -n spinnaker
NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
spin-clouddriver   ClusterIP   10.100.71.67     <none>        7002/TCP         32s
spin-deck          NodePort    10.108.46.235    <none>        9000:30000/TCP   32s
spin-echo          ClusterIP   10.107.61.118    <none>        8089/TCP         32s
spin-front50       ClusterIP   10.103.157.206   <none>        8080/TCP         32s
spin-gate          NodePort    10.104.62.134    <none>        8084:30001/TCP   32s
spin-orca          ClusterIP   10.96.142.112    <none>        8083/TCP         32s
spin-redis         ClusterIP   10.104.164.248   <none>        6379/TCP         32s
spin-rosco         ClusterIP   10.111.52.76     <none>        8087/TCP         32s

이렇게 뜬 pod로 접속해보면 접근이 되는 것이 확인된다.
http://localhost:30000
하지만 api 호출이 제대로 되지 않는 것을 확인할 수 있다.

localhost:30000 (deck)에서 localhost:30001 (gate)를 호출하면서 발생하는 CORS 오류이다.
이에 대해서 CORS 허용 설정을 추가한다.
(문서엔 custom setting에서 CORS 설정을 허용하는 항목이 보이지 않고 hal command로 추가할 수 있었다.)

hal config security api edit --cors-access-pattern http://localhost:30000

다시 hal deploy clean 후 hal deploy apply를 하면 이제 정상적으로 spinnaker 접속할 수 있는 것을 확인할 수 있다.

timezone 설정

기본 timezone 설정은 America/Los_Angeles 이다.

원하는 timezone 설정은 다음과 같이 한다.

hal config edit --timezone Asia/Seoul
반응형