>백엔드 개발 >Golang >Kubernetes 작업을 사용하여 OpenSSF 스코어카드를 확장하는 방법

Kubernetes 작업을 사용하여 OpenSSF 스코어카드를 확장하는 방법

WBOY
WBOY원래의
2024-08-09 10:20:521165검색

How we use Kubernetes jobs to scale OpenSSF Scorecard

최근 OpenSauced 플랫폼에서 OpenSSF Scorecard와의 통합을 출시했습니다. OpenSSF 스코어카드는 누구나 프로젝트 및 종속성의 보안 상태를 이해하는 데 사용할 수 있는 강력한 Go 명령줄 인터페이스입니다. 위험한 작업 흐름, CICD 모범 사례, 프로젝트가 여전히 유지 관리되고 있는지 등에 대한 여러 검사를 실행합니다. 이를 통해 소프트웨어 빌더와 소비자는 전반적인 보안 상황을 이해하고, 프로젝트가 사용하기에 안전한지, 보안 관행을 개선해야 하는 부분을 추론할 수 있습니다.

그러나 OpenSSF 스코어카드를 OpenSauced 플랫폼에 통합한 우리의 목표 중 하나는 이를 더 넓은 오픈 소스 생태계에서 사용할 수 있도록 하는 것이었습니다. GitHub의 저장소인 경우 이에 대한 점수를 표시할 수 있기를 원했습니다. 이는 GitHub의 거의 모든 저장소를 대상으로 Scorecard CLI를 확장하는 것을 의미했습니다. 말은 실천보다 훨씬 쉽습니다!

이 블로그 게시물에서는 Kubernetes를 사용하여 이를 수행한 방법과 이 통합을 구현하면서 내린 기술적 결정에 대해 자세히 살펴보겠습니다.

우리는 수많은 저장소에서 점수를 자주 업데이트하는 크론 유형 마이크로서비스를 구축해야 한다는 것을 알고 있었습니다. 진정한 질문은 이를 어떻게 수행할 것인가였습니다. 스코어카드 CLI를 임시로 실행하는 것은 의미가 없습니다. 플랫폼이 너무 쉽게 압도될 수 있으므로 OpenSauced 저장소 페이지가 작동하지 않더라도 오픈 소스 생태계 전반에 걸쳐 점수에 대한 심층 분석을 수행할 수 있기를 원했습니다. 최근에 방문했습니다. 처음에는 Scorecard Go 라이브러리를 직접 종속 코드로 사용하고 단일 모놀리식 마이크로서비스 내에서 스코어카드 확인을 실행하는 방법을 살펴보았습니다. 또한 서버리스 작업을 사용하여 개별 저장소에 대한 결과를 반환하는 일회성 스코어카드 컨테이너를 실행하는 것도 고려했습니다.

단순성, 유연성, 강력함을 결합한 우리가 최종적으로 선택한 접근 방식은 Kubernetes 작업을 대규모로 사용하는 것이며, 모두 "스케줄러" Kubernetes 컨트롤러 마이크로서비스로 관리됩니다. 스코어카드를 사용하여 더 심층적인 코드 통합을 구축하는 대신 Kubernetes 작업 중 하나를 실행하면 서버리스 접근 방식을 사용할 때와 동일한 이점을 얻을 수 있지만 모든 것을 Kubernetes 클러스터에서 직접 관리하므로 비용이 절감됩니다. 또한 작업은 실행 방식에 있어 많은 유연성을 제공합니다. 길고 연장된 시간 제한을 가질 수 있고, 디스크를 사용할 수 있으며, 다른 Kubernetes 패러다임과 마찬가지로 다양한 작업을 수행하는 여러 포드를 가질 수 있습니다.

이 시스템의 개별 구성요소를 분석하고 작동 방식을 자세히 살펴보겠습니다.

이 시스템의 첫 번째이자 가장 큰 부분은 "scorecard-k8s-scheduler"입니다. 클러스터에서 새로운 작업을 시작하는 Kubernetes 컨트롤러와 유사한 마이크로서비스입니다. 이 마이크로서비스는 기존 Kubernetes 컨트롤러 또는 연산자를 구축할 때 사용되는 많은 원칙, 패턴 및 방법을 따르지만 클러스터에서 사용자 지정 리소스를 감시하거나 변경하지 않습니다. 그 기능은 Scorecard CLI를 실행하고 완료된 작업 결과를 수집하는 Kubernetes 작업을 간단히 시작하는 것입니다.

