kubectl


kubectl apply

kubectl apply -f nginx.yaml

kubectl apply 를 통해 이미 만들어진 Object 를 파악하며 부분적으로 설정이 수정된 경우 해당 부분만 적용하는 기능 역시 지원한다.

# Live object configuration
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: {"apiVersion": "v1", ...}
  labels:
    app: myapp
    type: front-end
spec:
  containers:
  - name: nginx-container
    image: nginx
status:
  conditions:
  - lastProbeTime: null
    ...

kubectl apply 를 실행하면 쿠버네티스는 사용자가 작성한 YAML 파일과 K8s memory 에 저장된 Live object configuration 과 kubectl.kubernetes.io/last-applied-configuration 필드를 비교하여 변경된 사항만 부분적으로 확인하고 적용이 가능하다.

kubectl get -o=custom-columns

k get deployments.apps -n=admin2406 -o=json
k get deployments.apps -n=admin2406 -o=custom-columns=DEPLOYMENT:.metadata.name,CONTAINER_IMAGE:.spec.template.spec.containers[0].image,READY_REPLICAS:.status.readyReplicas,NAMESPACE:.metadata.namespace > /opt/admin2406_data

K8s Object 의 특정 정보를 취합해서 파일로 저장하고 싶을 때 custom-columns 옵션을 활용할 수 있다. json 옵션을 사용했을 때 출력되는 계층을 따라 특정 정보에 접근할 수 있다.

kubectl logs

kubectl logs -l app=log-lab --prefix

--prefix 옵션으로 로그 앞에 어느 파드의 어느 컨테이너에서 생성된 로그인지 확인 가능

kubectl logs -l app=log-lab --prefix --since=10m

--since 옵션으로 최근 시간 내에 생성된 로그만 확인 가능

kubectl logs -l app=log-lab --prefix --since=10m --tail=100

--tail 옵션으로 최근 로그 갯수 제한 가능

Some useful grep

kubectl logs -l app=log-lab --prefix --since=10m --tail=100 | grep -iE 'error|warn'

grep -E 로 여러 키워드를 매칭해서 필터링 가능, -i 옵션까지 추가하면 대소문자 구분하지 않고 확인

kubectl logs -l app=log-lab --prefix --since=10m --tail=100 | grep -F "connection refused"

grep -F 로 문자열 검색

kubectl logs -l app=log-lab --prefix --since=10m --tail=100 | grep -w "ERROR"

grep -w 로 단어 단위로 매칭

kubectl logs -l app=log-lab --prefix --since=10m --tail=100 | grep -C2 'error'

grep -C2 (Context 의 C) 로 매칭된 로그 앞 뒤로 2줄을 추가로 보여줄 수 있다

kubectl logs -l app=log-lab --prefix --since=10m --tail=100 | grep -A2 'error'

grep -A2 (After 의 A) 로 매칭된 로그 뒤 2줄을 추가로 보여줄 수 있다

kubectl logs -l app=log-lab --prefix --since=10m --tail=100 | grep -B2 'error'

grep -B2 (Before 의 B) 로 매칭된 로그 전 2줄을 추가로 보여줄 수 있다

kubectl logs -l app=log-lab --prefix -f | grep -E 'ERROR|WARN'

-f 로 실시간 로그 확인, grep 조합으로 원하는 로그만 추출 가능

kubectl alias 및 자동완성 설정

echo '[[ $commands[kubectl] ]] && source <(kubectl completion zsh)' >> ~/.zshrc
echo 'alias k=kubectl' >> ~/.zshrc
echo 'compdef __start_kubectl k' >> ~/.zshrc
source ~/.zshrc

Logging and Monitoring


Monitoring Cluster Components

K8s 를 운영할 때 모니터링 할 수 있는 지표는 Node 개수, CPU, Memory, Network, Disk 등이 있다. 이런 지표들은 kubelet 의 내장 컴포넌트 중 하나인 cAdvisor 를 통해 제공된다. K8s 는 기본적으로 제공하는 모니터링 툴이 없기 때문에 Prometheus, ELK, Datadog, Dynatrace 등 3rd Party 솔루션을 통해 K8s Cluster 를 모니터링 할 수 있다.

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
kubectl top node
kubectl top pod

Metric Server Pod 를 Cluster 에 배포한 뒤 위 명령어들을 통해 지표를 확인할 수 있다.

Managing Application Logs

docker logs -f {container-name}

Docker Container 로 Application 을 실행했을 때 위 명령어로 Application Log 를 확인할 수 있는 것 처럼,

kubectl logs -f {pod-name} {container-name}

위 명령어로 Pod 내 특정 Container 의 Log 를 확인할 수 있다.

Application Failure


curl http://web-service-ip:node-port

Application 에 접속할 수 없는 경우 아래와 같은 사항들을 진단해볼 수 있다.

Check Service Status

kubectl describe service web-service

먼저 위 명령어를 통해 SelectorEndpoints 부분을 확인하여 Service 가 Pod 을 잘 찾아냈는지 진단한 후 만약 이슈가 있다면 Pod 의 metadata.labels.namespec.containers.ports.containerPort 를 확인해 고쳐주도록 하자.

Check Pod

kubectl get pod
kubectl describe pod web
kubectl logs web -f --previous

Pod 의 재시작 상태와 log 들을 확인하여 문제를 찾아보자.

Check Dependent Service & Pod

위까지 문제가 없다면 종속성 있는 Service 와 Pod 를 위와 같은 방법으로 진단해보자.

Control Plane Failure


