k8s 二进制部署 五 (kube-apiserver)

大番茄 2019年11月06日 2,112次浏览

v1.16

一、介绍

kube-apiserver 提供了所有组件的入口,组件之间数据交互也是通过apiserver来实现。

大致的工作流程就是:

提交数据 ---> apiserver ---> etcd ---> apiserver ---> 获取数据
比如:
1、kubectl提交请求到apiserver,
2、apiserver收到以后会放到etcd。
3、apiserver同时在一直watch着etcd, 发现数据修改以后再获取数据,主要是为了数据存储以及高可用,只有放到etcd,其他节点的apiserver才能发现有操作发生。
4、然后controller-manager通过watch着apiserver的数据, 获取到数据变化,开始做具体操作创建pod之类的,然后把创建pod的操作再次发给apiserver。
5、apiserver发给etcd。
6、apiserver再次获取这个pod创建,scheduler 从apiserver获取。
7、scheduler 计算在哪个节点启动pod, 发送给apiserver,apiserver再放到etcd中对应节点的信息。
8、kubelet watch着apiserver, 发现本节点pod信息发生变化,更新变化,然后再发给apiserver, 存储进etcd。
还是借用一张图,这个是创建了ReplicaSet:

kubernetes权威指南(第四版)
image-6999a443

其他功能

apiserver作为入口,自然需要有安全机制。
一个请求想要进入apiserver需要经过三道槛:

1、 用户合法性认证,如:ca证书认证,token认证,serviceaccount认证等。
2、 授权机制,如: RBAC, Webhook, Node, ABAC。 确认用户对某些api创建的某些资源是否有获取、修改、删除的权限。
3、 最后,准入控制,确认这个资源能不能动, 类似于操作白名单、默认法则, 就算授权过了, 这里不能动还是不能动。有的还会对访问的请求做修改,实现部分请求。

kubernetes权威指南(第四版)
image-82f7417c

二、参数

看另一篇吧, 这里不占篇幅了。
https://www.yxingxing.net/archives/kubernetes-20191030-apiserver-parameter

三、安装

注意时区,centos7时区默认可能是utc。
关闭防火墙(firewalld),selinux。

1、生成证书

网上有很多生成私有CA的工具,这里我还是使用自己这个脚本。
https://www.yxingxing.net/archives/kubernetes-20191025-ca

证书用于apiserver提供的https接口,所以要包含所有客户端会访问到的ip和名称,如果客户端访问的地址证书里面没有,就会访问失败,这也是客户端认证apiserver的方式。

我这里的ca与etcd认证是同一个ca,所以连接etcd与k8s自身配置的证书是同一个。不是同一个ca的注意分开一下.

生成包含下面信息的证书:

DNS.1 = kubernetes
DNS.2 = kubernetes.default
IP.1 = 172.100.102.70
IP.2 = 172.100.102.80
IP.3 = 172.100.102.90
IP.4 = 10.0.0.1

DNS.1 是k8s自身的service名称kubernetes。
DNS.2 kubernetes 默认是创建在default namespace里面,其他namespace里访问需要kubernetes.default, 所以这里也要加上。完整的域名是: kubernetes.default.svc.cluster.local 为了防止有请求访问短域名,可以多拆几个。
IP.1和IP.2 是我这里的两台master节点,为了证书能够几个master节点都通用, 所以放到了一起
IP.3 是几个master 的 vip地址。
IP.4 是k8s自身service kubernetes的对应ip。 我这里使用的时10.0.0.0/16 的网段,kubernetes service 会使用网段中的第一个ip。
image-40c3d58c

2、安装

说是安装,其实就是创建一下目录和unit文件就完事了,从二进制包里复制一下程序文件。

[root@k8s-ca k8s]# tree 
.
├── bin
│   ├── kube-apiserver
│   ├── kube-controller-manager
│   └── kube-scheduler
├── log
└── ssl
    ├── cacert.pem
    ├── kube-apiserver.crt
    └── kube-apiserver.key

3 directories, 6 files

里面的ca证书是为了认证etcd。 之后的kube-controller-manager如果使用ca.key生成serviceaccount, 这里也是需要ca证书来认证。

[Unit]
Description=kubernetes api server

