本文发布于Cylon的收藏册,转载请著名原文链接~
在我们基于 Kubernetes 编写云原生 GoLang 代码时,通常在本地调试时,使用 kubeconfig 文件,以构建基于 clientSet 的客户端。而在将代码作为容器部署到集群时,则会使用集群 (in-cluster) 内的配置。
clientcmd 模块用于通过传递本地 kubeconfig 文件构建 clientSet。因此,在容器内使用相同模块构建 clientSet 将需要维护容器进程可访问的 kubeconfig 文件,并设置具有访问 Kubernetes 资源权限的 serviceaccount token。
下面是一个基于 kubeconfig 访问集群的代码模式
var (
k8sconfig *string //使用kubeconfig配置文件进行集群权限认证
restConfig *rest.Config
err error
)
if home := homedir.HomeDir(); home != "" {
k8sconfig = flag.String("kubeconfig", fmt.Sprintf("./admin.conf"), "kubernetes auth config")
}
flag.Parse()
if _, err := os.Stat(*k8sconfig); err != nil {
panic(err)
}
clientset,err := kubernetes.NewConfig(k8sconfig)
if err != nil {
panic(err)
}
这样做可能导致 serviceaccount token 本身被潜在地暴露出去。如果任何用户能够执行到使用 kubeconfig 与集群通信的容器,那么就可以获取该 token,并可以伪装成服务账号从集群外部与 kube-apiserver 进行通信。
为了避免这种情况,我们在 client-go 模块中使用了 rest 包。这将帮助我们从集群内部与集群通信,前提是使用适当的服务账号运行。但这需要对代码进行重写,以适应从集群外部构建 client-set 的方式。
下面代码时使用 in-cluster 方式进行通讯的模式
var (
k8sconfig *string //使用kubeconfig配置文件进行集群权限认证
restConfig *rest.Config
err error
)
if home := homedir.HomeDir(); home != "" {
k8sconfig = flag.String("kubeconfig", fmt.Sprintf("./admin.conf"), "kubernetes auth config")
}
k8sconfig = k8sconfig
flag.Parse()
if _, err := os.Stat(*k8sconfig); err != nil {
panic(err)
}
if restConfig, err = rest.InClusterConfig(); err != nil {
// 这里是从masterUrl 或者 kubeconfig传入集群的信息,两者选一
// 先从 in-cluster 方式获取,如果不能获取,再执行这里
restConfig, err = clientcmd.BuildConfigFromFlags("", *k8sconfig)
if err != nil {
panic(err)
}
}
restset, err := kubernetes.NewForConfig(restConfig)
除了这些之外,还需要创建对应的 serviceaccount 来让 Pod 在 in-cluster 有权限获取到自己要的资源,下面是一个完整的 deployment 创建这些资源的清单
apiVersion: v1
kind: Namespace
metadata:
name: infra
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-proxier-secret-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: pod-proxier-rolebinding
subjects:
- kind: ServiceAccount
name: pod-proxier-secret-sa
namespace: infra
roleRef:
kind: ClusterRole
name: pod-proxier-secret-reader
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: infra
name: pod-proxier-secret-sa
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: pod-proxier
spec:
replicas: 1
selector:
matchLabels:
app: pod-proxier
template:
metadata:
labels:
app: pod-proxier
spec:
serviceAccount: pod-proxier-secret-sa # 使用上面定义的 sa 进行in-cluster 访问
containers:
- name: container-1
image: haproxytech/haproxy-debian:2.6
ports:
- containerPort: 80
hostPort: 8080 # 添加 hostPort 字段
- name: container-2
image: container-2-image:tag
ports:
- containerPort: 8080
hostPort: 8081 # 添加 hostPort 字段
本文发布于Cylon的收藏册,转载请著名原文链接~
链接:https://www.oomkill.com/2023/11/ch07-in-cluster-pod/
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」 许可协议进行许可。