什么是Config机制

在部署Kubernetes https通信环境时,最困难的是各组件的参数的配置,而Kubernetes的Config机制就是为了方便https通信环境搭建的一种手段。组件可以通过读取Config中的内容自动完成密钥参数的配置。

生成认证密钥

要使用https进行通信,首先得需要生成密钥。我的环境是一台虚拟机设备,我把密钥放在/etc/kubernetes/security/serverkey目录下。在生成证书的时候,还使用了多域名机制,方便环境的使用。

修改openssl.cnf

首先拷贝openssl.cnf到/etc/kubernetes/security/serverkey目录下。
cp /etc/ssl/openssl.cnf ./

对openssl.cnf作如下修改,其中[ alt_names ]自己添加。alt_names中表明生成的密钥针对访问kubernetes, k8s, 10.100.0.1(为了能直接使用ServiceAccount,具体IP请根据自己的service网段来配置)的请求有效,alt_names之外的域名都无效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
req_extensions = v3_req
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = kubernetes
DNS.2 = k8s
IP.1 = 10.100.0.1

生成密钥

首先,在/etc/kubernetes/security/serverkey目录下完成如下命令:

1
2
3
mkdir -p demoCA/{certs,crl,newcerts,private}
touch demoCA/index.txt
echo 00 > demoCA/serial

在下面步骤中需要输入PEM,要记住此密码。其他信息按照自己的具体情况赶写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
root@fankang:/etc/kubernetes/security/serverkey# openssl req -new -x509 -days 3650 -keyout ca.key -out ca.crt -config openssl.cnf
Generating a 2048 bit RSA private key
.......................................................................................+++
.......+++
writing new private key to 'ca.key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:Zhejiang
Locality Name (eg, city) []:Hangzhou
Organization Name (eg, company) [Internet Widgits Pty Ltd]:abc
Organizational Unit Name (eg, section) []:abc
Common Name (e.g. server FQDN or YOUR name) []:abc
Email Address []:fankangbest@139.com

1
2
3
4
5
root@fankang:/etc/kubernetes/security/serverkey# openssl genrsa -out server.key 2048
Generating RSA private key, 2048 bit long modulus
..................+++
................................+++
e is 65537 (0x10001)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
root@fankang:/etc/kubernetes/security/serverkey# openssl req -new -key server.key -out server.csr -config openssl.cnf
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:Zhejiang
Locality Name (eg, city) []:Hangzhou
Organization Name (eg, company) [Internet Widgits Pty Ltd]:abc
Organizational Unit Name (eg, section) []:abc
Common Name (e.g. server FQDN or YOUR name) []:abc
Email Address []:fankangbest@139.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:123456
An optional company name []:123456

在Enter pass phrase for ca.key中输入的是之前我们设置的PEM密码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
root@fankang:/etc/kubernetes/security/serverkey# openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key -extensions v3_req -config openssl.cnf
Using configuration from openssl.cnf
Enter pass phrase for ca.key:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 0 (0x0)
Validity
Not Before: Jul 9 01:06:49 2017 GMT
Not After : Jul 9 01:06:49 2018 GMT
Subject:
countryName = CN
stateOrProvinceName = Zhejiang
organizationName = abc
organizationalUnitName = abc
commonName = abc
emailAddress = fankangbest@139.com
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
X509v3 Key Usage:
Digital Signature, Non Repudiation, Key Encipherment
X509v3 Subject Alternative Name:
DNS:kubernetes, DNS:k8s, IP Address:10.100.0.1
Certificate is to be certified until Jul 9 01:06:49 2018 GMT (365 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

现在,在/etc/kubernetes/security/serverkey中有如下文件:

1
2
root@fankang:/etc/kubernetes/security/serverkey# ls
ca.crt ca.key demoCA openssl.cnf server.crt server.csr server.key

密钥生成完毕,支持的域名有kubernetes, k8s, 10.100.0.1。

配置config

在Kubernetes中,默认的config文件为/root/.kube/config。在config中写入下面信息即完成config的创建:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: v1
kind: Config
users:
- name: node
user:
client-certificate: /etc/kubernetes/security/serverkey/server.crt
client-key: /etc/kubernetes/security/serverkey/server.key
clusters:
- name: local
cluster:
certificate-authority: /etc/kubernetes/security/serverkey/ca.crt
server: https://kubernetes:6443
contexts:
- context:
cluster: local
user: node
name: my-context
current-context: my-context

在config文件中,先定义了名为node的user,里面包含了生成好的密钥,然后定义了一个名为local的cluster,接着定义了my-context,最后,我们置my-context生效。

因为我们在config文件中使用了kubernetes作为访问apiserver的入口,但kubernetes域名是不存在的,所以我们需要在主机的/etc/hosts中添加域名kubernetes所对应的IP:
127.0.0.1 kubernetes

起Kubernetes进程

为了方便调试,我都是直接从二进制文件拉起所有服务的:

1
2
3
4
5
6
7
8
(dockerd -H 0.0.0.0:4243 -H unix:///var/run/docker.sock &>> /var/log/docker.log &)
(etcd --data-dir=/home/fankang/data/etcd150/ --listen-client-urls http://0.0.0.0:4001 --advertise-client-urls http://0.0.0.0:4001 &>> /var/log/etcd.log &)
(等待20秒再启Kubernetes进程,否则apiserver会因连不上etcd而退出)
(kube-apiserver --logtostderr=true --v=0 --etcd-servers=http://localhost:4001 --insecure-bind-address=0.0.0.0 --allow-privileged=false --service-cluster-ip-range=10.100.0.0/16 --admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,ResourceQuota --client-ca-file=/etc/kubernetes/security/serverkey/ca.crt --tls-private-key-file=/etc/kubernetes/security/serverkey/server.key --tls-cert-file=/etc/kubernetes/security/serverkey/server.crt &>> /var/log/kube-apiserver.log &)
(kube-controller-manager --logtostderr=true --v=0 --kubeconfig=/root/.kube/config &>> /var/log/kube-controller-manager.log &)
(kube-scheduler --logtostderr=true --v=0 --kubeconfig=/root/.kube/config &>> /var/log/kube-scheduler.log &)
(kube-proxy --logtostderr=true --v=0 --kubeconfig=/root/.kube/config &>> /var/log/kube-proxy.log &)
(kubelet --logtostderr=true --v=0 --address=0.0.0.0 --allow-privileged=false --pod-infra-container-image=pause:0.8.0 --cpu-cfs-quota=true --kubeconfig=/root/.kube/config --require-kubeconfig=True &>> /var/log/kubelet.log &)

kubectl使用Config

Kubectl会直接读取/root/.kube/config中的配置信息和kube-apiserver通信。如果把config中的server改为10.100.0.1:443,那么kubectl就是通过10.100.0.1获取内容的。下面就是更改后kubectl在–v=9时打印出来的日志,kubectl访问的是10.100.0.1:

1
I0709 10:21:41.636415 21126 round_trippers.go:299] curl -k -v -XGET -H "Accept: application/json" -H "User-Agent: kubectl/v1.5.2+08e0995 (linux/amd64) kubernetes/08e0995" https://10.100.0.1:443/api/v1/namespaces/default/pods

总结

感觉Config机制就是把复杂的配置放到Config中,通过node, cluster, context的概念来构造目前环境的配置,这样在使用时就可以屏蔽复杂的细节。