Kubernetes 클러스터의 업그레이드를 단순히 "버전을 올리는 작업"으로 이해하기 쉽지만, 그 이면에는 꽤 정교한 내부 동작과 절차가 숨어 있습니다. 이 글에서는 kubeadm 설치 환경에서 Kubernetes 업그레이드가 실제로 어떻게 작동하는지, 살펴보며 정리해보겠습니다.

 

Kubernetes는 선언적(Declarative) 시스템입니다. kubeadm upgrade는 단순히 새 바이너리를 덮어씌우는 것이 아니라, 클러스터의 현재 상태를 읽고, 목표 상태로 점진적이고 안전하게 조정해 나갑니다.

 

주요 업그레이드 단계와 내부 로직


1. 현재 상태 평가 (upgrade plan)

  • kubeadm upgrade plan 실행 시, 다음을 수행합니다
    • kubeadm-config ConfigMap을 읽어 현재 버전과 구성 확인
    • kube-apiserver의 version API로 실제 버전 조회
    • 대상 버전과의 호환성 검사
    • CoreDNS, kube-proxy, CNI 등 애드온 호환성 체크

관련코드

- https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/cmd/upgrade/plan.go

 

kubernetes/cmd/kubeadm/app/cmd/upgrade/plan.go at master · kubernetes/kubernetes

Production-Grade Container Scheduling and Management - kubernetes/kubernetes

github.com

실제로 업그레이드 실행은 하지 않고, 업그레이드가 가능한지 점검하고 계획(plan)을 출력하는 역할을 합니다.

kubeadm upgrade plan

이 명령어를 실행하면 아래의 함수가 실행되며 plan로직이 시작되게 됩니다.

 

func NewCmdPlan(...)

 

이 함수는 CLI 커맨드인 kubeadm upgrade plan을 정의합니다.

 

Run: func(cmd *cobra.Command, args []string) {
	err := runUpgradePlan(...)
	// ...
}

해당 커맨드가 실행되면 내부적으로 runUpgradePlan() 함수를 호출합니다

func runUpgradePlan(out io.Writer, flags *apply.PlanFlags) error

이 함수가 실제 plan 로직을 처리합니다. 주요 흐름은 아래와 같습니다

  • upgrade.GetAvailableUpgrades() 호출 → 업그레이드 가능한 버전 목록 조회
  • 현재 상태와 비교하여 업그레이드가 필요한 구성 요소 확인 (API Server, Controller Manager, Scheduler, CoreDNS, kube-proxy 등)
  • 업그레이드 시 어떤 작업이 수행될지 플랜 출력

실제로 업그레이드 가능 버전 계산하는 부분

plans, err := upgrade.GetAvailableUpgrades(...)
func GetAvailableUpgrades(...)

이 함수는

  • 현재 클러스터 상태 확인 (ConfigMap, kubelet, kube-apiserver 등)
  • 업그레이드 가능한 버전 목록을 kubeadm binary 기준으로 계산
  • CoreDNS, kube-proxy, etcd 등 업그레이드 대상 포함 여부 결정

 

실제 업그레이드를 수행하는 코드는?

kubeadm upgrade apply <version>

이 명령어를 실행하면 아래의 함수가 실행되며 apply로직이 시작되게 됩니다.

 

업그레이드는 다음 커맨드에서 수행됩니다

https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/cmd/upgrade/apply.go

 

kubernetes/cmd/kubeadm/app/cmd/upgrade/apply.go at master · kubernetes/kubernetes

Production-Grade Container Scheduling and Management - kubernetes/kubernetes

github.com

func NewCmdApply(...)

 

2. kube-apiserver → controller → scheduler 순으로 static pod 교체

업그레이드 실행 시, 다음과 같은 절차로 static pod를 교체합니다

  • /etc/kubernetes/manifests 경로에 있는 manifest 파일 교체
  • kubelet이 static pod 파일 감지 → 컨테이너 재생성
  • 교체된 프로세스가 readiness 상태로 돌아오면 다음 컴포넌트로 진행

관련코드

- https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/phases/upgrade/staticpods.go 

 

kubernetes/cmd/kubeadm/app/phases/upgrade/staticpods.go at master · kubernetes/kubernetes

Production-Grade Container Scheduling and Management - kubernetes/kubernetes

github.com

func PerformStaticPodUpgrade(...)
  • /etc/kubernetes/manifests/ 경로에 존재하는 static pod manifest들을 새로운 버전으로 교체
  • kubelet이 이 변경을 감지하고 기존 pod 종료 + 새 pod 생성
  • 업그레이드가 정상적으로 완료되었는지 확인 (해당 컴포넌트의 health check 수행)

 

실제 업그레이드 수행 코드

PerformStaticPodUpgrade() 내부의 핵심은 이 부분입니다

err = upgrader.UpgradeComponent(component)

여기서 upgrader는 StaticPodPathManager 인터페이스를 구현한 객체이며, 각 control plane 컴포넌트(kube-apiserver, controller-manager, scheduler)를 업그레이드합니다.

 

UpgradeComponent() 내부에서 어떤 일이?

UpgradeComponent()는 다음과 같은 흐름으로 동작합니다:

  1. 현재 static pod manifest를 백업
  2. 새로운 버전에 맞는 manifest를 생성
  3. 해당 manifest 파일을 /etc/kubernetes/manifests/에 덮어쓰기
  4. kubelet이 감지하여 새 static pod를 실행
  5. 업그레이드 완료되었는지 확인 (health check 또는 readiness probe 등으로)

이 로직은 다음과 같은 함수들을 통해 구성됩니다

  • CreateStaticPodManifestFiles(...)
  • WaitForStaticPodControlPlaneHashChange(...)
  • StaticPodControlPlaneWaiter.WaitForStaticPodSingleHash(...)

 

예를 들어 kube-apiserver 업그레이드 시

  1. /etc/kubernetes/manifests/kube-apiserver.yaml의 내용을 새 버전 기준으로 덮어씀
  2. kubelet이 이를 감지하고 기존 apiserver pod를 종료
  3. 새로 생성된 manifest로 새로운 버전의 kube-apiserver pod 실행
  4. WaitForStaticPodControlPlaneHashChange()로 업그레이드된 Pod의 hash 값이 변경되었는지 확인하여 성공 여부 판단
  5. 이 과정을 kube-controller-manager, kube-scheduler 등 모든 control plane 구성요소에 대해 반복합니다.

 

