애플리케이션 개발의 궁극적인 목적은 물론, 앱을 인터넷에 공개하는 것입니다. 개발자의 경우, Kubernetes는 Ingress 컨트롤러를 애플리케이션에 대한 요청을 라우팅하는 메커니즘으로 제공함으로써 이 프로세스를 어느 정도 단순화합니다. 하지만 모든 것이 여러분이 원하는 만큼 셀프 서비스인 것은 아닙니다. 여전히 앱의 도메인 이름을 Ingress 컨트롤러의 IP 주소에 매핑하기 위해 도메인 이름 시스템(DNS)에 레코드가 필요하고 HTTPS를 사용하여 연결을 보호하기 위한 TLS 인증서가 필요합니다. 대부분의 조직에서는 DNS나 TLS를 직접 소유하지 않으므로 이를 소유한 운영 그룹(또는 그룹들!)과 협력해야 합니다.
운영자에게는 반드시 더 쉬운 일은 아닙니다. 대부분의 조직에서는 DNS 레코드를 업데이트해야 할 필요성이 매우 낮아서 비즈니스 규칙과 실제 기술 단계를 포함한 절차가 거의 없거나 전혀 없는 경향이 있습니다. 즉, DNS 레코드를 추가해야 할 때 먼저 설명서를 찾거나 동료에게 물어보거나 (최악의 경우) 스스로 알아내야 합니다. 또한 회사의 보안 규칙을 준수하고 방화벽에서 유입이 적절하게 태그되어 있는지 확인해야 합니다.
다행히 개발자와 운영자 모두의 삶을 편리하게 만들어주는 방법이 있습니다. 이 게시물에서는 개발자가 Kubernetes 환경에서 DNS 레코드를 업데이트하고 TLS 인증서를 생성할 수 있는 셀프 서비스를 제공하기 위해 운영자가 Kubernetes 배포를 구성하는 방법을 보여줍니다. 사전에 인프라를 구축함으로써 모든 필수 비즈니스 및 기술 요구 사항이 충족되는지 확인할 수 있습니다.
솔루션이 구현되면 개발자가 해야 할 일은 Kubernetes 설치에서 관리하는 도메인 내의 정규화된 도메인 이름(FQDN)을 포함하는 제공된 템플릿에 따라 Ingress 컨트롤러를 만드는 것뿐입니다. Kubernetes는 템플릿을 사용하여 Ingress 컨트롤러에 대한 IP 주소를 할당하고, FQDN을 IP 주소에 매핑하기 위한 DNS A
레코드를 생성하고, FQDN에 대한 TLS 인증서를 생성하여 Ingress 컨트롤러에 추가합니다. 정리도 매우 쉽습니다. Ingress가 제거되면 DNS 레코드도 정리됩니다.
이 솔루션은 다음 기술을 활용합니다(아래에 설치 및 구성 지침 제공):
솔루션을 구성하기 전에 다음이 필요합니다.
LoadBalancer
) 개체가 있는 Kubernetes 클라우드 설치. 이 솔루션은 Linode를 사용하지만 다른 클라우드 공급자도 사용할 수 있습니다.kubectl
.또한 Kubernetes에 대한 기본적인 이해(매니페스트 적용 방법, Helm 차트 사용 방법, kubectl
명령을 실행하여 출력을 보고 문제를 해결하는 방법)가 있다고 가정합니다. Let's Encrypt의 기본 개념을 이해하는 것은 도움이 되지만 필수는 아닙니다. 개요는 블로그 에서 확인하세요. cert-manager가 어떻게 작동하는지 알 필요는 없지만 NGINX Ingress Controller에서 cert-manager가 어떻게 작동하는지(그리고 인증서 전반에 대해) 궁금하다면 최근 게시물인 Kubernetes 환경에서 인증서 관리 자동화를 참조하세요.
우리는 macOS와 Linux에서 모두 솔루션을 테스트했습니다. Linux 버전 2(WSL2)용 Windows 하위 시스템 에서는 테스트를 실시하지 않았지만, 아무런 문제가 발생하지 않을 것으로 예상됩니다.
메모: 이 솔루션은 실제 생산에 사용하기 위한 것이 아니라 개념 증명 샘플로 제공됩니다. 특히, 운영 및 보안에 대한 모든 모범 사례가 통합되어 있지는 않습니다. 해당 주제에 대한 자세한 내용은 cert-manager 및 ExternalDNS 설명서를 참조하세요.
솔루션을 배포하려면 다음 섹션의 단계를 따르세요.
NGINX Ingress Controller 저장소를 복제합니다.
$ git clone https://github.com/nginxinc/kubernetes-ingress.git 'kubernetes-ingress'에 복제... 원격: 객체 열거: 45176, 완료. 원격: 사물 세기: 100% (373/373), 완료. 원격: 객체 압축: 100% (274/274), 완료. 원격: 총 45176개(델타 173개), 재사용 219개(델타 79개), 팩 재사용 44803개 수신 객체: 100% (45176/45176), 60.45 MiB | 26.81 MiB/s, 완료.
델타 해결: 100% (26592/26592), 완료.
Kubernetes 클러스터에 연결할 수 있는지 확인하세요.
$ kubectl cluster-info Kubernetes 제어 평면은 https://ba35bacf-b072-4600-9a04-e04...6a3d.us-west-2.linodelke.net:443에서 실행 중입니다. KubeDNS는 https://ba35bacf-b072-4600-9a04-e04...6a3d.us-west-2.linodelke.net:443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy에서 실행 중입니다. 클러스터 문제를 추가로 디버깅하고 진단하려면 'kubectl cluster-info dump'를 사용하세요.
Helm을 사용하여 NGINX Ingress Controller를 배포합니다. 비표준 구성 옵션 3개가 추가된다는 점에 유의하세요.
controller.enableCustomResources
– Helm에 NGINX VirtualServer 및 VirtualServerRoute 사용자 정의 리소스를 만드는 데 사용되는 사용자 정의 리소스 정의(CRD)를 설치하도록 지시합니다.controller.enableCertManager
– NGINX Ingress Controller가 cert-manager 구성 요소와 통신하도록 구성합니다.controller.enableExternalDNS
– Ingress Controller가 ExternalDNS 구성 요소와 통신하도록 구성합니다.$ helm install nginx-kic nginx-stable/nginx-ingress --namespace nginx-ingress --set controller.enableCustomResources=true --create-namespace --set controller.enableCertManager=true --set controller.enableExternalDNS=true 이름: nginx-kic 마지막 배포: 요일 월 DD hh : mm : ss YYYY 네임스페이스: nginx-ingress 상태: 배포됨 개정: 1 테스트 모음: 없음 참고사항:
NGINX Ingress Controller가 설치되었습니다.
NGINX Ingress Controller가 실행 중인지 확인하고 EXTERNAL-IP
필드의 값을 기록해 둡니다. 이는 NGINX Ingress Controller의 IP 주소입니다(여기서는 www.xxx.yyy.zzz
). 가독성을 위해 출력은 두 줄로 분산되어 있습니다.
$ kubectl get services --namespace nginx-ingress 이름 유형 클러스터 IP ... nginx-kic-nginx-ingress LoadBalancer 10.128.152.88 ... ... 외부 IP 포트 나이 ... www.xxx.yyy.zzz 80:32457/TCP,443:31971/TCP 3h8m
이 솔루션에서 cert-manager는 TLS 인증서를 얻을 때 DNS-01 챌린지 유형을 사용하며, 이를 위해서는 ClusterIssuer 리소스를 생성하는 동안 Cloudflare API 토큰을 제공해야 합니다. 솔루션에서 API 토큰은 Kubernetes Secret 으로 제공됩니다.
Helm을 사용하여 cert-manager를 배포합니다 .
$ helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --version v1.9.1 --set installCRDs=true 이름: cert-manager 마지막 배포: 요일 월 DD hh : mm : ss YYYY 네임스페이스: cert-manager 상태: 배포됨 개정: 1 테스트 모음: 없음 참고사항: cert-manager v1.9.1이 성공적으로 배포되었습니다!
Cloudflare API 토큰을 Kubernetes Secret으로 배포하여 다음으로 대체합니다. <귀하의 API 토큰>
:
$ kubectl 적용 -f - <<EOFapiVersion: v1
종류: 비밀 메타데이터: 이름: Cloudflare-api-token-secret 네임스페이스: cert-manager 유형: 불투명
stringData:
api-token: "<귀하의 API 토큰>"
EOF
secret/Cloudflare-api-token-secret 생성됨
이전 단계에서 정의한 Cloudflare-api-token-secret을
토큰을 검색할 위치로 지정하여 ClusterIssuer 객체를 만듭니다. 원하시면 metadata.name
필드의 example-issuer
(및 spec.acme.privateKeySecretRef.name
필드의 example-issuer-account-key
)를 다른 이름으로 바꿀 수 있습니다.
$ kubectl 적용 -f - <<EOFapi버전: cert-manager.io/v1
종류: ClusterIssuer 메타데이터: 이름: example-issuer 네임스페이스: cert-manager 사양: acme: 이메일: example@example.com 서버: https://acme-v02.api.letsencrypt.org/directory privateKeySecretRef: 이름: example-issuer-account-key 솔버: - dns01:
Cloudflare: apiTokenSecretRef: 이름: Cloudflare-api-token-secret 키: api-token EOF clusterissuer.cert-manager.io/example-issuer 생성됨
ClusterIssuer가 배포되고 준비되었는지 확인합니다( READY
필드의 값이 True 임
).
$ kubectl get clusterissuer 이름 준비 연령 example-issuer True 3h9m
cert-manager와 마찬가지로 ExternalDNS 프로젝트에는 DNS를 관리하기 위한 Cloudflare API 토큰이 필요합니다. 두 프로젝트 모두에 동일한 토큰을 사용할 수 있지만 필수는 아닙니다.
프로젝트 간 통합을 활성화하기 위해 NGINX Ingress Controller에 대한 ExternalDNS CRD를 생성합니다.
$ kubectl create -f ./kubernetes-ingress/deployments/common/crds/externaldns.nginx.org_dnsendpoints.yaml customresourcedefinition.apiextensions.k8s.io/dnsendpoints.externaldns.nginx.org가 생성됨
외부 DNS 서비스( external-dns
)를 생성합니다. 명단이 꽤 길기 때문에 여기서는 두 부분으로 나누겠습니다. 첫 번째 부분에서는 계정, 역할 및 권한을 구성합니다.
external-dns
라는 ServiceAccount 객체를 생성합니다.external-dns
라고도 함)를 만듭니다.$ kubectl 적용 -f - <<EOFapiVersion: v1
종류: ServiceAccount 메타데이터: 이름: external-dns --- apiVersion: rbac.authorization.k8s.io/v1 종류: ClusterRole 메타데이터: 이름: external-dns 규칙: - apiGroups: [""] 리소스: ["services","endpoints","pods"] 동사: ["get","watch","list"] - apiGroups: ["extensions","networking.k8s.io"] 리소스: ["ingresses"] 동사: ["get","watch","list"] - apiGroups: ["externaldns.nginx.org"] 리소스: ["dnsendpoints"] 동사: ["get","watch","list"] - apiGroups: ["externaldns.nginx.org"] 리소스: ["dnsendpoints/status"] 동사: ["update"] - apiGroups: [""] 리소스: ["nodes"] 동사: ["list","watch"] --- apiVersion: rbac.authorization.k8s.io/v1 종류: ClusterRoleBinding 메타데이터: 이름: external-dns-viewer roleRef: apiGroup: rbac.authorization.k8s.io 종류: ClusterRole 이름: external-dns 주제: - 종류: ServiceAccount 이름: external-dns 네임스페이스: 기본 EOF serviceaccount/external-dns 생성됨 clusterrole.rbac.authorization.k8s.io/external-dns 생성됨 clusterrolebinding.rbac.authorization.k8s.io/external-dns-viewer 생성됨
매니페스트의 두 번째 부분은 ExternalDNS 배포를 생성합니다.
domain-filter를
example.com
으로 설정합니다.CF_API_TOKEN
환경 변수를 Cloudflare API 토큰으로 설정합니다. 을 위한 <귀하의 API 토큰>
실제 토큰이나 토큰을 포함하는 비밀로 대체하세요. 후자의 경우, 환경 변수를 사용하여 비밀을 컨테이너에 투영 해야 합니다.FREE_TIER
환경 변수를 "true"
로 설정합니다(유료 Cloudflare 구독이 없는 경우 적합).$ kubectl 적용 -f - <<EOF
---
api 버전: apps/v1
종류: 배포 메타데이터: 이름: 외부 DNS 사양: 전략: 유형: 선택기를 다시 만듭니다. matchLabels: 앱: 외부 DNS 템플릿: 메타데이터: 레이블: 앱: 외부 DNS 사양: serviceAccountName: 외부 DNS 컨테이너: - 이름: 외부 DNS 이미지: k8s.gcr.io/external-dns/external-dns:v0.12.0 인수: - --source=service - --source=ingress - --source=crd - --crd-source-apiversion=externaldns.nginx.org/v1 - --crd-source-kind=DNSEndpoint - --domain-filter=example.com - --provider=Cloudflare env: - 이름: CF_API_TOKEN 값: " <귀하의 API 토큰> " - 이름: FREE_TIER 값: "true" EOF serviceaccount/external-dns가 생성됨 clusterrole.rbac.authorization.k8s.io/external-dns가 생성됨 clusterrolebinding.rbac.authorization.k8s.io/external-dns-viewer가 생성됨 deployment.apps/external-dns가 생성됨
테스트 목적으로 Cafe 라는 표준 NGINX Ingress Controller 샘플 애플리케이션을 사용합니다.
카페 애플리케이션을 배포합니다.
$ kubectl apply -f ./kubernetes-ingress/examples/ingress-resources/complete-example/cafe.yaml deployment.apps/coffee가 생성되었습니다. service/coffee-svc가 생성되었습니다. deployment.apps/tea가 생성되었습니다. service/tea-svc가 생성되었습니다.
Cafe 애플리케이션에 NGINX Ingress Controller를 배포합니다. 다음 설정을 참고하세요.
친절한: VirtualServer
– 표준 Kubernetes Ingress 리소스가 아닌 NGINX VirtualServer 사용자 정의 리소스를 사용하고 있습니다.spec.host
– cafe.example.com을
배포하는 호스트의 이름으로 바꾸세요. 호스트는 ExternalDNS로 관리되는 도메인 내에 있어야 합니다.spec.tls.cert-manager.cluster-issuer
– 이 게시물에 지정된 값을 사용하고 있다면 이것은 example-issuer
입니다. 필요한 경우 cert‑manager 배포 3단계 에서 선택한 이름을 대체합니다.spec.externalDNS.enable
– true
값은 ExternalDNS에 DNS A
레코드를 생성하도록 지시합니다.이 단계를 완료하는 데 걸리는 시간은 Kubernetes가 공급자의 DNS API와 상호 작용하기 때문에 DNS 공급자에 따라 크게 달라집니다.
$ kubectl 적용 -f - <<EOFapi버전: k8s.nginx.org/v1
종류: VirtualServer 메타데이터: 이름: cafe 사양: 호스트: cafe.example.com tls: 비밀: cafe-secret 인증서 관리자: 클러스터 발급자: example-issuer externalDNS: 활성화: true 업스트림: - 이름: tea 서비스: tea-svc 포트: 80 - 이름: 커피 서비스: coffee-svc 포트: 80개 경로: - 경로: /tea 작업: 패스: tea - 경로: /coffee 작업: 패스: coffee EOF virtualserver.k8s.nginx.org/cafe 생성됨
DNS A
레코드를 확인합니다. 특히 ANSWER
SECTION
블록에서 FQDN(여기서는 cafe.example.com
)이 올바른 IP 주소( www.xxx.yyy.zzz
)에 매핑되어 있는지 확인합니다.
$ dig cafe.example.com ; <<>> DiG 9.10.6 <<>> cafe.example.com ;; 전역 옵션: +cmd ;; 답변을 받았습니다: ;; ->>HEADER<<- 명령어: 쿼리, 상태: 오류, id: 22633 ;; 플래그: qr rd ra; 쿼리: 1, 정답: 1, 권한: 0, 추가: 1 ;; OPT 의사 섹션: ; EDNS: 버전: 0, 플래그:; UDP: 4096 ;; 질문 섹션: ;cafe.example.com. 답변 섹션: cafe.example.com. 279 IN A www.xxx.yyy.zzz ;; 쿼리 시간: 1밀리초 ;; 서버: 2607:fb91:119b:4ac4:2e0: xxxx :fe1e:1359#53(2607:fb91:119b:4ac4:2e0: xxxx :fe1e:1359) ;; 언제: 요일 월 DD hh : mm : ss TZ YYYY ;; 메시지 크기 수신: 67
인증서가 유효한지 확인하세요( READY
필드의 값이 True 임
).
$ kubectl 인증서 가져오기 이름 준비 비밀 나이 cafe-secret True cafe-secret 8m51s
신청서에 접속할 수 있는지 확인하세요.
$ curl https://cafe.example.com/coffee 서버 주소: 10.2.2.4:8080 서버 이름: coffee-7c86d7d67c-lsfs6 날짜: DD/Mon/YYYY:hh:mm:ss +TZ-오프셋 URI: /coffee 요청 ID: 91077575f19e6e735a91b9d06e9684cd $ curl https://cafe.example.com/tea 서버 주소: 10.2.2.5:8080 서버 이름: tea-5c457db9-ztpns 날짜: DD/Mon/YYYY:hh:mm:ss +TZ-오프셋 URI: /tea 요청 ID: 2164c245a495d22c11e900aa0103b00f
해결책이 제시되면 많은 일이 비밀리에 일어납니다. 이 다이어그램은 개발자가 NGINX VirtualServer 사용자 정의 리소스와 함께 NGINX Ingress Controller를 배포할 때 어떤 일이 발생하는지 보여줍니다. 일부 운영 세부 사항은 생략되었습니다.
A
레코드를 생성합니다.A
레코드를 생성합니다.Kubernetes의 복잡성과 우리가 사용하는 구성 요소를 고려할 때, 포괄적인 문제 해결 가이드를 제공하는 것은 어렵습니다. 그런데, 문제를 파악하는 데 도움이 되는 몇 가지 기본적인 제안이 있습니다.
kubectl
get
및 kubectl
describe
명령을 사용하여 배포된 객체의 구성을 검증합니다.쿠벡틀
로그
<구성요소>
다양하게 배포된 구성 요소에 대한 로그 파일을 보는 명령입니다.여전히 문제가 발생하는 경우 NGINX 커뮤니티 Slack 에서 도움을 요청하세요! 우리는 활기찬 커뮤니티를 보유하고 있으며 항상 기꺼이 문제를 해결하고자 노력합니다.
NGINX Plus 기반 NGINX Ingress Controller를 사용해 보려면 오늘 30일 무료 평가판을 시작하거나 당사에 문의하여 사용 사례에 대해 논의해 보세요 .
"이 블로그 게시물에는 더 이상 사용할 수 없거나 더 이상 지원되지 않는 제품이 참조될 수 있습니다. 사용 가능한 F5 NGINX 제품과 솔루션에 대한 최신 정보를 보려면 NGINX 제품군을 살펴보세요. NGINX는 이제 F5의 일부가 되었습니다. 이전의 모든 NGINX.com 링크는 F5.com의 유사한 NGINX 콘텐츠로 리디렉션됩니다."