목표

  • 쿠버네티스 API 서버로 접근하는 3가지 방법 파헤치기

X509 Client Certs

  • 클러스터에 6443 포트로 API 서버가 열려있고, 사용자가 HTTPS로 접근하려면 kubeconfig라는 파일안에 Client key, Client crt를 가져오면 된다.
  • 여기서 CA는 중간 CA로, 자신의 개인키를 통해 CA csr을 만들고, 이를 상위 CA에서 서명을 받아 CA crt가 만들어진다.
  • Client key는 직접 만들거나, 툴을 통해 자동으로 만들 수 있다.
  • Client crt는 Client csr을 중간 CA의 개인키로 서명하면 만들어진다. 이때 CA crt가 필요한 이유는 중간 CA의 공개키가 들어있으므로 이를 통해 검증하는 과정을 할 수 있기 때문이다.
  • 즉, CA crt는 Client crt를 만드는데에 필요한 것은 아니고, 검증을 위한 것이다.
  • kubectl의 경우 kubeconfig 파일을 통채로 복사하는 과정이 있기 때문에 kubectl로 쿠버네티스 API 서버에 인증이 되어서 리소스들을 조회할 수 있는 것이다.
    • accept-hosts 옵션을 통해서 8001번 포트로 proxy를 열어두면 외부에서도 HTTP로 접근할 수 있다.
    • 이 경우에도 결국 kubectl의 kubeconfig를 사용하기 때문에 쿠버네티스 API 서버에 접근할 수 있는 것이다.
프록시 서버란? 중간에서 요청을 대신 전달해주는 서버
A -> (프록시 서버) -> B와 같다.
프록시 서버를 연다는 의미는 프록시 서버 기능을 하는 HTTP 서버를 띄운다는 말이다.
이 상황에서는 (사용자) → (kubectl이 띄운 로컬 프록시) → (Kubernetes API 서버) 와 같다.
명령어는 nohup kubectl proxy --port=8001 --address=192.168.56.30 --accept-hosts='^*$' >/dev/null 2>&1 & 와 같다.
정리하자면 kubectl proxy는 클라이언트로부터 받은 요청을 처리하고, kubectl이 들고 있는 kubeconfig에 따라 인증 정보를 자동으로 포함하여 쿠버네티스 API 서버로 전달한다.
[클라이언트] --> (HTTP) --> [kubectl proxy 로컬 서버] --> (HTTPS + 인증) --> [Kubernetes API 서버]

kubectl

  • 이 사진은 외부에 kubectl을 설치해서 멀티 클러스터에 접근하는 경우이다.
  • 사전에 각 클러스터에 있는 kubeconfig 파일이 kubectl에도 있어야 한다.
  • kubeconfig 안에는 다음과 같은 내용이 있다.
    • clusters라는 항목으로 클러스터를 등록할 수 있다. 내용으로는 이름과 url, CA crt가 있다.
    • users라는 항목으로 사용자를 등록할 수 있다. 내용으로는 유저 이름과 이 유저에 대한 개인키와 인증서가 있다.
    • contexts항목을 통해서 clusters와 users를 연결할 수 있다. 내용으로는 컨텍스트 이름과 클러스터 이름, 유저 이름이 있다.
  • kubeconfig를 가지고 있을 때, 클러스터 A에 연결하고 싶으면 "kubectl config use-context context-A" 명령어를 입력하면 된다.
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1KVEUtLS0tLQo=
    server: https://192.168.0.30:6443
  name: cluster-a
- cluster:
    certificate-authority-data: LS0tLS1KVEUtLS0tLQo=
    server: https://192.168.0.50:6443
  name: cluster-b
contexts:
- context:
    cluster: cluster-a
    user: admin-a
  name: context-a
- context:
    cluster: cluster-b
    user: admin-b
  name: context-b
current-context: context-a
kind: Config
preferences: {}
users:
- name: admin-a
  user:
    client-certificate-data: LS0tLS1KVEUtLS0tLQo=
    client-key-data: LS0tLS1KVEUtLS0tLQo=
- name: admin-b
  user:
    client-certificate-data: LS0tLS1KVEUtLS0tLQo=
    client-key-data: LS0tLS1KVEUtLS0tLQo=
  • 외부 kubectl에 들어있어야 할 kubeconfig 내용이다.
  • context와 clsuters, users 내부의 name은 임의의 값을 넣는 것이다.

Servcie Account

  • Namespace를 만들면 기본적으로 default라는 이름의 ServiceAccount가 자동으로 만들어진다.
  • 이후 ServiceAccount에 Secret을 하나 달아줘야 한다. Secret에는 CA crt와 token값이 들어있다.
  • Pod를 만들면 ServiceAccount와 연결이 되고 Pod는 이 토큰 값을 통해서 API 서버에 접근할 수 있다.
  • 따라서 외부에서도 이 토큰 값만 알면 API 서버에 접근할 수 있다.
  • 요청을 보낼 시에 헤더 중 "Authorization" key에 대해 "Bearer " 접두사를 주고 token 값을 넣어주면 된다.
apiVersion: v1
kind: Secret
metadata:
  name: default-sa-token
  namespace: my-namespace
  annotations:
    kubernetes.io/service-account.name: "default"
type: kubernetes.io/service-account-token
  • kubernetes.io/service-account.name: "default": 이 Secret이 어떤 ServiceAccount용인지 명시한다.
    • ServiceAccount의 이름을 통해 매칭시킨다.
  • type: kubernetes.io/service-account-token: 이 타입은 ServiceAccount용 토큰 Secret임을 명시한다.
    • Kubernetes는 이 타입의 Secret에 JWT, CA 인증서 등을 자동으로 넣어 Pod가 API 서버와 인증할 수 있도록 한다.

+ Recent posts