새소식

Recent Study/udemy - CKA with Practice Tests

Section 7 : Security

  • -

클러스터 자체를 형성하는 호스트부터 시작해보자. 이런 호스트에 대한 모든 접근은 보안되어야 하고, 비밀번호 기반의 인증은 사용하지 않게 하며, SSH 키 기반의 인증만 가능하다.

 

kubectl 명령어나 APU에 직접 접근할 때 모든 사용자의 접근은 kube-apiserver 상호작용하며 관리됩니다. 이 모든 요청은 kube-apiserver로 가게 되는데, kube-apiserver는 요청을 처리하기 전에 Authenticate(인증) 합니다. 이것을 통해 kube-apiserver 자체의 접근을 제어하는 것이고, 이때 사용되는 다양한 메커니즘이 있습니다.

 

1) 누가 클러스터에 접근할 수 있는가? (인증 메커니즘)

2) 그것이 무엇을 할 수 있는가? (인가 메커니즘)

 

클러스터 구성 요소간의 모든 통신은 kubelet과 kube-proxy와 같이 Worker 노드에서 실행되는 것은 TLS 암호화로 보안이 진행된다.

인증 메커니즘은 고정 암호 파일, 고정 토큰 파일, 인증서, 타사 인증 프로토콜 등이 있다.

 

 

1. TLS Certificates for Cluster Components

 

인증서는 거래 도중 상호 신뢰를 보장하기 위해 사용됩니다. 사용자가 웹 서버에 접근할 때 TLS 인증서사용자와 서버의 통신이 암호화되도록 합니다.

 

대칭 암호화데이터를 암호화하고, 해독하는 데 같은 키를 사용하고 송수신 측에 교환해야 하기 때문에 해커가 그 키에 접근해 데이터를 해독할 위험이 있습니다.

 

이를 위해 비대칭 암호화가 탄생합니다. Private Key는 송신측에서 가지고 있는 비공개 열쇠이자, 다른 사람과 공유해서는 안됩니다. 자물쇠는 다른 사람과 공유할 수 있지만, 오직 Pirvate Key로만 잠그고 열 수 있습니다.

 

 

예를 들어, 접근이 필요한 서버가 존재했을 때, 단순 암호를 수송신 하는 경우는 위험해서 사용하고 싶지 않다고 할 때, 위의 예제를 적용해보겠습니다. 공개키와 비공개키를 생성하는 것인데, SSH 키와 명령을 실행하면 됩니다.

- ssh-keygen

id_rsa id_rsa.pub

(사설키)    (2개의 파일을 생성합니다. 공공 자물쇠인 것이죠)

 

 공공 자물쇠를 사용해 잠긴 것은 제외하고, 보통 서버의 SSH 인증키 파일에 공용키로 엔트리를 추가합니다. 만약 다른 사용자가 당신의 서버에 접속해야 한다면, 그들도 똑같이 개인키와 공용 키를 쌍으로 따로 만들 수 있습니다. 서버에 접속할 수 있는 유일한 사람이니까 그들에게 추가 문을 만들어 공용 잠금장치로 Lock할 수 있습니다. 모든 서버에 복사하면, 다른 사용자가 개인키를 이용해 서버에 접속할 수 있죠. 

 

다시 돌아와서, 대칭 암호화의 문제는 데이터를 암호화할 때 사용된 키가 암호화된 데이터와 함께 네트워크를 통해 서버로 전송해야 했습니다. 그래서 해커로 부터 위협이 될 수 있었죠.

 

만약 서버 키를 안전하게 빼낼 수 있다면? 서버에 키가 안전하게 사용되면 서버와 클라이언트는 대칭 암호화를 통해 안전하게 통신할 수 있습니다. 클라이언트에서 서버로 안전하게 대칭키를 옮기기 위해 비대칭 암호화를 사용합니다. 서버에 공용과 개인 키 페어를 생성하는 거죠. 오픈 SSL 명령을 이용해 사설과 공용 키 쌍을 생성합니다. 이렇게 하면 암호화에 사용한 키와 암호화된 데이터는 해커에게 넘어갈 수 있지만, 서버의 개인키로만 데이터를 해독할 수 있기 때문에 해커에게 데이터를 안보여줄 수 있습니다.

 

 

 메시지를 암호화하려면 공용과 개인 키로 비대칭 암호화를 해야 해요. 관리자는 한 쌍의 키로 서버 SSH 연결을 보안해요. 서버는 한 쌍의 키로 HTTPS 트래픽을 확보해요. CA는 우리를 위해 인증서에 서명하고 유효성을 확인해주는 잘 알려진 기관입니다.

 

