인생은 여행

Vault HA 구성 with Consul 본문

Vault

Vault HA 구성 with Consul

산떠 버하둘 2021. 8. 9. 18:46

이 문서는 Hashicorp 홈페이지의 Vault High Availability with Consul 라는 문서에 주석을 더하여 번역하였습니다. 일부 오역이 있을 수 있음을 감안하여 주십시오.
Vault는 오픈소스 버전과 유료의 Enterprise 버전이 있습니다. Vault는 오픈소스 버전 만으로도 실 업무에 사용하기에 부족함이 없을 것으로 보입니다(많이 사용해 보지는 않아서 확신은...). Vault를 프로덕트에 적용하기 위해서는 고가용성(HA) 구성이 필수적이라 할 수 있는데, Vault 만으로는 HA 구성이 불가능하고 비밀 저장 백엔드를 Consul이나 Zookeeper 같은 서비스의 클러스터로 구성하여야 합니다(v1.4 부터는 raft라는 이름의 통합 저장소(Integrated Storage)를 지원하는데 이 저장소는 자체적으로 데이터 복제(replication)를 지원합니다). 이 문서는 Vault - Consul HA 구성에 대한 상세한 설명과 함께 단계적으로 따라서 해 볼 수 있는 자습서입니다.

Vault는 다중 서버 운용을 통하여 고가용성 모드에서 실행할 수 있습니다. Vault는 일반적인 컴퓨팅 요구 사항보다는 스토리지 백엔드의 IO 제한에 영향을 받습니다. Consul 같은 특정 스토리지 백엔드는 Vault가 고가용성 설정으로 실행되도록 추가적인 조정 기능을 제공하는 반면, 다른 백엔드는 보다 강력한 백업 및 복원 프로세스를 제공합니다.

HA 모드에서 실행할 때 Vault 서버에서는 Standby 및 Active의 두 가지 추가 상태가 있습니다. Vault 클러스터 내에서 단일 인스턴스만 Active되어 모든 요청(읽기 및 쓰기)을 처리하고 모든 Standby 노드는 요청을 Active 노드로 리디렉션합니다.

 

NOTE: 버전 0.11부터 Standby 노드는 read-replica 노드로써 대부분의 읽기 전용 요청을 처리할 수 있습니다. 이 Performance Standby Nodes 기능은 Vault Enterprise 기능의 일부입니다. 이는 대용량 Encryption as a Service(Transit secrets engine) 요청을 처리하는 데 특히 유용합니다. 자세한 내용은 Performance Standby Nodes documentationPerformance Standby tutorial 문서를 읽어 보세요.

transit 엔진의 경우 실시간으로 암호화 및 복호화를 수행하기 때문에 상대적으로 CPU 자원을 많이 사용합니다. 이런 transit 요청이 많다면 active-active 클러스터를 지원하는 엔터프라이즈 기능이 필요할 수도 있겠습니다.

여기에서는 기본적인 Vault 고가용성(HA) 클러스터를 구축하는 방법을 배웁니다. 이것은 드롭인 프로덕션 예제로 사용할 수 있는 완전하거나 규범적인 튜토리얼은 아니지만 자신의 프로덕션 설정을 위한 기본 사항을 충분하게 다루고 있습니다.

드롭인(drop-in) 프로덕트: 시장에 바로 진입하여 경쟁할 수 있는 상태의 제품

준비

이 중급 Vault 작업 튜토리얼은 귀하가 Vault 및 Consul에 대한 사전 지식을 가지고 있다고 가정합니다.

시나리오 소개

우리의 목표는 다음과 같이 Vault HA를 구성하는 것입니다.

  • 2 Vault Servers: 1 active, 1 standby
  • 3 Consul Servers 클러스터

Vault Reference Architecture 문서에서 권장하는 클러스터 아키텍처를 설명합니다. Vault HA 클러스터를 프로비저닝하기 위한 Terraform 모듈이 vault-guides 레포지토리에 있습니다.

이 자습서는, 더 나은 이해를 위해 Vault HA 클러스터를 만드는 수동 단계를 안내하는 것이 목적입니다.

