쿠버네티스 심화

이영진·2025년 4월 23일
1

클라우드

목록 보기
6/6

목표: 자신의 애플리케이션 프로그램을 Kubernetes 환경에 배포해서 운영 가능하도록 구성

  • 경로를 변환
cd shared-dir/collaboration 
  • 원격에 있는 파일을 local로 copy
remote-cp -rf ./cloud  /config/workspace
remote-cp -rf ./k8s-rbac  /config/workspace

ls -al

만약 workspace의 user가 root인 경우

sudo chown -R 911:911
-R재귀적(recursively) 변경 — 디렉토리일 경우 하위 모든 파일과 폴더 포함
911:911소유자 ID(uid): 911, 그룹 ID(gid): 911 로 설정
sudo chown -R 911:911 ./workspace

해당 코드로 user를 변경


Accounts

쿠버네티스 API server에 접속하는 주체(Subject)를 의미

ServiceAccount

  • Pod 또는 외부 서비스가 클러스터 리소스에 접근할 수 있게 해주는 K8s 내장 계정

  • 시스템 간 인증을 위한 계정

  • K8s 리소스로 Namespace 안에 생성

  • Pod 생성 시 default ServiceAccount가 자동 연결


User

  • 사람이(Human) 사용하는 계정

  • kubectl CLI, k8s Dashboard, 또는 API를 직접 호출해서 사용

  • K8s 자체에서는 미지원, 외부 시스템과 연동 필요

    예: OIDC, x509 인증서, SSO, alice@example.com, devops-admin


Group

  • 여러 User를 묶는 논리적 단위

  • K8s 자체에서는 미지원, 외부 시스템과 연동 필요


Service Account 중심 계정 관리

kubernete 내에서는 다음과 같은 이유로 Service Account 중심으로 사용하며 User 와 User Group은 잘 사용하지 않음

계정은 단순히 사용자를 구분하는 용도

  1. Kubernetes가 직접 User/Group을 관리 미지원

    • 외부 인증 연동이 필요하며, 구성과 운영이 복잡

    • 관리 포인트 증가

  2. 자동화 환경에서는 사람이 직접 API를 호출하는 경우가 거의 없음

    • 대부분 앱이나 컨트롤러(예: ArgoCD, Tekton, Jenkins 등)가 자동으로 실행

    • 자동화 앱이나 컨트롤러는 Pod로 동작하므로 ServiceAccount가 적합

    • kubectl 등을 활용한 접근 역시 Service Account로 생성해서 실행 가능

  3. RBAC이 ServiceAccount에 최적화되어 있음

    • RoleBinding, ClusterRoleBinding 등에서 명확하게 ServiceAccount를 지정

    • Namespace 단위로 권한을 잘게 쪼개어 관리하기 용이


ServiceAccount 는 쿠버네티스 클러스터 내부에서 Pod나 서비스가 API 서버에 인증된 방식으로 접근할 수 있도록 만들어진 계정.

이를 위해 인증 수단으로 JWT(JSON Web Token) 형태의 ServiceAccount 토큰이 사용

k get sa
  • default

자기 네임스페이스에 대한 접근 권한을 가질 수 있음


Service Account 기반 API server 통신 방식

  • Service Account는 Token 발행을 위해 동일 이름을 자동 생성, 1.24 이후 버전에서는 수동 연결해서 Token 발행

  • Pod가 Service Acount 연결 시 아래 디렉토리에 token, ca.crt, namespace 파일 생성

토큰 적용 순서

  1. KubeConfig 환경변수 설정

    config에 있는 토큰 값을 가져와서 담음

  2. 자기 홈 디렉토리 내 config에 있는 토큰을 가져옴

  3. /var/run/…/serviceaccount 경로의 토큰을 가져옴


[실습] mounted service account 확인하기

kubectl get pod -n skala-practice

k exec -it collabo-shared-sts-0 -- /bin/bash

collabo-shared-sts-0 Pod에 접속해서 bash 셸로 들어갈 수 있음.