1. 서버는 먼저 CA에 CSR(인증서 서명 요청)을 보내요.

2. CA는 개인키로 CSR에 서명하죠.

3. 모든 사용자는 CA 퍼블릭 키의 복사본을 갖고 있어요.

4. 서명된 인증서는 서버로 다시 보내지죠.

5. 서버는 서명된 인증서로 웹 응용 프로그램을 구성하죠.

6. 사용자가 웹 응용 프로그램에 액세스할 때마다 서버는 먼저 공개 키로 인증서를 보내죠.

7. 사용자, 정확히는 사용자의 브라우저가 인증서를 읽고 서버의 공개 키를 유효성 검사와 검색하기 위해 CA 공용 키를 사용하죠.

8. 그런 다음 대칭 키를 생성해 모든 통신에 사용하려고 하죠. 대칭키는 서버의 공개키로 암호화되어 서버로 전송돼요.

9. 서버는 개인 키로 메시지를 해독하고 대칭키를 회수해요.

10. 대칭키는 앞으로의 통신을 위한 거예요.

 

관리자가 SSH 보안 키 페어를 생성하죠. 웹 서버는 HTTPS로 웹사이트를 보호할 키 페어를 생성하죠. 인증서 기관은 자체 관리자를 생성해 인증서에 서명하죠. 하지만 최종 사용자는 단일 대칭키만 생성하죠.

웹 사이트에서 신뢰를 설정하면 아이디와 암호로 웹 서버에 인증해요. 하지만 서버 키퍼인 클라이언트는 서버의 유효성을 확인할 수 있었죠. 하지만 서버는 클라이언트인지 확실히 알 수 없어요. 사용자를 사칭하는 해커일 수도 있어요. 사용자의 자격 증명을 얻기 위해 네트워크를 이용한 건 아닐 겁니다. 이미 TLS로 보안을 확보했으니까요

 다른 방법을 썼을 수도 있고요. 어쨌든, 클라이언트가 진짜인지 확인하기 위해 서버가 뭘 할 수 있을까요? 이를 위해 트러스트 구축 연습의 일부로 서버가 클라이언트에게 인증서를 요청할 수 있죠. 그래서 클라이언트는 한 쌍의 키와 서명된 인증서를 생성해야 합니다. 유효한 CA로부터요. 그럼 클라이언트는 인증서를 서버로 보냅니다. 클라이언트가 자신들이 말하는 사람이 맞는지 확인하기 위해서요.

 

 

2. TLS In Kubernetes

 

1) Server Certificates for Servers

 

 

: 이미 알다시피 API 서버는 HTTPS를 공개합니다. 다른 구성 요소와 외부 사용자도 함께 k8s 클러스터를 관리하기 위해 사용합니다. 서버, 클라이언트의 모든 통신을 보호하기 위해 인증서가 필요합니다. 그래서 인증서와 키 페어를 생성하죠. 이를 아래와 같이 합니다.

apiserver.crt, apiserver.key (일반적인 명명)

 

클러스터에 있는 또 다른 서버는 ETCD 서버입니다. 따라서 인증서 한 쌍과 자체 키가 필요하죠.

또한 다른 구성 요소는 Worker 노드에 있습니다. 바로 Kubelet 서버죠. 이도 위와 마찬가지로 인증서와 키를 가지고 있습니다.

 

2) Clinet Certificates for Clients

 

 

: kube-apiserver에 접근하는 클라이언트 우리, kube-apiserver에 접근하는 REST API 관리자입니다. 사용자는 kube-apiserver에 인증하려면 인증서와 키 페어가 필요하죠. 스케줄러는 kube-apiserver에 보고해서 스케줄이 필요한 pod를 찾습니다. 후에 다음 api 서버가 올바른 Worker 노드의 pod를 찾도록 하죠. 스케줄러는 kube-apiserver에 접근하는 클라이언트죠.

 

