웹사이트 검색

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를 설치합니다.

  1. kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.yaml

기본적으로 cert-manager는 cert-manager라는 자체 네임스페이스에 설치됩니다. 파일이 적용되면 클러스터에 여러 리소스가 생성되어 출력에 표시됩니다(일부 출력은 길이로 인해 제거됨).

Output
namespace/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를 사용하여 해당 디렉토리에 들어갑니다.

  1. mkdir tutorial-cluster-config
  2. cd tutorial-cluster-config

디렉터리를 만든 후에는 이 자습서의 전제 조건의 일부로 만든 DNS 액세스용 개인 액세스 토큰이 필요합니다. DigitalOcean 액세스 토큰은 긴 숫자 문자열이 있는 dop_v1_4321...와 유사하게 보입니다.

Kubernetes에서 액세스 토큰을 비밀로 저장하려면 이를 base-64로 인코딩해야 합니다. 이렇게 하려면 echo 명령을 사용하여 토큰을 base64 명령으로 파이프하고 강조 표시된 부분을 액세스 토큰으로 바꿉니다.

  1. echo -n 'dop_v1_4321...' | base64

이 명령은 액세스 토큰을 echo에서 base64 명령으로 전송하여 인코딩합니다. -n 옵션은 끝에 새 줄이 포함되지 않도록 합니다. 액세스 토큰에 따라 다음과 유사한 출력을 받게 됩니다.

Output
ZG9wX3YxX3RoaXNpc25vdGFyZWFsdG9rZW5idXRpbXB1dHRpbmdhYnVuY2hvZnN0dWZmaW5oZXJlc29sZW5ndGhzbWF0Y2g=

이 출력은 base-64로 인코딩된 액세스 토큰입니다. 다음에 사용할 것이기 때문에 이것을 복사하십시오.

nano 또는 좋아하는 편집기를 사용하여 lets-encrypt-do-dns.yaml이라는 새 파일을 만들고 엽니다.

  1. 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를 사용하여 클러스터에 적용합니다.

  1. kubectl apply -f lets-encrypt-do-dns.yaml

출력에서 클러스터에 비밀이 생성되었다는 메시지를 받게 됩니다.

Output
secret/lets-encrypt-do-dns created

이제 Let’s Encrypt 인증서를 발급하는 데 사용할 cert-manager의 ClusterIssuer를 포함할 lets-encrypt-issuer.yaml이라는 새 파일을 만듭니다.

  1. 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

처음 두 줄에서 apiVersionkind는 이 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<의 lets-encrypt-do-dns access-token 필드를 참조합니다. 이전에 생성했습니다. cert-manager는 사용자를 대신하여 DNS 레코드를 생성할 때 이 액세스 토큰을 사용합니다.

발급자 파일을 저장했으면 kubectl apply를 사용하여 클러스터에 적용합니다.

  1. kubectl apply -f lets-encrypt-issuer.yaml

출력에서 letsencrypt-issuer라는 이름의 ClusterIssuer가 생성되었음을 확인할 수 있습니다.

Output
clusterissuer.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이라는 파일을 엽니다.

  1. nano traefik-ns.yaml

Kubernetes 네임스페이스 리소스를 입력합니다.

apiVersion: v1
kind: Namespace
metadata:
  name: traefik

파일을 저장한 후 kubectl apply를 사용하여 클러스터에 적용합니다.

  1. kubectl apply -f traefik-ns.yaml

명령이 실행되면 클러스터의 출력에서 네임스페이스가 생성되었음을 확인할 수 있습니다.

Output
namespace/traefik created

traefik 네임스페이스를 만든 후 Traefik 서비스 자체를 설치합니다. 이를 위해 chart라는 유틸리티를 사용합니다.

먼저 사용 가능한 리포지토리에 traefik Helm 리포지토리를 추가해야 합니다. 그러면 Helm이 traefik 패키지를 찾을 수 있습니다.

  1. helm repo add traefik https://helm.traefik.io/traefik

명령이 완료되면 traefik 리포지토리가 컴퓨터의 Helm 리포지토리에 추가되었다는 확인 메시지가 표시됩니다.

Output
"traefik" has been added to your repositories

