실습

Security Context

  1. Pod 생성

    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
    EOF
  2. 컨테이너에서 프로세스를 실행중인 유저 확인

    kubectl exec nginx -- id 
  3. 프로세스 유틸리티 설치

    kubectl exec nginx -- bash -c "apt update && apt install -y procps"
  4. 실행중인 프로세스 확인

    kubectl exec nginx -- ps aux
  5. nginx 유저 확인

    kubectl exec nginx -- id nginx
  6. Pod 재생성

    cat <<EOF | kubectl replace --force -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:
      securityContext:
        runAsNonRoot: true
      containers:
      - image: nginx
        name: nginx
    EOF
  7. Pod가 생성되었는지 확인

    kubectl get pod nginx
  8. Pod에 명시된 컨테이너가 실행 되지 않는다면 그 이유를 확인

    kubectl describe pod nginx
  9. Pod 재생성

    cat <<EOF | kubectl replace --force -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 101
      containers:
      - image: nginx
        name: nginx
    EOF
  10. Pod가 생성되었는지 확인

    kubectl get pod nginx
  11. Pod에 명시된 컨테이너가 실행 되지 않는다면 그 이유를 확인

    kubectl describe pod nginx
  12. Pod 로그 확인

    kubectl logs nginx
  13. NGINX 설정 파일 확인

    kubectl run nginx-tmp --image=nginx --rm -it --restart=Never \
    -- cat /etc/nginx/nginx.conf
  14. Pod 재생성

    cat <<EOF | kubectl replace --force -f -
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: nginx
    data:
      nginx.conf: |
        
        worker_processes  auto;
        
        error_log  /var/log/nginx/error.log notice;
        pid        /var/run/nginx.pid;
        
        
        events {
            worker_connections  1024;
        }
        
        
        http {
            include       /etc/nginx/mime.types;
            default_type  application/octet-stream;
        
            log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                              '$status $body_bytes_sent "$http_referer" '
                              '"$http_user_agent" "$http_x_forwarded_for"';
        
            access_log  /var/log/nginx/access.log  main;
        
            sendfile        on;
            #tcp_nopush     on;
        
            keepalive_timeout  65;
        
            #gzip  on;
        
            include /etc/nginx/conf.d/*.conf;
        }
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 101
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-conf
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
      volumes:
      - name: nginx-conf
        configMap:
          name: nginx
          items:
          - key: nginx.conf
            path: nginx.conf
    EOF
  15. Pod가 생성되었는지 확인

    kubectl get pod nginx
  16. Pod에 명시된 컨테이너가 실행 되지 않는다면 그 이유를 확인

    kubectl describe pod nginx
  17. Pod 로그 확인

    kubectl logs nginx
  18. 아래의 Dockerfile로 새로운 컨테이너 이미지 생성

    FROM nginx
    WORKDIR /app
    RUN chown -R nginx:nginx /app && chmod -R 755 /app && \
            chown -R nginx:nginx /var/cache/nginx && \
            chown -R nginx:nginx /var/log/nginx && \
            chown -R nginx:nginx /etc/nginx/conf.d
    RUN touch /var/run/nginx.pid && \
            chown -R nginx:nginx /var/run/nginx.pid
    USER nginx
    CMD ["nginx", "-g", "daemon off;"]
  19. Pod 재생성

    cat <<EOF | kubectl replace --force -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 101
      containers:
      - image: youngwjung/nginx-nonroot
        name: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-conf
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
      volumes:
      - name: nginx-conf
        configMap:
          name: nginx
          items:
          - key: nginx.conf
            path: nginx.conf
    EOF
  20. Pod 상태 확인

    kubectl get pod nginx
  21. Pod 로그 확인

    kubectl logs nginx
  22. Pod 재생성

    cat <<EOF | kubectl replace --force -f -
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: nginx
    data:
      nginx.conf: |
        
        worker_processes  auto;
        
        error_log  /var/log/nginx/error.log notice;
        pid        /var/run/nginx.pid;
        
        
        events {
            worker_connections  1024;
        }
        
        
        http {
            include       /etc/nginx/mime.types;
            default_type  application/octet-stream;
        
            log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                              '$status $body_bytes_sent "$http_referer" '
                              '"$http_user_agent" "$http_x_forwarded_for"';
        
            access_log  /var/log/nginx/access.log  main;
        
            sendfile        on;
            #tcp_nopush     on;
        
            keepalive_timeout  65;
        
            #gzip  on;
            
            server {
                listen       8080;
                server_name  localhost;
                location / {
                    root   /usr/share/nginx/html;
                    index  index.html index.htm;
                }
            }
        }
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 101
      containers:
      - image: youngwjung/nginx-nonroot
        name: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-conf
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
      volumes:
      - name: nginx-conf
        configMap:
          name: nginx
          items:
          - key: nginx.conf
            path: nginx.conf
    EOF
  23. Pod 상태 확인

    kubectl get pod nginx
  24. 컨테이너가 정상적으로 실행중인지 확인

    kubectl exec nginx -- curl -s localhost:8080
  25. 새로운 Pod 생성

    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: ubuntu
    spec:
      securityContext:dddd
        runAsNonRoot: true
        runAsUser: 101
      containers:
      - image: ubuntu
        name: ubuntu
        command: ["sleep", "3600"]
    EOF
  26. 컨테이너에서 프로세스를 실행중인 유저 확인

    kubectl exec ubuntu -- id 
  27. 실행중인 프로세스 확인

    kubectl exec ubuntu -- ps aux
  28. NGINX 설치 시도

    kubectl exec ubuntu -- bash -c "apt update && apt install -y nginx"
  29. Pod 재생성

    cat <<EOF | kubectl replace --force -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: ubuntu
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 101
      containers:
      - image: ubuntu
        name: ubuntu
        command: ["sleep", "3600"]
        securityContext:
          runAsUser: 0
    EOF
  30. Pod가 정상적으로 생성되었는지 확인

    kubectl get pod ubuntu
  31. Pod에 명시된 컨테이너가 실행되지 않는다면 그 이유를 확인

    kubectl describe pod ubuntu
  32. Pod 재생성

    cat <<EOF | kubectl replace --force -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: ubuntu
    spec:
      securityContext:
        runAsUser: 101
      containers:
      - image: ubuntu
        name: ubuntu
        command: ["sleep", "3600"]
        securityContext:
          runAsUser: 0
    EOF
  33. 컨테이너에서 프로세스를 실행중인 유저 확인

    kubectl exec ubuntu -- id 
  34. 새로운 Pod 생성

    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: alpine
    spec:
      containers:
      - image: alpine
        name: alpine
        command: ["sleep", "3600"]
        volumeMounts:
        - name: dev
          mountPath: /mnt/dev
      volumes:
      - name: dev
        hostPath:
          path: /dev
    EOF
  35. 생성된 컨테이너를 통해 호스트의 디스크 디바이스 접근 시도

    kubectl exec alpine -- head /mnt/dev/xvda
  36. 컨테이너에서 프로세스를 실행중인 유저 확인

    kubectl exec ubuntu -- id 
  37. Pod 재생성

    cat <<EOF | kubectl replace --force -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: alpine
    spec:
      containers:
      - image: alpine
        name: alpine
        command: ["sleep", "3600"]
        volumeMounts:
        - name: dev
          mountPath: /mnt/dev
        securityContext:
          privileged: true
      volumes:
      - name: dev
        hostPath:
          path: /dev
    EOF
  38. 생성된 컨테이너를 통해 호스트의 디스크 디바이스 접근 시도

    kubectl exec alpine -- head /mnt/dev/xvda
  39. 리소스 삭제

    {
        kubectl delete pod ubuntu alpine nginx
        kubectl delete cm nginx
    }

Seccomp

  1. Pod 생성

    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: ubuntu
    spec:
      containers:
      - image: ubuntu
        name: ubuntu
        command: ["sleep", "3600"]
    EOF
  2. 새로운 리눅스 네임스페이스를 만드는 명령어 실행

    kubectl exec -it ubuntu -- unshare
  3. Pod 생성

    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: ubuntu
    spec:
      securityContext:
        seccompProfile:
          type: RuntimeDefault
      containers:
      - image: ubuntu
        name: ubuntu
        command: ["sleep", "3600"]
    EOF

Network Policy

  1. Tigera Calico Operator 설치

    {
        helm repo add projectcalico https://docs.projectcalico.org/charts
        helm repo update
        helm install calico projectcalico/tigera-operator --version v3.21.4
    }
  2. Calico Operator 설치 확인

    kubectl get all -n tigera-operator
  3. Calico CNI 설치 확인

    kubectl get all -n calico-system
  4. 모든 Calico 구성 요소들이 정상 동작중인지 확인 - 에러메시지가 없으면 정상으로 판단

    {
        kubectl logs deploy/tigera-operator -n tigera-operator | grep ERROR
        kubectl logs ds/calico-node -n calico-system | grep ERROR
        kubectl logs deploy/calico-typha -n calico-system | grep ERROR
    }
  5. 리소스 생성

    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Namespace
    metadata:
      name: red
      labels:
        env: red
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: client
      namespace: red
      labels:
        role: client
    spec:
      containers:
      - image: curlimages/curl
        name: client
        command: ["sleep", "3600"]
    ---
    apiVersion: v1
    kind: Namespace
    metadata:
      name: blue
      labels:
        env: blue
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: client
      namespace: blue
      labels:
        role: client
    spec:
      containers:
      - image: curlimages/curl
        name: client
        command: ["sleep", "3600"]
    ---
    apiVersion: v1
    kind: Namespace
    metadata:
      name: web
      labels:
        env: web
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: server
      namespace: web
      labels:
        role: server
    spec:
      containers:
      - image: httpd
        name: httpd
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: client
      namespace: web
      labels:
        role: client
    spec:
      containers:
      - image: curlimages/curl
        name: client
        command: ["sleep", "3600"]
    EOF
  6. web Namespace에 있는 server Pod의 IP 주소 확인

    kubectl get pod server -o wide -n web
  7. red Namespace에 있는 client Pod에서 web Namespace에 있는 server Pod 호출

    kubectl -n red exec client -- \
    curl -s $(kubectl get pod server -n web -o=jsonpath='{.status.podIP}')
  8. redblue Namespace에 Network Policy 생성

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: default-deny-egress
      namespace: red
    spec:
      podSelector: {}
      policyTypes:
      - Egress
    ---
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: default-deny-egress
      namespace: blue
    spec:
      podSelector: {}
      policyTypes:
      - Egress
    EOF
  9. red Namespace에 있는 client Pod에서 web Namespace에 있는 server Pod 호출 - timeout을 1초로 설정

    kubectl -n red exec client -- \
    curl -m 1 -s $(kubectl get pod server -n web -o=jsonpath='{.status.podIP}')
  10. red Namespace에 새로운 Network Policy 생성

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: allow-egress-server
      namespace: red
    spec:
      podSelector:
        matchLabels:
          role: client
      policyTypes:
      - Egress
      egress:
      - to:
        - ipBlock:
            cidr: $(kubectl get pod server -n web -o=jsonpath='{.status.podIP}')/32
        ports:
        - protocol: TCP
          port: 80
    EOF
  11. 위에서 생성한 Network Policy 확인

    kubectl -n red describe networkpolicy allow-egress-server
  12. red Namespace에 있는 client Pod에서 web Namespace에 있는 server Pod 호출 - timeout을 1초로 설정

    kubectl -n red exec client -- \
    curl -m 1 -s $(kubectl get pod server -n web -o=jsonpath='{.status.podIP}')
  13. blue Namespace에 있는 client Pod에서 web Namespace에 있는 server Pod 호출 - timeout을 1초로 설정

    kubectl -n blue exec client -- \
    curl -m 1 -s $(kubectl get pod server -n web -o=jsonpath='{.status.podIP}')
  14. blue Namespace에 새로운 Network Policy 생성

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: allow-egress-server
      namespace: blue
    spec:
      podSelector:
        matchLabels:
          role: client
      policyTypes:
      - Egress
      egress:
      - to:
        - podSelector:
            matchLabels:
              role: server
        ports:
        - protocol: TCP
          port: 80
    EOF
  15. 위에서 생성한 Network Policy 확인

    kubectl -n blue describe networkpolicy allow-egress-server
  16. blue Namespace에 있는 client Pod에서 web Namespace에 있는 server Pod 호출 - timeout을 1초로 설정

    kubectl -n blue exec client -- \
    curl -m 1 -s $(kubectl get pod server -n web -o=jsonpath='{.status.podIP}')
  17. 위에서 생성한 Network Policy 수정

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: allow-egress-server
      namespace: blue
    spec:
      podSelector:
        matchLabels:
          role: client
      policyTypes:
      - Egress
      egress:
      - to:
        - namespaceSelector:
            matchLabels:
              env: web
        ports:
        - protocol: TCP
          port: 80
    EOF
  18. 위에서 수정한 Network Policy 확인

    kubectl -n blue describe networkpolicy allow-egress-server
  19. blue Namespace에 있는 client Pod에서 web Namespace에 있는 server Pod 호출 - timeout을 1초로 설정

    kubectl -n blue exec client -- \
    curl -m 1 -s $(kubectl get pod server -n web -o=jsonpath='{.status.podIP}')
  20. web Namespace에 Network Policy 생성

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: default-deny-all
      namespace: web
    spec:
      podSelector: {}
      policyTypes:
      - Ingress
      - Egress
    EOF
  21. blue Namespace에 있는 client Pod에서 web Namespace에 있는 server Pod 호출 - timeout을 1초로 설정

    kubectl -n blue exec client -- \
    curl -m 1 -s $(kubectl get pod server -n web -o=jsonpath='{.status.podIP}')
  22. web Namespace에 새로운 Network Policy 생성 - Egress 정책

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: allow-all-egress
      namespace: web
    spec:
      podSelector: {}
      policyTypes:
      - Egress
      egress:
      - {}
    EOF
  23. web Namespace에 새로운 Network Policy 생성 - Ingress 정책

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: allow-ingress-blue-client
      namespace: web
    spec:
      podSelector:
        matchLabels:
          role: server
      policyTypes:
      - Ingress
      ingress:
      - from:
        - namespaceSelector:
            matchLabels:
              env: blue
          podSelector:
            matchLabels:
              role: client
    EOF
  24. blue Namespace에 있는 client Pod에서 web Namespace에 있는 server Pod 호출 - timeout을 1초로 설정

    kubectl -n blue exec client -- \
    curl -m 1 -s $(kubectl get pod server -n web -o=jsonpath='{.status.podIP}')
  25. blue Namespace에 새로운 Pod를 생성

    kubectl -n blue run nginx --image=nginx
  26. 위에서 생성한 Pod에서 web Namespace에 있는 server Pod 호출 - timeout을 1초로 설정

    kubectl -n blue exec nginx -- \
    curl -m 1 -s $(kubectl get pod server -n web -o=jsonpath='{.status.podIP}')
  27. 리소스 삭제

    kubectl delete ns red blue web
  28. Calico 삭제

    helm uninstall calico
  29. Calico가 삭제되었는지 확인

    kubectl get ns tigera-operator calico-system
  30. 한개의 Node로 Session Manager 연결

    aws ssm start-session --target \
    $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+")
  31. Calico CNI가 생성한 iptable 규칙들이 남아 있는지 확인

    sudo iptables-save | grep -i cali
  32. Session Manager 종료

    exit
  33. 모든 Node 삭제 - 관리형 노드그룹에 의해서 새로운 Node가 자동으로 생성됨

    aws ec2 terminate-instances --instance-ids \
    $(kubectl get node -o jsonpath='{.items[*].spec.providerID}' | grep -oE "i-[a-z0-9]+" | column)
  34. Node를 새로 생성할수 없는 경우에는 해당 문서를 참고 - https://github.com/projectcalico/calico/blob/master/calico/hack/remove-calico-policy/remove-policy.md

  35. 새로운 Node가 생성되었는지 확인

    kubectl get node
  36. 한개의 Node로 Session Manager 연결

    aws ssm start-session --target \
    $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+")
  37. Calico CNI가 생성한 iptable 규칙들이 남아 있는지 확인

    sudo iptables-save | grep -i cali
  38. Session Manager 종료

    exit

Last updated