探索client-go中的exec和cp的原理

开发kubernetes控制器中可能涉及到进入特定的container中执行命令的操作,或者拷贝文件等操作,此时我们可能会借助client-go提供的这个工具去实现: "k8s.io/client-go/tools/remotecommand" // 构建请求 req := client.RESTClient().Post(). Resource("pods"). Name(podName). Namespace(namespace). SubResource("exec") req.VersionedParams(&v1.PodExecOptions{ Container: containerName, Command: cmd, Stdin: false, Stdout: true, Stderr: true, TTY: true, }, scheme.ParameterCodec) // 创建执行器 exec, err := remotecommand.NewSPDYExecutor(config, "POST", req.URL()) // 执行命令 exec.Stream(remotecommand.StreamOptions{ Stdin: nil, Stdout: &buf, Stderr: &buf, Tty: true, }) 上面代码执行时会向apiserver发起一个请求,apiserver会通过代理机制将请求转发给相应节点上的kubelet服务,kubelet会通过cri接口调用runtime的接口发起流式接口中的Exec()接口进入到container执行。针对一般化的命令调用,输入参数和输出结果多数以文本为主,并不会占用带宽和apiserver的资源,但是当设计到文件拷贝的时候则会占用较多带宽,因此在实际使用时这种方式拷贝大文件来说可能并不是最优方案。 此处顺便描述一下如kubectl工具对cp命令的原理,其实也是调用的exec接口,然后执行tar命令进行文件的拷贝动作: # 从容器向外拷贝,通过tar命令压缩将输出重定向到标准输出 tar cf - <srcFile# 从外面向容器内拷贝,将标准输入数据通过tar解压写入到container内的文件目录 tar --no-same-permissions --no-same-owner -xmf - # 或 tar -xmf - 考虑到上面所说的带宽问题,在实际使用时也可向kubelet直接发起exec请求,只要通过client-go将pod所在节点实现查询一下即可,当然还会设计一些端口,证书问题,下面是一个直接向kubelet发起请求的示例代码。 package main import…

kubernetes基础 – 管理守护进程

damonset一般运行在集群的所有节点上,是一些常驻服务,通常可以用来收集日志,作为存储节点,运行监控进程等。 下面是一个日志收集的daemonset的定义: apiVersion: apps/v1 kind: DaemonSet metadata: name: fluentd-elasticsearch namespace: kube-system labels: k8s-app: fluentd-logging spec: selector: matchLabels: name: fluentd-elasticsearch updateStrategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 maxSurge: "100%" template: metadata: labels: name: fluentd-elasticsearch spec: # nodeSelector: # node-role.kubernetes.io/worker: "true" tolerations: - key: node-role.kubernetes.io/master operator: Exists effect: NoSchedule containers: - name: fluentd-elasticsearch image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2 resources: limits: memory: 200Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: varlog mountPath: /var/log - name: varlibdockercontainers…

kubernetes基础 – 管理有状态服务

statefulset区别于deployment有两个最重要的特性:有序性,固定性。 适用的场景 StatefulSets 对于需要满足以下一个或多个需求的应用程序很有价值: 稳定的、唯一的网络标识符 稳定的、持久的存储 有序的、优雅的部署和缩放 有序的、自动的滚动更新 限制 pod的持久化存储基于pvc和pv。 为保证数据安全,删除或者收缩statefulset并不会自动删除它关联的存储卷。 需要手动创建无头服务使pod的dns可解析。 删除 statefulset时,并不按照有序性执行,要求有序的话,可以在删除之前将 statefulset 缩放为 0。 默认pod管理策略(OrderedReady) 时使用滚动更新,有可能会有更新终止,需要人为修复的状况。 有序性: 每个pod都有一个序号 部署时和扩容时根据序号递增依次启动新pod 缩容时依次根据序号递减依次删除pod 固定标识 statefulset在创建pod的时候会为每个pod分配下面几个固定的标识。 固定网络标识 pod的名称和pod的主机名是根据statefulset的名称和当前pod的序号组成的:$(statefulset-name)-$(ordinal)。dns解析需要无头服务。 规则 Cluster Domain Service (ns/name) StatefulSet (ns/name) StatefulSet Domain Pod DNS Pod Hostname cluster.local default/nginx default/web nginx.default.svc.cluster.local web-{0..N-1}.nginx.default.svc.cluster.local web-{0..N-1} cluster.local foo/nginx foo/web nginx.foo.svc.cluster.local web-{0..N-1}.nginx.foo.svc.cluster.local web-{0..N-1} kube.local foo/nginx foo/web nginx.foo.svc.kube.local web-{0..N-1}.nginx.foo.svc.kube.local web-{0..N-1} 固定存储 pvc名称规则:$(tpl-metadata.name)-$(podname) pod标签 每个pod标签里会自动加一个 statefulset.kubernetes.io/pod-name 方便针对单个pod创建service。 pod管理策略 对于部署,扩缩容和更新时的并行度设置。 OrderedReady(依次) Parallel(并行,只影响扩缩操作,对更新策略不生效) 更新策略 手动(需要手动删除pod)…

