写在开篇

这几天有点忙,终于抽出时间更新了,之前已经通过这篇 《通过源码分析告诉你:当访问K8S API的代码运行在POD里的容器时,在集群内是如何进行身份验证的》 搞清楚了在集群内如何进行身份验证。那么,官方还提供了一个简单的应用示例,链接:https://github.com/kubernetes/client-go/tree/master/examples/in-cluster-client-configuration

本篇的主题是解读一下这个示例。结合之前的知识储备并等本篇讲完后,就会很清晰的知道集群内的POD访问API时是如何进行身份验证的。下次就要回到这篇 《关于ServiceAccount以及在集群内访问K8S API》 继续讲解接下来的实战内容了,有没有发现兜了个圈又兜回来了。

示例代码分析

针对官方提供的示例,我做了点小改造。这段代码是一个使用Kubernetes Go客户端(client-go)的示例程序,用于获取Kubernetes集群中所有Pod的信息,并每隔10秒打印一次Pod的数量和POD名称。

package main

import (
 "context"
 "fmt"
 "time"

 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 "k8s.io/client-go/kubernetes"
 "k8s.io/client-go/rest"
)

func main() {
 config, err := rest.InClusterConfig()
 if err != nil {
  panic(err.Error())
 }
 clientset, err := kubernetes.NewForConfig(config)
 if err != nil {
  panic(err.Error())
 }
 for {
  pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})
  if err != nil {
   panic(err.Error())
  }
  for _, pod := range pods.Items {
   fmt.Printf("命名空间:%s POD名称:%s\n", pod.Namespace, pod.Name)
  }
  fmt.Printf("集群中有 %d 个 pod", len(pods.Items))
  time.Sleep(10 * time.Second)
 }
}

需要注意的事情,看这段代码的InClusterConfig函数,记得上次对它分析过:

config, err := rest.InClusterConfig()
if err != nil {
        panic(err.Error())
}

这段代码使用rest.InClusterConfig()函数获取当前运行环境下的Kubernetes集群的配置。如果获取配置时发生错误,通过panic抛出异常。

不信的话,编译后运行试试:

[root@workhost in-cluster-client-configuration]# ./app 
panic: unable to load in-cluster configuration, KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined

goroutine 1 [running]:
main.main()
        /root/project/gocode/src/in-cluster-client-configuration/main.go:17 +0x314

报错了。要解决这个问题,就是要将这个应用程序在POD内运行。

提示:报错的根本原因是因为这两个自定义变量是由K8S自身管理且定义在了POD里的容器内,只有将这个示例应用运行在POD里的容器才能正确加载自定义变量。

编译应用程序

[root@workhost src]# cd in-cluster-client-configuration/
[root@workhost in-cluster-client-configuration]# go mod init
go: creating new go.mod: module in-cluster-client-configuration
go: to add module requirements and sums:
        go mod tidy
[root@workhost in-cluster-client-configuration]# go mod tidy
[root@workhost in-cluster-client-configuration]# GOOS=linux go build -o ./app .
  • GOOS=linux:这将GOOS环境变量设置为linux,表示专门为Linux构建应用程序。
  • go build:这是Go语言的编译命令,用于编译Go源代码并生成可执行文件。
  • -o ./app:这是一个选项,指定编译输出的可执行文件的名称和路径。在这个命令中,-o表示指定输出文件,./app表示输出文件的路径和名称为当前目录下的app。
  • .:这是命令的最后一个参数,表示当前目录中的Go源代码文件。这告诉编译器从当前目录中的所有Go源文件中构建应用程序。

编译后:

[root@workhost in-cluster-client-configuration]# ls -l
total 43928
-rwxr-xr-x. 1 root root 44919028 May 23 08:59 app # 编译后得到的可执行二进制文件
-rw-r--r--. 1 root root       44 May 23 08:56 Dockerfile
-rw-r--r--. 1 root root     1909 May 23 08:59 go.mod
-rw-r--r--. 1 root root    47303 May 23 08:59 go.sum
-rw-r--r--. 1 root root     1750 May 23 08:57 main.go 

制作镜像

Dockerfile内容:

FROM debian
COPY ./app /app
ENTRYPOINT /app

构建镜像和推送到私有仓库:

