티스토리 뷰

728x170

개요

Polaris는 Kubernetes Pod 및 Controller가 모범 사례를 사용하여 구성되었는지 확인하기 위해 다양한 검사를 실행하여 향후 발생 가능한 문제를 사전에 방지하는데 도움을 주는 도구이다.

Polaris는 세 가지 모드로 실행할 수 있다.

  • 대시보드로 클러스터 내에서 실행 중인 항목을 감사할 수 있다.
  • 승인 컨트롤러로서 조직의 정책을 준수하지 않는 워크로드를 자동으로 거부할 수 있다.
  • CLI로 CI/CD 프로세스의 일부로 로컬 YAML 파일을 테스트할 수 있다.

설치

대시보드는 아래와 같이 yaml 파일을 통해 다운로드 받아 설치 할 수 있다. yaml 파일위치는 각 최신 버전을 기준으로 아래 경로에서 다운로드 받을 수 있다.

https://github.com/FairwindsOps/polaris/blob/v5.0.1/deploy/dashboard.yaml

 

GitHub - FairwindsOps/polaris: Validation of best practices in your Kubernetes clusters

Validation of best practices in your Kubernetes clusters - GitHub - FairwindsOps/polaris: Validation of best practices in your Kubernetes clusters

github.com

아래와 같이 대시보드 접근을 위해 Service를 NodePort로 변경하여 반영한다.

apiVersion: v1
kind: Service
metadata:
  name: polaris-dashboard
  namespace: polaris
  labels:
    app: polaris
  annotations:
spec:
  ports:
  - nodePort: 30005
    name: http-dashboard
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: polaris
    component: dashboard
  type: NodePort

반영 및 확인 결과는 아래와 같다.

[root@ip-192-168-84-159 minikube]# kubectl apply -f dashboard.yaml 
namespace/polaris created
serviceaccount/polaris created
clusterrole.rbac.authorization.k8s.io/polaris created
clusterrolebinding.rbac.authorization.k8s.io/polaris-view created
clusterrolebinding.rbac.authorization.k8s.io/polaris created
service/polaris-dashboard created
deployment.apps/polaris-dashboard created
[root@ip-192-168-84-159 minikube]# kubectl get all -n polaris
NAME                                     READY   STATUS    RESTARTS   AGE
pod/polaris-dashboard-6975976fff-hbsm2   1/1     Running   0          76s
pod/polaris-dashboard-6975976fff-hjccm   1/1     Running   0          76s

NAME                        TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
service/polaris-dashboard   NodePort   10.102.7.93   <none>        80:30005/TCP   76s

NAME                                READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/polaris-dashboard   2/2     2            2           76s

NAME                                           DESIRED   CURRENT   READY   AGE
replicaset.apps/polaris-dashboard-6975976fff   2         2         2       76s
[root@ip-192-168-84-159 minikube]#

대시보드 활용

Polaris 대시보드는 Kubernetes 워크로드의 현재 상태에 대한 간단한 시각적 개요와 개선할 수 있는 사항에 대한 로드맵을 얻을 수 있다. 대시보드는 클러스터 전체의 개요를 제공할 뿐만 아니라 범주, 네임스페이스 및 워크로드별로 결과를 분류한다. Polaris 대시보드를 통해 확인 가능한 사항은 아래와 같다.

1) Cluster Overview

먼저 연결되어 있는 Cluster의 상태 Overview를 볼 수 있다. Warning Checks, Dangerous Checks를 기준으로 Grade와 Score을 측정한다.

2) Result by Catagory

측정 결과는 아래 세가지 측면에서 판단한다.

  • Efficiency(효율성) : Kubernetes에서 실행되는 워크로드에 대한 Resource 확인. Resource Request 및 Limit이 설정되어 있는지 여부와 지정된 범위 내에 구성되어 있는지 확인.
  • Reliability(신뢰성) : Kubernetes의 안정성을 위한 구성이 적용되어 있는지 확인.
  • Security(보안성) : Kubernetes에서 제공하는 보안 관련 구성이 적용되어 있는지 확인. 액세스 수준 제한 설정 확인.

Polaris는 Kubernetes 컴퓨팅 리소스의 효율성을 높여 클라우드에서 비용을 절약하거나 데이터 센터에서 용량을 절약할 수 있는 가이드라인을 제시한다.