참조 다이어그램

이 다이어그램은 참조용 심플 아키텍처의 세부 정보를 보여 줍니다.

자습서에서는 다음 절차를 수행할 것입니다.

이 자습서의 목적을 위해 Vault 및 Consul의 오픈소스 버전을 사용합니다. 그러나 설정은 엔터프라이즈 버전과 동일합니다.

Step 1: Setup a Consul server cluster

이 자습서의 Consul 서버는 IP 주소로만 정의되지만 레이블(label)로도 참조됩니다.

  • consul_s1: 10.1.42.101
  • consul_s2: 10.1.42.102
  • consul_s3: 10.1.42.103

NOTE: 이 자습서에서는 Consul 바이너리가 /usr/local/bin/consul에 있다고 가정하지만, 다른 경우 경로 참조를 적절하게 조정합니다.

이를 염두에 두고, 기본적인 Consul 서버 구성 시작점은 다음과 같습니다.

{
  "server": true,
  "node_name": "$NODE_NAME",
  "datacenter": "dc1",
  "data_dir": "$CONSUL_DATA_PATH",
  "bind_addr": "0.0.0.0",
  "client_addr": "0.0.0.0",
  "advertise_addr": "$ADVERTISE_ADDR",
  "bootstrap_expect": 3,
  "retry_join": ["$JOIN1", "$JOIN2", "$JOIN3"],
  "ui": true,
  "log_level": "DEBUG",
  "enable_syslog": true,
  "acl_enforce_version_8": false
}

일부 값에는 변수 placeholer가 포함되어 있고 나머지에는 적절한 기본 값이 있습니다. 예제를 기반으로 고유한 Consul 서버 설정에서 다음 값을 바꿔야 합니다.

  • $NODE_NAME: 노드를 지칭하는 고유한 레이블; 여기에서는 consul_s1, consul_s2, consul_s3입니다.
  • $CONSUL_DATA_PATH: Consul 데이터 디렉토리의 절대 경로. 이 디렉토리는 Consul 프로세스 사용자가 쓰기 가능해야 합니다.
  • $ADVERTISE_ADDR: 해당 Consul 서버가 클러스터의 다른 서버에 알리는 것으로 선호하는 주소로 설정하되 0.0.0.0으로 설정하면 안 됩니다. 이 자습서에서는 각 Consul 서버의 주소 또는 각각 10,1.42.101, 10.1.42.102, 10.1.42.103으로 설정해야 합니다.
  • $JOIN1, $JOIN2, $JOIN3: 이 예제에서는 클러스터를 형성하기 위해 서버 에이전트를 조인하는 retry_join 방법을 사용합니다. 따라서 이 자습서의 값은 각각 10,1.42.101, 10.1.42.102, 10.1.42.103입니다.

웹 사용자 인터페이스가 활성화되어 있고("ui": true), Consul 서버는 디버깅 수준으로 시스템 로그를 남깁니다("log_level": "DEBUG"). 이 자습서의 목적을 위해 acl_enforce_version_8은 ACL에 대해 걱정할 필요가 없도록 false로 설정됩니다. 그러나 프로덕션 환경에서는 ACL을 활성화하고 자세한 내용은 Consul ACL Guide를 따르십시오.

NOTE: Consul 에이전트 설정 파일에 대한 제세한 내용은 Consul 문서를 참조하십시오.

각 Consul 서버의 설정 파일을 생성하고 /usr/local/etc/consul/<node_name>.json으로 저장합니다.

다음은 consul_s1.json의 예입니다.

{
  "server": true,
  "node_name": "consul_s1",
  "datacenter": "dc1",
  "data_dir": "/var/consul/data",
  "bind_addr": "0.0.0.0",
  "client_addr": "0.0.0.0",
  "advertise_addr": "10.1.42.101",
  "bootstrap_expect": 3,
  "retry_join": ["10.1.42.101", "10.1.42.102", "10.1.42.103"],
  "ui": true,
  "log_level": "DEBUG",
  "enable_syslog": true,
  "acl_enforce_version_8": false
}