cd /var/run/secrets/kubernetes.io/serviceaccount

ls

ctrl d로 나갈 수 있음


Role-Base Acess Control (RBAC)

RBAC (Role-baed Access Control)의 목적

Kubernetes는 모든 리소스에 대한 처리는 kube API Server + ETCD Resource 에 대한 접근

모든 Action에 대해서 API Server를 활용해야 하므로, 통신을 위해선 RBAC을 사용해야 함


RBAC (Role-baed Access Control)

역할 기반 접근 제어 (RBAC)는 사용자가 직접 권한을 받는 것이 아니라, 역할(Role)을 통해 접근 권한을 조절하는 방법

ServiceAccount skala-admin-sanamespace 리소스를 조회할 권한이 없어서 생긴 문제

  • skala-practice 네임스페이스 안의 skala-admin-sa 라는 ServiceAccount가 클러스터 수준(cluster scope)의 namespaces 리소스를 조회할 권한이 없음

Role 정의

api 그룹에 대한 path 내용도 담고 있음

  • verbs: 어떤 권한을 줄 지를 표시

⇒ Role은 namespace가 존재함

⇒ ClusterRole은 namespace가 존재하지 X


Role의 Rules

rules 필드 설명 (RBAC 권한 설정)

RBAC의 rules 필드는 Role 또는 ClusterRole 안에서 사용되며, 권한을 정의합니다.

필드 이름설명
apiGroups리소스가 속한 API 그룹 지정예: ""(core), apps, rbac.authorization.k8s.io
resources권한을 부여할 리소스 종류예: pods, deployments, configmaps
verbs허용할 동작(행위)예: get, list, watch, create, delete, update
resourceNames(선택) 특정 리소스 이름에만 제한예: ["my-secret", "my-pod"]
nonResourceURLs(선택) API 외부 URL 경로에 대한 권한 (예: /metrics, /healthz)→ 보통 ClusterRole에서 사용

kubectl api-resources 명령어 예시

kubectl api-resources

이 명령어는 Kubernetes 클러스터에서 사용 가능한 모든 API 리소스 목록을 보여줍니다.

필드설명
NAME리소스 이름 (예: pods, deployments)
SHORTNAMES줄임말 (예: po for pods, deploy for deployments)
APIGROUP리소스가 속한 API 그룹""이면 core API group
NAMESPACED해당 리소스가 Namespace에 종속적인지 여부 (true or false)



k get sa
k get secret

k get secret skala-admin-sa-token -o yaml

skala-admin-sa-token이라는 이름의 시크릿(Secret) 리소스를 YAML 형식으로 출력

k get pod

쿠버네티스(Kubernetes)에서 파드(Pod)의 목록과 상태를 조회하는 명령어

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  labels:
    amdp.io/app: skala25a-stock-api-wamdp
    amdp.io/profile: skala.skala-a
    argocd.argoproj.io/instance: skala25a-stock-api-wamdp.skala-a.skala
    cluster-tier: dev
  name: skala25a-stock-api-wamdp-pod-reader-skala-a
  namespace: skala-practice
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - configmaps
  verbs:
  - get
  - watch
  - list # 목록을 볼 수 있음

k get clusterrole admin -o yaml

쿠버네티스 클러스터 내에 정의된 admin이라는 이름의 ClusterRole의 상세 정보를 YAML 형식으로 출력

k get --raw /metrics

쿠버네티스 API 서버 또는 각 컴포넌트(예: kubelet, kube-scheduler, kube-controller-manager 등)가 노출하는 Prometheus 형식의 시스템 메트릭을 그대로 출력


(RDE) > kcns skala-argocd 
Context "skala-edu-cluster" modified.

쿠버네티스 환경에서 현재 작업 중인 네임스페이스를 skala-argocd로 전환하는 역할

(= kubectl config set-context --current --namespace=skala-argocd)


Namespace

Namespace는 Kubernetes 클러스터 안에서 리소스들을 논리적으로 분리해주는 가상 공간.