docker build -t 192.168.11.254:8081/library/example-app:v1 .
docker push 192.168.11.254:8081/library/example-app:v1

在K8S运行

[root@k8s-b-master ~]# kubectl run --rm -i example-pod --image=192.168.11.254:8081/library/example-app:v1
pod "example-pod" deleted
error: timed out waiting for the condition

居然超时了,没有获取到POD。官方示例中提到,如果在K8S集群上启用了RBAC,就需要创建角色绑定。就此看来是因为权限问题导致。那先确定一下k8s集群是否启用了RBAC:

[root@k8s-b-master kubernetes]# kubectl api-versions | grep rbac
rbac.authorization.k8s.io/v1
[root@k8s-b-master kubernetes]# kubectl get roles,rolebindings --all-namespaces
NAMESPACE     NAME                                                                            CREATED AT
kube-public   role.rbac.authorization.k8s.io/kubeadm:bootstrap-signer-clusterinfo             2023-04-30T03:23:50Z
kube-public   role.rbac.authorization.k8s.io/system:controller:bootstrap-signer               2023-04-30T03:23:48Z
kube-system   role.rbac.authorization.k8s.io/extension-apiserver-authentication-reader        2023-04-30T03:23:48Z
...

这些输出提供了与RBAC授权相关的信息,包括可用的API版本以及集群中的角色和角色绑定配置,所以是启用了RBAC的。

注意:如果是使用kubeadm搭建的k8s集群,那么rbac默认都是启用的。如果是二进制搭建的,那就不一定了,这将取决于您的配置和部署选择。

接下来,创建一个名为"default-view"的ClusterRoleBinding:

kubectl create clusterrolebinding default-view --clusterrole=view --serviceaccount=default:default
  • default-view:ClusterRoleBinding的名称。在这个例子中,ClusterRoleBinding将被命名为"default-view"。
  • --clusterrole=view:选项,指定要绑定的ClusterRole。这里指定了"view" ClusterRole,它具有查看(view)集群资源的权限。ClusterRole是一组权限的集合,可以授予用户、组或服务账号特定的权限。
  • --serviceaccount=default:default:选项,指定要绑定到ClusterRole的ServiceAccount。这里指定了"default:default",表示将"default"命名空间下的"default" ServiceAccount与ClusterRole进行绑定。
总之,这个命令将创建一个名为"default-view"的ClusterRoleBinding,将"default"命名空间下的"default" ServiceAccount与"view" ClusterRole进行绑定。这意味着"default" ServiceAccount将具有查看集群资源的权限。这可以用于授予特定的ServiceAccount对集群资源的只读访问权限,而无需授予其他更高级的权限。

创建完角色绑定后继续运行:

[root@k8s-b-master ~]# kubectl run --rm -i example-pod --image=192.168.11.254:8081/library/example-app:v1
If you don't see a command prompt, try pressing enter.
命名空间:default POD名称:example-pod
命名空间:default POD名称:goweb-7db674b88c-d544x
命名空间:default POD名称:goweb-7db674b88c-j5hd6
命名空间:default POD名称:goweb-7db674b88c-v2z5r
命名空间:default POD名称:nginx
命名空间:kube-system POD名称:calico-kube-controllers-567c56ff98-pb4dj
命名空间:kube-system POD名称:calico-node-7kqhw
命名空间:kube-system POD名称:calico-node-hbbs4
命名空间:kube-system POD名称:calico-node-pngws
命名空间:kube-system POD名称:calico-node-r8vp9
命名空间:kube-system POD名称:calico-node-sfws4
命名空间:kube-system POD名称:calico-node-skktr
命名空间:kube-system POD名称:calico-node-wm2lt
命名空间:kube-system POD名称:coredns-c676cc86f-lkw8r
命名空间:kube-system POD名称:coredns-c676cc86f-ncnnn
命名空间:kube-system POD名称:etcd-k8s-b-master
命名空间:kube-system POD名称:kube-apiserver-k8s-b-master
命名空间:kube-system POD名称:kube-controller-manager-k8s-b-master
命名空间:kube-system POD名称:kube-proxy-8hw4f
命名空间:kube-system POD名称:kube-proxy-9qsc8
命名空间:kube-system POD名称:kube-proxy-b4vjj
命名空间:kube-system POD名称:kube-proxy-d7lh9
命名空间:kube-system POD名称:kube-proxy-nmdxd
命名空间:kube-system POD名称:kube-proxy-ql2kf
命名空间:kube-system POD名称:kube-proxy-stfff
命名空间:kube-system POD名称:kube-scheduler-k8s-b-master
集群中有 26 个 pod命名空间:default POD名称:example-pod
命名空间:default POD名称:goweb-7db674b88c-d544x
命名空间:default POD名称:goweb-7db674b88c-j5hd6
命名空间:default POD名称:goweb-7db674b88c-v2z5r
命名空间:default POD名称:nginx
命名空间:kube-system POD名称:calico-kube-controllers-567c56ff98-pb4dj
命名空间:kube-system POD名称:calico-node-7kqhw
命名空间:kube-system POD名称:calico-node-hbbs4
命名空间:kube-system POD名称:calico-node-pngws
命名空间:kube-system POD名称:calico-node-r8vp9
命名空间:kube-system POD名称:calico-node-sfws4
命名空间:kube-system POD名称:calico-node-skktr
命名空间:kube-system POD名称:calico-node-wm2lt
命名空间:kube-system POD名称:coredns-c676cc86f-lkw8r
命名空间:kube-system POD名称:coredns-c676cc86f-ncnnn
命名空间:kube-system POD名称:etcd-k8s-b-master
命名空间:kube-system POD名称:kube-apiserver-k8s-b-master
命名空间:kube-system POD名称:kube-controller-manager-k8s-b-master
命名空间:kube-system POD名称:kube-proxy-8hw4f
命名空间:kube-system POD名称:kube-proxy-9qsc8
命名空间:kube-system POD名称:kube-proxy-b4vjj
命名空间:kube-system POD名称:kube-proxy-d7lh9
命名空间:kube-system POD名称:kube-proxy-nmdxd
命名空间:kube-system POD名称:kube-proxy-ql2kf
命名空间:kube-system POD名称:kube-proxy-stfff
命名空间:kube-system POD名称:kube-scheduler-k8s-b-master
集群中有 26 个 pod命名空间:default POD名称:example-pod
命名空间:default POD名称:goweb-7db674b88c-d544x
命名空间:default POD名称:goweb-7db674b88c-j5hd6
命名空间:default POD名称:goweb-7db674b88c-v2z5r
命名空间:default POD名称:nginx
命名空间:kube-system POD名称:calico-kube-controllers-567c56ff98-pb4dj
命名空间:kube-system POD名称:calico-node-7kqhw
命名空间:kube-system POD名称:calico-node-hbbs4
命名空间:kube-system POD名称:calico-node-pngws
命名空间:kube-system POD名称:calico-node-r8vp9
命名空间:kube-system POD名称:calico-node-sfws4
命名空间:kube-system POD名称:calico-node-skktr
命名空间:kube-system POD名称:calico-node-wm2lt
命名空间:kube-system POD名称:coredns-c676cc86f-lkw8r
命名空间:kube-system POD名称:coredns-c676cc86f-ncnnn
命名空间:kube-system POD名称:etcd-k8s-b-master
命名空间:kube-system POD名称:kube-apiserver-k8s-b-master
命名空间:kube-system POD名称:kube-controller-manager-k8s-b-master
命名空间:kube-system POD名称:kube-proxy-8hw4f
命名空间:kube-system POD名称:kube-proxy-9qsc8
命名空间:kube-system POD名称:kube-proxy-b4vjj
命名空间:kube-system POD名称:kube-proxy-d7lh9
命名空间:kube-system POD名称:kube-proxy-nmdxd
命名空间:kube-system POD名称:kube-proxy-ql2kf
命名空间:kube-system POD名称:kube-proxy-stfff
命名空间:kube-system POD名称:kube-scheduler-k8s-b-master
集群中有 26 个 pod
...
...
...

本文转载于WX公众号:不背锅运维(喜欢的盆友关注我们):https://mp.weixin.qq.com/s/N3ArZ-T62yUZClf2UN5Qrg


不背锅运维
32 声望2 粉丝

人在江湖飘,哪有不挨刀,运维也是如此。人在工位坐,祸从天上来。运维时而是救火英雄,又时而是背锅大侠。如何远离背锅,淡然饮茶?带你升级打怪、提升段位,走!带你上分去。