스케줄러는 클라이언트 TLS 인증서를 이용해 ID를 확인해야 합니다. 그래서 자체 인증서와 열쇠가 필요합니다. KUBE-CONTROLLER-MANAGE는 kube-apiserver에 접근하는 또 다른 클라이언트입니다. 이 또한 인증서와 키를 쌍으로 만들죠.

 

마지막 구성 요소는 KUBE-PROXY입니다. 이는 kube-apiserver에 인증하기 위해 클라이언트 인증서를 요구하기 때문에 위와 같이 자체적인 인증서와 키를 필요로 합니다.

 

사실 모든 구성 요소 중 kube-apiserver는 여러 개의 요소와 통신하는 유일한 서버입니다. 

 

 

3. TLS CERTIFICATES

 

인증서를 생성하기 위해 EASYRSA, OPENSSL, CFSSL 같은 다양한 도구들을 이용할 수 있습니다. 이번 강의에서는 OpenSSL 도구를 활용해 인증서를 생성하겠습니다. [ 클러스터 인증서 생성 ]

 

1. 먼저 OpenSSL 명령으로 Private 키를 생성합니다. (Generate Keys)

> openssl genrsa -out ca.key 2048

 

결과 : ca.key

 

2. OpenSSL Request 명령을 사용합니다. (Certificate Signing Request)

 > openssl req -new -key ca.key -subj "/CN=KUBERNETES-CA" -out ca.csr

 

결과 : ca.csr

 

3. 인증서 요청 생성을 위해 방금 만든 키와 함께요. 이후 인증서 서명을 위해 아래와 같이 작성합니다. (Sign Certificates)

> openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt 

결과 : ca.crt

 

이전 명령에서 생성한 인증서 서명 요청을 명시화하고, 이것은 CA 자체에 대한 거라 첫 단계에서 생성된 개인 키를 이용해 CA가 자체 서명을 하도록 했습니다. 다른 모든 인증서에는 CA 키 페어를 사용해서 서명할 것 입니다.

 

 

[ 클라이언트 인증서 생성 ]

1. 관리자용 개인키를 생성하는 것과 같은 과정을 거칩니다. (Generate Key)

> openssl genrsa -out admin.key 2048 

결과 : admin.key

 

2.  이후 CSR을 생성해 관리자 사용자의 이름을 지정합니다. (Certificate Signing Request)

> openssl req -new -key admin.key -subj "/CN=kube-admin" -out admin.csr

> openssl req -new -key admin.key -subj "/CN=kube-admin/O-system:masters" -out admin.csr

위와 같이 O 매개변수를 사용하면 그룹 세부 사항을 추가하면서 인증서 서명 요청을 생성할 수 있습니다.

 

결과 : admin.csr

3. 이후 인증서 서명을 위해 아래와 같이 작성합니다. (Sign Certificates)

> openssl x509 -req -in admin.csr -CA ca.crt -CAkey ca.key -out admin.crt 

 

위와 같이 CA 인증서와 CA 키를 지정하면, 클러스터 내 유효한 인증서가 됩니다. 이는 다른 구성 요소인 스케줄러, kube-proxy 등 인증서를 생성할 때 같은 프로세스를 거칩니다. 그렇다면 이 인증서로 무엇을 할까요?

 

rest api 호출에서 사용자 이름과 암호 대신 이 인증서를 사용할 수 있습니다. 키와 인증서, CA 인증서를 옵션으로 지정합니다.

> curl https://kube-apiserver:6443/api/v1/pods --key admin.key --cert admin.crt --cacert ca.crt

 

  

 다른 방법은 이 모든 매개 변수들을 kubeconfig라는 구성 파일로 옮기는 것이죠. 이는 다음 강의에 더욱 자세하게 다룰거고, 쿠버네티스에서 구성 요소끼리 서로를 확인하려면 CA의 루트 인증서 복사본이 필요합니다. 서버나 클라이언트가 인증서를 갖고 구성할 때마다 CA 루트 인증서도 지정해야 합니다.

 