특정 리소스 자원을 나눠주는, 리소스를 각각의 분리된 영역으로 나누기 좋은 방법

(명시적 분리)

  • 여러 네임스페이스를 사용하면 복잡한 쿠버네티스 시스템을 더 작은 그룹으로 분할

  • 멀티 테넌트(Multi-tenant) 환경을 분리하여 리소스를 생산, 개발, QA 환경 등으로 사용

  • 리소스 이름은 네임스페이스 내에서만 고유 명칭 사용

  • 현재 클러스터의 기본 네임스페이스 확인하기

테넌트
: 클라우드 인프라/서비스 제공 방식에서 소프트웨어 인스턴스(Software Instance)를 공유하는 사용자

Namespace는 Kubernetes 리소스를 논리적으로 나누고 관리하는 컨테이너 역할을 하며, 자원 분리와 보안, 조직화에 매우 유용


kubectlget pod -A. (full argument: --all-namespaces)

전체 네임스페이스를 대상으로 kubectl을 실행하는 방법


Pod

Kubernetes는 Pod 단위로 라이프사이클을 관리하며, 컨테이너는 직접적인 관리를 하지 않는다

  • 컨테이너의 공동 배포된 그룹이며 쿠버네티스의 기본 빌딩 블록을 대표

  • 쿠버네티스는 컨테이너를 개별적으로 배포하지 않고 컨테이너의 포드를 항상 배포하고 운영

  • 일반적으로 포드는 단일 컨테이너만 포함하지만 다수의 컨테이너를 포함 할 수 있음

  • 포드는 다수의 노드에 생성되지 않고 단일 노드에서만 실행

  • 여러 프로세스를 실행하기 위해서는 컨테이너 당 단일 프로세스가 적합

  • 다수의 프로세스를 제어하려면? -> 다수의 컨테이너를 다룰 수 있는 그룹이 필요!

컨테이너는 보통 하나의 Pod 안에서 함께 실행되며, 같은 네트워크(IP), 같은 저장소(Volume)를 공유합니다.

항목설명
같이 스케줄링Pod 안의 모든 컨테이너는 같은 노드에 같이 배치됨
같은 네트워크Pod 안의 컨테이너들은 같은 localhost(127.0.0.1) 로 통신 가능
같은 Volume 사용 가능공유 볼륨으로 파일을 공유할 수 있음
보통 하나의 컨테이너만 포함대부분 1 컨테이너 = 1 Pod (sidecar 쓰는 경우 제외)

장점

  • 포드는 밀접하게 연관된 프로세스를 함께 실행하고 마치 하나의 환경에서 동작하는 것처럼 보임

  • 그러나 동일한 환경을 제공하면서 다소 격리된 상태로 유지

동일한 포드의 컨테이너 사이의 부분 격리

포드의 모든 컨테이너는 동일한 네트워크 및 리눅스 네임스페이스에서 실행

같은 호스트 이름 및 네트워크 인터페이스를 공유 (포트 충돌 가능성 있음)

포드의 모든 컨테이너는 동일한 IPC 네임스페이스 아래에서 실행되며 IPC를 통해 통신 가능


POD 네트워크 구조

Plat Inter-Pod 네트워크 구조

  • 쿠버네티스 클러스터의 모든 포드는 공유된 단일 플랫, 네트워크 주소 공간에 위치

  • 파드 사이에는 NAT 게이트웨이가 존재 하지 않음

    ⇒ 모든 Pod는 고유한 IP를 갖고 있고, 클러스터 내부에서는 NAT 없이 직접 통신이 가능.

  • 파드내 컨테이너 간 통신은 local host 기반을 통신하면 모든 자원을 공유


POD 내 컨테이너 구성 방법

컨테이너를 포드 전체에 적절하게 구성하는 방법

  • 다수의 포드로 멀티티어 애플리케이션 분할하기

  • 각각 스케일링이 가능한 포드로 분할하기

front/back 단을 병렬로 띄우기 위해선 나누어서 구성

: 둘 간의 communication 과정을 보고 결정하지만, 보통 main process는 나누어서 구성


