도커 로고

 

이번 시간엔 쿠버네티스의 CLI 도구 kubectl 에 대해 정리해본다.

 

1. 커맨드 라인 인터페이스 (CLI) 도구, kubectl

앞서 말했듯, 쿠버네티스를 수동으로 조작하는 경우엔 'kubectl' 을 사용한다.

 

1.1. 인증 정보와 컨텍스트(config)

kubectl 이 쿠버네티스 마스터와 통신할 때는 접속 대상의 서버 정보, 인증 정보 등이 필요하다.

kubectl 은 kubeconfig(기본 위치는 ~/.kube/config)에 쓰여 있는 정보를 사용하여 접속한다.

 

kubeconfig도 매니페스트와 동일한 형식으로 작성된다.

 

~/.kube/config

apiVersion: v1
clusters:
- cluster: # 접속 대상 클러스터
    certificate-authority-data: ...
    server: https://kubernetes.docker.internal:6443
  name: docker-desktop
contexts:
- context: # 접속 대상과 인증 정보 조합
    cluster: docker-desktop
    namespace: default
    user: docker-desktop
  name: docker-desktop
current-context: docker-desktop
kind: Config
preferences: {}
users:
- name: docker-desktop
  user: # 인증 정보
    client-certificate-data: ...
    client-key-data: ...

 

kubeconfig 에서 구체적으로 설정이 이루어지는 부분은 clusters / users / contexts 세 가지.

이 세 가지 설정 항목은 모두 배열로 되어 있어 여러 대상을 등록할 수 있다.

 

clusters

  • 접속 대상 클러스터 정보

users

  • 사용자 인증 정보
  • X.509 클라이언트 인증서 / 토큰 / 패스워드 / 웹훅 등 다양한 방식을 사용 가능

contexts

  • cluster 와 user, 네임스페이스를 지정한 것을 정의

 

kubeconfig 설정을 변경하려면 직접 편집하는 방법 외에 kubectl 명령어를 사용할 수 있다.

(kubectl 사용 시, kubeconfig 에 자동 저장)

 

kubectl config 변경

# 클러스터 추가 및 변경
$ kubectl config set-cluster prd-cluster \
--server=https://localhost:6443

# 인증 정보 정의 추가, 변경
$ kubectl config set-credentials admin-user \
--client-certificate=./sample.crt \
--client-key=./sample.key \
--embed-certs=true

# 컨텍스트 정의(클러스터 / 인증 정보 / 네임스페이스 정의)를 추가, 변경
$ kubectl config set-context prd-admin \
--cluster=prd-cluster \
--user=admin-user \
--namespace=default

 

kubctl 컨텍스트 명령어

# 컨텍스트 목록 표시
$ kubectl config get-context

# 컨텍스트 전환
$ kubectl config use-context docker-desktop

# 현재 컨텍스트 표시
$ kubectl config current-context

# 명령어 실행마다 컨텍스트 지정 가능
$ kubectl --context docker-desktop get pod

 

1.2 kubectx / kubens 를 사용한 전환

kubectx 를 설치해서 사용하면 kubectl config use-context 나 kubectl --namespace 명령어 보다 더 간결하게 사용 가능하다.

 

kubectx / kubens 명령어

# 컨텍스트 전환
$ kubectx docker-desktop

# 바로 전 컨텍스트로 전환
$ kubectx -

# 다시 컨텍스트 전환
$ kubectx docker-desktop

# 컨텍스트 삭제
$ kubectx -d prd-admin

# 네임스페이스 전환
$ kubens default

 

1.3 매니페스트와 리소스 생성 / 삭제 / 갱신

kubectl 을 사용하여 컨테이너를 기동해보기

 

sample-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: sample-pod
spec:
  containers:
    - name: nginx-container
      image: nginx:1.12

 

kubectl create

# 리소스가 존재하지 않을 경우
$ kubectl create -f sample-pod.yaml
pod/sample-pod created

# 이미 있는 경우
$ kubectl create -f sample-pod.yaml
Error from server (AlreadyExists): error when creating "sample-pod.yaml": pods "sample-pod" already exists

 

kubectl get pods 로 확인

# 파드 목록 표시
$ kubectl get pods

NAME         READY   STATUS    RESTARTS   AGE
sample-pod   1/1     Running   0          3m50s

 

kubectl delete

# pods 삭제
$ kubectl delete -f sample-pod.yaml
pod "sample-pod" deleted

# 특정 리소스만 삭제
$ kubectl delete pod sample-pod

# 특정 리소스 종류를 모두 삭제
$ kubectl delete pod --all

# 리소스 삭제(삭제 완료 대기)
$ kubectl delete -f sample-pod.yaml --wait