[Service]
ExecStart=/usr/local/k8s/bin/kube-apiserver \
--logtostderr=false \
--log-dir=/usr/local/k8s/logs \
--v=4 \
--etcd-servers=https://172.100.102.71:2379,https://172.100.102.72:2379,https://172.100.102.73:2379 \
--etcd-cafile=/usr/local/k8s/ssl/cacert.pem \
--etcd-certfile=/usr/local/k8s/ssl/kube-apiserver.crt \
--etcd-keyfile=/usr/local/k8s/ssl/kube-apiserver.key \
--bind-address=172.100.102.70 \
--advertise-address=172.100.102.70 \
--secure-port=6443 \
--tls-cert-file=/usr/local/k8s/ssl/kube-apiserver.crt \
--tls-private-key-file=/usr/local/k8s/ssl/kube-apiserver.key \
--enable-bootstrap-token-auth \
--authorization-mode=RBAC,Node \
--client-ca-file=/usr/local/k8s/ssl/cacert.pem \
--service-cluster-ip-range=10.0.0.0/16 \
--service-node-port-range=20000-50000 \
--allow-privileged \
--kubelet-https \
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction \
--service-account-key-file=/usr/local/k8s/ssl/cacert.pem
Restart=on-failure

[Install]
WantedBy=multi-user.target

3、启动

systemctl start kube-apiserver
Nov 17 04:53:23 k8s-master systemd: Reloading.
Nov 17 04:53:25 k8s-master systemd: Started kubernetes api server.
Nov 17 04:53:29 k8s-master kube-apiserver: E1117 04:53:29.051605   24695 controller.go:154] Unable to remove old endpoints from kubernetes service: StorageError: key not found, Code: 1, Key: /registry/masterleases/172.100.102.70, ResourceVersion: 0, AdditionalErrorMsg:
Nov 17 04:54:08 k8s-master systemd: Stopping kubernetes api server...
Nov 17 04:54:08 k8s-master kube-apiserver: E1117 04:54:08.013371   24695 controller.go:185] Get https://172.100.102.70:6443/api/v1/namespaces/default/endpoints/kubernetes: dial tcp 172.100.102.70:6443: connect: connection refused
Nov 17 04:54:08 k8s-master systemd: Stopped kubernetes api server.
Nov 17 04:54:15 k8s-master systemd: Started kubernetes api server.
Nov 17 04:54:18 k8s-master kube-apiserver: E1117 04:54:18.682387   24737 controller.go:154] Unable to remove old endpoints from kubernetes service: StorageError: key not found, Code: 1, Key: /registry/masterleases/172.100.102.70, ResourceVersion: 0, AdditionalErrorMsg:

查看日志没有异常信息就算完成了。

复制kubectl到/usr/local/bin下面,直接就可以执行,默认连接的时8080非认证端口。

[root@k8s-master logs]# kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.0.0.1     <none>        443/TCP   11m
[root@k8s-master logs]# 

四、配置kubectl

不配置也没事,在本地用就行。
kubectl默认连接127.0.0.1的8080非授权端口, 这里简单配置一下。
生成kubectl的配置文件,默认路径是 ~/.kube/config。

1、给kubectl创建证书。

肯定还是要k8s中的CA。

[root@k8s-master test]# ls
cacert.pem  kubectl.crt  kubectl.key

cacert.pem 是用来kubectl认证apiserver的, 连接中的一点安全机制。

这里已经创建好了,CN就叫做kubectl。
image-c5733a71

2、创建配置。

下面的命令不指定--kubeconfig的情况下会保存到默认位置~/.kube/config。

# 创建所连接的apiserver。
[root@k8s-master test]# kubectl config set-cluster mycluster --server=https://172.100.102.70:6443 --certificate-authority=cacert.pem --embed-certs
Cluster "mycluster" set.
# 创建用户
[root@k8s-master test]# kubectl config set-credentials myuser --client-certificate=kubectl.crt --client-key=kubectl.key --embed-certs
User "myuser" set.
# 创建上下文。
[root@k8s-master test]# kubectl config set-context mycontext --cluster=mycluster --user=myuser
Context "mycontext" created.
# 设置当前使用的上下文。
[root@k8s-master test]# kubectl config use-context mycontext
Switched to context "mycontext".

3、给kubectl授权。

这一步应该放到创建配置之前。因为配置文件生成以后,kubectl会使用配置文件,但是kubectl用户没有授权。 所以提示这个:

[root@k8s-master .kube]# kubectl get services
Error from server (Forbidden): services is forbidden: User "kubectl" cannot list resource "services" in API group "" in the namespace "default"
[root@k8s-master .kube]# 

把~/.kube/config移走, 或者修改里面的 当前上下文为空, 注释也行。

#current-context: mycontext

授权:
直接授权为管理员。

[root@k8s-master .kube]# kubectl create clusterrolebinding kubectl --clusterrole=cluster-admin --user=kubectl
clusterrolebinding.rbac.authorization.k8s.io/kubectl created

把配置文件的注释去掉。

[root@k8s-master .kube]# kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.0.0.1     <none>        443/TCP   57m
[root@k8s-master .kube]# 

这样就可以了。


k8s自带的clusterrolebinding/cluster-admin 已经把clusterrole/cluster-admin绑定了system:masters组。 创建证书的时候可以直接使用system:masters组,不需要再单独创建clusterrolebinding。如创建证书的时候:
image