Cloud

EKS 파드로 노드 관리하기

Hanhorang31 2025. 4. 12. 22:50
 

K8S 파드에서 노드를 관리하기 위해 실습한 내용을 공유합니다.

실습 내용은 가시다님이 진행하는 CloudNet 스터디를 참고하였습니다.

 

파드에서 노드를 관리하기 위한 상황은 많습니다.

서버 모니터링이 될 수 도 있고, 서버 관리를 위해 서드 파티의 솔루션을 사용할 수 있습니다.

노드 관리를 위한 방법을 정리하겠습니다.

방법
장점
단점
사용 추천 상황
AWS SSM
SSH 없이 원격 실행 가능
SSM IAM 권한 필요, 에이전트가 설치되어 있어야 함 수동으로 설치해야 함
운영 중인 노드에서 수동으로 설치해야 할 때
골든 이미지(AMI)
모든 노드에 동일 환경 보장, 빠른 부팅 시간
AMI 변경 시 재배포 필요, AMI 관리 부담 있음
자주 재사용되는 설정이 없고, 노드 부팅 속도가 필요할 때
UserData
새로운 노드에 자동 배포
기존 노드에는 적용되지 않음, 노드 교체시 전체 노드 재시작 필요
EKS에서 기본 소프트웨어 배포 시
DaemonSet
모든 워커노드에서 자동 실행, 유연함
보안적 이슈 (권한 관리 필요) 관리
변경 사항이 많을 때

Q. AWS SSM 로 노드 관리 ?

더보기

AWS System Managers로 대규모 명령 실행이 가능합니다. 공식 문서

targets 를 지정하여 선택한 서버들에 대해 명령을 실행할 수 있습니다.

# 예시 
aws ssm send-command \    
    --document-name document-name \
    --targets Key=resource-groups:Name,Values=resource-group-name \
    [...]

Daemonset을 통한 SSM 설치 방법 공식 문서

 

cat << EOF > ssm_daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    k8s-app: ssm-installer
  name: ssm-installer
  namespace: kube-system
spec:
  selector:
    matchLabels:
      k8s-app: ssm-installer
  template:
    metadata:
      labels:
        k8s-app: ssm-installer
    spec:
      containers:
      - name: sleeper
        image: busybox
        command: ['sh', '-c', 'echo I keep things running! && sleep 3600']
      initContainers:
      - image: amazonlinux
        imagePullPolicy: Always
        name: ssm
        command: ["/bin/bash"]
        args: ["-c","echo '* * * * * root yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm & rm -rf /etc/cron.d/ssmstart' > /etc/cron.d/ssmstart"]
        securityContext:
          allowPrivilegeEscalation: true
        volumeMounts:
        - mountPath: /etc/cron.d
          name: cronfile
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      volumes:
      - name: cronfile
        hostPath:
          path: /etc/cron.d
          type: Directory
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      terminationGracePeriodSeconds: 30
EOF

# 일관 적용 
kubectl apply -f ssm_daemonset.yaml
  • Daemonset셋을 통해 각 노드에 SSM 에이전트를 설치합니다.
  • 노드에 접근하기 위해 컨테이너 보안컨텍스트 특권 권한을 사용합니다.
  • 초기화 컨테이너를 통해 SSM 에이전트를 설치합니다. 이는 파드가 재시작되어도 한번만 실행하도록 설정하기 위함입니다.
  • 각 파드들은 60분동안 유지되며 종료됩니다. (설치 시간 확보를 위함)

활성화 확인 - 노드 SSM 접근

# 접근 인스턴스 확인
aws ssm describe-instance-information \
  --region ap-northeast-2 \
  --query "InstanceInformationList[*].{InstanceId:InstanceId, Ping:PingStatus, Name:ComputerName}"

