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