본문 바로가기
클라우드

2025 CKA 시험 준비 핵심 요약

by 내기록 2025. 5. 1.
반응형

 

 

2025 CKA 시험을 준비하면서 개인적으로 정리했던 내용들입니다.

한번 쭉 훑어보시는 것도 도움될 것 같아서 올려봅니다.

내용은 대부분 이전 포스팅에서 알려드렸던 udemy, youtube 등을 참고한 문제풀이 및 개인적으로 정리한 내용입니다.

이 내용 외에도 알아야 하는 것이 많으니 참고만 해주세요.

 

 

2025 CKA 합격 후기 / 유형 변경 대응법 및 네트워크 문제 경험 공유

목차 개요2025 CKA 유형이 변경되었습니다. 아직 관련 정보가 많이 없어서, 이번 글에서 변경된 유형에 대한 팁을 정리해보려고 합니다.또한 시험 도중에 인터넷이 끊겨 시험이 종료되는 상황이

sunrise-min.tistory.com

 

 

목차

     

     

    설치 & 환경 구성

    🌟 deb 패키지 설치

    Question No: 11
    
    Complete these tasks to prepare the system for Kubernetes:
    Set up cri-dockerd:
    
    - Install the Debian package:
      ~/cri-dockerd_0.3.9.3-0.ubuntu-focal_amd64.deb
    - Start the cri-dockerd service.
    - Enable and start the systemd service for cri-dockerd.
    
    Configure these system parameters:
    
    - Set net.bridge.bridge-nf-call-iptables to 1.
    - Set net.ipv6.conf.all.forwarding to 1.
    - Set net.ipv4.ip_forward to 1.
    $ dpkg -i ~/cri-dockerd_0.3.9.3-0.ubuntu-focal_amd64.deb 
    
    Selecting previously unselected package cri-dockerd.
    (Reading database ... 140092 files and directories currently installed.)
    Preparing to unpack .../cri-dockerd_0.3.9.3-0.ubuntu-focal_amd64.deb ...
    Unpacking cri-dockerd (0.3.9~3-0~ubuntu-focal) ...
    Setting up cri-dockerd (0.3.9~3-0~ubuntu-focal) ...
    Created symlink /etc/systemd/system/multi-user.target.wants/cri-docker.service → /usr/lib/systemd/system/cri-docker.service.
    Created symlink /etc/systemd/system/sockets.target.wants/cri-docker.socket → /usr/lib/systemd/system/cri-docker.socket.
    
    # 실행
    $ sudo systemctl enable --now cri-docker 
    $ sudo systemctl status cri-docker
    
    # 시스템 관련 매개변수 구성
    <https://kubernetes.io/docs/setup/production-environment/container-runtimes/>
    
    # sysctl params required by setup, params persist across reboots
    cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
    net.ipv4.ip_forward = 1
    EOF
    
    # Apply sysctl params without reboot
    sudo sysctl --system

    매개변수 구성 없는 경우,

    bob@node01 ~ ✖ sudo dpkg -i /root/cri-docker_0.3.16.3-0.debian.deb
    
    Selecting previously unselected package cri-dockerd.
    (Reading database ... 18376 files and directories currently installed.)
    Preparing to unpack .../cri-docker_0.3.16.3-0.debian.deb ...
    Unpacking cri-dockerd (0.3.16~3-0~ubuntu-jammy) ...
    Setting up cri-dockerd (0.3.16~3-0~ubuntu-jammy) ...
    Created symlink /etc/systemd/system/multi-user.target.wants/cri-docker.service → /lib/systemd/system/cri-docker.service.
    Created symlink /etc/systemd/system/sockets.target.wants/cri-docker.socket → /lib/systemd/system/cri-docker.socket.
    /usr/sbin/policy-rc.d returned 101, not running 'start cri-docker.service cri-docker.socket'
    
    bob@node01 ~ ✖ sudo systemctl enable --now cri-docker

     

    🌟Calico install

    The CNI you choose must satisfy following requirement : <native network policy support>

    Install and configure a Container Network Interface (CNI) that satisfies the following conditions.  
    You may choose one of the following options:
    
    - Flannel using the manifest
      <https://github.com/flannel-io/flannel/releases/download/v0.26.1/kube-flannel.yml>
    
    - Calico using the manifest
      <https://raw.githubusercontent.com/projectcalico/calico/v3.29.2/manifests/tigera-operator.yaml>
    
    The chosen CNI must allow:
    
    - Pod-to-Pod communication
    - NetworkPolicy enforcement
    - Must be installed using manifest files (do not use Helm)
    
    다음 조건을 만족하는 CNI(Container Network Interface)를 설치하고 구성하세요.  
    아래 옵션 중 **하나를 선택하여** 설치할 수 있습니다:
    
    - Flannel (매니페스트 사용)
      <https://github.com/flannel-io/flannel/releases/download/v0.26.1/kube-flannel.yml>
    
    - Calico (매니페스트 사용)
      <https://raw.githubusercontent.com/projectcalico/calico/v3.29.2/manifests/tigera-operator.yaml>
    
    선택한 CNI는 반드시 다음 조건을 만족해야 합니다:
    
    - Pod 간 통신이 가능해야 함  
    - NetworkPolicy를 지원해야 함  
    - Helm을 사용하지 말고 매니페스트 파일을 사용하여 설치해야 함
    

    이 문제에서는, CNI 를 두개 다 설치하라는 것이 아니라 다음 조건을 만족하는 CNI를 선택해서 설치하라는 것

     

    • 문제에 “NetworkPolicy를 지원해야 한다” 라고 되어 있음 → 무조건 Calico
    • 단순히 Pod 간 통신만 되게 해라  Flannel이 빠르고 편함

    calico 설치 방법

    # create로 설치해야 한다! apply 사용 X
    🌟 k create -f https://raw.githubusercontent.com/projectcalico/calico/v3.29.2/manifests/tigera-operator.yaml
    # 테스트
    kubectl run test1 --image=busybox --restart=Never -- sleep 3600
    kubectl run test2 --image=busybox --restart=Never -- sleep 3600
    
    kubectl exec test1 -- ping -c 4 test2
    
    # calico pod 생성 확인
    k get pods -n kube-system

     

    +++

    # calico 설치 시, 옵션 변경이 필요한 부분이 있으면
    # curl -o https://.. 로 파일 다운로드 받은 다음 수정합니다.

     

     

     

    Flannel Install

    문제
    Install and configure a Container Network Interface (CNI) of your choice that meets the specified requirements. Choose one of the following CNI options:
    
    Flannel (v0.26.1)
    using the manifest:
    [kube-flannel.yml]
    (<https://github.com/flannel-io/flannel/releases/download/v0.26.1/kube-flannel.yml>)
    
    Calico (v3.28.2)
    using the manifest:
    [tigera-operator.yaml]
    (<https://raw.githubusercontent.com/projectcalico/calico/v3.28.2/manifests/tigera-operator.yaml>)
    
    Ensure the selected CNI is properly installed and configured in the Kubernetes cluster.

    여기서는 networkPolicy 같은 조건이 없으므로 Flannel 설치해도 무방함

    k apply -f <https://github.com/flannel-io/flannel/releases/download/v0.26.1/kube-flannel.yml>
    
    # 확인
    k get po -n kube-flannel

     

     

     

    🌟Helm

    CRD

    CRD = Custom Resource Definition (사용자 정의 리소스 정의)

    🌟 사이즈가 크기 때문에 CRD 가 있는 파일은 kubectl create -f 로 설치합니다.

    1. CRD 먼저 등록 (Application이라는 리소스 정의)
    
    2. 이제부터 아래 같은 리소스를 쓸 수 있음:
       apiVersion: argoproj.io/v1alpha1
       kind: Application
       
    kubectl get crd 로 조회 가능

     

    Helm template

    • Helm chart를 실제로 Kubernetes에 설치하지 않고, 생성될 리소스들을 YAML 형태로 출력해주는 명령어
    helm template argocd argo/argo-cd --version 7.7.3 -n argocd \\
    --set crds.install=false > ~/argo-helm.yaml

    values 보는 방법

    helm show values argo/argo-cd --version 7.7.3

    helm template은 렌더링된 YAML 출력, helm pull은 Chart 구조 전체를 디렉토리로 저장

     

    helm install

    helm repo add agro https://..

    argo-cd 설치 시 아래와 같은 에러가 뜨면, crd 가 이미 설치되어 있다는 것

    이때는 —skip-crds 옵션 사용

    Error: rendered manifests contain a resource that already exists. 
    Unable to continue with install: CustomResourceDefinition "applications.argoproj.io" already exists

    만약, —skip-crds 옵션이 안먹으면?

    아래에서 옵션을 보고, —set crds.install=false 설정.

    시험에서 주는 argo 공식 문서에 들어가면 바로 --set crds.install=false 쓰라고 나옴

    helm show values argo/argo-cd --version 7.7.3
    # 이미 생성된 helm release에 대해 values 조회 가능
    helm get values kocoon-hermes -n logging

     

    helm pull

    helm pull <chart-name> [flags]
    # 압축 해제하고 저장
    helm pull argo/argo-cd --version 7.7.3 --untar --untardir ./charts

     

    kustomize

    my-kustomize/
    ├── base/
    │   ├── deployment.yaml
    │   ├── service.yaml
    │   └── kustomization.yaml
    └── overlays/
        └── prod/
            ├── kustomization.yaml
            └── deployment-patch.yaml
    
    ---
    apiVersion: kustomize.config.k8s.io/v1beta1
    kind: Kustomization
    
    resources:
      - ../../base
    
    namespace: prod
    
    namePrefix: prod-
    
    commonLabels: # 모든 리소스에 라벨 추가
      env: prod
    
    patchesStrategicMerge:
      - deployment-patch.yaml
      
    ---
    
    # 리소스 생성
    kubectl apply -k overlays/prod
    
    # 적용하지 않고 눈으로만 결과 확인
    kubectl kustomize overlays/prod
    
    # yaml 파일로 저장 (제출용)
    kubectl kustomize overlays/prod > /root/final.yaml

     

    권한 / 보안

    Priorityclass

    리소스가 부족할 때 “누굴 먼저 죽이고 누굴 살릴지” 결정하는 기준으로 매우 중요한 역할

    즉, Priority class는 파드의 생존 우선순위를 정하는 값이다.

    문제
    Perform the following tasks:
    Create a new PriorityClass named high-priority for user workloads 
    with a value that is one less than the highest existing user-defined 
    priority class value.
    
    Patch the existing Deployment busybox-logger running 
    in the priority namespace to use the high-priority priority class. 
    
    Ensure that the busybox-logger Deployment rolls out successfully 
    with the new priority class set.
    
    Note - It is expected that pods from other Deployments running 
    in the priority namespace are evicted.
    k create priorityclass high-priority --value=999
    
    deployment에서 아래처럼 설정
    spec: 
    	priorityClassName: "high-priority"

    만약, 파드가 안뜨면?

    # k describe pod로 이유 확인
    # 강제 재시작
    k rollout restart deployment busybox-logger -n priority
    spec:
    	priorityClassName: high-priority
    	preemptionPolicy: PreemptLowerPriority // 기본값
    

    preemptionPolicy는 기본값이 나보다 우선순위 낮은 pod는 쫓아내고(eviction) 자리를 만든다.

    0/3 nodes are available: 1 Insufficient memory, 2 Pods have higher priority
    
    // 3개의 노드 중 어느 곳에서도 스케줄할 수 없음
    // 1 Insufficient memory : 한 개의 노드는 메모리가 부족함
    // 2 Pods have higher priority and do not preempt : 나머지 2개 노드는 우선순위 높은 Pod 가 있고, 쫓아낼 수 없다
    • PreemptionPolicy
      • PreemptLowerPriority(기본값) 자신보다 우선순위가 낮은 pod를 쫓아낼 수 있음
      • Never : 절대로 다른 pod를 쫓아내지 않음

    Pod Security Admission(PSA)

    PodSecurityPolicy (PSP) 는 Kubernetes 1.25에서 완전히 제거

    PSA(Pod Security Admission) 은 Pod 자체에 설정하는 게 아니라, Namespace에 레이블을 붙여서 해당 네임스페이스 내 모든 Pod을 제어하는 구조

    pod-security.kubernetes.io/enforce 적용할 모드 (restricted / baseline / privileged)
    pod-security.kubernetes.io/enforce-version 보안 정책의 버전 (예: latest)
    pod-security.kubernetes.io/warn 적용은 안 하고 경고만 표시
    pod-security.kubernetes.io/audit 로그에만 기록
    • privileged: 제한 거의 없음 (테스트용이나 관리자용)
    • baseline: 최소한의 제약
    • restricted: 가장 보안 수준이 높은 모드
    # 1. 네임스페이스 만들고
    kubectl create ns secure-ns
    
    # 2. restricted 정책 적용
    kubectl label ns secure-ns \\
      pod-security.kubernetes.io/enforce=restricted \\
      pod-security.kubernetes.io/enforce-version=latest
        
    # namespace 라벨 조회
    k get ns --show-labels
    
    # 예시) restricted는 이런 설정이 있어야 통과
    securityContext:
      runAsNonRoot: true
      allowPrivilegeEscalation: false
      
    securityContext:
    	runAsUser: 0 # restricted에선 root 금지!
    	runAsNonRoot: true # root 대신 일반 유저 -> 통과

    이제 secure-ns 네임스페이스에서 Pod을 생성하면, Pod가 restricted 정책을 위반할 경우 → 생성 거부

    k8s에서 Pod나 리소스를 생성하려고 할 때, API 서버가 생성 전에 “검열” 하는 단계가 있는데 이때 개입하는 것이 바로 Admission Controller이다. PSA는 AdmissionController 중 하나로, Pod 생성 요청이 들어오면 보안 정책을 기준으로 허용/거부 여부를 결정함.

    kubectl get ns secure-ns --show-labels
    • [PSA(Pod Security Admission)
    k label namespace restricted-ns pod-security.kubernetes.io/enforce=restricted
    k label namespace restricted-ns pod-security.kubernetes.io/enforce-version=v1.24

     

    securityContext

    컨테이너 또는 Pod 수준에서 보안 관련 설정을 지정하는 필드

    • privileged : 컨테이너에 호스트 수준의 강력한 권한을 부여할지 여부를 설정하는 옵션
    • capabilities:
    • securityContext: capabilities: add: ["NET_ADMIN", "SYS_TIME"] drop: ["ALL"]
    apiVersion: v1
    kind: Pod
    metadata:
      name: mypod
    spec:
      securityContext:         # Pod 수준
        runAsNonRoot: true
        fsGroup: 2000 # 볼륨에 접근할 때 group 권한 부여. pod 수준에서만 가능
    
      containers:
      - name: nginx
        image: nginx
        securityContext:       # 컨테이너 수준 <- 보통 이걸 많이쓴다고 함
          privileged: false # 웬만하면 false로 하자. 이게 true 라서 안뜨는 문제 많이나옴
          allowPrivilegeEscalation: false # 실행 중에 권한 상승을 허용할지 여부
    

     

    runAsNonRoot: true root 계정 실행 차단 ✅ 필수 없으면 거의 무조건 막힘
    runAsUser: 1000 특정 UID로 실행 ✅ 가능 root UID(0)이면 막힘
    privileged: true 호스트급 권한 부여 ❌ 금지 거의 시험에서 거부 이유로 나옴
    allowPrivilegeEscalation: false sudo 등 권한 상승 금지 ✅ 필수 없으면 PSA에서 막힘
    capabilities.add 위험 기능 추가 ❌ 금지 특히 NET_RAW, SYS_ADMIN
    가능: SYS_TIME      
    capabilities.drop: ["ALL"] 기능 모두 제거 ✅ 권장 PSA 통과 안정용
    readOnlyRootFilesystem: true 루트 파일시스템 읽기 전용 ✅ 권장 필수는 아님

    Default Mode

    Config, Secret 등을 Pod 안에 “파일처럼” 마운트할 때, 그 파일의 퍼미션을 설정하는 옵션

    defaultMode = 마운트된 파일 권한 설정으로 기본값은 보통 0644

    볼륨 타입이 configMap, secret, downwardAPI처럼 "파일로 마운트되는 리소스"일 때만 가능

    디렉토리에는 적용 못하고, 파일에만 적용됨 디렉토리는 무조건 0755로 고정

    일반 볼륨(emptyDir, hostPath, PVC)에는 적용 안됨!

    volumes:
      - name: config-vol
        configMap:
          name: my-config
          defaultMode: 0400   # ← 이게 파일 퍼미션 설정
    

     

    Taint 종류 보기 (NoSchedule..)

    노드에 조건을 걸어서, 특정 Pod만 올라올 수 있게 막는 기능

       
    NoSchedule Pod이 안 떠서 원인 찾는 문제에 자주 등장
    NoExecute 이 테인트를 허용하지 않는 파드는 즉시 evection
    toleration 설정에 tolerationSeconds 명시하지 않고 이 테인트를 허용하는 파드는 영구 유지
    PreferNoSchedule 보통 설명형 문제나 비교 문제로 등장

     

    value 없음 key:NoSchedule (예: node-role.kubernetes.io/master:NoSchedule)
    value 있음 key=value:NoSchedule (예: env=prod:NoSchedule)

     

    ✅ NoSchedule

    “Pod이 특정 노드에 스케줄되지 않음. → kubectl describe node → taint 확인 → 해결책은 toleration 추가

    $ kubectl get pod nginx -o wide
    NAME    READY   STATUS    RESTARTS   AGE   NODE
    nginx   0/1     Pending   0          1m    <none>
    
    $ kubectl describe node node1 | grep Taint
    Taints:    node-role.kubernetes.io/master:NoSchedule
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
      tolerations:
      - key: "node-role.kubernetes.io/master"
        operator: "Exists"
        effect: "NoSchedule"

     

    ✅ NoExecute

    “Pod이 정상적으로 실행되었으나 일정 시간 후 사라짐”

    NoExecute는 조건부로 얼마만큼은 버텨도 된다. 라는 개념이 있다.

    → NoExecute taint로 인해 evicted

    → toleration에 tolerationSeconds 필요

    Taints: zone=test:NoExecute
    
    spec:
      containers:
      - name: nginx
        image: nginx
      tolerations:
      - key: "zone"
        operator: "Equal"
        value: "test"
        effect: "NoExecute"
        tolerationSeconds: 60 # 60초만 떠있다가 내려감.
    

    Affinity

    • requiredDuringSchedulingIgnoredDuringExecution : 무조건 만족해야 하는데, 스케줄링할 때 검사하고 한번 스케줄링된 다음에는 더이상 신경쓰지 않겠다. (파드가 노드에서 제거evicted 되지 않음)
    • preferredDuringSchedulingIgnoredDuringExecution : 필수조건 통과한 노드 중 가중치
    • Affinity
      • nodeAffinity : 특정 노드에 파드 배치 유도
      • podAffinity : 어떤 라벨을 가진 파드와 같은 노드에 배치 유도
      • podAntiAffinity : 같은 라벨을 가진 파드가 같은 노드에 배치되지 못하게 함
    • nodeAffinity
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: disktype
                operator: In
                values:
                - ssd            
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
    

    스케줄러가 선호할 노드를 지정할 수 있다.

    A에 스케줄링되기를 원하지만, 만약 A에 파드를 위한 공간이 충분치 않거나 스케줄링할 수 없는 다른 중요한 이유가 있는 경우 다른 곳에 스케줄링되어도 된다.

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 1 # 1~ 100 까지 있는데 100이 가중치가 높음
            preference:
              matchExpressions:
              - key: disktype
                operator: In
                values:
                - ssd          
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
    
    

    책에 나온 예제

    spec:
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 80
            preference:
              matchExpressions:
              - key: availability-zone
                operator: In
                values:
                - zone1
          - weight: 20
    	      preference:
    		      matchExpression:
    		      - key: share-type
    			      operator: In
    			      values:
    			      - dedicated
    
    • podAffinity
    apiVersion: v1
    kind: Pod
    metadata:
      name: with-pod-affinity
    spec:
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution: # 필수
          - labelSelector:
              matchExpressions:
              - key: security
                operator: In
                values:
                - S1
            topologyKey: topology.kubernetes.io/zone
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: security
                  operator: In
                  values:
                  - S2
              topologyKey: topology.kubernetes.io/zone
      containers:
      - name: with-pod-affinity
        image: registry.k8s.io/pause:3.8
    
    
    • topolgyKey

    pod affinity 및 anti-affinity에서 topologyKey는 필수이다.

    topologyKey 속성은 파드를 배포해서는 안 되는 범위를 결정한다. 이를 사용해 파드가 동일한 랙, 가용 영역, 리전 또는 사용자 지정 노드 레이블을 사용해 만든 사용자 지정 범위에 배포되지 않도록 할 수 있다.

     

    ⭐️ topologyKey 값 뒤에만 다른거 아니니까 뒤에만 바꾸지말고 전체 복사 똑바로 하기.

    같은 zone 안에 스케줄링 topology.kubernetes.io/zone
    같은 노드 안에 스케줄링 kubernetes.io/hostname

     

    NodeAffinity 랑 PodAffinity 랑 사용법 약간 다름 주의

        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: security
                  operator: In
                  values:
                  - S2
              topologyKey: topology.kubernetes.io/zone

     

    Pv node affinity

    Pv에 node affinity 가 있으면, 해당 pv를 사용하는 Pod도 해당 노드에 떠야 합니다.

    pod는 node01에 떠있음, pv는 nodeAffinity가 있어서 node02 전용, pvc-pv 바인딩 상태

    pod 에서 pvc 바운드 하려면 실패 (이 노드에서는 해당 볼륨을 사용할 수 없다는 에러메시지)

    FailedAttachVolume: volume "static-pv-example" is not attached to the node
    pod has unbound immediate PersistentVolumeClaims

    pod가 해당 pv 사용하려면, pod를 node02에 뜨게 해야함

    spec:
      nodeSelector:
        kubernetes.io/hostname: node02

    nodeAffinity는 스케줄링과 관련된 리소스에 적용 가능

    • Pod, PV, StatefulSet, Deployment, Job, DaemonSet

    nodeAffinity는 Pod/PV 에서 사용 시 구조가 다릅니다.

    Pod affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution
    PV nodeAffinity.required.nodeSelectorTerms
    # pod
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: kubernetes.io/hostname
                    operator: In
                    values:
                      - node-1
    
    # pv
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: disktype
                operator: In
                values:
                - ssd
    

     

    워크로드

    🌟HPA

    문제
    Create a new HorizontalPodAutoscaler (HPA)
    named apache-server in the autoscale namespace.
    This HPA must target the existing Deployment called apache-server in the autoscale namespace.
    Set the HPA to target for 50% CPU usage per Pod.
    
    • Configure hpa to have at min 1 Pod and no more than 4 Pods [max].
    Also, we have to set the downscale stabilization window to 30 seconds.

    ✅ behavior는 spec 하위에 있음

    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
      name: apache-server
      namespace: autoscale
    spec:
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: apache-server
      minReplicas: 1
      maxReplicas: 4
      metrics:
      - type: Resource
        resource:
          name: cpu
          target:
            type: Utilization
            averageUtilization: 50
      behavior:
    	  scaleDown:
    	    stabilizationWindowSeconds: 30
    

    🌟SideCar

    문제
    Update the existing deployment synergy-leverager, 
    adding a co-located container named sidecar using the busybox:stable image 
    to the existing pod.
    
    The new co-located container has to run the following command:
    /bin/sh -c "tail -n+1 -f /var/log/synergy-leverager.log"
    Use a volume mounted at /var/log to make the log file synergy-leverager.log 
    available to the co-located container.
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: synergy-leverager
      labels:
        app: synergy-leverager
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: synergy-leverager
      template:
        metadata:
          labels:
            app: synergy-leverager
        spec:
          containers:
            - name: app
              image: nginx:latest
              volumeMounts:
                - name: log-volume
                  mountPath: /var/log
    	      - name: sidecar
    		      image: busybox:stable
    		      command: ["/bin/sh", "-c", "tail -n+1 -f /var/log/synergy-leverager.log"]
    		      volumeMounts:
    			      - name: log-volume
    					    mountPath: /var/log
          volumes:
            - name: log-volume
              emptyDir: {}
    

    테스트

    k get log -f synergy-leverager-abcd -c sidecar

     

    ++++++

     

    apiVersion: v1
    kind: Pod
    metadata:
      name: mc-pod
      namespace: mc-namespace
    spec:
      containers:
      - name: mc-pod-1
        image: nginx:1-alpine
        env:
          - name: NODE_NAME # 여기 복붙하고 바로지말고 수정 잘해
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName # 여기중요!
      - name: mc-pod-2
        image: busybox:1
        command:
          - sh
          - -c
    	  - "while true; do date >> /var/log/shared/date.log; sleep 1; done" # sidecar 예제보면 있음
        volumeMounts:
        - mountPath: /var/log/shared
          name: cache-volume
      - name: mc-pod-3
        image: busybox:1
        command:
          - sh
          - -c
          - "tail -f /var/log/shared/date.log"
        volumeMounts:
        - mountPath: /var/log/shared
          name: cache-volume
      volumes:
      - name: cache-volume
        emptyDir: {}

     

     

    1초마다 찍는 이유는, echo는 빠르게 실행되고 끝나기 때문에 컨테이너는 바로 Exit 0 (정상 종료) 상태가 되어버림

    그 순간 kubelet이 보기에 이건 “일 끝났네?” → 재시작 시도 → 반복 → CrashLoopBackOff 혹은 Completed 등 상태로 빠짐

    log 관련 sidecar 문제는 공식 문서에서 sidecar 검색해서 바로 보는게 편함

    command:
      - sh
      - -c
      - "while true; do date >> /var/log/shared/date.log; sleep 1; done"

     

    Node 자원 3등분해서 pod 생성

    문제
    
    You manage a WordPress application. Some pods are not up and running.
    Adjust all Pod resource requests as follows:
    
    Divide node resources evenly across all 3 pods.
    
    Give each Pod a fair share of CPU and memory.
    
    Add enough overhead to keep the node stable.
    
    Note - Use exact same requests for both containers and init containers.
    Scale down the wordpress deployment to 0 replicas while updating the resource requests.
    
    After updates, confirm: WordPress keeps 3 replicas.
    All Pods are running and ready.

     

    k describe node | grep -i capacity A5
    
    # 하지만, 보다보니 capacity가 아닌 Allocatable 값을 3등분하는게 맞는 것 같음
    k describe node | grep -i allocatable A5
    # requests만 설정!
        resources:
          requests:
            memory: "6774503Ki"
            cpu: "3"
    

    kubectl label

    리소스에 라벨을 추가할 때 사용

    k label pod my-pod app=web // 라벨 추가
    k label pod my-pod app=backend --overwrite // 라벨 수정
    k label pod my-pod app- // 라벨 삭제

    downward api

    클러스터 정보를 Pod안으로 전달되는 방식 (downward : 아래쪽으로, 하위로)

    Pod안에서 자기 자신의 메타데이터(이름, 네임스페이스, 레이블, CPU 리소스 등)를 환경변수나 파일 형태로 받아볼 수 있는 기능

    환경 변수로 넣는 문제가 훨씬 자주 출제됨

    • fieldRef : pod의 메타데이터
    • resourceFieldRef : 컨테이너가 요청한 리소스 정보(cpu, memory 등)를 가져오는 기능
    # 환경 변수
        env:
          - name: MY_POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
    
        env:
          - name: CPU_REQUEST
            valueFrom:
              resourceFieldRef:
                resource: requests.cpu
                divisor: 1Mi   # ← 바이트 대신 Mi 단위로 변환
    
    # 볼륨 파일
        volumeMounts:
          - name: podinfo
            mountPath: /etc/podinfo
            readOnly: true
      volumes:
        - name: podinfo
          downwardAPI:
            items:
              - path: "pod_name"
                fieldRef:
                  fieldPath: metadata.name
    

     

    Pod TroubleShooting (nodeName, nodeSelector)

    0/3 nodes are available: 
    1 Insufficient cpu, 
    2 Insufficient memory
    # 각 노드별 리소스 확인
    k describe nodes | grep -i allocatable -A5
    
    # pod의 requests 확인하고, 노드에서 리소스 감당 못하면 requests 값을 줄인다.
    # 또는! pod를 특정 노드에 강제로 띄운다.

    nodeName / nodeSelector

    • nodeName
      • 스케줄러 건너뛰고 해당 노드에 직접 할당
      • pod affinity/taint 무시하고 넣어버려서 문제가 좀 있음
    • spec: nodeName: node01
    • nodeSelector
      • 스케줄러가 라벨이 일치하는 노드를 골라서 조건에 맞는 노드에 배치할 수 있게 제한하는 방식
    • spec: nodeSelector: kubernetes.io/hostname: node01

     

    Service & Network

    Service - expose

    Create a service messaging-service to expose the messaging application within the cluster on port 6379.

    controlplane ~ ✖ k expose pod messaging --port=6379 --name=messaging-service

    kubectl expose 명령어로 Service를 만들 때, Pod의 ContainerPort를 자동으로 targetPort로 사용해준다.

    만약 Pod에 containerPort가 따로 없거나 찾을 수 없으면? 그냥 동일하게 targetPort = port 로 지정한다.

    따라서 clusterIP 만들때는 expose 명령어 사용하자.

    🌟NetworkPolicy

    모든 ingress 요청 허용하려면, 아래와 같이 설정한다.

    이 외에 networkpolicy 개념 중요하니 많이 알아두기.

    ingress:
    - ports:
      - protocol: TCP
        port: 80
    

    NodePort

    문제
    spline-reticulator 네임스페이스에 있는 기존 front-end Deployment를 수정해서 
    nginx 컨테이너의 80번 포트(TCP)를 노출하시오.
    front-end-svc라는 이름의 새로운 Service를 생성하고, 해당 컨테이너 포트 80/tcp를 노출하시오.
    새로 만든 서비스가 NodePort를 통해 개별 Pod에 접근할 수 있도록 구성하시오.
    (Configure the new service to also expose the individual pod via a NodePort)
    # deployment로 떠있는 ⭐️Pod의 label 확인
    # kubectl get pod --show-labels
    
    # deployment 수정해서, 80포트로 설정
    ports:
    	- containerPort: 80
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: front-end-svc
    spec:
      type: NodePort
      selector:
    	app: front-end # spec.template.metadata.labels 기준으로 selector 작성    
      ports:
        - port: 80
          targetPort: 80
    

     

    Headless Service + StatefulSet

    고정된 DNS는 Headless Service가 있어야 가능하다 !

    headless : ClusterIP없이 파드들을 직접 노출하는 서비스

    가상의 IP가 없고, 요청이 바로 파드로 가니까 머리(head)가 없는 것처럼 동작

    ✅ Stable Network Identities?

    StatefulSet의 Pod들이 재시작되거나 재스케쥴되더라도 항상 고정된 네트워크 주소(DNS 이름)을 갖는 것

    web-0 → 항상 web-0.web.default.svc.cluster.local
    web-1 → 항상 web-1.web.default.svc.cluster.local
    kind: StatefulSet
    metadata:
      name: web
    spec:
      serviceName: web
      replicas: 2
      
    ---
    
    kind: Service
    metadata:
      name: web
    spec:
      clusterIP: None # 핵심!
    

    Service가 Headless일 경우

    • clusterIP: None이면 각 Pod DNS가 직접 노출됨
    • Headless Service (clusterIP: None)가 있고, StatefulSet이 해당 서비스를 serviceName:으로 지정

    → CoreDNS가 자동으로 생성해줌

     

    참고) Headless를 사용하는 이유?

    StatefulSet을 사용하는 목적은 보통 Kafka, ZooKeeper, MySQL, MongoDB처럼,

    → 노드 간 직접 통신이 필요하고, 서로의 고정 주소를 알아야 하는 시스템에 쓰기 때문

    → 이때 Headless Service가 없으면 DNS 주소가 생기지 않아서 의미가 없음.

     

    ⭐️ Ingress to Gateway API

    ✅ Ingress TLS 는 Gateway에 설정한다.

    gateway tls 검색하면,

    Gateway API v1.1: Service mesh, GRPCRoute, and a whole lot more 클릭하면 예제있음.

    문제
    Migrate an existing web application from Ingress to Gateway API.
    We must maintain HTTPS access.
    
    A GatewayClass named nginx is installed in the cluster.
    
    First, create a Gateway named web-gateway with hostname gateway.web.k8s.local
    that maintains the existing TLS and listener configuration 
    from the existing ingress resource named web.
    
    Next, create an HTTPRoute named web-route with hostname gateway.web.k8s.local
    that maintains the existing routing rules 
    from the current Ingress resource named web.
    
    You can test your Gateway API configuration with the following command:
    curl <https://gateway.web.k8s.local>
    
    Finally, delete the existing Ingress resource named web.
    • 참고) 기존 Ingress
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: web
    spec:
      tls:
      - hosts:
        - gateway.web.k8s.local
        secretName: web-tls
      rules:
      - host: gateway.web.k8s.local
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web-service
                port:
                  number: 80
    

    Ingress → gateway, httproute 로 변경할 때 hostname 이 있으면 둘 다 일치시켜줘야 제대로 동작

    • gateway 생성
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: web-gateway
    spec:
      gatewayClassName: nginx
      listeners:
      - name: https
        protocol: HTTPS
        port: 443
        hostname: gateway.web.k8s.local
        tls:
    	    certificateRefs:
    		  - kind: Secret
    			  name: web-tls
    
    • HTTPRoute 생성
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: web-route
    spec:
      parentRefs:
      - name: web-gateway
      hostnames:
      - "gateway.web.k8s.local"
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /
        backendRefs:
        - name: web-service
          port: 80
    
    k get httproute
    
    # web-gateway.yaml
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: web-gateway
      namespace: cka5673
    spec:
      gatewayClassName: kodekloud
      listeners:
        - name: https
          protocol: HTTPS
          port: 443
          hostname: kodekloud.com # 이 도메인으로 오는 요청만 받아라
          tls:
            certificateRefs:
              - name: kodekloud-tls # 여기!
    

    httpRoute

    HTTPRoute - hostnames은 어떤 도메인 이름(Host)으로 들어온 요청을 받을지를 설정.

    즉, hostnames에 지정한 이름이 아니면, 요청이 무시된다.

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: example-route
    spec:
      hostnames:
      - "www.example.com"
      - "api.example.com"
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /app
        backendRefs:
        - name: app-service
          port: 80
    

    Ingress

    spec:
      ingressClassName: nginx # ingress class
      rules:
      - host: kodekloud-ingress.app # 요청한 host이름. 해당 host일때만 ingress 동작
        http:
          paths:
          - path: / # 요청 url의 경로가 / 로 시작할 때 적용한다.
            pathType: Prefix # /로 시작하는 모든 경로를 매칭시킨다.
            backend:
              service:
                name: webapp-svc # 요청을 이 서비스로 넘긴다
                port:
                  number: 80 # 해당 서비스의 80번 포트로 트래픽 넘긴다
    

     

    스토리지

    🌟StorageClass

    문제
    First, create a new StorageClass named local-path for 
    an existing provisioner named rancher.io/local-path. 
    Set the volume binding mode to WaitForFirstConsumer.
    
    Note – Not setting the volume binding mode or 
    setting it to anything other than WaitForFirstConsumer may result in reduced score. 
    Next, configure the StorageClass local-path as the default StorageClass.
    Note – Do not modify any existing Deployments 
    or PersistentVolumeClaims. Failure to do so may result in a reduced score.
    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: local-path
      annotations:
        storageclass.kubernetes.io/is-default-class: "true"
    provisioner: rancher.io/local-path
    volumeBindingMode: WaitForFirstConsumer
    

    디폴트 스토리지클래스 설정 방법

    • 기존 디폴트 스토리지클래스에서 디폴트 어노테이션 삭제
    • 신규 디폴트 스토리지클래스에 디폴트 어노테이션 추가
    metadata:
      name: my-fast-sc
      annotations:
        storageclass.kubernetes.io/is-default-class: "true"

     

    PV 복구

    문제
    A MariaDB Deployment in the mariadb namespace has been deleted by mistake.  
    Your task is to restore the Deployment ensuring data persistence. Follow the steps:
    
    • Create a PersistentVolumeClaim (PVC) named mariadb in the mariadb namespace  
      with the following specifications:  
      Storage 250Mi
    
    • Note - You must use the existing retained PersistentVolume (PV).  
      There is only one existing PersistentVolume.  
      Edit the MariaDB Deployment file located at ~/mariadb-deployment.yaml  
      to use the PVC you created in the previous step.  
      Apply the updated Deployment file to the cluster.
    기존 pv가 retain이면,
    pv를 보고 호환되면 pvc 생성. 이때, deployment에서 사용하는 pvc명 동일하게 써도 됨
    없으면 deployment에 추가합니다.


    volume, configmap - subPath

    subPath를 사용하면, configmap 중에서 특정 key 만 파일로 저장할 수 있다.

    key 이름은 subPath 값으로 넣어주고, 파일 경로는 mountPath에 지정한다.

    ❓ my-config ConfigMap의 debug.conf 키만
    /etc/config/debug.conf 경로에 파일로 마운트되도록 Pod을 작성하세요.
    
    ---
          volumeMounts:
            - name: config
              mountPath: /etc/app/app.conf
              subPath: app.conf
      volumes:
        - name: config
          configMap:
            name: my-config

     

    출력

    🌟explain 결과(명세) 조회

    문제
    
    Task:
    Verify the cert-manager application which has been deployed in the cluster.
    Create a list of all cert-manager Custom Resource Definitions (CRDs) and save it to ~/resources.yaml.
    make sure kubectl's default output format and use kubectl to list
    CRD's
    Do not set an output format.
    Failure to do so will result in a reduced score.
    
    Using kubectl, extract the documentation for the subject specification field of the Certificate Custom Resource and save it to ~/subject.yaml.
    You may use any output format that kubecl supports.

    k get crd | grep -i cert-manager > ~/resources.yaml
    
    k explain certificates.spec.subject > ~/subject.yaml

     

    jsonpath 사용

    k get nodes -o jsonpath='{.items[*].status.images[*].sizeBytes}'
    
    # 제일 첫번째 range .items[*]는 loop 도는 대상
    # 뒤에 있는게 출력 대상
    # 아래 두개는 출력 결과가 다름!
    k get nodes -o jsonpath='{range .items[*]}{.status.images[*].sizeBytes}{"\\n"}{end}'
    k get nodes -o jsonpath='{range .items[*].status.images[*]}{.sizeBytes}{"\\n"}{end}'
    

     

    트러블 슈팅

    journalctl

    systemd 리눅스 시스템에서, 시스템 로그를 확인할 수 있게 해주는 명령어

    kubelet 상태 확인 시 사용된다.

    -u : unit
    -n : 100줄까지 보여줘.
    
    journalctl -u kubelet -n 100

     

     

    Pod

    k8s 클러스터는 pod가 스케쥴 되지 않는 이유를 노드 단위로 표현한다.

    그래서 PVC 문제여도 노드 리스트(0/2 nodes) 형태로 에러를 보여준다.

    • Node 1: "이 Pod를 받을 수 없음 (PVC unbound 때문)"
    • Node 2: "이 Pod를 받을 수 없음 (PVC unbound 때문)"

    각각의 노드에서 스케줄 실패를 기록해서 최종 출력이 0/2 nodes are available 처럼 보임.

    Warning  FailedScheduling  default-scheduler
    0/2 nodes are available: pod has unbound immediate PersistentVolumeClaims.
    preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling.
    # 다른 파드 죽이기 해봐야 소용이 없다. 자원문제가 아니라는 말.

    pod가 요구하는 node affinity 조건에 맞지 않는 것 하나

    control-plane인데 pod에 toleration이 없다.

    그래서 사용 가능한 노드가 없고, 타 자원 삭제는 도움이 안된다 (자원 문제 아님)

    0/2 nodes are available:
    - 1 node(s) didn't match Pod's node affinity/selector,
    - 1 node(s) had untolerated taint {node-role.kubernetes.io/control-plane: }.
    preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling.

    (참고)

    에디터 열고 수정했을 때 발생하는 에러

    수정한 yaml 내용이 k8s validation 규칙에 맞지 않아서 서버가 거부했다.

    왜냐면, pod같은 Immutable 리소스는 특정 필드를 수정할 수 없기 때문. 그래서 수정 불가한 필드를 바꾸거나 했을 때 invalid 에러가 뜸

    error: pods "frontend" is invalid
    A copy of your changes has been stored to "/tmp/kubectl-edit-2440713918.yaml"
    error: Edit cancelled, no valid changes were saved.

    Pod가 시작되려고 하는데, kubelet이 ConfigMap이나 Secret을 API 서버에서 가져오지 못했다.

    특히, kube-api-access-xxx는 Pod가 ServiceAccount 토큰, CA 인증서 등을 자동으로 mount할 때 사용하는 내부 시스템 볼륨이다.

    MountVolume.SetUp failed for volume "kube-api-access-xxxx" : 
    failed to sync configmap cache: timed out waiting for the condition

     

    kubelet

    kubelet은 systemctl로 떠있으니까, journalctl로 로그 봅니다.

    journalctl -u kubelet -n 100
    
    # 설정파일 위치 알고싶으면
    systemctl cat kubelet
    
    # journalctl로 확인한 정보
    # 해당 설정 파일이 없거나 깨져있다.
    rror failed to read kubelet config file \\"/var/lib/kubelet/config.yaml\\", error: open /var/lib/kubelet/config.yaml: no such file or directory"
    
    # 해당 파일을 봐야겠군!

    🌟 위와 동일하게 파일이 문제였는데, 이 설정값이 비어있어서 notReady 상태였다!

    containerRuntimeEndpoint: unix:///run/containerd/containerd.sock
    

     

    Deployment

    상황 : deployment 가 replica 2 로 설정되었으나 아무런 에러없이 그냥 0

    rs 도 생성 안돼있음.

    ReplicaSet이 생성되지 않은 이유 ?
    controlplane 노드에 kube-controller-manager가 죽어 있거나 비정상이다.
    
    왜 kube-controller-manager가 문제인가 ?
    Deployment → ReplicaSet 생성 작업은 kube-controller-manager가 담당하는데,
    
    kube-controller-manager가 죽어 있으면, Deployment는 etcd에 등록되지만
    ReplicaSet을 만들어주는 작업이 수행되지 않는다.
    
    결국 controller 트러블슈팅
    

    label 변경은 3군데 다 바꾸자.

     

    kubelet

    # 이건 꼭 알아야하는 트러블슈팅 포인트로, kubelet이 CRI랑 통신할 때 필요한 설정
    container-runtime-endpoint
    
    # staticpod yaml path
    staticPodPath: /etc/kubernetes/manifests

    api 서버의 포트는 어디서 볼 수 있는가?

    # yaml 파일에서 아래 설정!
    --secure-port=6443
    controlplane:~$ k get pods -n kube-system
    The connection to the server 172.30.1.2:6443 was refused - did you specify the right host or port?

     

    ServiceAccount

    sa 에서 can-i 쓸때는 —as 뒤를 아래처럼 해야 함

    controlplane:~$ kubectl auth can-i create pods --as system:serviceaccount:default:dev-sa

    configmap

    kubectl set env deployment/cm-webapp -n cm-namespace \\
      --from=configmap/app-config

     

    기타 팁 & 명령어

    Cluster node join

    # CA 키 해시는 아래 명령어 출력 결과에 출력된다.
    kubeadm token create --print-join-command
    
    # workernode면 위 출력 명령어 바로 사용
    # masternode면 --contol-plane 붙이고, certificate-key 가 주어졌다면 함께 넣는다.

     

    Daemonset

    hostPath는 pod가 삭제되어도 그대로 남아있기 때문에, 경로 지정을 신중하게 하자

    # node 가 나오는건 hostpath이기 때문이고
    # via 는 통해서, 이용해서 라는 뜻.
    
    mount /configurator as HostPath volume on the Node it's running on
    write aba997ac-1c89-4d64 into file /configurator/config 
    on its Node via the command: section
    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: configurator
      namespace: configurator
    spec:
      selector:
        matchLabels:
          name: configurator
      template:
        metadata:
          labels:
            name: configurator
        spec:
          containers:
          - name: configurator
            image: bash
            command:
            - sh
            - -c
            - 'echo aba997ac-1c89-4d64 > /configurator/config && sleep 1d'
            volumeMounts:
            - name: varlog
              mountPath: /configurator
          volumes:
          - name: varlog
            hostPath:
              path: /configurator
    

     

    RBAC

    하나의 계정에, 두 개의 binding 이 가능

    clusterrole의 쓰임새는 2개이다.

    1. 클러스터 전체의 권한 관리
    2. 네임스페이스 내 권한이지만, 여러 네임스페이스에서 공통으로 쓸 권한

     Role이나 ClusterRole을 수정하면, 바인딩도 자동으로 따라가니 새로 만들 필요 없음

    There are existing Namespaces ns1 and ns2 .
    
    Create ServiceAccount pipeline in both Namespaces.
    
    # clusterrolebinding 으로 전체 클러스터 권한
    These SAs should be allowed to view almost everything in the whole cluster. You can use the default ClusterRole view for this.
    
    # rolebinding으로 단일 네임스페이스 권한
    These SAs should be allowed to create and delete Deployments in their Namespace.
    
    Verify everything using kubectl auth can-i .

     

    kubectl set

    kubectl set selector 명령어를 사용해 서비스의 파드 셀렉터를 변경할 수 있다

    # deployment env 추가
    kubectl set env deployment/registry STORAGE_DIR=/local
    
    # selector 수정 가능
    kubectl set selector svc my-service app=nginx,env=prod

     

     

    🌟 Pod에서 사용하는 Configmap 수정

    여기서 중요한건 configmap 수정하고, 반영하려면 Pod 재시작해야한다. 이건 deployment 이므로 Rollout restart 실행한다.

    문제
    An NGINX Deploy named nginx-static is running in the nginx-static NS.
    It is configured using a CfgMap named nginx-config.
    Update the nginx-config CfgMap to allow only TLSv1.3 connections.
    Re-create, restart, or scale resources as necessary.
    By using command to test the changes:
    
    [candidate@cka2025] $ curl --tls-max 1.2 <https://web.k8s.local>
    
    As TLSv1.2 should not be allowed anymore, the command should fail.
    k edit configmap nginx-config -n nginx-static
    
    ssl_protocols TLSv1.3; < 1.2 제거
    
    k rollout restart deployment nginx-static -n nginx-static

     

    kubectl port-forward

    Pod나 Service에 있는 포트를 내 로컬 포트와 연결해서 외부 노출 없이 접근할 수 있게 해주는 명령어

    언제 사용하는가?

    • 클러스터 안에서만 노출된 포트를 테스트하고 싶을 때 : localhost:8080 → pod:80
    • CluterIP라 외부 노출이 안될 때, 외부에 노출하지 않고도 접속 가능
    k port-forward pod/<pod-name> <local-port>:<pod-port>
    
    k port-forward pod/my-pod 8080:80

    이렇게 하면, 내 로컬의 localhost:8080으로 접속하면 클러스터 내 my-pod:80에 연결

    Pod외에 서비스에도 가능합니다.

    k port-forward svc/my-service 8888:80

    Q) “해당 Pod의 80번 포트를 로컬의 8080번으로 연결하여 접근 가능한 상태를 확인하시오.”

    “Service가 외부 노출되지 않음. 포트포워딩으로 curl 테스트하시오.”

    k port-forwarad pod/my-pod 8080:3000
    
    이렇게 하고 내 로컬에서 localhost:8080 접속했더니, 프로메테우스 창 떴음!

     

    반응형

    댓글