static pod 교체의 핵심 원리

Kubernetes control plane의 핵심 컴포넌트(apiserver, controller-manager, scheduler)는 static pod로 동작합니다. 업그레이드 시에는 이 static pod의 manifest 파일이 새 버전으로 덮어쓰기되며, kubelet이 이를 감지하여 자동으로 재시작합니다.

/etc/kubernetes/manifests/kube-apiserver.yaml → 변경
└──> kubelet이 detect → 기존 컨테이너 종료 + 새로운 버전으로 시작

이 덕분에 systemd나 외부 툴 없이도 자체적으로 control plane을 self-managed하게 유지할 수 있습니다.

 

3. CoreDNS, kube-proxy 등의 애드온 리소스 업그레이드

  • CoreDNS: Deployment를 patch하거나 recreate
  • kube-proxy: DaemonSet을 rolling update 방식으로 갱신
  • ClusterConfiguration의 필드 비교 후, apply 방식으로 업데이트

관련코드

- https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/phases/addons/dns/dns.go

 

kubernetes/cmd/kubeadm/app/phases/addons/dns/dns.go at master · kubernetes/kubernetes

Production-Grade Container Scheduling and Management - kubernetes/kubernetes

github.com

- https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/phases/addons/proxy/proxy.go

 

kubernetes/cmd/kubeadm/app/phases/addons/proxy/proxy.go at master · kubernetes/kubernetes

Production-Grade Container Scheduling and Management - kubernetes/kubernetes

github.com

 

func EnsureDNSAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset.Interface) error {
	// ...
	return coreDNS.EnsureDNSAddon(cfg, client)
}

 

func EnsureProxyAddon(cfg *kubeadmapi.ClusterConfiguration, client clientset.Interface) error {
	// ...
	return proxyaddon.EnsureProxyAddon(cfg, client)
}

 

4. kubelet, kubectl은 별도 수동 업그레이드

  • 바이너리 교체 및 systemctl restart kubelet 필요
  • 노드별 kubeadm upgrade node 명령으로 kubelet 설정 업데이트
  • 업그레이드된 kubelet은 새 control plane과 통신하면서 정상 상태 유지

 

etcd는 언제 업그레이드될까?


  • etcd는 kubeadm-config에 명시된 버전에 따라 업그레이드됩니다.
  • 단독 실행 중이면 외부 관리 필요 (kOps, kubeadm 외)
  • embedded etcd일 경우 static pod로 관리되며 다른 컴포넌트와 동일 방식으로 교체

 

kubeadm 업그레이드 흐름


etcd snapshot
└──> 업그레이드 전 백업(선택사항)

kubeadm upgrade plan
└──> 현재 상태 + kubeadm-config + version API 분석

kubeadm upgrade apply v1.31.1
├── static pod 교체 (/etc/kubernetes/manifests)
├── CoreDNS, kube-proxy patch
└── kubeadm-config 업데이트

 

정리


Kubernetes의 업그레이드는 단순히 “버전 교체”가 아니라, 클러스터의 상태를 확인하고 각 구성요소를 안정적으로 교체하는 과정입니다. kubeadm은 이러한 과정을 단계적 절차를 거치는 메커니즘을 통해 안전하게 업그레이드를 수행하고 있다는 것을 알아보았습니다.

 

실제 운영환경에서는 주기적인 버전 업그레이드 작업이 필요하게 됩니다. 본 글을 통해 업그레이드 과정시에 조금이나마 도움이 되셨으면 좋겠습니다.

개요


Kubernetes 클러스터를 운영하다 보면 다양한 보안 구성 요소들이 작동하는 것을 확인할 수 있습니다. 특히, 클러스터 내부의 모든 구성 요소들은 서로 TLS 인증서를 기반으로 통신하며, 이 인증서들은 일정한 주기로 교체되어야 합니다.

하지만 인증서의 유효 기간이 다가오는 것을 모르고 방치하거나, 갱신 과정을 잘못 수행하면 kubelet이 클러스터에 연결되지 않거나, kubectl 명령어가 동작하지 않는 문제가 발생할 수 있습니다. 이런 문제를 방지하기 위해, Kubernetes에서 인증서가 어떻게 생성되고 언제, 어떤 방식으로 교체되는지를 이해하는 것은 매우 중요합니다.

이 글에서는 Kubernetes의 인증서 구조부터 시작하여, 자동으로 갱신되는 인증서와 수동으로 갱신해야 하는 인증서의 차이, 인증서 갱신 명령어, 실습 예제까지 자세히 알아보겠습니다.

 

Kubernetes에서 인증서가 사용되는 곳


Kubernetes는 클러스터 내 모든 통신을 TLS로 암호화하여 보안을 강화합니다. 대표적으로 아래와 같은 컴포넌트 간 통신에서 인증서가 사용됩니다.

  • kube-apiserver ↔ kube-controller-manager / kube-scheduler / etcd
  • kubelet ↔ kube-apiserver
  • kubectl ↔ kube-apiserver
  • webhook admission controller ↔ kube-apiserver

이러한 통신에서 각 컴포넌트는 서버 인증서와 클라이언트 인증서를 사용하여 신뢰를 검증하고 통신을 허용합니다.

예를 들어 kubectl이 kube-apiserver에 접근할 때는 클라이언트 인증서를 이용하여 신원을 증명하며, 반대로 apiserver는 서버 인증서로 자신을 증명합니다.

 

Kubernetes 인증서 구조 이해하기


Kubernetes에서 인증서를 생성하고 저장하는 기본 경로는 다음과 같습니다.

/etc/kubernetes/pki

 

이 경로에는 여러 인증서와 프라이빗 키들이 존재하며, 주요 파일은 다음과 같습니다.

 

파일명 설명
ca.crt / ca.key 클러스터의 Root CA 인증서와 키
apiserver.crt / apiserver.key kube-apiserver용 서버 인증서
apiserver-kubelet-client.crt kube-apiserver가 kubelet에 접근할 때 사용하는 인증서
front-proxy-ca.crt / front-proxy-client.crt Aggregation layer용 인증서
etcd/server.crt / etcd/peer.crt 등 etcd 서버 간 통신용 인증서

 

Kubernetes를 kubeadm으로 설치할 경우, 이러한 인증서들은 kubeadm init 명령어 실행 시 자동으로 생성되며, 기본적으로 1년의 유효 기간을 갖습니다.

 