port-forward

컨테이너에서 호스트로 포트 포워딩, 로컬 PC ↔ 클러스터 내부 리소스 간에 직접 연결하는 유용한 디버깅 도구

  • 디버깅 혹은 다른 이유로 서비스를 거치지 않고 특정 포드와 통신하고 싶을 때 사용

  • kubectlport-forward 명령으로 수행

  • 컨테이너 8888 포트를 pod의 8080 포트로 전달

Multi-Pod에 Port-forward 시 개별 IP

kubectl port-forward pod/webserver-pod 8888:8080 –n {namespace}

bg

curl localhost:8888

kubectl port-forward로컬 포트를 Kubernetes 리소스의 포트에 연결해서, 클러스터 내부 리소스를 외부에서 직접 접근 가능하게 해주는 도구.


Pod yaml 구조

Pod는 하나의 독자적인 실행 단위이며, kubernetes에서 관리하는 최소 단위


Pod Argument 전달

docker가 가지고 있는 arguments를 전달할 수 있음.

python3 fastserver.py --host 0.0.0.0 --port 8080

Init-Containr

Pod의 실행되기 전 가장 먼저 초기에 실행되어 초기화 및 사전 작업을 수행하는 컨테이너로 Pod 내 포함

  • Pod 실행 시 최초 실행되며, Init-container가 정상적으로 종료해야 하지만 다음 절차가 실행

  • Init-container가 일정 시간 이상 내에 정상 처리되지 않으면 재시작 정책에 따라 재시도

apiVersion: v1
kind: Pod
metadata:
  name: sk000-init-container-test
  namespace: skala-practice
  annotations:
    prometheus.io/scrape: 'true'
    prometheus.io/port: '8081'
    prometheus.io/path: '/actuator/prometheus'
    update: ${ANNOTATION_UPDATE}
  labels:
    app: sk000-init-container-test
spec:
  initContainers:
  - name: check-active-enabled
    image: busybox
    command:
    - sh
    - -c
    - |
      timeout 300 sh -c "
      while [ ! -f /root/active.enabled ]; do
        echo 'Waiting for active.enabled file...'
        sleep 5
      done
      echo 'File active.enabled found. Initialization complete.'
      "
    volumeMounts:
    - name: root-volume
      mountPath: /root
  containers:
  - name: init-container-test
    image: amdp-registry.skala-ai.com/skala25a/sk000-webserver:2.0.0
    imagePullPolicy: Always
    env:
    - name: LOGGING_LEVEL
      value: DEBUG
    - name: USER_NAME
      value: sk000
  volumes:
  - name: root-volume
    emptyDir: {}


[실습] kubernetes 환경에서 배포를 실행

yaml을 생성한 후 생성된 pod 확인

  1. env.properties 파일에 들어가서, USER_NAME=sk021 로 변경
cicd.sh -y

중간에 묻는 질문 없이 자동으로 모든 과정을 진행하는 자동 확인 옵션

k apply –f init-pod.yaml

해당 YAML 파일을 기준으로 Kubernetes 리소스를 생성하거나 업데이트하는 명령어

k get pod –w

 k exec  -it sk021-init-container-test -c check-active-enabled -- /bin/sh
 
 / # cd /root
 ~ # ls
 ~ # touch active.enabled

해당 pod 내 check-active-enabled 컨테이너에 셸로 접속

~ # touch active.enabled

active.enabled라는 빈 파일을 생성

sk021-init-container-test라는 Pod의 check-active-enabled 컨테이너 안에 접속해서 /root/active.enabled라는 상태 파일을 생성

  1. env.properties에서 자기 username으로 고치고
sudo cicd.sh --all # -a or -build -push

sudo cicd.sh --allDocker 이미지 빌드부터 푸시, 배포까지의 전체 파이프라인을 자동으로 실행하는 스크립트


