기본 제공 Linux 보안 기능을 사용하여 리소스에 대한 보안 컨테이너 액세스
이 문서에서는 AKS(Azure Kubernetes Service) 워크로드에 대한 리소스에 대한 컨테이너 액세스를 보호하는 방법을 알아봅니다.
개요
사용자나 그룹에 필요한 최소한의 권한을 부여해야 하듯이 컨테이너를 필요한 작업과 프로세스로만 제한해야 합니다. 공격 위험을 최소화하려면 상승된 권한이나 루트 액세스가 필요한 애플리케이션 및 컨테이너를 구성하지 마십시오.
기본 제공 Kubernetes Pod 보안 컨텍스트 를 사용하여 실행할 사용자 또는 그룹, 노출할 Linux 기능 또는 Pod 매니페스트에서 설정 allowPrivilegeEscalation: false
과 같은 더 많은 권한을 정의할 수 있습니다. 추가 모범 사례에 대해서는 리소스에 대한 pod 액세스 보안 유지를 참조하세요.
컨테이너 작업을 보다 세부적으로 제어하기 위해 AppArmor 및 seccomp와 같은 기본 제공 Linux 보안 기능을 사용할 수 있습니다.
- 노드 수준에서 Linux 보안 기능을 정의합니다.
- Pod 매니페스트를 통해 기능을 구현합니다.
Linux 노드 및 pod에서만 기본 제공 Linux 보안 기능을 사용할 수 있습니다.
참고 항목
현재 Kubernetes 환경은 적대적인 다중 테넌트 사용에 완전히 안전하지 않습니다. 컨테이너용 Microsoft Defender, AppArmor, seccomp, Pod Security 허용 또는 노드용 Kubernetes RBAC와 같은 추가 보안 기능은 악용을 효율적으로 차단합니다.
악의적인 다중 테넌트 워크로드를 실행할 때의 진정한 보안을 위해서는 하이퍼바이저만 신뢰하세요. Kubernetes의 보안 도메인은 개별 노드가 아닌 전체 클러스터가 됩니다.
이러한 유형의 악의적인 다중 테넌트 워크로드의 경우 물리적으로 격리된 클러스터를 사용해야 합니다.
App Armor
컨테이너 작업을 제한하기 위해 AppArmor Linux 커널 보안 모듈을 사용할 수 있습니다. AppArmor는 기본 AKS 노드 OS의 일부로 사용할 수 있으며 기본적으로 사용하도록 설정됩니다. 읽기, 쓰기 또는 실행 작업이나 파일 시스템 탑재와 같은 시스템 함수를 제한하는 AppArmor 프로필을 만듭니다. 기본 AppArmor 프로필은 다양한 /proc
/sys
위치에 대한 액세스를 제한하고 컨테이너를 기본 노드에서 논리적으로 격리하는 수단을 제공합니다. AppArmor는 Kubernetes pod 뿐 아니라 Linux에서 실행되는 모든 애플리케이션에 작동합니다.
작동하는 AppArmor를 볼 수 있도록 하기 위해 다음 예제에서는 파일에 대한 쓰기를 방지하는 프로필을 만듭니다.
AKS 노드에 SSH로 연결합니다.
deny-write.profile이라는 파일을 만듭니다.
다음 콘텐츠를 복사하여 붙여넣습니다.
#include <tunables/global> profile k8s-apparmor-example-deny-write flags=(attach_disconnected) { #include <abstractions/base> file, # Deny all file writes. deny /** w, }
AppArmor 프로필은 apparmor_parser
명령을 사용하여 추가됩니다.
AppArmor에 프로필을 추가합니다.
이전 단계에서 만든 프로필의 이름을 지정합니다.
sudo apparmor_parser deny-write.profile
프로필이 올바르게 구문 분석되어 AppArmor에 적용되는 경우 출력이 표시되지 않으며 명령 프롬프트로 돌아갑니다.
로컬 컴퓨터에서 aks-apparmor.yaml이라는 Pod 매니페스트를 생성합니다. 이 매니페스트는:
container.apparmor.security.beta.kubernetes
에 대한 주석을 정의합니다.- 이전 단계에서 만든 deny-write 프로필을 참조합니다.
apiVersion: v1 kind: Pod metadata: name: hello-apparmor annotations: container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-deny-write spec: containers: - name: hello image: mcr.microsoft.com/dotnet/runtime-deps:6.0 command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]
Pod가 배포된 상태에서 다음 명령을 실행하고 hello-apparmor Pod에 실행 중 상태가 표시되는지 확인합니다.
kubectl get pods NAME READY STATUS RESTARTS AGE aks-ssh 1/1 Running 0 4m2s hello-apparmor 0/1 Running 0 50s
AppArmor에 대한 자세한 내용은 Kubernetes의 AppArmor 프로필을 참조하세요.
보안 컴퓨팅(seccomp)
AppArmor는 Linux 애플리케이션에 작동하지만 seccomp(secure computing)는 프로세스 수준에서 작동합니다. Seccomp는 Linux 커널 보안 모듈이기도 하며 AKS 노드에서 사용하는 런타임에서 containerd
기본적으로 지원됩니다. seccomp를 사용하면 컨테이너의 시스템 호출을 제한할 수 있습니다. Seccomp는 악의적인 행위자가 악용하는 일반적인 시스템 호출 취약성에 대한 추가 보호 계층을 설정하고 노드의 모든 워크로드에 대한 기본 프로필을 지정할 수 있습니다.
기본 seccomp 프로필 구성(미리 보기)
새 Linux 노드 풀을 만들 때 사용자 지정 노드 구성을 사용하여 기본 seccomp 프로필을 적용할 수 있습니다. AKS RuntimeDefault
Unconfined
에는 두 가지 값이 지원됩니다. 일부 워크로드에는 다른 워크로드보다 적은 수의 syscall 제한이 필요할 수 있습니다. 즉, 'RuntimeDefault' 프로필을 사용하여 런타임 중에 실패할 수 있습니다. 이러한 오류를 완화하려면 프로필을 지정할 Unconfined
수 있습니다. 워크로드에 사용자 지정 프로필이 필요한 경우 사용자 지정 seccomp 프로필 구성을 참조하세요.
제한 사항
- SeccompDefault는 Windows 노드 풀에 대해 지원되는 매개 변수가 아닙니다.
- SeccompDefault는 2024-09-02-preview API부터 사용할 수 있습니다.
Important
AKS 미리 보기 기능은 셀프 서비스에서 사용할 수 있습니다(옵트인 방식). 미리 보기는 "있는 그대로" 및 "사용 가능한 상태로" 제공되며 서비스 수준 계약 및 제한적 보증에서 제외됩니다. AKS 미리 보기의 일부는 고객 지원팀에서 최선을 다해 지원합니다. 따라서 이러한 기능은 프로덕션 용도로 사용할 수 없습니다. 자세한 내용은 다음 지원 문서를 참조하세요.
KubeletDefaultSeccompProfilePreview
기능 플래그 등록
az feature register
명령을 사용하여KubeletDefaultSeccompProfilePreview
기능 플래그를 등록합니다.az feature register --namespace "Microsoft.ContainerService" --name "KubeletDefaultSeccompProfilePreview"
상태가 Registered로 표시되는 데 몇 분 정도 걸립니다.
또한
az feature show
명령을 사용하여 등록 상태를 확인합니다.az feature show --namespace "Microsoft.ContainerService" --name "KubeletDefaultSeccompProfilePreview"
상태가 Registered(등록됨)를 반영하면
az provider register
명령을 사용하여 Microsoft.ContainerService 리소스 공급자의 등록을 새로 고칩니다.az provider register --namespace Microsoft.ContainerService
seccomp를 사용하여 컨테이너의 시스템 호출 제한
1. 다음 단계를 수행하여 kubelet 구성에서 seccomp 프로필을 지정하여 적용합니다. "seccompDefault": "RuntimeDefault"
RuntimeDefault
는 containerd의 기본 seccomp 프로필을 사용하여 보안을 강화하기 위해 특정 시스템 호출을 제한합니다. 제한된 syscall이 실패합니다. 자세한 내용은 containerD 기본 seccomp 프로필을 참조 하세요.
2. 구성이 적용되었는지 확인합니다.
호스트에 연결하고 파일 시스템에 구성이 변경되었는지 확인하여 설정이 노드에 적용되었는지 확인할 수 있습니다.
3. 워크로드 오류 문제를 해결합니다.
SeccompDefault를 사용하도록 설정하면 컨테이너 런타임 기본 seccomp 프로필은 기본적으로 노드에 예약된 모든 워크로드에 사용됩니다. 이로 인해 차단된 syscall로 인해 워크로드가 실패할 수 있습니다. 워크로드 오류가 발생한 경우 다음과 같은 오류가 표시될 수 있습니다.
- 기능이 활성화된 후 워크로드가 예기치 않게 존재하며 "사용 권한 거부" 오류가 발생합니다.
- seccomp 오류 메시지는 SCMP_ACT_ERRNO 기본 프로필의 SCMP_ACT_LOG 바꿔 감사 또는 syslog에서도 볼 수 있습니다.
위의 오류가 발생하는 경우 seccomp 프로필을 Unconfined
.로 변경하는 것이 좋습니다. Unconfined
는 syscall에 제한을 두지 않고 모든 시스템 호출을 허용하여 보안을 줄입니다.
사용자 지정 seccomp 프로필 구성
사용자 지정 seccomp 프로필을 사용하면 제한된 syscall을 보다 세부적으로 제어할 수 있습니다. 다음을 통해서만 실행할 수 있도록 컨테이너에 최소한의 권한을 부여하는 모범 사례에 맞춰 조정합니다.
- 필터를 사용하여 허용하거나 거부할 작업을 정의합니다.
- seccomp 필터와 연결할 Pod YAML 매니페스트 내에서 주석을 추가합니다.
작동 중인 seccomp를 보려면 파일에 대한 권한을 변경하지 못하게 하는 필터를 만듭니다.
AKS 노드에 SSH로 연결합니다.
/var/lib/kubelet/seccomp/prevent-chmod라는 seccomp 필터를 만듭니다.
다음 콘텐츠를 복사하여 붙여넣습니다.
{ "defaultAction": "SCMP_ACT_ALLOW", "syscalls": [ { "name": "chmod", "action": "SCMP_ACT_ERRNO" }, { "name": "fchmodat", "action": "SCMP_ACT_ERRNO" }, { "name": "chmodat", "action": "SCMP_ACT_ERRNO" } ] }
버전 1.19 이상에서는 다음을 구성해야 합니다.
{ "defaultAction": "SCMP_ACT_ALLOW", "syscalls": [ { "names": ["chmod","fchmodat","chmodat"], "action": "SCMP_ACT_ERRNO" } ] }
로컬 컴퓨터에서 aks-seccomp.yaml이라는 Pod 매니페스트를 만든 후 다음 콘텐츠를 붙여넣습니다. 이 매니페스트는:
seccomp.security.alpha.kubernetes.io
에 대한 주석을 정의합니다.- 이전 단계에서 만든 prevent-chmod 필터를 참조합니다.
apiVersion: v1 kind: Pod metadata: name: chmod-prevented annotations: seccomp.security.alpha.kubernetes.io/pod: localhost/prevent-chmod spec: containers: - name: chmod image: mcr.microsoft.com/dotnet/runtime-deps:6.0 command: - "chmod" args: - "777" - /etc/hostname restartPolicy: Never
버전 1.19 이상에서는 다음을 구성해야 합니다.
apiVersion: v1 kind: Pod metadata: name: chmod-prevented spec: securityContext: seccompProfile: type: Localhost localhostProfile: prevent-chmod containers: - name: chmod image: mcr.microsoft.com/dotnet/runtime-deps:6.0 command: - "chmod" args: - "777" - /etc/hostname restartPolicy: Never
kubectl apply 명령을 사용하여 샘플 pod를 배포합니다.
kubectl apply -f ./aks-seccomp.yaml
kubectl get pods 명령을 사용하여 Pod 상태를 봅니다.
- Pod는 오류를 보고합니다.
- 예제
chmod
출력에 표시된 것처럼 seccomp 필터에서 명령을 실행할 수 없습니다.
kubectl get pods NAME READY STATUS RESTARTS AGE chmod-prevented 0/1 Error 0 7s
Seccomp 보안 프로필 옵션
Seccomp 보안 프로필은 허용되거나 제한된 정의된 syscall 집합입니다. 대부분의 컨테이너 런타임에는 Docker에서 사용하는 것과 동일하지 않은 경우 유사한 기본 seccomp 프로필이 있습니다. 사용 가능한 프로필에 대한 자세한 내용은 Docker 또는 containerD 기본 seccomp 프로필을 참조하세요.
AKS는 사용자 지정 노드 구성을 사용하여 seccomp를 구성할 때 RuntimeDefault에 대해 containerD 기본 seccomp 프로필을 사용합니다.
기본 프로필에 의해 차단된 중요한 syscall
Docker 및 containerD는 모두 안전한 syscall 허용 목록을 유지 관리합니다. 이 표에는 허용 목록에 없기 때문에 효과적으로 차단되는 중요한(전부는 아님) syscall이 나열되어 있습니다. 워크로드에 차단된 syscall이 필요한 경우 seccomp 프로필을 사용하지 RuntimeDefault
마세요.
Docker 및 containerD가 변경되면 AKS는 기본 구성을 일치하도록 업데이트합니다. 이 목록을 업데이트하면 워크로드 오류가 발생할 수 있습니다. 릴리스 업데이트는 AKS 릴리스 정보를 참조 하세요.
차단된 syscall | 설명 |
---|---|
acct |
컨테이너가 자체 리소스 제한을 사용하지 않도록 설정하거나 회계를 처리할 수 있는 회계 syscall입니다. 또한 에 의해 CAP_SYS_PACCT 게이트 . |
add_key |
컨테이너가 이름 간격이 지정되지 않은 커널 키링을 사용하지 못하도록 합니다. |
bpf |
이미 CAP_SYS_ADMIN 제어된 커널에 잠재적으로 영구적인 bpf 프로그램 로드를 거부합니다. |
clock_adjtime |
시간/날짜의 이름은 지정되지 않습니다. 또한 에 의해 CAP_SYS_TIME 게이트 . |
clock_settime |
시간/날짜의 이름은 지정되지 않습니다. 또한 에 의해 CAP_SYS_TIME 게이트 . |
clone |
새 네임스페이스 복제를 거부합니다. 또한 플래그에 의해 CAP_SYS_ADMIN for CLONE_* 제어( 제외)CLONE_NEWUSER |
create_module |
커널 모듈에서 조작 및 함수를 거부합니다. 사용되지 않습니다. 또한 에 의해 CAP_SYS_MODULE 게이트 . |
delete_module |
커널 모듈에서 조작 및 함수를 거부합니다. 또한 에 의해 CAP_SYS_MODULE 게이트 . |
finit_module |
커널 모듈에서 조작 및 함수를 거부합니다. 또한 에 의해 CAP_SYS_MODULE 게이트 . |
get_kernel_syms |
내보낸 커널 및 모듈 기호의 검색을 거부합니다. 사용되지 않습니다. |
get_mempolicy |
커널 메모리 및 NUMA 설정을 수정하는 Syscall입니다. 이미 에 의해 CAP_SYS_NICE 게이트 . |
init_module |
커널 모듈에서 조작 및 함수를 거부합니다. 또한 에 의해 CAP_SYS_MODULE 게이트 . |
ioperm |
컨테이너가 커널 I/O 권한 수준을 수정하지 못하도록 합니다. 이미 에 의해 CAP_SYS_RAWIO 게이트 . |
iopl |
컨테이너가 커널 I/O 권한 수준을 수정하지 못하도록 합니다. 이미 에 의해 CAP_SYS_RAWIO 게이트 . |
kcmp |
삭제하여 이미 차단된 프로세스 검사 기능을 제한합니다 CAP_SYS_PTRACE . |
kexec_file_load |
같은 일을하는 kexec_load 자매 syscall, 약간 다른 인수. 또한 에 의해 CAP_SYS_BOOT 게이트 . |
kexec_load |
나중에 실행하기 위해 새 커널 로드를 거부합니다. 또한 에 의해 CAP_SYS_BOOT 게이트 . |
keyctl |
컨테이너가 이름 간격이 지정되지 않은 커널 키링을 사용하지 못하도록 합니다. |
lookup_dcookie |
추적/프로파일링 syscall- 호스트에 대한 정보가 누출될 수 있습니다. 또한 에 의해 CAP_SYS_ADMIN 게이트 . |
mbind |
커널 메모리 및 NUMA 설정을 수정하는 Syscall입니다. 이미 에 의해 CAP_SYS_NICE 게이트 . |
mount |
거부 탑재, 이미 에 의해 CAP_SYS_ADMIN 제어 . |
move_pages |
커널 메모리 및 NUMA 설정을 수정하는 Syscall입니다. |
nfsservctl |
커널 nfs 디먼과의 상호 작용을 거부합니다. Linux 3.1 이후 사용되지 않습니다. |
open_by_handle_at |
이전 컨테이너 중단의 원인입니다. 또한 에 의해 CAP_DAC_READ_SEARCH 게이트 . |
perf_event_open |
추적/프로파일링 syscall- 호스트에 대한 정보가 누출될 수 있습니다. |
personality |
컨테이너가 BSD 에뮬레이션을 사용하도록 설정하지 않도록 합니다. 본질적으로 위험하지는 않지만 제대로 테스트되지 않은 커널 vulns의 잠재력입니다. |
pivot_root |
pivot_root 거부는 권한 있는 작업이어야 합니다. |
process_vm_readv |
삭제하여 이미 차단된 프로세스 검사 기능을 제한합니다 CAP_SYS_PTRACE . |
process_vm_writev |
삭제하여 이미 차단된 프로세스 검사 기능을 제한합니다 CAP_SYS_PTRACE . |
ptrace |
추적/프로파일링 syscall. seccomp 바이패스를 방지하기 위해 4.8 이전의 Linux 커널 버전에서 차단되었습니다. 추적/프로파일링 임의 프로세스는 호스트에 대한 정보를 누수할 수 있으므로 CAP_SYS_PTRACE 삭제하여 이미 차단됩니다. |
query_module |
커널 모듈에서 조작 및 함수를 거부합니다. 사용되지 않습니다. |
quotactl |
컨테이너가 자체 리소스 한도 또는 프로세스 회계를 사용하지 않도록 설정할 수 있는 할당량 syscall입니다. 또한 에 의해 CAP_SYS_ADMIN 게이트 . |
reboot |
컨테이너가 호스트를 다시 부팅하지 않도록 합니다. 또한 에 의해 CAP_SYS_BOOT 게이트 . |
request_key |
컨테이너가 이름 간격이 지정되지 않은 커널 키링을 사용하지 못하도록 합니다. |
set_mempolicy |
커널 메모리 및 NUMA 설정을 수정하는 Syscall입니다. 이미 에 의해 CAP_SYS_NICE 게이트 . |
setns |
스레드를 네임스페이스와 연결하지 않습니다. 또한 에 의해 CAP_SYS_ADMIN 게이트 . |
settimeofday |
시간/날짜의 이름은 지정되지 않습니다. 또한 에 의해 CAP_SYS_TIME 게이트 . |
stime |
시간/날짜의 이름은 지정되지 않습니다. 또한 에 의해 CAP_SYS_TIME 게이트 . |
swapon |
파일/디바이스에 대한 시작/중지 교환을 거부합니다. 또한 에 의해 CAP_SYS_ADMIN 게이트 . |
swapoff |
파일/디바이스에 대한 시작/중지 교환을 거부합니다. 또한 에 의해 CAP_SYS_ADMIN 게이트 . |
sysfs |
사용되지 않는 syscall입니다. |
_sysctl |
사용되지 않으며 /proc/sys로 대체됩니다. |
umount |
권한 있는 작업이어야 합니다. 또한 에 의해 CAP_SYS_ADMIN 게이트 . |
umount2 |
권한 있는 작업이어야 합니다. 또한 에 의해 CAP_SYS_ADMIN 게이트 . |
unshare |
프로세스에 대한 새 네임스페이스 복제를 거부합니다. CAP_SYS_ADMIN 또한 공유 해제 --user를 제외하고 제어합니다. |
uselib |
공유 라이브러리와 관련된 이전 syscall로, 오랫동안 사용되지 않습니다. |
userfaultfd |
프로세스 마이그레이션에 주로 필요한 사용자 공간 페이지 오류 처리입니다. |
ustat |
사용되지 않는 syscall입니다. |
vm86 |
커널 x86 실제 모드 가상 머신에서. 또한 에 의해 CAP_SYS_ADMIN 게이트 . |
vm86old |
커널 x86 실제 모드 가상 머신에서. 또한 에 의해 CAP_SYS_ADMIN 게이트 . |
다음 단계
관련 모범 사례는 AKS의 클러스터 보안 및 업그레이드 모범 사례 및 AKS의 Pod 보안 모범 사례를 참조하세요.
Azure Kubernetes Service