또한, Kubernetes는 기본적으로 안전하지 않으므로 Polaris는 보안 구성에 대해 여러 클러스터를 지속적으로 모니터링하여 컨테이너 및 Kubernetes의 취약사항을 찾아내, 우선 순위를 지정하고, 조치 방안을 제시한다.

마지막으로 거버넌스를 일관되게 검사하고 적용하여 여러 클러스터에 대한 가시성을 확보한다. 발생 가능한 문제를 진단하여 서비스 중지 시간을 최소화할 수 있다.

3) Filter by Namespace & Namespace

해당 클러스터 내 생성되어 있는 namespace를 지정하여 검사할 수 있다. 각각의 상세 내용은 Namesapce 항목을 펼쳐 확인한다.

위 사항 중 첫번째 Spec: "Only one replica is scheduled"를 해결하고 확인해 보도록 하자. 아래와 같이 replicas를 2로 변경하여 nginx를 기동하고 다시 deployment: my-nginx를 확인해 보도록 하자.

[root@ip-192-168-84-159 minikube]# kubectl get pods
NAME                        READY   STATUS    RESTARTS        AGE
my-nginx-6645fdd559-524kw   1/1     Running   0               4s
my-nginx-6645fdd559-dkj56   1/1     Running   1 (4h15m ago)   12h
[root@ip-192-168-84-159 minikube]#

아래와 같이 Warning이 Spec: Multiple replicas are scheduled로 변경된 것을 확인할 수 있다.

다음으로 Dangerous도 조치를 해보도록 하자. Container my-nginx: "Image tag should be specified"는 Container를 기동하는 Image가 명시되어 있지 않거나, latest를 사용할 경우 변조 가능성이 있으므로 명확한 버전을 명시하라는 경고이다. 아래와 같이 nginx 이미지를 latest에서 1.21.6 버전으로 변경하고 반영한 결과이다.

> deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
    # namespace: app-test
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx:1.21.6
        command: ["/bin/bash"]
        args: ["-c", "echo \"<p>Hello from $(hostname)</p>\" > index.html; sleep 30000 && python -m SimpleHTTPServer 8080"]
        ports:
        - containerPort: 80

> Pod restart

[root@ip-192-168-84-159 minikube]# kubectl get pods
NAME                        READY   STATUS        RESTARTS   AGE
my-nginx-594c77778-274vf    1/1     Terminating   0          113s
my-nginx-594c77778-drjn8    1/1     Terminating   0          109s
my-nginx-7b76897769-ts7p8   1/1     Running       0          7s
my-nginx-7b76897769-z2bn7   1/1     Running       0          11s
[root@ip-192-168-84-159 minikube]#

아래와 같이 Image Tag 관련 사항도 조치된 것을 확인할 수 있다.


Polaris CLI 활용

Polaris CLI는 yaml 파일에 저장된 Kubernetes manifest를 감사하는데 사용할 수 있다. 이는 CI/CD 파이프라인의 일부로 Polaris를 실행하는데 사용할 수 있다. Polaris Score가 특정 임계값 아래로 떨어지거나 Dangerous Check가 발생하는 경우 CI/CD가 실패하도록 처리하여 yaml 파일에 대한 검증을 파이프라인에 통합할 수 있다.

1) Polaris CLI 설치

 wget https://github.com/FairwindsOps/polaris/releases/download/v5.0.1/polaris_linux_amd64.tar.gz

위와 같이 바이너리를 직접 다운로드 받아 압축 해제 후 path에 포함되어 있는 /usr/local로 복사하는 것으로 사용 가능하다.

2) Polaris audit

[root@ip-192-168-84-159 minikube]# polaris audit --help
Runs a one-time audit.

Usage:
  polaris audit [flags]

Flags:
      --audit-path string               If specified, audits one or more YAML files instead of a cluster.
      --color                           Whether to use color in pretty format. (default true)
      --display-name string             An optional identifier for the audit.
  -f, --format string                   Output format for results - json, yaml, pretty, or score. (default "json")
      --helm-chart string               Will fill out Helm template
      --helm-values string              Optional flag to add helm values
  -h, --help                            help for audit
      --only-show-failed-tests          If specified, audit output will only show failed tests.
      --output-file string              Destination file for audit results.
      --output-url string               Destination URL to send audit results.
      --resource string                 Audit a specific resource, in the format namespace/kind/version/name, e.g. nginx-ingress/Deployment.apps/v1/default-backend.
      --set-exit-code-below-score int   Set an exit code of 4 when the score is below this threshold (1-100).
      --set-exit-code-on-danger         Set an exit code of 3 when the audit contains danger-level issues.

