본 가이드는 AppArmor for 쿠버네티스(Kubernetes) 핵심 가이드 및 실전 아키텍처의 핵심 개념, 구성 아키텍처 및 실무 엔지니어링 베스트 프랙티스를 체계적으로 정리했습니다.
📑 Table of Contents
- AppArmor 동작 이해
- 왜 AppArmor인가? (DAC vs MAC)
- AppArmor의 핵심 모드 및 프로필 제어
- Kubernetes(K8s) 환경에서의 AppArmor 통합
- 핵심 정리
- 참고 자료
- Kubernetes 활용 요점정리
- 1. 개요 및 개념 (Overview & Concepts)
- 2. 시스템 아키텍처 (Architecture)
- 3. 시퀀스 다이어그램 (Sequence Diagram)
- 4. 시스템 바이너리
- 5. 유틸리티 바이너리
- CKS(Certified Kubernetes Security Specialist) 응시 및 활용 팁
AppArmor 동작 이해
왜 AppArmor인가? (DAC vs MAC)
- 임의적 접근 제어 (DAC, Discretionary Access Control)
- 정의: 사용자/그룹의 신원을 기반으로 파일 권한(
rwxrwxrwx)을 부여하는 리눅스의 기본 보안 모델입니다. - 한계: 프로세스가 해당 프로세스를 실행한 사용자의 모든 권한을 상속받습니다.
- 취약점 사례: 단순 로그 정리 프로그램(
cleanup.sh)이 루트(root) 권한으로 실행 중일 때, 공격자에 의해 오염되어 외부 인터넷으로 중요 데이터를 유출하려 하거나 핑(ping) 등의 바이너리를 실행하려 해도 DAC 환경에서는 사용자가 루트이므로 이를 제한할 방법이 없습니다. - 필수적 접근 제어 (MAC, Mandatory Access Control)
- 정의: 중앙의 미리 정의된 보안 정책(프로필)을 기반으로 프로세스의 행동을 강제적으로 제약합니다.
- 효과: 프로세스가 루트 권한으로 실행되더라도, 프로필에 명시되지 않은 행동(예: 인터넷 연결, 비인가 파일 접근 등)은 모두 차단됩니다.
- 대안 솔루션: SELinux(RedHat 계열, 설정이 복잡함)와 AppArmor(Ubuntu/Debian 계열, 설정이 직관적이고 상대적으로 쉬움)가 대표적입니다.
AppArmor의 핵심 모드 및 프로필 제어
AppArmor는 시스템에서 세 가지 모드로 작동할 수 있습니다.
1. AppArmor 3대 모드
- Enforce (적용 모드): 정의된 보안 프로필을 강제 적용하여 비인가 행동을 즉시 차단합니다.
- Complain (신고 모드): 정책 위반 행위를 차단하지 않고 로그(
syslog,audit.log)에 기록만 남깁니다. (운영 환경 적용 전 테스트 단계에서 주로 사용) - Unconfined (제한 없음): 아무런 제약을 가하지 않고 일반 프로세스처럼 실행합니다.
# 특정 프로파일을 'Enforce (실제 차단하는 모드)'로 변경
sudo aa-enforce /etc/apparmor.d/$profile
# 특정 프로파일을 'Complain (로그만 남기는 모드)'로 변경
sudo aa-complain /etc/apparmor.d/$profile
# 프로필 제거 = 'Unconfined (프로필이 적용되지 않은 상태)'로 변경
sudo apparmor_parser -R /etc/apparmor.d/$profile
2. 실습: 프로필 자동 생성 프로세스
수동으로 규칙을 짜는 대신, AppArmor의 모니터링 도구를 사용하여 간편하게 프로필을 빌드할 수 있습니다.
- 유틸리티 설치
# auditd 설치 (syslog에 App활동 기록, profile 자동생성시 필요)
sudo apt install -y auditd
# auditd 서비스 시작 및 부팅 시 자동 실행 설정
sudo systemctl start auditd
sudo systemctl enable auditd
sudo apt-get install -y apparmor-utils
- 대상 스크립트 작성 (
/root/apparmor/app.sh)
mkdir -p /root/apparmor/
cat <<EOF > /root/apparmor/app.sh
#!/bin/bash
touch /tmp/file.txt # 임시 파일 생성
echo "File Created"
rm /tmp/file.txt # 임시 파일 삭제
echo "File Removed"
EOF
- 프로필 자동 생성 실행
sudo aa-genprof /root/apparmor/app.sh
- 실행 후 다른 터미널에서 스크립트를 실제로 실행(
./app.sh)하여 평소 필요한 파일 접근 패턴을 생성합니다. aa-genprof화면으로 돌아와S를 입력하여 로그를 스캔하고, 접근 요청건에 대해Inherit(상속)또는Allow(허용)등을 선택합니다.- 프로필 저장이 완료되면
/etc/apparmor.d/root.apparmor.app.sh경로에 파일이 생성됩니다.
Allow Guide (S – I – I – A – A – A – A – S – F)
[(S)can system log for AppArmor events] / (F)inish
Reading log entries from /var/log/audit/audit.log.
Profile: /root/apparmor/app.sh
Execute: /usr/bin/touch
Severity: 3
(I)nherit / (C)hild / (N)amed / (X) ix On / (D)eny / Abo(r)t / (F)inish
Profile: /root/apparmor/app.sh
Execute: /usr/bin/rm
Severity: unknown
(I)nherit / (C)hild / (N)amed / (X) ix On / (D)eny / Abo(r)t / (F)inish
Complain-mode changes:
Profile: /root/apparmor/app.sh
Path: /dev/tty
New Mode: owner rw
Severity: 9
[1 - include <abstractions/consoles>]
2 - owner /dev/tty rw,
(A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish
Adding include <abstractions/consoles> to profile.
Profile: /root/apparmor/app.sh
Path: /etc/ld.so.cache
New Mode: owner r
Severity: 1
[1 - owner /etc/ld.so.cache r,]
(A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish
Adding owner /etc/ld.so.cache r, to profile.
Profile: /root/apparmor/app.sh
Path: /etc/locale.alias
New Mode: owner r
Severity: unknown
[1 - owner /etc/locale.alias r,]
(A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish
Adding owner /etc/locale.alias r, to profile.
Profile: /root/apparmor/app.sh
Path: /tmp/file.txt
New Mode: owner w
Severity: unknown
[1 - include <abstractions/user-tmp>]
2 - owner /tmp/file.txt w,
(A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish
Adding include <abstractions/user-tmp> to profile.
= Changed Local Profiles =
The following local profiles were changed. Would you like to save them?
[1 - /root/apparmor/app.sh]
(S)ave Changes / Save Selec(t)ed Profile / [(V)iew Changes] / View Changes b/w (C)lean profiles / Abo(r)t
Writing updated profile for /root/apparmor/app.sh.
Profiling: /root/apparmor/app.sh
Please start the application to be profiled in
another window and exercise its functionality now.
Once completed, select the "Scan" option below in
order to scan the system logs for AppArmor events.
For each AppArmor event, you will be given the
opportunity to choose whether the access should be
allowed or denied.
[(S)can system log for AppArmor events] / (F)inish
Setting /root/apparmor/app.sh to enforce mode.
Reloaded AppArmor profiles in enforce mode.
Please consider contributing your new profile!
See the following wiki page for more information:
https://gitlab.com/apparmor/apparmor/wikis/Profiles
Finished generating profile for /root/apparmor/app.sh.
4. 허용되지 않은 동작 테스트
– 스크립트에 ping localhost 같은 허용되지 않은 바이너리 호출을 몰래 추가한 후 실행하면, 실행자가 root일지라도 Permission Denied 에러와 함께 동작이 엄격하게 제한됩니다.
5. 프로필 비활성화(제거) 방법
sudo apparmor_parser -R /etc/apparmor.d/root.apparmor.app.sh
Kubernetes(K8s) 환경에서의 AppArmor 통합
쿠버네티스는 Pod 내부 컨테이너의 보안 향상을 위해 노드 레벨의 AppArmor 프로필을 로드하여 적용할 수 있습니다.
1. 사전 조건
- 노드(Node) 커널에 AppArmor가 활성화되어 있어야 합니다.
- 컨테이너에 적용할 AppArmor 프로필이 포드가 실행될 모든 노드의 파일 시스템에 미리 로드되어 있어야 합니다.
2. K8s 적용용 AppArmor 프로필 예시 (전체 쓰기 거부)
/etc/apparmor.d/k8s-deny-write 파일에 등록 후 파싱하는 방식:
cat <<EOF > /etc/apparmor.d/k8s-deny-write
profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
file,
# 모든 쓰기 동작 차단 (여기서의 #은 실제 주석입니다)
deny /** w,
}
EOF
# 로드
sudo apparmor_parser -r -W /etc/apparmor.d/k8s-deny-write
# 프로필 로드 상태 확인
aa-status | grep k8s-apparmor-example-deny-write
3. Pod 매니페스트 설정 (securityContext 적용)
V1.30+ 규격 또는 일반적인 Pod 스펙에 따라 securityContext를 통해 프로필을 선언합니다.
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: hello-apparmor
spec:
securityContext:
appArmorProfile:
type: Localhost
localhostProfile: k8s-apparmor-example-deny-write # 노드에 로드된 프로필 이름
containers:
- name: busybox
image: busybox:1.36
command: ["sh", "-c", "echo 'Hello AppArmor' && sleep 3600"]
EOF
k get pods hello-apparmor
[!IMPORTANT]
주의 사항 (Troubleshooting)
localhostProfile로 명시한 이름의 프로필이 해당 노드에 실제로 로드되어 있지 않은 경우, Pod는 실행되지 않고ContainerCreating상태에 머무릅니다.kubectl describe pod을 수행하면Failed to create container... AppArmor profile not found에러 메시지를 보게 됩니다. 따라서 데몬셋(DaemonSet)이나 프로비저닝 도구를 사용해 모든 노드에 보안 프로필을 일괄 배포해 두어야 합니다.
4. 프로필 적용 테스트
kubectl exec -it hello-apparmor -- sh
# in container
touch /tmp/test.txt
```prompt
touch: /tmp/test.txt: Permission denied
`
echo "test" > /var/log/test.log
```prompt
sh: can't create /var/log/test.log: nonexistent directory
`
5. 테스트 리소스 정리
# 프로필 제거
sudo apparmor_parser -R /etc/apparmor.d/k8s-deny-write
# 프로필 파일 제거
rm /etc/apparmor.d/k8s-deny-write
# 제거
k delete pods hello-apparmor --force
핵심 정리
- AppArmor는 DAC의 ‘루트 권한 과다 상속’ 문제를 보완하는 강력한 리눅스 보안 모듈입니다.
- 프로덕션 적용 전략: 처음부터 바로 Enforce 모드를 적용하면 실서비스 기능이 중단되는 참사가 일어날 수 있으므로, Complain 모드로 시작해 로그 분석 후 안정화된 상태에서 Enforce로 변경하는 것이 정석입니다.
- K8s 보안의 기초: CKS 시험 및 엔터프라이즈 환경에서 보안 경계를 공고히 하기 위해 Pod 수준의
securityContext에 AppArmor 설정을 결합하는 패턴은 필수적입니다.
참고 자료
- AppArmor | Killer Shell CKS | Killercoda
- Restrict a Container’s Access to Resources with AppArmor
- Configure a Security Context for a Pod or Container
- Certified Kubernetes Security Specialist 2026
Kubernetes 활용 요점정리
1. 개요 및 개념 (Overview & Concepts)
AppArmor(Application Armor)는 리눅스 커널에 구현된 강제 접근 제어(MAC, Mandatory Access Control) 시스템입니다. 전통적인 유닉스 방식의 임의적 접근 제어(DAC, Discretionary Access Control – 파일 소유자 및 권한 기반)를 보완하여, 프로세스가 시스템 리소스(파일, 네트워크, 기능 등)에 접근하는 것을 제한합니다.
핵심 개념
- 경로 기반 제한(Path-based): SELinux가 파일 시스템의 ‘레이블(Label)’을 기준으로 작동하는 반면, AppArmor는 파일의 절대 경로를 기준으로 보안 규칙을 적용하므로 직관적이고 관리가 편합니다.
- 프로필(Profile): 특정 애플리케이션이나 실행 파일이 수행할 수 있는 작업 목록을 정의한 텍스트 파일입니다. 주로
/etc/apparmor.d/디렉토리에 위치합니다. - 작동 모드 (Execution Modes):
- Enforce (강제 모드): 프로필에 정의되지 않은 작업을 허용하지 않고 차단하며, 로그를 남깁니다.
- Complain (불평 모드): 규칙을 위반해도 차단하지 않고, 허용되지 않은 작업이 무엇인지 로그만 기록합니다. (개발 및 프로필 학습 단계에서 주로 사용)
쿠버네티스 환경에서의 흐름
– 적용 대상: 특정 경로의 실행 파일(바이너리) 또는 프로세스
– 작동 위치: 컨테이너 내부가 아닌, 호스트 디바이스의 리눅스 커널(LSM: Linux Security Module)
– 제한하는 행위: * 특정 파일/디렉토리의 읽기, 쓰기, 실행 권한 (r, w, x)
– 네트워크 소켓 생성 및 통신
– RAW 캡처 등 특수 기능(Capabilities) 사용
쿠버네티스에서 AppArmor를 적용할 때의 흐름을 보면 왜 프로세스가 통제 대상인지 명확해집니다.
- 호스트 노드에 프로필 로드: 먼저 쿠버네티스 워커 노드(호스트 OS)의 AppArmor에 프로필을 등록합니다. (예:
k8s-apparmor-deny-write) - Pod YAML에 선언: Pod 설정을 통해 특정 컨테이너에 해당 프로필을 지정합니다.
- 컨테이너 실행 시 적용: 컨테이너가 구동되면, 컨테이너의 메인 프로세스(PID 1)와 그 자식 프로세스들이 호스트 커널에 의해 프로필 제약을 받게 됩니다.
쉽게 이해하는 예시
만약 컨테이너 내부의 프로세스가 /etc/passwd 파일을 수정하려고 하거나, 허용되지 않은 네트워크 바인딩을 시도하면 호스트 커널 단에서 AppArmor가 이를 가로채 Permission Denied 에러를 발생시키고 차단합니다.
클러스터 Requirements
- 쿠버네티스 버전: 1.4\~
- AppArmor 커널 모듈을 사용 가능해야 한다. — 리눅스 커널에 AppArmor 프로파일을 강제 적용하기 위해 AppArmor 커널 모듈은 반드시 설치되어 있고 사용 가능해야 한다. 예를 들어 Ubuntu 및 SUSE 같은 배포판은 모듈을 기본값으로 지원하고, 그 외 많은 다른 배포판들은 선택적으로 지원한다.
# 모듈이 사용 가능한지 확인하려면 다음이 `Y`인지 확인
cat /sys/module/apparmor/parameters/enabled
- 컨테이너 런타임이 AppArmor을 지원한다. — 현재 모든 일반적인 쿠버네티스를 지원하는 도커 (원문, Docker), CRI-O 또는 containerd 와 같은 컨테이너 런타임들은 AppArmor를 지원해야 한다. 이 런타임 설명서를 참조해서 클러스터가 AppArmor를 사용하기 위한 요구 사항을 충족하는지 확인해야 한다.
- 프로파일이 적재되어 있다. — AppArmor는 각 컨테이너와 함께 실행해야 하는 AppArmor 프로파일을 지정하여 파드에 적용한다. 커널에 지정한 프로파일이 적재되지 않았다면, Kubelet(>= v1.4)은 파드를 거부한다.
# 해당 노드에 어떤 프로파일이 적재되었는지는 다음을 통해 확인
ssh nodename "sudo cat /sys/kernel/security/apparmor/profiles | sort"
적용범위와 프로필 지정에 관하여
- AppArmor 프로필은 파드 수준 또는 컨테이너 수준에서 지정할 수 있습니다. 컨테이너 AppArmor 프로필이 파드 프로필보다 우선순위가 높습니다.
pod.spec.containers.securityContext.appArmorProfilepod.spec.securityContext.appArmorProfileappArmorProfile
securityContext:
appArmorProfile:
type: <profile_type>
은 다음 중 하나입니다.RuntimeDefault: 런타임의 기본 프로필 사용Localhost: 호스트에 로드된 프로필 사용(아래 참조)Unconfined: AppArmor 없이 실행
-
Description
“`yaml
k explain pod.spec.securityContext.appArmorProfile
—
KIND: Pod
VERSION: v1FIELD: appArmorProfile
DESCRIPTION:
appArmorProfile is the AppArmor options to use by the containers in this
pod. Note that this field cannot be set when spec.os.name is windows.
AppArmorProfile defines a pod or container’s AppArmor settings.FIELDS:
localhostProfile
localhostProfile indicates a profile loaded on the node that should be used.
The profile must be preconfigured on the node to work. Must match the loaded
name of the profile. Must be set if and only if type is “Localhost”.type
-required-
enum: Localhost, RuntimeDefault, Unconfined
type indicates which kind of AppArmor profile will be applied. Valid options
are:
Localhost – a profile pre-loaded on the node.
RuntimeDefault – the container runtime’s default profile.
Unconfined – no AppArmor enforcement.Possible enum values: - `"Localhost"` indicates that a profile pre-loaded on the node should be used. - `"RuntimeDefault"` indicates that the container runtime's default AppArmor profile should be used. - `"Unconfined"` indicates that no AppArmor profile should be enforced.“`
2. 시스템 아키텍처 (Architecture)
AppArmor는 사용자 공간의 관리 도구들과 리눅스 커널 내부의 LSM(Linux Security Module) 프레임워크가 긴밀히 연결되어 작동합니다.
3. 시퀀스 다이어그램 (Sequence Diagram)
컨테이너 또는 일반 프로세스가 파일에 접근을 시도할 때, AppArmor 커널 모듈이 이를 검사하고 처리하는 런타임 흐름입니다.
4. 시스템 바이너리
AppArmor는 커널과 상호작용하고 프로필을 관리하기 위한 다양한 사용자 공간(Userspace) 도구 및 바이너리를 제공합니다.
커널 보안도구이므로 각 노드별로 별도로 실행되어야 합니다.
핵심 관리 바이너리
apparmor_parser, aa-status 외의 바이너리는 CKS 출제범위 외로 확인됩니다.
apparmor_parser: AppArmor의 가장 핵심적인 바이너리입니다. 사람이 읽을 수 있는 텍스트 프로필을 파싱하여 커널이 이해할 수 있는 바이너리 형태로 컴파일한 뒤, 커널 내에 로드합니다.
# -r 플래그와 함께 사용하면 create/update 모두 대응가능
sudo apparmor_parser -r /etc/apparmor.d/$profile
# 프로파일 적용
sudo apparmor_parser $profile
aa-status(또는apparmor_status): 현재 시스템의 AppArmor 상태를 확인합니다. 로드된 프로필 수, 각 프로필의 모드(Enforce/Complain), 프로필이 적용되어 격리 중인 프로세스 목록을 보여줍니다.
# 실행된 노드의 로드된 프로필 목록 조회
sudo aa-status
# 프로파일 활성화여부 조회
sudo aa-status | grep $profile
시스템 진단 및 확인
aa-enabled현재 시스템 커널에서 AppArmor가 활성화(Enabled)되어 있는지 여부를Yes또는No로 아주 심플하게 답해주는 바이너리입니다. 스크립트 분기문에서 주로 씁니다.
aa-enabled
프로세스 직접 격리 실행 (출제범위 외)
aa-exec특정 AppArmor 프로필을 강제로 지정하면서 프로그램을 실행할 때 씁니다.
aa-exec -p <프로필이름> <실행할명령어>
시스템 관리 및 초기화 (주로 부팅/종료 시 사용) (출제범위 외)
aa-teardown현재 커널에 로드된 모든 AppArmor 프로필을 한 번에 제거하고 언로드합니다. 즉, AppArmor의 모든 방어벽을 일시적으로 완전히 내릴 때 사용합니다. (주의해서 사용해야 합니다.)
sudo aa-teardown
aa-remove-unknown커널에 로드되어 있는 프로필 중, 현재/etc/apparmor.d/디렉토리에 실제 파일로 존재하지 않는 ‘출처 불분명한(Unknown)’ 프로필들을 식별해 커널에서 자동으로 깨끗하게 지워줍니다.
sudo aa-remove-unknown
aa-load/etc/apparmor.d/에 있는 정책 파일들을 한꺼번에 커널로 다시 로드할 때 쓰는 내부 스크립트입니다. (우리가 앞서 배운apparmor_parser -r을 디렉토리 전체에 반복 실행하는 것과 유사합니다.)
sudo aa-load
개발자 및 내부 확인용 (출제범위 외)
aa-features-abi현재 리눅스 커널이 지원하는 AppArmor의 기능(Feature) 인터페이스 버전을 출력합니다. 일반적인 운영이나 시험에서는 직접 사용할 일이 거의 없습니다.
aa-features-abi
5. 유틸리티 바이너리
프로필 생성 및 변경 관리 바이너리 (출제범위 외)
aa-genprof: 새로운 애플리케이션을 위한 프로필을 처음부터 생성할 때 사용합니다. 프로그램을 실행하고 동작을 모니터링하여 자동으로 기초 프로필을 빌드합니다.
sudo aa-genprof /usr/bin/custom-app
# 명령어를 실행하면 대기 상태가 됩니다.
# 다른 터미널에서 custom-app을 실행해 정삭적인 작업을 수행한 뒤,
# 다시 돌아와 'S'를 눌러 로그를 스캔하고 프로필을 저장합니다.
aa-logprof: Complain 모드 등으로 인해 발생한 시스템 로그(/var/log/audit/audit.log또는syslog)를 스캔하여, 새로 발견된 애플리케이션의 동작을 기존 프로필에 추가할지 인터랙티브하게 물어보고 업데이트합니다.
sudo aa-logprof
# 시스템 로그를 읽어와 허용 여부를 묻는 인터랙티브 창(Y/N/A/D 등)이 뜹니다.
aa-autodep: 대상 바이너리가 사용하는 공유 라이브러리, 의존성 등을 분석하여 매우 기본적인 뼈대(Minimal skeleton) 프로필을 자동으로 생성해 줍니다.
sudo aa-autodep /usr/bin/custom-app
모드 전환 및 유틸리티 바이너리 (출제범위 외)
aa-enforce: 대상 프로필 또는 바이너리를 Enforce(강제 차단) 모드로 즉시 전환합니다.
# 프로필 파일 경로를 지정하거나, 등록된 바이너리 경로를 지정할 수 있습니다.
sudo aa-enforce /etc/apparmor.d/usr.sbin.nginx
sudo aa-enforce /usr/sbin/nginx
aa-complain: 대상 프로필 또는 바이너리를 Complain(로그 기록) 모드로 즉시 전환합니다.
sudo aa-complain /usr/sbin/nginx
aa-disable: 특정 프로필을 커널에서 언로드하고 영구적으로 비활성화합니다.
sudo aa-disable /usr/sbin/nginx
aa-audit: 특정 프로필에 대해 감사(Audit) 로그 기록을 강제화합니다.
# 1. 특정 바이너리에 적용된 프로필에 audit 모드 강제 적용
sudo aa-audit /usr/sbin/nginx
# 2. 프로필 파일 경로를 직접 지정하여 적용
sudo aa-audit /etc/apparmor.d/usr.sbin.nginx
# 3. (원상 복구) 감사 모드를 해제하고 일반 모드로 복귀
sudo aa-audit --remove /usr/sbin/nginx
aa-unconfined: 현재 네트워크 소켓을 열고 실행 중인 프로세스 중, AppArmor 프로필에 의해 보호(제한)받지 않고 있는 바이너리 목록을 식별해 줍니다.
# 1. 현재 네트워크 소켓을 열고 실행 중인 프로세스 중 보호받지 않는 목록 출력
sudo aa-unconfined
# 출력 예시:
# 1234 /usr/sbin/sshd not confined
# 5678 /usr/bin/python3 (정상 보호 중인 건 아예 안 뜨거나 다르게 표시됨)
# 2. 네트워크 사용 여부와 상관없이, 시스템에서 실행 중인 모든 프로세스를 샅샅이 검사
sudo aa-unconfined --paranoid
aa-notify: AppArmor 차단 로그(DENIED)가 발생했을 때 바탕화면이나 지정된 채널로 알림을 보내주는 유틸리티입니다.
aa-notify -p -s 5 &
# -p: 데스크톱 알림(Notification) 창으로 표시
# -s 5: 최근 5초 이내의 밀린 로그는 요약해서 보여줌
CKS(Certified Kubernetes Security Specialist) 응시 및 활용 팁
CKS 시험에서 AppArmor는 단골로 출제되는 고득점 보안 주제 중 하나입니다. 시험장에서 당황하지 않고 빠르게 문제를 풀기 위한 실전 팁을 정리합니다.
CKS 시험장 실전 행동 강령
- 모든 워커 노드 확인: AppArmor 프로필은 쿠버네티스 마스터가 아니라 컨테이너가 직접 실행될 워커 노드(Worker Node)의 커널에 로드되어 있어야 합니다. 문제에서 지정한 노드로
ssh접속한 뒤 작업을 수행하세요. - 프로필 유효성 선검사: 노드에 접속하면
aa-status를 쳐서 문제에서 요구한 프로필 이름이 이미 로드되어 있는지 확인합니다. - 새로운 프로필 로드 명령 암기: 만약 문제에서 제공한 프로필 파일 파일이 지정되어 있다면 파서를 이용해 커널에 로드해 주어야 합니다.Bash
# 프로필 추가/새로고침 (-r 옵션 사용)
sudo apparmor_parser -r /etc/apparmor.d/제공된_프로필_파일명
- 컨테이너 가동 실패 시 디버깅: AppArmor 설정을 마친 Pod가
CreateContainerConfigError또는CrashLoopBackOff상태로 터진다면 아래 두 가지를 즉시 의심하세요.
–localhostProfile에 적은 프로필 이름이 워커 노드의aa-status에 뜨는 이름과 대소문자까지 일치하는가?
– 프로필 파일 내부 구조의 문법 오류가 없는가? (노드의/var/log/syslog혹은journalctl -u kubelet확인)
seccomp와의 차이점 (CKS 빈출 개념)
CKS 시험에서 AppArmor와 함께 반드시 출제되는 seccomp도 프로세스를 제한하지만, 제어하는 ‘레이어’에 차이가 있습니다.
| 보안 도구 | 주요 차단 대상 및 기준 | 특징 |
| AppArmor |
바이너리 경로 및 자원(개념) 예: “이 프로세스는 /vmlinuz 읽기 금지, 네트워킹 금지”
|
파일 경로, 네트워크 등 추상화된 자원 접근을 직관적으로 통제 |
| seccomp |
시스템 콜(System Call) 번호 예: “이 컨테이너는 chmod, chown 시스템 콜 사용 금지”
|
커널 기능 자체를 로우 레벨(syscall)에서 촘촘하게 차단
|
문제풀이 Tip
- 특정 노드에 특정 프로파일이 활성화되었는지 찾아서 기록하기
### 원격으로 기록하기
cat <<EOF > /root/profiles.txt
$(ssh node01 bash -c 'aa-status' | grep -E 'docker-default|snap.lxd.lxc|ftpd|tcpdump' | awk '{print $1}')
EOF
### or 직접 조회 후 기록
ssh node01
aa-status | grep -E 'docker-default|snap.lxd.lxc|ftpd|tcpdump'
- 준비된 profile의 이름 변경 후 모든 노드에서 활성화
### Change in File
vi $profile
```profile
profile <profile_name> flags=(attach_disconnected,mediate_deleted) {
`
### 모든 노드에 파일 전송
scp $profile node01:
### 모든 노드에 적용
apparmor_parser $profile
ssh node01
apparmor_parser $profile
- 잘못된 프로필명으로 인한 오류 발생 deployment 수정하여 배포 성공하기
# 프로파일명 확인
ssh node01 bash -c 'aa-status'
# 수정 적용
kubectl edit deployment -n $ns $deploy_name
```yaml
# pod.spec or pod.spec.containers
securityContext:
appArmorProfile:
type: Localhost
localhostProfile: <profile_name>
`
-
특정 컨테이너(Multi-Container) 단위 타깃 지정 유형
1. 지정 컨테이너명을 확인하고,
pod.spec.securityContext를pod.spec.containers.securityContext로 이동




Leave a Reply