각 pod는 고유한 네트워크 네임스페이스를 사용하기 때문에 각각의 ip와 port를 갖고, 자체 pid 네임스페이스를 가지고 고유한 IPC 네임스페이스도 사용하므로 동일한 파드의 프로세스간 통신 매커니즘(IPC, Inter-Process Communication)으로 서로 통신할 수 있다.
apiVersion: v1
kind: Pod
metadata:
name: pod-with-host-network
spec:
hostNetwork: true # 노드의 네트워크 인터페이스 사용
containers:
- name: main
image: alpine
command: ["/bin/sleep", "999999"]
$ kubectl create -f host-network.yaml
$ kubectl exec pod-with-host-network ifconfig
docker0 Link encap:Ethernet HWaddr 02:42:14:08:23:47
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
...
eth0 Link encap:Ethernet HWaddr 08:00:27:F8:FA:4E
inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.0
...
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
...
veth1178d4f Link encap:Ethernet HWaddr 1E:03:8D:D6:E1:2C
inet6 addr: fe80::1c03:8dff:fed6:e12c/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
...
apiVersion: v1
kind: Pod
metadata:
name: kubia-hostport
spec:
containers:
- image: luksa/kubia
name: kubia
ports:
- containerPort: 8080 # pod의 ip의 port
hostPort: 9000 # node의 port
protocol: TCP
apiVersion: v1
kind: Pod
metadata:
name: pod-with-host-pid-and-ipc
spec:
hostPID: true
hostIPC: true
containers:
- name: main
image: alpine
command: ["/bin/sleep", "999999"]
$ kubectl create -f host-pid-and-ipc.yaml
$ kubectl exec pod-with-host-pid-and-ipc ps aux
PID USER TIME COMMAND
1 root 0:01 /usr/lib/systemd/systemd --switched-root --system ...
2 root 0:00 [kthreadd]
3 root 0:00 [ksoftirqd/0]
5 root 0:00 [kworker/0:0H]
6 root 0:00 [kworker/u2:0]
7 root 0:00 [migration/0]
8 root 0:00 [rcu_bh]
9 root 0:00 [rcu_sched]
10 root 0:00 [watchdog/0]
...
SECURITY CONTEXT는 무엇을 할 수 있나?
SECURITY CONTEXT 사용x
$ kubectl run pod-with-defaults --image alpine --restart Never -- /bin/sleep 999999
$ kubectl exec pod-with-defaults id
uid=0(root) gid=0(root) groups=0(root), 1(bin), 2(daemon), 3(sys), 4(adm), 6(disk), 10(wheel), 11(floppy), 20(dialout), 26(tape), 27(video)
➕ Dockerfile의 USER로도 설정 가능
apiVersion: v1
kind: Pod
metadata:
name: pod-as-user-guest
spec:
containers:
- name: main
image: alpine
command: ["/bin/sleep", "999999"]
securityContext:
runAsUser: 405 # userID를 405로 지정
$ kubectl create -f user-guest.yaml
$ kubectl exec pod-as-user-guest id
uid=405(guest) gid=100(users)
apiVersion: v1
kind: Pod
metadata:
name: pod-run-as-non-root
spec:
containers:
- name: main
image: alpine
command: ["/bin/sleep", "999999"]
securityContext:
runAsNonRoot: true # root가 아닌 사용자로 컨테이너 실행
특권 모드의 컨테이너는 모든 호스트 노드의 디바이스를 자유롭게 보고 사용할 수 있다.
apiVersion: v1
kind: Pod
metadata:
name: pod-privileged
spec:
containers:
- name: main
image: alpine
command: ["/bin/sleep", "999999"]
securityContext:
privileged: true # privileged mode로 컨테이너 실행
$ kubectl exec -it pod-with-defaults -- date +%T -s "12:00:00"
date: can't set date: Operation not permitted
apiVersion: v1
kind: Pod
metadata:
name: pod-add-settime-capability
spec:
containers:
- name: main
image: alpine
command: ["/bin/sleep", "999999"]
securityContext:
capabilities:
add: # capability 추가
- SYS_TIME
$ kubectl exec -it pod-add-settime-capability -- date +%T -s "12:00:00"
12:00:00
$ kubectl exec -it pod-add-settime-capability -- date
Sun May 7 12:00:03 UTC 2017
➕ Linux man 페이지에서 Linux 커널 목록 확인
apiVersion: v1
kind: Pod
metadata:
name: pod-drop-settime-capability
spec:
containers:
- name: main
image: alpine
command: ["/bin/sleep", "999999"]
securityContext:
capabilities:
drop: # capability 제거
- CHOWN
apiVersion: v1
kind: Pod
metadata:
name: pod-with-readonly-filesystem
spec:
containers:
- name: main
image: alpine
command: ["/bin/sleep", "999999"]
securityContext:
readOnlyRootFilesystem: true # write 방지
volumeMounts:
- name: my-volume
mountPath: /volume # 볼륨에는 write 가능
readOnly: false
volumes:
- name: my-volume
emptyDir:
➕ pod.spec에서 securityContext속성을 설정하면 pod 수준에서 설정 가능
apiVersion: v1
kind: Pod
metadata:
name: pod-with-shared-volume-fsgroup
spec:
securityContext:
fsGroup: 555 # 볼륨 소유 그룹
supplementalGroups: [666, 777] # 추가 그룹
containers:
- name: first
image: alpine
command: ["/bin/sleep", "999999"]
securityContext:
runAsUser: 1111 # 1번 유저
volumeMounts:
- name: shared-volume
mountPath: /volume
readOnly: false
- name: second
image: alpine
command: ["/bin/sleep", "999999"]
securityContext:
runAsUser: 2222 # 2번 유저
volumeMounts:
- name: shared-volume
mountPath: /volume
readOnly: false
volumes: # 같은 볼륨을 공유
- name: shared-volume
emptyDir:
$ kubectl create -f shared-volume-fsgroup.yaml
# 실행 및 id 확인
$ kubectl exec -it pod-with-shared-volume-fsgroup -c first sh
/ $ id
uid=1111 gid=0(root) groups=555,666,777
# 볼륨 소유 그룹 확인
/ $ ls -l / | grep volume
drwxrwsrwx 2 root 555 ...
/ $ echo foo > /volume/foo
/ $ ls -l /volume
total 4
-rw-r--r-- 1 1111 555 ...
# 파일시스템에서 파일 소유자는?
/ $ echo foo > /tmp/foo
/ $ ls -l /tmp
total 4
-rw-r--r-- 1 1111 root ...
pod에서 사용하거나 못할 보안 관련 기능을 정의하는 클러스터 수준 리소스. API 서버에서 실행되는 PodSecurityPolicy admission control plugin이 PodSecurityPolicy로 pod 정의를 확인.
Minikube에서는 PodSecurityPolicy plugin이 비활성화 되어있는 것이 기본
PodSecurityPolicy 기능
사용
apiVersion: extensions/v1beta1
kind: PodSecurityPolicy
metadata:
name: default
spec:
hostIPC: false # host의 IPC, PID, network namespace 사용 불가
hostPID: false
hostNetwork: false
hostPorts: # 바인드 가능한 host port
- min: 10000
max: 11000
- min: 13000
max: 14000
privileged: false # privilieged mode에서 실행 불가
readOnlyRootFilesystem: true # read-only root filesystem
runAsUser: # 모든 user와 group으로 실행 가능
rule: RunAsAny
fsGroup:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
seLinux: # 모든 SELinux 그룹도 사용 가능
rule: RunAsAny
volumes: # 모든 볼륨 타입 사용 가능
- '*'
# PodSecurityPolicy 생성
kubectl create -f pod-security-policy.yaml
# PodSecurityPolicy 조회
kubectl get psp
runAsUser:
rule: MustRunAs
ranges: # 하나만 허용
- min: 2
max: 2
fsGroup:
rule: MustRunAs
ranges: # 범위로 허용
- min: 2
max: 10
- min: 20
max: 30
supplementalGroups:
rule: MustRunAs
ranges:
- min: 2
max: 10
- min: 20
max: 30
FROM node:7
ADD app.js /app.js
USER 5
ENTRYPOINT ["node", "app.js"]
# 생성 시 API서버가 거부하지 않음
$ kubectl run run-as-5 --image luksa/kubia-run-as-user-5 --restart Never
pod "run-as-5" created
# ID 확인 (PodSecurityPolicy에 정의된 대로 설정)
$ kubectl exec run-as-5 -- id
uid=2(bin) gid=2(bin) groups=2(bin)
apiVersion: extensions/v1beta1
kind: PodSecurityPolicy
spec:
allowedCapabilities:
- SYS_TIME
defaultAddCapabilities:
- CHOWN
requiredDropCapabilities:
- SYS_ADMIN
- SYS_MODULE
...
allowedCapabilities
securityContext.capabilities 필드에 추가할 수 있는 기능 정의. PodSecurityPolicy admission control plugin이 활성화된 경우에는 적혀있지 않은 기능은 추가할 수 없다.
defaultAddCapabilities
배포되는 모든 pod의 컨테이너에 추가할 기능 정의
requiredDropCapabilities
모든 컨테이너에서 기능 삭제. 기능을 포함한 pod를 생성하면 거부된다.
kind: PodSecurityPolicy
spec:
volumes:
- emptyDir
- configMap
- secret
- downwardAPI
- persistentVolumeClaim
PodSecurityPolicy는 클러스터 수준의 리소스라 특정 네임스페이스에만 적용시킬 수 없다. 각각의 user 및 group에 다른 PodSecurityPolicies를 할당하기 위한 방법.
apiVersion: extensions/v1beta1
kind: PodSecurityPolicy
metadata:
name: privileged # 정책 이름
spec:
privileged: true # privileged container 허용
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
seLinux:
rule: RunAsAny
volumes:
- '*'
# psp 생성
kubectl create -f psp-privileged.yaml
# psp 확인
$ kubectl get psp
NAME PRIV CAPS SELINUX RUNASUSER FSGROUP ...
default false [] RunAsAny RunAsAny RunAsAny ...
privileged true [] RunAsAny RunAsAny RunAsAny ...
# 기본 클러스터 생성
$ kubectl create clusterrole psp-default --verb=use --resource=podsecuritypolicies --resource-name=default
# 특권모드 클러스터 생성
$ kubectl create clusterrole psp-privileged --verb=use --resource=podsecuritypolicies --resource-name=privileged
# 인증된 사용자에게 default ClusterRole 바인딩
$ kubectl create clusterrolebinding psp-all-users --clusterrole=psp-default --group=system:authenticated
# bob 사용자에게 privileged ClusterRole 바인딩
$ kubectl create clusterrolebinding psp-bob --clusterrole=psp-privileged --user=bob
# 유저 생성
$ kubectl config set-credentials alice --username=alice --password=password
$ kubectl config set-credentials bob --username=bob --password=password
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: # 빈 파드 셀렉터는 네임스페이스에 있는 모든 pod에 매칭된다.
해당 네임스페이스의 pod들에 다른 네임스페이스에서 연결 불가
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: postgres-netpolicy
spec:
podSelector: # 액세스 될 pod
matchLabels:
app: database
ingress:
- from: # 여기서 오는 연결만 허용
- podSelector:
matchLabels:
app: webserver
ports:
- port: 5432
클라이언트 pod가 서비스를 통해서 접근할 때도 적용된다.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: shoppingcart-netpolicy
spec:
podSelector: # 마이크로 서비스를 위한 label
matchLabels:
app: shopping-cart
ingress:
- from:
- namespaceSelector: # 해당 테넌트의 pod에서만 접근 가능
matchLabels:
tenant: manning
ports:
- port: 80
ingress:
- from:
- ipBlock:
cidr: 192.168.1.0/24 # 해당 IP 블록에서만 허용
spec:
podSelector:
matchLabels:
app: webserver
egress: # outbound 트래픽 제한
- to:
- podSelector:
matchLabels:
app: database