먼저 Go 코드의 메인 제어 루프를 살펴보겠습니다. 이 마이크로서비스는 Kubernetes Client-Go 라이브러리를 사용하여 마이크로서비스가 실행 중인 클러스터와 직접 인터페이스합니다. 이를 종종 클러스터 내 구성 및 클라이언트라고 합니다. 코드 내에서 클러스터 내 클라이언트를 부트스트래핑한 후 업데이트가 필요한 데이터베이스의 저장소를 폴링합니다. 일부 저장소가 발견되면 각 작업이 완료될 때까지 기다리는 개별 작업자 "스레드"에서 Kubernetes 작업을 시작합니다.

// buffered channel, sort of like semaphores, for threaded working
sem := make(chan bool, numConcurrentJobs)

// continuous control loop
for {
    // blocks on getting semaphore off buffered channel
    sem <- true

    go func() {
        // release the hold on the channel for this Go routine when done
        defer func() {
            <-sem
        }()

        // grab repo needing update, start scorecard Kubernetes Job on-cluster,
        // wait for results, etc. etc.

        // sleep the configured amount of time to relieve backpressure
        time.Sleep(backoff)
    }()
}

버퍼링된 채널을 사용하는 이 "무한 제어 루프" 방법은 Go에서 구성된 수의 스레드만 사용하여 지속적으로 작업을 수행하는 일반적인 방법입니다. 특정 시점에 실행되는 동시 Go 기능의 수는 "numConcurrentJobs" 변수에 구성된 값에 따라 달라집니다. 이는 특정 시간에 실행되는 동시 Go 기능 수를 나타내는 작업자 풀 또는 세마포 역할을 하도록 버퍼링된 채널을 설정합니다. 버퍼링된 채널은 모든 스레드가 사용하고 검사할 수 있는 공유 리소스이기 때문에 저는 종종 이것을 세마포어, 즉 여러 스레드가 잠그고 액세스하려고 시도할 수 있는 뮤텍스와 유사한 리소스로 생각하고 싶습니다. 프로덕션 환경에서는 동시에 실행되는 이 스케줄러의 스레드 수를 확장했습니다. 실제 스케줄러는 계산량이 그리 많지 않고 작업을 시작하고 결과가 나타날 때까지 기다리므로 이 스케줄러가 관리할 수 있는 범위를 확장할 수 있습니다. 또한 필요할 때 부담을 완화하려고 시도하는 백오프 시스템이 내장되어 있습니다. 이 시스템은 오류가 있거나 점수를 계산할 리포지토리가 없는 경우 구성된 "백오프" 값을 증가시킵니다. 이렇게 하면 쿼리로 인해 데이터베이스가 지속적으로 중단되지 않고 스코어카드 스케줄러 자체가 클러스터의 귀중한 컴퓨팅 리소스를 차지하지 않고 "대기" 상태로 유지될 수 있습니다.

제어 루프 내에서 몇 가지 작업을 수행합니다. 먼저 스코어카드를 업데이트해야 하는 저장소를 데이터베이스에 쿼리합니다. 이는 우리가 관찰하고 인덱스를 갖고 있는 일부 타임스탬프 메타데이터를 기반으로 하는 간단한 데이터베이스 쿼리입니다. 저장소에 대한 마지막 점수가 계산된 후 구성된 시간이 지나면 Scorecard CLI를 실행하는 Kubernetes 작업에 의해 버블링되어 크런치됩니다.

다음으로 점수를 얻을 수 있는 저장소가 있으면 'gcr.io/openssf/scorecard' 이미지를 사용하여 Kubernetes 작업을 시작합니다. Client-Go를 사용하여 Go 코드에서 이 작업을 부트스트랩하는 것은 "k8s.io" 가져오기를 통해 사용할 수 있는 다양한 라이브러리와 API를 사용하고 프로그래밍 방식으로 수행한다는 점에서 yaml을 사용하는 것과 매우 유사해 보입니다.

// defines the Kubernetes Job and its spec
job := &batchv1.Job{
    // structs and details for the actual Job
    // including metav1.ObjectMeta and batchv1.JobSpec
}