# 리소스 즉시 강제 삭제
$ kubectl delete -f sample-pod.yaml --grae-period 0 --force

 

kubectl apply 명령어를 사용한 리소스 업데이트

# 백업 파일을 만들때 아래 명령어를 사용하면 편하다.
# sample-pod.yaml 파일을 sample-pod.yaml.old 로 백업
$ cp -av sample-pod.yaml{,.old}

# 일부 수정한 sample-pod.yaml 변경 사항 확인
$ diff sample-pod.yaml sample-pod.yaml.old

8c8
<       image: nginx:1.17
---
>       image: nginx:1.12

# 생성하고,
$ kubectl create -f sample-pod.yaml

# 리소스 업데이트 하기
$ kubectl apply -f sample-pod.yaml

# sample-pod에서 사용 중인 이미지 확인
$ kubectl get pod sample-pod -o jsonpath="{.spec.containers[?(@.name == 'nginx-container')].image}"

nginx:1.17

 

1.4 리소스 생성에도 kubectl apply 를 사용해야 하는 이유

처음에 리소스가 없는 상태에서 kubectl create 가 아닌, kubectl apply 를 사용해도 pod 가 생성이 된다.

kubectl create 가 아닌 kubectl apply 를 사용해야 하는 이유는 크게 두 가지 라고 함..

 

첫 번째

  • kubectl create 를 사용하고, 업데이트는 kubectl apply 를 사용해야 한다는 구분이 필요하기 때문.
  • 스크립트나 CI/CD 등에 포함될 것을 생각하면 조건 분기는 하지 않는게 좋다.

두 번째

  • kubectl create 와 kubectl apply 를 섞어서 사용하면 kubectl apply 를 실행할 때 변경 사항을 검출하지 못할 경우가 있기 때문.
  • kubectl create 는 의도대로 반영되지 않는 경우가 생길 수 있으므로.. 항상 kubectl apply 를 사용할 것을 추천.

 

kubectl create 로 생성 후, kubectl apply 로 변경하게 되면 아래와 같은 경고가 나온다. (어쩐지..)

Warning: resource pods/sample-pod is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
pod/sample-pod configured

 

kubectl apply 명령어와 kubectl create 명령어를 사용한 경우 결과가 다를 수 있으므로 항상 apply 를 쓰도록 하자..!

 

1.5 Server-side apply

간단하게 얘기하면 충돌을 막는 기능이다.

예를 들어

 

1. sample-pod.yaml 을 통해 pod 를 생성한다. 이때 nginx 버전은 1.16 이다.

 

2. kubectl set image 를 통해 nginx 버전을 1.17 로 올린다.

 

3. kubectl apply 를 통해 sample-pod.yaml 의 다른 정보를 업데이트 한다.

 

3번 과정에서 nginx 버전이 1.16회귀해버린다. 이런 충돌을 막기 위해 --server-side 옵션을 사용한다.

 

--server-side 옵션을 추가한 apply

# server-side apply 를 활성화하여 매니페스트 생성
$ kubectl apply -f sample-pod.yaml --server-side

# 이미지 변경
$ kubectl set image pod sample-pod nginx-container=nginx:1.17

# apply 실행, 에러가 발생한다.
$ kubectl apply -f sample-pod.yaml --server-side

error: Apply failed with 1 conflict: conflict with "kubectl-set" using v1: .spec.containers[name="nginx-container"].image
Please review the fields above--they currently have other managers. Here
are the ways you can resolve this warning:
* If you intend to manage all of these fields, please re-run the apply
  command with the `--force-conflicts` flag.
* If you do not intend to manage all of the fields, please edit your

# 강제 apply 실행하기, force-conflicts 를 사용한다.
$ kubectl apply -f sample-pod.yaml --server-side --force-conflicts

# -o yaml 옵션을 추가하여 yaml 형식으로 볼 수 있다.
$ kubectl get pod sample-pod -o yaml

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2022-02-27T11:29:37Z"
  name: sample-pod
  namespace: default
  resourceVersion: "84157"
  uid: 4b8d2b89-5b7b-4bf8-bfde-9762ebef28cf
spec:
  containers:
  - image: nginx:1.16
...

 

 

kubectl 사용 시 개발자/운영자 가 콘솔에서 사용하는 kubectl 을 구별할 수 있게 --field-manager 옵션을 사용해서 manager 이름을 부여할 수 있는데, 이 경우에도 충돌 감지가 된다.

 

# Manager 이름을 변경하고 변경 내용을 적용
$ kubectl apply -f sample-pod.yaml --server-side --field-manager developer

# sample-pod.yaml 를 수정하고 apply 할 때, 에러 발생!
$ kubectl apply -f sample-pod.yaml --server-side

 

 

kubectl 을 활용한 사용법은 다음 시간에 계속 -