k8s中设置annotation的方法总结

server/2024/12/18 20:25:35/

k8s中设置annotation的方法总结

annotation是什么

在 Kubernetes 中,Annotations 是一种用于向 Kubernetes 对象附加非标识性元数据的机制。

annotation有什么用

annotation与 Labels 类似,但有一些关键区别和特定用途。 常用于存储与对象相关的配置信息、工具信息、元数据等,但这些信息不会影响 Kubernetes 对象的调度或生命周期管理。

注意相比labels来说, annotation具有不可见性: Annotations 不会被 Kubernetes API 用于选择或路由对象,因此不会影响调度决策或资源管理。

annotation的设置方式

我们可以为常见的资源种类,pod、pvc、pv、deployment、statefulset等设置annotation.

对于 annotation 的操作,只有3种:增加、删除、更新。(如果需要查看可以kubectl get pod -oyaml方式从详细信息中过滤)

方式一:kubectl annotate命令

# 为pod设置一个新的 annotation
root@dg02-k8s-pnode1:~# kubectl annotate pod ubuntu1604 it/city="shenzhen"
pod/ubuntu1604 annotated# 为pod修改存在的 annotation 对应的key/value
root@dg02-k8s-pnode1:~# kubectl annotate pod ubuntu1604 it/city="shanghai" --overwrite
pod/ubuntu1604 annotated# 删除 annotation 对应的key/value
root@dg02-k8s-pnode1:~# kubectl annotate pod ubuntu1604 it/city-
pod/ubuntu1604 annotated

方式二: kubectl patch命令

这里需要注意,在patch时,对于json串中的~,/需要分别转义为~0~1

# 增
kubectl patch pod --type=json -p='[{"op": "add", "path": "/metadata/annotations/it~1city", "value": "shenzhen"}]' ubuntu1604
# 改
kubectl patch pod --type=json -p='[{"op": "replace", "path": "/metadata/annotations/it~1city", "value": "shanghai"}]' ubuntu1604
# 删
kubectl patch pod --type=json -p='[{"op": "remove", "path": "/metadata/annotations/it~1city", "value": ""}]' ubuntu1604

方式三: client-go

除了前2种使用kubectl命令的方式,开发人员通常使用client-go对资源操控annotation

使用Patch方式更新K8S的 API Objects 一共有三种方式:strategic merge patch, json-patch,json merge patch。本文介绍最常用的json-patch,其他2种方式,请参考其他文献

本次示例以给一个pod新增一个annotation为例,直接上代码:

package serviceimport ("encoding/json""fmt""github.com/pkg/errors""go.uber.org/zap"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/apimachinery/pkg/types""kubecmdb/internal/buildk8s""kubecmdb/utils""strings"
)// AnnotationReplace 更新pod的annotation
func AnnotationReplace(clusterName, namespace, name, key string, value interface{}) error {// 获取 clientSetmyClientSet := buildk8s.GetK8SClientSet(clusterName)// 判断 pod 是否存在_, err := myClientSet.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{})if err != nil {utils.Error("[annotation]", zap.String("err", err.Error()))return errors.Wrapf(err, "AnnotationAdd pod get err.")}// 符号 ~ 需要转换为 ~0if strings.Contains(key, "~") {key = strings.Replace(key, "~", "~0", -1)}if strings.Contains(key, "/") {// 符号 / 需要转换为 ~1key = strings.Replace(key, "/", "~1", -1)}// 需要修改的 annotation 的键值对patchObj := struct {Op    string      `json:"op"`Path  string      `json:"path"`Value interface{} `json:"value"`}{Op:    "replace", // 可以使用add 或 replacePath:  "/metadata/annotations/" + key,Value: value,}// 转换为json串var patchObjs []interface{}patchObjs = append(patchObjs, patchObj)patchData, err := json.Marshal(patchObjs)if err != nil {utils.Error("[annotation]", zap.String("err", err.Error()))return errors.Wrapf(err, "AnnotationAdd Marshal err.")}// 使用 Patch 方法修改//patchData:=fmt.Sprintf("'[{\"op\": \"replace\", \"path\": \"/metadata/annotations/it~1domain\", \"value\": \"xxx\"}]'")fmt.Printf("patchData=%v\n", string(patchData))_, err = myClientSet.CoreV1().Pods(namespace).Patch(name, types.JSONPatchType, patchData)if err != nil {utils.Error("[annotation]", zap.String("err", err.Error()))return errors.Wrapf(err, "AnnotationAdd Patch err.")}return nil}// AnnotationAdd 添加pod的annotation
func AnnotationAdd(clusterName, namespace, name, key string,value interface{}) error {return AnnotationReplace(clusterName, namespace, name, key, value)
}// AnnotationRemove 删除pod的annotation
func AnnotationRemove(clusterName, namespace, name, key string) error {// 获取 clientSetmyClientSet := buildk8s.GetK8SClientSet(clusterName)pod, err := myClientSet.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{})if err != nil {utils.Error("[annotation]", zap.String("err", err.Error()))return errors.Wrapf(err, "AnnotationAdd pod get err.")}// 如果不存在,返回操作成功if _,ok := pod.ObjectMeta.Annotations[key];!ok {return nil}// 符号 ~ 需要转换为 ~0if strings.Contains(key, "~") {key = strings.Replace(key, "~", "~0", -1)}// 符号 / 需要转换为 ~1if strings.Contains(key, "/") {key = strings.Replace(key, "/", "~1", -1)}// 需要修改的 annotation 的键值对patchObj := struct {Op    string      `json:"op"`Path  string      `json:"path"`Value interface{} `json:"value"`}{Op:    "remove",Path:  "/metadata/annotations/" + key,Value: "", // 不需要填 value}// 转换为json串var patchObjs []interface{}patchObjs = append(patchObjs, patchObj)patchData, err := json.Marshal(patchObjs)if err != nil {utils.Error("[annotation]", zap.String("err", err.Error()))return errors.Wrapf(err, "AnnotationAdd Marshal err.")}// 使用 Patch 方法修改//patchData:=fmt.Sprintf("'[{\"op\": \"replace\", \"path\": \"/metadata/annotations/it~1domain\", \"value\": \"xxx\"}]'")fmt.Printf("patchData=%v\n", string(patchData))_, err = myClientSet.CoreV1().Pods(namespace).Patch(name, types.JSONPatchType, patchData)if err != nil {utils.Error("[annotation]", zap.String("err", err.Error()))return errors.Wrapf(err, "AnnotationAdd Patch err.")}return nil
}

单元测试


package serviceimport ("testing"
)// 更改
// go test -run "^TestAnnotationReplace$" -v
func TestAnnotationReplace(t *testing.T) {err := AnnotationReplace("dg11test", "public", "ubuntu1604", "it/city", "shanghai")if err != nil {t.Fatal(err)}
}// 添加
// go test -run "^TestAnnotationAdd$" -v
func TestAnnotationAdd(t *testing.T) {err := AnnotationAdd("dg11test", "public", "ubuntu1604", "it/city", "shenzhen")if err != nil {t.Fatal(err)}
}//删除
// go test -run "^TestAnnotationRemove$" -v
func TestAnnotationRemove(t *testing.T) {err := AnnotationRemove("dg11test", "public", "ubuntu1604", "it/city", )if err != nil {t.Fatal(err)}
}

参考文献

K8S client-go Patch example
kuberntes中文文档


http://www.ppmy.cn/server/151267.html

相关文章

Spring Boot 条件注解:@ConditionalOnProperty 完全解析

在 Spring Boot 项目中,有时候我们希望根据配置文件中的某个属性值来决定是否启用某个功能或加载某个组件。此时,ConditionalOnProperty 注解就可以发挥作用。它通过配置文件的属性值控制 Bean 或配置类的加载,使得我们的程序更具灵活性。 本…

Flink SQL保留关键字

官方参考资料: SQL | Apache Flink 在使用flink时,如果不小心用到了flink保留关键字,会产生关键字错误。关于flink关键字,官方原话是“Although not every SQL feature is implemented yet, some string combinations are alread…

限制redis内存

要限制Redis的内存使用,可以在Redis的配置文件中设置maxmemory参数。以下是如何在Docker环境中限制Redis内存的步骤: 编辑Redis配置文件: 已经创建了Redis的配置文件/mydata/redis/conf/redis.conf,现在需要在这个文件中添加或修…

每天40分玩转Django:Django视图和URL

Django视图和URL 一、课程概述 学习项目具体内容预计用时视图基础函数视图、类视图、视图装饰器90分钟URL配置URL模式、路由系统、命名URL60分钟请求处理请求对象、响应对象、中间件90分钟 二、视图基础 2.1 函数视图 # blog/views.py from django.shortcuts import render…

vue.js数据绑定和事件处理

单元一 vue.js 数据的绑定 学习目标 (1)插值 (2)绑定表达式 任务一 插值 1.1任务描述 数据绑定最常见的形式就是使用 “Mustache” 语法(双大括号)的文本插值,对于所有的数据绑定&#…

linux网络编程 | c | epoll实现IO多路转接服务器

epoll实现IO多路转接服务器 可通过以下视频学习 06-opell函数实现的多路IO转接_哔哩哔哩_bilibili 通过响应式–多路IO转接实现 文章目录 epoll实现IO多路转接服务器1.思路&功能核心思路 2.代码实现multi_epoll_sever.c运行图 1.思路&功能 **功能:**客…

Android 13 相较于 Android 12 的新特性

标签: Android 13 ; Android 13 新特性; Android 13 相较于 Android 12 的新特性及开发者注意事项 一、Android 13 相较于 Android 12 的新特性 Android 13(代号 Tiramisu)在用户体验、安全性、隐私保护以及开发者工…

Android AOSP 源码中批量替换“phone“为“tablet“的命令详解

我来帮你写一篇关于这条命令的分析博客。 Android 项目中批量替换"phone"为"tablet"的命令详解 前言 在 Android 开发中,有时我们需要批量修改资源文件中的某些文本内容。今天我们来分析一条结合了 grep 和 sed 的强大命令,该命令用于将项目中的 “ph…