인증서 갱신의 원리


인증서가 만료되면 Kubernetes 컴포넌트 간 통신에 문제가 생기므로, 사전에 갱신이 필요합니다. Kubernetes에서는 일부 인증서는 자동으로 갱신되고, 일부는 관리자가 수동으로 갱신해야 합니다.

 

자동으로 갱신되는 인증서

  • kubelet client 인증서는 자동 갱신됩니다.
  • kubelet에 --rotate-certificates=true 설정이 되어 있으면, kubelet은 유효 기간이 80% 경과한 시점부터 새로운 인증서를 요청하고 갱신합니다.
  • 인증서 갱신 요청은 kubelet이 kube-apiserver에 요청하고, certificates.k8s.io API를 통해 처리됩니다.
  • 해당 인증서는 보통 다음 위치에 저장됩니다:
/var/lib/kubelet/pki/kubelet-client-current.pem

 

수동으로 갱신해야 하는 인증서

아래 인증서들은 kubeadm을 사용하는 클러스터에서 수동으로 갱신해야 합니다.

  • apiserver.crt
  • apiserver-kubelet-client.crt
  • front-proxy-client.crt
  • etcd 관련 인증서 등

갱신은 kubeadm 명령어를 사용하여 수행할 수 있습니다.

kubeadm certs renew all
systemctl restart kubelet

 

갱신 전 인증서의 유효 기간을 확인하려면 아래 명령어를 사용할 수 있습니다.

kubeadm certs check-expiration

 

인증서 유효 기간과 교체 타이밍


Kubernetes 클러스터의 인증서는 대부분 유효 기간이 존재하며, 이 기간이 지나면 더 이상 해당 인증서를 사용할 수 없게 됩니다. 인증서가 만료되면 API 서버 접근 실패, 노드 등록 해제, etcd 통신 실패 등 다양한 문제가 발생할 수 있으므로, 사전에 주기적인 확인과 갱신 작업이 필요합니다.

 

자동 교체 타이밍 (kubelet)

Kubernetes에서 자동으로 인증서를 갱신하는 대표적인 컴포넌트는 kubelet입니다.

  • kubelet은 기본적으로 인증서 유효 기간이 50% 경과했을 때 갱신을 시도합니다.
  • 실제 갱신은 유효 기간의 80%가 경과한 시점에서 수행됩니다.
  • 예를 들어 1년짜리 인증서라면, 약 292일(365일 × 0.8) 경과 시점에서 자동 갱신이 발생합니다.
  • kubelet 로그에서 갱신 관련 메시지를 확인할 수 있습니다:
journalctl -u kubelet | grep certificate
certificate rotation is enabled
rotated certificate successfully
 

수동 인증서의 갱신 시기 판단

Control Plane의 인증서는 자동 갱신되지 않기 때문에, 관리자가 직접 유효 기간을 확인하고 갱신 시점을 결정해야 합니다.

이를 위해 kubeadm은 편리한 점검 명령어를 제공합니다.

kubeadm certs check-expiration

 

예시 출력:

CERTIFICATE                EXPIRES                  RESIDUAL TIME   CERTIFICATE AUTHORITY
admin.conf                 Mar 29, 2025 14:30 UTC   300d            ca
apiserver                  Mar 29, 2025 14:32 UTC   300d            ca
etcd/peer                  Mar 29, 2025 14:34 UTC   300d            etcd-ca

 

인증서 교체를 정기적으로 점검하는 팁

  • 월간 또는 분기별로 kubeadm certs check-expiration 결과를 CI/CD 또는 CronJob으로 점검
  • 만료까지 30일 미만인 경우 슬랙/메일 등으로 알림 전송
  • 기업 환경에서는 Ansible, Terraform 등 IaC 도구와 통합하여 자동화 가능

 

cert-manager를 이용한 인증서 자동화


앞서 설명한 kubeadm certs renew 방식은 수동으로 인증서를 갱신해야 한다는 단점이 있습니다. 클러스터 규모가 커지거나 다양한 어플리케이션이 TLS 인증서를 사용하는 경우, 인증서를 자동으로 발급하고 주기적으로 갱신해주는 시스템이 필요합니다.

이때 사용되는 대표적인 도구가 바로 cert-manager입니다.

 

cert-manager란?

https://cert-manager.io/

 

cert-manager

Cloud native X.509 certificate management for Kubernetes and OpenShift

cert-manager.io

 