kube-apiserver 인증서는 다양한 구성 요소와 통신합니다. 그렇기에 CA 파일이 있어야 하고, 그런 다음 API 서버 인증서를 TLS 인증 옵션 아래에 제공합니다. 그런 다음 kube-apiserver에서 사용되는 클라이언트 인증서를 지정해 키타 서버에 CA 파일로 다시 연결합니다. 그리고 마지막으로 kube-apiserver 인증서입니다. kubelet에 연결하기 위해서죠.

 

kubelet 서버는 각 노드에서 실행되며, 노드 관리에 책임이 있습니다. API 서버가 노드를 모니터하기 위해 그들과 통신하는거죠. 그렇기에 클러스터의 각각 노드에 대해 키 인증서 쌍이 필요합니다. 명명은 대체적으로 노드 이름을 따서 node01, node02 이렇게 지을겁니다. 인증서가 생성되면 kubelet-config 파일을 이용할 수 있습니다. 클러스터의 각 노드를 위해 루트 인증서를 지정해 kubelet 노드 인증서를 제공합니다.

 

CA는 우리가 생성한 키와 인증서 파일 한 쌍입니다. 이 파일 쌍에 접근할 수 있는 사람은 누구든 쿠버네티스 환경에 대한 인증서에 서명할 수 있습니다. Master 노드는 CA 서버이기도 합니다. 지금까지 수동으로 해보았는데 이를 자동화할 수 있습니다. 쿠버네티스에 내장 인증서 API가 있어서 이것으로 대신 할 수 있죠. 인증서 API로 인증서 서명 요청을 직접 보냅니다.

 

관리자가 인증서 서명 요청을 받을 때 마스터 노드에 로그인 후 스스로 인증서를 서명하는 대신 1.Create CertificateSigningRequest Object를 생성합니다. 개체가 생성되면 모든 인증서 서명 요청은 클러스터 관리자들이 보게 됩니다. 2.Review Requests이는 kubectl 명령어를 통해 쉽게 검토하고 승인할 수 있습니다. 3.Approve Requests  인증서는 추출되어 사용자와 공유할 수 있습니다. 4.share Certs to Users 

 

1. 사용자는 먼저 키를 만들고 이름이 적힌 키를 사용해 인증서 서명 요청을 생성해 관리자에게 보냅니다.

>openssl genrsa -out jane.key 2048

결과 : jane.key

 

2. 관리자가 키를 취해 인증서 사인 구성 개체를 생성합니다. 

>openssl req -new -key jane.key -subj "/CN=jane" -out jane.csr

 

3. 이때 Base64 명령을 이용해 암호화 하고, 인코딩된 텍스트를 요청 필드로 옮겨 제출합니다.

>cat jane.csr | base64

 

4. 새 요청을 확인하고 승인할 수 있습니다.

> kubectl get csr

> kubectl certificate approve jane

 

모든 인증서 관련 작업은 Controller Manager가 담당합니다.

 

 

4. KubeConfig

 

 

kubeconfig 구성 파일은 3가지 섹션이 있습니다. Clusters, Contexts, Users.

Clusters는 접근에 필요한 다양한 쿠버네티스의 클러스터입니다. 당신이 여러개의 클러스터를 개발 환경이나 테스트 환경, 혹은 서로 다른 조직, 혹은 클라우드 공급자등 가지고 있다고 가정한다면, Users는 이런 클러스터에 접근 권한이 있는 사용자 계정이죠. 관리자, 개발자 등을 말합니다. 이 Users들은 다른 클러스터에서 다른 권한을 가질 수 있는데, 마지막으로 이 2가지가 Contexts에서 만납니다.

 

Contexts는 어떤 사용자 계정이 어떤 클러스터에 접근하기 위해 사용될지를 정의합니다. 예로 프로덕션에서 관리자라는 이름의 Contexts를 만들 수 있고, 관리자 계정을 이용해 프로덕션 클러스터에 접근하는 것이죠.

 

새로운 Users를 생성하건, 이 프로세스와 함께 클러스터에 권한을 설정하는 것이 아니라, 기존 유저의 사용 권한을 통해 클러스터에 접근하기 위해 사용할 유저로 정의할 수 있습니다.

 

kubectl config를 실행해 컨텍스트 명령을 이용해 현재 컨텍스트를 프로덕션 컨텍스트의 프로드 사용자로 바꿀 수 있습니다. 파일의 현재 컨텍스트 필드에서 볼 수 있고, kubectl config 명령이 바꾼 건 파일에 반영됩니다.

