Information in this document may be out of date
This document has an older update date than the original, so the information it contains may be out of date. If you're able to read English, see the English version for the most up-to-date information: Restrict a Container's Access to Resources with AppArmor
AppArmor๋ฅผ ์ฌ์ฉํ์ฌ ๋ฆฌ์์ค์ ๋ํ ์ปจํ ์ด๋์ ์ ๊ทผ ์ ํ
Kubernetes v1.4 [beta]
AppArmor๋ ํ์ค ๋ฆฌ๋ ์ค ์ฌ์ฉ์์ ๊ทธ๋ฃน ๊ธฐ๋ฐ์ ๊ถํ์ ๋ณด์ํ์ฌ, ํ์ ๋ ๋ฆฌ์์ค ์งํฉ์ผ๋ก ํ๋ก๊ทธ๋จ์ ์ ํํ๋ ๋ฆฌ๋ ์ค ์ปค๋ ๋ณด์ ๋ชจ๋์ด๋ค. AppArmor๋ ์์์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ํด์ ์ ์ฌ์ ์ธ ๊ณต๊ฒฉ ๋ฒ์๋ฅผ ์ค์ด๊ณ ๋์ฑ ์ฌ์ธต์ ์ธ ๋ฐฉ์ด๋ฅผ ์ ๊ณตํ๋๋ก ๊ตฌ์ฑํ ์ ์๋ค. ์ด ๊ธฐ๋ฅ์ ํน์ ํ๋ก๊ทธ๋จ์ด๋ ์ปจํ ์ด๋์์ ํ์ํ ๋ฆฌ๋ ์ค ๊ธฐ๋ฅ, ๋คํธ์ํฌ ์ฌ์ฉ, ํ์ผ ๊ถํ ๋ฑ์ ๋ํ ์ ๊ทผ์ ํ์ฉํ๋ ํ๋กํ์ผ๋ก ๊ตฌ์ฑํ๋ค. ๊ฐ ํ๋กํ์ผ์ ํ์ฉํ์ง ์์ ๋ฆฌ์์ค ์ ๊ทผ์ ์ฐจ๋จํ๋ ๊ฐ์ (enforcing) ๋ชจ๋ ๋๋ ์๋ฐ๋ง์ ๋ณด๊ณ ํ๋ ๋ถํ(complain) ๋ชจ๋๋ก ์คํํ ์ ์๋ค.
AppArmor๋ฅผ ์ด์ฉํ๋ฉด ์ปจํ ์ด๋๊ฐ ์ํํ ์ ์๋ ์์ ์ ์ ํํ๊ณ ๋๋ ์์คํ ๋ก๊ทธ๋ฅผ ํตํด ๋ ๋์ ๊ฐ์ฌ๋ฅผ ์ ๊ณตํ์ฌ ๋ ์์ ํ ๋ฐฐํฌ๋ฅผ ์คํํ ์ ์๋ค. ๊ทธ๋ฌ๋ AppArmor๊ฐ ์ํํ(์ธ์ ๋ ํตํ๋ ๋ฌด์ ์ ๋ฐฉ๋ฒ)์ด ์๋๋ฉฐ, ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋ ์ทจ์ฝ์ ์ ๋ณดํธํ๊ธฐ ์ํ ์ฌ๋ฌ ์กฐ์น๋ฅผ ํ ์ ์๋ ๊ฒ ๋ฟ์์ ์์ผ๋ฉด ์๋๋ค. ์ํธํ๊ณ ์ ํ์ ์ธ ํ๋กํ์ผ์ ์ ๊ณตํ๊ณ , ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ ํด๋ฌ์คํฐ๋ฅผ ์ฌ๋ฌ ์ธก๋ฉด์์ ๊ฐํํ๋ ๊ฒ์ด ์ค์ํ๋ค.
๋ชฉ์
- ๋ ธ๋์ ํ๋กํ์ผ์ ์ด๋ป๊ฒ ์ ์ฌํ๋์ง ์์๋ฅผ ๋ณธ๋ค.
- ํ๋์ ํ๋กํ์ผ์ ์ด๋ป๊ฒ ๊ฐ์ ์ ์ฉํ๋์ง ๋ฐฐ์ด๋ค.
- ํ๋กํ์ผ์ด ์ ์ฌ๋์๋์ง ํ์ธํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์ด๋ค.
- ํ๋กํ์ผ์ ์๋ฐํ๋ ๊ฒฝ์ฐ๋ฅผ ์ดํด๋ณธ๋ค.
- ํ๋กํ์ผ์ ์ ์ฌํ ์ ์์ ๊ฒฝ์ฐ๋ฅผ ์ดํด๋ณธ๋ค.
์์ํ๊ธฐ ์ ์
๋ค์์ ๋ณด์ฅํด์ผ ํ๋ค.
์ฟ ๋ฒ๋คํฐ์ค ๋ฒ์ ์ ์ต์ 1.4 ์ด๋ค. -- ์ฟ ๋ฒ๋คํฐ์ค v1.4๋ถํฐ AppArmor ์ง์์ ์ถ๊ฐํ๋ค. v1.4 ์ด์ ์ฟ ๋ฒ๋คํฐ์ค ์ปดํฌ๋ํธ๋ ์๋ก์ด AppArmor ์ด๋ ธํ ์ด์ ์ ์ธ์ํ์ง ๋ชปํ๊ณ ์ ๊ณต๋๋ AppArmor ์ค์ ์ ์กฐ์ฉํ ๋ฌด์ํ ๊ฒ์ด๋ค. ํ๋์์ ์์ํ๋ ๋ณดํธ๋ฅผ ๋ฐ๊ณ ์๋์ง ํ์ธํ๋ ค๋ฉด ํด๋น ๋ ธ๋์ Kubelet ๋ฒ์ ์ ํ์ธํ๋ ๊ฒ์ด ์ค์ํ๋ค.
$ kubectl get nodes -o=jsonpath=$'{range .items[*]}{@.metadata.name}: {@.status.nodeInfo.kubeletVersion}\n{end}'
gke-test-default-pool-239f5d02-gyn2: v1.4.0 gke-test-default-pool-239f5d02-x1kf: v1.4.0 gke-test-default-pool-239f5d02-xwux: v1.4.0
AppArmor ์ปค๋ ๋ชจ๋์ ์ฌ์ฉ ๊ฐ๋ฅํด์ผ ํ๋ค. -- ๋ฆฌ๋ ์ค ์ปค๋์ AppArmor ํ๋กํ์ผ์ ๊ฐ์ ์ ์ฉํ๊ธฐ ์ํด AppArmor ์ปค๋ ๋ชจ๋์ ๋ฐ๋์ ์ค์น๋์ด ์๊ณ ์ฌ์ฉ ๊ฐ๋ฅํด์ผ ํ๋ค. ์๋ฅผ ๋ค์ด Ubuntu ๋ฐ SUSE ๊ฐ์ ๋ฐฐํฌํ์ ๋ชจ๋์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ง์ํ๊ณ , ๊ทธ ์ธ ๋ง์ ๋ค๋ฅธ ๋ฐฐํฌํ๋ค์ ์ ํ์ ์ผ๋ก ์ง์ํ๋ค. ๋ชจ๋์ด ์ฌ์ฉ ๊ฐ๋ฅํ์ง ํ์ธํ๋ ค๋ฉด
/sys/module/apparmor/parameters/enabled
ํ์ผ์ ํ์ธํ๋ค.$ cat /sys/module/apparmor/parameters/enabled Y
Kubelet(>=v1.4)์ด AppArmor ๊ธฐ๋ฅ ์ง์์ ํฌํจํ์ง๋ง, ์ปค๋ ๋ชจ๋์ ์ฌ์ฉํ ์ ์์ผ๋ฉด ํ๋์์ AppArmor ์ต์ ์ ์คํํ๋ ๊ฒ์ด ๊ฑฐ๋ถ๋๋ค.
์ฐธ๊ณ :
์ฐ๋ถํฌ์๋ ์ถ๊ฐ์ ์ธ ํ (hook)์ด๋ ์ถ๊ฐ ๊ธฐ๋ฅ ํจ์น๋ฅผ ํฌํจํ ๋ฆฌ๋ ์ค ์ปค๋์ ์์ ์คํธ๋ฆผ์ ๋จธ์ง๋์ง ์์ ๋ง์ AppArmor ํจ์น๋ฅผ ๊ฐ์ง๊ณ ์๋ค. ์ฟ ๋ฒ๋คํฐ์ค๋ ์์ ์คํธ๋ฆผ ๋ฒ์ ์์ ํ ์คํธํ ํจ์น๋ง์ ๊ฐ์ง๊ณ ์์ด์ ๋ค๋ฅธ ๊ธฐ๋ฅ์ ์ง์์ ๋ณด์ฅํ์ง ์๋๋ค.์ปจํ ์ด๋ ๋ฐํ์์ด AppArmor์ ์ง์ํ๋ค. -- ํ์ฌ ๋ชจ๋ ์ผ๋ฐ์ ์ธ ์ฟ ๋ฒ๋คํฐ์ค๋ฅผ ์ง์ํ๋ ๋์ปค(Docker), CRI-O ๋๋ containerd ์ ๊ฐ์ ์ปจํ ์ด๋ ๋ฐํ์๋ค์ AppArmor๋ฅผ ์ง์ํด์ผ ํ๋ค. ์ด ๋ฐํ์ ์ค๋ช ์๋ฅผ ์ฐธ์กฐํด์ ํด๋ฌ์คํฐ๊ฐ AppArmor๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ์๊ตฌ ์ฌํญ์ ์ถฉ์กฑํ๋์ง ํ์ธํด์ผ ํ๋ค.
ํ๋กํ์ผ์ด ์ ์ฌ๋์ด ์๋ค. -- AppArmor๋ ๊ฐ ์ปจํ ์ด๋์ ํจ๊ป ์คํํด์ผ ํ๋ AppArmor ํ๋กํ์ผ์ ์ง์ ํ์ฌ ํ๋์ ์ ์ฉํ๋ค. ์ปค๋์ ์ง์ ํ ํ๋กํ์ผ์ด ์ ์ฌ๋์ง ์์๋ค๋ฉด, Kubelet(>= v1.4)์ ํ๋๋ฅผ ๊ฑฐ๋ถํ๋ค. ํด๋น ๋ ธ๋์ ์ด๋ค ํ๋กํ์ผ์ด ์ ์ฌ๋์๋์ง๋
/sys/kernel/security/apparmor/profiles
ํ์ผ์ ํตํด ํ์ธํ ์ ์๋ค. ์๋ฅผ ๋ค์ด,$ ssh gke-test-default-pool-239f5d02-gyn2 "sudo cat /sys/kernel/security/apparmor/profiles | sort"
apparmor-test-deny-write (enforce) apparmor-test-audit-write (enforce) docker-default (enforce) k8s-nginx (enforce)
๋ ธ๋์ ํ๋กํ์ผ์ ์ ์ฌํ๋ ๊ฒ์ ๋ํด ๋ ์์ธํ ๋ด์ฉ์ ํ๋กํ์ผ๊ณผ ํจ๊ป ๋ ธ๋ ์ค์ ํ๊ธฐ.
AppArmor ์ง์์ด ํฌํจ๋ Kubelet (>= v1.4)์ด๋ฉด ์ด๋ค ์ ์ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋์ง ์์ผ๋ฉด AppArmor์ ํจ๊ปํ ํ๋๋ฅผ ๊ฑฐ๋ถํ๋ค. ๋ ธ๋ ์์ AppArmor ์ง์ ์ฌ๋ถ๋ ๋ ธ๋ ์ค๋น ์กฐ๊ฑด ๋ฉ์์ง๋ฅผ ํ์ธํ์ฌ(์ดํ ๋ฆด๋ฆฌ์ค์์๋ ์ญ์ ๋ ๊ฒ ๊ฐ์ง๋ง) ๊ฒ์ฆํ ์ ์๋ค.
kubectl get nodes -o=jsonpath='{range .items[*]}{@.metadata.name}: {.status.conditions[?(@.reason=="KubeletReady")].message}{"\n"}{end}'
gke-test-default-pool-239f5d02-gyn2: kubelet is posting ready status. AppArmor enabled
gke-test-default-pool-239f5d02-x1kf: kubelet is posting ready status. AppArmor enabled
gke-test-default-pool-239f5d02-xwux: kubelet is posting ready status. AppArmor enabled
ํ๋ ๋ณด์ ๊ฐํํ๊ธฐ
์ฐธ๊ณ :
AppArmor๋ ํ์ฌ ๋ฒ ํ์ด๋ฉฐ, ์ด ๋๋ฌธ์ ์ต์ ์ ์ด๋ ธํ ์ด์ ํ์์ผ๋ก ์ง์ ํ๋ค. ์ผ๋ฐ ์ฌ์ฉ์ ๋ฒ์ ์ด ๋๋ฉด, ์ด๋ ธํ ์ด์ ์ ์ต์์ ์ข ๋ฅ์ ํ๋๋ก ๋์ฒด๋ ๊ฒ์ด๋ค(์์ธํ ๋ด์ฉ์ ์ผ๋ฐ ์ฌ์ฉ์ ๋ฒ์ ์ผ๋ก ์ ๊ทธ๋ ์ด๋ ๋ฐฉ๋ฒ ์ฐธ๊ณ )AppArmor ํ๋กํ์ผ์ ์ปจํ ์ด๋๋ง๋ค ์ง์ ๋๋ค. ํจ๊ป ์คํํ ํ๋ ์ปจํ ์ด๋์ AppArmor ํ๋กํ์ผ์ ์ง์ ํ๋ ค๋ฉด ํ๋์ ๋ฉํ๋ฐ์ดํฐ์ ์ด๋ ธํ ์ด์ ์ ์ถ๊ฐํ๋ค.
container.apparmor.security.beta.kubernetes.io/<container_name>: <profile_ref>
<container_name>
์ ํ๋กํ์ผ์ ์ ์ฉํ๋ ์ปจํ
์ด๋ ์ด๋ฆ์ด๊ณ , <profile_ref>
๋
์ ์ฉํ ํ๋กํ์ผ์ ์ง์ ํ๋ค. profile_ref
๋ ๋ค์ ์ค์ ํ๋์ด๋ค.
- ๋ฐํ์์ ๊ธฐ๋ณธ ํ๋กํ์ผ์ ์ ์ฉํ๊ธฐ ์ํ
runtime/default
<profile_name>
๋ก ์ด๋ฆํ ํธ์คํธ์ ์ ์ฌ๋๋ ํ๋กํ์ผ์ ์ ์ฉํ๊ธฐ ์ํlocalhost/<profile_name>
- ์ ์ฌํ ํ๋กํ์ผ์ด ์์์ ๋ํ๋ด๋
unconfined
์ด๋ ธํ ์ด์ ๊ณผ ํ๋กํ์ผ ์ด๋ฆ ํ์์ ์์ธํ ๋ด์ฉ์ API ์ฐธ์กฐ๋ฅผ ์ดํด๋ณธ๋ค.
์ฟ ๋ฒ๋คํฐ์ค AppArmor ์ ์๋ ์์๋ ๋ชจ๋ ์ ํ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋์๋์ง ํ์ธํ๊ณ , ์ ์ฉ์ ์ํด ์ ํํ ํ๋กํ์ผ์ ์ปจํ ์ด๋ ๋ฐํ์์ผ๋ก ์ ๋ฌํ์ฌ ์ด๋ฃจ์ด์ง๋ค. ๋ง์ฝ ์ ํ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋์ง ์์ผ๋ฉด ํ๋๋ ๊ฑฐ๋ถ๋๊ณ ์คํ๋์ง ์๋๋ค.
ํ๋กํ์ผ์ด ์ ์ฉ๋์๋์ง ํ์ธํ๊ธฐ ์ํด, ์ปจํ ์ด๋ ์์ฑ ์ด๋ฒคํธ์ ๋์ด๋ AppArmor ๋ณด์ ์ต์ ์ ์ฐพ์ ๋ณผ ์ ์๋ค.
kubectl get events | grep Created
22s 22s 1 hello-apparmor Pod spec.containers{hello} Normal Created {kubelet e2e-test-stclair-node-pool-31nt} Created container with docker id 269a53b202d3; Security:[seccomp=unconfined apparmor=k8s-apparmor-example-deny-write]
์ปจํ ์ด๋์ ๋ฃจํธ ํ๋ก์ธ์ค๊ฐ ์ฌ๋ฐ๋ฅธ ํ๋กํ์ผ๋ก ์คํ๋๋์ง๋ proc attr์ ํ์ธํ์ฌ ์ง์ ๊ฒ์ฆํ ์ ์๋ค.
kubectl exec <pod_name> -- cat /proc/1/attr/current
k8s-apparmor-example-deny-write (enforce)
์์
์ด ์์๋ AppArmor๋ฅผ ์ง์ํ๋ ํด๋ฌ์คํฐ๋ฅผ ์ด๋ฏธ ๊ตฌ์ฑํ์๋ค๊ณ ๊ฐ์ ํ๋ค.
๋จผ์ ๋ ธ๋์์ ์ฌ์ฉํ๋ ค๋ ํ๋กํ์ผ์ ์ ์ฌํด์ผ ํ๋ค. ์ฌ์ฉํ ํ๋กํ์ผ์ ํ์ผ ์ฐ๊ธฐ๋ฅผ ๊ฑฐ๋ถํ๋ค.
#include <tunables/global>
profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
#include <abstractions/base>
file,
# Deny all file writes.
deny /** w,
}
ํ๋๋ฅผ ์ธ์ ์ค์ผ์คํ ์ง ์์ง ๋ชปํ๋ฏ๋ก ๋ชจ๋ ๋ ธ๋์ ํ๋กํ์ผ์ ์ ์ฌํด์ผ ํ๋ค. ์ด ์์์์๋ SSH๋ฅผ ์ด์ฉํ์ฌ ํ๋กํ์ผ์ ์ค์นํ ๊ฒ์ด๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ํ๋กํ์ผ๊ณผ ํจ๊ป ๋ ธ๋ ์ค์ ํ๊ธฐ์์ ๋ ผ์ํ๋ค.
NODES=(
# The SSH-accessible domain names of your nodes
gke-test-default-pool-239f5d02-gyn2.us-central1-a.my-k8s
gke-test-default-pool-239f5d02-x1kf.us-central1-a.my-k8s
gke-test-default-pool-239f5d02-xwux.us-central1-a.my-k8s)
for NODE in ${NODES[*]}; do ssh $NODE 'sudo apparmor_parser -q <<EOF
#include <tunables/global>
profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
#include <abstractions/base>
file,
# Deny all file writes.
deny /** w,
}
EOF'
done
๋ค์์ผ๋ก ์ฐ๊ธฐ ๊ธ์ง ํ๋กํ์ผ๋ "Hello AppArmor" ํ๋๋ฅผ ์คํํ๋ค.
apiVersion: v1
kind: Pod
metadata:
name: hello-apparmor
annotations:
# ์ฟ ๋ฒ๋คํฐ์ค์ 'k8s-apparmor-example-deny-write' AppArmor ํ๋กํ์ผ์ ์ ์ฉํจ์ ์๋ฆฐ๋ค.
# ์์ง ๋ง ๊ฒ์ ์ฟ ๋ฒ๋คํฐ์ค ๋
ธ๋์์ ์คํ ์ค์ธ ๋ฒ์ ์ด 1.4 ์ด์์ด ์๋ ๊ฒฝ์ฐ์๋ ์ด ์ค์ ์ ๋ฌด์๋๋ค๋ ๊ฒ์ด๋ค.
container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-deny-write
spec:
containers:
- name: hello
image: busybox:1.28
command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]
kubectl create -f ./hello-apparmor.yaml
ํ๋ ์ด๋ฒคํธ๋ฅผ ์ดํด๋ณด๋ฉด, 'k8s-apparmor-example-deny-write' AppArmor ํ๋กํ์ผ๋ก ์์ฑ๋ ํ๋ ์ปจํ ์ด๋๋ฅผ ํ์ธํ ์ ์๋ค.
kubectl get events | grep hello-apparmor
14s 14s 1 hello-apparmor Pod Normal Scheduled {default-scheduler } Successfully assigned hello-apparmor to gke-test-default-pool-239f5d02-gyn2
14s 14s 1 hello-apparmor Pod spec.containers{hello} Normal Pulling {kubelet gke-test-default-pool-239f5d02-gyn2} pulling image "busybox"
13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Pulled {kubelet gke-test-default-pool-239f5d02-gyn2} Successfully pulled image "busybox"
13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Created {kubelet gke-test-default-pool-239f5d02-gyn2} Created container with docker id 06b6cd1c0989; Security:[seccomp=unconfined apparmor=k8s-apparmor-example-deny-write]
13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Started {kubelet gke-test-default-pool-239f5d02-gyn2} Started container with docker id 06b6cd1c0989
proc attr์ ํ์ธํ์ฌ ์ปจํ ์ด๋๊ฐ ์ค์ ๋ก ํด๋น ํ๋กํ์ผ๋ก ์คํ ์ค์ธ์ง ํ์ธํ ์ ์๋ค.
kubectl exec hello-apparmor -- cat /proc/1/attr/current
k8s-apparmor-example-deny-write (enforce)
๋ง์ง๋ง์ผ๋ก ํ์ผ ์ฐ๊ธฐ๋ฅผ ํตํด ํ๋กํ์ผ์ ์๋ฐํ๋ฉด ์ด๋ป๊ฒ ๋๋์ง ํ์ธํ ์ ์๋ค.
kubectl exec hello-apparmor -- touch /tmp/test
touch: /tmp/test: Permission denied
error: error executing remote command: command terminated with non-zero exit code: Error executing in Docker Container: 1
์ด์ ์ ๋ฆฌํ๋ฉด์, ์ ์ฌ๋์ง ์์ ํ๋กํ์ผ์ ์ง์ ํ๋ฉด ์ด๋ป๊ฒ ๋๋์ง ์ดํด๋ณธ๋ค.
kubectl create -f /dev/stdin <<EOF
apiVersion: v1
kind: Pod
metadata:
name: hello-apparmor-2
annotations:
container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-allow-write
spec:
containers:
- name: hello
image: busybox:1.28
command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]
EOF
pod/hello-apparmor-2 created
kubectl describe pod hello-apparmor-2
Name: hello-apparmor-2
Namespace: default
Node: gke-test-default-pool-239f5d02-x1kf/
Start Time: Tue, 30 Aug 2016 17:58:56 -0700
Labels: <none>
Annotations: container.apparmor.security.beta.kubernetes.io/hello=localhost/k8s-apparmor-example-allow-write
Status: Pending
Reason: AppArmor
Message: Pod Cannot enforce AppArmor: profile "k8s-apparmor-example-allow-write" is not loaded
IP:
Controllers: <none>
Containers:
hello:
Container ID:
Image: busybox
Image ID:
Port:
Command:
sh
-c
echo 'Hello AppArmor!' && sleep 1h
State: Waiting
Reason: Blocked
Ready: False
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-dnz7v (ro)
Conditions:
Type Status
Initialized True
Ready False
PodScheduled True
Volumes:
default-token-dnz7v:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-dnz7v
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: <none>
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
23s 23s 1 {default-scheduler } Normal Scheduled Successfully assigned hello-apparmor-2 to e2e-test-stclair-minion-group-t1f5
23s 23s 1 {kubelet e2e-test-stclair-node-pool-t1f5} Warning AppArmor Cannot enforce AppArmor: profile "k8s-apparmor-example-allow-write" is not loaded
ํ๋ ์ํ๋ Pending์ด๋ฉฐ, ์ค๋ฅ ๋ฉ์์ง๋ Pod Cannot enforce AppArmor: profile "k8s-apparmor-example-allow-write" is not loaded
์ด๋ค. ์ด๋ฒคํธ๋ ๋์ผํ ๋ฉ์์ง๋ก ๊ธฐ๋ก๋์๋ค.
๊ด๋ฆฌ
ํ๋กํ์ผ๊ณผ ํจ๊ป ๋ ธ๋ ์ค์ ํ๊ธฐ
ํ์ฌ ์ฟ ๋ฒ๋คํฐ์ค๋ AppArmor ํ๋กํ์ผ์ ๋ ธ๋์ ์ ์ฌํ๊ธฐ ์ํ ๋ค์ดํฐ๋ธ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํ์ง ์๋๋ค. ํ๋กํ์ผ์ ์ค์ ํ๋ ์ฌ๋ฌ ๋ฐฉ๋ฒ์ด ์๋ค. ์๋ฅผ ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
- ๊ฐ ๋ ธ๋์์ ํ๋๋ฅผ ์คํํ๋ ๋ฐ๋ชฌ์ ์ ํตํด์ ์ฌ๋ฐ๋ฅธ ํ๋กํ์ผ์ด ์ ์ฌ๋์๋์ง ํ์ธํ๋ค. ์์ ๊ตฌํ์ ์ฌ๊ธฐ์์ ์ฐพ์๋ณผ ์ ์๋ค.
- ๋ ธ๋ ์ด๊ธฐํ ์๊ฐ์ ๋ ธ๋ ์ด๊ธฐํ ์คํฌ๋ฆฝํธ(์๋ฅผ ๋ค์ด Salt, Ansible ๋ฑ)๋ ์ด๋ฏธ์ง๋ฅผ ์ด์ฉ
- ์์์์ ๋ณด์ฌ์ค ๊ฒ์ฒ๋ผ, ํ๋กํ์ผ์ ๊ฐ ๋ ธ๋์ ๋ณต์ฌํ๊ณ SSH๋ฅผ ํตํด ์ ์ฌํ๋ค.
์ค์ผ์ค๋ฌ๋ ์ด๋ค ํ๋กํ์ผ์ด ์ด๋ค ๋ ธ๋์ ์ ์ฌ๋๋์ง ๊ณ ๋ คํ์ง ์์ผ๋, ํ๋กํ์ผ ์ ์ฒด ์งํฉ์ด ๋ชจ๋ ๋ ธ๋์ ์ ์ฌ๋์ด์ผ ํ๋ค. ๋์์ ์ธ ๋ฐฉ๋ฒ์ ๊ฐ ํ๋กํ์ผ(ํน์ ํ๋กํ์ผ์ ํด๋์ค)์ ์ํ ๋ ธ๋ ๋ ์ด๋ธ์ ๋ ธ๋์ ์ถ๊ฐํ๊ณ , ๋ ธ๋ ์ ๋ ํฐ๋ฅผ ์ด์ฉํ์ฌ ํ๋๊ฐ ํ์ํ ํ๋กํ์ผ์ด ์๋ ๋ ธ๋์์ ์คํ๋๋๋ก ํ๋ค.
AppArmor ๋นํ์ฑํ
ํด๋ฌ์คํฐ์์ AppArmor๋ฅผ ์ฌ์ฉํ์ง ์์ผ๋ ค๋ฉด, ์ปค๋งจ๋๋ผ์ธ ํ๋๊ทธ๋ก ๋นํ์ฑํ ํ ์ ์๋ค.
--feature-gates=AppArmor=false
๋นํ์ฑํ๋๋ฉด, AppArmor ํ๋กํ์ผ์ ํฌํจํ ํ๋๋ "Forbidden" ์ค๋ฅ๋ก ๊ฒ์ฆ ์คํจํ๋ค.
์ฐธ๊ณ :
์ฟ ๋ฒ๋คํฐ์ค ๊ธฐ๋ฅ์ด ๋นํ์ฑํ๋์ด ์์ด๋, ๋ฐํ์์ด ๊ณ์ ๊ธฐ๋ณธ ํ๋กํ์ผ์ ๊ฐ์ ํ ์๋ ์๋ค. AppArmor๊ฐ general availability (GA) ์ํ๋ก ๋ฐ๋๋ฉด AppArmor ๊ธฐ๋ฅ์ ๋นํ์ฑํํ๋ ์ต์ ์ ์ ๊ฑฐ๋ ๊ฒ์ด๋ค.ํ๋กํ์ผ ์ ์
AppArmor ํ๋กํ์ผ์ ๋ง๋ค๊ณ ์ฌ๋ฐ๋ฅด๊ฒ ์ง์ ํ๋ ๊ฒ์ ๋งค์ฐ ๊น๋ค๋ก์ธ ์ ์๋ค. ๋คํํ ์ด ์์ ์ ๋์ ๋๋ ๋๊ตฌ๊ฐ ์๋ค.
aa-genprof
์aa-logprof
๋ ์ ํ๋ฆฌ์ผ์ด์ ํ๋๊ณผ ๋ก๊ทธ์ ์ํ์ ํ์ํ ํ๋์ ๋ชจ๋ํฐ๋งํ์ฌ ์ผ๋ฐ ํ๋กํ์ผ ๊ท์น์ ์์ฑํ๋ค. ์์ธํ ์ฌ์ฉ๋ฐฉ๋ฒ์ AppArmor ๋ฌธ์์์ ์ ๊ณตํ๋ค.- bane์ ๋จ์ํ๋ ํ๋กํ์ผ ์ธ์ด๋ฅผ ์ด์ฉํ๋ ๋์ปค๋ฅผ ์ํ AppArmor ํ๋กํ์ผ ์์ฑ๊ธฐ์ด๋ค.
AppArmor ๋ฌธ์ ๋ฅผ ๋๋ฒ๊น
ํ๊ธฐ ์ํด์ ๊ฑฐ๋ถ๋ ๊ฒ์ผ๋ก ๋ณด์ด๋ ์์คํ
๋ก๊ทธ๋ฅผ ํ์ธํ ์ ์๋ค.
AppArmor ๋ก๊ทธ๋ dmesg
์์ ๋ณด์ด๋ฉฐ, ์ค๋ฅ๋ ๋ณดํต ์์คํ
๋ก๊ทธ๋
journalctl
์์ ๋ณผ ์ ์๋ค. ๋ ๋ง์ ์ ๋ณด๋
AppArmor ์คํจ์์ ์ ๊ณตํ๋ค.
API ์ฐธ์กฐ
ํ๋ ์ด๋ ธํ ์ด์
์ปจํ ์ด๋๋ฅผ ์คํํ ํ๋กํ์ผ์ ์ง์ ํ๋ค.
- ํค:
container.apparmor.security.beta.kubernetes.io/<container_name>
<container_name>
๋ ํ๋ ๋ด์ ์ปจํ ์ด๋ ์ด๋ฆ๊ณผ ์ผ์นํ๋ค. ๋ถ๋ฆฌ๋ ํ๋กํ์ผ์ ํ๋ ๋ด์ ๊ฐ ์ปจํ ์ด๋๋ก ์ง์ ํ ์ ์๋ค. - ๊ฐ: ์๋ ๊ธฐ์ ๋ ํ๋กํ์ผ ์ฐธ์กฐ
ํ๋กํ์ผ ์ฐธ์กฐ
runtime/default
: ๊ธฐ๋ณธ ๋ฐํ์ ํ๋กํ์ผ์ ์ฐธ์กฐํ๋ค.- (๊ธฐ๋ณธ ํ๋์ํ๋ฆฌํฐํด๋ฆฌ์ ์์ด) ํ๋กํ์ผ์ ์ง์ ํ์ง ์๊ณ AppArmor๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๋๋ฑํ๋ค.
- ์ค์ ๋ก๋, ๋ง์ ์ปจํ ์ด๋ ๋ฐํ์์ ๋์ผํ OCI ๊ธฐ๋ณธ ํ๋กํ์ผ์ ์ฌ์ฉํ๋ฉฐ, ์ด๋ https://github.com/containers/common/blob/main/pkg/apparmor/apparmor_linux_template.go ์ ์ ์๋์ด ์๋ค.
localhost/<profile_name>
: ๋ ธ๋(localhost)์ ์ ์ฌ๋ ํ๋กํ์ผ์ ์ด๋ฆ์ผ๋ก ์ฐธ์กฐํ๋ค.- ๊ฐ์ฉํ ํ๋กํ์ผ ์ด๋ฆ์ ์์ธ ๋ด์ฉ์ ํต์ฌ ์ ์ฑ ์ฐธ์กฐ์ ์ค๋ช ๋์ด ์๋ค.
unconfined
: ์ด๊ฒ์ ์ปจํ ์ด๋์์ AppArmor๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๋นํ์ฑ์ํจ๋ค.
๋ค๋ฅธ ์ด๋ค ํ๋กํ์ผ ์ฐธ์กฐ ํ์๋ ์ ํจํ์ง ์๋ค.
๋ค์ ๋ด์ฉ
์ฐธ๊ณ ์๋ฃ