1. Kubezoo简介
kubezoo是字节开源的一个k8s多租户实施方案。其本质上是一个网关,网关会部署在K8S集群前头,拦截对K8S apiserver的请求以及apiserver的应答,通过协议转换(对api对象name加上租户名称前缀等)来达到不同租户公用同一个K8S集群的目的。它本身是无状态的,可以比较方便的扩容,kubezoo利用etcd来存储一些元信息。
2. 本文主旨
本文着重于介绍kubezoo的安装和基本使用,介绍通过pod和本地启动两种方式来安装使用kubezoo。本文基于如下部署方式;
(1) 一台通过虚拟机安装的centos7,在这台机器上启动单实例的kubezoo;
(2) K8S集群使用Kind进行安装,单机的K8S集群;
3. 安装准备
3.1.1. 安装Kind
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.16.0/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
3.1.2. 安装docker
参照文章 https://developer.aliyun.com/article/765545 即可。
3.1.3. 安装kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
mv kubectl /usr/local/bin/
3.1.4. 安装cfssl,用户生成证书的时候用;
yum install wget -y
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 cfssl-certinfo_linux-amd64
mv cfssl_linux-amd64 /usr/bin/cfssl
mv cfssljson_linux-amd64 /usr/bin/cfssljson
mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo
cfssl version
3.1.5. 下载yq
yq是一个json 和 yaml 转换的工具;
wget https://github.com/mikefarah/yq/releases/download/v4.16.2/yq_linux_amd64
chmod +x yq_linux_amd64
mv yq_linux_amd64 /usr/local/bin/yq
3.1.6. clone kubezoo的代码
git clone https://github.com/kubewharf/kubezoo
3.1.7. 通过Kind创建K8S集群
Kind create cluster;
需要等待一会儿,会有成功的提示。之后你就拥有了一个k8s集群了,只不过是单机的。
3.1.8. 下载kubezoo代码
git clone https://github.com/kubewharf/kubezoo
后面将kubezoo在本地的代码记为 KUBEZOO_PATH
3.1.9. 生成证书等信息
生成证书的脚本是 $KUBEZOO_PATH/hack/lib/gen_pki.sh
在运行这个代码之前,要改一下这个脚本,增加一行echo $TEMP_DIR的代码,要记住这个目录,在后面本地安装的时候会有用,记作TEMP_DIR
然后运行 bash $KUBEZOO_PATH/hack/lib/gen_pki.sh
这段代码的具体作用主要有四个:
生成一个CA证书,并用CA给kubezoo签发证书,这个证书主要是kubezoo用户签发租户证书的时候使用的;
生成kubezoo访问K8S集群生成serviceAccount;
将上述生成的两对认证信息会放到K8S集群中作为secret,通过kubectl get secrets能看到;
生成了访问kubezoo的一个context,user叫zoo-admin,集群名是zoo;通过kubectl config get-contexts可以看到,在本地用户的~/.kube/config中能看到具体的详细信息。
4. 安装
4.1. pod方式来进行安装
(1) kubectl apply -f $KUBEZOO_PATH/config/setup/all_in_one.yaml
在K8S集群中部署kubezoo和etcd;kubezoo的meta信息是存储在etcd中,kubezoo也可以和集群共用一套etcd,这里部署了一个单机的kubezoo pod;
可以通过kubectl get all来查看进度;
(2) kubectl port-forward svc/kubezoo 6443:6443 &
在K8S中部署的kubezoo暴露了一个service,端口分别为6443和8080。由于6443与8080是在K8S网络中;在宿主机(我的虚拟机)上访问的时候这里做一个端口转发,我这里将宿主机的6443映射到service的6443;这样的话,可以通过127.0.0.1:6443访问到kubezoo。
(3) kubectl api-resources --context zoo | grep tenants
接下来要就可以访问kubezoo了,可以看到kubezoo中最主要的tenants对象已经支持了。
(4) 实际去创建一个tenant对象
通过 kubectl apply -f $KUBEZOO_PATH/config/setup/sample_tenant.yaml --context zoo 去创建一个tenant对象;
通过 kubectl get tenants --context zoo 去查看tenant对象是否已经建立好;这里需要注意的一点是租户名必须是有效的6位字符,通配符为`[A-Za-z0-9][A-Za-z0-9\-]{5}`。
(5) 创建租户自己的kubeconfig文件
kubectl get tenant 111111 --context zoo -o jsonpath='{.metadata.annotations.kubezoo\.io\/tenant\.kubeconfig\.base64}' | base64 --decode > 111111.kubeconfig
这是为租户创建访问K8S集群的专属kubeconfig文件,其中包含了kubezoo给用户建立的证书。
(6) 租户自己创建一个pod
kubectl apply --kubeconfig 111111.kubeconfig -f- <<EOF
apiVersion: v1
kind: Pod
metadata:
name: test
spec:
containers:
- name: test
image: busybox
command:
- tail
args:
- -f
- /dev/null
EOF
(7) 租户查看自己创建的pod
kubectl get po --kubeconfig 111111.kubeconfig,这里只能看到租户自己的pod
--NAME READY STATUS RESTARTS AGE--
--test 1/1 Running 0 44s--
使用kubectl查询K8S集群,可以看到所有的pod,并且test这个pod所在的namespace是带了租户名的前缀的;
再验证一下,使用kubectl get pods --context zoo去验证一下,报如下错误:
说明,除了tenant对象来,通过kubezoo访问其他的API对象(如pod等)必须使用用户自己的kubeconfig,因为要有tenantID的信息。
4.2. 本地编译方式安装
本地部署的好处在于,你可以结合vscode等工具对代码设置断点,对于阅读代码比较有帮助;
(1) 删除遗留数据
首先我们将pod安装方式中安装的kubezoo以及tenant对象去掉:
kubectl delete pods test -n 111111-default
kubectl delete pods kubezoo-0 -n default
kubectl delete svc kubezoo
kubectl delete secrets kubezoo-pki
kubectl delete secrets upstream-pki
(2) 准备本地本地证书
mkdir -p /etc/kubezoo/pki
mkdir -p /etc/upstream/pki
cp -a $TEMP_DIR/upstream/* /etc/upstream/pki
cp -a $TEMP_DIR/kubezoo/* /etc/kubezoo/pki
(3) 准备本地证书等信息
mkdir -p /etc/kubezoo/pki
mkdir -p /etc/upstream/pki
cp -a $TEMP_DIR/upstream/* /etc/upstream/pki
cp -a $TEMP_DIR/kubezoo/* /etc/kubezoo/pki
(4) 本地编译kubezoo
这一步编译的前提是你本地需要安装Go,安装Go的步骤这里就不做详细的说明了;
cd $KUBEZOO_PATH/cmd
go build main.go -o kubezoo
(5) 准备etcd
这里我们偷个懒,复用上面我们通过pod安装的etcd,但由于之前的etcd是使用pod的方式安装的,所以我们要做一个端口映射;
kubectl port-forward pod/kubezoo-etcd-0 2379:2379 &
(6) 准备对K8S集群的端口映射
本地启动的kubezoo要对接通过Kind启动的K8S,所以之类要做一个对Kind中K8S apiserver的端口映射;
kubectl port-forward pod/kube-apiserver-kind-control-plane -n kube-system 5557:6443 &
我这里将本地的5557映射到Kind中api server的6443端口;
(7) 本地启动kubezoo
将如下启动命令写到一个脚本中,记作start.sh;
./kubezoo --allow-privileged=true --apiserver-count=1 --cors-allowed-origins=.* --delete-collection-workers=1 --etcd-prefix=/zoo --etcd-servers=http://127.0.0.1:2379 --event-ttl=1h0m0s --logtostderr=true --max-requests-inflight=1002 --service-cluster-ip-range=192.168.0.1/16 --service-node-port-range=20000-32767 --storage-backend=etcd3 --authorization-mode=AlwaysAllow --client-ca-file=/etc/kubezoo/pki/ca.pem --client-ca-key-file=/etc/kubezoo/pki/ca-key.pem --tls-cert-file=/etc/kubezoo/pki/kubernetes.pem --tls-private-key-file=/etc/kubezoo/pki/kubernetes-key.pem --service-account-key-file=/etc/upstream/pki/sa.pub --service-account-issuer=kubezoo --service-account-signing-key-file=/etc/upstream/pki/sa.key --proxy-client-cert-file=/etc/upstream/pki/client.crt --proxy-client-key-file=/etc/upstream/pki/client-key.crt --proxy-client-ca-file=/etc/upstream/pki/ca.crt --request-timeout=10m --watch-cache=true --proxy-upstream-master=https://127.0.0.1:5557 --service-account-lookup=false --proxy-bind-address=127.0.0.1 --proxy-secure-port=6443 --api-audiences=kubezoo
这里的main就是刚才编译好的kubezoo;--proxy-upstream-master表示上游K8S的地址,由于我们做了端口映射,为https://127.0.0.1:5557;--etcd-servers是指向的K8S的地址,刚才我们也做了端口映射,所以为http://127.0.0.1:2379
然后启动脚本
bash start.sh > kubezoo.log 2>&1 &
(8) 创建一个新的tenant对象;
修改$KUBEZOO_PATH/config/setup/sample_tenant.yaml, 修改成511111;
通过 kubectl apply -f $KUBEZOO_PATH/config/setup/sample_tenant.yaml --context zoo 去创建一个tenant对象;
通过 kubectl get tenants --context zoo 去查看tenant对象是否已经建立好。
(9) 创建租户自己的kubeconfig文件
kubectl get tenant 511111 --context zoo -o jsonpath='{.metadata.annotations.kubezoo\.io\/tenant\.kubeconfig\.base64}' | base64 --decode > 511111.kubeconfig
这是为租户创建访问K8S集群的专属kubeconfig文件,其中包含了kubezoo给用户建立的证书。
(10) 租户自己创建一个pod
kubectl apply --kubeconfig 511111.kubeconfig -f- <<EOF
apiVersion: v1
kind: Pod
metadata:
name: test
spec:
containers:
- name: test
image: busybox
command:
- tail
args:
- -f
- /dev/null
EOF
(11) 租户查看自己创建的pod
kubectl get po --kubeconfig 511111.kubeconfig,这里只能看到租户自己的pod
使用kubectl查询K8S集群,可以看到所有的pod,并且test这个pod所在的namespace是带了租户名的前缀的;