343 lines
18 KiB
Markdown
343 lines
18 KiB
Markdown
---
|
|
|
|
|
|
title: kubeadm을 사용한 인증서 관리
|
|
content_type: task
|
|
weight: 10
|
|
---
|
|
|
|
<!-- overview -->
|
|
|
|
{{< feature-state for_k8s_version="v1.15" state="stable" >}}
|
|
|
|
[kubeadm](/ko/docs/reference/setup-tools/kubeadm/)으로 생성된 클라이언트 인증서는 1년 후에 만료된다.
|
|
이 페이지는 kubeadm으로 인증서 갱신을 관리하는 방법을 설명하며,
|
|
kubeadm 인증서 관리와 관련된 다른 작업에 대해서도 다룬다.
|
|
|
|
## {{% heading "prerequisites" %}}
|
|
|
|
|
|
[쿠버네티스의 PKI 인증서와 요구 조건](/ko/docs/setup/best-practices/certificates/)에 익숙해야 한다.
|
|
|
|
<!-- steps -->
|
|
|
|
## 사용자 정의 인증서 사용 {#custom-certificates}
|
|
|
|
기본적으로, kubeadm은 클러스터를 실행하는 데 필요한 모든 인증서를 생성한다.
|
|
사용자는 자체 인증서를 제공하여 이 동작을 무시할 수 있다.
|
|
|
|
이렇게 하려면, `--cert-dir` 플래그 또는 kubeadm `ClusterConfiguration` 의
|
|
`certificatesDir` 필드에 지정된 디렉터리에 배치해야 한다.
|
|
기본적으로 `/etc/kubernetes/pki` 이다.
|
|
|
|
`kubeadm init` 을 실행하기 전에 지정된 인증서와 개인 키(private key) 쌍이 존재하면,
|
|
kubeadm은 이를 덮어 쓰지 않는다. 이는 예를 들어, 기존 CA를
|
|
`/etc/kubernetes/pki/ca.crt` 와 `/etc/kubernetes/pki/ca.key` 에
|
|
복사할 수 있고, kubeadm은 이 CA를 사용하여 나머지 인증서에 서명한다는 걸 의미한다.
|
|
|
|
## 외부 CA 모드 {#external-ca-mode}
|
|
|
|
`ca.key` 파일이 아닌 `ca.crt` 파일만 제공할
|
|
수도 있다(이는 다른 인증서 쌍이 아닌 루트 CA 파일에만 사용 가능함).
|
|
다른 모든 인증서와 kubeconfig 파일이 있으면, kubeadm은 이 조건을
|
|
인식하고 "외부 CA" 모드를 활성화한다. kubeadm은 디스크에
|
|
CA 키없이 진행한다.
|
|
|
|
대신, `--controllers=csrsigner` 사용하여 controller-manager를
|
|
독립적으로 실행하고 CA 인증서와 키를 가리킨다.
|
|
|
|
[PKI 인증서와 요구 조건](/ko/docs/setup/best-practices/certificates/)은 외부 CA를
|
|
사용하도록 클러스터 설정에 대한 지침을 포함한다.
|
|
|
|
## 인증서 만료 확인
|
|
|
|
`check-expiration` 하위 명령을 사용하여 인증서가 만료되는 시기를 확인할 수 있다.
|
|
|
|
```
|
|
kubeadm certs check-expiration
|
|
```
|
|
|
|
출력 결과는 다음과 비슷하다.
|
|
|
|
```
|
|
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
|
|
admin.conf Dec 30, 2020 23:36 UTC 364d no
|
|
apiserver Dec 30, 2020 23:36 UTC 364d ca no
|
|
apiserver-etcd-client Dec 30, 2020 23:36 UTC 364d etcd-ca no
|
|
apiserver-kubelet-client Dec 30, 2020 23:36 UTC 364d ca no
|
|
controller-manager.conf Dec 30, 2020 23:36 UTC 364d no
|
|
etcd-healthcheck-client Dec 30, 2020 23:36 UTC 364d etcd-ca no
|
|
etcd-peer Dec 30, 2020 23:36 UTC 364d etcd-ca no
|
|
etcd-server Dec 30, 2020 23:36 UTC 364d etcd-ca no
|
|
front-proxy-client Dec 30, 2020 23:36 UTC 364d front-proxy-ca no
|
|
scheduler.conf Dec 30, 2020 23:36 UTC 364d no
|
|
|
|
CERTIFICATE AUTHORITY EXPIRES RESIDUAL TIME EXTERNALLY MANAGED
|
|
ca Dec 28, 2029 23:36 UTC 9y no
|
|
etcd-ca Dec 28, 2029 23:36 UTC 9y no
|
|
front-proxy-ca Dec 28, 2029 23:36 UTC 9y no
|
|
```
|
|
|
|
이 명령은 `/etc/kubernetes/pki` 폴더의 클라이언트 인증서와 kubeadm이 사용하는 KUBECONFIG 파일(`admin.conf`, `controller-manager.conf` 및 `scheduler.conf`)에 포함된 클라이언트 인증서의 만료/잔여 기간을 표시한다.
|
|
|
|
또한, kubeadm은 인증서가 외부에서 관리되는지를 사용자에게 알린다. 이 경우 사용자는 수동으로 또는 다른 도구를 사용해서 인증서 갱신 관리를 해야 한다.
|
|
|
|
{{< warning >}}
|
|
`kubeadm` 은 외부 CA가 서명한 인증서를 관리할 수 없다.
|
|
{{< /warning >}}
|
|
|
|
{{< note >}}
|
|
`kubelet.conf` 는 위 목록에 포함되어 있지 않은데, 이는
|
|
kubeadm이 [자동 인증서 갱신](/ko/docs/tasks/tls/certificate-rotation/)을 위해
|
|
`/var/lib/kubelet/pki`에 있는 갱신 가능한 인증서를 이용하여 kubelet을 구성하기 때문이다.
|
|
만료된 kubelet 클라이언트 인증서를 갱신하려면
|
|
[kubelet 클라이언트 갱신 실패](/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm/#kubelet-client-cert) 섹션을 확인한다.
|
|
{{< /note >}}
|
|
|
|
{{< warning >}}
|
|
kubeadm 1.17 이전의 버전에서 `kubeadm init` 으로 작성된 노드에는
|
|
`kubelet.conf` 의 내용을 수동으로 수정해야 하는 [버그](https://github.com/kubernetes/kubeadm/issues/1753)가 있다. `kubeadm init` 수행 완료 후, `client-certificate-data` 및 `client-key-data` 를 다음과 같이 교체하여,
|
|
로테이트된 kubelet 클라이언트 인증서를 가리키도록 `kubelet.conf` 를 업데이트해야 한다.
|
|
|
|
```yaml
|
|
client-certificate: /var/lib/kubelet/pki/kubelet-client-current.pem
|
|
client-key: /var/lib/kubelet/pki/kubelet-client-current.pem
|
|
```
|
|
{{< /warning >}}
|
|
|
|
## 자동 인증서 갱신
|
|
|
|
kubeadm은 컨트롤 플레인 [업그레이드](/ko/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/) 동안 모든 인증서를 갱신한다.
|
|
|
|
이 기능은 가장 간단한 유스케이스를 해결하기 위해 설계되었다.
|
|
인증서 갱신에 대해 특별한 요구 사항이 없고 쿠버네티스 버전 업그레이드를 정기적으로(매 1년 이내 업그레이드 수행) 수행하는 경우, kubeadm은 클러스터를 최신 상태로 유지하고 합리적으로 보안을 유지한다.
|
|
|
|
{{< note >}}
|
|
보안을 유지하려면 클러스터를 자주 업그레이드하는 것이 가장 좋다.
|
|
{{< /note >}}
|
|
|
|
인증서 갱신에 대해 보다 복잡한 요구 사항이 있는 경우, `--certificate-renewal=false` 를 `kubeadm upgrade apply` 또는 `kubeadm upgrade node` 와 함께 사용하여 기본 동작이 수행되지 않도록 할 수 있다.
|
|
|
|
{{< warning >}}
|
|
kubeadm 1.17 이전 버전에는 `kubeadm upgrade node` 명령에서
|
|
`--certificate-renewal` 의 기본값이 `false` 인 [버그](https://github.com/kubernetes/kubeadm/issues/1818)가
|
|
있다. 이 경우 `--certificate-renewal=true` 를 명시적으로 설정해야 한다.
|
|
{{< /warning >}}
|
|
|
|
## 수동 인증서 갱신
|
|
|
|
`kubeadm certs renew` 명령을 사용하여 언제든지 인증서를 수동으로 갱신할 수 있다.
|
|
|
|
이 명령은 `/etc/kubernetes/pki` 에 저장된 CA(또는 프론트 프록시 CA) 인증서와 키를 사용하여 갱신을 수행한다.
|
|
|
|
명령을 실행한 후에는 컨트롤 플레인 파드를 재시작해야 한다.
|
|
이는 현재 일부 구성 요소 및 인증서에 대해 인증서를 동적으로 다시 로드하는 것이 지원되지 않기 때문이다.
|
|
[스태틱(static) 파드](/ko/docs/tasks/configure-pod-container/static-pod/)는 API 서버가 아닌 로컬 kubelet에서 관리되므로
|
|
kubectl을 사용하여 삭제 및 재시작할 수 없다.
|
|
스태틱 파드를 다시 시작하려면 `/etc/kubernetes/manifests/`에서 매니페스트 파일을 일시적으로 제거하고
|
|
20초를 기다리면 된다 ([KubeletConfiguration struct](/docs/reference/config-api/kubelet-config.v1beta1/)의 `fileCheckFrequency` 값을 참고한다).
|
|
파드가 매니페스트 디렉터리에 더 이상 없는 경우 kubelet은 파드를 종료한다.
|
|
그런 다음 파일을 다시 이동할 수 있으며 또 다른 `fileCheckFrequency` 기간이 지나면,
|
|
kubelet은 파드를 생성하고 구성 요소에 대한 인증서 갱신을 완료할 수 있다.
|
|
|
|
{{< warning >}}
|
|
HA 클러스터를 실행 중인 경우, 모든 컨트롤 플레인 노드에서 이 명령을 실행해야 한다.
|
|
{{< /warning >}}
|
|
|
|
{{< note >}}
|
|
`certs renew` 는 기존 인증서를 kubeadm-config 컨피그맵(ConfigMap) 대신 속성(공통 이름, 조직, SAN 등)의 신뢰할 수 있는 소스로 사용한다. 둘 다 동기화 상태를 유지하는 것을 강력히 권장한다.
|
|
{{< /note >}}
|
|
|
|
`kubeadm certs renew` 는 다음의 옵션을 제공한다.
|
|
|
|
쿠버네티스 인증서는 일반적으로 1년 후 만료일에 도달한다.
|
|
|
|
- `--csr-only` 는 실제로 인증서를 갱신하지 않고 인증서 서명 요청을 생성하여 외부 CA로 인증서를 갱신하는 데 사용할 수 있다. 자세한 내용은 다음 단락을 참고한다.
|
|
|
|
- 모든 인증서 대신 단일 인증서를 갱신할 수도 있다.
|
|
|
|
## 쿠버네티스 인증서 API를 사용하여 인증서 갱신
|
|
|
|
이 섹션에서는 쿠버네티스 인증서 API를 사용하여 수동 인증서 갱신을 실행하는 방법에 대한 자세한 정보를 제공한다.
|
|
|
|
{{< caution >}}
|
|
조직의 인증서 인프라를 kubeadm으로 생성된 클러스터에 통합해야 하는 사용자를 위한 고급 주제이다. 기본 kubeadm 구성이 요구 사항을 충족하면 kubeadm이 인증서를 대신 관리하도록 해야 한다.
|
|
{{< /caution >}}
|
|
|
|
### 서명자 설정
|
|
|
|
쿠버네티스 인증 기관(Certificate Authority)은 기본적으로 작동하지 않는다.
|
|
[cert-manager](https://cert-manager.io/docs/configuration/ca/)와 같은 외부 서명자를 설정하거나, 빌트인 서명자를 사용할 수 있다.
|
|
|
|
빌트인 서명자는 [`kube-controller-manager`](/docs/reference/command-line-tools-reference/kube-controller-manager/)의 일부이다.
|
|
|
|
빌트인 서명자를 활성화하려면, `--cluster-signing-cert-file` 와 `--cluster-signing-key-file` 플래그를 전달해야 한다.
|
|
|
|
새 클러스터를 생성하는 경우, kubeadm [구성 파일](https://pkg.go.dev/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3)을 사용할 수 있다.
|
|
|
|
```yaml
|
|
apiVersion: kubeadm.k8s.io/v1beta3
|
|
kind: ClusterConfiguration
|
|
controllerManager:
|
|
extraArgs:
|
|
cluster-signing-cert-file: /etc/kubernetes/pki/ca.crt
|
|
cluster-signing-key-file: /etc/kubernetes/pki/ca.key
|
|
```
|
|
|
|
### 인증서 서명 요청(CSR) 생성
|
|
|
|
쿠버네티스 API로 CSR을 작성하려면 [CertificateSigningRequest 생성](/docs/reference/access-authn-authz/certificate-signing-requests/#create-certificatesigningrequest)을 본다.
|
|
|
|
## 외부 CA로 인증서 갱신
|
|
|
|
이 섹션에서는 외부 CA를 사용하여 수동 인증서 갱신을 실행하는 방법에 대한 자세한 정보를 제공한다.
|
|
|
|
외부 CA와 보다 효과적으로 통합하기 위해 kubeadm은 인증서 서명 요청(CSR)을 생성할 수도 있다.
|
|
CSR은 클라이언트의 서명된 인증서에 대한 CA 요청을 나타낸다.
|
|
kubeadm 관점에서, 일반적으로 온-디스크(on-disk) CA에 의해 서명되는 모든 인증서는 CSR로 생성될 수 있다. 그러나 CA는 CSR로 생성될 수 없다.
|
|
|
|
### 인증서 서명 요청(CSR) 생성
|
|
|
|
`kubeadm certs renew --csr-only` 로 인증서 서명 요청을 만들 수 있다.
|
|
|
|
CSR과 함께 제공되는 개인 키가 모두 출력된다.
|
|
`--csr-dir` 로 사용할 디텍터리를 전달하여 지정된 위치로 CSR을 출력할 수 있다.
|
|
`--csr-dir` 을 지정하지 않으면, 기본 인증서 디렉터리(`/etc/kubernetes/pki`)가 사용된다.
|
|
|
|
`kubeadm certs renew --csr-only` 로 인증서를 갱신할 수 있다.
|
|
`kubeadm init` 과 마찬가지로 출력 디렉터리를 `--csr-dir` 플래그로 지정할 수 있다.
|
|
|
|
CSR에는 인증서 이름, 도메인 및 IP가 포함되지만, 용도를 지정하지는 않는다.
|
|
인증서를 발행할 때 [올바른 인증서 용도](/ko/docs/setup/best-practices/certificates/#모든-인증서)를
|
|
지정하는 것은 CA의 책임이다.
|
|
|
|
* `openssl` 의 경우
|
|
[`openssl ca` 명령](https://superuser.com/questions/738612/openssl-ca-keyusage-extension)으로 수행한다.
|
|
* `cfssl` 의 경우
|
|
[설정 파일에 용도](https://github.com/cloudflare/cfssl/blob/master/doc/cmd/cfssl.txt#L170)를 지정한다.
|
|
|
|
선호하는 방법으로 인증서에 서명한 후, 인증서와 개인 키를 PKI 디렉터리(기본적으로 `/etc/kubernetes/pki`)에 복사해야 한다.
|
|
|
|
## 인증 기관(CA) 순환(rotation) {#certificate-authority-rotation}
|
|
|
|
Kubeadm은 CA 인증서의 순환이나 교체 기능을 기본적으로 지원하지 않는다.
|
|
|
|
CA의 수동 순환이나 교체에 대한 보다 상세한 정보는 [CA 인증서 수동 순환](/docs/tasks/tls/manual-rotation-of-ca-certificates/) 문서를 참조한다.
|
|
|
|
## 서명된 kubelet 인증서 활성화하기 {#kubelet-serving-certs}
|
|
|
|
기본적으로 kubeadm에 의해서 배포된 kubelet 인증서는 자가 서명된(self-signed) 것이다.
|
|
이것은 [metrics-server](https://github.com/kubernetes-sigs/metrics-server)와
|
|
같은 외부 서비스의 kubelet에 대한 연결은
|
|
TLS로 보안되지 않음을 의미한다.
|
|
|
|
제대로 서명된 인증서를 얻기 위해서 신규 kubeadm 클러스터의 kubelet을 구성하려면
|
|
다음의 최소 구성을 `kubeadm init` 에 전달해야 한다.
|
|
|
|
```yaml
|
|
apiVersion: kubeadm.k8s.io/v1beta3
|
|
kind: ClusterConfiguration
|
|
---
|
|
apiVersion: kubelet.config.k8s.io/v1beta1
|
|
kind: KubeletConfiguration
|
|
serverTLSBootstrap: true
|
|
```
|
|
|
|
만약 이미 클러스터를 생성했다면 다음을 따라 이를 조정해야 한다.
|
|
- `kube-system` 네임스페이스에서 `kubelet-config-{{< skew latestVersion >}}` 컨피그맵을 찾아서 수정한다.
|
|
해당 컨피그맵에는 `kubelet` 키가
|
|
[KubeletConfiguration](/docs/reference/config-api/kubelet-config.v1beta1/#kubelet-config-k8s-io-v1beta1-KubeletConfiguration)
|
|
문서를 값으로 가진다. `serverTLSBootstrap: true` 가 되도록 KubeletConfiguration 문서를 수정한다.
|
|
- 각 노드에서, `serverTLSBootstrap: true` 필드를 `/var/lib/kubelet/config.yaml` 에 추가한다.
|
|
그리고 `systemctl restart kubelet` 로 kubelet을 재시작한다.
|
|
|
|
`serverTLSBootstrap: true` 필드는 kubelet 인증서를 이용한 부트스트랩을
|
|
`certificates.k8s.io` API에 요청함으로써 활성화할 것이다. 한 가지 알려진 제약은
|
|
이 인증서들에 대한 CSR(인증서 서명 요청)들이 kube-controller-manager -
|
|
[`kubernetes.io/kubelet-serving`](/docs/reference/access-authn-authz/certificate-signing-requests/#kubernetes-signers)의
|
|
기본 서명자(default signer)에 의해서 자동으로 승인될 수 없다는 점이다.
|
|
이것은 사용자나 제 3의 컨트롤러의 액션을 필요로 할 것이다.
|
|
|
|
이 CSR들은 다음을 통해 볼 수 있다.
|
|
|
|
```shell
|
|
kubectl get csr
|
|
NAME AGE SIGNERNAME REQUESTOR CONDITION
|
|
csr-9wvgt 112s kubernetes.io/kubelet-serving system:node:worker-1 Pending
|
|
csr-lz97v 1m58s kubernetes.io/kubelet-serving system:node:control-plane-1 Pending
|
|
```
|
|
|
|
이를 승인하기 위해서는 다음을 수행한다.
|
|
```shell
|
|
kubectl certificate approve <CSR-name>
|
|
```
|
|
|
|
기본적으로, 이 인증서는 1년 후에 만기될 것이다. Kubeadm은
|
|
`KubeletConfiguration` 필드의 `rotateCertificates` 를 `true` 로 설정한다. 이것은 만기가
|
|
다가오면 인증서를 위한 신규 CSR 세트가 생성되는 것을 의미하며,
|
|
해당 순환(rotation)을 완료하기 위해서는 승인이 되어야 한다는 것을 의미한다. 더 상세한 이해를 위해서는
|
|
[인증서 순환](/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/#certificate-rotation)를 확인한다.
|
|
|
|
만약 이 CSR들의 자동 승인을 위한 솔루션을 찾고 있다면 클라우드 제공자와
|
|
연락하여 대역 외 메커니즘(out of band mechanism)을 통해 노드의 신분을 검증할 수 있는
|
|
CSR 서명자를 가지고 있는지 문의하는 것을 추천한다.
|
|
|
|
{{% thirdparty-content %}}
|
|
|
|
써드파티 커스텀 컨트롤러도 사용될 수 있다.
|
|
- [kubelet-csr-approver](https://github.com/postfinance/kubelet-csr-approver)
|
|
|
|
이러한 컨트롤러는 CSR의 CommonName과 요청된 IPs 및 도메인 네임을
|
|
모두 검증하지 않는 한, 보안이 되는 메커니즘이 아니다. 이것을 통해 악의적 행위자가
|
|
kubelet 인증서(클라이언트 인증)를 사용하여 아무 IP나 도메인 네임에 대해 인증서를
|
|
요청하는 CSR의 생성을 방지할 수 있을 것이다.
|
|
|
|
## 추가 사용자를 위한 kubeconfig 파일 생성하기 {#kubeconfig-additional-users}
|
|
|
|
클러스터 생성 과정에서, kubeadm은
|
|
`Subject: O = system:masters, CN = kubernetes-admin` 값이 설정되도록 `admin.conf`의 인증서에 서명한다.
|
|
[`system:masters`](/docs/reference/access-authn-authz/rbac/#user-facing-roles)는
|
|
인증 계층(예: RBAC)을 우회하는 획기적인 슈퍼유저 그룹이다.
|
|
`admin.conf`를 추가 사용자와 공유하는 것은 **권장하지 않는다**!
|
|
|
|
대신, [`kubeadm kubeconfig user`](/docs/reference/setup-tools/kubeadm/kubeadm-kubeconfig)
|
|
명령어를 사용하여 추가 사용자를 위한 kubeconfig 파일을 생성할 수 있다.
|
|
이 명령어는 명령줄 플래그와
|
|
[kubeadm 환경 설정](/docs/reference/config-api/kubeadm-config.v1beta3/) 옵션을 모두 인식한다.
|
|
생성된 kubeconfig는 stdout으로 출력되며,
|
|
`kubeadm kubeconfig user ... > somefile.conf` 명령어를 사용하여 파일에 기록될 수 있다.
|
|
|
|
다음은 `--config` 플래그와 함께 사용될 수 있는 환경 설정 파일 예시이다.
|
|
|
|
```yaml
|
|
# example.yaml
|
|
apiVersion: kubeadm.k8s.io/v1beta3
|
|
kind: ClusterConfiguration
|
|
# kubeconfig에서 타겟 "cluster"로 사용될 것이다.
|
|
clusterName: "kubernetes"
|
|
# kubeconfig에서 클러스터의 "server"(IP 또는 DNS 이름)로 사용될 것이다.
|
|
controlPlaneEndpoint: "some-dns-address:6443"
|
|
# 클러스터 CA 키 및 인증서가 이 로컬 디렉토리에서 로드될 것이다.
|
|
certificatesDir: "/etc/kubernetes/pki"
|
|
```
|
|
|
|
이러한 항목들이 사용하고자 하는 클러스터의 상세 사항과 일치하는지 확인한다.
|
|
기존 클러스터의 환경 설정을 보려면 다음 명령을 사용한다.
|
|
|
|
```shell
|
|
kubectl get cm kubeadm-config -n kube-system -o=jsonpath="{.data.ClusterConfiguration}"
|
|
```
|
|
|
|
다음 예시는 `appdevs` 그룹의 새 사용자 `johndoe`를 위해
|
|
24시간동안 유효한 인증서와 함께 kubeconfig 파일을 생성할 것이다.
|
|
|
|
```shell
|
|
kubeadm kubeconfig user --config example.yaml --org appdevs --client-name johndoe --validity-period 24h
|
|
```
|
|
|
|
다음 예시는 1주일간 유효한 관리자 크리덴셜을 갖는 kubeconfig 파일을 생성할 것이다.
|
|
|
|
```shell
|
|
kubeadm kubeconfig user --config example.yaml --client-name admin --validity-period 168h
|
|
```
|