> kubectl config use-context prod-user@production

 

 

5. API Groups

: 쿠버네티스 API는 목적에 따라 여러 그룹으로 그룹화됩니다. 예로 /api, /healthz, /logs 등 있습니다. API는 /api, /apis로 나뉘는데 core와 named 그룹으로 나뉩니다.

 

핵심 기능은 core 그룹

 

named 그룹 api는 더 조직화 되어 있고, 새로운 기능들도 이 그룹을 통해 사용이 가능

 

 

  • kube-proxy는 클러스터 내 다양한 노드에 걸쳐 pod와 서비스 간 연결을 가능하게 하는 데 사용된다.
  • kubectl proxy는 https 프록시 서비스로 kubectl 유틸리티가 kube-api-server에 접근하기 위해 만든 것이다.

 

 

6. Authorization

: 쿠버네티스의 권한 부여 방식은 여러가지가 있습니다.

 

1. Node : Kube API 서버는 관리 목적으로 우리 같은 유저에게 접근됩니다. 클러스터 내 관리 프로세스를 위해 클러스터 내 노드에서 kubelets도 그렇습니다. kubelet은 API 서버에 접근해 Services, Endpoints, Pods 등 정보를 읽습니다. 그리고 이 정보를 Kube API 서버에 해당 서비스에 대한 정보를 전달합니다. 이런 요청은 노드 승인기로 알려진 특별 승인자가 처리합니다. 

 

2. ABAC : API의 외부 접근에 대해 말해보겠습니다. ABAC은 사용자나 사용자 그룹을 허가 모음으로 연결하는 것 입니다. 인접 형식으로 정의된 정책 집합과 함께 정책 파일을 생성해야 합니다. 이런 식으로 API 서버에 이 파일을 넘기죠. 이 파일의 사용자나 그룹에 대한 정책 정의 파일도 만들 수 있고요. 보안을 추가하거나 변경해야 할 때마다 이 정책 파일을 수동으로 수정하고 Kube API 서버를 다시 시작해야 하죠.그래서 ABAC는 관리하기 어렵습니다.

 

3. RBAC : 사용자에게 요구되는 적절한 권한 모음이 있다면 그 역할에 사용자를 연결하세요. 앞으로는 사용자의 액세스에 변화가 필요할 때마다 역할을 수정하기만 하면 됩니다. 모든 개발자에게 즉시 반영되죠. 역할 기반 액세스 제어는 쿠버네테스 클러스터 내에서 액세스 관리에 좀 더 표준적인 접근법을 제공하죠. 

 

 

3개의 섹션으로 나뉩니다. apiGroups, resources, verbs.

core 그룹은 apiGroups를 비워둘 수 있지만, 다른 그룹은 그룹 이름을 지정해야 합니다. 해당 역할에게 제공하고 싶은 것에는 resources를 작성해주면 됩니다. 취할 수 있는 행동은 verbs를 통해 작성할 수 있습니다. 역할 하나에 여러 규칙을 추가할 수 있고, 명령은 아래와 같습니다. > kubectl create -f developer-role.yaml

 

다음 단계는 사용자를 링크하면 됩니다. role binding 객체를 위에서 만든 .yaml에 연결하면 됩니다. 2개의 항목으로 구성되는데, subject는 세부 정보를 지정하는 곳입니다. roleRef는 미리 만든 규칙의 세부 사항을 제공하는 곳입니다.

> kubectl create -f devuser-developer-binding.yaml

 

role, binding은 namespace 범위 아래에 있다는 것을 주의하셔야 합니다. 사용자가 클러스터의 특정 리소스에 접근하고 싶다면 어떻게 해야할까요? 방법은 아래와 같습니다.

> kubectl auth can-i create deployments

> kubectl auth can-i delete nodes

여러분이 관리자라면 다른 유저를 사칭해 사용자의 권한을 확인할 수도 있습니다.

> kubectl auth can-i create deployments --as dev-user

 

마지막으로 하나의 네임스페이스의 지정된 resources에만 접근이 가능하기 때문에, role.yaml에 아래와 같이 namespace 필드를 추가해 원하는 namepsace의 리소스에 접근도 가능합니다.

 

 