kubernetes基础 – 管理无状态服务

考虑到性能和可用性,通常一个服务会有多个服务实例,在k8s中通过多个pod实现。 无状态服务是各个pod完全是一样,彼此可替代。 有状态服务是各个pod不完全一样,不可彼此替代,比如pod关联特定存储卷。 对于以下场景可以使用replicaset: 稳定的、唯一的网络标识符。 稳定的、持久的存储。 有序的、优雅的部署和缩放。 有序的、自动的滚动更新。 replicaset讲解 replicaset 的目的是维护一组在任何时候都处于运行状态的 Pod 副本的稳定集合。 因此,它通常用来保证给定数量的、完全相同的 Pod 的可用性。 replicaset通过pod的metadata.ownerReferences对应的replicaset。如果匹配的pod没有这个值扩不是控制器,那么replicaset将捕获纳管这个pod。 ReplicaSet 确保任何时间都有指定数量的 Pod 副本在运行。 然而,Deployment 是一个更高级的概念,它管理ReplicaSet,并向 Pod 提供声明式的更新以及许多其他有用的功能。 因此,我们建议使用 Deployment 而不是接使用 ReplicaSet,除非 你需要自定义更新业务流程或根本不需要更新。 示例replicaset: apiVersion: apps/v1 kind: ReplicaSet metadata: name: frontend labels: app: guestbook tier: frontend spec: # modify replicas according to your case replicas: 3 selector: matchLabels: tier: frontend template: metadata: labels: tier: frontend spec: containers: - name: php-redis image: gcr.io/google_samples/gb-frontend:v3 操作:…

kubernets基础 – 基础对象讲解

kubernetes中api资源由特定的规范进行定义,api资源由组,版本和类型三部分组成,简称gvk。一个gvk确定一种对象类型,对该类型由对应的结构对其进行定义。kubernetes中对象的存储和传输可以使用protobuf,yaml和json三种序列化形式。 pod pod是kubernetes中最小可部署单元。pod由一组container构成,包括业务容器,init容器,还有一个特殊的pause容器。 下面是一个简单的pod定义。 apiVersion: v1 kind: Pod metadata: name: webserver labels: app: webserver spec: containers: - name: webserver image: nginx:latest imagePullPolicy: IfNotPresent ports: - containerPort: 80 # hostPort: 8080 # hostIP: "169.169.1.1" name: http protocol: TCP initContainers: - name: init-dir image: busybox:latest workingDir: /tmp command: - /bin/sh - -c args: - "mkdir -p test" env: - name: MY_ENV value: "123456" - name: ANOTHER_ENV valueFrom: configMapKeyRef: name: test-cm key: CM_ENV…

kubernetes基础 – 常用命令