다음으로 차트 리포지토리를 업데이트합니다.

  1. helm repo update

출력에서 traefik 차트 리포지토리가 업데이트되었음을 확인할 수 있습니다.

Output
Hang 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을 설치합니다.

  1. helm install --namespace=traefik traefik traefik/traefik

이 명령에는 많은 traefik이 있으므로 각각의 기능을 살펴보겠습니다. 명령의 첫 번째 traefik(--namespace=traefik 포함)은 이전에 생성한 traefik 네임스페이스에 Traefik을 설치하도록 Helm에 지시합니다. 다음으로 강조 표시된 traefik은 클러스터에서 이 Traefik 설치에 제공하려는 이름입니다. 이렇게 하면 동일한 클러스터에 Traefik이 여러 개 설치되어 있는 경우 traefik-website1traefik-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 리소스를 확인합니다.

  1. kubectl get -n traefik all

출력은 아래 출력과 유사하게 나타납니다.

Output
NAME 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/traefikEXTERNAL-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_addresstutorial-proxy.your_domain 도메인에 대한 DNS A 레코드를 만듭니다. 마크>:

  1. 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_domaintraefik_ip_address를 가리킵니다. 따라서 누군가 tutorial-proxy.your_domain에서 웹사이트를 요청하면 DNS 서버는 traefik_ip_address로 안내합니다. .

명령을 실행하면 레코드가 생성되었다는 확인 메시지가 표시됩니다.

Output
ID 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에 후행 마침표(.)를 포함해야 합니다.

  1. 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 서버에 제공되는 도메인의 끝이며 끝에 다른 정보를 추가해서는 안 된다는 것을 알려줍니다. 마침표(.)가 문장을 끝내는 데 사용되는 방식과 비슷합니다.

명령을 실행하면 다음과 유사한 출력이 표시됩니다.

Output
ID 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 서버 중 하나로 바꿉니다.

  1. dig @ns1.linux-console.net +noall +answer +domain=your_domain tutorial-proxy tutorial-service

Dig를 사용하여 DNS 정보 검색

다음으로 +domain=your_domain을 사용하여 dig.your_domain을 명령에 제공된 호스트 이름의 끝. 마지막으로 tutorial-proxytutorial-service는 조회할 호스트 이름입니다. +domain 옵션을 사용하고 있으므로 tutorial-proxy.your_domain 전체 구문을 사용할 필요가 없습니다. 마지막에 자동으로 추가됩니다.

your_domaintraefik_ip_address에 대한 자체 값을 사용하여 다음과 유사한 출력을 수신해야 합니다.

