자격증/Kubernetes CKA

[CKA] 명령어 정리 - 1

Nowon9159 2024. 1. 2. 10:16
반응형

CKA (https://www.credly.com/org/the-linux-foundation/badge/cka-certified-kubernetes-administrator)

Core Concepts

PODs

명령어

# 파드 확인하기
kubectl get pod # k get po

# 특정 네임스페이스 안에 있는 파드 확인하기
kubectl get pod -n <namespace name>

# 파드 더 자세히 확인하기
kubectl get pod -o wide

# 파드 생성하기
kubectl run pod <pod name>

# 파드 생성할 때 이미지 설정
kubectl run pod <pod name> --image=<image name>:<image version>

# 파드 생성할 때 레이블 설정
kubectl run pod <pod name> --image=<image name>:<image version> -l <key>=<value>
# -l <key>=<value>,<key>=<value> 레이블의 경우 콤마(,)를 넣어주면 다수도 지정 가능

# 파드 상세 정보 출력
kubectl describe pod <pod name>

# 파드 삭제
kubectl delete po <pod name>
kubectl delete po <pod name> <pod name> # 다중 삭제도 가능

# 파드 정보 변경
kubectl edit pod <pod name>

# 파드 생성할 때 파일 기반으로 생성하기
kubectl create -f <pod yaml>.yaml
kubectl apply -f <pod yaml>.yaml

YAML

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: nginx:latest
    ports:
    - containerPort: 80

확인 사항

  • describe 명령어로 확인할 때 Events로 파드의 상태를 간략히 로그로 확인 가능
  • describe 명령어로 확인할 때 Containers 항목에서 State와 Reason을 통해 트러블 슈팅 가능
  • kubectl get po 명령어로 확인할 때 READY 항목은 Running Containers in POD/Total Containers in POD
  • kubectl delete 명령어로 삭제할 때 강제 삭제하려면 --force 옵션 넣어주면 된다.
  • kubectl get, describe, delete 등은 pod, replicaset, service 등등 모든 자원에 거의 비슷하게 사용 가능하다.

Replicasets

명령어

# Replicaset 확인
kubectl get replicasets <replicasets name> # k get rs

# Replicaset 상세 정보 확인
kubectl describe replicasets <replicasets name>

# Replicaset 삭제
kubectl delete replicasets <replicasets name>

# Replicaset 정보 변경
kubectl edit replicasets <replicasets name>

# Replicaset replicas 개수 스케일 하기 (스케일은 업/다운 모두 포함)
kubectl scale replicasets <replicasets name> --replicas=<replicas COUNT>
kubectl edit replicaset <replicasets name> # edit 명령어 입력 후 replicas 항목 변경

YAML

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: example-replicaset
  labels:
    app: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp-container
        image: nginx:latest
        ports: # 포트는 없어도 됨
        - containerPort: 80

확인 사항

  • YAML 기반으로 생성 시 apiVersion 항목 apps/v1인 지 확인
  • selector에 matchLabels에 있는 레이블이랑 template에 있는 레이블이랑 일치하는지 확인

Deployments

명령어

# Deployment 확인
kubectl get deployment <deployment name> # k get deploy

# Deployment 상세 정보 확인
kubectl describe deployment <deployment name>

# Deployment 삭제
kubectl delete deployment <deployment name>

# Deployment 정보 변경
kubectl edit deployment <deployment name>

YAML

apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-deployment
  labels:
    app: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp-container
        image: nginx:latest
        ports: # 포트는 없어도 됨
        - containerPort: 80
  • 명령어나 YAML에서 replicaset이나 pod에 있는 비슷한 내용들은 전부 삭제했다.
  • deployment는 거의 replicaset과 비슷한듯
  • kind에 Deployment나 apiVersion에 apps/v1을 유의하면 될듯

Namespaces

명령어

# Namespace 확인
kubectl get namespace <namespace name> # k get ns

# 서비스에 도메인으로 접근 가능
## 예를들어 동일 네임스페이스에 있는 서비스 example1 으로 접근 할 경우
curl example1
## 다른 네임스페이스 good에 있는 서비스 example2 으로 접근 할 경우
curl example2.good.svc.cluster.local

Services

명령어

# Services 확인
kubectl get service <service name> # k get svc

YAML

apiVersion: v1
kind: Service
metadata:
  name: example-service
  labels:
    app: myapp
spec:
  selector:
    app: myapp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      # nodePort: 30080  노드 포트를 지정할 수도 있다.
  type: ClusterIP
  • service에서 type은 LoadBalancer, NodePort, ClusterIP, Endpoints 가 있다.

Imperative command

kubectl apply -f 없이 명령어로만 수행

controlplane ~ ➜  kubectl run nginx-pod --image=nginx:alpine
pod/nginx-pod created

controlplane ~ ➜  kubectl run redis --image=redis:alpine -l tier=db
pod/redis created

controlplane ~ ➜  k create service clusterip redis-service --tcp=6379:6379
service/redis-service created

controlplane ~ ➜  k create deploy webapp --image=kodekloud/webapp-color --replicas=3
deployment.apps/webapp created

controlplane ~ ✖ k run custom-nginx --image=nginx --port 8080
pod/custom-nginx created

controlplane ~ ➜  k create ns dev-ns
namespace/dev-ns created

controlplane ~ ➜  k create deploy redis-deploy -n dev-ns --image=redis --replicas=2
deployment.apps/redis-deploy created

controlplane ~ ➜  k run httpd --image=httpd:alpine --port=80 --expose
service/httpd created
pod/httpd created

deployment expose 하기

# 생성된 deployment에 service 바로 생성해서 expose하는 방법
kubectl expose deployment hr-web-app --type=NodePort --port=8080 --name=hr-web-app-service --dry-run=client -o yaml > hr-web-app-service.yaml

pod 기반으로 service expose

kubectl expose pod messaging --port=6379 --name messaging-service

Scheduling

Manual Scheduling

파드를 특정 노드에 생성하기

---
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  nodeName: node01 # nodeName 항목을 넣어주면 해당 노드에 파드 생성
  containers:
  -  image: nginx
     name: nginx

Labels and Selectors

특정 레이블 기반 파드 검색

controlplane ~ ➜  k get po -l env=dev
NAME          READY   STATUS    RESTARTS   AGE
db-1-pwlcs    1/1     Running   0          72s
db-1-bbxbq    1/1     Running   0          72s
app-1-rqxtj   1/1     Running   0          72s
app-1-r98vm   1/1     Running   0          72s
db-1-ng6bh    1/1     Running   0          71s
app-1-v9psf   1/1     Running   0          72s
db-1-z2hvj    1/1     Running   0          72s

모든 리소스에 대해서 레이블 검색

controlplane ~ ➜  k get all --selector env=prod
NAME              READY   STATUS    RESTARTS   AGE
pod/app-2-gx2pv   1/1     Running   0          3m32s
pod/db-2-v6vmj    1/1     Running   0          3m31s
pod/app-1-zzxdf   1/1     Running   0          3m31s
pod/auth          1/1     Running   0          3m31s

NAME            TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/app-1   ClusterIP   10.43.47.176   <none>        3306/TCP   3m31s

NAME                    DESIRED   CURRENT   READY   AGE
replicaset.apps/app-2   1         1         1       3m32s
replicaset.apps/db-2    1         1         1       3m32s

레이블 다중 검색

controlplane ~ ➜  k get po --selector env=prod,bu=finance,tier=frontend
NAME          READY   STATUS    RESTARTS   AGE
app-1-zzxdf   1/1     Running   0          5m55s

Taints and Tolerations

Taints 설정하기

controlplane ~ ✖ k taint node node01 spray=mortein:NoSchedule
node/node01 tainted

Tolerations 설정하기

---
apiVersion: v1
kind: Pod
metadata:
  name: bee
spec:
  containers:
  - image: nginx
    name: bee
  tolerations:
  - key: spray
    value: mortein
    effect: NoSchedule
    operator: Equal
  • Toleration 설정하는 명령형은 없음. 그래서 dry run으로 선언형으로 생성해줘야한다. 구조를 잘 알고 있어야 할 듯

Node의 Taints 삭제하는 법

apiVersion: v1
kind: Node
metadata:
  name: your-node-name
  labels:
    node-role: worker
spec:
  taints:
  - key: example-key
    value: example-value
    effect: NoSchedule
  • kubectl edit 명령어를 실행해주고, taints 섹션을 지우면 된다.

Node Affinity

Node Affinity Deployment에 생성하기

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: blue
spec:
  replicas: 3
  selector:
    matchLabels:
      run: nginx
  template:
    metadata:
      labels:
        run: nginx
    spec:
      containers:
      - image: nginx
        imagePullPolicy: Always
        name: nginx
      affinity: # 이 부분 참고
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: color
                operator: In
                values:
                - blue
  • operator에는 In , NotIn, Exists, DoesNotExist 가 있음. Exists와 DoesNotExist는 Key 값만 비교하기 때문에 values 섹션이 없어도 됨

Resource Limits

YAML

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
  - name: example-container
    image: nginx:latest
    resources:
      requests:
        memory: "64Mi"  # Request 64 megabytes of memory
        cpu: "250m"     # Request 250 milliCPU (0.25 CPU cores)
      limits:
        memory: "128Mi" # Limit memory usage to 128 megabytes
        cpu: "500m"     # Limit

DaemonSets

kubectl get daemonset <daemonset name> # k get ds
apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    app: elasticsearch
  name: elasticsearch
  namespace: kube-system
spec:
  selector:
    matchLabels:
      app: elasticsearch
  template:
    metadata:
      labels:
        app: elasticsearch
    spec:
      containers:
      - image: registry.k8s.io/fluentd-elasticsearch:1.20
        name: fluentd-elasticsearch
  • Daemonset은 kubeclt create deployment 명령어를 이용해서 yaml을 추출해주고 일부 수정 및 kind를 DaemonSet으로 변경한 후 apply 해주면 된다.

Static Pods

  • Static Pod는 kubectl get po 명령어로 확인한 후 난수가 없는 파드를 찾거나 /etc/kubernetes/manifests/ 위치에 있는 yaml 파일 개수를 세면 됨
  • 꼭 Control Plane에만 Static pod가 있는 것이 아니라 워커 노드에도 있을 수 있으니 문제 내에 파드가 Control Plane에 없다면 워커 노드에도 들어가봐야 함

Multiple Schedulers

특정 scheduler 지정하는 법

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - image: nginx
    name: nginx
  schedulerName: my-scheduler # schedulerName 필드로 지정해주면 됨
  • Scheduler의 이미지는 registry.k8s.io/kube-scheduler:v1.27.0 이런 식으로 k8s registry에서 가져올 수 있다.

Logging & Monitoring

Monitor Cluster Components

node 사용량 모니터링

controlplane kubernetes-metrics-server on  master ➜  kubectl top node
NAME           CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
controlplane   277m         0%     1273Mi          0%        
node01         41m          0%     361Mi           0%        

pod 사용량 모니터링

controlplane kubernetes-metrics-server on  master ➜  kubectl top pod
NAME       CPU(cores)   MEMORY(bytes)   
elephant   16m          32Mi            
lion       1m           18Mi            
rabbit     108m         252Mi

Managing Application Logs

파드 로그 확인하기

# kubectl logs <pod name>
controlplane ~ ✖ k logs webapp-1
[2023-12-21 00:33:20,444] INFO in event-simulator: USER1 is viewing page1
[2023-12-21 00:33:21,445] INFO in event-simulator: USER4 is viewing page2
[2023-12-21 00:33:22,446] INFO in event-simulator: USER1 is viewing page2
[2023-12-21 00:33:23,447] INFO in event-simulator: USER3 logged out
[2023-12-21 00:33:24,449] INFO in event-simulator: USER1 is viewing page3
[2023-12-21 00:33:25,450] WARNING in event-simulator: USER5 Failed to Login as the account is locked due to MANY FAILED ATTEMPTS.

Application Lifecycle Management

Rolling Updates and Rollbacks

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  namespace: default
spec:
  replicas: 4
  selector:
    matchLabels:
      name: webapp
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        name: webapp
    spec:
      containers:
      - image: kodekloud/webapp-color:v2
        name: simple-webapp
        ports:
        - containerPort: 8080
          protocol: TCP
  • Deployment는 RollingUpdate와 Recreate 두 개의 strategy 가 있음
  • RollingUpdate의 경우 한번에 얼마나 많은 개수의 파드를 업데이트 할 것인지 지정 가능, maxSurge와 maxUnavailable의 경우 파드의 개수 또는 퍼센트로 표시 가능
  • Recreate는 전체 삭제 후 전체 생성.

RollingUpdate

strategy:
  type: RollingUpdate
  rollingUpdate:
    maxSurge: 1 # 퍼센트로도 설정 가능하다. 
    maxUnavailable: 1 # 퍼센트로도 설정 가능하다. 

Recreate

strategy:
  type: Recreate

Commands and Arguments

Command YAML

apiVersion: v1
kind: Pod 
metadata:
  name: ubuntu-sleeper-3
spec:
  containers:
  - name: ubuntu
    image: ubuntu
    command:
      - "sleep"
      - "1200"
  • 유의해야할 점은 commnad 아래 리스트는 무조건 String이어야 한다.
FROM python:3.6-alpine

RUN pip install flask

COPY . /opt/

EXPOSE 8080

WORKDIR /opt

ENTRYPOINT ["python", "app.py"]

CMD ["--color", "red"]
  • Dockerfile에서는 ENTRYPOINT 와 CMD로 명령어와 인자 값을 정한다.

도커파일과 yaml파일 상관관계

apiVersion: v1 
kind: Pod 
metadata:
  name: webapp-green
  labels:
      name: webapp-green 
spec:
  containers:
  - name: simple-webapp
    image: kodekloud/webapp-color
    command: ["--color","green"]
FROM python:3.6-alpine

RUN pip install flask

COPY . /opt/

EXPOSE 8080

WORKDIR /opt

ENTRYPOINT ["python", "app.py"]

CMD ["--color", "red"]
  • 위와 같이 Dockerfile에는 ENTRYPOINT와 CMD가 저렇게 설정 되어 있고, Pod의 Yaml 파일에는 command: ["--color","green"] 로 구성되어 있다고 하면 yaml 파일에 있는 내용이 우선적이기 때문에 Pod가 실행되면 --color green 명령어가 실행될 것이다. 결과적으로 아무런 동작을 못하고 오류가 발생함.

Env Variables

명령형으로 ConfigMap 생성

controlplane ~ ➜  k create cm webapp-config-map --from-literal=APP_COLOR=darkblue --from-literal=APP_OTHER=disregard
configmap/webapp-config-map created
  • --from-literal=<KEY>=<VAUUE> 옵션을 이용해서 key value 지정해주면 된다.

파드 특정 env 설정 및 사용

apiVersion: v1
kind: Pod
metadata:
  labels:
    name: webapp-color
  name: webapp-color
  namespace: default
spec:
  containers:
  - env:
    - name: APP_COLOR
      value: green
    image: kodekloud/webapp-color
    name: webapp-color

파드에서 특정 ComfigMap의 Key 참조

apiVersion: v1
kind: Pod
metadata:
  labels:
    name: webapp-color
  name: webapp-color
  namespace: default
spec:
  containers:
  - env:
    - name: APP_COLOR
      valueFrom:
        configMapKeyRef:
          name: webapp-config-map
          key: APP_COLOR
    image: kodekloud/webapp-color
    name: webapp-color

Configmap이 저장된 파일을 mount해서 사용하는 방법

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
  - name: example-container
    image: nginx:latest
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
volumes:
- name: config-volume
  configMap:
    name: my-configmap
    items:
    - key: config-key
      path: my-config-file

정리

# 파드 내에서 env 설정 후 사용하기
containers:
- env:
  - name: APP_COLOR
    value: green


# configMap 전체 불러오기
envFrom:
  - configMapRef:
      name: app-config

# 단일 ENV 불러오기
env:
  - name: APP_COLOR
    valueFrom:
      configMapKeyRef:
        name: app-config
        key: APP_COLOR

# 볼륨으로 불러오기
volumes:
- name: app-config-volume
  configMap:
    name: app-config
  • YAML 구조를 외우는 게 중요할듯 하다.

Secrets

명령어로 Secret 생성하는 법

controlplane ~ ➜  k create secret generic db-secret --from-literal=DB_Host=sql01 --from-literal=DB_User=root --from-literal=DB_Password=password123
secret/db-secret created

Secret Yaml에서 불러오는 예시

piVersion: v1
kind: Pod
metadata:
  labels:
    name: webapp-pod
  name: webapp-pod
  namespace: default
spec:
  containers:
  - image: kodekloud/simple-webapp-mysql
    name: webapp
    envFrom:
    - secretRef:
        name: db-secret
  • Secret도 ENV와 동일하게 여러가지 방법으로 불러올 수 있음

정리

# 단일 Secret 불러오기
env:
  - name: DB_Password
    valueFrom:
      secretKeyRef:
        name: app-secret # <secret name>
        key: DB_Password # secret안에 있는 key name

# Secret 파일 전체 불러오기
envFrom:
  - secretRef: 
      name: app-config # 다른 형식과는 다르게 상위와의 공백을 4개 띄워 줘야함

# 볼륨으로 불러오기
volumes:
- name: app-secret-volume
  secret:
    secretName: app-secret

Multi Container Pods

멀티 컨테이너 예시

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: yellow
  name: yellow
spec:
  containers:
  - command:
    - "sleep"
    - "1000"
    image: busybox
    name: lemon
  - name: gold
    image: redis
  restartPolicy: Always

멀티 컨테이너에서 볼륨 하나를 공유하여 쓰는 법

apiVersion: v1
kind: Pod
metadata:
  name: two-containers
spec:
  restartPolicy: Never
  volumes:
  - name: shared-data
    emptyDir: {}
  containers:
  - name: nginx-container
    image: nginx
    volumeMounts:
    - name: shared-data
      mountPath: /usr/share/nginx/html
  - name: debian-container
    image: debian
    volumeMounts:
    - name: shared-data
      mountPath: /pod-data
    command: ["/bin/sh"]
    args: ["-c", "echo Hello from the debian container > /pod-data/index.html"]
  • volume 을 emptyDir로 설정해주면 되는 듯함, 그리고 해당 네임으로 볼륨 마운트 동시에 해주면 됨

Init Containers

apiVersion: v1
kind: Pod
metadata:
  name: orange
  namespace: default
spec:
  containers:
  - command:
    - sh
    - -c
    - echo The app is running! && sleep 3600
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    name: orange-container
  initContainers:
  - command:
    - sh
    - -c
    - sleep 2
    image: busybox
    imagePullPolicy: Always
    name: init-myservice
  • initContainer가 여러 개 있는 경우 순차적으로 A 실행 이후 B 실행이라 소요 시간을 구할 때는 두 개의 컨테이너를 합쳐서 계산해야 한다.
반응형