Kustomize는 Kubernetes 객체의 CLI 구성 관리자로, 레이어링을 활용하여 애플리케이션의 기본 설정을 보존합니다. 이는 원본 매니페스트를 실제로 수정하지 않고도 선언적 YAML 아티팩트를 오버레이하여 기본 설정을 덮어쓰는 방식으로 이루어집니다. Kustomize는 또한 kubectl과 통합되어 있습니다.
Kustomize는 Kubernetes 리소스 및 필드를 인식하며 다른 도구들과 달리 단순한 텍스트 템플릿 솔루션이 아닙니다.
Kustomize를 사용하면 하나의 기본 파일을 모든 환경 (개발, 스테이징, 프로덕션 등)에서 재사용하고 각 환경에 대한 오버레이 사양을 적용할 수 있습니다. 또한 Kustomize는 Helm 및 Argo CD와 같은 CD 솔루션과 함께 사용할 수 있습니다.
Kustomize의 작동 방식
- kustomization.yaml
- 각 디렉토리에는 kustomization.yaml 파일이 있으며, 이는 Kubernetes 객체를 생성하거나 변환하는 방법을 설명하는 리소스 또는 매니페스트 목록입니다.
- base 폴더
- base 폴더에는 기본 리소스가 포함되어 있습니다. 예를 들어, deployment.yaml, service.yaml, configmap.yaml 등이 있습니다. 이 폴더에는 초기 매니페스트가 포함되어 있으며 리소스에 대한 네임스페이스 및 레이블이 포함되어 있습니다.
- overlays 폴더
- overlays 폴더에는 환경별 오버레이가 포함되어 있습니다. 이러한 오버레이는 YAML 파일을 정의하고 기본 설정 위에 오버레이 할 수 있도록 패치를 사용합니다.
예시 구조
kustomize-k8s
├── base
│ ├── configmap.yaml
│ ├── kustomization.yaml
└── overlays
├── production
│ ├── configmap-patch.yaml
│ ├── kustomization.yaml
└── staging
├── configmap-patch.yaml
├── kustomization.yaml
각 환경에 대한 설정을 변경하려면 오버레이에서 해당 설정을 정의합니다.
base/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: django-configmap
data:
DJANGO_AUTH_PUBLIC_URI: "http://dj.192.168.0.139.sslip.io"
DEBUG: "True"
overlays/staging/configmap-patch.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: django-configmap
data:
DJANGO_AUTH_PUBLIC_URI: "http://staging.192.168.0.139.sslip.io"
overlays/staging/kustomization.yaml
namePrefix: staging-
commonLabels:
env: staging
bases:
- ../../base
patchesStrategicMerge:
- configmap-patch.yaml
배포 및 확인
- 리포지토리 클론
git clone git@github.com:sureshdsk/kustomize-k8s-example.git cd kustomize-k8s-example
- 매니페스트 미리보기 및 적용
또는 kubectl 플러그인으로도 사용 가능합니다.# 미리보기 kustomize build overlays/staging # 적용 kustomize build overlays/staging | kubectl apply -f -
# 미리보기 kubectl kustomize overlays/staging # 적용 kubectl apply -k overlays/staging
이제 Kustomize를 사용하여 Kubernetes에 배포하는 방법에 대한 예시였습니다.
기존에 배포한 Kubernetes에서 Pod을 업데이트할 때 일부 필드를 변경할 수 없는 규칙에 따라 오류가 발생할 수 있습니다. 특히, spec.containers[*].resources.limits
및 spec.containers[*].resources.requests
와 같은 필드가 변경되어서는 안 됩니다.
CPU 및 메모리 리소스에 대한 변경이 감지되는 경우 해결 방법은 다음과 같습니다.
- Pod 업데이트 제한 확인: 먼저 현재 Pod의 리소스 제한을 확인하십시오. 현재 리소스 제한이 변경되고 있음을 알 수 있습니다.
- Rolling Update 사용: Pod을 업데이트할 때, "Rolling Update"를 사용하는 것이 좋습니다. 이를 통해 기존 Pod을 새로운 Pod으로 안전하게 교체할 수 있습니다.
- 컨테이너 이미지 버전 변경: 리소스 제한이나 요청을 변경하려면 새로운 컨테이너 이미지를 사용해야 합니다. 따라서 새로운 이미지를 빌드하고 배포하십시오.
- Pod 스펙 업데이트 제한 확인: 오류 메시지에서 언급된 것처럼 허용되는 업데이트 필드만 변경되도록 Pod 스펙을 수정하십시오. 이러한 필드는
spec.containers[*].image
,spec.initContainers[*].image
,spec.activeDeadlineSeconds
,spec.tolerations
,spec.terminationGracePeriodSeconds
입니다. 다른 필드를 변경하면 해당 오류가 발생할 수 있습니다. - kubectl apply 대신에 kubectl edit 사용: 만약
kubectl apply
를 사용하고 있다면, 대신kubectl edit
을 사용하여 Pod 스펙을 직접 편집할 수 있습니다. 이렇게 하면 편집기를 열어 직접 변경할 수 있습니다. - Pod 재시작: 변경된 Pod 스펙을 저장한 후 Pod을 다시 시작하십시오. Rolling Update를 사용하여 안전하게 이를 수행할 수 있습니다.
다음은 예제입니다.
kubectl edit pod elastic-operator-0 -n <namespace>
여기서 <namespace>
는 배포된 네임스페이스입니다. 이 명령을 실행하면 Pod 스펙이 편집기로 열립니다. 변경 후 저장하면 Kubernetes가 새로운 Pod을 시작하여 업데이트된 스펙을 적용합니다.
kubectl edit
을 사용하여 Pod을 직접 편집하려고 할 때, Kubernetes가 오류를 반환하여 변경 사항을 저장하지 못하는 경우에는 다음과 같은 몇 가지 해결 방법이 있습니다.
- 삭제 및 재생성: Pod을 삭제하고 새로운 Pod을 생성하여 변경된 스펙이 적용되도록 합니다. 이 방법은 가장 간단하지만, 운영 중인 Elasticsearch에 영향을 줄 수 있으므로 신중하게 진행하십시오.
그런 다음 Kubernetes가 자동으로 새 Pod을 시작합니다.kubectl delete pod elastic-operator-0 -n <namespace>
- Rolling Update를 통한 변경: 만약 StatefulSet을 사용하고 있다면, Rolling Update를 통해 Pod을 안전하게 교체할 수 있습니다.
위 명령에서kubectl rollout restart statefulset <statefulset-name> -n <namespace>
<statefulset-name>
은 Elasticsearch를 배포하는 StatefulSet의 이름이어야 합니다. - yaml 파일 수정 후 Apply: 변경 사항을 직접 yaml 파일로 수정한 다음,
kubectl apply
를 사용하여 변경 사항을 적용합니다. 예를 들어, Pod 스펙이 포함된 YAML 파일을 수정한 다음 다음 명령을 사용할 수 있습니다.
이 명령에서kubectl apply -f <modified-pod-spec-file.yaml>
<modified-pod-spec-file.yaml>
는 수정된 Pod 스펙이 포함된 YAML 파일의 경로입니다. - kubectl patch 사용:
kubectl patch
명령을 사용하여 Pod의 일부를 수정할 수도 있습니다. 이를 통해 리소스 제한과 요청을 변경할 수 있습니다.
위 명령에서kubectl patch pod elastic-operator-0 -n <namespace> -p '{"spec":{"containers":[{"name":"<container-name>","resources":{"limits":{"cpu":"4","memory":"2Gi"},"requests":{"cpu":"100m","memory":"150Mi"}}}]}}'
<container-name>
은 수정하려는 컨테이너의 이름입니다.
이러한 해결 방법 중 하나를 선택하여 변경 사항을 적용해 보십시오.
kubectl patch
명령을 사용하면, 기존 값은 유지되고 지정된 값만 업데이트됩니다. Patch 작업을 수행할 때, 명시한 필드만 변경되고 나머지는 그대로 유지됩니다.
예를 들어, 다음과 같은 kubectl patch
명령어를 사용하여 Pod의 리소스 제한 및 요청을 변경할 수 있습니다.
kubectl patch pod elastic-operator-0 -n <namespace> --type='json' -p='[{"op": "replace", "path": "/spec/containers/0/resources/limits/cpu", "value": "4"}, {"op": "replace", "path": "/spec/containers/0/resources/limits/memory", "value": "2Gi"}, {"op": "replace", "path": "/spec/containers/0/resources/requests/cpu", "value": "100m"}, {"op": "replace", "path": "/spec/containers/0/resources/requests/memory", "value": "150Mi"}]'
이 명령은 JSON 포맷으로 변경할 필드를 지정하고, 해당 필드에 새로운 값을 할당하여 Pod을 업데이트합니다. 이때, 변경되는 것이 지정된 필드이며, 다른 필드는 변경되지 않습니다.
또한, kubectl patch
명령을 사용할 때 --dry-run=client
옵션을 사용하여 실제로 적용되기 전에 변경 사항을 미리 확인할 수 있습니다.
kubectl patch pod elastic-operator-0 -n <namespace> --type='json' -p='[{"op": "replace", "path": "/spec/containers/0/resources/limits/cpu", "value": "4"}, {"op": "replace", "path": "/spec/containers/0/resources/limits/memory", "value": "2Gi"}, {"op": "replace", "path": "/spec/containers/0/resources/requests/cpu", "value": "100m"}, {"op": "replace", "path": "/spec/containers/0/resources/requests/memory", "value": "150Mi"}]' --dry-run=client -o yaml
이렇게 하면 변경 사항을 확인하고 실제로 적용하기 전에 어떻게 변경되는지 미리 확인할 수 있습니다.
이 시점에서, 컨테이너 이름과 Pod 이름은 다른 개념을 간단히 설명하겠습니다.
Pod 이름은 Kubernetes에서 실행 중인 애플리케이션의 논리적인 이름을 나타냅니다. Pod은 하나 이상의 컨테이너로 구성될 수 있습니다.
컨테이너 이름은 Pod 내에서 실행 중인 각각의 컨테이너를 식별하는 데 사용됩니다. 하나의 Pod에 여러 컨테이너가 있을 수 있으며, 각 컨테이너는 고유한 이름을 가집니다.
예를 들어, 다음과 같은 Pod 정의가 있다고 가정해봅시다.
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: container1
image: myimage1
- name: container2
image: myimage2
이 경우, Pod의 이름은 "mypod"이고, 컨테이너 이름은 "container1"과 "container2"입니다. 따라서 각각의 컨테이너는 mypod
라는 하나의 Pod 내에서 실행됩니다.
kubectl patch
명령을 사용할 때, 특정 컨테이너의 리소스를 업데이트하려면 컨테이너의 이름을 정확하게 지정해야 합니다. 이를 위해 --type=json
과 함께 JSON 패치를 사용하여 특정 컨테이너의 경로를 지정하는 것이 중요합니다.
컨테이너 이름을 확인하려면 다음 명령어를 사용할 수 있습니다.
kubectl get pods <pod-name> -o=jsonpath='{.spec.containers[*].name}' -n <namespace>
여기서 <pod-name>
은 Pod의 이름이고, <namespace>
은 Pod이 배포된 네임스페이스입니다. 이 명령은 Pod의 컨테이너 이름 목록을 출력합니다.
예를 들어:
kubectl get pods mypod -o=jsonpath='{.spec.containers[*].name}' -n mynamespace
이렇게 하면 "mypod"라는 Pod에 속한 컨테이너들의 이름 목록이 출력됩니다.
Pod가 생성되었지만 해당 Pod에는 실행 중인 컨테이너가 없을 수 있습니다. Pod은 하나 이상의 컨테이너로 구성될 수 있지만, 때로는 특정 시점에서는 컨테이너가 실행되지 않을 수 있습니다. 컨테이너가 없다면, kubectl get pods
명령어로는 컨테이너에 대한 정보가 나타나지 않을 것입니다.
컨테이너가 있는지 여부를 확인하려면 kubectl describe pod
명령을 사용할 수 있습니다.
예를 들어:
kubectl describe pod <pod-name> -n <namespace>
위 명령에서 <pod-name>
은 확인하려는 Pod의 이름이고, <namespace>
은 Pod이 배포된 네임스페이스입니다. 이 명령을 통해 Pod의 상세 정보가 출력되며, 여기에서 컨테이너에 대한 정보를 확인할 수 있습니다.
Kubernetes 클러스터에서 배포한 서비스가 정상적으로 작동하지 않을 때, 다음과 같은 단계로 문제를 진단하고 해결할 수 있습니다.
- Pod 상태 확인
kubectl get pods
명령어를 사용하여 해당 서비스의 Pod 상태를 확인합니다. Pod가 정상적으로 생성되고 실행 중인지 확인하세요.kubectl describe pod <pod-name>
명령어를 사용하여 Pod의 상세 정보를 확인할 수 있습니다. 여기서 이벤트 섹션을 주목하여 에러 메시지 또는 문제를 확인할 수 있습니다.
- 서비스 상태 확인
kubectl get services
명령어를 사용하여 해당 서비스의 상태를 확인합니다. External IP나 Cluster IP가 할당되었는지 확인하세요.kubectl describe service <service-name>
명령어를 사용하여 서비스의 상세 정보를 확인할 수 있습니다.
- 로그 확인
- Pod의 로그를 확인하여 어떤 문제가 발생했는지 확인할 수 있습니다. 아래 명령어로 로그를 확인합니다.
kubectl logs <pod-name>
- Kafka와 Zookeeper의 경우, 주로 해당 컨테이너의 로그에 문제의 원인이 기록됩니다.
- 이벤트 확인
kubectl get events
명령어를 사용하여 클러스터의 이벤트를 확인할 수 있습니다. 여기에서 에러 또는 경고 이벤트를 찾아 문제를 진단하세요.
- Pod 내부로 들어가서 진단
kubectl exec -it <pod-name> -- /bin/bash
명령어를 사용하여 Pod 내부로 들어가서 필요한 명령어로 진단을 시도할 수 있습니다.
- YAML 파일 검토
- 배포에 사용한 YAML 파일을 다시 확인하여 오타나 잘못된 설정이 없는지 확인합니다.
- 네트워크 정책 확인
- 네트워크 정책이 Pod 간 통신을 방해하지 않는지 확인합니다.
- 리소스 부족 확인
- 클러스터의 자원(CPU, 메모리) 부족 여부를 확인하고, 필요한 리소스를 할당해야 하는지 판단합니다.
- Kubernetes 이벤트 및 로그 확인
kubectl get events
명령어로 Kubernetes 이벤트를 확인하고, 이벤트 메시지를 통해 문제를 파악할 수 있습니다.
위의 단계들을 따라가면서 어떤 부분에서 문제가 발생하는지를 확인하고, 그에 따른 조치를 취할 수 있습니다.
kubectl replace
는 존재하는 Kubernetes 리소스를 새로운 정의로 대체하는 데 사용되는 명령입니다. 이 명령은 기존 리소스를 제거하고 새로운 정의를 적용합니다. 주의해야 할 점은 리소스의 이름과 유형이 변경되지 않아야 합니다.
다음은 kubectl replace
의 기본 사용법 및 예제입니다.
kubectl replace -f <new-definition.yaml>
<new-definition.yaml>
은 새로운 리소스 정의 파일의 경로입니다.
- Pod의 예제: 생성할 Pod의 YAML 정의 파일을 만듭니다. (
nginx-pod.yaml
)
기존에 생성한 Pod가 있다면, 다음 명령으로 새로운 Pod로 대체할 수 있습니다.apiVersion: v1 kind: Pod metadata: name: my-nginx-pod spec: containers: - name: nginx-container image: nginx
kubectl replace -f nginx-pod.yaml
- Deployment의 예제: 새로운 Deployment 정의 파일을 만듭니다. (
nginx-deployment.yaml
)
기존에 생성한 Deployment가 있다면, 다음 명령으로 새로운 Deployment로 대체할 수 있습니다.apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx-container image: nginx
kubectl replace -f nginx-deployment.yaml
주의:
kubectl replace
를 사용할 때는 주의해야 합니다. 기존 리소스가 삭제되고 새로운 리소스가 만들어지므로 주의가 필요합니다.kubectl apply
와 비교하여kubectl replace
는 일부 경우에만 권장되며, 주의를 기울여 사용해야 합니다.- 리소스의 유형과 이름은 변경되지 않아야 합니다. 이름이나 유형을 변경하려면
kubectl apply
를 사용해야 합니다.
댓글