4. Webhook : 모든 승인 메커니즘을 외부에 위탁하고 싶다면요? 방금 말씀드린 내장 메커니즘이 아닌 외부에서 권한을 관리하고 싶다고 해보죠. 가령, 오픈 정책 에이전트는 타사 도구로 입장 통제와 승인을 돕죠. 쿠버네테스가 오픈 정책 에이전트에 API 콜을 하도록 할 수 있습니다 사용자에 관한 정보와 요구 사항 액세스 정보와 함께요. 오픈 정책 에이전트가 사용자의 허용 여부를 결정하게 하는 거죠.

 

인증서는 서버의 인증 모드 옵션을 통해 설정됩니다. 설정하지 않으면 Default로 AlwaysAllow로 설정되어 있습니다.

> --authorization-mode=AlwaysAllow 여기서 예로 옵션값을 Node, RBAC, Webhook으로 변경시 지정된 순서대로 각각의 요청을 사용할 권한이 부여됩니다.

 

사용자가 요청을 보냈을 때, Node 승인을 확인 후 Yes라면 그대로 지나가고, 거부되었다면 다음 승인 순서인 RBAC으로 넘어가게 됩니다.

 

 

7. Cluster Roles

: role, rolebindings는 네임스페이스 내에서 생성된다고 앞에서 학습했습니다. 기본 Default는 기본 namespace에 생성되고, 그 내에서만 제어가 가능했습니다. 그럼 만약에 namespace에서 노드를 그룹화하거나 격리할 수 있을까요? node01이 dev-namespace의 일부라고 할 수 있을까요? 아닙니다. 그것은 클러스터 범위의 리소스입니다. 어떤 namespace와도 연결될 수 없습니다.

 

 

그렇다면 nodes나 PV 같은 클러스터 간 리소스에 어떻게 사용자에게 권한을 부여할까요? 여기서 clusterroles, clusterrolebindings를 사용하시면 됩니다. clusterroles는 앞서 배운 roles와 역할이 같습니다. 앞서 사용자에게 포드에 접속할 권한을 부여하는 역할을 만들었을 때 사용자는 특정 네임스페이스에서만 포드에 접속할 수 있었죠. 클러스터 역할로 사용자에게 포드 접속을 승인하면 사용자는 클러스터의 모든 Pods에 접속할 수 있습니다.

 

 

8. Service Accounts

 

 

: Service Accounts는 쿠버네티스의 다른 보안과 관련된 개념과 연결되어 있습니다. 예로 인증이나 권한부여, 역할 기반 접근 컨트롤 등등입니다. 쿠버네티스 계정은 2가지로 나뉩니다. 사용자 계정서비스 계정입니다.

 

사용자 계정은 사람이 사용하고, 관리 작업을 수행하기 위해 클러스터에 액세스하는 관리자를 위한 것일 수 있고, 응용 프로그램을 배포하기 위해 클러스터에 접근하는 개발자를 위한 것일 수도 있습니다.

 

서비스 계정은 기계가 사용합니다. 쿠버네티스 그룹과 상호작용하기 위해 앱이 사용하는 계정일 수 있습니다. 예로 프로메테우스 같은 모니터링 응용 프로그램은 서비스 계정을 이용해 퍼포먼스 메트릭을 위해 쿠버네티스 API를 가져옵니다. 젠킨스 사용자 계정 같은 자동 빌드된 도구를 이용해 쿠버네티스 클러스터에 앱을 배포합니다.

 

쿠버네티스의 모든 네임스페이스에 대해 기본값으로 서비스 계정이 자동 생성됩니다. 각각의 네임스페이스는 고유의 기본 서비그 계정을 갖고 있기에, pod가 생성될 때 기본 서비스 계정과 토큰이 자동으로 볼륨 마운트로 탑재되어 있습니다. 기존 pod의 서비스 계정은 수정할 수 없습니다. 삭제 후 재생성, 하지만 deployment의 경우 서비스 계정을 수정할 수 있습니다.

 

서비스 계정이 존재하는 한 토큰은 유효하고, 예전에는 만료일자가 없었다. 각 JWT는 서비스 당 개별 Secret 개체를 요구했고, 확장성 문제가 발생한다.

 