Global Flags:
  -c, --config string                    Location of Polaris configuration file.
      --disallow-annotation-exemptions   Disallow any exemption defined as a controller annotation.
      --disallow-config-exemptions       Disallow exemptions set within the configuration file.
      --disallow-exemptions              Disallow any configured exemption.
      --kubeconfig string                Paths to a kubeconfig. Only required if out-of-cluster.
      --log-level string                 Logrus log level. (default "info")
[root@ip-192-168-84-159 minikube]#

위 polaris audit 명령어를 통해 ci/cd pipeline에서 yaml 파일에 대한 검증을 수행할 수 있다. 활용 가능한 옵션으로는

  • --set-exit-code-on-danger : polaris 감사 결과 dangerous check가 있을 경우 exit code 3 return
  • --set-exit-code-below-score : polaris score가 임계치 이하일 경우 exit code 4 return

위 두가지 옵션을 포함하여 권고하는 옵션 조합은 아래와 같다.

[root@ip-192-168-84-159 minikube]# polaris audit --audit-path /root/minikube/deployment.yaml --set-exit-code-on-danger --set-exit-code-below-score 90 --only-show-failed-tests true --format=pretty


Polaris audited Path /root/minikube/deployment.yaml at 2022-03-13T13:37:23Z
    Nodes: 0 | Namespaces: 0 | Controllers: 1
    Final score: 55

Deployment my-nginx
  Container my-nginx
    memoryRequestsMissing                삱 Warning
        Efficiency - Memory requests should be set
    pullPolicyNotAlways                  삱 Warning
        Reliability - Image pull policy should be "Always"
    insecureCapabilities                 삱 Warning
        Security - Container should not have insecure capabilities
    notReadOnlyRootFilesystem            삱 Warning
        Security - Filesystem should be read only
    memoryLimitsMissing                  삱 Warning
        Efficiency - Memory limits should be set
    readinessProbeMissing                삱 Warning
        Reliability - Readiness probe should be configured
    runAsRootAllowed                     Danger
        Security - Should not be allowed to run as root
    cpuLimitsMissing                     삱 Warning
        Efficiency - CPU limits should be set
    privilegeEscalationAllowed           Danger
        Security - Privilege escalation should not be allowed
    cpuRequestsMissing                   삱 Warning
        Efficiency - CPU requests should be set
    livenessProbeMissing                 삱 Warning
        Reliability - Liveness probe should be configured


INFO[0000] 2 danger items found in audit                
[root@ip-192-168-84-159 minikube]#

추가된 옵션은 아래와 같다.

  • --audit-path : 감사 대상 yaml 파일이 저장된 위치이다. 파일명 또는 디렉토리 지정이 가능하다.
  • --only-show-failed-tests : 실패한 테스트만 보여준다.
  • --format=pretty : 포맷을 정돈하여 보여준다.

위와 같이 2 danger items가 확인된 것을 알 수 있다. 해당 명령어 실행 결과를 확인해 보자.

[root@ip-192-168-84-159 minikube]# echo $?
3
[root@ip-192-168-84-159 minikube]#

exit code 3으로 끝난 것을 알 수 있다.

Shell Script 또는 CLI 실행 결과에 대한 결과를 확인하는 exit code에는 Well-Known code가 있다.

  • exit code 0 : Successful completion of the command
  • exit code 1 : General unknown error
  • exit code 2 : Misuse of shell command
  • exit code 126 : The command can't execute
  • exit code 127 : Command not found
  • exit code 128 : Invalid exit argument
  • exit code 128+x : Fatal error with Linux signal x
  • exit code 130 : Command terminated with Ctrl-C
  • exit code 255 : Exit status out of range 

그 밖의 범위는 사용자 정의에 의해 지정하여 사용할 수 있다.

다음으로 --set-exit-code-on-danger 옵션을 빼고 감사 후 결과를 확인해 보자.

[root@ip-192-168-84-159 minikube]# polaris audit --audit-path /root/minikube/deployment.yaml --set-exit-code-below-score 90 --only-show-failed-tests true --format=pretty


Polaris audited Path /root/minikube/deployment.yaml at 2022-03-13T13:42:47Z
    Nodes: 0 | Namespaces: 0 | Controllers: 1
    Final score: 55

