02月27, 2017

kubernetes + etcd ssl 支持

在kubernetes和etcd部署的时候都会遇到需要添加SSL/TLS认证的需求,但目前网上这部分的介绍很少,所以作为学习的笔记将这部分的内容补充一下。

关于SSL/TLS的支持详见:

对于kubernetes和etcd的部署我们在kuberntes中已经介绍了,这里不再涉及。我们重点介绍一下SSL/TLS证书制作相关内容。 首先我们来认识几个概念:SSL、TLS、HTTPS、X.509、CRT、CSR、PEM

SSL:(Secure Socket Layer,安全套接字层),用以保障在Internet上数据传输之安全,利用数据加密(Encryption)技术,可确保数据在网络上之传输过程中不会被截取。它已被广泛地用于Web浏览器与服务器之间的身份认证和加密数据传输。

TLS:(Transport Layer Security,传输层安全协议),用于两个应用程序之间提供保密性和数据完整性。它建立在SSL 3.0协议规范之上,是SSL 3.0的后续版本,可以理解为SSL 3.1,它是写入了 RFC 的。该协议由两层组成: TLS 记录协议(TLS Record)和 TLS 握手协议(TLS Handshake)。较低的层为 TLS 记录协议,位于某个可靠的传输协议(例如 TCP)上面。

HTTPS:咱们通常所说的 HTTPS 协议,说白了就是“HTTP 协议”和“SSL/TLS 协议”的组合,给HTTP协议添加了安全层。 如果原来的 HTTP 是塑料水管,容易被戳破;那么如今新设计的 HTTPS 就像是在原有的塑料水管之外,再包一层金属水管。一来,原有的塑料水管照样运行;二来,用金属加固了之后,不容易被戳破。

X.509:这是一种证书标准,主要定义了证书中应该包含哪些内容.其详情可以参考RFC5280,SSL使用的就是这种证书标准.

CRT:(Certificate,证书),常见于*NIX系统,有可能是PEM编码,也有可能是DER编码,大多数应该是PEM编码,相信你已经知道怎么辨别.

CSR:(Certificate Signing Request,即证书签名请求),这个并不是证书,而是向权威证书颁发机构获得签名证书的申请,其核心内容是一个公钥(当然还附带了一些别的信息),在生成这个申请的时候,同时也会生成一个私钥,私钥要自己保管好.做过iOS APP的朋友都应该知道是怎么向苹果申请开发者证书的吧.

PEM:(Privacy Enhanced Mail), 是 X.509 的一种编码格式(以"-----BEGIN..."开头, "-----END..."结尾,内容是BASE64编码)。还有一种是DER。

OpenSSL: 是一个安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用。

基础知识介绍这些,如果还有疑惑,看这里聊聊HTTPS和SSL/TLS协议、这里数字证书CA及扫盲、这里互联网加密及OpenSSL介绍和简单使用

SSL/TSL 认证分单向认证和双向认证两种方式。简单说就是单向认证只是客户端对服务端的身份进行验证,双向认证是客户端和服务端互相进行身份认证。就比如,我们登录淘宝买东西,为了防止我们登录的是假淘宝网站,此时我们通过浏览器打开淘宝买东西时,浏览器会验证我们登录的网站是否是真的淘宝的网站,而淘宝网站不关心我们是否“合法”,这就是单向认证。而双向认证是服务端也需要对客户端做出认证。具体原理可以参考这里SSL双向认证和单向认证的区别

因为大部分 kubernetes 基于内网部署,而内网应该都会采用私有 IP 地址通讯,权威 CA 好像只能签署域名证书,对于签署到 IP 可能无法实现。所以我们需要预先自建 CA 签发证书。

自签CA

对于私有证书签发首先要自签署一个 CA 根证书,这里我们要用到上面讲到的 openssl 工具,openssl配置文件(通常是/etc/ssl/openssl.conf)如下:

####################################################################
[ ca ]
default_ca      = CA_default            # The default ca section

####################################################################
[ CA_default ]

dir             = ./demoCA              # Where everything is kept
certs           = $dir/certs            # Where the issued certs are kept
crl_dir         = $dir/crl              # Where the issued crl are kept
database        = $dir/index.txt        # database index file.
#unique_subject = no                    # Set to 'no' to allow creation of
                                        # several ctificates with same subject.
new_certs_dir   = $dir/newcerts         # default place for new certs.

certificate     = $dir/cacert.pem       # The CA certificate
serial          = $dir/serial           # The current serial number
crlnumber       = $dir/crlnumber        # the current crl number
                                        # must be commented out to leave a V1 CRL