v1.22 : TokenRequestAPI는 쿠버네티스 개선 제안서1205의 일부로 API를 통해 더 안전하고 확장성 있게 쿠버네티스 서비스 계정 토큰을 프로비저닝하는 메커니즘을 도입했다. TokenRequest API(Audience, Time, Object bound)로 더 안전해짐. 새로운 파드가 생성되면 더 이상 Service Account의 Secret token에 의존하지 않는다. 대신 TokenRequestAPI를 통해 정해진 만료일자를 가진 토큰이 생성되고 파드에 volume으로 탑재된다.

 

v1.24 : 더 이상 자동으로 Secret이나 Secret Token이 생성되지 않도록 변경되었다. 따라서, kubectl create 명령어로 필요한 토큰을 생성해야 한다. 이때, 서비스 계정 이름을 입력해 필요한 서비스 계정을 위한 토큰을 생성하도록 해야 한다.

 

 

9. Image Security

 

 

 위와 같은 nginx 이미지는 Docker의 기본값 레지스트리 Docker hub로 추정되어 가져옵니다. 레지스트리는 모든 이미지를 저장하는 곳이죠. 새 이미지를 생성 또는 업데이트할 때 레지스트리에 push하면 누군가 이 응용 프로그램을 배포할 때 레지스트리에서 끌어옵니다. 

 

 

pod 정의 파일로 돌아가서 개인 레지스트리의 이미지를 사용합니다. 개인 레지스트리에 있는 것으로 전체 경로로 이미지 이름을 치환합니다. 인증과 로그인 파트는 어떻게 구현하죠? 쿠버네티스가 어떻게 접속할 자격을 얻었죠? 쿠버네티스 안에서 우린 이미지가 작업자 노드의Docker 런타임에 의해 실행된다는 걸 알죠 작업자 노드에서 자격 증명을 docker 실행 시간에 어떻게 전달하죠?

이를 위해 먼저 자격 증명이 포함된 비밀 개체를 생성하죠. 도커 레지스트리의 비밀은 regcred라는 이름이죠. Docker 레지스트리는 Docker 자격 증명을 저장하기 위해 비밀리에 빌드된 유형이죠. 그런 다음 레지스트리 서버 이름을 지정합니다 레지스트리에 엑세스할 사용자 이름, 암호 사용자의 이메일 주소를요. 그런 다음 포드 정의 파일 안의 비밀을 지정합니다. imagePullSecrets 아래에요 포드가 생성되면 작업자 노드에 있는 쿠버네티스 혹은 쿠벨렛은 기밀에 있는 자격 증명을 이용해 이미지를 가져오죠.

 

 

9. Docker Security

: 가상 머신과 달리 컨테이너는 호스트로부터 완전히 격리되어 있지 않습니다. 컨테이너와 호스트가 같은 커널을 공유하죠. 컨테이너는 Linux에서 네임 스페이스를 이용해 격리됩니다. 컨테이너에 의해 실행되는 모든 프로세스는 호스트 자체에서 실행되지만, 고유의 네임스페이스에서 실행됩니다.

 

고유의 네임 스페이스에 있어 고유의 프로세스만 볼 수 있습니다. 바깥이나 다른 네임 스페이스에서는 볼 수 없다는 뜻이죠. 만약 sleep 3600 명령을 수행하는 Docker container 내에서 ps aux 명령어로 docker container 내의 프로세스를 나열하면 PID 1로 sleep3600 프로세스를 볼 수 있습니다.

 

호스트에서 ps aux 명령어로 호스트 내의 프로세스를 나열하면 sleep 3600를 실행중인 다른 PID를 확인할 수 있습니다. 이는 프로세스가 다른 다른 네임스페이스에서 다른 PID를 가질 수 있기 때문이고, 이것이 docker가 시스템 내에서 컨테이너를 격리하는 방식입니다.

 

 

docker는 컨테이너 내 루트 사용자의 능령을 제한하는 보안 기능을 제공합니다. 컨테이너 루트 사용자는 호스트 루트 사용자와 다르며. docker는 이것을 구현하기 위해 리눅스 기능을 이용합니다.

 

루트 사용자는 시스템에서 가장 강력하고, 어떤 프로세스이든, 시스템의 제한없이 접근이 가능하다. 기본값으로 docker는 컨테이너의 기능을 제한하고, 호스트를 재부팅하거나 다른 컨테이너를 방해할 수 없다. 추가적인 특권을 제공하고 싶다면 docker run 명령에 '--cap-add[추가권한]'을 추가해주면 된다.

 