cert-manager는 Kubernetes 상에서 X.509 인증서 및 인증서 발급자를 관리하는 컨트롤러입니다. 다음과 같은 기능을 제공합니다.

  • ACME (예: Let's Encrypt)를 통한 무료 TLS 인증서 발급
  • CA 서버 또는 내부 Root CA를 통한 인증서 발급
  • Kubernetes 리소스로 인증서를 선언적(Declarative)으로 관리
  • 자동 갱신 (예: 30일 전 자동 갱신)
  • webhook, ingress, gateway 등 다양한 리소스에 자동 연결

 

cert-manager 구조

cert-manager는 아래와 같은 구성 요소로 이루어져 있습니다.

구성 요소 설명
Issuer / ClusterIssuer 인증서를 발급해줄 주체를 정의 (ACME, SelfSigned, CA 등)
Certificate 발급할 인증서의 정의 (common name, duration 등)
CertificateRequest 실제 인증서 발급 요청 (자동 생성됨)
Secret 발급된 인증서와 키가 저장되는 Kubernetes Secret

 

cert-manager 설치 방법

cert-manager는 Helm 또는 YAML 매니페스트로 설치할 수 있습니다. 가장 간단한 설치 방법은 다음과 같습니다.

# CRDs 먼저 설치
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.17.1/cert-manager.crds.yaml

# cert-manager 설치
helm repo add jetstack https://charts.jetstack.io
helm repo update

helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.17.1

설치 후 아래 리소스를 확인합니다:

kubectl get pods -n cert-manager

 

사용 예시 1: SelfSigned 인증서 자동 발급

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: selfsigned-issuer
spec:
  selfSigned: {}
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: example-cert
  namespace: default
spec:
  secretName: example-tls
  duration: 90d
  renewBefore: 15d
  issuerRef:
    name: selfsigned-issuer
    kind: ClusterIssuer
  commonName: example.default.svc.cluster.local
  dnsNames:
    - example.default.svc.cluster.local

위와 같이 선언하면 cert-manager가 자동으로 인증서를 생성하고, /etc/ssl/certs 대신 Kubernetes Secret에 저장합니다. 서비스나 Ingress, Gateway 등에서 쉽게 참조할 수 있습니다.

 

사용 예시 2: Let's Encrypt를 활용한 HTTPS Ingress 자동화

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: your-email@example.com
    privateKeySecretRef:
      name: letsencrypt-prod-key
    solvers:
    - http01:
        ingress:
          class: nginx

이후 Ingress 리소스에 다음과 같이 주석을 달면 cert-manager가 HTTPS 인증서를 자동으로 발급합니다.

 

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  tls:
  - hosts:
    - myapp.example.com
    secretName: myapp-tls
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-app-svc
            port:
              number: 80

 

cert-manager의 자동 갱신 원리

cert-manager는 Certificate 리소스의 renewBefore 필드에 따라, 인증서 만료 시점보다 앞서 자동으로 재발급을 시도합니다. 기본값은 30일 전, 설정에 따라 조절 가능합니다.

또한, 문제가 발생하면 CertificateRequest, Events, Conditions 필드를 통해 상세한 원인 분석이 가능합니다.

kubectl describe certificate example-cert
kubectl describe certificaterequest -n default

 

정리


Kubernetes는 자체적으로 다양한 인증서 기반 보안 체계를 가지고 있으며, 이 인증서들은 클러스터의 신뢰성과 보안성 유지에 핵심적인 역할을 합니다. 운영 환경에서 인증서 만료는 심각한 장애를 유발할 수 있습니다. API 서버가 응답하지 않거나, 노드가 분리되거나, 서비스 간 통신이 실패하는 일이 발생할 수 있기 때문입니다. 이러한 리스크를 사전에 방지하려면 정기적인 인증서 관리 체계가 반드시 필요합니다.

또한 cert-manager와 같은 도구를 도입하면, 운영자의 수고를 줄이고 보안성을 자동으로 유지할 수 있는 기반을 마련할 수 있습니다.

 

운영 환경에서 발생하는 인증서 관리는 아주 중요한 역할을 하고있습니다. 본 글에서 다룬 내용들이 실무 운영대응에도 도움이 되셨으면 좋겠습니다.

Kubernetes 환경에서 Pod가 갑작스럽게 종료되며 OOMKilled 상태가 되는 경우, 운영자 입장에서는 당황할 수밖에 없습니다. 이는 단순한 에러 로그가 아니라, 리소스 설정 미스 혹은 애플리케이션의 과도한 메모리 사용이 불러온 중요한 징후입니다.

이 글에서는 OOMKilled의 발생 원리부터, 원인 분석, 그리고 재발 방지를 위한 설정 팁까지 다뤄보겠습니다.

 

OOMKilled란 무엇인가?


OOMKilled는 Out Of Memory Killed의 약자로, 컨테이너가 할당받은 메모리 한도(memory limit)를 초과하여 종료된 상태를 의미합니다.

Kubernetes는 컨테이너 실행 시 설정한 memory limit 값보다 메모리를 더 사용하면, cgroup 제한에 의해 커널이 해당 프로세스를 강제로 종료시킵니다. 이 때 Pod는 OOMKilled 상태로 기록됩니다.

kubectl get pod my-app-123 -o json | jq '.status.containerStatuses[].lastState.terminated'
{
  "reason": "OOMKilled",
  "exitCode": 137,
  ...
}

 

왜 OOMKilled가 발생할까?


  1. 리소스 제한 설정이 너무 낮은 경우
    • 개발 환경에서 무심코 설정한 낮은 limit 값이 실제 서비스 상황에서 부족해짐
  2. 메모리 누수(Memory Leak)
    • 애플리케이션의 메모리 해제가 정상적으로 이뤄지지 않아 사용량이 지속 증가
  3. 버스트 트래픽/비정상 입력
    • 특정 입력이나 이벤트로 인해 일시적으로 과도한 메모리 소비 발생
  4. Limit 설정은 했지만 Request는 안 한 경우
    • CPU는 공유되지만, 메모리는 강제 제한됨 → 예상보다 적은 메모리로 실행됨
  5. JVM 기반 앱의 heap 설정 누락
    • Java 앱에서 -Xmx 없이 실행하면, 전체 메모리를 heap으로 쓰려고 시도

 

OOMKilled 문제 진단 방법


1. Pod 상태 확인

kubectl describe pod <pod-name>
  • 이벤트 로그에서 OOMKilled 여부 확인

2. 리소스 사용량 확인

  • 모니터링 도구 활용 -> Prometheus/Grafana 등을 활용
kubectl top pod <pod-name>
  • 리소스 peak 시점 기록 여부 확인

3. 로그 및 내부 상태 분석

  • 애플리케이션 로그 확인 (메모리 누수 의심)
  • 필요시 컨테이너 쉘 접속하여 ps, top 등으로 메모리 사용량 추적

 

해결 방법과 재발 방지 팁


1. 적절한 리소스 설정 (Request / Limit)

resources:
  requests:
    memory: "256Mi"
  limits:
    memory: "512Mi"
  • 너무 작게 잡으면 잦은 OOM, 너무 크면 노드 낭비 → 실제 사용량 기반으로 조정

2. JVM 기반 앱이라면 heap 제한 필수

JAVA_OPTS="-Xms128m -Xmx256m"
  • Container limit보다 JVM heap이 커지면 바로 OOM 발생

3. VPA (Vertical Pod Autoscaler) 도입 고려

  • 애플리케이션의 메모리 사용량을 학습해 자동으로 Request/Limit을 조정

4. 메모리 누수 점검

  • Go, Node.js, Java 등에서 누수 탐지 도구 활용 (e.g., pprof, heap dump)

5. 모니터링 설정

  • 메모리 사용량에 대한 알람 설정
  • OOMKilled 발생 시 자동 Slack/이메일 알림

 

정리


Pod의 OOMKilled는 단순 종료가 아니라 운영 환경이 감당하지 못하는 워크로드가 발생했음을 나타내는 신호입니다. 이는 곧 시스템의 신뢰성과 사용자 경험에 영향을 미칠 수 있기 때문에, 정확한 분석과 대응이 필수입니다.

리소스 설정, 모니터링, 애플리케이션의 메모리 효율 개선을 통해 운영환경에서 최적의 방법을 찾으시면 도움이 될 것이라고 생각합니다. 

개요


Kubernetes에서 kubectl get nodes 명령을 실행했을 때 특정 노드가 NotReady 상태로 표시되는 경우가 있습니다. 이는 노드가 정상적으로 클러스터에 참여하지 못하고 있으며, 해당 노드에서 실행 중인 워크로드에도 영향을 미칠 수 있음을 의미합니다.

이 글에서는 NotReady 상태가 발생하는 주요 원인과 해결 방법을 정리하여, Kubernetes 운영 시 문제를 신속하게 진단하고 복구하는데 도움이 되셨으면 합니다.

 

NotReady 상태가 발생하는 경우


Kubelet 프로세스 이상

원인: Kubelet 프로세스가 충돌했거나 중지됨

확인 방법:

systemctl status kubelet
journalctl -u kubelet --no-pager | tail -n 20

설명: Kubelet이 실행되지 않으면 노드가 상태를 클러스터에 보고하지 못하여 NotReady가 됩니다.

 

네트워크 연결 문제

원인: 마스터 노드와의 네트워크 단절, CNI 플러그인 오류

확인 방법:

ping <node-ip>
kubectl get pods -n kube-system -o wide | grep calico #calico, cilium 등, CNI 플러그인 확인.

설명: API 서버와의 통신이 불가능하면 노드가 NotReady 상태가 됩니다.

 

디스크 공간 부족

원인: 디스크 공간이 가득 차서 Kubelet이 실행되지 못함

확인 방법:

df -h
kubectl describe node <node-name> | grep "DiskPressure"

설명: 디스크 압박(DiskPressure)이 발생하면 노드는 NotReady 상태가 됩니다.

 

CPU/메모리 부족

원인: 과부하로 인해 노드 리소스 부족

확인 방법:

kubectl describe node <node-name> | grep -E "MemoryPressure|PIDPressure"
top

설명: MemoryPressure가 감지되면 노드가 NotReady 상태가 될 수 있습니다.

 

컨트롤 플레인 문제

원인: kube-apiserver 또는 etcd 장애, kube-proxy 오류

확인 방법:

kubectl get pods -n kube-system | grep -E "etcd|kube-apiserver|kube-proxy"

설명: 컨트롤 플레인과 연결되지 않으면 노드가 NotReady 상태가 됩니다.

 

인증서 만료 문제

원인: Kubelet 인증서(/var/lib/kubelet/pki/kubelet-client.crt) 또는 API 서버 인증서 만료

확인 방법:

openssl x509 -in /var/lib/kubelet/pki/kubelet-client.crt -noout -enddate

설명: Kubernetes의 kubelet 및 API 서버는 인증서를 사용하여 상호 인증을 수행합니다. 인증서가 만료되면 kubelet이 API 서버와 통신할 수 없어 노드가 NotReady 상태가 됩니다.

 

해결 방법


Kubelet 재시작

systemctl restart kubelet

 

네트워크 문제 해결

마스터 노드와의 연결 확인:

ping <master-node-ip>

 

CNI 플러그인 재설정:

kubectl delete pod <cni-pod-name> -n kube-system

 

방화벽 규칙 확인:

iptables -L -v -n

 

디스크 정리

해결 예시: 디스크를 차지하고 있는 로그 삭제

rm -rf /var/log/*.log

 

리소스 최적화

해결 예시: 리소스를 많이 차지하고 있는 Pod 삭제 

kubectl top pod -A
kubectl delete pod <pod-name> -n <namespace>

 

컨트롤 플레인과 연결 문제 해결

해결 예시: kube-proxy 연결 재시작

systemctl restart kube-proxy

 

인증서 갱신 및 재시작

인증서의 갱신과정은 설치한 k8s 방법(kubeadm, kubespary 등)에 따라 다를 수 있으며 아래의 내용은 참고사항입니다.

 

인증서 수동 갱신:

kubeadm certs renew all
systemctl restart kubelet

 

kubelet 인증서 갱신:

systemctl stop kubelet
rm -f /var/lib/kubelet/pki/kubelet-client.*
systemctl start kubelet

kubelet이 API 서버와 다시 연결되면서 새로운 인증서를 자동으로 요청합니다.

 

정리


Kubernetes에서 노드가 NotReady 상태가 되는 주요 원인은 Kubelet 오류, 네트워크 문제, 디스크 및 리소스 부족, 컨트롤 플레인 장애, 그리고 인증서 만료 등입니다. 원인을 신속하게 파악하고 적절한 조치를 취하면 클러스터의 안정성을 유지할 수 있습니다.

빠른 점검 체크리스트

    1. systemctl status kubelet 확인 (Kubelet 상태 점검)
    2. ping <master-node-ip> (네트워크 연결 점검)
    3. df -h (디스크 용량 확인)
    4. kubectl describe node <node-name> (리소스 상태 및 인증서 만료 여부 확인)
    5. kubectl get pods -n kube-system (kube-system namespace 내부 컴포넌트 정상 동작 여부 확인)

 

위 체크리스트를 활용하여 문제를 빠르게 해결하고, 클러스터 운영 중 NotReady 상태가 발생하더라도 신속하게 대응할 수 있도록 준비하는 것이 중요합니다.

개요


Kubernetes에서 Pod를 생성하면 정상적으로 실행(Running)되거나 오류로 인해 실패(Failed)하는 경우가 있습니다. 그러나 때때로 Pod가 Pending 상태에서 멈춰있는 경우가 발생합니다. Pending 상태는 일반적으로 노드에서 Pod가 실행될 준비가 완료되지 않았음을 의미합니다. 본 글에서는 Pod가 Pending 상태에 머무르는 주요 원인과 해결 방법에 대해서 알아보고자 합니다.

 

Pending 상태란?


Kubernetes에서 Pending 상태는 Pod가 스케줄링되지 않았거나, 컨테이너가 아직 시작되지 않은 상태를 의미합니다. kubectl get pods 명령어를 실행했을 때 STATUS 필드가 Pending으로 나타날 수 있습니다.

kubectl get pods

 

출력 예시:

NAME           READY   STATUS    RESTARTS   AGE
my-pod         0/1     Pending   0          5m

Pod가 Pending 상태로 남아있는 경우, 다음과 같은 주요 원인들을 확인해야 합니다.

 

Pending 상태의 주요 원인과 해결 방법


적절한 노드가 없음 (Insufficient Resources)

원인:

  • 클러스터 내에서 사용할 수 있는 CPU, 메모리 등의 리소스가 부족하여 Pod가 배치되지 못하는 경우.
  • 특정 노드에만 할당하도록 설정했는데 해당 노드의 리소스가 부족한 경우.

확인 방법:

kubectl get pods -n kube-system

 

출력 예시:

Events:
  Type     Reason             Age   From               Message
  ----     ------             ----  ----               -------
  Warning  FailedScheduling   2m    default-scheduler  0/3 nodes are available: 3 Insufficient cpu.

 

해결 방법:

  • 클러스터의 리소스 사용량 확인 (kubectl top nodes)
  • 노드 추가 또는 기존 노드의 리소스 증가
  • Pod의 리소스 요청 줄이기 (spec.containers.resources.requests 설정 수정)

예시 (deployment.yaml):

resources:
  requests:
    cpu: "500m"
    memory: "256Mi"
  limits:
    cpu: "1000m"
    memory: "512Mi"

 

노드 셀렉터(Node Selector) 또는 테인트(Taint) 문제

원인:

  • Pod에 특정 노드에만 배치되도록 nodeSelector가 설정되었으나, 해당 노드가 존재하지 않거나 스케줄링이 불가능한 경우.
  • 노드에 Taint가 설정되어 있어 Pod가 해당 노드에 배치되지 못하는 경우.

확인 방법:

kubectl describe pod my-pod

 

출력 예시:

Events:
  Type     Reason             Age   From               Message
  ----     ------             ----  ----               -------
  Warning  FailedScheduling   1m    default-scheduler  0/3 nodes available: node(s) had taint {key=value: NoSchedule}.

 

해결 방법:

  1. nodeSelector 설정 확인 (kubectl get nodes --show-labels)
  2. 필요하다면 kubectl taint nodes 명령어로 taint 제거:
kubectl taint nodes node-name key=value:NoSchedule-

 

PersistentVolume (PV) 및 Storage 문제

원인:

  • Pod가 PersistentVolumeClaim(PVC)을 요청했으나, 적절한 PersistentVolume이 할당되지 않은 경우.
  • 동적 볼륨 프로비저닝(dynamic provisioning)이 실패한 경우.

확인 방법:

kubectl get pvc

 

출력 예시:

NAME        STATUS    VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
my-volume   Pending                                       standard       5m

 

해결 방법:

  • 적절한 StorageClass가 존재하는지 확인 (kubectl get storageclass)
  • 수동으로 PersistentVolume을 생성하여 PVC와 매칭

 

이미지 다운로드 지연 (Image Pull Error)

원인:

  • 컨테이너 이미지가 존재하지 않거나, Docker Hub 또는 프라이빗 레지스트리에서 다운로드가 실패한 경우.
  • 네트워크 문제로 인해 이미지 다운로드가 오래 걸리는 경우.

확인 방법:

kubectl describe pod my-pod

 

출력 예시:

Events:
  Type     Reason             Age   From               Message
  ----     ------             ----  ----               -------
  Warning  Failed             30s   kubelet            Failed to pull image "my-private-registry/my-app": image not found

 

해결 방법:

  • 컨테이너 이미지 태그 확인 (kubectl get pod my-pod -o yaml)
  • 프라이빗 레지스트리 인증 필요 시, imagePullSecrets 설정
  • 노드에서 수동으로 이미지 다운로드 가능 여부 확인 (docker pull <image> 또는 crictl pull <image> 실행)

 

네트워크 정책 및 CNI 문제

원인:

  • CNI(Container Network Interface) 플러그인이 정상적으로 동작하지 않는 경우.
  • 네트워크 정책(NetworkPolicy)으로 인해 Pod의 통신이 차단된 경우.

확인 방법:

kubectl get pods -n kube-system

출력 예시:

NAME                                       READY   STATUS             RESTARTS   AGE
coredns-66bff467f8-8c9jk                   0/1     CrashLoopBackOff   5          10m
calico-node-h5s7t                          0/1     CrashLoopBackOff   5          10m

 

해결 방법:

  • CNI 플러그인 재설치 (kubectl get ds -n kube-system 확인 후 재배포)
  • kubectl logs -n kube-system <cni-pod>로 로그 확인
  • 네트워크 정책 수정하여 Pod 간 통신 가능하도록 설정

 

정리


Kubernetes에서 Pod가 Pending 상태로 멈춰 있는 경우, 다음과 같은 주요 원인을 확인해야 합니다.

원인 확인 방법 해결 방법
리소스 부족 kubectl describe pod 리소스 추가, 요청량 조정
노드 제약 조건 kubectl get nodes --show-labels nodeSelector 수정, taint 제거
PVC 문제 kubectl get pvc 올바른 PV 제공
이미지 다운로드 실패 kubectl describe pod 이미지 태그 확인, imagePullSecrets 설정
CNI 네트워크 문제 kubectl get pods -n kube-system CNI 플러그인 확인 및 재설치

 

 

운영 환경에서는 Pod가 Pending 상태인 경우를 자주 맞이하게 됩니다. 당장 Pending 상태라면 위의 체크리스트를 하나씩 확인하고 적절한 조치를 취하면 해결하는데 도움이 될 수 있을 것 입니다.

개요



Kubernetes를 운영하면서 가장 자주 마주하는 이슈 중 하나가 CrashLoopBackOff입니다. 이 글에서는 CrashLoopBackOff가 발생하는 이유를 살펴보고, 그중 컨테이너 이미지 태그 오류로 인해 발생하는 사례를 재현하여 분석해 보겠습니다.


CrashLoopBackOff란?



CrashLoopBackOff는 Kubernetes에서 특정 Pod가 지속적으로 충돌(Crash)하여 재시작을 반복하는 상태를 의미합니다. 일반적으로 Pod가 실행되었다가 비정상적으로 종료되면, kubelet은 이를 다시 시작하려고 합니다. 하지만 계속해서 실패하면 일정 시간 동안 재시도 간격을 늘려가며 CrashLoopBackOff 상태를 반복하게 됩니다.

 

발생 가능한 원인


CrashLoopBackOff가 발생하는 주요 원인은 다음과 같습니다.

  • 잘못된 컨테이너 이미지 태그: 이미지 레지스트리에서 해당 태그를 찾을 수 없음
  • 애플리케이션 내부 오류: 코드 버그, 의존성 문제, 환경 변수 설정 오류
  • 권한 문제: 애플리케이션이 실행되기 위한 권한 부족
  • 네트워크 문제: 외부 서비스와의 통신 실패로 인해 앱이 종료됨
  • OOMKilled(Out of Memory): 컨테이너가 메모리 초과로 종료됨
  • Liveness Probe 실패: Kubernetes가 컨테이너가 비정상적으로 동작한다고 판단하여 재시작함

이번 글에서는 "잘못된 컨테이너 이미지 태그"로 인해 CrashLoopBackOff가 발생하는 시나리오를 다뤄보겠습니다.

잘못된 컨테이너 이미지 태그로 인해 CrashLoopBackOff 발생


잘못된 이미지 태그를 가진 Deployment 생성

아래의 Deployment 파일을 보면 image: nginx:invalid-tag라는 존재하지 않는 태그를 사용하고 있습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:invalid-tag  # 존재하지 않는 태그
        ports:
        - containerPort: 80

 

 

이제 이 Deployment를 생성합니다.

kubectl apply -f nginx-deployment.yaml

 

Pod 상태 확인

Deployment를 생성한 후 Pod 상태를 확인하면 다음과 같이 ImagePullBackOff 또는 ErrImagePull 상태가 나타납니다.

kubectl get pods

 

출력 예시:

NAME                                 READY   STATUS             RESTARTS   AGE
nginx-deployment-5d4b5b4b7f-abcde    0/1     ImagePullBackOff   0          1m

 

이후 Kubernetes가 지속적으로 재시도를 하다가 일정 시간이 지나면 CrashLoopBackOff 상태로 전환됩니다.

kubectl describe pod nginx-deployment-5d4b5b4b7f-abcde

 

출력 예시:

Events:
  Type     Reason             Age                From               Message
  ----     ------             ----               ----               -------
  Normal   Scheduled          2m                 default-scheduler  Successfully assigned default/nginx-deployment-5d4b5b4b7f-abcde to node01
  Normal   Pulling            2m                 kubelet            Pulling image "nginx:invalid-tag"
  Warning  Failed             2m                 kubelet            Failed to pull image "nginx:invalid-tag": rpc error: code = NotFound desc = failed to pull and unpack image "nginx:invalid-tag"
  Warning  Failed             2m                 kubelet            Error: ErrImagePull
  Normal   BackOff            1m (x3 over 2m)    kubelet            Back-off pulling image "nginx:invalid-tag"
  Warning  Failed             1m                 kubelet            Error: ImagePullBackOff

 

해결 방법


1. 컨테이너 이미지 태그 확인

  • 올바른 태그를 사용하고 있는지 체크합니다.
  • 사용 가능한 태그 목록은 공개된 컨테이너 이미지 레지스트리 또는 프라이빗 컨테이너 이미지 레지스트리에서 확인할 수 있습니다.
docker pull nginx:latest

사용가능한 이미지와 태그를 Docker Hub를 통해 받아옵니다.

 

2. Deployment 수정 nginx:latest 또는 기존에 존재하는 태그로 변경하고, 다시 배포합니다.

containers:
- name: nginx
  image: nginx:latest  # 존재하는 태그로 변경
kubectl apply -f nginx-deployment.yaml

 

3. Pod 삭제 및 재시작 기존 Pod를 삭제하고 새로운 Pod를 배포합니다.
kubectl delete pod nginx-deployment-5d4b5b4b7f-abcde
 

Kubernetes가 새롭게 생성하는 Pod에서 정상적으로 이미지가 받아지면 문제가 해결됩니다.

 

4. 프라이빗 레지스트리 사용 시 인증 확인 만약 내부 레지스트리를 사용한다면, 인증 문제가 원인일 수도 있습니다. 해당 경우, imagePullSecrets을 추가하여 해결할 수 있습니다.

spec:
  imagePullSecrets:
  - name: my-registry-secret

 

정리


CrashLoopBackOff는 Kubernetes에서 흔히 발생하는 문제 중 하나이며, 여러 가지 원인으로 인해 발생할 수 있습니다. 이번 글에서는 컨테이너 이미지 태그 오류로 인해 발생하는 CrashLoopBackOff 문제를 분석하고 해결하는 방법을 살펴보았습니다.

Kubernetes 환경에서 CrashLoopBackOff가 발생하면 다음을 확인해보셔야 합니다.

  • kubectl describe pod <POD_NAME> 명령어로 이벤트 로그 분석
  • kubectl logs <POD_NAME> 명령어로 컨테이너 로그 확인
  • kubectl get events 명령어로 클러스터 이벤트 체크

운영 환경에서 발생하는 CrashLoopBackOff는 다양한 원인으로 발생할 수 있으므로, 본 글에서 다룬 내용들이 빠르게 대응하는데 도움이 되셨으면 좋겠습니다.

개요


Kubernetes를 운영하면서 가장 자주 사용하는 CLI 도구가 바로 kubectl입니다. 하지만 kubectl get pods와 같은 명령어를 실행했을 때, 실제로 어떤 과정이 일어나고, etcd에서 데이터가 어떻게 조회되는지에 대해 한번쯤은 궁금하게 되는데요. 본 글에서는 kubectl의 내부 동작을 탐구하며, 명령어가 실행되는 과정부터 etcd에서 데이터를 읽어오는 방식까지 자세히 알아보겠습니다.
 

Kubectl의 기본 동작


kubectl은 Kubernetes API 서버와 통신하여 클러스터의 상태를 조회하거나 리소스를 조작하는 역할을 합니다. 기본적인 동작 방식은 다음과 같습니다.
  1. 사용자가 kubectl 명령어를 입력합니다.
  2. kubectl은 ~/.kube/config 파일을 참고하여 API 서버의 주소 및 인증 정보를 확인합니다.
  3. REST API 요청을 API 서버(kube-apiserver)에 전송합니다.
  4. API 서버는 요청을 처리하고, 필요한 경우 etcd에서 데이터를 조회하거나 변경합니다.
  5. API 서버는 결과를 kubectl에 반환하고, kubectl은 이를 사용자에게 출력합니다.
이제 위 과정이 실제로 어떻게 동작하는지 더 자세히 살펴보겠습니다.
 

Kubectl의 명령어 실행 과정


사용자가 kubectl get pods 명령어를 실행하면 내부적으로 다음과 같은 과정이 진행됩니다.
 

kubectl이 API 요청을 생성

    1. kubectl은 ~/.kube/config 파일을 읽고, 클러스터의 API 서버 주소와 인증 정보를 확인합니다.

    2. kubectl은 Kubernetes API에 대한 HTTP 요청을 생성합니다. 예를 들어, kubectl get pods를 실행하면 다음과 같은 요청이 생성됩니다.

GET /api/v1/namespaces/default/pods HTTP/1.1
Host: <API_SERVER>
Authorization: Bearer <TOKEN>

 

    3. 요청은 RESTful API를 통해 Kubernetes API 서버로 전달됩니다.

 

API 서버가 요청을 처리

API 서버는 다음 단계를 거쳐 요청을 처리합니다.

  1. 인증(Authentication): API 서버는 ~/.kube/config에 저장된 인증 정보(예: Bearer Token)를 확인하여 요청을 보낸 사용자가 유효한지 검증합니다.
  2. 인가(Authorization): RBAC(Role-Based Access Control) 정책을 확인하여 사용자가 해당 리소스를 조회할 권한이 있는지 확인합니다.
  3. 어드미션 컨트롤(Admission Control): 요청을 검증하고, 필요한 경우 정책(예: 리소스 제한, 네임스페이스 정책 등)을 적용합니다.
  4. etcd에서 데이터 조회: 요청이 유효하면, API 서버는 etcd에서 해당 데이터를 조회하여 응답을 생성합니다.

 

etcd에서 Pod 정보 조회

etcd는 Kubernetes의 핵심 데이터 저장소로, 모든 클러스터 상태 정보를 Key-Value 형식으로 저장하고 있습니다. kubectl get pods를 실행하면 API 서버는 etcd에서 pod 정보를 조회하는데, 이 과정은 다음과 같습니다.

 

    1. API 서버는 etcd 클라이언트를 통해 특정 key를 검색합니다. 예를 들어, default 네임스페이스의 pod 목록을 가져오는 경우, etcd에서 다음 key를 조회합니다.

/registry/pods/default/

    2. etcd는 요청을 처리하고, 해당 key에 저장된 데이터를 JSON 형식으로 반환합니다.

    3. API 서버는 etcd에서 받은 데이터를 Kubernetes API 응답 형식으로 변환합니다.

    4. 변환된 데이터는 kubectl로 반환됩니다.

 

응답을 사용자에게 출력

  1. kubectl은 API 서버에서 받은 JSON 데이터를 사용자가 보기 쉽게 가공합니다.
  2. 최종적으로 터미널에 보기 좋은 형태로 pod 목록이 출력됩니다.
NAME       READY   STATUS    RESTARTS   AGE
my-pod     1/1     Running   0          5m

 

etcd의 데이터 저장 방식


etcd는 Kubernetes의 상태를 Key-Value 형태로 저장하는 분산 저장소입니다. pod 정보는 다음과 같은 형식으로 저장됩니다.

  • Key: /registry/pods/{namespace}/{pod_name}
  • Value: Pod 객체의 JSON 데이터

예를 들어, default 네임스페이스의 my-pod의 데이터를 조회하면 etcd 내부에서는 다음과 같은 JSON 값이 저장되어 있습니다.

{
  "metadata": {
    "name": "my-pod",
    "namespace": "default",
    "uid": "12345",
    "creationTimestamp": "2025-02-28T12:00:00Z"
  },
  "status": {
    "phase": "Running"
  },
  "spec": {
    "containers": [
      {
        "name": "app-container",
        "image": "nginx:latest"
      }
    ]
  }
}

이 데이터를 API 서버가 조회하여 kubectl에 반환하는 것입니다.

 

정리


kubectl이 어떻게 동작하는지 한눈에 정리하면 다음과 같습니다.

  1. 사용자가 kubectl 명령어를 실행하면 HTTP 요청이 Kubernetes API 서버로 전달됩니다.
  2. API 서버는 인증 및 인가를 확인한 후, 필요한 경우 etcd에서 데이터를 조회합니다.
  3. etcd는 Key-Value 저장소에서 데이터를 찾아 API 서버에 반환합니다.
  4. API 서버는 받은 데이터를 JSON으로 변환하여 kubectl에 반환합니다.
  5. kubectl은 데이터를 사용자 친화적으로 가공하여 출력합니다.

이제 kubectl이 단순한 CLI 도구가 아니라, Kubernetes API 서버 및 etcd와 긴밀하게 연동되어 동작하는 구조임을 이해할 수 있습니다. 이러한 내부 동작을 이해하면 Kubernetes를 더 효과적으로 운영하고 문제 발생 시 빠르게 원인을 파악할 수 있습니다.

이번 포스트에서는 Kubernetes 환경에서의 패키지 매니저로서 주로 오픈소스 어플리케이션 배포시에 자주 사용하는 Helm 설치 방법을 소개합니다.
설치환경에 따라 설치방법이 다를 수 있으니 참고 부탁드립니다.
 
설치환경
- Apple M1 MacBook Pro 13 Inch 2020
- MacOS Sonoma
 
https://helm.sh/docs/intro/install/

Installing Helm

Learn how to install and get running with Helm.

helm.sh

 

1. Helm 공식 홈페이지 접속 후 설치 스크립트 확인

 

2. 설치 스크립트를 로컬에 다운로드 후 설치 진행

curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3

 
get_helm.sh 파일을 실행가능한 파일로 변경해 줍니다.

chmod 700 get_helm.sh

 
ls 명령어로만 확인하게 되면 터미널 설정에 의해 색깔이 변하게 되는데 더 정확하게 파악하기 위해서는 ls -al 명령어를 통해 현재 유저에 rw권한이 있는지 확인해 줍니다.

./get_helm.sh

 
설치 스크립트를 실행하여 설치를 진행해 줍니다. (현재 유저의 패스워드를 입력 후 진행)

위와 같은 상태로 보여지면 설치가 완료 됩니다.
 

3. Helm 설치 완료

helm version 명령어를 통해 설치된 버전을 확인합니다.

helm version

 
이렇게 진행하면 아주 간단한 방법으로 Helm 설치가 가능합니다.
 
감사합니다.

'Mac' 카테고리의 다른 글

Docker Desktop에서 Kubernetes 설치하기  (0) 2024.07.07
Mac에서 Docker Desktop 설치하기  (0) 2024.07.07
Mac에서 oh-my-zsh 설치하기  (0) 2024.07.07
Mac에서 Homebrew 설치하기  (0) 2024.06.30
Mac에서 iTerm2 설치하기  (0) 2024.06.28

+ Recent posts