Kubernetes Basics
쿠버네티스 기본 사항
AWS 해킹 배우고 실습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우고 실습하기:
HackTricks Training GCP Red Team Expert (GRTE)
이 페이지의 원 저자는 Jorge 입니다(그의 원본 게시물을 여기에서 확인하세요)
아키텍처 및 기본 사항
쿠버네티스의 역할은 무엇인가요?
컨테이너를 컨테이너 엔진에서 실행할 수 있게 합니다.
스케줄링을 통해 컨테이너를 효율적으로 배치합니다.
컨테이너를 유지합니다.
컨테이너 간 통신을 허용합니다.
배포 기술을 허용합니다.
다량의 정보를 처리합니다.
아키텍처
![](https://cloud.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2Fsickrov.github.io%2Fmedia%2FScreenshot-68.jpg&width=768&dpr=4&quality=100&sign=4902871c&sv=1)
노드: 팟 또는 팟이 있는 운영 체제.
팟: 컨테이너 또는 여러 컨테이너를 감싸는 래퍼. 팟은 일반적으로 하나의 응용 프로그램만 포함해야 합니다(따라서 보통 팟은 하나의 컨테이너만 실행합니다). 팟은 쿠버네티스가 실행 중인 컨테이너 기술을 추상화하는 방법입니다.
서비스: 각 팟은 노드의 내부 범위에서 1개의 내부 IP 주소를 가집니다. 그러나 서비스를 통해 노출될 수도 있습니다. 서비스에도 IP 주소가 있으며, 그 목표는 팟 간 통신을 유지하고, 따라서 하나가 종료되면 새로운 대체품(다른 내부 IP를 가진)이 서비스의 동일한 IP에서 접근 가능하도록 합니다. 내부 또는 외부로 구성할 수 있습니다. 또한 2개의 팟이 동일한 서비스에 연결되어 있을 때 서비스는 로드 밸런서로 작동합니다. 서비스가 생성되면
kubectl get endpoints
를 실행하여 각 서비스의 엔드포인트를 찾을 수 있습니다.Kubelet: 주요 노드 에이전트. 노드와 kubectl 간의 통신을 설정하고, API 서버를 통해 팟만 실행할 수 있습니다. kubelet은 쿠버네티스에서 생성되지 않은 컨테이너를 관리하지 않습니다.
Kube-proxy: apiserver와 노드 간의 통신(서비스)을 담당하는 서비스입니다. 기본적으로 노드용 IPtables입니다. 숙련된 사용자는 다른 공급업체의 kube-proxy를 설치할 수 있습니다.
사이드카 컨테이너: 사이드카 컨테이너는 팟 내의 주 컨테이너와 함께 실행되어야 하는 컨테이너입니다. 이 사이드카 패턴은 현재의 컨테이너 기능을 확장하고 향상시킵니다. 요즘에는 응용 프로그램이 어디에서든 실행될 수 있도록 모든 종속성을 래핑하기 위해 컨테이너 기술을 사용한다는 것을 알고 있습니다. 컨테이너는 한 가지 일만 하고 그 일을 아주 잘합니다.
마스터 프로세스:
API 서버: 사용자와 팟이 마스터 프로세스와 통신하는 방법입니다. 인증된 요청만 허용되어야 합니다.
스케줄러: 스케줄링은 Kubelet이 실행할 수 있도록 Pod를 노드에 일치시키는 것을 의미합니다. 더 많은 사용 가능한 리소스가 있는 노드를 결정하고 새로운 팟을 할당하는 데 충분한 지능을 가지고 있습니다. 스케줄러는 새로운 팟을 시작하지 않고, 그저 노드 내에서 실행되는 Kubelet 프로세스와 통신합니다.
Kube Controller Manager: 예를 들어 올바른 수의 팟 또는 노드가 실행 중인지 확인하기 위해 레플리카 세트 또는 배포와 같은 리소스를 확인합니다. 팟이 누락된 경우 스케줄러와 통신하여 새로 시작합니다. API에 대한 복제, 토큰 및 계정 서비스를 제어합니다.
etcd: 데이터 저장소, 지속적이고 일관적이며 분산형입니다. 쿠버네티스의 데이터베이스이며 클러스터의 완전한 상태를 유지하는 키-값 저장소입니다(각 변경 사항은 여기에 로그됩니다). 스케줄러나 컨트롤러 매니저와 같은 구성 요소는 변경 사항을 알기 위해 이 데이터에 의존합니다(노드의 사용 가능한 리소스, 실행 중인 팟 수 등). 클라우드 컨트롤러 매니저: 흐름 제어 및 응용 프로그램을 위한 특정 컨트롤러입니다. 예: AWS 또는 OpenStack에 클러스터가 있는 경우.
여러 노드(여러 팟을 실행하는)가 있을 수 있기 때문에 여러 마스터 프로세스가 있을 수 있으며, 이들의 Api 서버 액세스는 로드 밸런싱되고 etcd가 동기화됩니다.
볼륨:
팟이 사라지더라도 손실되지 않아야 하는 데이터를 생성할 때 물리적 볼륨에 저장해야 합니다. 쿠버네티스는 팟에 볼륨을 연결하여 데이터를 지속시킬 수 있습니다. 볼륨은 로컬 머신이나 원격 저장소에 있을 수 있습니다. 서로 다른 물리적 노드에서 팟을 실행 중이라면 모든 팟이 액세스할 수 있도록 원격 저장소를 사용해야 합니다.
기타 구성:
ConfigMap: 서비스에 액세스하기 위한 URL을 구성할 수 있습니다. 팟은 여기서 데이터를 가져와 다른 서비스(팟)와 통신하는 방법을 알게 됩니다. 이는 자격 증명을 저장하는 권장되지 않는 위치입니다!
Secret: 비밀 데이터(비밀번호, API 키 등)를 저장하는 곳입니다. B64로 인코딩됩니다. 팟은 필요한 자격 증명을 사용하기 위해 이 데이터에 액세스할 수 있습니다.
Deployments: 쿠버네티스에서 실행할 구성 요소가 지정되는 곳입니다. 사용자는 일반적으로 직접 팟을 다루지 않고, 팟은 ReplicaSets(복제된 동일한 팟 수)로 추상화되어 배포를 통해 실행됩니다. 배포는 상태를 유지하지 않는 응용 프로그램을 위한 것입니다. 배포의 최소 구성은 이름과 실행할 이미지입니다.
StatefulSet: 데이터베이스와 같은 애플리케이션에 특히 적합한 구성 요소로, 동일한 저장소에 액세스해야 하는 애플리케이션을 위한 것입니다.
Ingress: URL로 응용 프로그램을 공개하는 구성입니다. 외부 서비스를 사용하여도 가능하지만 이 방법이 응용 프로그램을 노출하는 올바른 방법입니다.
Ingress를 구현하면 Ingress Controllers를 생성해야 합니다. Ingress Controller는 요청을 받아들이고 확인한 후 서비스로 로드 밸런싱하는 팟입니다. Ingress Controller는 구성된 Ingress 규칙에 따라 요청을 보냅니다. Ingress 규칙은 서로 다른 경로나 하위 도메인을 가리킬 수 있습니다.
더 나은 보안 관행은 Kubernetes 클러스터의 일부를 노출하지 않도록 클라우드 로드 밸런서나 프록시 서버를 진입점으로 사용하는 것입니다.
Ingress 규칙과 일치하지 않는 요청이 수신되면 Ingress Controller는 "기본 백엔드"로 이동합니다. 이 매개변수의 주소를 얻으려면 Ingress Controller를
describe
할 수 있습니다.minikube addons enable ingress
PKI 인프라 - 인증 기관 CA:
![](https://cloud.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2Fsickrov.github.io%2Fmedia%2FScreenshot-66.jpg&width=768&dpr=4&quality=100&sign=ddfcd3be&sv=1)
CA는 클러스터 내 모든 인증서에 대한 신뢰할 수 있는 루트입니다.
구성 요소가 서로 유효성을 검사할 수 있게 합니다.
모든 클러스터 인증서는 CA에 의해 서명됩니다.
ETCd는 자체 인증서를 갖습니다.
유형:
apiserver cert.
kubelet cert.
scheduler cert.
기본 작업
Minikube
Minikube를 사용하여 전체 kubernetes 환경을 배포할 필요 없이 kubernetes에서 빠른 테스트를 수행할 수 있습니다. 마스터 및 노드 프로세스를 한 대의 기계에서 실행할 것입니다. Minikube는 노드를 실행하기 위해 virtualbox를 사용할 것입니다. 여기에서 설치하는 방법을 확인하세요.
Kubectl 기본 사항
**Kubectl
**은 쿠버네티스 클러스터용 명령줄 도구입니다. 이 도구는 마스터 프로세스의 Api 서버와 통신하여 쿠버네티스에서 작업을 수행하거나 데이터를 요청합니다.
미니큐브 대시보드
대시보드를 통해 미니큐브가 실행 중인 것을 더 쉽게 확인할 수 있습니다. 액세스할 URL은 다음 위치에 있습니다:
YAML 구성 파일 예시
각 구성 파일에는 metadata (메타데이터), specification (실행해야 하는 내용), status (원하는 상태) 세 부분이 있습니다. 배포 구성 파일의 specification 내부에는 실행할 이미지를 정의하는 새 구성 구조로 정의된 템플릿을 찾을 수 있습니다:
동일한 구성 파일에서 선언된 배포 + 서비스 예시 (여기서 여기에서)
서비스는 일반적으로 하나의 배포와 관련이 있으므로 동일한 구성 파일에서 둘 다 선언하는 것이 가능합니다 (이 구성에서 선언된 서비스는 내부에서만 접근 가능합니다):
외부 서비스 구성 예시
이 서비스는 외부에서 접근 가능합니다 (nodePort
및 type: LoadBalancer
속성 확인):
테스트에 유용하지만 프로덕션에서는 내부 서비스만 있고 응용 프로그램을 노출하기 위해 Ingress가 있어야 합니다.
Ingress 구성 파일 예시
이것은 응용 프로그램을 http://dashboard.com
에 노출시킵니다.
시크릿 구성 파일 예시
비밀번호가 B64로 인코딩되어 있는 것을 주목하세요 (안전하지 않음!)
ConfigMap 예시
ConfigMap은 팟에 제공되는 구성으로, 다른 서비스를 찾고 액세스하는 방법을 알 수 있습니다. 이 경우 각 팟은 mongodb-service
라는 이름이 통신할 수 있는 팟의 주소임을 알게 될 것입니다 (이 팟은 mongodb를 실행할 것입니다):
그럼, 배포 구성 내부에서 이 주소를 다음과 같이 지정할 수 있으므로 팟의 환경에 로드됩니다:
볼륨 구성 예시
https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes에서 스토리지 구성 yaml 파일의 다양한 예시를 찾을 수 있습니다. 볼륨은 네임스페이스 안에 있지 않음을 주의하세요
네임스페이스
Kubernetes는 동일한 물리적 클러스터를 뒷받침하는 여러 가상 클러스터를 지원합니다. 이러한 가상 클러스터를 네임스페이스라고 합니다. 이들은 많은 사용자가 여러 팀 또는 프로젝트에 걸쳐 분산되어 있는 환경에서 사용하기 위한 것입니다. 몇 명에서 수십 명의 사용자가 있는 클러스터의 경우, 네임스페이스를 생성하거나 고려할 필요가 없습니다. Kubernetes에 배포된 응용 프로그램의 각 부분을 더 잘 제어하고 조직화하기 위해 네임스페이스를 사용해야 합니다.
네임스페이스는 이름에 대한 범위를 제공합니다. 리소스의 이름은 네임스페이스 내에서 고유해야 하지만 네임스페이스 간에는 고유할 필요가 없습니다. 네임스페이스는 서로 중첩될 수 없으며 각 Kubernetes 리소스는 하나의 네임스페이스에만 있을 수 있습니다.
minikube를 사용하는 경우 기본적으로 4개의 네임스페이스가 있습니다:
kube-system: 사용자가 사용하도록 의도된 것이 아니며 손대서는 안 됩니다. 마스터 및 kubectl 프로세스용입니다.
kube-public: 공개적으로 접근 가능한 데이터입니다. 클러스터 정보를 포함하는 configmap이 있습니다.
kube-node-lease: 노드의 가용성을 결정합니다.
default: 사용자가 리소스를 생성하는 데 사용할 네임스페이스입니다.
대부분의 Kubernetes 리소스 (예: pods, services, replication controllers 및 기타)는 일부 네임스페이스에 있습니다. 그러나 네임스페이스 리소스 및 노드 및 persistenVolumes와 같은 저수준 리소스와 같은 다른 리소스는 네임스페이스에 속해 있지 않습니다. 어떤 Kubernetes 리소스가 네임스페이스에 속하는지 속하지 않는지 확인하려면:
그 컨텍스트에서 모든 후속 kubectl 명령에 대해 네임스페이스를 저장할 수 있습니다.
Helm
Helm은 Kubernetes의 패키지 관리자입니다. 이를 사용하여 YAML 파일을 패키징하고 공개 및 비공개 저장소에서 배포할 수 있습니다. 이러한 패키지를 Helm 차트라고 합니다.
쿠버네티스 시크릿
시크릿은 비밀 데이터인 비밀번호, 토큰 또는 키와 같은 데이터를 포함하는 객체입니다. 이러한 정보는 그 외에는 Pod 사양이나 이미지에 넣을 수 있습니다. 사용자는 시크릿을 생성할 수 있고 시스템도 시크릿을 생성합니다. 시크릿 객체의 이름은 유효한 DNS 하위 도메인 이름이어야 합니다. 공식 문서에서 자세히 읽을 수 있습니다.
시크릿은 다음과 같은 것들일 수 있습니다:
API, SSH 키.
OAuth 토큰.
자격 증명, 비밀번호 (일반 텍스트 또는 b64 + 암호화).
정보 또는 주석.
데이터베이스 연결 코드, 문자열... .
쿠버네티스에는 다양한 유형의 시크릿이 있습니다
내장 유형 | 사용법 |
---|---|
Opaque | 임의의 사용자 정의 데이터 (기본값) |
kubernetes.io/service-account-token | 서비스 계정 토큰 |
kubernetes.io/dockercfg | 직렬화된 ~/.dockercfg 파일 |
kubernetes.io/dockerconfigjson | 직렬화된 ~/.docker/config.json 파일 |
kubernetes.io/basic-auth | 기본 인증을 위한 자격 증명 |
kubernetes.io/ssh-auth | SSH 인증을 위한 자격 증명 |
kubernetes.io/tls | TLS 클라이언트 또는 서버 데이터 |
bootstrap.kubernetes.io/token | 부트스트랩 토큰 데이터 |
Opaque 유형은 기본 유형으로, 사용자가 정의한 전형적인 키-값 쌍입니다.
시크릿 작동 방식:
![](https://cloud.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2Fsickrov.github.io%2Fmedia%2FScreenshot-164.jpg&width=768&dpr=4&quality=100&sign=407ce89f&sv=1)
다음 구성 파일은 username: YWRtaW4=
및 password: MWYyZDFlMmU2N2Rm
과 같은 2개의 키-값 쌍을 가진 mysecret
라는 시크릿을 정의합니다. 또한 mysecret
에 정의된 username
및 password
가 환경 변수 SECRET_USERNAME
및 SECRET_PASSWORD
에 노출되는 secretpod
라는 팟을 정의합니다. 또한 username
시크릿을 /etc/foo/my-group/my-username
경로에 0640
권한으로 마운트합니다.
etcd에 저장된 비밀
etcd는 모든 클러스터 데이터를 위한 Kubernetes 백업 저장소로 사용되는 일관된 고가용성 키-값 저장소입니다. etcd에 저장된 비밀에 액세스해 봅시다:
인증서, 키 및 URL이 파일 시스템에 위치해 있습니다. 이를 획득하면 etcd에 연결할 수 있습니다.
한 번 통신을 확립하면 비밀을 얻을 수 있습니다:
ETCD에 암호화 추가하기
기본적으로 모든 비밀은 etcd 내부에 평문으로 저장됩니다. 암호화 계층을 적용하지 않는 한. 다음 예제는 https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/를 기반으로 합니다.
이후에는 --encryption-provider-config
플래그를 kube-apiserver
에 설정하여 생성된 구성 파일의 위치를 가리켜야 합니다. /etc/kubernetes/manifest/kube-apiserver.yaml
파일을 수정하고 다음 라인을 추가할 수 있습니다:
volumeMounts에서 아래로 스크롤하세요.
volumeMounts에서 hostPath로 스크롤하세요:
데이터가 암호화되었는지 확인
데이터는 etcd에 쓰여질 때 암호화됩니다. kube-apiserver
를 다시 시작한 후에는 새로 생성하거나 업데이트된 시크릿이 저장될 때 암호화되어야 합니다. 확인하기 위해 etcdctl
명령줄 프로그램을 사용하여 시크릿의 내용을 검색할 수 있습니다.
default
네임스페이스에secret1
이라는 새 시크릿을 생성합니다:
etcdctl 명령줄을 사용하여 etcd에서 해당 시크릿을 읽어옵니다:
ETCDCTL_API=3 etcdctl get /registry/secrets/default/secret1 [...] | hexdump -C
여기서 [...]
은 etcd 서버에 연결하기 위한 추가 인수여야 합니다. 3. 저장된 시크릿이 k8s:enc:aescbc:v1:
로 시작하는지 확인합니다. 이는 aescbc
제공자가 결과 데이터를 암호화했음을 나타냅니다. 4. API를 통해 검색된 시크릿이 올바르게 복호화되었는지 확인합니다:
mykey: bXlkYXRh
와 일치해야 합니다. mydata
가 인코딩되어 있으며, 시크릿을 완전히 디코딩하려면 시크릿 디코딩을 확인하세요.
시크릿이 쓰기 시 암호화되므로 시크릿을 업데이트하면 해당 내용이 암호화됩니다:
최종 팁:
FS에 비밀을 저장하지 말고 다른 곳에서 가져오세요.
https://www.vaultproject.io/에서 비밀에 추가적인 보호를 더하세요.
참고 자료
AWS 해킹 학습 및 실습:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 학습 및 실습:
HackTricks Training GCP Red Team Expert (GRTE)
Last updated