介绍
如果您计划在您控制之外的网络环境中运行 CoreOS 集群,例如在共享数据中心或公共互联网中,您可能已经注意到etcd
通过进行未加密的 HTTP 请求进行通信。
幸运的是,etcd 支持对等 TLS/SSL 连接,这样一个群集的每个成员都被验证了,所有的通信都被加密了. 在本指南中,我们将开始提供一个简单的群集,包括三个成员,然后在每个机器上配置 HTTPS 终端和基本的防火墙。
前提条件
本指南主要基于在 本介绍 CoreOS 系统组件和 本指南在 DigitalOcean 上设置 CoreOS 集群中讨论的概念。
您应该熟悉etcd
,fleetctl
,cloud-config
文件的基本知识,并生成一个发现URL。
为了创建和访问集群中的机器,您需要与您的 DigitalOcean 帐户相关联的 SSH 公共密钥。
如果您想使用 DigitalOcean API 来创建您的 CoreOS 机器,请参阅 本教程以获取有关如何生成和使用个人访问令牌的信息。
创建新发现 URL
通过访问 https://discovery.etcd.io/new?size=3在您的浏览器中,复制显示的 URL,或使用从本地机器的终端的弯曲
:
1curl -w "\n" "https://discovery.etcd.io/new?size=3"
保存返回的 URL;我们将很快在我们的云配置
中使用它。
写一个包含 HTTPS 配置的云配置文件
我们将从写一个云配置
开始。在初始化每个服务器时,云配置
将作为用户数据提供,为集群定义重要配置细节. 这个文件将很长,但不应该比基本集群指南中的版本复杂得多(https://andsky.com/tech/tutorials/how-to-set-up-a-coreos-cluster-on-digitalocean).我们将明确告诉fleet
使用HTTPS终端,为我们的防火墙启用一个名为iptables-restore
的服务,并写出配置文件,告诉etcd
和fleet
在哪里找到SSL证书。
在本地计算机上打开终端,确保您在主目录中,并使用nano
(或您最喜欢的文本编辑器)创建和打开~/cloud-config.yml
:
1cd ~
2nano cloud-config.yml
粘贴以下内容,然后在etcd2
节中更改https://discovery.etcd.io/token
到你在最后一节声称的发现URL。
您也可以删除iptables-restore
部分,如果您不想启用防火墙。
当粘贴时要小心插入时,云配置
是用YAML编写的,这是对白空间敏感的。 请参阅文件中的评论,以获取有关特定行的信息,然后我们将更详细地讨论一些重要的部分。
1[label ~/cloud-config.yml]
2#cloud-config
3
4coreos:
5 etcd2:
6 # generate a new token for each unique cluster from https://discovery.etcd.io/new:
7 discovery: https://discovery.etcd.io/token
8 # multi-region deployments, multi-cloud deployments, and Droplets without
9 # private networking need to use $public_ipv4:
10 advertise-client-urls: https://$private_ipv4:2379,https://$private_ipv4:4001
11 initial-advertise-peer-urls: https://$private_ipv4:2380
12 # listen on the official ports 2379, 2380 and one legacy port 4001:
13 listen-client-urls: https://0.0.0.0:2379,https://0.0.0.0:4001
14 listen-peer-urls: https://$private_ipv4:2380
15 fleet:
16 # fleet defaults to plain HTTP - explicitly tell it to use HTTPS on port 4001:
17 etcd_servers: https://$private_ipv4:4001
18 public-ip: $private_ipv4 # used for fleetctl ssh command
19 units:
20 - name: etcd2.service
21 command: start
22 - name: fleet.service
23 command: start
24 # enable and start iptables-restore
25 - name: iptables-restore.service
26 enable: true
27 command: start
28write_files:
29 # tell etcd2 and fleet where our certificates are going to live:
30 - path: /run/systemd/system/etcd2.service.d/30-certificates.conf
31 permissions: 0644
32 content: |
33 [Service]
34 # client environment variables
35 Environment=ETCD_CA_FILE=/home/core/ca.pem
36 Environment=ETCD_CERT_FILE=/home/core/coreos.pem
37 Environment=ETCD_KEY_FILE=/home/core/coreos-key.pem
38 # peer environment variables
39 Environment=ETCD_PEER_CA_FILE=/home/core/ca.pem
40 Environment=ETCD_PEER_CERT_FILE=/home/core/coreos.pem
41 Environment=ETCD_PEER_KEY_FILE=/home/core/coreos-key.pem
42 - path: /run/systemd/system/fleet.service.d/30-certificates.conf
43 permissions: 0644
44 content: |
45 [Service]
46 # client auth certs
47 Environment=FLEET_ETCD_CAFILE=/home/core/ca.pem
48 Environment=FLEET_ETCD_CERTFILE=/home/core/coreos.pem
49 Environment=FLEET_ETCD_KEYFILE=/home/core/coreos-key.pem
作为一个可选的步骤,您可以将云配置
粘贴到 官方的 CoreOS 云配置验证器并按 验证云配置。
在「nano」中,您可以用 Ctrl-X来退出, y来确认写文件,和 Enter来确认要保存的文件名。
让我们看看从cloud-init.yml
中的一些特定的块,首先是fleet
值:
1fleet:
2 # fleet defaults to plain HTTP - explicitly tell it to use HTTPS:
3 etcd_servers: https://$private_ipv4:4001
4 public-ip: $private_ipv4 # used for fleetctl ssh command
请注意,etcd_servers
设置为https
URL. 对于简单的 HTTP 操作,这个值不需要设置. 但是,如果没有明确的配置,HTTPS 将失败($private_ipv4
是一个由 CoreOS 初始化过程理解的变量,而不是你需要改变的变量)。
然后我们进入了write_files
块,值被分成一个文件系统path
,permissions
面具和content
,其中包含一个文件的所需内容。
1write_files:
2 # tell etcd2 and fleet where our certificates are going to live:
3 - path: /run/systemd/system/etcd2.service.d/30-certificates.conf
4 permissions: 0644
5 content: |
6 [Service]
7 # client environment variables
8 Environment=ETCD_CA_FILE=/home/core/ca.pem
9 ...
10 - path: /run/systemd/system/fleet.service.d/30-certificates.conf
11 permissions: 0644
12 content: |
13 [Service]
14 # client auth certs
15 Environment=FLEET_ETCD_CAFILE=/home/core/ca.pem
16 ...
虽然我们告诉服务在哪里找到证书文件,但我们还不能提供文件本身. 为此,我们需要知道每个CoreOS机器的私人IP地址,这只有在机器被创建后才可用。
<$>[注] 注: 在CoreOS Droplets中,在创建Droplet后,无法更改‘Cloud-config’的内容,并且在每次启动时都会重新执行该文件。
供应滴
现在我们已经定义了cloud-config.yml
,我们将使用它来提供群集的每个成员。在DigitalOcean上,我们可以采取两种基本方法:通过基于Web的控制面板,或使用命令行中的cURL向DigitalOcean API进行调用。
使用数字海洋控制面板
在同一数据中心区域内创建三个新的 CoreOS 滴滴,请确保每次检查 私人网络和 启用用户数据。
- coreos-1
- coreos-2
- coreos-3
在用户数据
字段中,从上方粘贴cloud-config.yml
的内容,确保您在文件顶部附近的发现
字段中插入了发现 URL。
使用 DigitalOcean API
作为一种可以节省重复粘贴到字段的替代方法,我们可以写一个短的Bash脚本,它使用弯曲
来请求从DigitalOcean API使用我们的云配置
,并呼吁每一个Droplet一次。
1cd ~
2nano makecoreos.sh
粘贴并保存下面的脚本,根据您的集群所需调整区域
和大小
字段(nyc3
和512mb
的默认值适用于演示目的,但您可能想要一个不同的区域或更大的Dropplets用于现实世界项目):
1[label ~/makecoreos.sh]
2#!/usr/bin/env bash
3
4# A basic Droplet create request.
5curl -X POST "https://api.digitalocean.com/v2/droplets" \
6 -d'{"name":"'"$1"'","region":"nyc3","size":"512mb","private_networking":true,"image":"coreos-stable","user_data":
7"'"$(cat ~/cloud-config.yml)"'",
8 "ssh_keys":[ "'$DO_SSH_KEY_FINGERPRINT'" ]}' \
9 -H "Authorization: Bearer $TOKEN" \
10 -H "Content-Type: application/json"
现在,让我们将环境变量 $DO_SSH_KEY_FINGERPRINT 和 $TOKEN 设置为与您的 DigitalOcean 帐户相关联的 SSH 密钥的指纹和 API Personal Access Token。
有关获取个人访问令牌和使用API的信息,请参阅 本教程。
要找到与您的帐户相关联的密钥的指纹,请检查您的帐户设置的 安全性部分(https://cloud.digitalocean.com/settings/security),在 SSH 密钥下。
我们在这里使用导出
,以便壳的子过程,如makecoreos.sh
,能够访问变量. 无论在使用脚本时,都必须在当前壳中设置,否则API调用将失败:
1export DO_SSH_KEY_FINGERPRINT="ssh_key_fingerprint"
2export TOKEN="your_personal_access_token"
<$>[注] 注: 如果您刚刚为 API 生成了一个个人访问令牌,请记住保持方便和安全。
一旦我们为每一个所需的凭证设置了环境变量,我们就可以运行脚本来创建每一个想要的Droplet。 makecoreos.sh
使用其第一个参数来填写其 API 调用中的 `name' 字段:
1bash makecoreos.sh coreos-1
2bash makecoreos.sh coreos-2
3bash makecoreos.sh coreos-3
您应该看到 JSON 输出描述每一个新的 Droplet,并且所有三个都应该出现在控制面板中的 Droplets 列表中。
点击点击Coreos-1
无论您是否使用了控制面板或API,您现在都应该有三个运行 Droplets. 现在是注意他们的公共和私人IP的良好时机,这些IP在控制面板上可以通过单击单个 Droplet,然后点击 Settings链接来获取。
请确保您的 SSH 密钥被添加到您的本地 SSH 代理:
1eval $(ssh-agent)
2ssh-add
在 DigitalOcean 控制面板中找到 coreos-1 的公共 IP 地址,并连接到启用 SSH 代理转发:
1ssh -A core@coreos-1_public_ip
第一次登录到群集中的任何成员时,我们可能会收到来自systemd
的错误消息:
1[secondary_label Output]
2CoreOS stable (766.5.0)
3Failed Units: 1
4 iptables-restore.service
这表明防火墙尚未配置,目前无视此消息是安全的(如果您选择在云配置
中不启用防火墙,您将不会看到错误消息。
在我们担心防火墙之前,让我们在集群的每个成员上看到etcd2
实例彼此交谈。
使用CFSSL生成自签证书
CFSSL是由CloudFlare发布的TLS/SSL证书的工具包,在这篇文章写作时,它是CoreOS维护者选择的工具,用于生成自签证书,而不是OpenSSL和现在被贬值的etcd-ca
。
在本地机器上安装CFSSL
CFSSL 需要从源头安装一个工作 Go 安装,请参阅 此安装 Go 指南。
确保您的$GOPATH
设置正确并添加到您的$PATH
,然后使用go get
来安装cfssl
命令:
1export GOPATH=~/gocode
2export PATH=$PATH:$GOPATH/bin
3go get -u github.com/cloudflare/cfssl/cmd/cfssl
4go get -u github.com/cloudflare/cfssl/...
作为一种替代方法,可以从 pkg.cfssl.org获取预先构建的二进制。
1mkdir -p ~/bin
2export PATH=$PATH:~/bin
然后使用curl
来获取您平台的cfssl
和cfssljson
的最新版本:
1curl -s -L -o ~/bin/cfssl https://pkg.cfssl.org/R1.1/cfssl_linux-amd64
2curl -s -L -o ~/bin/cfssljson https://pkg.cfssl.org/R1.1/cfssljson_linux-amd64
确保cfssl
二进制是可执行的:
1chmod +x ~/bin/cfssl
2chmod +x ~/bin/cfssljson
生成证书权威
现在安装了cfssl
命令,我们可以使用它们来生成一个自定义证书权限,我们将使用它来签署我们每个CoreOS机器的证书。
1mkdir ~/coreos_certs
2cd ~/coreos_certs
现在,在nano
中创建并打开ca-config.json
(或您最喜欢的文本编辑器):
1nano ca-config.json
粘贴并保存以下内容,该内容将配置cfssl
如何进行签名:
1[label ~/coreos_certs/ca-config.json]
2{
3 "signing": {
4 "default": {
5 "expiry": "43800h"
6 },
7 "profiles": {
8 "client-server": {
9 "expiry": "43800h",
10 "usages": [
11 "signing",
12 "key encipherment",
13 "server auth",
14 "client auth"
15 ]
16 }
17 }
18 }
19}
值得注意的是到期期限
,目前设置为43800小时(或5年),以及客户端服务器
配置文件,其中包括服务器auth
和客户端auth
的使用。
接下来,创建并打开ca-csr.json
。
1nano ca-csr.json
粘贴以下内容,根据您的位置和组织所需调整CN
和名称
数组,可以安全地使用主机
输入以及地点和组织名称的虚构值:
1[label ~/coreos_certs/ca-csr.json]
2{
3 "CN": "My Fake CA",
4 "hosts": [
5 "example.net",
6 "www.example.net"
7 ],
8 "key": {
9 "algo": "rsa",
10 "size": 2048
11 },
12 "names": [
13 {
14 "C": "US",
15 "L": "CO",
16 "O": "My Company",
17 "ST": "Lyons",
18 "OU": "Some Org Unit"
19 }
20 ]
21}
<$>[注]
如果您想将这些值与 ca-config.json
和 ca-csr.json
的默认值进行比较,则可以使用 cfssl
打印默认值。
1cfssl print-defaults config
对于ca-csr.json
,请使用:
1cfssl print-defaults csr
美元
有了ca-csr.json
和ca-config.json
,生成证书权限:
1cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
生成和签署 CoreOS 机器的证书
现在我们有证书权限,我们可以为CoreOS机器写默认值:
创建并打开coreos-1.json
:
1nano coreos-1.json
粘贴并保存下列内容,将其调整为 coreos-1的私人IP地址(通过单个 Droplet 点击在 DigitalOcean 控制面板中可见):
1[label ~/coreos_certs/coreos-1.json]
2{
3 "CN": "coreos-1",
4 "hosts": [
5 "coreos-1",
6 "coreos-1.local",
7 "127.0.0.1",
8 "coreos-1_private_ip"
9 ],
10 "key": {
11 "algo": "rsa",
12 "size": 2048
13 },
14 "names": [
15 {
16 "C": "US",
17 "L": "Lyons",
18 "ST": "Colorado"
19 }
20 ]
21}
最重要的部分是CN
,这应该是您的主机名,以及主机
阵列,必须包含所有:
- 您的本地主机名(s)
127.0.0.1
- CoreOS 机器的私人 IP 地址(不是其面向公众的 IP)
这些将被添加到结果的证书为 subjectAltNames. etcd
连接(包括在 `127.0.0.1 上的本地循环设备)需要证书具有匹配连接主机名的 SAN。
您也可以更改名称
数组以反映您的位置,如果您想要的话。
对每个剩余的机器重复这个过程,创建一个与相应的主机
条目匹配的coreos-2.json
和coreos-3.json
。
<$>[注]
注: 如果您想查看 coreos-1.json
的默认值,您可以使用 cfssl
:
1cfssl print-defaults csr
美元
现在,对于每个CoreOS机器,生成一个签名的证书,并将其上传到正确的机器:
1cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client-server coreos-1.json | cfssljson -bare coreos
2chmod 0644 coreos-key.pem
3scp ca.pem coreos-key.pem coreos.pem core@coreos-1_public_ip:
这将创建三个文件(ca.pem
, coreos-key.pem
和 coreos.pem
),确保权限在 keyfile 上正确,并通过 scp
将其复制到 coreos-1上的 core的主目录。
对于剩余的每个机器,重复这个过程,记住每个命令的召唤都会重写上一组证书文件:
1cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client-server coreos-2.json | cfssljson -bare coreos
2chmod 0644 coreos-key.pem
3scp ca.pem coreos-key.pem coreos.pem core@coreos-2_public_ip:
1cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client-server coreos-3.json | cfssljson -bare coreos
2chmod 0644 coreos-key.pem
3scp ca.pem coreos-key.pem coreos.pem core@coreos-3_public_ip:
在 coreos-1 上检查 etcd2 功能
有了证书,我们应该能够在 coreos-1上运行fleetctl
。
1ssh -A core@coreos-1_public_ip
接下来,尝试列出群集中的所有机器:
1fleetctl list-machines
您应该看到列出的每个机器的标识符以及其私人IP地址:
1[secondary_label Output]
2MACHINE IP METADATA
37cb57440... 10.132.130.187 -
4d91381d4... 10.132.87.87 -
5eeb8726f... 10.132.32.222 -
如果「fleetctl」暂停无限期,则可能需要重新启动集群。
1exit
使用 SSH 向每个 CoreOS 机器发送重启
命令:
1ssh core@coreos-1_public_ip 'sudo reboot'
2ssh core@coreos-2_public_ip 'sudo reboot'
3ssh core@coreos-3_public_ip 'sudo reboot'
等待几分钟,重新连接到 coreos-1,然后再试试fleetctl
。
在集群成员中配置 IPTables 防火墙
有了证书,本地网络上的其他机器将无法控制您的集群或从etcd2
中提取值。然而,如果可能的话,最好减少可用的攻击面积。
请记住,如果我们在cloud-config
中启用了iptables-restore
服务,我们会在首次登录CoreOS机时看到systemd
错误消息:
1[secondary_label Output]
2CoreOS stable (766.5.0)
3Failed Units: 1
4 iptables-restore.service
这让我们知道,虽然该服务已启用,但iptables-restore
无法正确加载,我们可以使用systemctl
来诊断这种情况:
1systemctl status -l iptables-restore
1[secondary_label Output]
2● iptables-restore.service - Restore iptables firewall rules
3 Loaded: loaded (/usr/lib64/systemd/system/iptables-restore.service; enabled; vendor preset: disabled)
4 Active: failed (Result: exit-code) since Wed 2015-11-25 00:01:24 UTC; 27min ago
5 Process: 689 ExecStart=/sbin/iptables-restore /var/lib/iptables/rules-save (code=exited, status=1/FAILURE)
6 Main PID: 689 (code=exited, status=1/FAILURE)
7
8Nov 25 00:01:24 coreos-2 systemd[1]: Starting Restore iptables firewall rules...
9Nov 25 00:01:24 coreos-2 systemd[1]: iptables-restore.service: Main process exited, code=exited, status=1/FAILURE
10Nov 25 00:01:24 coreos-2 systemd[1]: Failed to start Restore iptables firewall rules.
11Nov 25 00:01:24 coreos-2 iptables-restore[689]: Can't open /var/lib/iptables/rules-save: No such file or directory
12Nov 25 00:01:24 coreos-2 systemd[1]: iptables-restore.service: Unit entered failed state.
13Nov 25 00:01:24 coreos-2 systemd[1]: iptables-restore.service: Failed with result 'exit-code'.
这里有很多信息,但最有用的行是包含iptables-restore[689]
的行,这就是试图与其过程ID一起运行的过程systemd
的名称,这就是我们经常找到失败服务的实际错误输出的地方。
防火墙未能恢复,因为,虽然我们在云配置
中启用了iptables-restore
,但我们还没有提供包含我们想要的规则的文件。
在编辑器中打开一个新的文件,粘贴以下内容,并用每个CoreOS机的私有IP地址代替coreos-1_private_ip
,coreos-2_private_ip
和coreos-3_private_ip
。
1[label /var/lib/iptables/rules-save]
2*filter
3:INPUT DROP [0:0]
4:FORWARD DROP [0:0]
5:OUTPUT ACCEPT [0:0]
6
7# Accept all loopback (local) traffic:
8-A INPUT -i lo -j ACCEPT
9
10# Accept all traffic on the local network from other members of
11# our CoreOS cluster:
12-A INPUT -i eth1 -p tcp -s coreos-1_private_ip -j ACCEPT
13-A INPUT -i eth1 -p tcp -s coreos-2_private_ip -j ACCEPT
14-A INPUT -i eth1 -p tcp -s coreos-3_private_ip -j ACCEPT
15
16# Keep existing connections (like our SSH session) alive:
17-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
18
19# Accept all TCP/IP traffic to SSH, HTTP, and HTTPS ports - this should
20# be customized for your application:
21-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
22-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
23-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
24
25# Accept pings:
26-A INPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT
27-A INPUT -p icmp -m icmp --icmp-type 3 -j ACCEPT
28-A INPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT
29COMMIT
将上述内容复制到剪辑板上,登录到 coreos-1,并使用 Vim打开规则保存
,这是 CoreOS 上的默认文本编辑器:
1ssh -A core@coreos-1_public_ip
1sudo vim /var/lib/iptables/rules-save
一旦进入编辑器,键入 :set paste
并按 Enter 以确保自动插入被关闭,然后按 i 进入插入模式并粘贴您的防火墙规则。
<$>[警告] 警告: 请确保文件的最后一行上有新线条,否则IPTables可能会导致混淆的语法错误,尽管文件中的所有命令都显示正确。
最后,请确保文件具有适当的权限(为用户阅读和写入,仅为组和世界阅读):
1sudo chmod 0644 /var/lib/iptables/rules-save
现在我们应该准备好再次尝试服务:
1sudo systemctl start iptables-restore
如果成功,‘systemctl’会默默地退出,我们可以通过两种方式检查防火墙的状态,首先是使用‘systemctl status’:
1sudo systemctl status -l iptables-restore
第二,通过列出当前的iptables
规则本身:
1sudo iptables -v -L
我们使用-v
选项来获得无语的输出,这将让我们知道一个规则适用于哪个界面。
一旦您确信 coreos-1上的防火墙已配置,请退出:
1exit
接下来,重复此过程以在 coreos-2 和 coreos-3 上安装 /var/lib/iptables/rules-save
。
结论
在本指南中,我们定义了三个成员的基本 CoreOS 集群,每个成员都提供了一个 TLS/SSL 证书用于身份验证和运输安全,并使用防火墙来阻止本地数据中心网络上的其他 Droplets 的连接,这有助于缓解在共享网络上使用 CoreOS 的许多基本安全问题。
从这里,您可以应用本系列的其余部分(https://www.digitalocean.com/community/tutorial_series/getting-started-with-coreos-2)中的技术来定义和管理服务。