다음은 consul_s2.json의 예입니다.

{
  "server": true,
  "node_name": "consul_s2",
  "datacenter": "dc1",
  "data_dir": "/var/consul/data",
  "bind_addr": "0.0.0.0",
  "client_addr": "0.0.0.0",
  "advertise_addr": "10.1.42.102",
  "bootstrap_expect": 3,
  "retry_join": ["10.1.42.101", "10.1.42.102", "10.1.42.103"],
  "ui": true,
  "log_level": "DEBUG",
  "enable_syslog": true,
  "acl_enforce_version_8": false
}

다음은 consul_s3.json의 예입니다.

{
  "server": true,
  "node_name": "consul_s3",
  "datacenter": "dc1",
  "data_dir": "/var/consul/data",
  "bind_addr": "0.0.0.0",
  "client_addr": "0.0.0.0",
  "advertise_addr": "10.1.42.103",
  "bootstrap_expect": 3,
  "retry_join": ["10.1.42.101", "10.1.42.102", "10.1.42.103"],
  "ui": true,
  "log_level": "DEBUG",
  "enable_syslog": true,
  "acl_enforce_version_8": false
}

이 인스턴스가 서버 모드에서 실행될 것임을 나타내기 위해 server 파라미터가 true로 설정되었음을 주목하십시오.

Consul systemd 단위 파일

Consul 바이너리와 적절한 기본 구성이 준비되었으면 이제 각 서버 인스턴스에서 Consul을 시작하기만 하면 됩니다. systemd가 대부분의 최신 Linux 배포판에서 널리 사용되는 점을 고려하여 다음과 같이 systemd 단위 파일(/etc/systemd/system/consul.service)을 구성하였습니다.

### BEGIN INIT INFO
# Provides:          consul
# Required-Start:    $local_fs $remote_fs
# Required-Stop:     $local_fs $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Consul agent
# Description:       Consul service discovery framework
### END INIT INFO

[Unit]
Description=Consul server agent
Requires=network-online.target
After=network-online.target

[Service]
User=consul
Group=consul
PIDFile=/var/run/consul/consul.pid
PermissionsStartOnly=true
ExecStartPre=-/bin/mkdir -p /var/run/consul
ExecStartPre=/bin/chown -R consul:consul /var/run/consul
ExecStart=/usr/local/bin/consul agent \
    -config-file=/usr/local/etc/consul/consul_s1.json \
    -pid-file=/var/run/consul/consul.pid
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
KillSignal=SIGTERM
Restart=on-failure
RestartSec=42s

[Install]
WantedBy=multi-user.target

다음 값들은 스타일이나 파일시스템 계층 표준 준수 수준에 따라 변경이 필요할 수 있습니다.

  • -config-file
  • -pid-file

각 서버에서 단위 파일을 정의하고 저장하면, systemctl daemon-reload를 수행한 다음 Consul 서비스를 시작할 수 있습니다.

Step 2: Start and verify the Consul cluster state

data_dir로 지정된 경로에 대한 소유권과 권한이 올바른지 확인한 후, 각 시스템에서 Consul 서비스를 시작하고 상태를 확인하십시오.

systemd를 사용하여 Consul 에이전트를 시작합니다.

$ sudo systemctl start consul

Consul 에이전트의 상태를 체크합니다.

$ sudo systemctl status consul