이처럼 docker 컨테이너를 실행할 때 보안 표준 집합을 정의할 수 있는 옵션이 있었는데, 쿠버네티스에서도 이러한 기능이 있습니다.

 

쿠버네티스에서는 컨테이너를 캡슐에 넣어 보관합니다. 컨테이너 레벨 또는 pod 레벨에서 보안 설정을 선택할 수 있습니다. pod 수준으로 설정하면 pod 내 모든 컨테이너에 설정값이 전달됩니다. pod와 컨테이너 둘 다에 구성하면 컨테이너의 설정이 pod의 설정을 무효화합니다.

 

 

10. Network Policies

: 쿠버네티스 네트워킹의 전제 조건 중 하나는 어떤 솔루션을 구현하든 pod가 서로 통신할 수 있어야 한다는 것 입니다. 경로 같은 추가적인 설정이 필요 없다는 것이죠.

 

 

위를 예로, 네트워크 솔루션에선 모든 Pod가 가상 사설 네트워크에 있고, 쿠버네티스 클러스터 내 노드를 가로지르며 기본값으로 서로 닿습니다. 그 목적으로 구성된 IP나 pod 이름 또는 서비스를 이용해서요. 쿠버네티스는 기본값으로 모든 허용 규칙과 함께 구성됩니다. 어떤 Pod, 트래픽이 다른 pod, 또는 클러스터 내의 서비스가 가능하도록요.

 

그런데 만약, 웹 서버와 데이터베이스 서버가 직접적으로 통신하지 않는 것을 원하면 어떻게 할까요? 여기서 네트워크 정책을 구현할 수 있습니다. Network Policy은 쿠버네티스 네임스페이스에 있는 또 다른 객체로 pod, ReplicaSet이나 서비스처럼 하나 이상의 pod에 네트워크 정책을 연결합니다. 아래의 경우 3306 포트 API pod에서만 Ingress 트래픽을 허용한다. 일단 이 정책이 생성되면 pod의 모든 트래픽을 차단하고 지정된 규칙에 부합하는 트래픽만 허용합니다.

 

 

그렇다면 Network Policy을 어떻게 pod에 적용하고 링크할까요? replicaSet, Service를 pod와 label, selector에 링크하는 데 사용한 동일한 기술을 사용합니다. pod에 label을 붙이고, 네트워크 정책의 port selector 필드에 같은 Label을 사용합니다. 그리고 규칙을 만들죠.

 

 

정책 유형에서 트래픽의 진입과 퇴장을 허용할지 혹은 둘 다 허용할지 명시하세요. 예로 위에서는 DB pod에 입력 트래픽만 허용하고 싶어요. 그래서 추가합니다. 다음 Ingress 규칙을 지정합니다. 그것이 API pod의 트래픽을 허용하고, 사용자는 Label, Selector를 이용해 API Pod를 다시 지정합니다. .yaml 파일 작성은 아래와 같습니다.

 

 

참고로 Network Policy는 네트워크 솔루션에 의해 시행되었습니다. 모든 네트워크 솔루션이 Network Policy 정책을 지원하는 것은 아닙니다. Kube-router, Calico, Romana, Weabe-net은 지원이 되고, FLannel은 지원되지 않습니다.

 

만약 들어오는 트래픽을 허용하면 그 트래픽에 대한 응답이나 회신이 자동으로 허용된다. 그래서 응답, 회신에 대한 것은 따로 규정하지 않아도 된다.

 

 

추가로 namespaceSelector만 지정할 수도 있다. 그럴 경우, 지정한 네임스페이스 내의 모든 파드만 데이터베이스 파드에 도달할 수 없다. 또한 ipBlock 영역을 통해 IP 주소를 지정하면 해당 IP의 개체가 DB 파드에 접근할 수 있다.

 

정리하자면 특정한 파드, 네임스페이스, ip 주소를 지정하기 위해 podSelector, namespaceSelector, ipBlock 영역을 사용하면 된다. namespaceSelector 앞에 대시를 추가해 규칙을 분리할 수 있다.

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.