Deployment my-nginx
  Container my-nginx
    livenessProbeMissing                 삱 Warning
        Reliability - Liveness probe should be configured
    privilegeEscalationAllowed           Danger
        Security - Privilege escalation should not be allowed
    memoryLimitsMissing                  삱 Warning
        Efficiency - Memory limits should be set
    insecureCapabilities                 삱 Warning
        Security - Container should not have insecure capabilities
    memoryRequestsMissing                삱 Warning
        Efficiency - Memory requests should be set
    notReadOnlyRootFilesystem            삱 Warning
        Security - Filesystem should be read only
    cpuRequestsMissing                   삱 Warning
        Efficiency - CPU requests should be set
    pullPolicyNotAlways                  삱 Warning
        Reliability - Image pull policy should be "Always"
    readinessProbeMissing                삱 Warning
        Reliability - Readiness probe should be configured
    cpuLimitsMissing                     삱 Warning
        Efficiency - CPU limits should be set
    runAsRootAllowed                     Danger
        Security - Should not be allowed to run as root


INFO[0000] Audit score of 55 is less than the provided minimum of 90 
[root@ip-192-168-84-159 minikube]# echo $?
4
[root@ip-192-168-84-159 minikube]#

위와 같이 exit code 4로 끝난 것을 알 수 있다.

--set-exit-code-below-score 90 옵션까지 빼고 감사 후 결과를 확인해 보자.

[root@ip-192-168-84-159 minikube]# polaris audit --audit-path /root/minikube/deployment.yaml --only-show-failed-tests true --format=pretty


Polaris audited Path /root/minikube/deployment.yaml at 2022-03-13T13:43:30Z
    Nodes: 0 | Namespaces: 0 | Controllers: 1
    Final score: 55

Deployment my-nginx
  Container my-nginx
    insecureCapabilities                 삱 Warning
        Security - Container should not have insecure capabilities
    pullPolicyNotAlways                  삱 Warning
        Reliability - Image pull policy should be "Always"
    readinessProbeMissing                삱 Warning
        Reliability - Readiness probe should be configured
    runAsRootAllowed                     Danger
        Security - Should not be allowed to run as root
    livenessProbeMissing                 삱 Warning
        Reliability - Liveness probe should be configured
    cpuLimitsMissing                     삱 Warning
        Efficiency - CPU limits should be set
    cpuRequestsMissing                   삱 Warning
        Efficiency - CPU requests should be set
    privilegeEscalationAllowed           Danger
        Security - Privilege escalation should not be allowed
    memoryLimitsMissing                  삱 Warning
        Efficiency - Memory limits should be set
    memoryRequestsMissing                삱 Warning
        Efficiency - Memory requests should be set
    notReadOnlyRootFilesystem            삱 Warning
        Security - Filesystem should be read only


[root@ip-192-168-84-159 minikube]# echo $?
0
[root@ip-192-168-84-159 minikube]#

위와 같이 exit code가 0으로 성공하는 것을 확인할 수 있다. 이와 같이 dangerous check 발생 여부와 score를 통해 배포 전 CI 단계에서 yaml 파일의 안정성, 신뢰성을 검증할 수 있다.

이를 CI 도구(Jenkins, GitLabCI 등)에서 활용하는 것은 간단한 일이다. exit code가 정해져 있기 때문에 exit code 3 또는 exit code 4가 나올 경우 실패 처리하거나, exit code가 0이 아닌 경우 실패 처리하면 손쉽게 파이프라인을 관리하고, yaml 파일 검증과 CI를 통합할 수 있다.


결론

Polaris에서 권고하는 기본 내장된 RuleSet은 아래에서 확인 가능하다.

https://github.com/FairwindsOps/polaris/tree/master/checks

 

GitHub - FairwindsOps/polaris: Validation of best practices in your Kubernetes clusters

Validation of best practices in your Kubernetes clusters - GitHub - FairwindsOps/polaris: Validation of best practices in your Kubernetes clusters

github.com

때때로 놓치기 쉬운 보안 설정이나, 관리 측면에서 권고하는 여러 모범 사례를 기준으로 가이드라인을 제공해주는 Polaris를 활용하여 보다 안전하고, 활용도 높은 Kubernetes를 구축해 보도록 하자.

그리드형
댓글
댓글쓰기 폼