写在开篇
在之前的分享中,还有遗留的实战内容没有作出分享,也就是为Pod配置ServiceAccount:
-
创建ServiceAccount -
创建Role:定义所需的权限 -
创建RoleBinding,将ServiceAccount和Role关联起来 -
将ServiceAccount对象分配给Pod
其实,在实战这个内容之前,且已经将涉及到的前置知识点作了分享,可参考如下3篇:
本篇实战场景:开发示例应用,该应用运行在集群内POD中,并通过访问K8S API读取业务相关配置参数,且配置保存在configmap资源对象中。下面模拟了几个业务应用程序假设需要使用到参数:
键 | 值 | 说明 |
---|---|---|
MaxConn | 500 | 最大连接数 |
MinConn | 100 | 最小连接数 |
CleanCacheTime | 300s | 清理缓存时间 |
UploadDataTime | 86400s | 上传数据时间 |
准备工作
使用kubectl命令创建名称空间和configmap
kubectl create ns goweb
kubectl create configmap gowebcm --from-literal=MaxConn=500 --from-literal=MinConn=100 --from-literal=CleanCacheTime=300s --from-literal=UploadDataTime=86400s -n goweb
对应的yaml:
apiVersion: v1
kind: Namespace
metadata:
name: goweb
---
apiVersion: v1
kind: ConfigMap
metadata:
name: gowebcm
namespace: goweb
data:
CleanCacheTime: 300s
MaxConn: "500"
MinConn: "100"
UploadDataTime: 86400s
[root@k8s-b-master ~]# kubectl get configmap -n goweb
NAME DATA AGE
gowebcm 4 107s
示例应用代码
下面这段代码的功能是从 Kubernetes 的 ConfigMap 中获取数据,并通过一个简单的 HTTP 服务器将数据展示在网页上:
package main
import (
"context"
"fmt"
"log"
"net/http"
"sync"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
var Data []map[string]string
func getConfigMapData() {
// 如果要使用集群外身份验证,请取消以下注释
// var kubeconfig *string
// if home := homedir.HomeDir(); home != "" {
// kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(可选)kubeconfig 文件的绝对路径")
// } else {
// kubeconfig = flag.String("kubeconfig", "", "kubeconfig 文件的绝对路径")
// }
// config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
// if err != nil {
// panic(err.Error())
// }
// 当前使用集群内身份验证
config, err := rest.InClusterConfig()
if err != nil {
panic(err.Error())
}
// 创建 clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err.Error())
}
configMap, err := clientset.CoreV1().ConfigMaps("goweb").Get(context.TODO(), "gowebcm", metav1.GetOptions{})
if err != nil {
panic(err.Error())
}
data := configMap.Data
Data = append(Data, data)
}
func home(w http.ResponseWriter, r *http.Request) {
// 构建 HTML 表格字符串
html := `
<!DOCTYPE html>
<html>
<head>
<title>ConfigMap</title>
<style>
table {
width: 100%;
border-collapse: collapse;
border: 1px solid #ddd;
}
th, td {
padding: 10px;
border: 1px solid #ddd;
}
</style>
</head>
<body>
<h1>从ConfigMap读取的数据:</h1>
<table>
`
for _, v := range Data {
for key, value := range v {
html += fmt.Sprintf("<tr><td>%v</td><td>%v</td></tr>", key, value)
}
}
html += `
</table>
</body>
</html>
`
// 设置响应头的 Content-Type 为 text/html
w.Header().Set("Content-Type", "text/html; charset=utf-8")
// 将 HTML 写入响应体
fmt.Fprint(w, html)
}
func startWeb() {
http.HandleFunc("/", home)
err := http.ListenAndServe(":80", nil)
if err != nil {
log.Println(err)
}
}
func main() {
var wg sync.WaitGroup
wg.Add(2)
go getConfigMapData()
go startWeb()
wg.Wait()
}
编译代码:
go mod tidy
GOOS=linux go build -o ./app .
Dockerfile内容:
FROM debian
COPY ./app /app
ENTRYPOINT /app
构建镜像和推送到私有Harbor:
docker build -t 192.168.11.254:8081/webdemo/goweb:20230530v1 .
docker push 192.168.11.254:8081/webdemo/goweb:20230530v1
创建Pod,并为其配置使用指定的ServiceAccount启动
-
创建ServiceAccount
命令:
kubectl create serviceaccount goweb-sa -n goweb
对应的yaml:
apiVersion: v1
kind: ServiceAccount
metadata:
name: goweb-sa
namespace: goweb
-
创建Role,定义所需的权限
命令:
kubectl create role goweb-role --verb=get --verb=list --verb=watch --namespace=goweb --resource=configmaps --resource-name=gowebcm
对应的yaml:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: goweb-role
namespace: goweb
rules:
- apiGroups:
- ""
resourceNames:
- gowebcm
resources:
- configmaps
verbs:
- get
- list
- watch
-
创建RoleBinding,将ServiceAccount和Role关联起来
命令:
kubectl create rolebinding goweb-rolebinding --role=goweb-role --serviceaccount=goweb:goweb-sa --namespace=goweb
对应的yaml:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: goweb-rolebinding
namespace: goweb
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: goweb-role
subjects:
- kind: ServiceAccount
name: goweb-sa
namespace: goweb
-
创建Pod,将ServiceAccount对象分配给Pod
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: goweb
name: goweb
namespace: goweb
spec:
replicas: 3
selector:
matchLabels:
app: goweb
template:
metadata:
labels:
app: goweb
spec:
serviceAccountName: goweb-sa # 这里是关键
containers:
- name: goweb
image: 192.168.11.254:8081/webdemo/goweb:20230530v1
imagePullPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
labels:
app: goweb
name: goweb
namespace: goweb
spec:
ports:
- name: http-port
port: 5678
protocol: TCP
targetPort: 80
nodePort: 30080
selector:
app: goweb
type: NodePort
-
暴露后访问
如果POD没有指定ServiceAccount启动会怎么样
也就是在deployment中注释掉以下内容:
# serviceAccountName: goweb-sa
删掉之前的,并添加完注释后,再次创建后,看看接下来发生的情况:
[root@k8s-b-master ~]# kubectl get pod -n goweb
NAME READY STATUS RESTARTS AGE
goweb-5d455dd849-5gnnp 0/1 Error 2 (16s ago) 18s
goweb-5d455dd849-76pkw 0/1 Error 2 (16s ago) 18s
goweb-5d455dd849-pn5dl 0/1 Error 2 (16s ago) 18s
# 看pod里容器内log
[root@k8s-b-master ~]# kubectl logs goweb-5d455dd849-5gnnp -n goweb
panic: configmaps "gowebcm" is forbidden: User "system:serviceaccount:goweb:default" cannot get resource "configmaps" in API group "" in the namespace "goweb"
goroutine 6 [running]:
main.getConfigMapData()
/data/project/gocode/src/goweb/main.go:44 +0x13b
created by main.main
/data/project/gocode/src/goweb/main.go:104 +0x45
[root@k8s-b-master ~]#
❝
通过查看log发现,这个错误表明名为 “gowebcm” 的 ConfigMap 对于位于 “goweb” 命名空间中的 “default” 服务账户而言是被禁止的资源。k8s使用访问控制规则来限制不同服务账户对资源的访问权限。所以,想要访问gowebcm,必须要使用刚才创建好的服务账号goweb-sa。
❞
原文始发于微信公众号(不背锅运维):为Pod配置ServiceAccount:实战POD内应用以API方式读取ConfigMap
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/149456.html