cert-manager, Traefik 및 Let’s Encrypt를 사용하여 Kubernetes에서 사이트를 보호하는 방법
저자는 Write for DOnations 프로그램을 선택했습니다.
소개
트래픽을 보호하기 위한 TLS. 그러나 TLS 인증서 획득에서 해당 인증서를 적시에 갱신하고 이를 사용하도록 서버를 구성하는 데 이르기까지 TLS 기반 사이트를 호스팅하는 데 필요한 모든 이동 부분을 관리하는 것은 어려울 수 있습니다.
다행스럽게도 Kubernetes 클러스터에서 실행하여 이러한 많은 복잡성을 관리할 수 있는 서비스가 있습니다. 무료 자동 보안 인증서 제공업체인 Let’s Encrypt를 사용하면 일반적으로 초기 설정만 수행하면 되는 수준까지 인증서 관리 부담을 줄일 수 있습니다.
이 자습서에서는 Kubernetes 클러스터에서 cert-manager, Traefik 및 Let’s Encrypt를 예제 웹사이트 서비스와 함께 설정하여 웹사이트에서 자동으로 보안 인증서를 획득, 갱신 및 사용합니다.
전제 조건
kubectl
로 액세스할 수 있는 Kubernetes 클러스터. 클러스터를 생성해야 하는 경우 DigitalOcean에는 Kubernetes Quickstart가 있습니다.- 클러스터와 상호 작용하기 위한 최신 버전의
kubectl
. Linux, MacOS 및 Windows에kubectl
을 설치하는 방법은 제품 설명서를 참조하세요. doctl
이 설치 및 구성된 DigitalOcean 계정. 이를 설정하려면 doctl 설치 및 구성 방법에 대한 제품 설명서를 참조하십시오.- Helm 설치.
kubectl
을 사용하여 Kubernetes 클러스터와 상호작용하는 경험을 해보세요. 시작하려면 첫 번째 클러스터에 첫 번째 이미지 빌드 및 배포 자습서를 따르십시오.- 등록된 도메인 이름. 이 자습서에서는
your_domain
을 사용합니다. Freenom에서 도메인 이름을 구입하거나 선택한 도메인 등록 기관을 사용할 수 있습니다. - 도메인 이름에 대한 DNS 설정. 이 자습서에서는 DigitalOcean DNS를 사용한다고 가정하지만 필수 사항은 아닙니다. DigitalOcean을 사용하는 경우 공통 도메인 등록 기관에서 DigitalOcean DNS를 사용하는 방법에 대한 정보는 공통 도메인 등록 기관에서 DigitalOcean 이름 서버를 가리키는 방법을 참조하십시오.
- DNS에 DigitalOcean을 사용하는 경우 DigitalOcean DNS에 대한 읽기 및 쓰기 액세스 권한이 있는 개인 액세스 토큰. 다른 공급자도 비슷한 액세스 토큰을 갖습니다.
1단계 - 클러스터에서 cert-manager 설정
일반적으로 웹 사이트에 대한 보안 인증서를 설정할 때 인증서를 생성하려면 인증 기관을 생성해야 합니다. 그런 다음 해당 인증서를 사용하도록 웹 서버를 구성하고 매년 동일한 프로세스를 거쳐 인증서를 최신 상태로 유지해야 합니다.
그러나 인증서의 수명 주기를 자동으로 관리하는 Kubernetes에서 실행되도록 설계된 서비스인 cert-manager가 생성되었습니다.
이 섹션에서는 자체 cert-manager
네임스페이스의 클러스터에서 실행되도록 cert-manager를 설정합니다.
먼저 cert-manager의 릴리스 파일과 함께 kubectl
을 사용하여 cert-manager를 설치합니다.
- kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.yaml
기본적으로 cert-manager는 cert-manager
라는 자체 네임스페이스에 설치됩니다. 파일이 적용되면 클러스터에 여러 리소스가 생성되어 출력에 표시됩니다(일부 출력은 길이로 인해 제거됨).
Outputnamespace/cert-manager created
customresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io created
# some output excluded
deployment.apps/cert-manager-cainjector created
deployment.apps/cert-manager created
deployment.apps/cert-manager-webhook created
mutatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created
validatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created
이 섹션에서는 보안 인증서를 관리하기 위해 cert-manager를 설치했습니다. 이제 인증서 발급 방법을 cert-manager에 알리는 방법을 설정해야 합니다. 다음 섹션에서는 클러스터에서 Let’s Encrypt 발급자를 설정합니다.
2단계 - Let’s Encrypt 인증서 발급자 구성
웹사이트에 보안 인증서를 사용하는 것은 사용자에게 보고 있는 사이트가 귀하의 서버에서 온 것임을 신뢰할 수 있음을 알리는 방법입니다. 이를 위해 인증 기관은 귀하가 인증서의 대상 도메인을 소유하고 있음을 확인해야 합니다. Let’s Encrypt는 DigitalOcean의 DNS 공급자와 함께 DNS-01 챌린지라는 표준을 사용하여 이를 수행합니다.
이 섹션에서는 클러스터에 대한 ClusterIssuer
를 생성하여 cert-manager에게 Let’s Encrypt에서 인증서를 발급하는 방법과 Let’s Encrypt에 필요한 DNS 챌린지를 완료하는 데 사용할 자격 증명을 알려줍니다.
참고: 이 자습서에서는 DNS 공급자에 DigitalOcean을 사용하고 있다고 가정하고 해당 가정으로 ClusterIssuer
를 구성합니다. cert-manager는 HTTP 및 DNS 챌린지에 대해 다양한 클라우드 공급자를 지원하므로 동일한 개념을 적용할 수 있습니다.
cert-manager에서 지원하는 다른 공급자에 대한 자세한 내용은 cert-manager 설명서의 ACME 소개를 참조하십시오.
클러스터에 대한 ClusterIssuer
를 만들기 전에 클러스터 구성을 위한 디렉터리를 만들어야 합니다. mkdir
명령을 사용하여 디렉토리를 만든 다음 cd
를 사용하여 해당 디렉토리에 들어갑니다.
- mkdir tutorial-cluster-config
- cd tutorial-cluster-config
디렉터리를 만든 후에는 이 자습서의 전제 조건의 일부로 만든 DNS 액세스용 개인 액세스 토큰이 필요합니다. DigitalOcean 액세스 토큰은 긴 숫자 문자열이 있는 dop_v1_4321...
와 유사하게 보입니다.
Kubernetes에서 액세스 토큰을 비밀로 저장하려면 이를 base-64로 인코딩해야 합니다. 이렇게 하려면 echo
명령을 사용하여 토큰을 base64
명령으로 파이프하고 강조 표시된 부분을 액세스 토큰으로 바꿉니다.
- echo -n 'dop_v1_4321...' | base64
이 명령은 액세스 토큰을 echo
에서 base64
명령으로 전송하여 인코딩합니다. -n
옵션은 끝에 새 줄이 포함되지 않도록 합니다. 액세스 토큰에 따라 다음과 유사한 출력을 받게 됩니다.
OutputZG9wX3YxX3RoaXNpc25vdGFyZWFsdG9rZW5idXRpbXB1dHRpbmdhYnVuY2hvZnN0dWZmaW5oZXJlc29sZW5ndGhzbWF0Y2g=
이 출력은 base-64로 인코딩된 액세스 토큰입니다. 다음에 사용할 것이기 때문에 이것을 복사하십시오.
nano
또는 좋아하는 편집기를 사용하여 lets-encrypt-do-dns.yaml
이라는 새 파일을 만들고 엽니다.
- nano lets-encrypt-do-dns.yaml
다음 코드를 추가하여 Kubernetes Secret
을 생성합니다. access-token
필드에 base-64로 인코딩된 액세스 토큰을 사용해야 합니다.
apiVersion: v1
kind: Secret
metadata:
namespace: cert-manager
name: lets-encrypt-do-dns
data:
access-token: ZG9wX3Y...
이 비밀
은 lets-encrypt-do-dns
라고 하며 네임스페이스 cert-manager
에 저장됩니다. data
섹션에서 이전에 생성한 base-64로 인코딩된 access-token
을 포함합니다. 이 시크릿은 Let’s Encrypt 발급자를 생성할 때 참조할 액세스 토큰을 안전하게 저장합니다.
다음으로 파일을 저장하고 kubectl apply
를 사용하여 클러스터에 적용합니다.
- kubectl apply -f lets-encrypt-do-dns.yaml
출력에서 클러스터에 비밀이 생성되었다는 메시지를 받게 됩니다.
Outputsecret/lets-encrypt-do-dns created
이제 Let’s Encrypt 인증서를 발급하는 데 사용할 cert-manager의 ClusterIssuer
를 포함할 lets-encrypt-issuer.yaml
이라는 새 파일을 만듭니다.
- nano lets-encrypt-issuer.yaml
spec.acme.email
필드에 이메일 주소를 입력하여 다음 줄을 추가합니다(이 주소는 Let’s Encrypt가 제공하는 인증서와 연결됩니다).
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-issuer
spec:
acme:
email: your_email_address
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-issuer-account-key
solvers:
- selector: {}
dns01:
digitalocean:
tokenSecretRef:
name: lets-encrypt-do-dns
key: access-token
처음 두 줄에서 apiVersion
및 kind
는 이 Kubernetes 리소스가 cert-manager ClusterIssuer
임을 나타냅니다. 다음으로 이름을 letsencrypt-issuer
로 지정합니다. 이 경우 리소스가 클러스터
리소스이기 때문에 네임스페이스
필드를 포함하지 않았습니다. 즉, 단일 네임스페이스가 아닌 전체 클러스터에 적용됩니다.
다음으로 spec
섹션에서 acme
챌린지 섹션을 정의하여 cert-manager에게 이 ClusterIssuer
가 ACME를 사용하여 <letsencrypt-issuer. 이메일
은 Let’s Encrypt가 문제가 있고 cert-manager가 제때 갱신하지 않는 경우 갱신 알림과 같은 인증서 관련 통신을 보낼 이메일 주소입니다. server
필드는 ACME 챌린지를 요청하기 위해 연락할 URL을 지정하고 프로덕션 Let’s Encrypt URL로 설정됩니다. server
필드 뒤에 privateKeySecretRef
필드를 cert-manager가 클러스터에 대해 생성된 개인 키를 저장하는 데 사용할 비밀 이름과 함께 포함합니다.
spec.acme
섹션에서 가장 중요한 섹션 중 하나는 solvers
섹션입니다. 이 섹션에서는 letsencrypt-issuer
에 사용할 ACME 챌린지 해결 프로그램을 구성합니다. 이 경우 단일 해결사인 dns01
해결사를 포함합니다. 솔버 구성의 첫 번째 부분인 selector
는 "무엇이든\을 의미하는 {}
로 구성됩니다. 클러스터의 다른 인증서에 대해 다른 솔버를 사용하려는 경우 동일한 발급자에서 추가 선택기를 설정할 수 있습니다.이 작업을 수행하는 방법에 대한 자세한 내용은 cert-manager의 ACME 소개에서 찾을 수 있습니다.
dns01
섹션 안에 digitalocean
섹션을 추가하여 이 발급자가 DigitalOcean을 DNS-01 솔버로 사용해야 한다고 말합니다. 다른 클라우드 공급자를 사용하는 경우 여기에서 다른 공급자를 구성합니다. 이 섹션 안에 tokenSecretRef
를 포함하여 Secret<의
이전에 생성했습니다. cert-manager는 사용자를 대신하여 DNS 레코드를 생성할 때 이 액세스 토큰을 사용합니다.lets-encrypt-do-dns
access-token
필드를 참조합니다.
발급자 파일을 저장했으면 kubectl apply
를 사용하여 클러스터에 적용합니다.
- kubectl apply -f lets-encrypt-issuer.yaml
출력에서 letsencrypt-issuer
라는 이름의 ClusterIssuer
가 생성되었음을 확인할 수 있습니다.
Outputclusterissuer.cert-manager.io/letsencrypt-issuer created
이 섹션에서는 cert-manager를 설정하고 Let’s Encrypt에서 인증서를 발급하도록 구성했습니다. 그러나 인증서가 요청되지 않고 웹 사이트를 제공하지 않으며 클러스터에서 실행 중인 웹 사이트 서비스가 없습니다. 다음 섹션에서는 Traefik을 외부 세계와 웹 사이트 간의 프록시로 설정합니다.
3단계 - Traefik과 함께 로드 밸런서 사용
로드 밸런서는 네트워크 연결을 수락하고 다른 Traefik 인스턴스로 전송하여 사실상 네트워크 트래픽 부하를 분산시킵니다.
이 섹션에서는 클러스터에 Traefik을 설치하고 cert-manager에서 관리하는 인증서와 5단계에서 추가할 웹사이트와 함께 사용할 준비를 합니다. 또한 로드 밸런서를 설정하여 들어오는 클러스터 외부에서 Traefik 서비스로의 네트워크 트래픽은 물론 실행하도록 선택한 경우 Traefik의 여러 인스턴스를 처리할 수 있도록 준비합니다.
먼저 Traefik을 설치할 traefik
이라는 네임스페이스를 만듭니다. 이렇게 하려면 traefik-ns.yaml
이라는 파일을 엽니다.
- nano traefik-ns.yaml
Kubernetes 네임스페이스
리소스를 입력합니다.
apiVersion: v1
kind: Namespace
metadata:
name: traefik
파일을 저장한 후 kubectl apply
를 사용하여 클러스터에 적용합니다.
- kubectl apply -f traefik-ns.yaml
명령이 실행되면 클러스터의 출력에서 네임스페이스가 생성되었음을 확인할 수 있습니다.
Outputnamespace/traefik created
traefik
네임스페이스를 만든 후 Traefik 서비스 자체를 설치합니다. 이를 위해 chart라는 유틸리티를 사용합니다.
먼저 사용 가능한 리포지토리에 traefik
Helm 리포지토리를 추가해야 합니다. 그러면 Helm이 traefik
패키지를 찾을 수 있습니다.
- helm repo add traefik https://helm.traefik.io/traefik
명령이 완료되면 traefik
리포지토리가 컴퓨터의 Helm 리포지토리에 추가되었다는 확인 메시지가 표시됩니다.
Output"traefik" has been added to your repositories
다음으로 차트 리포지토리를 업데이트합니다.
- helm repo update
출력에서 traefik
차트 리포지토리가 업데이트되었음을 확인할 수 있습니다.
OutputHang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "traefik" chart repository
Update Complete. ⎈Happy Helming!⎈
마지막으로 클러스터에서 생성한 traefik
네임스페이스에 traefik
을 설치합니다.
- helm install --namespace=traefik traefik traefik/traefik
이 명령에는 많은 traefik
이 있으므로 각각의 기능을 살펴보겠습니다. 명령의 첫 번째 traefik
(--namespace=traefik
포함)은 이전에 생성한 traefik
네임스페이스에 Traefik을 설치하도록 Helm에 지시합니다. 다음으로 강조 표시된 traefik은 클러스터에서 이 Traefik 설치에 제공하려는 이름입니다. 이렇게 하면 동일한 클러스터에 Traefik이 여러 개 설치되어 있는 경우 traefik-website1
및 traefik-website2
와 같이 서로 다른 이름을 지정할 수 있습니다. 현재 클러스터에 Traefik 설치가 하나만 있으므로 traefik
이름을 사용할 수 있습니다. 세 번째 traefik/
는 이전에 추가하고 설치하려는 리포지토리입니다. 마지막으로 마지막 traefik
은 설치하려는 차트의 이름입니다.
명령을 실행하면 다음과 유사한 출력이 화면에 인쇄됩니다.
NAME: traefik
LAST DEPLOYED: Sun Oct 2 16:32:57 2022
NAMESPACE: traefik
STATUS: deployed
REVISION: 1
TEST SUITE: None
Helm 차트가 설치되면 Traefik이 클러스터에서 다운로드를 시작합니다. Traefik이 실행 중인지 확인하려면 kubectl get all
을 실행하여 traefik
네임스페이스에서 생성된 모든 Traefik 리소스를 확인합니다.
- kubectl get -n traefik all
출력은 아래 출력과 유사하게 나타납니다.
OutputNAME READY STATUS RESTARTS AGE
pod/traefik-858bb8459f-k4ztp 1/1 Running 0 94s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/traefik LoadBalancer 10.245.77.251 <pending> 80:31981/TCP,443:30188/TCP 94s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/traefik 1/1 1 1 94s
NAME DESIRED CURRENT READY AGE
replicaset.apps/traefik-858bb8459f 1 1 1 94s
클러스터에 따라 그리고 이전 명령을 실행한 시기에 따라 일부 이름과 연령이 다를 수 있습니다. service/traefik
의 EXTERNAL-IP
아래에
가 표시되면 를 계속 실행합니다. IP 주소가 나열될 때까지 kubectl get -n traefik all
명령. EXTERNAL-IP
는 로드 밸런서를 인터넷에서 사용할 수 있는 IP 주소입니다. IP 주소가 나열되면 해당 IP 주소를 traefik_ip_address
로 기록해 둡니다. 다음 섹션에서 이 주소를 사용하여 도메인을 설정합니다.
이 섹션에서는 클러스터에 Traefik을 설치했으며 웹 사이트 트래픽을 보낼 수 있는 EXTERNAL-IP
가 있습니다. 다음 섹션에서는 도메인에서 로드 밸런서로 트래픽을 전송하도록 DNS를 변경합니다.
4단계 - 도메인으로 Traefik에 액세스
이제 클러스터에 Traefik을 설정하고 로드 밸런서를 통해 인터넷에서 액세스할 수 있으므로 Traefik 로드 밸런서를 가리키도록 도메인의 DNS를 업데이트해야 합니다. 계속하기 전에 도메인이 DigitalOcean 계정에 추가되었는지 확인하십시오. cert-manager는 이전에 설정한 액세스 토큰을 사용하여 도메인의 DNS 설정을 업데이트할 수 있어야 합니다. doctl
을 사용하여 Traefik의 로드 밸런서를 가리키도록 도메인의 DNS 레코드를 설정합니다.
참고: 이 섹션에서는 DigitalOcean을 DNS 호스트로 사용한다고 가정합니다. DigitalOcean 이외의 DNS 호스트를 사용하는 경우에도 동일한 값으로 동일한 DNS 레코드 유형을 생성하지만 이를 추가하는 방법은 DNS 호스트의 설명서를 참조해야 합니다.
먼저 traefik_ip_address를 가리키는
:tutorial-proxy.your_domain
도메인에 대한 DNS A
레코드를 만듭니다. 마크>
- doctl compute domain records create your_domain --record-name tutorial-proxy --record-type A --record-data traefik_ip_address
DNS A
레코드는 지정된 호스트 이름이 특정 IP 주소를 가리키도록 DNS에 지시합니다. 이 경우 tutorial-proxy.your_domain
은 traefik_ip_address
를 가리킵니다. 따라서 누군가 tutorial-proxy.your_domain
에서 웹사이트를 요청하면 DNS 서버는 traefik_ip_address
로 안내합니다. .
명령을 실행하면 레코드가 생성되었다는 확인 메시지가 표시됩니다.
OutputID Type Name Data Priority Port TTL Weight
12345678 A tutorial-proxy traefik_ip_address 0 0 1800 0
이제 tutorial-service.your_domain
이라는 CNAME
유형 DNS 레코드를 만들고 tutorial-proxy.로 지정합니다. your_domain
. 어느 시점에 클러스터에서 여러 서비스가 실행될 가능성이 있으므로 A
레코드를 사용하여 각 도메인을 Traefik 프록시로 지정하는 것은 프록시의 IP를 변경해야 하는 경우 많은 작업이 될 수 있습니다. 주소. CNAME
을 사용하면 DNS가 가리키는 도메인의 주소를 사용합니다. 이 경우 도메인은 tutorial-proxy.your_domain
이므로 새 IP를 가리키도록 하나의 A
레코드만 업데이트하면 됩니다. 여러 A
레코드 대신 주소.
CNAME
레코드를 생성하려면 doctl
명령을 다시 사용하십시오. --record-data
에 후행 마침표(.
)를 포함해야 합니다.
- doctl compute domain records create your_domain --record-name tutorial-service --record-type CNAME --record-data tutorial-proxy.your_domain.
이렇게 하면 tutorial-service.your_domain
CNAME
tutorial-proxy.your_domain을 가리키는 DNS 레코드가 생성됩니다.
. 이제 누군가 tutorial-service.your_domain
을 요청하면 DNS 서버는 IP 주소 tutorial-proxy.your_domain
에 연결하라고 알려줍니다. mark가 가리키고 있습니다. --record-data
의 후행 .
는 DNS 서버에 제공되는 도메인의 끝이며 끝에 다른 정보를 추가해서는 안 된다는 것을 알려줍니다. 마침표(.
)가 문장을 끝내는 데 사용되는 방식과 비슷합니다.
명령을 실행하면 다음과 유사한 출력이 표시됩니다.
OutputID Type Name Data Priority Port TTL Weight
12345679 CNAME tutorial-service tutorial-proxy.your_domain 0 0 1800 0
DigitalOcean은 기본 DNS 서버이므로 인터넷의 다른 DNS 서버가 업데이트될 때까지 기다리지 않고 서버에 직접 쿼리하여 서버가 올바르게 설정되었는지 확인할 수 있습니다. 설정이 DNS 서버를 통해 올바르게 전달되는지 확인하려면 dig
명령을 사용하여 DigitalOcean의 기본 DNS 서버인 ns1.linux-console.net
에서 레코드가 다음과 같아야 한다고 생각하는지 확인합니다.
참고: DigitalOcean 이외의 DNS 호스트를 사용하는 경우 이 명령의 ns1.linux-console.net
을 DNS 호스트가 도메인에 설정한 DNS 서버 중 하나로 바꿉니다.
- dig @ns1.linux-console.net +noall +answer +domain=your_domain tutorial-proxy tutorial-service
Dig를 사용하여 DNS 정보 검색
다음으로 +domain=your_domain
을 사용하여 dig
가 .your_domain
을 명령에 제공된 호스트 이름의 끝. 마지막으로 tutorial-proxy
및 tutorial-service
는 조회할 호스트 이름입니다. +domain
옵션을 사용하고 있으므로 tutorial-proxy.your_domain
전체 구문을 사용할 필요가 없습니다. 마지막에 자동으로 추가됩니다.
your_domain
및 traefik_ip_address
에 대한 자체 값을 사용하여 다음과 유사한 출력을 수신해야 합니다.
Outputtutorial-proxy.your_domain. 1662 IN A traefik_ip_address
tutorial-service.your_domain. 1800 IN CNAME tutorial-proxy.your_domain.
tutorial-proxy.your_domain. 1800 IN A traefik_ip_address
출력의 첫 번째 줄은 tutorial-proxy.your_domain
이 A
(IN A
) 레코드임을 보여줍니다. traefik_ip_address
를 가리킵니다. 두 번째는 tutorial-service.your_domain
이 CNAME
(IN CNAME
) 레코드임을 확인합니다. >tutorial-proxy.your_domain. 마지막 줄은 CNAME
레코드가 가리키는 주소를 찾기 위해 실행하는 쿼리 dig
입니다. tutorial-proxy.your_domain
이므로 이전과 동일한 A
레코드 IP 주소를 표시합니다.
이 섹션에서는 브라우저와 같은 네트워크 클라이언트가 어디로 가야 하는지 알 수 있도록 A
유형 DNS 레코드와 CNAME
유형 DNS 레코드를 도메인에 추가했습니다. Traefik 서비스에 연결하십시오. 다음 섹션에서는 클러스터에 임시 웹 서버를 설정하여 구성을 완료합니다.
5단계 - 웹 서비스 만들기
이전 섹션에서는 웹 사이트의 보안 인증서를 처리하고 웹 트래픽을 웹 서비스로 라우팅하도록 cert-manager 및 Traefik을 설정했습니다. 하지만 이 시점에서는 트래픽을 보낼 웹 서비스가 없습니다. 이 섹션에서는 Nginx 웹 서버를 사용하여 클러스터에서 호스팅할 웹 사이트를 시뮬레이션합니다.
웹사이트를 시뮬레이션하기 위해 nginx
Docker 이미지를 사용하여 배포
를 설정합니다. Nginx "Welcome!\만 표시됩니다. 페이지에 있지만 모든 것이 올바르게 연결되고 예상대로 작동하는지 확인하기에 충분합니다.
먼저 tutorial-service.yaml
이라는 파일을 만듭니다.
- nano tutorial-service.yaml
tutorial
이라는 네임스페이스
와 tutorial-service
라는 배포
를 생성하는 다음 코드를 추가합니다.
apiVersion: v1
kind: Namespace
metadata:
name: tutorial
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: tutorial
name: tutorial-service
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: tutorial-service
app.kubernetes.io/part-of: tutorial
template:
metadata:
labels:
app.kubernetes.io/name: tutorial-service
app.kubernetes.io/part-of: tutorial
spec:
containers:
- name: service
image: nginx
ports:
- containerPort: 80
이전에 생성한 traefik
네임스페이스와 유사하게 이 파일의 첫 번째 리소스는 클러스터에 tutorial
이라는 이름의 새 네임스페이스를 생성합니다. 다음 리소스인 tutorial-service
배포
는 클러스터에서 실행 중인 웹 사이트의 복제본 3개를 지정하므로 하나가 충돌하더라도 다른 두 개는 남게 됩니다. 세 번째가 돌아올 때까지.
다음 섹션인 selector
는 이 Deployment
와 관련된 포드를 찾는 방법을 Kubernetes에 알려줍니다. 이 경우 레이블이 일치하는 포드를 찾습니다. 템플릿
섹션에서 각 포드의 모양을 정의합니다. metadata
섹션은 selector
에서 일치할 레이블을 제공하고 spec
은 service
는 nginx
이미지를 사용하고 포트 80
에서 네트워크 연결을 수신 대기합니다.
변경 사항을 저장했으면 클러스터에 적용합니다.
- kubectl apply -f tutorial-service.yaml
출력은 tutorial
네임스페이스와 tutorial-service
배포가 생성되었음을 확인합니다.
Outputnamespace/tutorial created
deployment.apps/tutorial-service created
배포가 실행 중인지 확인하려면 kubectl get pods
명령을 사용하여 tutorial
네임스페이스에서 실행 중인 포드를 나열할 수 있습니다.
- kubectl get -n tutorial pods
다음과 유사한 출력이 인쇄됩니다.
OutputNAME READY STATUS RESTARTS AGE
tutorial-service-568b4f8477-hpstl 1/1 Running 0 2m15s
tutorial-service-568b4f8477-mcpqd 1/1 Running 0 2m15s
tutorial-service-568b4f8477-mg8mb 1/1 Running 0 2m15s
Running
의 STATUS
와 tutorial-service-
다음에 임의의 이름이 있는 세 개의 포드 목록을 찾아야 합니다. AGE
는 kubectl apply
와 kubectl get
명령 실행 사이에 경과된 시간에 따라 달라집니다.
이제 웹 서비스가 시작되어 실행 중이므로 세 개의 팟(Pod) 모두에서 트래픽을 전송할 방법이 필요합니다. Kubernetes에서는 이를 위해 Service
를 사용합니다. Service
로 전송되는 모든 트래픽은 Service
가 가리키는 다양한 포드 간에 부하 분산됩니다.
Service
를 생성하려면 tutorial-service.yaml
파일을 다시 열고 끝에 Service
를 추가하세요.
...
- name: service
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
namespace: tutorial
name: tutorial-service
spec:
selector:
app.kubernetes.io/name: tutorial-service
app.kubernetes.io/part-of: tutorial
ports:
- protocol: TCP
port: 80
targetPort: 80
Deployment
와 유사하게 Service
에는 트래픽을 보내려는 포드를 찾기 위한 레이블을 나열하는 selector
섹션이 있습니다. 이러한 레이블은 배포
의 포드 템플릿
섹션에 포함된 레이블과 일치합니다. 서비스
에는 또한 포트
섹션에 나열된 하나의 포트가 있으며, 이는 포트: 80
의 포트: 80
으로 전송된 모든 TCP
트래픽을 말합니다. 서비스는 로드 밸런서가 선택한 포드의 targetPort: 80
으로 전송되어야 합니다.
변경 사항을 저장한 후 클러스터에 서비스
를 적용합니다.
- kubectl apply -f tutorial-service.yaml
이번에는 출력에서 네임스페이스와 배포가 변경되지 않음
으로 나열되고(변경하지 않았기 때문에) tutorial-service
가 되었습니다. 생성
:
Outputnamespace/tutorial unchanged
deployment.apps/tutorial-service unchanged
service/tutorial-service created
tutorial-service
가 생성되면 kubectl port-forward
명령을 사용하여 로컬 컴퓨터에서 서비스를 사용할 수 있도록 하여 서비스에 액세스할 수 있는지 테스트할 수 있습니다.
- kubectl port-forward -n tutorial service/tutorial-service 8888:80
이 명령은 로컬 컴퓨터의 포트 8888
로 전송된 모든 트래픽을 클러스터에 있는 tutorial-service
의 포트 80
으로 전달합니다. Kubernetes 클러스터에서 포트 80
에서 연결을 수신하도록 tutorial-service
Service
를 설정하고 트래픽을 보낼 방법이 필요합니다. 로컬 컴퓨터에서 클러스터의 해당 서비스로. 명령에서 tutorial
네임스페이스의 service/tutorial-service
로 port-forward
하도록 지정하고 다음 조합을 제공합니다. 포트 8888:80
. 나열된 첫 번째 포트는 로컬 컴퓨터가 수신할 포트이고 두 번째 포트(:
다음)는 트래픽이 수신되는 service/tutorial-service
의 포트입니다. 전송됩니다. 로컬 컴퓨터의 포트 8888
로 트래픽을 보내면 모든 트래픽이 service/tutorial-service
의 포트 80
으로 보내지고 궁극적으로 service/tutorial-service
가 가리키는 포드에 연결됩니다.
명령을 실행하면 다음과 유사한 출력이 표시됩니다.
OutputForwarding from 127.0.0.1:8888 -> 80
Forwarding from [::1]:8888 -> 80
명령이 반환되지 않고 계속 실행되어 트래픽을 전달합니다.
서비스에 대해 요청하려면 컴퓨터에서 두 번째 터미널을 열고 포트 8888
에서 컴퓨터에 curl
명령을 사용합니다.
- curl http://localhost:8888/
이 명령은 전달된 포트(8888
)를 통해 클러스터의 tutorial-service
로 HTTP 요청을 만들고 Nginx 시작 페이지가 포함된 HTML 응답을 반환합니다.
Output<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
원래 터미널에서 이제 CONTROL+C
를 눌러 port-forward
명령을 중지할 수 있습니다. 또한 curl
연결을 만들 때 추가 출력이 표시됩니다.
OutputForwarding from 127.0.0.1:8888 -> 80
Forwarding from [::1]:8888 -> 80
Handling connection for 8888
이 섹션에서는 배포
및 서비스
를 사용하여 클러스터에 nginx
웹 서비스를 설정합니다. 그런 다음 curl
명령과 함께 kubectl port-forward
를 사용하여 nginx
가 올바르게 실행되는지 확인했습니다. 이제 cert-manager, Traefik 및 서비스가 설정되었으므로 다음 섹션에서 모두 함께 가져오고 cert-manager 및 Traefik을 사용하여 인터넷에서 HTTPS를 통해 서비스를 사용할 수 있도록 합니다.
6단계 - 웹 서비스를 사용 가능하고 안전하게 만들기
클러스터에서 실행 중인 모든 개별 서비스가 있지만 모두 상대적으로 독립적으로 실행됩니다. cert-manager는 그냥 거기에 있고 Traefik은 서비스해야 하는 사이트에 대해 알지 못하며 Nginx 웹사이트는 클러스터로 포워딩하는 경우에만 사용할 수 있습니다. 이 섹션에서는 Ingress
리소스를 만들어 모든 서비스를 연결합니다.
먼저 tutorial-service.yaml
을 다시 엽니다.
- nano tutorial-service.yaml
이전에 추가한 tutorial-service
Service
다음에 파일 끝에 Ingress
를 추가합니다. 자신의 도메인 이름으로 구성을 업데이트하고 처음에 ---
를 포함하여 Ingress
리소스를 Service
리소스에서 분리해야 합니다. 그 위에:
...
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tutorial-service-ingress
namespace: tutorial
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
cert-manager.io/cluster-issuer: letsencrypt-issuer
spec:
rules:
- host: tutorial-service.your_domain
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: tutorial-service
port:
number: 80
tls:
- secretName: tutorial-service-cert
hosts:
- tutorial-service.your_domain
이 줄에는 모든 것을 함께 맞추는 방법을 알려주는 규칙과 주석이 포함되어 있습니다. Ingress
리소스에는 Traefik, cert-manager 및 tutorial-service
에 대한 참조가 포함되어 있습니다. annotations
섹션에는 몇 가지 다르지만 중요한 주석이 포함되어 있습니다.
traefik.ingress.kubernetes.io/router.entrypoints
주석은 Traefik에게 이 Ingress
에 대한 트래픽이 websecure
진입점을 통해 사용 가능해야 한다고 알려줍니다. 이것은 Helm 차트가 기본적으로 HTTPS 트래픽을 처리하도록 구성하고 HTTPS의 기본값인 traefik_ip_address
포트 443
에서 수신하는 진입점입니다.
다음 주석인 traefik.ingress.kubernetes.io/router.tls
는 true
로 설정되어 Traefik에게 HTTP 트래픽이 아닌 HTTPS 트래픽에만 응답하도록 지시합니다. 민감한 데이터를 처리하려면 웹 사이트가 안전해야 하므로 사용자가 실수로 안전하지 않은 버전을 사용하는 것을 원하지 않습니다.
마지막 주석인 cert-manager.io/cluster-issuer
는 letsencrypt-issuer
로 설정되어 보안 인증서를 발급할 때 사용할 발급자를 cert-manager에 알립니다. 이 인그레스
에 대해. 이 시점에서 letsencrypt-issuer
는 사용자가 구성한 유일한 발급자이지만 나중에 더 추가하고 사이트마다 다른 발급자를 사용할 수 있습니다.
Ingress
spec.rules
섹션에서 Ingress
로 전송되는 트래픽을 라우팅하기 위한 하나의 규칙을 포함합니다. tutorial-service.your_domain
이라는 호스트
에 대해 지정된 paths<에 대해
http
를 사용한다고 말합니다. /코드>. 포함된 유일한 path
는 Prefix
의 pathType
이 있는 루트 /
경로입니다. 제공된 백엔드
로 전송됩니다. backend
섹션은 이것이 service
라고 말하고 트래픽을 보내야 하는 서비스는 tutorial-service
Service
입니다. 이전에 생성했으며 해당 트래픽은 Service
의 포트 80
으로 전송되어야 합니다.
Ingress
의 spec.tls
섹션은 cert-manager가 보안 인증서를 요청하고 발급하는 데 필요한 정보와 Traefik이 해당 인증서를 사용하는 데 필요한 정보를 제공합니다. secretName
은 cert-manager가 발급된 보안 인증서를 넣을 Kubernetes Secret
이고 Traefik이 발급된 인증서를 로드하는 데 사용할 Secret
입니다. hosts
섹션에는 cert-manager가 인증서를 요청할 호스트 이름이 나열됩니다. 이 경우 tutorial-service.your_domain
호스트 이름만 해당되지만 사이트가 여러 호스트 이름에 응답하도록 하려면 소유한 다른 호스트 이름을 포함할 수도 있습니다. .
생성한 Ingress
를 저장한 후 kubectl apply
를 다시 사용하여 새 리소스를 클러스터에 적용합니다.
- kubectl apply -f tutorial-service.yaml
Ingress
는 생성
되고 다른 리소스는 변경되지 않은
상태로 유지됩니다.
Outputnamespace/tutorial unchanged
deployment.apps/tutorial-service unchanged
service/tutorial-service unchanged
ingress.networking.k8s.io/tutorial-service-ingress created
Ingress
가 생성되면 Traefik은 자체 구성을 시작하고 cert-manager는 인증서를 발급하기 위해 시도/응답 프로세스를 시작합니다. 이 작업은 몇 분 정도 걸릴 수 있으므로 튜토리얼
네임스페이스에서 인증서
를 검토하여 인증서가 발급되었는지 확인할 수 있습니다.
- kubectl get -n tutorial certificates
다음과 유사한 출력이 표시됩니다.
OutputNAME READY SECRET AGE
tutorial-service-cert False tutorial-service-cert 12m
READY
필드가 False
이면 인증서가 아직 발급되지 않은 것입니다. 동일한 명령을 계속 실행하여 True
로 바뀌는 것을 지켜볼 수 있습니다. 발행하는 데 시간이 다소 걸릴 수 있지만 몇 분 이상 걸리는 경우 구성에 문제가 있음을 의미할 수 있습니다.
참고: 10~15분 후에도 인증서가 발급되지 않으면 cert-manager의 로그 메시지를 확인하여 인증서 요청에 문제가 있는지 확인하는 것이 도움이 될 수 있습니다. 이러한 로그를 보려면 다음 명령을 사용하여 로그를 보고 CONTRL+C
를 눌러 추적을 중지할 수 있습니다.
- kubectl logs -n cert-manager deployment/cert-manager --tail=10 -f
인증서가 준비되면 curl
을 사용하여 클러스터에 대해 HTTPS 요청을 할 수 있습니다.
- curl https://tutorial-service.your_domain
참고: DNS 레코드를 업데이트한 기간과 DNS 레코드가 인터넷의 DNS 서버에 퍼지는 데 걸리는 시간에 따라 도메인을 찾을 수 없거나 잘못된 위치로 이동한다는 오류가 표시될 수 있습니다. 이 경우 curl
해결 방법을 사용하여 다음 명령을 실행하여 지금은 DNS 확인을 건너뛸 수 있습니다.
- curl https://tutorial-service.your_domain --resolve 'tutorial-service.your_domain:443:traefik_ip_address'
이 명령은 curl
명령에 --resolve
옵션을 사용하여 tutorial-service.your_domain
에 대한 DNS 확인을 재정의하도록 지시합니다. 포트 443
에서 대신 traefik_ip_address
를 사용하십시오. DNS 결과 curl
이 올바르지 않기 때문에 DNS가 완전히 업데이트될 때까지 클러스터 내부의 Traefik에 연결할 수 있습니다.
출력에 동일한 Nginx "Welcome!\이 표시됩니다. 이전에는 포트 포워딩에서 페이지를 열었지만 이번에는 인터넷을 통해 액세스할 수 있습니다.
Output<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
그러나 사이트의 HTTP 버전을 요청하면 응답을 받지 못합니다.
- curl http://tutorial-service.your_domain
대신 404
오류가 로드됩니다.
Output404 page not found
HTTP 트래픽에 응답하지 않도록 Ingress
에서 사이트를 구성했으므로 Traefik은 해당 주소에 사이트를 설정하지 않고 404
오류를 반환합니다. 이로 인해 사용자가 웹 사이트를 확인해야 한다는 사실을 알고 있으면 혼란스러울 수 있으므로 많은 관리자가 HTTP 트래픽을 자동으로 HTTPS 사이트로 리디렉션하도록 서버를 구성합니다. 또한 Traefik을 사용하면 모든 웹
트래픽을 websecure
포트로 리디렉션하도록 Traefik을 업데이트하여 이를 수행할 수 있습니다.
- helm upgrade --namespace=traefik traefik traefik/traefik --set 'ports.web.redirectTo=websecure'
--set ports.web.redirectTo=websecure
옵션은 Traefik이 리디렉션을 자동으로 수행하도록 스스로 재구성하도록 지시합니다.
traefik
설치가 "업그레이드\되었다는 아래와 유사한 메시지가 표시되어야 합니다.
OutputRelease "traefik" has been upgraded. Happy Helming!
NAME: traefik
LAST DEPLOYED: Sun Oct 2 19:17:34 2022
NAMESPACE: traefik
STATUS: deployed
REVISION: 2
TEST SUITE: None
이제 HTTP 위치에 요청하면 사이트가 이동되었다는 출력을 받게 됩니다.
- curl http://tutorial-service.your_domain
다음 응답이 예상됩니다.
OutputMoved Permanently
모든 트래픽이 HTTPS 사이트로 이동하기를 원하므로 이제 Traefik은 사용자를 대신하여 HTTP 사이트에서 HTTPS 사이트로 자동 리디렉션을 반환합니다. 웹 브라우저는 이 리디렉션을 자동으로 수행하지만 curl
에는 리디렉션을 따르도록 지시하는 추가 옵션 -L
이 필요합니다. 리디렉션을 따르도록 curl
명령을 -L
옵션으로 업데이트합니다.
- curl -L http://tutorial-service.your_domain
출력에는 HTTPS 사이트의 Nginx 시작 페이지가 포함됩니다.
Output<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
이 출력은 리디렉션이 예상대로 작동하는지 확인합니다.
이 섹션에서는 Kubernetes Ingress
리소스를 사용하여 cert-manager, Traefik 및 Nginx 웹사이트를 함께 연결했습니다. 또한 사용자가 웹사이트를 찾을 수 있도록 HTTP 트래픽을 HTTPS 웹사이트로 리디렉션하도록 Traefik 구성을 업데이트했습니다.
결론
이 튜토리얼에서는 보안 인증서로 웹 사이트를 더 쉽게 실행할 수 있도록 Kubernetes 클러스터에 몇 가지 다른 서비스를 설치했습니다. Let’s Encrypt에서 발급된 TLS 인증서의 수명 주기를 처리하기 위해 cert-manager 서비스를 설치했습니다. 클러스터 외부에서 웹 사이트를 사용할 수 있도록 하고 Let’s Encrypt에서 발급한 TLS 인증서를 사용하기 위해 Traefik을 설치했습니다. 마지막으로 cert-manager 및 Traefik 구성을 테스트하기 위해 클러스터에 Nginx 웹 사이트를 만들었습니다.
이제 클러스터에 cert-manager 및 Traefik이 구성되었으므로 단일 cert-manager 및 Traefik 설치로 동일한 클러스터의 많은 웹사이트에 서비스를 제공하기 위해 다른 Ingress
리소스로 더 많은 웹사이트를 설정할 수도 있습니다.
cert-manager에는 다른 유형의 Let's Encrypt 챌린지 및 Let's Encrypt 이외의 소스와 함께 사용하는 방법에 대한 광범위한 문서가 있습니다.
Kubernetes 클러스터 구성을 계속하려면 Kubernetes에 대한 다른 자습서를 확인하십시오.