..
    {
        "InstanceId": "i-082e2721128b863e1",
        "Ping": "Online",
        "Name": "ip-172-16-0-155.ap-northeast-2.compute.internal"
    },
    {
        "InstanceId": "i-0f8350c95e23e0d8b",
        "Ping": "Online",
  • system manager 에서 인벤토리 구성에서 연결 후 명령어 실행이 가능합니다.

 

 

 

워크로드에 따라 노드 관리 방법이 다르지만, 이번 블로그 글에서는 Daemonset을 통한 관리 방법을 다루겠습니다.

Daemonset 을 통해 노드 관리를 하는 이점으로 유연함을 들 수 있습니다.

변경 사항이 있을 때마다 노드 교체 없이 Daemonset만 교체하면 되기 때문입니다.

하지만, 고려사항이 많습니다.

파드 권한과 호스트 네임스페이스 공유로 호스트 탈취될 수 있기 때문입니다.


kubectl create -n kube-system -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: root-shell
  namespace: kube-system
spec:
  containers:
  - command:
    - /bin/cat
    image: alpine:3
    name: root-shell
    securityContext:
      privileged: true
    tty: true
    stdin: true
    volumeMounts:
    - mountPath: /host
      name: hostroot
  hostNetwork: true
  hostPID: true
  hostIPC: true
  tolerations:
  - effect: NoSchedule
    operator: Exists
  - effect: NoExecute
    operator: Exists
  volumes:
  - hostPath:
      path: /
    name: hostroot
EOF

# 호스트 탈취!
kubectl -n kube-system exec -it root-shell -- chroot /host /bin/bash

위 예제처럼 컨테이너 보안컨텍스트 특권 권한인 privileged 없이 노드(호스트)를 관리해야 합니다.

 

 

컨테이너 보안컨텍스트

침해사고 발생 시 침해사고를 당한 권한을 최대한 축소하여 그 사고에 대한 확대를 축소해야 합니다.

이를 위해 컨테이너 보안컨텍스트 종류 중 capabilities 를 이용하겠습니다.

capabilities는 슈퍼 유저의 힘을 작은 조각으로 나누는 옵션입니다. 링크

종류
개요
privileged
특수 권한을 가진 컨테이너로 실행
capabilities
Capabilities 의 추가와 삭제
allowPrivilegeEscalation
컨테이너 실행 시 상위 프로세스보다 많은 권한을 부여할지 여부
readOnlyRootFilesystem
root 파일 시스템을 읽기 전용으로 할지 여부
runAsUser
실행 사용자
runAsGroup
실행 그룹
runAsNonRoot
root 에서 실행을 거부
seLinuxOptions
SELinux 옵션
# Linux Capabilities 확인 : 현재 38개 
capsh --print
..
Bounding set =cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read,cap_perfmon,cap_bpf,cap_checkpoint_restore


# CapPrm 프로세스가 가질 수 있는 전체 권한, CapEff 실제 사용 가능한 권한 
# 37비트가 전부 1인 상태
cat /proc/1/status | egrep 'CapPrm|CapEff'
CapPrm: 000001ffffffffff
CapEff: 000001ffffffffff


# Linux Capabilities 권한 
cap_chown                   파일이나 디렉토리의 소유자를 변경할 수 있는 권한
cap_dac_override            파일이나 디렉토리의 접근 권한을 무시하고 파일이나 디렉토리에 대한 접근을 수행할 수 있는 권한 (DAC의 약자는 Discretionary access control이다)
cap_dac_read_search         파일이나 디렉토리를 읽거나 검색할 수 있는 권한
cap_fowner                  파일이나 디렉토리의 소유자를 변경할 수 있는 권한
cap_fsetid                  일이나 디렉토리의 Set-User-ID (SUID) 또는 Set-Group-ID (SGID) 비트를 설정할 수 있는 권한
cap_kill                    다른 프로세스를 종료할 수 있는 권한
cap_setgid                  프로세스가 그룹 ID를 변경할 수 있는 권한
cap_setuid                  프로세스가 사용자 ID를 변경할 수 있는 권한
cap_setpcap                 프로세스가 자신의 프로세스 권한을 변경할 수 있는 권한
cap_linux_immutable         파일의 immutability(불변성) 속성을 변경할 수 있는 권한을 제공
cap_net_bind_service        프로그램이 특정 포트에 바인딩(bind)하여 소켓을 개방할 수 있는 권한
cap_net_broadcast           프로세스가 네트워크 브로드캐스트 메시지를 보낼 수 있는 권한
cap_net_admin               네트워크 인터페이스나 소켓 설정을 변경할 수 있는 권한
cap_net_raw                 네트워크 패킷을 송수신하거나 조작할 수 있는 권한
cap_ipc_lock                메모리 영역을 잠금(lock)하고 언락(unlock)할 수 있는 권한
cap_ipc_owner               IPC 리소스(Inter-Process Communication Resources)를 소유하고, 권한을 변경할 수 있는 권한
cap_sys_module              커널 모듈을 로드하거나 언로드할 수 있는 권한
cap_sys_rawio               입출력(I/O) 포트와 같은 하드웨어 리소스를 직접 접근할 수 있는 권한
cap_sys_chroot              프로세스가 chroot() 시스템 콜을 호출하여 프로세스의 루트 디렉토리를 변경할 수 있는 권한
cap_sys_ptrace              다른 프로세스를 추적(trace)하거나 디버깅할 수 있는 권한
cap_sys_pacct               프로세스 회계(process accounting)를 위한 파일에 접근할 수 있는 권한
cap_sys_admin               시스템 관리자 권한을 제공하는 권한
cap_sys_boot                시스템 부팅과 관련된 작업을 수행할 수 있는 권한
cap_sys_nice                프로세스의 우선순위를 변경할 수 있는 권한
cap_sys_resource            자원 제한(resource limit)과 관련된 작업을 수행할 수 있는 권한
cap_sys_time                시스템 시간을 변경하거나, 시간 관련 시스템 콜을 사용할 수 있는 권한
cap_sys_tty_config          터미널 설정을 변경할 수 있는 권한
cap_mknod                   mknod() 시스템 콜을 사용하여 파일 시스템에 특수 파일을 생성할 수 있는 권한
cap_lease                   파일의 잠금과 관련된 작업을 수행할 수 있는 권한
cap_audit_write             시스템 감사(audit) 로그에 대한 쓰기 권한
cap_audit_control           시스템 감사(audit) 설정과 관련된 작업을 수행할 수 있는 권한
cap_setfcap                 파일 시스템 캡러빌리티(file system capability)을 설정할 수 있는 권한
cap_mac_override            SELinux 또는 AppArmor과 같은 MAC(Mandatory Access Control) 시스템을 우회하고 자신의 프로세스가 접근 가능한 파일, 디바이스, 네트워크 등을 제한 없이 접근할 수 있는 권한
cap_mac_admin               SELinux 또는 AppArmor과 같은 MAC(Mandatory Access Control) 시스템을 관리하고 수정할 수 있는 권한
cap_syslog                  시스템 로그를 읽거나, 쓸 수 있는 권한
cap_wake_alarm              시스템의 RTC(Real-Time Clock)를 사용하여 장치를 깨우거나 슬립 모드를 해제할 수 있는 권한
cap_block_suspend           시스템의 전원 관리 기능 중 하나인 Suspend(절전 모드)를 방지하는 권한
cap_audit_read              시스템 감사(audit) 로그를 읽을 수 있는 권한

파드의 Capabilities 권한 확인


# 샘플 파드 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: sample-capabilities
spec:
  containers:
  - name: nginx-container
    image: masayaaoyama/nginx:capsh
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0
EOF


kubectl exec -it sample-capabilities -- capsh --print | grep Current
Current: = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap+ep
cap_chown                   # 파일이나 디렉토리의 소유자를 변경할 수 있는 권한
cap_dac_override            # 파일이나 디렉토리의 접근 권한을 무시하고 접근할 수 있는 권한 (DAC = Discretionary Access Control)
cap_fowner                  # 소유하지 않은 파일/디렉토리에 대해 권한 변경 등 소유자 권한 수행 가능
cap_fsetid                  # SUID/SGID 비트를 설정하거나 유지할 수 있는 권한
cap_kill                    # 다른 사용자의 프로세스에 시그널(SIGNAL)을 보낼 수 있는 권한
cap_setgid                  # 그룹 ID(GID)를 변경할 수 있는 권한
cap_setuid                  # 사용자 ID(UID)를 변경할 수 있는 권한
cap_setpcap                 # 프로세스의 capability를 추가/제거할 수 있는 권한
cap_net_bind_service        # 1024 이하의 privileged 포트(예: 80, 443)에 바인딩할 수 있는 권한
cap_net_raw                 # raw socket을 사용하여 네트워크 패킷을 조작하거나 수신/전송할 수 있는 권한 (예: ping)
cap_sys_chroot              # chroot() 시스템 콜을 사용하여 루트 디렉토리를 변경할 수 있는 권한
cap_mknod                   # mknod()를 사용하여 특수 파일(디바이스 노드 등)을 생성할 수 있는 권한
cap_audit_write             # 커널의 audit 로그에 기록을 쓸 수 있는 권한
cap_setfcap+ep              # 파일에 file-based capability를 설정할 수 있는 권한 (+ep는 현재 활성화 중임을 의미)

# proc 에서 확인 : bit 별 Capabilities
kubectl exec -it sample-capabilities -- cat /proc/1/status | egrep 'CapPrm|CapEff'
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb

# 시간 변경 시도
kubectl exec -it sample-capabilities -- date
Thu Apr 10 15:05:16 UTC 2025

# 불가 
kubectl exec -it sample-capabilities -- date -s "12:00:00"
date: cannot set date: Operation not permitted
Thu Apr 10 12:00:00 UTC 2025
command terminated with exit code 1

# 시간 확인
kubectl exec -it sample-capabilities -- date
Thu Apr 10 15:06:47 UTC 2025

파드 내 Capabilities 부여

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: sample-capabilities2
spec:
  containers:
  - name: nginx-container
    image: masayaaoyama/nginx:capsh
    command: ["tail"]
    args: ["-f", "/dev/null"]
    securityContext:
      capabilities:
        add: ["NET_ADMIN", "SYS_TIME"] # 네트워크IP 어드민 및 시간 권한 부여 
        drop: ["AUDIT_WRITE"]
  terminationGracePeriodSeconds: 0
EOF

# 권한 추가 확인 
kubectl exec -it sample-capabilities2 -- capsh --print | grep Current
Current: = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_admin,cap_net_raw,cap_sys_chroot,cap_sys_time,cap_mknod,cap_setfcap+ep

# 파드 상세 확인
kubectl get pod sample-capabilities2 -o jsonpath="{.spec.containers[0].securityContext}" | jq
{
  "capabilities": {
    "add": [
      "NET_ADMIN",
      "SYS_TIME"
    ],
    "drop": [
      "AUDIT_WRITE"
    ]
  }
  
# 시간 변경 시도
kubectl exec -it sample-capabilities2 -- date -s "12:00:00"
Thu Apr 10 12:00:00 UTC 2025

# 배포 노드 시간 확인, 변경 확인
[root@ip-100-64-191-230 /]# date 
Thu Apr 10 12:01:07 UTC 2025

왜 추가 구성이 필요할까?

쿠버네티스에서는 Job 대상을 노드 별로 관리하는 오브젝트는 따로 없습니다.

Daemonset 오브젝트에서 추가 관리르 추가하여 관리가 필요합니다.

기능 요구사항은 인터넷 서치를 통해 찾을 수 있지만, 명확한 가이드는 없습니다.

스택오버플로우 깃허브

 

오픈소스 확인하기

모니터링 파드들의 경우 어떻게 노드 메트릭을 가져오는 지 확인하겠습니다.

  • 노드의 메트릭을 수집하여 Prometheus로 전송
  • 노드의 상태와 자원 사용량을 모니터링
apiVersion: apps/v1
kind: DaemonSet
metadata:
  annotations:
    deprecated.daemonset.template.generation: "1"
    meta.helm.sh/release-name: kube-prometheus-stack
    meta.helm.sh/release-namespace: kube-prometheus-stack
  creationTimestamp: "2025-04-08T01:34:42Z"
  generation: 1
  labels:
    app.kubernetes.io/component: metrics
    app.kubernetes.io/instance: kube-prometheus-stack
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: prometheus-node-exporter
    app.kubernetes.io/part-of: prometheus-node-exporter
    app.kubernetes.io/version: 1.6.0
    helm.sh/chart: prometheus-node-exporter-4.18.1
    jobLabel: node-exporter
    release: kube-prometheus-stack
  name: kube-prometheus-stack-prometheus-node-exporter
  namespace: kube-prometheus-stack
  resourceVersion: "4845"
  uid: 44407fc6-018f-4d31-a49f-79666502face
spec:
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app.kubernetes.io/instance: kube-prometheus-stack
      app.kubernetes.io/name: prometheus-node-exporter
  template:
    metadata:
      annotations:
        cluster-autoscaler.kubernetes.io/safe-to-evict: "true"
      creationTimestamp: null
      labels:
        app.kubernetes.io/component: metrics
        app.kubernetes.io/instance: kube-prometheus-stack
        app.kubernetes.io/managed-by: Helm
        app.kubernetes.io/name: prometheus-node-exporter
        app.kubernetes.io/part-of: prometheus-node-exporter
        app.kubernetes.io/version: 1.6.0
        helm.sh/chart: prometheus-node-exporter-4.18.1
        jobLabel: node-exporter
        release: kube-prometheus-stack
    spec:
      automountServiceAccountToken: false
      containers:
      - args:
        - --path.procfs=/host/proc
        - --path.sysfs=/host/sys
        - --path.rootfs=/host/root
        - --path.udev.data=/host/root/run/udev/data
        - --web.listen-address=[$(HOST_IP)]:9100
        - --collector.filesystem.mount-points-exclude=^/(dev|proc|sys|var/lib/docker/.+|var/lib/kubelet/.+)($|/)
        - --collector.filesystem.fs-types-exclude=^(autofs|binfmt_misc|bpf|cgroup2?|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|iso9660|mqueue|nsfs|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|selinuxfs|squashfs|sysfs|tracefs)$
        env:
        - name: HOST_IP
          value: 0.0.0.0
        image: quay.io/prometheus/node-exporter:v1.6.0
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /
            port: 9100
            scheme: HTTP
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        name: node-exporter
        ports:
        - containerPort: 9100
          name: http-metrics
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /
            port: 9100
            scheme: HTTP
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        resources: {}
        securityContext:
          readOnlyRootFilesystem: true
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /host/proc
          name: proc
          readOnly: true
        - mountPath: /host/sys
          name: sys
          readOnly: true
        - mountPath: /host/root
          mountPropagation: HostToContainer
          name: root
          readOnly: true
      dnsPolicy: ClusterFirst
      hostNetwork: true
      hostPID: true
      nodeSelector:
        kubernetes.io/os: linux
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext:
        fsGroup: 65534
        runAsGroup: 65534
        runAsNonRoot: true
        runAsUser: 65534
      serviceAccount: kube-prometheus-stack-prometheus-node-exporter
      serviceAccountName: kube-prometheus-stack-prometheus-node-exporter
      terminationGracePeriodSeconds: 30
      tolerations:
      - effect: NoSchedule
        operator: Exists
      volumes:
      - hostPath:
          path: /proc
          type: ""
        name: proc
      - hostPath:
          path: /sys
          type: ""
        name: sys
      - hostPath:
          path: /
          type: ""
        name: root
  updateStrategy:
    rollingUpdate:
      maxSurge: 0
      maxUnavailable: 1
    type: RollingUpdate
status:
  currentNumberScheduled: 2
  desiredNumberScheduled: 2
  numberAvailable: 2
  numberMisscheduled: 0
  numberReady: 2
  observedGeneration: 1
  updatedNumberScheduled: 2
  • hostPID: true 및 hostNetwork: true: 파드가 호스트의 PID 네임스페이스와 네트워크 네임스페이스를 공유하여 노드에 대한 정확한 정보를 수집합니다.
  • readOnlyRootFilesystem: true: 보안 강화를 위해 컨테이너 내부 파일시스템을 읽기 전용으로 설정하여 파일 시스템 변경을 방지합니다.

 

노드 관리 요구사항

Daemonset를 통해 노드 관리를 하기 위한 고려 사항을 검토하겠습니다.

  1. 노드당 한 번만 실행 (initcontainer)
  2. 스크립트를 통해 명령어 실행하기
  3. 실행 결과 확인 가능(kubectl logs)
  4. 보안 이슈 최소화(Linux Capabilities) 이용

위에서 예제로 활용한 AWS SSM daemonset 설치 스크립트를 적용하겠습니다.


# 스크립트 분리 
cat << 'EOT' > install.sh
#!/bin/bash
set -e

echo "[INFO] 사용자 스크립트 실행 중"
echo "노드 이름: \$(hostname)"
echo "현재 시간: \$(date)"
touch /tmp/ssm-installed.marker

# 예: SSM 설치
yum install -y \
  https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm

echo "[INFO] 설치 완료"
EOT

# 컨피그맵 설정 
kubectl create configmap user-install-script \
  --from-file=install.sh=./install.sh \
  -n kube-system


# 데몬셋 배포
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: ssm-installer
  namespace: kube-system
  labels:
    k8s-app: ssm-installer
spec:
  selector:
    matchLabels:
      k8s-app: ssm-installer
  template:
    metadata:
      labels:
        k8s-app: ssm-installer
    spec:
      initContainers: # 한번만 실행
      - name: user-script-runner
        image: amazonlinux:2023
        command: ["/bin/bash", "/scripts/install.sh"]
        volumeMounts:
        - name: script-volume
          mountPath: /scripts
        securityContext:
          allowPrivilegeEscalation: false # 프로세스에서 더 높은 권한을 못가짐 
          capabilities: 
            add: ["CAP_DAC_OVERRIDE"] # 파일 작업 권한 부여 
      containers:
      - name: sleeper
        image: busybox
        command: ["sh", "-c", "sleep 3600"]
      restartPolicy: Always
      volumes:
      - name: script-volume
        configMap:
          name: user-install-script


# 로그 확인
kubectl logs -n kube-system -l k8s-app=ssm-installer -c user-script-runner 

 

'Cloud' 카테고리의 다른 글

EKS Version Upgrade  (0) 2025.04.02
EKS Fargate & AutoMode  (0) 2025.03.23
EKS Security  (2) 2025.03.16
EKS Karpenter  (0) 2025.03.09
EKS Autoscaling  (0) 2025.03.09