Init Container 동작 원리 요약

  1. Init Container는 메인 컨테이너보다 먼저 실행.

  2. 모든 Init Container성공적으로 종료(exit 0) 되어야 메인 컨테이너가 실행되고, Pod 전체가 Running 상태가 됨.

  3. 보통 Init Container는 특정 조건이나 파일 존재 등을 검사하고, 조건이 맞아야 끝나도록 설계됨.

init-container의 목적은 어떤 조건이 충족될 때까지 기다리는 것이고, 그 조건이 /root/active.enabled 존재 여부라면 touch로 조건을 만족시킴

initContainers:
- name: check-active-enabled
  image: busybox
  command:
  - sh
  - -c
  - |
    timeout 300 sh -c "
    while [ ! -f /root/active.enabled ]; do
      echo 'Waiting for active.enabled file...'
      sleep 5
    done
    echo 'File active.enabled found. Initialization complete.'
    "

해당 코드는 init-pod.yaml 중 일부로 init-container가 실행되면서 /root/active.enabled 파일이 존재할 때까지 최대 5분(300초) 동안 대기한다는 의미

항목내용
init-container 역할특정 파일(/root/active.enabled)이 존재할 때까지 대기
동작 방식쉘 루프로 감시, 파일 생기면 정상 종료
공유 방법emptyDir/root에 마운트해 다른 컨테이너와 공유
너의 행동 결과예상대로 루프 종료 → Pod Running 상태

Sidecar container

일반적으로 Pod는 주 컨테이너 와 지원 컨테이너인 한 개 이상의 side car 컨테이너로 이루어져 있다.

Pod 내 모든 컨테이너가 주 컨테이너로 구성하지 않는 이유

  • Pod내 컨테이너는 한 배를 탄 동지 죽어도 같이 죽고 살아도 같이 산다

  • Kubernetes의 핵심은 컨테이너의 탄력적 확장성 지원인데, Pod 내 컨테이너는 지원되지 않는다.

일반적으로 공통 기능을 옆에 같이 포함 (side car) 시켜서 컨테이너의 안정성, 네트워크, 로그, 모니터링, 자가 복구를 지원하도록 한다

service mesh istio

service간 트래픽 연결을 그물망처럼 자유롭게 연결

  • Pod 내 주 컨테이너로 들어오고 나가는 모든 트래픽을 side car container인 proxy가 모두 통제함으로써 유연하게 트래픽 제어

외/내부의 모든 traffic을 관리할 수 있음
Traffic Flow Control & Traffic Resilient


ReplicaSet

ReplicaSet은 Kubernetes에서 지정한 수의 Pod 복제본을 항상 유지하도록 도와주는 컨트롤러

만약 어떤 Pod가 종료되거나 삭제되면, ReplicaSet이 자동으로 새로운 Pod를 생성해서 지정된 수를 유지

  • ReplicaSet을 사용자가 생성하지 않고 Deployment 적용 시 ReplicaSet Controller가 RepllicaSet을 자동 구성

  • Deployment는 여러 개의 ReplicasSet을 제공해서 버전 변화에 따라 Rolling Update 및 Rollback 실행

Replicaset을 둬서, Rolling-update 역할(점진적 업데이트)을 할 수 있음

ReplicaSet를 통한 Rolling Update

  • pod 이미지 업데이트 시 새로운 ReplicaSet이 만들어지고 Old 와 New Pod가 점진적 업데이트 (Rolling update) 지원

  • ReplicaSet의 선언적 정의는 Deployment 내에 포함되어 있음


ReplicaSet를 통한 Rolling Update: 2가지 정책

  1. maxSurge: (최대 넘침)

Rolling Update 시 기존 desired replica 개수보다 추가로 생성될 수 있는 Pod = 일시적 넘침

  1. maxUnavailable

업데이트 중에 기존 desired replica 개수기준 동작하지 않아도 되는 Pod 수


maxSurge 만큼 넘친 다음에 항상 4개가 유지되도록 해서 멈춘 pod가 없게끔 설정


maxSurge 만큼 넘치지만, 최대 maxUnavailable만큼 비활성화될 수 있음