kubectl get nodes
kubectl get pods
kubectl get pods -n kube-system

먼저 K8s Cluster 의 Node 와 Pod 들의 상태를 확인한 후, Control Plane Pod 들이 정상적으로 작동하는지 확인한다.

service kube-apiserver status
service kube-controller-manager status
service kube-scheduler status
service kubelet status
service kube-proxy status

만약 kubeadm 으로 구축하지 않아 service 형태로 실행중인 경우 위와 같은 명령어로 상태를 확인할 수 있다.

kubectl logs kube-apiserver-master -n kube-system
sudo journalctl -u kube-apiserver

이후 각 Component 들의 Log 를 확인해보자.

/etc/kubernetes/manifests/

kubeadm 을 사용해 Cluster 를 구축한 경우 위 경로에서 조치가 필요한 Component 를 수정해주자.

Worker Node Failure


kubectl get nodes
kubectl describe node worker-1

위 명령어들로 Node 의 상태를 확인한 뒤,

top
df -h

CPU 와 메모리 사용량을 확인하고,

service kubelet status
sudo journalctl -u kubelet

kubelet 의 상태를 확인하고,

service kubelet start

kubelet 을 재시작하거나,

cat /etc/kubernetes/kubelet.conf

kubelet 설정을 확인해보자.

openssl x509 -in /var/lib/kubelet/worker-1.crt -text

CA 의 Issuer, Validity, Subject 등을 확인해보자.

Network Troubleshooting


Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox "c117e7be807116764889d820a073a0054630776881ddb92dfc46c2cbd174ce4e": plugin type="weave-net" name="weave" failed (add): unable to allocate IP address: Post "http://127.0.0.1:6784/ip/c117e7be807116764889d820a073a0054630776881ddb92dfc46c2cbd174ce4e": dial tcp 127.0.0.1:6784: connect: connection refused

CNI Plugin 이 설치되어있지 않은 경우 위와 같은 에러를 확인할 수 있다.

curl -L https://github.com/weaveworks/weave/releases/download/latest_release/weave-daemonset-k8s-1.11.yaml | kubectl apply -f

설치해주자.

K9s


K9s 는 터미널 환경에서 실행되는 TUI, Text-based User Interface 도구이다.

brew install k9s

설치 후 k9s 를 입력하면 현재 kubectl 컨텍스트에 설정된 클러스터 상태를 확인할 수 있다.

핵심 기능

  • :pods, :deploy, :svc 등의 명령어로 리소스 및 네임스페이스를 빠르게 이동할 수 있다.
  • l: Pod 로그 확인
  • s: 컨테이너 쉘 접속
  • d: 리소스 describe

Node Rolling 소요시간 확인


kubectl get nodes -l eks.amazonaws.com/nodegroup=${NODE_GROUP_NAME} -o json | jq -r '
  .items[]
  | (.status.conditions[] | select(.type=="Ready" and .status=="True") | .lastTransitionTime) as $ready
  | select($ready != null)
  | (.metadata.creationTimestamp | fromdateiso8601) as $c
  | ($ready | fromdateiso8601) as $r
  | [
      .metadata.name,
      (.spec.providerID | split("/")[-1]),
      .metadata.annotations["alpha.kubernetes.io/provided-node-ip"],
      .metadata.labels["topology.kubernetes.io/zone"],
      .metadata.creationTimestamp[0:19],
      $ready[0:19],
      "\($r - $c)s"
    ] | @tsv
' | sort -k5 | column -t -s $'\t'

현재 노드 Create, Ready 시간 및 AZ 확인

aws autoscaling describe-scaling-activities \
  --auto-scaling-group-name "$ASG" \
  --region ap-east-1 | jq -r '
  ["INSTANCE","ACTION","AZ","START(UTC)","END(UTC)","DUR","STATUS","PROG"],
  (.Activities
    | sort_by(.StartTime) | .[]
    | (if   (.Description | test("Launching"))   then "Launch"
       elif (.Description | test("Terminating")) then "Terminate"
       else "?" end) as $action
    | ((.Description | capture("(?<i>i-[0-9a-f]+)").i) // "-") as $iid
    | ((.Details? | if . then (. | fromjson | .["Availability Zone"]) else null end) // "-") as $az
    | ((.StartTime[0:19] + "Z") | fromdateiso8601) as $s
    | (if .EndTime then (.EndTime[0:19] + "Z") | fromdateiso8601 else null end) as $e
    | [ $iid,
        $action,
        $az,
        .StartTime[0:19],
        (.EndTime[0:19] // "-"),
        (if $e then "\($e - $s)s" else "running" end),
        .StatusCode,
        (.Progress | tostring)
      ]
  ) | @tsv
' | column -t -s $'\t'

노드 Launch/Terminate 시간 trace

  • Node Group Update Config 에서 max_unavailable=1 (기본값) 일 경우, 새로운 노드가 하나씩 Launch 되고 기존 노드가 하나씩 Terminate 된다.
  • 즉, Launch 시간, Terminate 시간 차이가 기존 노드 drain duration 이 된다.

Pod Eviction Failure 429 발생 시 기본적으로 1분마다 eviction retry 를 실행한다.

  • Node Group force_update_version=True 일 경우, 19번의 retry 실패 후 Node drain timeout 으로 노드가 강제종료된다.
  • 즉, 기존 노드 drain 은 3-5분 걸리는데 비해 약 20분 가량까지 노드 drain 이 지연되어 Rolling Update 시간이 늘어날 수 있다.

References