TLS 암호화 활성화
TLS 암호화 활성화 (Enable TLS encryption)
Nomad의 클러스터 통신을 보호하는 것은 보안뿐 아니라 실수와 잘못된 구성을 방지해 운영을 더 쉽게 만들 수도 있어요. Nomad는 모든 HTTP 및 RPC 통신에 선택적으로 상호 TLS (mTLS)를 사용해요. Nomad의 mTLS 사용은 다음 속성을 제공해요:
출처: 문서
본문
- 무단 Nomad 접근 방지
- Nomad 통신 관찰 또는 변조 방지
- 클라이언트/서버 역할 또는 리전 잘못된 구성 방지
- 다른 서비스가 Nomad 에이전트로 위장하는 것 방지
리전 잘못된 구성 방지는 공개 인터넷의 TLS 구현에서 흔히 찾아볼 수 없는 Nomad mTLS의 속성이에요. 대부분의 TLS 사용은 example.com 같은 도메인 이름을 기반으로 연결하는 서버의 정체성을 확인하는 반면, Nomad는 연결하는 노드가 예상된 리전에 있고 예상된 역할(예: client.us-west.nomad)로 구성됐는지 확인해요. 이는 또한 같은 프라이빗 CA가 서명한 인증서를 접근할 수 있는 다른 서비스가 Nomad 에이전트로 위장하는 것을 방지해요. 인증서가 호스트 이름/IP를 기준으로 식별됐다면 호스트의 다른 어떤 서비스도 Nomad 에이전트로 위장할 수 있었을 거예요.
TLS를 올바르게 구성하는 것은 특히 배포 방법이 매우 다양하기 때문에 복잡한 과정일 수 있어요. Nomad GitHub 리포지토리의 샘플 Vagrantfile을 사용하거나 Nomad를 설치했다면, 이 가이드는 프로덕션용 TLS 구성을 제공할 거예요.
Nomad의 TLS 구성이 프로덕션용이 될 수 있지만, 키 관리와 로테이션은 이 가이드에서 다루지 않는 복잡한 주제라는 점을 참고해요. Vault가 키 생성과 관리의 권장 솔루션이에요.
인증서 만들기 (Creating certificates)
Nomad용 TLS를 구성하는 첫 단계는 인증서를 생성하는 것이에요. 무단 클러스터 접근을 방지하기 위해 Nomad는 모든 인증서가 동일한 인증 기관(CA, Certificate Authority)이 서명하도록 요구해요. 이는 프라이빗 CA여야 하며 Let's Encrypt 같은 공개 CA가 아니어야 해요. 이 CA가 서명한 모든 인증서는 클러스터와 통신할 수 있기 때문이에요.
루트 CA가 같으면 Nomad 인증서는 중간(intermediate) CA가 서명할 수도 있어요. 모든 중간 CA를 cert_file에 추가해요.
인증 기관 (Certificate authority)
Vault의 PKI 시크릿 백엔드처럼 자체 CA를 관리하는 다양한 도구가 있지만, 단순함을 위해 이 가이드는 Nomad tls ca create 명령을 사용해요.
CA의 프라이빗 키와 인증서를 생성해요.
CA 키(nomad-agent-ca-key.pem)는 Nomad 에이전트 인증서 서명에 사용되며 반드시 비밀로 유지해야 해요. CA 인증서(nomad-agent-ca.pem)에는 Nomad 인증서를 검증하는 데 필요한 공개 키가 포함되어 있으므로 접근이 필요한 모든 노드에 배포해야 해요.
에이전트 인증서 (Agent certificates)
CA 인증서와 키가 있으면 Nomad가 직접 사용할 인증서를 생성하고 서명할 수 있어요. TLS 인증서는 일반적으로 식별되는 시스템의 정규화된 도메인 이름을 인증서의 Common Name(CN)으로 사용해요. 그러나 호스트(그리고 호스트 이름과 IP)는 Nomad 클러스터에서 종종 일시적(ephemeral)이에요. 노드마다 새 인증서를 서명하는 것이 어려울 뿐 아니라, 호스트 이름을 사용해도 Nomad에 보안이나 기능상의 이점이 없어요. 위의 원하는 보안 속성을 충족하기 위해 Nomad 인증서는 다음과 같이 리전과 역할로 서명해요:
global리전의 클라이언트 노드용client.global.nomadus-west리전의 서버 노드용server.us-west.nomad
Nomad 서버용 인증서를 생성해요.
Nomad 클라이언트용 인증서를 생성해요.
CLI용 인증서를 생성해요.
Subject Alternate Names(SANs)로 localhost와 127.0.0.1을 사용하면 같은 호스트에서 실행될 때 curl 같은 도구가 Nomad의 HTTP API와 통신할 수 있어요. 서드파티 도구에서 원격 HTTP 요청을 허용하도록 DNS로 해석 가능한 호스트 이름을 포함한 다른 SAN을 추가할 수도 있어요.
이제 다음 파일이 있어야 해요:
nomad-agent-ca-key.pem- CA 프라이빗 키. 안전하게 보관.nomad-agent-ca.pem- CA 공개 인증서.global-cli-nomad-key.pem-global리전용 Nomad CLI 프라이빗 키.global-cli-nomad.pem-global리전용 Nomad CLI 인증서.global-client-nomad-key.pem-global리전용 Nomad 클라이언트 노드 프라이빗 키.global-client-nomad.pem-global리전용 Nomad 클라이언트 노드 공개 인증서.global-server-nomad-key.pem-global리전용 Nomad 서버 노드 프라이빗 키.global-server-nomad.pem-global리전용 Nomad 서버 노드 공개 인증서.
각 Nomad 노드는 리전과 역할에 맞는 적절한 키(-key.pem)와 인증서(.pem) 파일을 가져야 해요. 또한 각 노드는 CA의 공개 인증서(nomad-agent-ca.pem)가 필요해요.
Nomad 구성 (Configuring Nomad)
다음으로 Nomad가 mTLS에 대해 새로 만든 키와 인증서를 사용하도록 구성해야 해요. Getting Started 가이드의 서버 구성에서 시작해 다음 TLS 구성 옵션을 추가해요:
log_level = "DEBUG"
# Setup data dir
data_dir = "/tmp/server1"
# Enable the server
server {
enabled = true
# Self-elect, should be 3 or 5 for production
bootstrap_expect = 1
}
# Require TLS
tls {
http = true
rpc = true
ca_file = "nomad-agent-ca.pem"
cert_file = "global-server-nomad.pem"
key_file = "global-server-nomad-key.pem"
verify_server_hostname = true
verify_https_client = true
}
새 tls 섹션은 더 자세히 나눠볼 가치가 있어요:
http = true
rpc = true
# ...
}
이것은 HTTP와 RPC 프로토콜에 TLS를 활성화해요. 웹 서버와 달리 Nomad는 TLS 트래픽과 비-TLS 트래픽에 별도의 포트를 사용하지 않아요. 클러스터는 TLS를 사용하거나 사용하지 않아야 해요.
# ...
ca_file = "nomad-agent-ca.pem"
cert_file = "global-server-nomad.pem"
key_file = "global-server-nomad-key.pem"
# ...
}
파일 경로는 인증서 파일을 노드의 어디에 두었는지 가리켜야 해요. 이 가이드는 Nomad의 현재 디렉터리에 있다고 가정해요.
# ...
verify_server_hostname = true
verify_https_client = true
}
이 두 설정은 Nomad의 모든 mTLS 보안 속성이 충족되도록 하는 데 중요해요. verify_server_hostname을 false로 설정하면 노드의 인증서가 같은 CA로 서명됐는지 확인하지만 역할과 리전은 검증하지 않아요. 즉, Nomad와 같은 CA가 서명한 인증서를 가진 모든 서비스가 어떤 리전의 클라이언트나 서버 역할을 할 수 있어요.
verify_https_client는 HTTP API 클라이언트가 Nomad 인증서와 같은 CA가 서명한 인증서를 제시하도록 요구해요. 이것을 비활성화하면 HTTP API 클라이언트(예: Nomad CLI, Consul, curl)가 클라이언트 측 인증서를 제시하지 않고 HTTPS API와 통신할 수 있어요. verify_https_client가 활성화되면 Nomad 인증서와 같은 CA가 서명한 인증서를 제시하는 HTTP API 클라이언트만 Nomad에 접근할 수 있어요.
verify_https_client를 활성화하면 에이전트의 Consul HTTPS 헬스 체크를 잃는 대가로 Nomad를 무단 네트워크 접근으로부터 효과적으로 보호해요.
클라이언트 구성 (Client configuration)
Nomad 클라이언트 구성은 서버 구성과 유사해요. 가장 큰 차이는 구성에 사용되는 인증서와 키예요.
log_level = "DEBUG"
# Setup data dir
data_dir = "/tmp/client1"
# Enable the client
client {
enabled = true
# For demo assume you are talking to server1. For production,
# this should be like "nomad.service.consul:4647" and a system
# like Consul used for service discovery.
server_join {
retry_join = ["127.0.0.1:4647"]
}
}
# Modify our port to avoid a collision with server1
ports {
http = 5656
}
# Require TLS
tls {
http = true
rpc = true
ca_file = "nomad-agent-ca.pem"
cert_file = "global-client-nomad.pem"
key_file = "global-client-nomad-key.pem"
verify_server_hostname = true
verify_https_client = true
}
TLS로 실행 (Running with TLS)
이제 클라이언트와 서버에 대한 인증서와 구성을 생성했으니 TLS가 활성화된 클러스터를 테스트할 수 있어요!
별도의 터미널에서 서버와 클라이언트 에이전트를 시작해요:
한 터미널에서 서버 프로세스를 시작해요.
다른 터미널에서 클라이언트를 시작해요.
지금 nomad node status를 실행하면 다음과 같은 오류가 발생해요:
이것은 Nomad CLI가 HTTPS 대신 HTTP로 통신하는 것이 기본값이기 때문이에요. 명령줄을 사용해 로컬 Nomad 클라이언트가 TLS로 연결하고 커스텀 키와 인증서를 지정하도록 구성할 수 있어요:
-ca-cert=nomad-agent-ca.pem \
-client-cert=global-cli-nomad.pem \
-client-key=global-cli-nomad-key.pem \
-address=https://127.0.0.1:4646
이 과정을 매번 입력하기는 번거로우므로 Nomad CLI는 기본값을 위해 환경 변수도 찾아봐요. 셸에서 환경 변수를 설정하려면 다음 명령을 사용해요.
NOMAD_ADDR는 Nomad 에이전트의 URL이며 -addr의 기본값을 설정해요.
NOMAD_CACERT는 CA 인증서의 위치이며 -ca-cert의 기본값을 설정해요.
NOMAD_CLIENT_CERT는 CLI 인증서의 위치이며 -client-cert의 기본값을 설정해요.
NOMAD_CLIENT_KEY는 CLI 키의 위치이며 -client-key의 기본값을 설정해요.
이 환경 변수들이 올바르게 구성되면 CLI가 예상대로 응답해요.
nomad node status를 실행해요.
ID DC Name Class Drain Eligibility Status
237cd4c5 dc1 nomad <none> false eligible ready
또는 샘플 작업을 생성하고 실행해요.
Example job file written to example.nomad.hcl
==> Monitoring evaluation "e9970e1d"
Evaluation triggered by job "example"
Allocation "a1f6c3e7" created: node "237cd4c5", group "cache"
Evaluation within deployment: "080460ce"
Evaluation status changed: "pending" -> "complete"
==> Evaluation "e9970e1d" finished with status "complete"
기존 클러스터를 TLS로 전환 (Switching an existing cluster to TLS)
Nomad는 TLS 및 비-TLS 통신에 서로 다른 포트를 사용하지 않기 때문에 TLS의 사용은 클러스터 전체에 걸쳐 일관되어야 해요. 기존 클러스터를 어디에서나 TLS를 사용하도록 전환하는 것은 운영상으로는 Nomad 버전 간 업그레이드와 유사하지만, 할당(allocation)을 불필요하게 재스케줄링하지 않도록 추가 단계가 필요해요.
- 모든 노드에 적절한 키와 인증서를 추가해요. 프라이빗 키 파일이 Nomad 사용자만 읽을 수 있는지 확인해요.
- CLI를 사용하는 모든 노드에 환경 변수를 추가해요.
- 모든 노드의 구성 파일에 적절한
tls블록을 추가해요. - 가십(gossip) 키를 생성하고 Nomad 서버 구성에 추가해요.
서버의 정족수(quorum)가 TLS를 활성화하면 클라이언트는 자체 클라이언트 구성이 업데이트되고 다시 로드될 때까지 서버와 통신할 수 없게 돼요.
이 시점에서 클러스터의 롤링 재시작이 어디에서나 TLS를 활성화해요. 그러나 서버가 재시작되면 클라이언트는 하트비트를 보낼 수 없어요. 즉, 하트비트 TTL이 만료되기 전에 TLS를 활성화해 재시작할 수 없는 클라이언트는 할당이 lost로 표시되고 재스케줄링돼요.
기본 하트비트 설정이 할당이 lost로 표시되지 않고 소수의 노드를 동시에 재시작하는 데 충분할 수 있지만, 대부분의 운영자는 서버를 재시작하기 전에 heartbeat_grace 구성 설정을 높여야 해요:
- 서버에서
heartbeat_grace = "1h"또는 적절한 기간을 설정해요. - 서버를 한 번에 하나씩 재시작해요.
- 클라이언트를 한 번에 하나 이상 재시작해요.
heartbeat_grace를 이전 값으로 되돌려요(또는 기본값을 받아들이려면 제거해요).- 서버를 한 번에 하나씩 재시작해요.
향후 릴리스에서 Nomad는 마이그레이션 중에 서버가 클라이언트의 TLS 및 비-TLS 연결을 모두 수락하도록 허용해 클러스터를 TLS로 업그레이드할 수 있게 할 거예요.
클러스터에서 실행 중인 작업은 영향을 받지 않으며, 모든 클라이언트가 하트비트 TTL 내에 재시작할 수 있다면 전환 내내 계속 실행될 거예요.
Nomad 인증서 동적 변경 (Changing Nomad certificates on the fly)
0.7.1부터 Nomad는 SIGHUP을 통한 동적 인증서 다시 로드를 지원해요.
다음과 같은 사전 TLS 구성이 있다고 가정해요:
http = true
rpc = true
ca_file = "nomad-ca.pem"
cert_file = "server.pem"
key_file = "server-key.pem"
verify_server_hostname = true
verify_https_client = true
}
TLS 스탠자를 다음으로 업데이트하면 Nomad의 cert_file과 key_file을 SIGHUP으로 다시 로드할 수 있어요:
http = true
rpc = true
ca_file = "nomad-ca.pem"
cert_file = "new_server.pem"
key_file = "new_server_key.pem"
verify_server_hostname = true
verify_https_client = true
}
클러스터를 TLS로 마이그레이션 (Migrating a cluster to TLS)
SIGHUP으로 TLS 구성 다시 로드 (Reloading TLS configuration via SIGHUP)
Nomad는 클라이언트와 서버의 TLS 구성을 모두 동적으로 다시 로드하는 것을 지원해요. 에이전트의 TLS 구성을 다시 로드하려면 먼저 에이전트의 구성 파일에서 TLS 블록을 업데이트한 다음 Nomad 에이전트에 SIGHUP 신호를 보내요. 참고로 이 작업은 TLS 구성을 포함한 구성 파일의 일부만 다시 로드해요.
SIGHUP을 통한 구성 다시 로드 중에 TLS 구성에 변화가 있으면 에이전트는 모든 네트워크 연결을 다시 로드해요. 새로 수립된 연결은 업데이트된 구성을 사용하고, 진행 중인 기존 연결은 닫혀요. 이 과정은 TLS로 업그레이드하거나, TLS에서 다운그레이드하거나, 인증서를 롤링할 때 작동해요.
Nomad 서버용 RPC 업그레이드 모드 (RPC upgrade mode for Nomad servers)
TLS로 마이그레이션할 때 Nomad 서버의 TLS 구성에서 rpc_upgrade_mode 옵션(기본값 false)을 true로 설정할 수 있어요. true로 설정하면 서버가 TLS 및 비-TLS 연결을 모두 수락해요. 비-TLS 연결을 수락함으로써 운영자는 클라이언트 연결이 TLS를 통하지 않아 서버가 거부해 클라이언트가 lost로 표시되지 않고도 클라이언트를 TLS로 업그레이드할 수 있어요. 그러나 rpc_upgrade_mode는 마이그레이션 과정의 임시 솔루션으로 사용해야 하고, 클러스터 전체가 마이그레이션된 후에는 이 옵션을 다시 false로 설정해야 한다는 점(즉, 서버가 오직 TLS 연결만 엄격히 수락한다는 의미)을 주의해야 해요.