[실습] Rolling Update & Roll back

  1. env.properties 수정

  1. 각 명령어를 버전을 바꿔가면서 해보기
cicd.sh -y  
kubectl apply -f deploy.yaml

k describe replicaset sk021-replicaset-test-7bd98549cd

kubectl rollout history deploy sk021-replicaset-test 

kubectl rollout history deploy sk021-replicaset-test --revision=3

(RDE) > kubectl port-forward svc/sk021-replicaset-test 8080:8080

  • 롤백
(RDE) > kubectl rollout undo deploy sk021-replicaset-test
  • 롤백 확인
(RDE) > kubectl rollout history deploy sk021-replicaset-test --revision=4

undo를 통해서 정상적으로 rollback이 됨을 확인할 수 있음

(⎈|skala-edu-cluster:skala-practice) ~/workspace/cloud/k8s-ddive/04.replicaset
(RDE) > k get pod -l app=sk021-replicaset-test               
NAME                                     READY   STATUS             RESTARTS   AGE
sk021-replicaset-test-68fd9576bf-gjmbr   0/1     ImagePullBackOff   0          14m
sk021-replicaset-test-7bd98549cd-s4wzw   1/1     Running            0          44m

(⎈|skala-edu-cluster:skala-practice) ~/workspace/cloud/k8s-ddive/04.replicaset
(RDE) > k delete pod sk021-replicaset-test-68fd9576bf-gjmbr  
pod "sk021-replicaset-test-68fd9576bf-gjmbr" deleted

(⎈|skala-edu-cluster:skala-practice) ~/workspace/cloud/k8s-ddive/04.replicaset
(RDE) > k get pod -l app=sk021-replicaset-test         
NAME                                     READY   STATUS    RESTARTS   AGE
sk021-replicaset-test-68fd9576bf-z7jjq   1/1     Running   0          15s

Rollback을 했는데, Webserver에 1.0.0 버전이 없어서 오류가 발생
→ 해당 pod에는 오류가 생겨 정상적으로 작동하지 않고, 그 전의 pod를 죽이지 않고 그대로 유지
→ webserver에 우선적으로 1.0.0을 배포하고 오류가 있는 pod를 지우고 다시 실행해야 롤백한 버전이 정상적으로 웹에 뜸

C:\Users\Administrator\Desktop\cloud_k8s\rde-launcher-1.2.2.add-jmeter\exec\rde-launcher-windows\config\workspace\cloud\container\05.webserver

해당 경로에서

docker login amdp-registry.skala-ai.com/skala25a

아이디와 비밀번호를 입력한 후,

docker build --tag amdp-registry.skala-ai.com/skala25a/sk021-webserver:1.0.0 .
docker push amdp-registry.skala-ai.com/skala25a/sk021-webserver:1.0.0

해당 과정을 통해서 1.0.0 버전을 docker 로 push하여 webserver에 이미지를 올릴 수 있음

k port-forward deploy/sk021-replicaset-test --address 0.0.0.0 8080:8080

Deployment

Deployment는 여러 개의 Replicas를 관리하기 위한 ReplicaSet 상위 리소스

새로운 이미지를 가지는 동일한 Deployment를 배포하는 경우 기존 운영 중인 Replica Set Pod와 신규 버전 Replica Set Pod가 점진적 업데이트되는데, 이를 통합 관리하는 것이 Deployment


label 과 Selector

Label

k8s 리소스에 붙이는 Key-value 쌍의 메타데이터로, 리소스를 그룹화하기 위한 필터링 도구로 활용

⇒ 사용자가 리소스를 분류하거나 특정 그룹으로 묶는 데 사용예를 들어, 특정 애플리케이션, 환경, 또는 릴리즈 버전에 따라 리소스를 구분

붙였다가 땔 수 있음.

Selector

특정 조건에 따라 Label을 가진 리소스를 선택하는 기능

⇒ Service, Deployment, 또는 다른 리소스가 Selector를 통해 특정 Label을 가진 리소스(예: Pod)를 타겟팅하거나 관리


업로드중..


0개의 댓글