kubectl命令将用户的请求经过处理转换为apiserver的相应接口提交给apiserver处理。 可通过kubectl -v=8查看提交的详细信息。 资源的增删改查 创建资源 kubectl create -f - -f filename/directory/url -n namespace -l kubectl create -h ​ kubectl create service loadbalancer test --tcp=80:80 kubectl create deployment test --image=nginx ​ kubectl apply 删除资源 kubectl delete pod name kubectl delete pod/name -n namespace -l k8s-app=canal -f kubectl delete ns kubectl delete pod/all -all kubectl delete -h 编辑资源 KUBE_EDITOR=vim kubectl edit cm -n kube-system canal-config kubectl patch deployment test --patch='{"spec": {"template": {"spec":…

kubernetes网络 – metallb讲解

metallb用来实现在私有化搭建的裸机环境中实现负载均衡器的功能,在没有云环境的情况下通过metallb将service暴露到网络环境中,供其他系统访问。 https://metallb.universe.tf/ 部署metallb kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.10.2/manifests/namespace.yaml kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.10.2/manifests/metallb.yaml 创建配置 metallb监视名为config或metallb-config(helm部署)的configmap资源,我们创建这个资源之后它就开始工作了。 下面是layer 2模式下的配置示例,其中的addresses配置为预留的ip地址段,可配置多个。 [root@master3 ~]# cat metallb-configmap.yaml apiVersion: v1 kind: ConfigMap metadata: namespace: metallb-system name: config data: config: | address-pools: - name: default protocol: layer2 addresses: # 可配置为下列形式或者192.168.1.0/24形式,根据预留的网段具体决定 # 可配置多个 - 10.77.1.220-10.77.1.240 kubectl apply -f metallb-configmap.yaml 测试 [root@master3 ~]# kubectl run nginx --image=nginx --port=80 [root@master3 ~]# kubectl expose pod nginx --port=80 --target-port=80 --type=LoadBalancer [root@master3 ~]# kubectl get svc…

kubernetes网络 – 云控制器

https://kubernetes.io/zh/docs/concepts/architecture/cloud-controller/ 使用云基础设施技术,你可以在公有云、私有云或者混合云环境中运行 Kubernetes。 Kubernetes 的信条是基于自动化的、API 驱动的基础设施,同时避免组件间紧密耦合。 组件 cloud-controller-manager 是指云控制器管理器, 云控制器管理器是指嵌入特定云的控制逻辑的 控制平面组件。 云控制器管理器使得你可以将你的集群连接到云提供商的 API 之上, 并将与该云平台交互的组件同与你的集群交互的组件分离开来。 通过分离 Kubernetes 和底层云基础设置之间的互操作性逻辑, 云控制器管理器组件使云提供商能够以不同于 Kubernetes 主项目的 步调发布新特征。 cloud-controller-manager 组件是基于一种插件机制来构造的, 这种机制使得不同的云厂商都能将其平台与 Kubernetes 集成。 设计 云控制器管理器以一组多副本的进程集合的形式运行在控制面中,通常表现为 Pod 中的容器。每个 cloud-controller-manager 在同一进程中实现多个 控制器。 说明: 你也可以用 Kubernetes 插件 的形式而不是控制面中的一部分来运行云控制器管理器。 云控制器管理器的功能 云控制器管理器中的控制器包括: 节点控制器 节点控制器负责在云基础设施中创建了新服务器时为之 创建 节点(Node)对象。 节点控制器从云提供商获取当前租户中主机的信息。节点控制器执行以下功能: 针对控制器通过云平台驱动的 API 所发现的每个服务器初始化一个 Node 对象; 利用特定云平台的信息为 Node 对象添加注解和标签,例如节点所在的 区域(Region)和所具有的资源(CPU、内存等等); 获取节点的网络地址和主机名;否则是由kubelet获取设置这些信息。 检查节点的健康状况。如果节点无响应,控制器通过云平台 API 查看该节点是否 已从云中禁用、删除或终止。如果节点已从云中删除,则控制器从 Kubernetes 集群 中删除 Node 对象。 某些云驱动实现中,这些任务被划分到一个节点控制器和一个节点生命周期控制器中。 路由控制器 Route 控制器负责适当地配置云平台中的路由,以便 Kubernetes…