Output
tutorial-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_domainA(IN A) 레코드임을 보여줍니다. traefik_ip_address를 가리킵니다. 두 번째는 tutorial-service.your_domainCNAME(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이라는 파일을 만듭니다.

  1. 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에서 일치할 레이블을 제공하고 specservice는 nginx 이미지를 사용하고 포트 80에서 네트워크 연결을 수신 대기합니다.

변경 사항을 저장했으면 클러스터에 적용합니다.

  1. kubectl apply -f tutorial-service.yaml

출력은 tutorial 네임스페이스와 tutorial-service 배포가 생성되었음을 확인합니다.

Output
namespace/tutorial created deployment.apps/tutorial-service created

배포가 실행 중인지 확인하려면 kubectl get pods 명령을 사용하여 tutorial 네임스페이스에서 실행 중인 포드를 나열할 수 있습니다.

  1. kubectl get -n tutorial pods

다음과 유사한 출력이 인쇄됩니다.

Output
NAME 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

RunningSTATUStutorial-service- 다음에 임의의 이름이 있는 세 개의 포드 목록을 찾아야 합니다. AGEkubectl applykubectl 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으로 전송되어야 합니다.

변경 사항을 저장한 후 클러스터에 서비스를 적용합니다.

  1. kubectl apply -f tutorial-service.yaml

이번에는 출력에서 네임스페이스와 배포가 변경되지 않음으로 나열되고(변경하지 않았기 때문에) tutorial-service되었습니다. 생성:

Output
namespace/tutorial unchanged deployment.apps/tutorial-service unchanged service/tutorial-service created

tutorial-service가 생성되면 kubectl port-forward 명령을 사용하여 로컬 컴퓨터에서 서비스를 사용할 수 있도록 하여 서비스에 액세스할 수 있는지 테스트할 수 있습니다.

  1. kubectl port-forward -n tutorial service/tutorial-service 8888:80

이 명령은 로컬 컴퓨터의 포트 8888로 전송된 모든 트래픽을 클러스터에 있는 tutorial-service의 포트 80으로 전달합니다. Kubernetes 클러스터에서 포트 80에서 연결을 수신하도록 tutorial-service Service를 설정하고 트래픽을 보낼 방법이 필요합니다. 로컬 컴퓨터에서 클러스터의 해당 서비스로. 명령에서 tutorial 네임스페이스의 service/tutorial-serviceport-forward하도록 지정하고 다음 조합을 제공합니다. 포트 8888:80. 나열된 첫 번째 포트는 로컬 컴퓨터가 수신할 포트이고 두 번째 포트(: 다음)는 트래픽이 수신되는 service/tutorial-service의 포트입니다. 전송됩니다. 로컬 컴퓨터의 포트 8888로 트래픽을 보내면 모든 트래픽이 service/tutorial-service의 포트 80으로 보내지고 궁극적으로 service/tutorial-service가 가리키는 포드에 연결됩니다.

명령을 실행하면 다음과 유사한 출력이 표시됩니다.

Output
Forwarding from 127.0.0.1:8888 -> 80 Forwarding from [::1]:8888 -> 80

명령이 반환되지 않고 계속 실행되어 트래픽을 전달합니다.

서비스에 대해 요청하려면 컴퓨터에서 두 번째 터미널을 열고 포트 8888에서 컴퓨터에 curl 명령을 사용합니다.

  1. 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 연결을 만들 때 추가 출력이 표시됩니다.

Output
Forwarding 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을 다시 엽니다.

  1. 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.tlstrue로 설정되어 Traefik에게 HTTP 트래픽이 아닌 HTTPS 트래픽에만 응답하도록 지시합니다. 민감한 데이터를 처리하려면 웹 사이트가 안전해야 하므로 사용자가 실수로 안전하지 않은 버전을 사용하는 것을 원하지 않습니다.

마지막 주석인 cert-manager.io/cluster-issuerletsencrypt-issuer로 설정되어 보안 인증서를 발급할 때 사용할 발급자를 cert-manager에 알립니다. 이 인그레스에 대해. 이 시점에서 letsencrypt-issuer는 사용자가 구성한 유일한 발급자이지만 나중에 더 추가하고 사이트마다 다른 발급자를 사용할 수 있습니다.

Ingress spec.rules 섹션에서 Ingress로 전송되는 트래픽을 라우팅하기 위한 하나의 규칙을 포함합니다. tutorial-service.your_domain이라는 호스트에 대해 지정된 paths<에 대해 http를 사용한다고 말합니다. /코드>. 포함된 유일한 pathPrefixpathType이 있는 루트 / 경로입니다. 제공된 백엔드로 전송됩니다. backend 섹션은 이것이 service라고 말하고 트래픽을 보내야 하는 서비스는 tutorial-service Service입니다. 이전에 생성했으며 해당 트래픽은 Service의 포트 80으로 전송되어야 합니다.

Ingressspec.tls 섹션은 cert-manager가 보안 인증서를 요청하고 발급하는 데 필요한 정보와 Traefik이 해당 인증서를 사용하는 데 필요한 정보를 제공합니다. secretName은 cert-manager가 발급된 보안 인증서를 넣을 Kubernetes Secret이고 Traefik이 발급된 인증서를 로드하는 데 사용할 Secret입니다. hosts 섹션에는 cert-manager가 인증서를 요청할 호스트 이름이 나열됩니다. 이 경우 tutorial-service.your_domain 호스트 이름만 해당되지만 사이트가 여러 호스트 이름에 응답하도록 하려면 소유한 다른 호스트 이름을 포함할 수도 있습니다. .

생성한 Ingress를 저장한 후 kubectl apply를 다시 사용하여 새 리소스를 클러스터에 적용합니다.

  1. kubectl apply -f tutorial-service.yaml

Ingress생성되고 다른 리소스는 변경되지 않은 상태로 유지됩니다.

Output
namespace/tutorial unchanged deployment.apps/tutorial-service unchanged service/tutorial-service unchanged ingress.networking.k8s.io/tutorial-service-ingress created

Ingress가 생성되면 Traefik은 자체 구성을 시작하고 cert-manager는 인증서를 발급하기 위해 시도/응답 프로세스를 시작합니다. 이 작업은 몇 분 정도 걸릴 수 있으므로 튜토리얼 네임스페이스에서 인증서를 검토하여 인증서가 발급되었는지 확인할 수 있습니다.

  1. kubectl get -n tutorial certificates

다음과 유사한 출력이 표시됩니다.

Output
NAME READY SECRET AGE tutorial-service-cert False tutorial-service-cert 12m

READY 필드가 False이면 인증서가 아직 발급되지 않은 것입니다. 동일한 명령을 계속 실행하여 True로 바뀌는 것을 지켜볼 수 있습니다. 발행하는 데 시간이 다소 걸릴 수 있지만 몇 분 이상 걸리는 경우 구성에 문제가 있음을 의미할 수 있습니다.

참고: 10~15분 후에도 인증서가 발급되지 않으면 cert-manager의 로그 메시지를 확인하여 인증서 요청에 문제가 있는지 확인하는 것이 도움이 될 수 있습니다. 이러한 로그를 보려면 다음 명령을 사용하여 로그를 보고 CONTRL+C를 눌러 추적을 중지할 수 있습니다.

  1. kubectl logs -n cert-manager deployment/cert-manager --tail=10 -f

인증서가 준비되면 curl을 사용하여 클러스터에 대해 HTTPS 요청을 할 수 있습니다.

  1. curl https://tutorial-service.your_domain

참고: DNS 레코드를 업데이트한 기간과 DNS 레코드가 인터넷의 DNS 서버에 퍼지는 데 걸리는 시간에 따라 도메인을 찾을 수 없거나 잘못된 위치로 이동한다는 오류가 표시될 수 있습니다. 이 경우 curl 해결 방법을 사용하여 다음 명령을 실행하여 지금은 DNS 확인을 건너뛸 수 있습니다.

  1. 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 버전을 요청하면 응답을 받지 못합니다.

  1. curl http://tutorial-service.your_domain

대신 404 오류가 로드됩니다.

Output
404 page not found

HTTP 트래픽에 응답하지 않도록 Ingress에서 사이트를 구성했으므로 Traefik은 해당 주소에 사이트를 설정하지 않고 404 오류를 반환합니다. 이로 인해 사용자가 웹 사이트를 확인해야 한다는 사실을 알고 있으면 혼란스러울 수 있으므로 많은 관리자가 HTTP 트래픽을 자동으로 HTTPS 사이트로 리디렉션하도록 서버를 구성합니다. 또한 Traefik을 사용하면 모든 트래픽을 websecure 포트로 리디렉션하도록 Traefik을 업데이트하여 이를 수행할 수 있습니다.

  1. helm upgrade --namespace=traefik traefik traefik/traefik --set 'ports.web.redirectTo=websecure'

--set ports.web.redirectTo=websecure 옵션은 Traefik이 리디렉션을 자동으로 수행하도록 스스로 재구성하도록 지시합니다.

traefik 설치가 "업그레이드\되었다는 아래와 유사한 메시지가 표시되어야 합니다.

Output
Release "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 위치에 요청하면 사이트가 이동되었다는 출력을 받게 됩니다.

  1. curl http://tutorial-service.your_domain

다음 응답이 예상됩니다.

Output
Moved Permanently

모든 트래픽이 HTTPS 사이트로 이동하기를 원하므로 이제 Traefik은 사용자를 대신하여 HTTP 사이트에서 HTTPS 사이트로 자동 리디렉션을 반환합니다. 웹 브라우저는 이 리디렉션을 자동으로 수행하지만 curl에는 리디렉션을 따르도록 지시하는 추가 옵션 -L이 필요합니다. 리디렉션을 따르도록 curl 명령을 -L 옵션으로 업데이트합니다.

  1. 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에 대한 다른 자습서를 확인하십시오.