kubernetes学习笔记(一)
一、证书工具
1.1、证书工具介绍
证书制作工具:openssl;cfssl;keytool;makecert
问题1:啥叫HTTPS?
场景:我是小明想和小红聊骚,但又怕别人听见。于是我们就各自制作了一个一对儿密钥。因为担心被别人瞅见(害羞),因此就约定暴露自己的公钥。然对方用自己的私钥加密聊天内容。这样就实现了加密只要私钥不丢失不被人看见了。然后这个策略被小刚和小雨复用了,他俩也准备学习,生成了密钥。但是不巧的是被小黑发现了。小黑自己制作了一套密钥。然后发给小刚说他是小雨,发给小雨说他是小刚。小刚和小雨因此就被偷窥了。为了避免被偷听,因此我们决定了,去公安局(CA)把自己的证书登记一下,公安局让我们填写下自己的家庭地址、工作地 ... ;然后CA用自己的私钥加密我们的数据,这样再和小红通信的时候,我就可以先向小红要证书、公钥,随机数...,然后验证证书内容(用CA的公钥解密,CA权威不权威,内容是否有误...);然后生成一个对称加密密码(认证阶段用非对阵加密,传输阶段用对称加密,主要是考虑传输效率快),用小红的公钥加密。这样再也不用担心小黑了,而且即使消息发错人了也没事,因为只有小红自己的私钥可以解决传输密码,且传输过程中,每次使用的通信过程的密码都不一样
问题2:啥是证书信任链?
CA用自己的私钥加密的证书,我们用CA的公钥去(一般本地会持有根证书)解密就得到证书的签名摘要(证明此CA是真CA)。当我们再次用相同的摘要算法(证书里面有保存所使用的算法)对整个证书做签名,如果得到的签名和证书上的签名是一致的(证明是CA签署的),说明这个证书是可信任的。证书信任链说白了就是我毕业证发了,老师说我发的(校长授权的),校长说我发的(教育部授权的),教育部(根CA,我们都承认的一个部分)。我拿到证书后会先验证他的证书发布机构(不是根证书就查他的上级办法机构,直到根证书)。我信任班主任->班主任信任校长->校长信任教育部。k8s要求的ca必须是根证书
问题3:自签证书是啥:(证书如果不是由一个独立的ca签署的签署的证书,称为自签证书)
自签名证书必须直接信任(而不是通过信任CA间接信任),或者根本不信任。通常,我们的客户端CA证书是自签名的,因为它们代表我们信任关系的“根”:客户端必须天生信任CA。
问题4:单向认证和双向认证
单项认证:一般说的是client认证server端的。比如我们访问baidu,一般我们只需要验证badiu是不是真的baidu,而baidu不需要认证client是否是合法的客户端
双向认证:client认证server的证书,server也会去认证client的证书,由server端决定是否需要双向认证,一般用于限定特定的客户端才能访问
针对openssl推荐笔者之前的博客:https://blog.51cto.com/hmtk520/1983793
keytool为jdk自带,也非常方便使用,可自行查阅资料了解。这里主要介绍CFSSL
1.2、CFSSL用法概述
CFSSL is CloudFlare's PKI/TLS swiss army knife. It is both a command line tool and an HTTP API server for signing, verifying, and bundling TLS certificates. It requires Go 1.12+ to build
安装这里不再赘述:yum或者源码编译安装。主要有三个工具:cfssl、cfssljson、cfssl-certinfo
1、证书编码结构:
PEM(Privacy Enhanced Mail),通常用于数字证书认证机构(Certificate Authorities,CA),扩展名为.pem, .crt, .cer, 和 .key。内容为Base64编码的ASCII码文件,有类似"-----BEGIN CERTIFICATE-----" 和 "-----END CERTIFICATE-----"的头尾标记
DER(Distinguished Encoding Rules),与PEM不同之处在于其使用二进制而不是Base64编码的ASCII。扩展名为.der,但也经常使用.cer用作扩展名,所有类型的认证证书和私钥都可以存储为DER格式
CSR(Certificate Signing Request),它是客户端向CA机构申请数字×××书时使用的请求文件
2、安装
Git地址:https://github.com/cloudflare/cfssl
二进制下载:https://pkg.cfssl.org/
工具包:
cfssl:使用CFSSL包的规范命令行实用程序
cfssljson:同cfssl bundle
cfssl-newkey:
multirootca:可以使用多个签名密钥的证书颁发机构服务器
mkbundle:生成证书池绑定
3、命令行介绍
cfssl:
genkey generate a private key and a certificate request
gencert generate a private key and a certificate
gencrl generate a new Certificate Revocation List
sign signs a certificate
serve start the API server
revoke revoke a certificate in the certificate store
selfsign generates a self-signed certificate
print-defaults print default configurations
certinfo output certinfo about the given cert
info get info about a remote signer
version prints out the current version
[root@localhost work]# cfssl print-defaults config #ca配置文件
{
"signing": {
"default": {
"expiry": "168h"
},
"profiles": {
"www": {
"expiry": "8760h",
"usages": [
"signing",
"key encipherment",
"server auth"
]
},
"client": {
"expiry": "8760h",
"usages": [
"signing",
"key encipherment",
"client auth"
]
}
}
}
}
策略说明:
profiles:可以定义多个 ,分别指定不同的过期时间、使用场景等参数。cfssl gencert的时候需要指定profile说明使用哪个场景
signing:表示证书可用于签名其它证书,生成的 ca.pem 证书中CA=TRUE;
server auth:表示client可以用该该证书对 server 提供的证书进行验证;
key encipherment:用于密钥加密
client auth:表示server可以用该该证书对 client 提供的证书进行验证;
[root@localhost work]# cfssl print-defaults csr #证书请求文件
{
"CN": "example.net",
"hosts": [
"example.net",
"www.example.net"
],
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "<country>",
"ST": "<state>",
"L": "<city>",
"O": "<organization>",
"OU": "<organization unit>"
}
]
}
(CN)Common Name: kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name),浏览器使用该字段验证网站是否合法;
O:Organization,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group); kube-apiserver 将提取的 User、Group 作为 RBAC 授权的用户标识;
C = <country> 国家
ST = <state> 州,省
L = <city> 城市
O = <organization> 组织名称/公司名称
OU = <organization unit> 组织单位/公司部门
1.3、CFSSL使用案例
案例1:生成自签CA
1)、创建ca-config.json
[root@localhost work]# cat ca-config.json
{
"signing": {
"default": {
"expiry": "8760h"
},
"profiles": {
"etcd": {
"expiry": "8760h",
"usages": [
"server auth",
"client auth",
"key encipherment"
]
},
"master": {
"expiry": "8760h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
},
"node": {
"expiry": "4380h",
"usages": [
"server auth",
"key encipherment",
"client auth"
]
}
}
}
}
2)、创建ca-csr.json
[root@localhost work]# cat ca-csr.json
{
"CN": "kubernetes-ca",
"key": {
"algo": "rsa",
"size": 4096
},
"names": [
{
"C": "CN",
"ST": "HangZhou",
"L": "HangZhou",
"O": "DevOps",
"OU": "line1"
}
],
"ca": {
"expiry": "876000h"
}
}
3)、生成证书
[root@localhost work]# cfssl gencert -config=./ca-config.json -initca ca-csr.json | cfssljson -bare ca
2020/12/14 11:27:47 [INFO] generating a new CA key and certificate from CSR
2020/12/14 11:27:47 [INFO] generate received request
2020/12/14 11:27:47 [INFO] received CSR
2020/12/14 11:27:47 [INFO] generating key: rsa-4096
2020/12/14 11:27:49 [INFO] encoded CSR
2020/12/14 11:27:49 [INFO] signed certificate with serial number 37137515052047904666345348590620497645548812027
[root@localhost work]# ll
总用量 20
-rw-r--r-- 1 root root 757 12月 14 10:42 ca-config.json
-rw-r--r-- 1 root root 1748 12月 14 11:27 ca.csr //ca的证书签署请求
-rw-r--r-- 1 root root 253 12月 14 11:26 ca-csr.json
-rw------- 1 root root 3243 12月 14 11:27 ca-key.pem //ca的私钥
-rw-r--r-- 1 root root 2025 12月 14 11:27 ca.pem //公钥
4)、查看证书
[root@localhost work]# cfssl-certinfo -cert ca.pem
{
"subject": {
"common_name": "kubernetes-ca",
"country": "CN",
"organization": "DevOps",
"organizational_unit": "line1",
"locality": "HangZhou",
"province": "HangZhou",
"names": [
"CN",
"HangZhou",
"HangZhou",
"DevOps",
"line1",
"kubernetes-ca"
]
},
"issuer": {
"common_name": "kubernetes-ca",
"country": "CN",
"organization": "DevOps",
"organizational_unit": "line1",
"locality": "HangZhou",
"province": "HangZhou",
"names": [
"CN",
"HangZhou",
"HangZhou",
"DevOps",
"line1",
"kubernetes-ca"
]
},
"serial_number": "37137515052047904666345348590620497645548812027",
"not_before": "2020-12-14T03:23:00Z",
"not_after": "2120-11-20T03:23:00Z",
"sigalg": "SHA512WithRSA",
"authority_key_id": "",
"subject_key_id": "F4:A7:51:C9:8E:40:3B:75:74:49:07:5F:96:12:51:30:BF:30:69:7E",
"pem": "-----BEGIN CERTIFICATE-----\nMIIFqjCCA5KgAwIBAgIUBoFNw94/E1bbkTJCOQbZ0iXfNvswDQYJKoZIhvcNAQEN\nBQAwbDELMAkGA1UEBhMCQ04xETAPBgNVBAgTCEhhbmdaaG91MREwDwYDVQQHEwhI\nYW5nWmhvdTEPMA0GA1UEChMGRGV2T3BzMQ4wDAYDVQQLEwVsaW5lMTEWMBQGA1UE\nAxMNa3ViZXJuZXRlcy1jYTAgFw0yMDEyMTQwMzIzMDBaGA8yMTIwMTEyMDAzMjMw\nMFowbDELMAkGA1UEBhMCQ04xETAPBgNVBAgTCEhhbmdaaG91MREwDwYDVQQHEwhI\nYW5nWmhvdTEPMA0GA1UEChMGRGV2T3BzMQ4wDAYDVQQLEwVsaW5lMTEWMBQGA1UE\nAxMNa3ViZXJuZXRlcy1jYTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB\nANDrcAsxY0+0JdY+btZJ7Y94Ca54Ysj38JQPX4lDMqZj0+o2G0J+ExR6ZxwnYquU\n7gniAcby93uVBuSCBLX8pF0yVSHlA1MOLo+aEpI/7JZuw+pp7AxEEHzQ4P16kRrS\nBgGRH2N2+l0aOAz7tHD4RoLs+o8BjozWLLirMvIABgdA8N9rqzsBZ9RimcwWnPdC\nMaemSLAgEsgRu47adQpDgHNTZWgRdjayanyrbUoKm6efwyrfopfMVfiEIgKaX4MS\n87KCRbtPbsjhR2MyrrJx81URedfXp4hNb2c0FNQ0vmTlRwQZiGjyLYCf0s/EQkHJ\ntNLVB2O5DGgCrnzTXFBH32d1EKuYljrMbch+pA5RZfnX32RytFW1KLBtD0zVZpwx\nH0ujG1b4gw2Rj+/ADuNMGipo1v5bYkZOxt7IEoCKxU6cRz/MXQn89iM+j4VpUUGs\ncFk+Wll+2JiVkROCXXRXsecHWrs/7f/D/XIejycy4QWFF9cV4cNNA4R4MNFDkYMk\nmtAy0CEgE89YfrQM6gTuMZ5/YbIomeuA30SlFKDfsiM02NH67c4t1mpDp2f3a0lZ\nzBHBxbkJWJV725tjEI0JHorp17/8Len1dkczk2bVTW2hzQdajuBnkN0s87JX0eQa\nQnvyEBdZxa9oOQEJcLA8IFGFixPNaMjJlI6o+e1MmA59AgMBAAGjQjBAMA4GA1Ud\nDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBT0p1HJjkA7dXRJ\nB1+WElEwvzBpfjANBgkqhkiG9w0BAQ0FAAOCAgEALxE5pvFwjIQxoQRkojKp8/hn\nR6rRi3WNVVuUnCFr+jQzDP56a7BBiv2xVLdLMQQ9qOvQ9RQhZt/UiwB6dN1vE95Y\ndAtkVz8yITo8NTsrWxW1pXT1MI4/dXAzCa7xTHGxCxh+csXCdNlxwJTbWvMXlCTX\n8eKvRM7xjkVg29q/OtTZDM5/uG75LXCt/+83ywNOrPXA1so/UgTjcBK++As4NWDw\n2EmR4UXCr02lEmRZ7NHr5idyEDhuIpKZvnIdm6oiaoOuLKEv7lt8VXUg13ZtLMJA\ny9KVmJL8SqBIzTFRLV8FXD6SaKgaK6GSKPkkeCauS+AvfAG2oD3nJCTAyxCQV7rY\n/JdrzZDSjcklK97pKOD7ZSa64FbNTWMUkp0J83isDqhLC90G+Frl9l9HFf6nbJI+\n8Y4vzAj0t+thkGmG1OinCu54iijJdLx9YZSZBJATWLSpOQyx7soOEPbKCHe5nlgG\nFXjGYHZL4St0Yr403SZJeGgFDGy6TXMjEriqrAAJklZolf/+ePISwxmz4Mb83k+H\nIBIFxM+VWAupnA6XdRf2agQhDsSHwyHdBhkedJ1LxmXAbyAODkRaJi1la9En7vdv\n2h+L1KOtY1ROzP+bi49PI6XiUAD3U27eSEMmSiiLInwZWau46TL/Kd74WuG8lPlF\nDxpxhMjTCSwTPdonHNA=\n-----END CERTIFICATE-----\n"
}
5)、查看csr
[root@localhost work]# cfssl certinfo -csr=./ca.csr // 内容太长,这里忽略
案例2:签署请求
[root@localhost etcd]# cat etcd-csr.json
{
"CN": "etcd",
"hosts": [
"127.0.0.1",
"192.168.153.129",
"192.168.153.130",
"192.168.153.131"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "HangZhou",
"L": "HangZhou",
"O": "DevOps",
"OU": "line1"
}
]
}
[root@localhost etcd]# cfssl gencert -ca ../ca.pem -ca-key ../ca-key.pem -config ../ca-config.json -profile=etcd etcd-csr.json | cfssljson -bare etcd
2020/12/14 13:36:02 [INFO] generate received request
2020/12/14 13:36:02 [INFO] received CSR
2020/12/14 13:36:02 [INFO] generating key: rsa-2048
2020/12/14 13:36:02 [INFO] encoded CSR
2020/12/14 13:36:02 [INFO] signed certificate with serial number 532942753251767919271193259496893196907203191678
1.4、远程签署
1、启动签署服务器
[root@localhost work]# cfssl serve -address 192.168.153.129 -port 8888 -ca ./ca.pem -ca-key ./ca-key.pem -int-dir ./tmp -config ./ca-config.json -loglevel=12020/12/14 13:56:19 [INFO] Initializing signer
2020/12/14 13:56:19 [WARNING] couldn't initialize ocsp signer: open : no such file or directory
2020/12/14 13:56:19 [INFO] bundler API ready
2020/12/14 13:56:19 [INFO] endpoint '/api/v1/cfssl/bundle' is enabled
2020/12/14 13:56:19 [INFO] endpoint '/api/v1/cfssl/init_ca' is enabled
2020/12/14 13:56:19 [INFO] endpoint '/api/v1/cfssl/scan' is enabled
2020/12/14 13:56:19 [WARNING] endpoint 'ocspsign' is disabled: signer not initialized
2020/12/14 13:56:19 [INFO] endpoint '/api/v1/cfssl/sign' is enabled
2020/12/14 13:56:19 [WARNING] endpoint 'authsign' is disabled: {"code":5200,"message":"Invalid or unknown policy"}
2020/12/14 13:56:19 [INFO] endpoint '/api/v1/cfssl/gencrl' is enabled
2020/12/14 13:56:19 [INFO] endpoint '/api/v1/cfssl/certinfo' is enabled
2020/12/14 13:56:19 [WARNING] endpoint 'revoke' is disabled: cert db not configured (missing -db-config)
2020/12/14 13:56:19 [INFO] endpoint '/' is enabled
2020/12/14 13:56:19 [INFO] endpoint '/api/v1/cfssl/info' is enabled
2020/12/14 13:56:19 [WARNING] endpoint 'crl' is disabled: cert db not configured (missing -db-config)
2020/12/14 13:56:19 [INFO] setting up key / CSR generator
2020/12/14 13:56:19 [INFO] endpoint '/api/v1/cfssl/newkey' is enabled
2020/12/14 13:56:19 [INFO] endpoint '/api/v1/cfssl/newcert' is enabled
2020/12/14 13:56:19 [INFO] endpoint '/api/v1/cfssl/scaninfo' is enabled
2020/12/14 13:56:19 [INFO] endpoint '/api/v1/cfssl/health' is enabled
2020/12/14 13:56:19 [INFO] Handler set up complete.
2020/12/14 13:56:19 [INFO] Now listening on 192.168.153.129:8888
2、签署证书
[root@localhost etcd]# cfssl gencert -remote 192.168.153.129 -profile etcd etcd-csr.json
二、etcd
2.1、规划
etcd 是 CoreOS 团队项目,key-value存储、可用于服务注册和发现、支持SSL、raft算法保证可用性和一致性、restful 风格api设计。多用于作为k8s做元数据存储。本文重点介绍使用,以后有时间再深入了解
etcd主机ip | etcd工作目录 | name |
---|---|---|
192.168.153.129 | /opt/etcd/data | etcd1 |
192.168.153.130 | /opt/etcd/data | etcd2 |
192.168.153.131 | /opt/etcd/data | etcd3 |
2.2、安装
所有主机同样的操作:
[root@localhost etcd]# wget https://github.com/coreos/etcd/releases/download/v3.4.3/etcd-v3.4.3-linux-amd64.tar.gz
[root@localhost etcd]# tar xvf etcd-v3.4.3-linux-amd64.tar.gz -C ./ #解压etcd压缩文件中的所有内容到/opt/etcd目录下
[root@localhost etcd]# mkdir -p /opt/etcd/cert /opt/etcd/data /opt/etcd/wal
[root@localhost cert]# cp -arp /opt/cfssl/work/etcd/etcd*.pem /opt/etcd/cert #拷贝etcd.pem和etcd-key.pem到/opt/etcd/cert 目录下,证书为1.3生成的证书
[root@localhost work]# cp /opt/cfssl/work/ca.pem /opt/cfssl/work #etcd或者k8s的master通常只需要ca的公钥即可
[root@localhost etcd]# etcd.service 文件简介
[Service]
Type=notify
WorkingDirectory=/opt/etcd/data #工作目录
ExecStart=/opt/etcd/etcd \ #etcd程序位置
--data-dir=/opt/etcd/data \ #数据目录,目录不存在的需要手动创建
--wal-dir=/opt/etcd/wal \ #专用wal目录的路径
--name=etcd1 \ #分别为etcd1,etcd2,etcd3
--cert-file=/opt/etcd/cert/etcd.pem \ #证书
--key-file=/opt/etcd/cert/etcd-key.pem \ #私钥
--trusted-ca-file=/opt/ca/ca.pem \ #ca证书
--peer-cert-file=/opt/etcd/cert/etcd.pem \ #peer 之间使用的证书
--peer-key-file=/opt/etcd/cert/etcd-key.pem \ #peer之间使用的私钥
--peer-trusted-ca-file=/opt/ca/ca.pem \ #peer 使用的ca证书
--peer-client-cert-auth \ #启用peer之间客户端认证
--client-cert-auth \ #启用客户端证书认证,必须使用https
--listen-peer-urls=https://192.168.153.129:2380 \ #不同的etcd主机需要调整,监听地址
--initial-advertise-peer-urls=https://192.168.153.129:2380 \ #不同的etcd主机需要调整,对外宣告监听地址
--listen-client-urls=https://192.168.153.129:2379,http://127.0.0.1:2379 \ #不同的etcd主机需要调整,监听地址
--advertise-client-urls=https://192.168.153.129:2379 \ #不同的etcd主机需要调整
--initial-cluster-token=etcd-cluster-0 \ #初始化集群使用的token,用于peer之间认证
--initial-cluster="etcd1=https://192.168.153.129:2380,etcd2=https://192.168.153.130:2380,etcd3=https://192.168.153.131:2380" \ #集群成员
--initial-cluster-state=new \ #初始化集群状态,可选值为"new"或"existing"
--auto-compaction-mode=periodic \#etcd 内存与磁盘自动整理,可选参数 periodic(基于时间保留)|revision(基于修订号保留 )
--auto-compaction-retention=1 \#每间1h
--max-request-bytes=33554432 \
--quota-backend-bytes=6442450944 \
--heartbeat-interval=3000 \ #心跳间隔
--election-timeout=15000 #选举超时实践10s
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
etcd配置文件
[root@localhost ~]# cat /usr/lib/systemd/system/etcd.service #etcd1
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos
[Service]
Type=notify
WorkingDirectory=/opt/etcd/data
ExecStart=/opt/etcd/etcd \
--data-dir=/opt/etcd/data \
--wal-dir=/opt/etcd/wal \
--name=etcd1 \
--cert-file=/opt/etcd/cert/etcd.pem \
--key-file=/opt/etcd/cert/etcd-key.pem \
--trusted-ca-file=/opt/ca/ca.pem \
--peer-cert-file=/opt/etcd/cert/etcd.pem \
--peer-key-file=/opt/etcd/cert/etcd-key.pem \
--peer-trusted-ca-file=/opt/ca/ca.pem \
--peer-client-cert-auth \
--client-cert-auth \
--listen-peer-urls=https://192.168.153.129:2380 \
--initial-advertise-peer-urls=https://192.168.153.129:2380 \
--listen-client-urls=https://192.168.153.129:2379,http://127.0.0.1:2379 \
--advertise-client-urls=https://192.168.153.129:2379 \
--initial-cluster-token=etcd-cluster-0 \
--initial-cluster="etcd1=https://192.168.153.129:2380,etcd2=https://192.168.153.130:2380,etcd3=https://192.168.153.131:2380" \
--initial-cluster-state=new \
--auto-compaction-mode=periodic \
--auto-compaction-retention=1 \
--max-request-bytes=33554432 \
--quota-backend-bytes=6442450944 \
--heartbeat-interval=3000 \
--election-timeout=15000
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
[root@localhost ~]# cat /usr/lib/systemd/system/etcd.service #etcd2
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos
[Service]
Type=notify
WorkingDirectory=/opt/etcd/data
ExecStart=/opt/etcd/etcd \
--data-dir=/opt/etcd/data \
--wal-dir=/opt/etcd/wal \
--name=etcd2 \
--cert-file=/opt/etcd/cert/etcd.pem \
--key-file=/opt/etcd/cert/etcd-key.pem \
--trusted-ca-file=/opt/ca/ca.pem \
--peer-cert-file=/opt/etcd/cert/etcd.pem \
--peer-key-file=/opt/etcd/cert/etcd-key.pem \
--peer-trusted-ca-file=/opt/ca/ca.pem \
--peer-client-cert-auth \
--client-cert-auth \
--listen-peer-urls=https://192.168.153.130:2380 \
--initial-advertise-peer-urls=https://192.168.153.130:2380 \
--listen-client-urls=https://192.168.153.130:2379,http://127.0.0.1:2379 \
--advertise-client-urls=https://192.168.153.130:2379 \
--initial-cluster-token=etcd-cluster-0 \
--initial-cluster="etcd1=https://192.168.153.129:2380,etcd2=https://192.168.153.130:2380,etcd3=https://192.168.153.131:2380" \
--initial-cluster-state=new \
--auto-compaction-mode=periodic \
--auto-compaction-retention=1 \
--max-request-bytes=33554432 \
--quota-backend-bytes=6442450944 \
--heartbeat-interval=3000 \
--election-timeout=15000
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
[root@localhost ~]# cat /usr/lib/systemd/system/etcd.service #etcd3
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos
[Service]
Type=notify
WorkingDirectory=/opt/etcd/data
ExecStart=/opt/etcd/etcd \
--data-dir=/opt/etcd/data \
--wal-dir=/opt/etcd/wal \
--name=etcd3 \
--cert-file=/opt/etcd/cert/etcd.pem \
--key-file=/opt/etcd/cert/etcd-key.pem \
--trusted-ca-file=/opt/ca/ca.pem \
--peer-cert-file=/opt/etcd/cert/etcd.pem \
--peer-key-file=/opt/etcd/cert/etcd-key.pem \
--peer-trusted-ca-file=/opt/ca/ca.pem \
--peer-client-cert-auth \
--client-cert-auth \
--listen-peer-urls=https://192.168.153.131:2380 \
--initial-advertise-peer-urls=https://192.168.153.131:2380 \
--listen-client-urls=https://192.168.153.131:2379,http://127.0.0.1:2379 \
--advertise-client-urls=https://192.168.153.131:2379 \
--initial-cluster-token=etcd-cluster-0 \
--initial-cluster="etcd1=https://192.168.153.129:2380,etcd2=https://192.168.153.130:2380,etcd3=https://192.168.153.131:2380" \
--initial-cluster-state=new \
--auto-compaction-mode=periodic \
--auto-compaction-retention=1 \
--max-request-bytes=33554432 \
--quota-backend-bytes=6442450944 \
--heartbeat-interval=3000 \
--election-timeout=15000
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
备注:如果安装出现问题,可以尝试在前台运行etcd程序,查看错误输出
[root@localhost ~]# /opt/etcd/etcdctl --endpoints=https://192.168.153.129:2379 --cacert=/opt/ca/ca.pem --cert=/opt/etcd/cert/etcd.pem --key=/opt/etcd/cert/etcd-key.pem endpoint health
https://192.168.153.129:2379 is healthy: successfully committed proposal: took = 8.360942ms
[root@localhost ~]# /opt/etcd/etcdctl --endpoints=https://192.168.153.130:2379 --cacert=/opt/ca/ca.pem --cert=/opt/etcd/cert/etcd.pem --key=/opt/etcd/cert/etcd-key.pem endpoint health
https://192.168.153.130:2379 is healthy: successfully committed proposal: took = 7.984891ms
[root@localhost ~]# /opt/etcd/etcdctl --endpoints=https://192.168.153.131:2379 --cacert=/opt/ca/ca.pem --cert=/opt/etcd/cert/etcd.pem --key=/opt/etcd/cert/etcd-key.pem endpoint health
https://192.168.153.131:2379 is healthy: successfully committed proposal: took = 6.799912ms
[root@localhost ~]# [root@localhost ~]# ETCD_ENDPOINTS="https://192.168.153.129:2379,https://192.168.153.130:2379,https://192.168.153.131:2379"
[root@localhost ~]# /opt/etcd/etcdctl --endpoints=${ETCD_ENDPOINTS} --cacert=/opt/ca/ca.pem --cert=/opt/etcd/cert/etcd.pem --key=/opt/etcd/cert/etcd-key.pem member list -w table
+------------------+---------+-------+------------------------------+------------------------------+------------+
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS | IS LEARNER |
+------------------+---------+-------+------------------------------+------------------------------+------------+
| 899fb6b223d05e4d | started | etcd3 | https://192.168.153.131:2380 | https://192.168.153.131:2379 | false |
| a962f9dc9fd134e8 | started | etcd1 | https://192.168.153.129:2380 | https://192.168.153.129:2379 | false |
| d04e93670ca08d70 | started | etcd2 | https://192.168.153.130:2380 | https://192.168.153.130:2379 | false |
+------------------+---------+-------+------------------------------+------------------------------+------------+
[root@localhost ~]# /opt/etcd/etcdctl --endpoints=${ETCD_ENDPOINTS} --cacert=/opt/ca/ca.pem --cert=/opt/etcd/cert/etcd.pem --key=/opt/etcd/cert/etcd-key.pem endpoint status -w table
+------------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+------------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| https://192.168.153.129:2379 | a962f9dc9fd134e8 | 3.4.3 | 20 kB | false | false | 16 | 19 | 19 | |
| https://192.168.153.130:2379 | d04e93670ca08d70 | 3.4.3 | 20 kB | false | false | 16 | 19 | 19 | |
| https://192.168.153.131:2379 | 899fb6b223d05e4d | 3.4.3 | 25 kB | true | false | 16 | 19 | 19 | |
+------------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
[root@localhost ~]# /opt/etcd/etcdctl --endpoints=${ETCD_ENDPOINTS} --cacert=/opt/ca/ca.pem --cert=/opt/etcd/cert/etcd.pem --key=/opt/etcd/cert/etcd-key.pem endpoint health -w table
+------------------------------+--------+-------------+-------+
| ENDPOINT | HEALTH | TOOK | ERROR |
+------------------------------+--------+-------------+-------+
| https://192.168.153.131:2379 | true | 13.633632ms | |
| https://192.168.153.130:2379 | true | 14.745481ms | |
| https://192.168.153.129:2379 | true | 15.673066ms | |
+------------------------------+--------+-------------+-------+
三、CRI和OCI
3.1、runtime介绍
经典的k8s runtime架构:(图抄别人的,)
当kubelet要创建一个容器时,需要以下几步:
1、Kubelet 通过 CRI 接口(gRPC)调用 dockershim,请求创建一个容器。CRI 即容器运行时接口(Container Runtime Interface),这一步中,Kubelet 可以视作一个简单的 CRI Client,而 dockershim 就是接收请求的 Server。目前 dockershim 的代码其实是内嵌在 Kubelet 中的,所以接收调用的凑巧就是 Kubelet 进程;
2、dockershim 收到请求后,转化成 Docker Daemon 能听懂的请求,发到 Docker Daemon 上请求创建一个容器。
3、Docker Daemon 早在 1.12 版本中就已经将针对容器的操作移到另一个守护进程——containerd 中了,因此 Docker Daemon 仍然不能帮我们创建容器,而是要请求 containerd 创建一个容器;分离的目录主要是docker daemon去处理整个docker的生态(volumne,编排,net...),而containerd 负责container runtime
4、containerd 收到请求后,并不会自己直接去操作容器,而是创建一个叫做 containerd-shim 的进程,让 containerd-shim 去操作容器。这是因为容器进程需要一个父进程来做诸如收集状态,维持 stdin 等 fd 打开等工作。而假如这个父进程就是 containerd,那每次 containerd 挂掉或升级,整个宿主机上所有的容器都得退出了。而引入了 containerd-shim 就规避了这个问题(containerd 和 shim 并不是父子进程关系);
5、我们知道创建容器需要做一些设置 namespaces 和 cgroups,挂载 root filesystem 等等操作,而这些事该怎么做已经有了公开的规范了,那就是 OCI(Open Container Initiative,开放容器标准)。它的一个参考实现叫做 runC。于是,containerd-shim 在这一步需要调用 runC 这个命令行工具,来启动容器;
6、runC 启动完容器后本身会直接退出,containerd-shim 则会成为容器进程的父进程,负责收集容器进程的状态,上报给 containerd,并在容器中 pid 为 1 的进程退出后接管容器中的子进程进行清理,确保不会出现僵尸进程。
OCI 标准 CRI 接口的项目:
- OCI Compatible:runC,Kata(以及它的前身 runV 和 Clear Containers),gVisor。其它比较偏门的还有 Rust 写的 railcar
- CRI Compatible:Docker(借助 dockershim),containerd(借助 CRI-containerd),CRI-O,Frakti,etc
当前的架构:
3.2、名词理解
OCI:多家公司共同成立的项目(不是K8s)推出的container runtime标准,提出实践比CRI要早,代表作是Docker推出的runC
CRI:k8s推出的自己的container runtime标准,比OCI更踢进与k8s自己,添加了pod的生命周期管理的概念,为什么要推出这个:早期k8s只需要支持rkt,docker等容器引擎(docker runtime)进行兼容即可,后来docker runtime多了起来,为了获取主动权推出了自己的container runtime标准。
container runtime:主要是负责容器的生命周期管理
runC:是OCI的一个参考实现,用于操作容器的一个工具(创建、运行等),负责和cgroup/linux kernel交互
containerd:docker要搞swarm,把容器操作从docker daemon中剥离出来形成containerd,containerd向docker提供运行容器的API,二者通过gRPC进行交互。containerd通过runc来实际运行容器。而docker daemon则专门负责上层的编排。containerd 后来则捐给了CNCF(swarm不行哈 ...)
docker Engine:不仅包含对于容器的生命周期的管理,还包括了对于容器生态的管理,比如对于镜像等。现在的docker、rkt以及阿里推出的pouch均可属于此范畴
docker:现在说docker,不仅仅包含对容器生命周期的管理,还包含对整个容器生态的管理(volume,network...)
shim:垫片,作为 Adapter 将各种容器运行时本身的接口适配到 Kubernetes 的 CRI 接口上。
cri-containerd:k8s推出的为了适配containerd到k8s启的进程,kubelet->cri-containerd->containerd->container
cri-o: k8s专用的runtime,兼容CRI和OCI
CRI-conatinerd
CRI-containerd-进化版(cri-containerd作为一个适配器放在了containerd中)
CRI-O(挺好的,但是目前每怎么用。common[对应containerd-shim])
使用yum install docker的时候,可以发现docker.service和containerd.service对应的是两个服务
[root@master ~]# cat /usr/lib/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
BindsTo=containerd.service
After=network-online.target firewalld.service containerd.service
Wants=network-online.target
Requires=docker.socket
[root@master ~]# cat /usr/lib/systemd/system/containerd.service
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target local-fs.target
四、网络插件
4.1、CNM
CNM(Container Network Model Interfacing):docker公司提出的网络模型,CNM模型主要通过Network Sandbox、Endpoint和Nework这三个组件实现。
参考实现:Weave、Project Calico、Kuryr和Plumgrid
Network Sandbox:容器内部的网络栈,包括网络接口、路由表、DNS等配置的管理。Sandbox可用Linux网络命名空间、FreeBSD Jail等机制进行实现。一个Sandbox可以包含多个Endpoint。
Endpoint:用于将容器内的Sandbox与外部网络相连的网络接口。可以使用veth对、Open vSwitch的内部port等技术进行实现。一个Endpoint仅能够加入一个Network。
Network:可以直接互连的Endpoint的集合。可以通过Linux网桥、VLAN等技术进行实现。一个Network包含多个Endpoint
libnetwork是CNM的原生实现,为Docker daemon和网络驱动程序之间提供了接口,网络驱动程序负责将驱动和一个网络进行对接。每个驱动程序负责管理它所拥有的网络以及为该网络提供的各种服务,例如IPAM等等。由多个驱动支撑的多个网络可以同时并存。网络驱动可以按提供方被划分为原生驱动(libnetwork内置的或Docker支持的)或者远程驱动 (第三方插件)。原生驱动包括 none, bridge, overlay 以及 MACvlan。驱动也可以被按照适用范围被划分为本地(单主机)的和全局的 (多主机)。
4.2、CNI
CNI是由CoreOs公司公司提出的另一种容器网络规范
CNI规定了一个容器runtime和网络插件之间的简单的契约。这个契约通过JSON schema定义了CNI插件所需要提供的输入和输出。一个容器可以被加入到被不同插件所驱动的多个网络之中。一个网络有自己对应的插件和唯一的名称。CNI 插件需要提供两个命令:一个用来将网络接口加入到指定网络,另一个用来将其移除。这两个接口分别在容器被创建和销毁的时候被调用。CNI仅关注在创建容器时分配网络资源,和在销毁容器时删除网络资源,这使得CNI规范非常轻巧、易于实现,得到了广泛的支持。
CNI插件包括两种类型, CNI Plugin和IPAM(IP Address Management)Plugin
CNI Plugin负责为容器配置网络资源
IPAM Plugin负责对容器的IP地址进行分配和管理。IPAM Plugin作为CNI Plugin的一部分,与CNI Plugin一起工作。
4.4、calico
4.4.1、概述
问题一、什么是calico
Calico是一个开源的网络和网络安全解决方案,用于容器、虚拟机和本机主机的工作负载。Calico支持广泛的平台,包括Kubernetes、OpenShift、Docker EE、OpenStack和裸机服务。Calico 不使用隧道或 NAT 来实现转发,而是巧妙的把所有二三层流量转换成三层流量,并通过 host 上路由配置完成跨 Host 转发。
问题二、calico的特点
1)可选数据层,包括:purge linux eBPF dataplane,标准的linux networking dataplane,windows HNS dataplane;
网络有2个重要功能;转发(如何把包发送出去,router的输入和输出)和路由(包如何到达目的地,需要路由算法)
2)安全:丰富的网络策略模型,Wireguard加密支持,
3)性能高: Linux eBPF/Linux内核的高度优化的标准network pipeline,占用cpu少
4)可扩展性:支持大规模的集群和节点
5)k8s网络策略支持
6)社区优越性以及企业版兼容
4.4.2、架构
Calico 主要由 Felix、etcd、BGP client 以及 BGP Route Reflector 组成
1. Felix,Calico Agent,跑在每台需要运行 Workload 的节点上,主要负责配置路由及 ACLs 等信息来确保 Endpoint 的连通状态;
2. etcd,分布式键值存储,主要负责网络元数据一致性,确保 Calico 网络状态的准确性;
3. BGP Client(BIRD), 主要负责监听 Host 上由 Felix 注入的路由信息,把 Felix 写入 Kernel 的路由信息分发到当前 Calico 网络,确保 Workload 间的通信的有效性;是一个路由程序,支持OSPF、BGP、RIP等
4. BGP Route Reflector(BIRD),大规模部署时使用,摒弃所有节点互联的 mesh 模式,通过一个或者多个 BGP Route Reflector 来完成集中式的路由分发。
5. calico/calico-ipam,主要用作 Kubernetes 的 CNI 插件
4.4.3、BGP和IPIP
calico和node之间有两种网络模型:
IPIP,把一个IP数据包又套在一个IP包里,即把 IP 层封装到 IP 层的一个 tunnel
BGP,边界网关协议(Border Gateway Protocol, BGP)是互联网上一个核心的去中心化自治路由协议。它通过维护IP路由表或‘前缀’表来实现自治系统(AS)之间的可达性,属于矢量路由协议
IP-IP模式:
BGP工作模式:
4.4.4、其他
多租户隔离问题:多租户网段重复问题无法解决
路由规模:路由规模和pod分布有关,pod如果分散在host集群中,势必会产生较多的路由条目
Calico 控制平面的设计要求物理网络得是 L2 Fabric,这样 vRouter 间都是直接可达的,路由不需要把物理设备当做下一跳。为了支持 L3 Fabric,需要使用IPIP模式
参考博客:
https://www.cnblogs.com/charlieroro/articles/10998203.html
https://www.cnblogs.com/xuxinkun/p/8036832.html
https://github.com/kubernetes-sigs/apiserver-builder-alpha/blob/master/docs/concepts/auth.md
https://www.opencontainers.org
https://github.com/opencontainers/runtime-spec
https://github.com/opencontainers/runc
https://github.com/kubernetes/community/blob/master/contributors/devel/container-runtime-interface.md
http://blog.kubernetes.io/2016/12/container-runtime-interface-cri-in-kubernetes.html
https://github.com/kubernetes-incubator/cri-containerd
https://github.com/kubernetes-incubator/cri-o
https://docs.projectcalico.org/about/about-calico
https://www.cnblogs.com/goldsunshine/p/10701242.html