consul.service - Consul server agent
   Loaded: loaded (/etc/systemd/system/consul.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2019-05-23 21:48:18 UTC; 11s ago
 Main PID: 2068 (consul)
    Tasks: 13
   Memory: 13.6M
      CPU: 0m 52.784s
   CGroup: /system.slice/consul.service
           └─2068 /usr/local/bin/consul agent -config-file=/usr/local/etc/consul/server_agent.json -pid-file=/var/run/consul/consul.pid

 

모든 Consul 서버를 시작한 후 Consul 클러스터 상태를 체크합니다.

$ consul members

Node       Address           Status  Type    Build  Protocol  DC    Segment
consul_s1  10.1.42.101:8301  alive   server  1.0.6  2         dc1   <all>
consul_s2  10.1.42.102:8301  alive   server  1.0.6  2         dc1   <all>
consul_s3  10.1.42.103:8301  alive   server  1.0.6  2         dc1   <all>

클러스터의 상태가 양호해 보이고 3개의 서버가 모두 표시됩니다. 계속하기 전에 리더가 있는지 확인하십시오.

$ consul operator raft list-peers

Node                   ID                                    Address           State     Voter  RaftProtocol
consul_s2              536b721f-645d-544a-c10d-85c2ca24e4e4  10.1.42.102:8300  follower  true   3
consul_s1              e10ba554-a4f9-6a8c-f662-81c8bb2a04f5  10.1.42.101:8300  follower  true   3
consul_s3              56370ec8-da25-e7dc-dfc6-bf5f27978a7a  10.1.42.103:8300  leader    true   3

위 출력은 이 예제에서 consul_s3가 현재 클러스터의 리더인 것을 보여줍니다. 이제 Vault 서버 설정 단계로 이동할 수 있습니다.

Step 3: Setup Consul client agents on Vault nodes

Vault 서버에서는 각 노드에 Consul 및 Vault 바이너리가 모두 필요합니다. Consul은 클라이언트 에이전트로 구성되고 Vault는 서버로 구성됩니다.

Consul 클라이언트 에이전트 구성

Consul은 고가용성 스토리지 백엔드를 제공하는 데 사용되므로, Vault 서버의 Consul 에이전트를 Consul 서버 클러스터와 통신하여 헬스체크 등록, 서비스 디스커버리, 클러스터 HA 패일오버(failover) 조정(클러스터 리더십) 하도록 구성해야 합니다.

Note that it is not recommended to connect the Vault servers directly to the Consul servers.

Consul 클라이언트 에이전트는 Consul 서버 클러서트에 대한 네트워크 통신을 위해 Vault 서버와 동일한 주소를 사용하지만 Vault가 루프백 인터페이스를 통해 연결할 수 있도록 루프백 인터페이스에만 client_address 를 바인딩합니다.

다음은 Consul 클라이언트 에이전트의 구성 예입니다.

{
  "server": false,
  "datacenter": "dc1",
  "node_name": "$NODE_NAME",
  "data_dir": "$CONSUL_DATA_PATH",
  "bind_addr": "$BIND_ADDR",
  "client_addr": "127.0.0.1",
  "retry_join": ["$JOIN1", "$JOIN2", "$JOIN3"],
  "log_level": "DEBUG",
  "enable_syslog": true,
  "acl_enforce_version_8": false
}

Step1에서 수행한 작업과 유사하게 고유한 Consul 클라이언트 에이전트 구성에서 다음 값을 적절하게 바꿉니다.

  • $NODE_NAME: 노드에 대한 고유한 레이블, 여기에서는 각각 consul_c1, consul_c2가 될 것입니다.
  • $CONSUL_DATA_PATH: Consul 데이터 디렉토리의 절대 경로, Consul 프로세스가 쓰기 가능해야 합니다.
  • $BIND_ADDR: 이것은 Consul 서버가 클러스터의 다른 서버에 알리는 것을 선호하는 주소로 설정되어야 하며 0.0.0.0으로 설정되어서는 안 됩니다. 이 자습서의 경우 구성 파일의 각 인스턴스에 있는 Vault 서버의 IP 주소 또는 각각 10.1.42.201 및 10.1.42.202로 설정해야 합니다.
  • $JOIN1, $JOIN2, $JOIN3: 이 예제에서는 클러스터를 형성하기 위해 서버 에이전트를 조인하는 retry_join 방법을 사용합니다. 따라서 이 자습서의 값은 각각 10,1.42.101, 10.1.42.102, 10.1.42.103입니다.

각 Consul 에이전트의 설정 파일을 생성하고 /usr/local/etc/consul/<node_name>.json으로 저장합니다.

다음은 consul_c1.json의 예입니다.

{
  "server": false,
  "datacenter": "dc1",
  "node_name": "consul_c1",
  "data_dir": "/var/consul/data",
  "bind_addr": "10.1.42.201",
  "client_addr": "127.0.0.1",
  "retry_join": ["10.1.42.101", "10.1.42.102", "10.1.42.103"],
  "log_level": "DEBUG",
  "enable_syslog": true,
  "acl_enforce_version_8": false
}
{
  "server": false,
  "datacenter": "dc1",
  "node_name": "consul_c2",
  "data_dir": "/var/consul/data",
  "bind_addr": "10.1.42.202",
  "client_addr": "127.0.0.1",
  "retry_join": ["10.1.42.101", "10.1.42.102", "10.1.42.103"],
  "log_level": "DEBUG",
  "enable_syslog": true,
  "acl_enforce_version_8": false
}

이 인스턴스가 클라이언트 모드에서 실행될 것임을 나타내기 위해 server 매개변수가 false로 설정되어 있습니다.

Consul systemd 단위 파일

Consul 바이너리와 적절한 기본 구성이 준비되었으면 이제 각 서버 인스턴스에서 Consul을 시작하기만 하면 됩니다. 다음과 같이 systemd 단위 파일을 구성하였습니다.

### BEGIN INIT INFO
# Provides:          consul
# Required-Start:    $local_fs $remote_fs
# Required-Stop:     $local_fs $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Consul agent
# Description:       Consul service discovery framework
### END INIT INFO

[Unit]
Description=Consul client agent
Requires=network-online.target
After=network-online.target

[Service]
User=consul
Group=consul
PIDFile=/var/run/consul/consul.pid
PermissionsStartOnly=true
ExecStartPre=-/bin/mkdir -p /var/run/consul
ExecStartPre=/bin/chown -R consul:consul /var/run/consul
ExecStart=/usr/local/bin/consul agent \
    -config-file=/usr/local/etc/consul/consul_c1.json \
    -pid-file=/var/run/consul/consul.pid
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
KillSignal=SIGTERM
Restart=on-failure
RestartSec=42s

[Install]
WantedBy=multi-user.target

필요에 따라 다음 값을 변경하십시오.

  • config-file
  • pid-file

각 Vault 서버에서 단위 파일을 정의하고 저장하면(예, /etc/systemd/system/consul.service), systemctl daemon-reload를 수행한 다음 Consul 서비스를 시작할 수 있습니다.

Consul을 시작하고 해당 클러스터 상태를 확인하여 설정에서 data_dir 값으로 지정한 경로의 소유권과 권한이 올바른지 확인한 다음, 각 시스템에서 Consul 서비스를 시작하고 상태를 확인합니다.

$ sudo systemctl start consul
$ sudo systemctl status consul

consul.service - Consul client agent
   Loaded: loaded (/etc/systemd/system/consul.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2019-05-23 21:48:18 UTC; 11s ago
 Main PID: 23758 (consul)
    Tasks: 11
   Memory: 9.8M
      CPU: 571ms
   CGroup: /system.slice/consul.service
           └─23758 /usr/local/bin/consul agent -config-file=/usr/local/etc/consul/client_agent.json -pid-file=/var/run/consul/consul.pid

모든 Consul 클라이언트 에이전트를 시작하고 나서 Consul 클러스터의 상태를 체크합니다.

$ consul members

Node        Address           Status  Type    Build  Protocol  DC    Segment
consul_s1   10.1.42.101:8301  alive   server  1.0.6  2         dc1   <all>
consul_s2   10.1.42.102:8301  alive   server  1.0.6  2         dc1   <all>
consul_s3   10.1.42.103:8301  alive   server  1.0.6  2         dc1   <all>
consul_c1   10.1.42.201:8301  alive   client  1.0.6  2         arus  <default>
consul_c2   10.1.42.202:8301  alive   client  1.0.6  2         arus  <default>
NOTE: Consul 클러스터 아키텍처에 대해 더 배우고자 한다면 Consul Reference Architecture 자습서를 참고하십시오. 또한 Consul 클러스터 배포에 대해 자세한 내용은 Deployment Guide를 참고하십시오.

Step 4: Configure the Vault servers

이제 Vault 서버를 위한 3개의 서버와 2개의 클라이언트 에이전트로 구성된 Consul 클러스터가 있으므로 Vault HA 설정을 부트스트랩할 수 있도록 Vault에 대한 구성과 시작 스크립트를 함께 가져와 보겠습니다.

이 튜토리얼의 Vault 서버는 IP 주소로만 정의되지만 레이블로도 참조됩니다.

  • vault_s1: 10.1.42.201
  • vault_s2: 10.1.42.202

구성 파일에서 다음을 설정합니다.

이 섹션에서는 Vault 바이너리가 /usr/local/bin/vault에 있다고 가정합니다.

Vault 구성

listener "tcp" {
  address          = "127.0.0.1:8200"
  cluster_address  = "127.0.0.1:8201"
  tls_disable      = "true"
}

storage "consul" {
  address = "127.0.0.1:8500"
  path    = "vault/"
}

api_addr =  "$API_ADDR"
cluster_addr = "$CLUSTER_ADDR"
이 자습서에서는 리스너 절에서 TLS를 비활성화하지만 프로덕션 환경에서 클라이언트와 Vault 서버 간의 안전한 통신을 위해서는 항상 TLS와 함께 사용하여야 합니다. 이를 위해서는 각 Vault 호스트마다 인증서 파일과 키 파일이 필요합니다.

tcp 리스너에서 다음의 파라미터를 설정합니다.

  • address (string: "127.0.0.1:8200"): 수신을 위해 바인딩할 주소를 지정합니다.
  • cluster_address (string: "127.0.0.1:8201"): 클러스터 서버 간 요청에 대해 바인딩할 주소를 지정합니다. 이는 기본적으로 address 포트 값보다 1 높은 수치입니다. 일반적으로 설정할 필요는 없지만 Vault 서버가 서로 격리되어 TCP 로드발란서 또는 다른 체계를 경유(hop)하여 통신해야하는 경우 필요할 수 있습니다.

이 구성을 사용하면 모든 인터페이스에서 수신 대기할 수 있습니다(예, 루프백 주소에 대한 Vault 명령이 성공함).

또한 Vault의 HA 파라미터(api_addr 및 cluster_addr)를 명시적으로 설정하고 있습니다. Consul을 Vault의 스토리지 백엔드로 사용할 때, 경우에 따라 Consul이 자동으로 active Vault 노드의 주소를 찾고 전파하려고 시도하므로 이 두 파라미터를 구성할 필요가 없습니다. 그러나 어떤 클러스터 구성에서는 명시적으로 설정할 필요가 있습니다(예, 로드발란서(LB)를 통한 Vault 접근).

단순화를 위하여, 이 시나리오에서는 로드발란서를 통해서 접속하는 대신에 Vault 노드에 직접 접속하는 것으로 하겠습니다. 클라이언트 접근 패턴과 그 의미에 대한 자세한 내용은 Client Redirection 문서를 검토하십시오.

일부 값들은 변수 placeholder가 포함되어 있고 나머지에는 적절한 기본값이 있습니다. 다음의 값들은 예제에 기반하여 각자의 Vault 서버 구성에 맞는 값으로 변경하십시오.

  • $API_ADDR: 클라이언트 리디렉션을 위해 다른 Vault 서버에게 통지할 주소(full URL). 환경 변수 VAULT_API_ADDR을 통해 제공될 수도 있습니다. 일반적으로 이것은 리스너 주소 값을 가리키는 전체 URL로 설정해야 합니다. 이 시나리오에서는 각각 http://10.1.42.201:8200 와 http://10.1.42.202:8200이 되어야 합니다.
  • $CLUSTER_ADDR: 요청 전달을 위해 클러스터의 다른 Vault 서버에 광고할 주소를 지정합니다. 이는 환경 변수 VAULT_CLUSTER_ADDR을 통해 제공될 수도 있습니다. 이것은 api_addr과 같은 전체 URL입니다. 이 시나리오에서는 각각 https://10.1.42.201:8201 및 https://10.1.42.202:8201이 됩니다.
여기에 있는 scheme(https)는 무시됩니다. 모든 클러스터 구성원은 항상 개인키/인증서 쌍과 함께 TLS를 사용합니다.

vault_s1.hcl 예제

listener "tcp" {
  address          = "0.0.0.0:8200"
  cluster_address  = "10.1.42.201:8201"
  tls_disable      = "true"
}

storage "consul" {
  address = "127.0.0.1:8500"
  path    = "vault/"
}

api_addr = "http://10.1.42.201:8200"
cluster_addr = "https://10.1.42.201:8201"

vault_s2.hcl 예제

listener "tcp" {
  address          = "0.0.0.0:8200"
  cluster_address  = "10.1.42.202:8201"
  tls_disable      = "true"
}

storage "consul" {
  address = "127.0.0.1:8500"
  path    = "vault/"
}

api_addr = "http://10.1.42.202:8200"
cluster_addr = "https://10.1.42.202:8201"

Vault 서버 systemd 단위 파일

Vault 바이너리와 함께 적절하게 Consul 로컬 클라이언트 에이전트로 구성한 기본 설정이 있습니다. 이제 각 서버 인스턴스에서 Vault를 시작하기만 하면 됩니다. 다음은 systemd 단위 파일의 예입니다.

### BEGIN INIT INFO
# Provides:          vault
# Required-Start:    $local_fs $remote_fs
# Required-Stop:     $local_fs $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Vault server
# Description:       Vault secret management tool
### END INIT INFO

[Unit]
Description=Vault secret management tool
Requires=network-online.target
After=network-online.target

[Service]
User=vault
Group=vault
PIDFile=/var/run/vault/vault.pid
ExecStart=/usr/local/bin/vault server -config=/etc/vault/vault_server.hcl -log-level=debug
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
KillSignal=SIGTERM
Restart=on-failure
RestartSec=42s
LimitMEMLOCK=infinity

[Install]
WantedBy=multi-user.target

다음 값들은 스타일이나 파일시스템 계층 표준 준수 수준에 따라 변경이 필요할 수 있습니다.

  • -config-file
  • -pid-file

각 서버에서 단위 파일을 /etc/systemd/system/vault.service 같은 파일로 정의하고 저장하면, systemctl daemon-reload를 수행한 다음 Vault 서비스를 시작할 수 있습니다.

Step 5: Start Vault and verify its State

각 서버에서 Vault 서비스를 시작하십시오.

$ sudo systemctl start vault
$ sudo systemctl status vault

vault.service - Vault secret management tool
   Loaded: loaded (/etc/systemd/system/vault.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2019-05-23 21:48:18 UTC; 11s ago
 Main PID: 2080 (vault)
    Tasks: 12
   Memory: 71.7M
      CPU: 50s
   CGroup: /system.slice/vault.service
           └─2080 /usr/local/bin/vault server -config=/home/ubuntu/vault_nano/config/vault_server.hcl -log-level=debug

이제 Vault 서버를 초기화하고 봉인해제할 수 있습니다.

Vault 초기화

$ vault operator init

이렇게 하면 Consul에서 저장소를 준비하고 active Vault 서버를 결정합니다. 기본적으로 초기화 프로세스에서는 인메모리 마스터키가 생성되고 Shamir의 비밀 공유 알고리즘을 적용하여 해당 마스터키를 분해합니다. 마스터키를 분해하기 위해서 설정에 있는 키공유(key shares) 값 만큼 봉인해제 키가 생성되어 사용됩니다. 봉인해제, 즉 마스터키를 재조립하기 위해서는 마찬가지로 설정에 있는 쿼럼 형성 수 만큼의 봉인해제 키가 필요합니다. 기본적으로 5개의 키가 공유되고 봉인해제를 위한 쿼럼 형성에는 3개의 공유키가 필요합니다.

클러스터 내 각 Vault 서버는 이러한 봉인해제 키를 사용할 수 있으며 각 Vault 서버는 사용하기 전에 봉인을 해제해야 합니다.

다음은 기본 초기화의 출력 예입니다.

Unseal Key 1: mK3KawqyUfzaxF+cvH7PjvUQENhWSawvydi9aZpcJZpO
Unseal Key 2: Ptzj1SuPwY/kMl2soujwnelBiMP6oizAMDkEN9O/5EKd
Unseal Key 3: 4BTEyTEU+ffDQMKZzTIuZcbZfH0jKEk8nN04RDiTI4z9
Unseal Key 4: zi8m4wlzya6PKV8fFdl//OtIPrmascpBnfcKAlwdx3MM
Unseal Key 5: 264hCHpfTC4N/dURRjht9RyFsW0tUq647q3A022Z+qyC

Initial Root Token: s.NiJ2kO6H49ckdNBsMiXyo7uR

Vault initialized with 5 key shares and a key threshold of 3. Please securely
distribute the key shares printed above. When the Vault is re-sealed,
restarted, or stopped, you must supply at least 3 of these keys to unseal it
before it can start servicing requests.

Vault does not store the generated master key. Without at least 3 key to
reconstruct the master key, Vault will remain permanently sealed!

It is possible to generate new unseal keys, provided you have a quorum of
existing unseal keys shares. See "vault operator rekey" for more information.

출력에는 나중에 Vault에 인증할 수 있는 초기 루트 토큰도 포함됩니다.

Vault를 성공적으로 초기화했으므로 먼저 vault_s1 서버의 봉인을 해제하십시오.

$ vault operator unseal <unseal_key_1>

임계 값에 도달할 때까지 다른 봉인해제 키를 입력하십시오.

$ vault operator unseal <unseal_key_2>

임계 값 만큼 봉인해제 키를 입력하면 Vault 서버는 봉인해제되어 사용할 수 있는 상태가 됩니다.

$ vault operator unseal <unseal_key_3>

Key                    Value
---                    -----
Seal Type              shamir
Initialized            true
Sealed                 false
Total Shares           5
Threshold              3
Version                1.4.0-rc1
Cluster Name           vault-cluster-5f9488de
Cluster ID             4175d4b0-58d4-f60d-1488-9860f2d53e9b
HA Enabled             true
HA Cluster             n/a
HA Mode                standby
Active Node Address    <none>

이제 Vault를 초기화할 때 생성 및 출력된 봉인해제 키를 사용하여 두 번째 Vault 서버(vault_s2)를 봉인해제하십시오.

Standby Vault 서버에서 Vault 상태를 체크하십시오.

$ vault status

Key                    Value
---                    -----
Seal Type              shamir
Initialized            true
Sealed                 false
Total Shares           5
Threshold              3
Version                1.4.0-rc1
Cluster Name           vault-cluster-5f9488de
Cluster ID             4175d4b0-58d4-f60d-1488-9860f2d53e9b
HA Enabled             true
HA Cluster             https://10.1.42.201:8201
HA Mode                standby
Active Node Address:   http://10.1.42.201:8200

이 시점에서 Vault 서버는 HA 모드에서 작동하며 active 또는 standby Vault 인스턴스에서 비밀을 쓸 수 있어야 하며 요청 전달 테스트로 성공했는지 확인할 수 있습니다. 또한 active 인스턴스를 종료(sudo systemctl stop vault)하여 시스템 오류를 시뮬레이션하고 standby 인스턴스가 리더십을 차지하는 것을 확인할 수 있습니다.

Help and Reference

NOTE: Provision a Best Practices Vault Cluster in AWS 에서는 AWS에서 Vault HA 클러스터를 프로비저닝하기 위한 Terraform 자산을 제공합니다. 최소 3개의 가용 영역(AZs)이 있는 AWS 리전을 선택해야 합니다.

'Vault' 카테고리의 다른 글

Vault KV Secrets Engine  (0) 2021.07.22
Vault Seal/Unseal  (0) 2021.07.20
Vault의 AppRole을 사용하는 권장 패턴  (0) 2021.07.18
Comments