// create the actual Job on cluster
// using the in-cluster config and client
return s.clientset.BatchV1().Jobs(ScorecardNamespace).Create(ctx, job, metav1.CreateOptions{})

작업이 생성된 후 작업이 완료되었거나 오류가 발생했음을 알리는 신호를 기다립니다. kubectl과 마찬가지로 Client-Go는 리소스를 "감시"하고 변경 시 상태를 관찰하는 유용한 방법을 제공합니다.

// watch selector for the job name on cluster
watch, err := s.clientset.BatchV1().Jobs(ScorecardNamespace).Watch(ctx, metav1.ListOptions{
    FieldSelector: "metadata.name=" + jobName,
})

// continuously pop off the watch results channel for job status
for event := range watch.ResultChan() {
        // wait for job success, error, or other states
}

마지막으로 작업이 성공적으로 완료되면 스코어카드 CLI의 실제 json 결과가 포함된 Job의 Pod 로그에서 결과를 가져올 수 있습니다! 해당 결과가 나오면 점수를 데이터베이스에 다시 삽입하고 필요한 메타데이터를 변경하여 다른 마이크로서비스나 OpenSauced API에 새 점수가 있음을 알릴 수 있습니다.

앞서 언급했듯이 Scorecard-k8s-scheduler는 동시에 실행되는 동시 작업 수에 제한이 없습니다. 프로덕션 환경에서는 한 번에 실행되는 많은 수의 작업이 있으며 모두 이 마이크로서비스에 의해 관리됩니다. 목표는 GitHub의 모든 리포지토리에서 2주마다 점수를 업데이트할 수 있도록 하는 것입니다. 이러한 규모를 통해 우리는 모든 오픈 소스 관리자나 소비자에게 강력한 도구와 통찰력을 제공할 수 있기를 바랍니다!

'스케줄러' 마이크로서비스는 결국 이 전체 시스템의 작은 부분이 됩니다. Kubernetes 컨트롤러에 익숙한 사람이라면 시스템 작동에 필요한 추가 Kubernetes 인프라 부분이 있다는 것을 알고 있습니다. 우리의 경우 마이크로서비스가 클러스터에서 작업을 생성할 수 있도록 하려면 역할 기반 액세스 제어(RBAC)가 필요했습니다.

먼저 서비스 계정이 필요합니다. 이 계정은 스케줄러에서 사용하고 액세스 제어를 바인딩할 계정입니다.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: scorecard-sa
  namespace: scorecard-ns

우리는 이 서비스 계정을 이 모든 것이 실행되는 "scorecard-ns" 네임스페이스에 배치합니다.

다음으로 서비스 계정에 대한 역할과 역할 바인딩이 필요합니다. 여기에는 실제 액세스 제어(작업 생성, 포드 로그 보기 등 포함)가 포함됩니다.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: scorecard-scheduler-role
  namespace: scorecard-ns
rules:
- apiGroups: ["batch"]
  resources: ["jobs"]
  verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list", "watch"]

—

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: scorecard-scheduler-role-binding
  namespace: scorecard-ns
subjects:
- kind: ServiceAccount
  name: scorecard-sa
  namespace: scorecard-ns
roleRef:
  kind: Role
  name: scorecard-scheduler-role
  apiGroup: rbac.authorization.k8s.io

'팟과 팟 로그를 가져오기 위해 이 서비스 계정에 액세스 권한을 부여해야 하는 이유는 무엇인가요? 그것은 접근 통제를 과도하게 확장한 것이 아닌가?” 기억하다! 작업에는 포드가 있으며 스코어카드 CLI의 실제 결과가 포함된 포드 로그를 얻으려면 작업에서 포드를 나열한 다음 해당 로그를 읽을 수 있어야 합니다!

두 번째 부분인 "RoleBinding"은 실제로 역할을 서비스 계정에 연결하는 부분입니다. 그러면 클러스터에서 새 작업을 시작할 때 이 서비스 계정을 사용할 수 있습니다.

Alex Ellis와 그의 뛰어난 실행 작업 컨트롤러에 큰 박수를 보냅니다. 이는 Jobs에서 Client-Go를 올바르게 사용하는 데 큰 영감이자 참고 자료가 되었습니다!

모두들 건성하세요!

위 내용은 Kubernetes 작업을 사용하여 OpenSSF 스코어카드를 확장하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.