k8s 新建用户远程连接集群和context切换
一、kubectl 远程连接cluster
1、kubectl是k8s的客户端程序,也是k8s的命令行工具,kubectl提供了大量的子命令可以让用户和集群进行交互。
kubectl操作k8s集群对象是通过调用 k8s API实现的
kubectl不一定部署在master上,也可以在内网的私人笔记本上,开发或者运维人员只有config文件和kubectl工具就可操作k8s集群。
2、默认情况下是默认连接本地的apiserver,也可以使用https连接集群。
一般情况下,在k8s 的 master节点上kubectl是连接的本地http 8080端口和apiserver进行通讯的,当然也可以通过https端口进行通讯前提是要生成证书。所以说
1 | kubectl -s 127.0.0.1:8080 get node ###二进制老版本 |
配置kubectl使用apiserver安全的https端口(6443)连接集群
使用脚本快速添加用户
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | #!/bin/bash # 每个对应一个namespace,用户名和namespace名称相同 # 注意修改KUBE_APISERVER为你的API Server的地址 KUBE_APISERVER=$1 USER=$2 USAGE="USAGE: create-user.sh <api_server> <username>\n Example: https: //192.168.40.134:6443 ops" CSR=`pwd`/user-crt.json SSL_PATH= "/root/cfssl" SSL_FILES=(ca-key.pem ca.pem ca-config.json) CERT_FILES=(${USER}.csr $USER-key.pem ${USER}.pem) if [[ $KUBE_APISERVER == "" ]]; then echo -e $USAGE exit 1 fi if [[ $USER == "" ]];then echo -e $USAGE exit 1 fi # 创建用户的csr文件 function createCSR(){ cat>$CSR<<EOF { "CN" : "USER" , "hosts" : [], "key" : { "algo" : "rsa" , "size" : 2048 }, "names" : [ { "C" : "CN" , "ST" : "BeiJing" , "L" : "BeiJing" , "O" : "k8s" , "OU" : "System" } ] } EOF # 替换csr文件中的用户名 sed -i "s/USER/$USER/g" $CSR } echo "Create CSR file..." createCSR echo "$CSR created" function ifExist(){ if [ ! -f "$SSL_PATH/$1" ]; then echo "$SSL_PATH/$1 not found." exit 1 fi } ##创建证书配置模板ca-config.json文件 cat > $SSL_PATH/ca-config.json <<EOF { "signing" : { "default" : { "expiry" : "87600h" }, "profiles" : { "kubernetes" : { "usages" : [ "signing" , "key encipherment" , "server auth" , "client auth" ], "expiry" : "87600h" } } } } EOF # 判断证书文件是否存在 for f in ${SSL_FILES[@]}; do echo "Check if ssl file $f exist..." ifExist $f echo "OK" done echo "Create user's certificates and keys..." cd $SSL_PATH cfssl gencert -ca=/etc/kubernetes/pki/ca.crt -ca-key=/etc/kubernetes/pki/ca.key -config=ca-config.json -profile=kubernetes $CSR| cfssljson -bare $USER cd - # 设置集群参数 kubectl config set -cluster kubernetes \ --certificate-authority=${SSL_PATH}/ca.pem \ --embed-certs= true \ --server=${KUBE_APISERVER} \ --kubeconfig=${USER}.kubeconfig # 设置客户端认证参数 kubectl config set -credentials $USER \ --client-certificate=$SSL_PATH/${USER}.pem \ --client-key=$SSL_PATH/${USER}-key.pem \ --embed-certs= true \ --kubeconfig=${USER}.kubeconfig # 设置上下文参数 kubectl config set -context kubernetes \ --cluster=kubernetes \ --user=$USER \ -- namespace =$USER \ --kubeconfig=${USER}.kubeconfig # 设置默认上下文 kubectl config use-context kubernetes --kubeconfig=${USER}.kubeconfig # 创建 namespace kubectl create ns $USER # 绑定角色 kubectl create rolebinding ${USER}-admin-binding --clusterrole=admin --user=$USER -- namespace =$USER --serviceaccount=$USER: default kubectl config get -contexts echo "Congratulations!" echo "Your kubeconfig file is ${USER}.kubeconfig" |
注意:
如果是kubeadm方式搭建的k8s环境:
1 2 | cp /etc/kubernetes/pki/ca.crt /root/cfssl/ca.pem cp /etc/kubernetes/pki/ca.key /root/cfssl/ca-key.pem |
3、 使用cfssl签发证书
生成pem和key.pem文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | ###集群之前已经有了ca证书那就不需要在生成了,只需要利用该ca证书生成用户证书即可。 cat > ca-config.json <<EOF { "signing" : { "default" : { "expiry" : "87600h" }, "profiles" : { "kubernetes" : { "usages" : [ "signing" , "key encipherment" , "server auth" , "client auth" ], "expiry" : "87600h" } } } } EOF |
signing
:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE
;
server auth
:表示可以用该 CA 对 server 提供的证书进行验证;
client auth
:表示可以用该 CA 对 client 提供的证书进行验证;
profile kubernetes
包含了server auth
和client auth
,所以可以签发三种不同类型证书;
expiry 证书有效期,默认50年
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | cat > zjz-csr.json <<EOF { "CN" : "zjz" , "hosts" : [], "key" : { "algo" : "rsa" , "size" : 2048 }, "names" : [ { "C" : "CN" , "ST" : "BeiJing" , "L" : "BeiJing" , "O" : "system:masters" , "OU" : "System" } ] } EOF |
注:
- CN就是要创建的用户名,Common Name,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name)
- profile= 对应的是ca-config.json中的profiles字段
- 证书请求中
O
指定该证书的 Group 为system:masters
,而RBAC
预定义的ClusterRoleBinding
将 Groupsystem:masters
与 ClusterRolecluster-admin
绑定,这就赋予了用户所有集群权限
1 2 3 4 5 6 7 8 9 10 11 | $ kubectl describe clusterrolebinding cluster-admin Name: cluster-admin Labels: kubernetes.io/bootstrapping=rbac-defaults Annotations: rbac.authorization.kubernetes.io/autoupdate= true Role: Kind: ClusterRole Name: cluster-admin Subjects: Kind Name Namespace ---- ---- --------- Group system :masters |
生成zjz用户的证书
1 2 | cfssl gencert -ca=/etc/kubernetes/pki/ca.crt -ca-key=/etc/kubernetes/pki/ca.key \ -config=ca-config.json -profile=kubernetes zjz-csr.json | cfssljson -bare zjz |
查看证书
1 2 | # ls admin* zjz.csr zjz-csr.json zjz-key.pem zjz.pem |
5、配置config
拷贝证书以及相关kubectl到目标机器
1 2 | scp /opt/kubernetes/bin/kubectl 10.1.210.32:/usr/bin #拷贝kubectl二进制可执行文件 scp zjz* ca.pem 10.1.210.32:/opt/kubernetes/kubectl/ssl # 拷贝证书 |
配置config和kubectl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #进入证书目录 cd /opt/kubernetes/kubectl/ssl #配置访问的集群 kubectl config set-cluster k8s-cluster1 --server=https: //10.25.72.62:6443 --certificate-authority=ca.pem --embed-certs=true Cluster "k8s-cluster1" set. #配置访问特定的集群、特定的context、特定的namespace kubectl config set-context kube- system -ctx --cluster=k8s-cluster1 --user=kubectl -- namespace =kube- system Context "kube-system-ctx" modified. #设置用户项中cluster-admin用户证书认证字段 kubectl config set-credentials cluster-admin --certificate-authority=ca.pem --client-key=admin-key.pem --client-certificate=admin.pem #设置默认上下文 kubectl config set-context default --cluster=kubernetes --user=cluster-admin #切换上下文context kubectl config use-context kube- system -ctx Switched to context "kube-system-ctx" . |
查看config文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # kubectl config view apiVersion: v1 clusters: - cluster: certificate-authority: /opt/kubernetes/kubectl/ssl/ca.pem server: https: //10.1.210.33:6443 name: kubernetes contexts: - context: cluster: kubernetes user: cluster-admin name: default current-context: default kind: Config preferences: {} users: - name: cluster-admin user: client-certificate: /opt/kubernetes/kubectl/ssl/admin.pem client-key: /opt/kubernetes/kubectl/ssl/admin-key.pem |
将kubeconfig和kubelet可执行文件拷贝到远程主机或者笔记本上即可(笔记本要有vpn ping得通内网的服务器)
1 | cp zjz.kubeconfig ~/.kube/config |
二、context的理解
context:背景,环境,上下文
对上下文(context)的理解:集群包含context,一个k8s集群中可以有多个context,比如ops、dev、lead。在不同的上下文中,资源是相互隔离的,互不干扰。
k8s集群可以通过namespace和context的设置来对不同的工作组进行区分,同一集群,不同的namespace下,不同context,资源隔离,互不干扰。而同一集群,同一namespace,不同context,资源做不到隔离。
另外,如果用一台机器管理多个k8s集群,集群切换操作也可以用context实现。
用途:配置对多集群的访问时,context字段定义用户访问凭证
每个上下文包含三部分(集群、用户和名字空间),
例如config配置如下:
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 32 33 34 35 36 37 38 | apiVersion: v1 clusters: - cluster: certificate-authority: fake-ca-file server: https: //1.2.3.4 name: development - cluster: insecure-skip-tls-verify: true server: https: //5.6.7.8 name: scratch contexts: - context: cluster: development namespace : frontend user: developer name: dev-frontend - context: cluster: development namespace : storage user: developer name: dev-storage - context: cluster: scratch namespace : default user: experimenter name: exp-scratch current-context: "" kind: Config preferences: {} users: - name: developer user: client-certificate: fake-cert-file client-key: fake-key-file - name: experimenter user: password: some-password username: exp |
dev-frontend
上下文表明:使用 developer
用户的凭证来访问 development
集群的 frontend
名字空间。
查看当前的context(是一个合并后的结果)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | $ kubectl config view apiVersion: v1 clusters: - cluster: certificate-authority-data: DATA+OMITTED server: https: //xx.xx.xx.xx:6443 name: Kubernetes contexts: - context: cluster: Kubernetes namespace : ops user: ops name: Kubernetes current-context: Kubernetes kind: Config preferences: {} users: - name: ops user: client-certificate-data: REDACTED client-key-data: REDACTED |
切换context
1 | kubectl config use-context k8s-cluster-name |
验证是否已经切换到了新的context
1 2 | kubectl config current-context Kubernetes |
删除context,不影响其下的资源
1 2 | kubectl config delete -context context1 deleted context context1 from /Users/zhangjingzhi/.kube/config |
新增一个context
1 2 | kubectl config set-context zjz -- namespace =zjz-ops --cluster=Kubernetes --user=ops Context "zjz" created. |
查看所有的contexts
1 2 3 4 5 | $ kubectl config get-contexts CURRENT NAME CLUSTER AUTHINFO NAMESPACE * Kubernetes Kubernetes ops ops context3 Kubernetes ops kube- system zjz Kubernetes ops zjz-ops |
设置工作上下文,前提是该命名空间已经存在
1 | kubectl config set-context xxx -- namespace =xxxx --cluster=xxxx --user=xxxx |
在kubeconfig配置文件中设置一个context。 如果指定了一个已存在的名字,将合并新字段并覆盖旧字段。
1 | kubectl config set-context NAME --cluster=cluster_nickname --user=user_nickname -- namespace = namespace |
示例
1 2 | # 设置gce环境项中的user字段,不影响其他字段。 $ kubectl config set-context gce --user=cluster-admin |
选项
1 2 3 | --cluster= "" : 设置kuebconfig配置文件中环境选项中的集群。 -- namespace = "" : 设置kuebconfig配置文件中环境选项中的命名空间。 --user= "" : 设置kuebconfig配置文件中环境选项中的用户。 |
继承自父命令的选项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | --alsologtostderr[= false ]: 同时输出日志到标准错误控制台和文件。 --api-version= "" : 和服务端交互使用的API版本。 --certificate-authority= "" : 用以进行认证授权的.cert文件路径。 --client-certificate= "" : TLS使用的客户端证书路径。 --client-key= "" : TLS使用的客户端密钥路径。 --cluster= "" : 指定使用的kubeconfig配置文件中的集群名。 --context= "" : 指定使用的kubeconfig配置文件中的环境名。 --insecure-skip-tls-verify[= false ]: 如果为 true ,将不会检查服务器凭证的有效性,这会导致你的HTTPS链接变得不安全。 --kubeconfig= "" : 命令行请求使用的配置文件路径。 -- log -backtrace-at=:0: 当日志长度超过定义的行数时,忽略堆栈信息。 -- log -dir= "" : 如果不为空,将日志文件写入此目录。 -- log -flush-frequency=5s: 刷新日志的最大时间间隔。 --logtostderr[= true ]: 输出日志到标准错误控制台,不输出到文件。 --match-server-version[= false ]: 要求服务端和客户端版本匹配。 -- namespace = "" : 如果不为空,命令将使用此 namespace 。 --password= "" : API Server进行简单认证使用的密码。 -s, --server= "" : Kubernetes API Server的地址和端口号。 --stderrthreshold=2: 高于此级别的日志将被输出到错误控制台。 --token= "" : 认证到API Server使用的令牌。 --user= "" : 指定使用的kubeconfig配置文件中的用户名。 --username= "" : API Server进行简单认证使用的用户名。 --v=0: 指定输出日志的级别。 --vmodule=: 指定输出日志的模块,格式如下:pattern=N,使用逗号分隔。 |
测试同一集群中,不同namespace下,不同的context,二者之间的关系
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #当前的context如下 kubectl config current-context Kubernetes #在Kubernetes中创建rc资源 kubectl apply -f redis.yaml replicationcontroller/redis-slave created $ kubectl get rc NAME DESIRED CURRENT READY AGE redis-slave 2 2 0 11s #切换到zjz-ops这个context下 $ kubectl config use-context zjz-ops Switched to context "zjz-ops" . 查看资源,正常输出是 No resources found in zjz-ops namespace . $ kubectl get rc The connection to the server localhost:8080 was refused - did you specify the right host or port |
测试同一个集群,同一个namespace下,不同的context,二者关系
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 32 33 34 35 36 | #查看现有的context,zjz1和Kubernetes属于同一集群同一namespace下: kubectl config get-contexts CURRENT NAME CLUSTER AUTHINFO NAMESPACE * Kubernetes Kubernetes ops ops context3 Kubernetes ops kube- system zjz Kubernetes ops zjz-ops zjz1 Kubernetes ops ops #切换到zjz1 kubectl config use-context zjz1 Switched to context "zjz1" . #创建资源、查看 $ kubectl create deployment web --image=nginx -n ops deployment.apps/web created $ kubectl get deployment -n ops NAME READY UP-TO-DATE AVAILABLE AGE postgresql 1/1 1 1 41d web 1/1 1 1 21s #切换到Kubernetes kubectl config use-context Kubernetes Switched to context "Kubernetes" . $ kubectl config current-context Kubernetes #可以查看zjz1创建的资源,也可以删除 $ kubectl get deployment -n ops NAME READY UP-TO-DATE AVAILABLE AGE postgresql 1/1 1 1 41d web 1/1 1 1 4m13s kubectl delete deployment web -n ops deployment.apps "web" deleted |
三、创建用户的shell脚本(cfssl工具生成证书)
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | #!/usr/bin/env bash # 注意修改KUBE_APISERVER为你的API Server的地址 KUBE_APISERVER=$1 USER=$2 USER_SA= system :serviceaccount: default :${USER} Authorization=$3 USAGE="USAGE: create-user.sh <api_server> <username> <clusterrole authorization>\n Example: https: //192.168.1.2:6443 brand" CSR=`pwd`/user-csr.json SSL_PATH= "/opt/kubernetes/ssl" USER_SSL_PATH= "/opt/kubernetes/create-user" SSL_FILES=(ca-key.pem ca.pem ca-config.json) CERT_FILES=(${USER}.csr $USER-key.pem ${USER}.pem) if [[ $KUBE_APISERVER == "" ]]; then echo -e $USAGE exit 1 fi if [[ $USER == "" ]];then echo -e $USAGE exit 1 fi if [[ $Authorization == "" ]];then echo -e $USAGE exit 1 fi # 创建用户的csr文件 function createCSR(){ cat>$CSR<<EOF { "CN" : "USER" , "hosts" : [], "key" : { "algo" : "rsa" , "size" : 2048 }, "names" : [ { "C" : "CN" , "ST" : "BeiJing" , "L" : "BeiJing" , "O" : "k8s" , "OU" : "System" } ] } EOF # 替换csr文件中的用户名 sed -i "s/USER/$USER_SA/g" $CSR } function ifExist(){ if [ ! -f "$SSL_PATH/$1" ]; then echo "$SSL_PATH/$1 not found." exit 1 fi } function ifClusterrole(){ kubectl get clusterrole ${Authorization} &> /dev/null if (( $? !=0 ));then echo "${Authorization} clusterrole there is no" exit 1 fi } # 判断clusterrole授权是否存在 ifClusterrole # 判断证书文件是否存在 for f in ${SSL_FILES[@]}; do echo "Check if ssl file $f exist..." ifExist $f echo "OK" done echo "Create CSR file..." createCSR echo "$CSR created" echo "Create user's certificates and keys..." cd $USER_SSL_PATH cfssl gencert -ca=${SSL_PATH}/ca.pem -ca-key=${SSL_PATH}/ca-key.pem -config=${SSL_PATH}/ca-config.json -profile=kubernetes $CSR| cfssljson -bare $USER_SA # 创建 sa kubectl create sa ${USER} -n default # 设置集群参数 kubectl config set-cluster kubernetes \ --certificate-authority=${SSL_PATH}/ca.pem \ --embed-certs= true \ --server=${KUBE_APISERVER} \ --kubeconfig=${USER}.kubeconfig # 设置客户端认证参数 kubectl config set-credentials ${USER_SA} \ --client-certificate=${USER_SSL_PATH}/${USER_SA}.pem \ --client-key=${USER_SSL_PATH}/${USER_SA}-key.pem \ --embed-certs= true \ --kubeconfig=${USER}.kubeconfig # 设置上下文参数 kubectl config set-context kubernetes \ --cluster=kubernetes \ --user=${USER_SA} \ -- namespace =development \ --kubeconfig=${USER}.kubeconfig # 设置默认上下文 kubectl config use-context kubernetes --kubeconfig=${USER}.kubeconfig # 创建 namespace # kubectl create ns $USER # 绑定角色 # kubectl create rolebinding ${USER}-admin-binding --clusterrole=admin --user=$USER --namespace=$USER --serviceaccount=$USER:default kubectl create clusterrolebinding ${USER}-binding --clusterrole=${Authorization} --user=${USER_SA} # kubectl config get-contexts echo "Congratulations!" echo "Your kubeconfig file is ${USER}.kubeconfig" |
context和kubeconfig的详细信息可参考官网:
1 2 3 | https: //kubernetes.io/zh/docs/concepts/configuration/organize-cluster-access-kubeconfig/#%E4%B8%8A%E4%B8%8B%E6%96%87-context https: //kubernetes.io/zh/docs/tasks/access-application-cluster/configure-access-multiple-clusters/#set-the-kubeconfig-environment-variable |
https://blog.csdn.net/zhangxiangui40542/article/details/81672578/ kubectl config配置示例
https://blog.csdn.net/ywq935/article/details/84840935 K8S基础-鉴权框架与用户权限分配,整理详细
用户认证ServiceAccount与授权策略RBAC · Devops Roadmap (curiouser.top)