crl             = $dir/crl.pem          # The current CRL
private_key     = $dir/private/cakey.pem# The private key
RANDFILE        = $dir/private/.rand    # private random number file

x509_extensions = usr_cert              # The extentions to add to the cert

# Comment out the following two lines for the "traditional"
# (and highly broken) format.
name_opt        = ca_default            # Subject Name options
cert_opt        = ca_default            # Certificate field options

# Extension copying option: use with caution.
# copy_extensions = copy

# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
# so this is commented out by default to leave a V1 CRL.
# crlnumber must also be commented out to leave a V1 CRL.
# crl_extensions        = crl_ext

default_days    = 365                   # how long to certify for
default_crl_days= 30                    # how long before next CRL
default_md      = default               # use public key default MD
preserve        = no                    # keep passed DN ordering

# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy          = policy_match

# For the CA policy
[ policy_match ]
countryName             = match # 两个字符表示的国家代码,CN为中国
stateOrProvinceName     = match # 省或洲的完整名称
organizationName       = match  # 组织机构名称(默认为公司)
organizationalUnitName  = optional # 组织机构单元名称(eg.部门)
commonName              = supplied # 持有者名或者所在服务器主机名(即域名)
emailAddress            = optional # 管理员邮件地址

根据实际需要调整参数,一般我们要修改的几个参数有: default_days: 证书的有效期,这个有效期,可以设置的长一点,减少更新证书的工作。 policy_match: 其子项可以根据公司实际信息填写,使证书尽量规范化、标准化。

配置文件修改完成后我们就可以通过openssl来自签CA了

生成私钥 openssl genrsa -out demoCA/private/cakey.pem 2048

生成一个自签名的证书,来标明自己的身份,签名方法如下 openssl req -new -x509 -key demoCA/private/cakey.pem -out demoCA/cacert.pem

-new:生成新证书签署请求; -x509:生成自签格式证书,专用于创建私有CA时; -key:生成请求时用到的私有文件路径; -out:生成的请求文件路径;如果自签操作将直接生成签署过的证书; -days:证书的有效时长,单位是day;

申请证书

生成公钥 openssl genrsa -out ca.key 2048 申请证书签署请求 openssl req -new -key ca.key -out ca.csr 使用 CA 进行签署,生成证书 openssl ca -in mycrt/ca.csr -out mycrt/ca.crt

到此,证书生成。就是这么简单。

到这里,或许你还不知道这些证书到具体场景该怎么用,那么我们就以kubernetes为例,来说一下怎么在具体业务中使用。

对于一套系统来说只有一套 CA,通过这个统一的 CA 来给 server 端和 client 端办法证书。

生成 server 端证书

生成 apiserver 私钥
openssl genrsa -out server-key.pem 2048
生成签署请求
openssl req -new -key server-key.pem -out server.csr -subj "/CN=kube-server"

注意:CN 可以将范围限制的更精确,例如:SERVER.k8s.com 或 *.SERVER.k8s.com

使用自建 CA 签署
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt

生成 client 端证书

先声明两个变量方便引用 WORKER_FQDN=kube-client # 这里我们是给client生成了一个统配的证书node名,如果是单独给某个主机生成证书,这里需要改成其IP或主机名

生成 node 私钥
openssl genrsa -out ${WORKER_FQDN}.key 2048
生成 签署请求
openssl req -new -key ${WORKER_FQDN}.key -out ${WORKER_FQDN}.csr -subj "/CN=${WORKER_FQDN}"
使用自建 CA 签署
openssl x509 -req -in ${WORKER_FQDN}.csr -CA ca.pem -CAkey ca-key -CAcreateserial -out ${WORKER_FQDN}.crt

配置kubernetes

配置master

证书生成好以后,我们开始配置master,首先将server端的证书复制到所有server节点(目录随便,但最好标准,我们这里是统一放到/etc/kubernetes/ssl下)

编辑 master 配置文件,这里apiserver、scheduler、controller-manager我们使用的一个配置文件 vim /etc/kubernetes/master-config

认证相关配置如下

KUBE_API_ARGS="--tls-cert-file=/etc/kubernetes/ssl/server.crt  \
               --tls-private-key-file=/etc/kubernetes/ssl/server.key \
               --client-ca-file=/etc/kubernetes/ssl/ca.crt "

配置node

KUBELET_ARGS="--tls-cert-file=/etc/kubernetes/ssl/kube-client.crt --tls-private-key-file=/etc/kubernetes/ssl/kube-client.key"

至此,就完成了TLS认证的配置。

最后,推荐一款同事发现的一个制作证书非常简单的工具easy-rsa,有了这款工具,证书制作变得so easy。

本文链接:https://www.opsdev.cn/post/tls-for-kubernetes-etcd.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。