Blogs

KubeVirt通过Kube-OVN使用Underlay网络

之前文章介绍了如何通过Kube-OVN实现Kubernetes网络租户隔离,今天我们一起看一下KubeVirt通过Kube-OVN使用Underlay网络,使虚拟机接入物理网络。 实践操作 检查Kubernetes使用的Pod网络地址段和Service网络地址段。 sukai@ubuntuserver:/etc/kubernetes/manifests$ sudo grep cidr kube-controller-manager.yaml - --allocate-node-cidrs=true - --cluster-cidr=10.244.0.0/16 sukai@ubuntuserver:/etc/kubernetes/manifests$ sudo grep range kube-controller-manager.yaml - --service-cluster-ip-range=10.211.0.0/16 检查kube-ovn-controller配置项是否正确 kube-ovn在版本v1.11.0开始支持keep-vm-ip参数,虚拟机使用固定IP地址。 Containers: kube-ovn-controller: Container ID: containerd://0f8d53403c9821c7b535c64d2c98e1ca130a15e1b2b878270cd9388c36d0e48a Image: kubeovn/kube-ovn:v1.11.0 Image ID: docker.io/kubeovn/kube-ovn@sha256:fea623e68a2a81ef78102c6cfe95b96c16c054c57f4c8b9d168bd3ff620b6779 Port: <none> Host Port: <none> Args: /kube-ovn/start-controller.sh --default-cidr=10.244.0.0/16 --default-gateway=10.244.0.1 --default-gateway-check=true --default-logical-gateway=false --default-exclude-ips= --node-switch-cidr=100.64.0.0/16 --service-cluster-ip-range=10.211.0.0/16 --network-type=geneve --default-interface-name= --default-vlan-id=100 --pod-nic-type=veth-pair --enable-lb=true --enable-np=true --enable-eip-snat=true --enable-external-vpc=true --keep-vm-ip=true 创建服务网络 指定物理服务器上访问物理网络的网卡。 apiVersion: kubeovn.io/v1 kind: ProviderNetwork metadata: name: office spec: defaultInterface: eno1 创建VLAN 创建在指定服务网络上创建一个VLAN,这里VLAN ID为0表示不属于任何VLAN。 apiVersion: kubeovn.

继续阅读

kube-ovn实现Kubernetes多租户网络管理

Kubernetes容器平台正在成为越来越多的数据中心基础平台,我们希望Kubernetes能够满足虚拟化平台的一些基本要求,比如实现了多租户的灵活的软件定义网络SDN。工作中一个项目在使用Kubernetes平台,所以考虑通过KubeVirt来管理虚拟机,同时使用kube-ovn来实现多租户网络隔离。下面我们一起来看看如何使用kube-ovn来管理网络。 基本概念 Underlay/Overlay网络 Underlay网络是指传统IT基础设施网络,是由交换机、路由器、负载均衡等设备组成的底层物理网络。Overlay网络是通过网络虚拟化技术,在Underlay网络上构建出的虚拟的逻辑网络。 OVS/OVN Open vSwitch(OVS)是一个多层软件交换机,OVS只里一个单机软件,没有集群的信息。Open Virtual Nework(OVN)提供了一个集中式的OVS控制器,从集群的角度对整个网络设施进行编排。 使用Kubernetes后会发现,Kubernetes网络功能缺少软件定义网络SDN能力,缺少VPC, Subnet, Nat, Route, SecurityGroup等常用功能。Kube-OVN基于OVN为Kubernetes网络提供了网络编排能力。 CNI 容器网络接口(Container Network Interface),由CoreOS提出的一种容器网络规范,主要内容是容器创建时的网络分配,和容器被删除时释放网络资源。CNI让网络层变得可插拔,只要遵循CNI的协议规范,容器管理平台就可以调用CNI插件可执行文件提供网络功能。Kubernetes网络模型采用了CNI容器网络接口规范。 macvlan macvlan是一种Linux内核的网络虚拟化技术,从一个主机接口虚拟出多个虚拟网络接口。macvlan可以在物理网卡构成的父接口上添加子接口,每个子接口都拥有独立的MAC地址和IP地址。容器可以通过绑定子接口,拥有与物理网络通信的能力。这解决了容器接入物理网络需求,比如我们需要通过docker运行gitlab服务,gitlab服务需要用到80,443,22端口,这些常用端口经常会产生冲突,那么我们可以通过docker命令创建一个macvlan驱动类型的网络来拥有独立MAC和IP地址。Kubernetes内置CNI插件包含了macvlan,配置使用macvlan CNI,可以让Kubernetes的Pod使用Underlay网络 。 Kube-OVN Kube-OVN插件将Kubernetes容器网络接入ovs网络。提供了vpc, router, switch, subnet管理能力。 Multus Multus CNI插件提供了Kubernetes Pod添加多块网卡的能力。容器同时接入多个不同的网络,解决了类似Ceph这种区分多个网络应用场景。 IPAM IP地址管理(IP Address Management),分配和维护IP地址,DNS,网关,路由等信息。CNI插件在执行过程中调用相应的IPAM插件,IPAM插件将IP相关信息返回到主CNI插件。IPAM插件减少了CNI插件重复编写相同代码管理IP的工作,而且解决了多个CNI插件统一集中IP管理的需求。 场景需求 1,通过VPC实现网络租户隔离 2,通过NAT网关SNAT访问外网 3,通过NAT网关DNAT暴露端口给外网访问 安装部署 安装Kube-OVN curl -O https://raw.githubusercontent.com/kubeovn/kube-ovn/release-1.10/yamls/crd.yaml curl -O https://raw.githubusercontent.com/kubeovn/kube-ovn/release-1.10/yamls/ovn.yaml curl -O https://raw.githubusercontent.com/kubeovn/kube-ovn/release-1.10/yamls/kube-ovn.yaml curl -O https://raw.githubusercontent.com/kubeovn/kube-ovn/master/charts/templates/kubeovn-crd.yaml sed -i 's/\$addresses/<Node IP>/g' ovn.yaml kubectl label node ubuntuserver1 kube-ovn/role=master kubectl apply -f crd.yaml kubectl apply -f kubeovn-crd.

继续阅读

Kubernetes资源类型发现

在基于Kubernetes平台开发过程中,经常需要访问不同Kuberntes版本的集群资源,这时就需要去获取所访问集群支持的资源版本信息。下面我们一起来看一下,如何来实现Kubernetes资源类型发现? 文章分为下面几部分为大家介绍: 1,kubectl命令查看Kubernetes集群资源 2,client-go库获取Kubernetes集群资源 3,controller-runtime动态获取Kubernetes集群资源 kubectl命令 kubectl命令行工具提供api-resources,api-versions命令来查看kubernetes集群当前支持的资源类型。 kubectl api-resources查看k8s所有资源和版本列表。 sukai@sukai:~$ kubectl api-resources NAME SHORTNAMES APIVERSION NAMESPACED KIND bindings v1 true Binding componentstatuses cs v1 false ComponentStatus configmaps cm v1 true ConfigMap endpoints ep v1 true Endpoints events ev v1 true Event limitranges limits v1 true LimitRange namespaces ns v1 false Namespace nodes no v1 false Node persistentvolumeclaims pvc v1 true PersistentVolumeClaim persistentvolumes pv v1 false PersistentVolume pods po v1 true Pod .

继续阅读

通过Karmada实现应用多Kubernetes集群管理--调度器

前面文章介绍了Karmada的控制器流程,了解了Karmada如何实现Kubernetes资源下发到成员集群的。今天我们一起看一下Karmada的调度器,看看Karmada如何实现Kubernetes资源下发调度的。 前面控制器流程里讲过,用户创建了Kubernetes资源对象模板,下发策略和差异策略后,由resourceDetector根据下发策略,创建ResourceBinding绑定资源与策略,再由BindingController根据ResourceBinding,查找并应用OverridePolicy,最终生成创建成员集群资源的Work,由ExecutionController在成员集群中执行Work完成Kubernetes资源操作。 在流程上,Karmada调度器工作在ResourceBinding创建生成后,BindingController控制器工作之前。在功能上,Karmada调度器主要负责Kubernetes资源对象在成员集群的分布,Karmada调度器通过算法得出在哪些成员集群上运行多少个副本数量的结果,将调度结果保存到ResourceBinding的Clusters参数中。 业务流程 1,监听事件加入队列:Informer监听资源绑定ResourceBinding, 下发策略PropagationPolicy事件,将对应的ResourceBinding资源加入工作队列。 2,取出队列中ResourceBinding对象:每秒中开启一个worker,从队列中取出ResourceBinding对象进行处理。循环处理工作队列,直到队列处理结束。 3,获取分布规则:根据ResourceBinding的Annotation中下发策略PropagationPolicy名称,获取下发策略的分布规则。分布规则包括:集群亲和,集群容忍,拓扑分布约束规则以及副本调度策略等信息。 4,判断是否进行ResourceBinding调度:比对新旧分布规则,判断是否需要进行ResourceBinding调度。 5,调度ResourceBinding,计算出成员集群分配副本数量: a,FilterPlugin过滤插件判断集群亲和和容忍是否匹配条件,得到匹配集群。 b,ScorePlugin计算匹配集群的得分,得到集群的优先级。 c,根据SpreadConstraint拓扑分布约束规则,得到最后的下发成员集群。 d,发配副本,副本调度策略类型分两种:Duplicated复制, Divided切分。如果是复制类型,每个成员集群部署与模板相同的资源副本数量。如果是切分类型,可以配置PreferenceWeighted权重优先和PreferenceAggregated聚合优先,前者会根据权重比例来进行切分,后者根据总的副本数量来判断是scaleUP还是scaleDown,再根据成员集群的最大可用副本数来分配副本数量。 6,更新ResourceBinding中的Clusters字段,设置为计算出的成员集群分配副本数量结果。 7,完成了一个ResourceBinding的处理,继续处理下一条。 代码实现 过滤和计分插件 构造调度算法实例,算法插件包括:集群亲和,污点容忍,已安装支持的资源API,已下发集群。 algorithm := core.NewGenericScheduler(schedulerCache, []string{clusteraffinity.Name, tainttoleration.Name, apiinstalled.Name, clusterlocality.Name}) 集群亲和:过滤插件,1,集群名称是否在亲和策略的排除集群列表中。2,集群的标签、字段过滤是否与亲和策略中的标签和字段过滤匹配。返回是否成功结果。 // Filter checks if the cluster matched the placement cluster affinity constraint. func (p *ClusterAffinity) Filter(ctx context.Context, placement *policyv1alpha1.Placement, resource *workv1alpha2.ObjectReference, cluster *clusterv1alpha1.Cluster) *framework.Result { affinity := placement.ClusterAffinity if affinity != nil { if util.ClusterMatches(cluster, *affinity) { return framework.NewResult(framework.Success) } return framework.NewResult(framework.Unschedulable, "cluster is not matched the placement cluster affinity constraint") } // If no clusters specified and it is not excluded, mark it matched return framework.

继续阅读

通过Karmada实现应用多Kubernetes集群管理--控制器

Karmada是华为云开源的,提供应用的跨云多集群统一管理和部署。今天一起来看一下Karmada的控制器,怎么来完成集群纳管和Kubernetes应用工作负载在成员集群创建的。 基本概念 Cluster 在Karmada集群管理中,将Kubernetes集群分为两种:控制面集群,成员集群。控制面集群是Karmada管理组件所在的集群。成员集群为纳管的业务集群。Cluster自定义资源指的是成员集群,指定成员集群的API地址,访问密钥,伪装身份,同步模式。同步模式分为Push和Pull,控制面集群能够主动建立与成员集群的连接,创建资源的为Push模式,控制面集群不能与成员集群主动建立连接的,成员集群建立与控制面集群的连接,监听控制面集群的资源事件,创建资源的为Pull模式。 PropagationPolicy Namespaced下发策略,Kubernetes资源对象下发到成员集群的策略,指定资源对象,成员集群。ClusterPropagationPolicy,非Namespaced下发策略。PropagationPolicy只能下发自己所在命名空间的资源,ClusterPropagationPolicy能够下发集群范围的除了系统保留命名空间外的任意命名空间的资源。 OverridePolicy Namespaced差异策略,Kubernetes资源对象下发到某些集群时,使用指定的参数值。ClusterOverridePolicy,非Namespaced差异策略。 ResourceBinding 根据下发策略生成ResourceBinding,指定具体版本的Kubernetes资源对象与下发策略PropagationPolicy绑定。ClusterResourceBinding绑定Kubernetes资源与ClusterPropagationPolicy。 Work 下发到成员集群的资源列表,可以为Deployment, Configmap, Service, Role, CRD等Kubernetes资源。控制面集群通过Work来实现对成员集群的资源控制。Push模式下,控制面集群监听Work资源事件,执行对成员集群的资源对象操作。Pull模式下,成员集群Agent监听Work资源事件,并在成员集群里执行资源对象的操作。 Karmada用户操作 1,添加成员集群,创建Cluster自定义资源的实例对象 2,创建Kubernetes的资源,这里就是Kubernetes原生的Deployment, Statefulset, Daemonset, Job, Configmap, Secret, Service等。 3,创建下发策略PropagationPolicy,指定资源对象部署到哪些集群中。 4,创建差异策略OverridePolicy,指定资源对象在哪些集群中覆盖哪些参数值。 Karmada用户操作完成后,由Karmada控制器进行资源调谐,最终完成在指定的成员集群中创建Kubernetes资源对象。 Karmada控制器 ClusterController 负责调谐Cluster自定义资源,创建集群对应的execution命名空间。Cluster为纳入管理的业务成员集群。 ClusterStatusController 负责调谐Cluster子资源Status,检测并更新成员集群的健康状态、资源使用信息、集群版本信息、集群主机资源信息以及支持的APIResource。 HpaController Pod水平自动扩展控制器,负责调谐HorizontalPodAutoscaler自定义资源。在成员集群创建对应的HorizontalPodAutoscaler。 BindingController 包括两个控制器,ResourceBindingController监听Work, OveridePolicy, ClusterOverridePolicy资源的事件,调谐ResourceBinding负责创建对应的Work,指定要创建的Kubernetes工作负载Workload。ClusterResourceBindingController主要调谐ClusterResourceBinding。 ExecutionController 负责调谐Work自定义资源,在指定集群创建用户定义的Kubernetes工作负载Workload。 WorkStatusController 负责调谐Work的子资源Status,将引用的资源信息保存到Status中。 NamespaceController 监听Cluster自定义资源事件,创建Work,指定创建namespace。 ServiceExportController 监听Work事件,启动对应集群的Informer,监听serviceexports,endpointslices事件,将事件处理后放入worker队列。 EndpointSliceController 监听Work事件,根据Work定义,创建对应的EndpointSlice。 ServiceImportController 调谐ServiceImport资源,创建Kubernetes Service资源对象。 UnifiedAuthController 监听Cluster, ClusterRole, ClusterRoleBinding资源事件,生成Work指定创建ClusterRole, ClusterRoleBinding资源对象。 FederatedResourceQuotaSyncController 调谐FederatedResourceQuota,监听Cluster事件,创建Work指定创建ResourceQuota资源。 FederatedResourceQuotaStatusController 调谐FederatedResourceQuota子资源Status,更新Status信息。 Karmada控制器执行流程 1,创建一个成员集群Cluster资源实例 2,ClusterController创建成员集群对应的执行命名空间executionNamespace。 3,UnifiedAuthController生成创建成员集群ClusterRole, ClusterRoleBinding的Work。 4,ExecutionController根据Work中的集群和资源对象,在成员集群中执行对应操作,比如创建ClusterRole, ClusterRoleBinding等。 5,ClusterStatusController更新成员集群的健康状态,集群及主机信息。 6,成员集群加入成功后,用户创建Kubernetes资源对象模板,下发策略PropagationPolicy,差异配置策略OverridePolicy。

继续阅读

Clusterpedia安装与使用

今天我们一起来安装一下Clusterpedia,看看Clusterpedia的功能。 安装 Clusterpedia代码目录deploy下提供了kubectl安装Clusterpedia的YAML文件。部署数据库,安装CRD自定义资源,安装apiserver和clustersynchro,注册apiservice。 cd ./deploy/internalstorage/postgres export STORAGE_NODE_NAME=sukai sed "s|__NODE_NAME__|$STORAGE_NODE_NAME|g" `grep __NODE_NAME__ -rl ./templates` > clusterpedia_internalstorage_pv.yaml kubectl create -f . cd ../../.. kubectl apply -f ./deploy/crds kubectl apply -f ./deploy 两个组件的deployment里可以修改镜像地址为: m.daocloud.io/ghcr.io/clusterpedia-io/clusterpedia/clustersynchro-manager:v0.1.0 m.daocloud.io/ghcr.io/clusterpedia-io/clusterpedia/apiserver:v0.1.0 导入集群 创建Clusterpedia的CRD PediaCluster资源实例,syncResources指定Clusterpedia需要同步的资源。 apiVersion: cluster.clusterpedia.io/v1alpha2 kind: PediaCluster metadata: name: cluster-sukai spec: apiserver: "https://192.168.0.111:6443" caData: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeU1ESXdOakE1TXpjek1Wb1hEVE15TURJd05EQTVNemN6TVZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBSnUzCjlvS0MwUjVQYkgyUTZCa2ZCSzIwYzRVNkJpQmJpdW14akI5VVBZaExja2VhTkIwVHFLY2xXTjNzV2Y4QVBGM0sKYlFyb1F5UzdhNEVGWVU3WFJRcWFWTHdlSGhWZWZnMU1nZ3gzMXpsNS8wR3NqdFRlc1hyTmR4RXBvTnBvVWtrWAp1Uy8wWXZoNjZSUklPMks5WmNLKytvK1YycDl3UFZLTHYvUm45WDZpRVRlVjJSeCt0RDFXbEpDRSs0UGhublJNCm1jYUJyWkxkazVONGtCb1JDMTV0alhWRkpNSVJIejNaUVhwS1RydzVEZ3pvS0MyUUpCcnl1L2kxS0pSWGNIUm8KcXd6dzExWkRMemFXU3VnQ1hMT3pCeXVvblhoOGVpWW5jbldJa0NKZzlUblczamRXU3hZTHBtZUJFaXd5TDNNegpEWUIxWTVpaVVZV0pvbERCQjNNQ0F3RUFBYU5aTUZjd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZJK2NhY0psbW1oUElPZGJaRjV1LzMzaDVNRUtNQlVHQTFVZEVRUU8KTUF5Q0NtdDFZbVZ5Ym1WMFpYTXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBQkdVanNacEZuKy9LR2VpRnpUNApKaEtITno3Yzl5NjF3eEUvNzYvcFd2eGU1RVRyT1FWbjdTQk54SUQ1OXNBKzUrcEtyNnk5TUxrUUxDZmhhZFdKCmd4WklEVmlHTmV4ejFsSlNKZ2h0L0lTOUtKbnl5YmQ1QUV4cTZ2ZkxrT1VKZkxaYnJMWUNGYUVIWXg1Q055TXEKUGdtdG1Tb1NlOVVKMGpEZlFvanJGakVIbWJpT0hHV0o3R2dHaStKUzhSbFZwc3pyK215c05FcitiMCtiR2hWWApNR3NDNTVCQndOTVZhSHFXZWZmRjB0ZGlSaVY4SW1xa0loSVdNSXA0RFdvbjBJc2xFYTZ0RWNrTGhaM0dsR2lrCmRvcCtGTmJZRmVZWXpPU05yRkpCZitKSnd4U1lSWGlTTXVCc29nd2NYcFZ1S0lza2hoVjU0dUEwUTcxSUNLN3IKN3VnPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== tokenData: certData: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURJVENDQWdtZ0F3SUJBZ0lJV2YrWkJSK1I0SFF3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TWpBeU1EWXdPVE0zTXpGYUZ3MHlNekF5TURZd09UTTNNelJhTURReApGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXVhOHAvUnBITmUzemhGOWkKZEFZUFlBalJIaTlBYTlGc1FhdzY4NzJoOUhBVVpneUNnU3JxUmIwc1hBOUZ4aSsybHJsSWIzUE9sRGd3bnJwZApacmI1VnQyZHRuVGhXZitJYVV4bGNraGs1VWdNQnUwa1VFVGpUTFZtY1RvczVZWGJWejk5aUEwQ3h4LzViYzcwCnJKRWRyWkJQYngrdFN1Mk5kN1paeTE5SExWYVh6a256R3NRZ1o0Z1piT09oeFVNd201OFd4a2hDeDdyczhLQnIKdmNOWXFVMC9UNXVydFJPcEJabCtYMTFnNGcyeXkwSTdBc2R1cnVCMmhiOG1RUW1MRzg5VmdqZHQzOEdrUTJhMApZMGNLay9aeVQzUVUxeGZkUTlvb2FYbWN1SnBkUmJpeTU5a1VBNzVSc3V2L1V3UXZucDgrUzNLR2dFVkJBTkpqCjFCNTljd0lEQVFBQm8xWXdWREFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RBWURWUjBUQVFIL0JBSXdBREFmQmdOVkhTTUVHREFXZ0JTUG5HbkNaWnBvVHlEblcyUmVidjk5NGVUQgpDakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBUk8xVldObW40N1A4ajl3THkrZUdiMVB6WjBnUTg1WlQvOVU1Ck5yVHZ1YXFCVW80bUxvNzBISHRtVDAreVlMSmhWV0kxSW9IT3dqc3gwcUhJWXc3U0lIWS90K3VqOHh4TDJnakgKSVdWT0NwSW5xeDF1TTQwQ0xORGtmbUM1b2JYbEtUbCt0d0hETDBuQzV3am8wdE5TV0x0SERqWjVoRVF2VWlieQoxdmpHZnhDS3YxNXdqVFlvTjZ3OS9nS1ZHQm5scjJjNm1kTmUwSktmUEdHeHRKMmN3R0daQXRYQ1EvcUNRZmpoCnVVM3ZSSTlXSFp5THhJWWF2RjdpRlVlaGdqYVBKc3lwQ0xHejRPVjA3dlFEbHdBQlp3Mjk1WGI3c1FVK1FOMVoKMEwzWHIyVzIydE52ZHBiNlRNSjRMaFN2Z2RLOHFWUDREK0RscWY2ajFUUHFwOFVucGc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== keyData: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBdWE4cC9ScEhOZTN6aEY5aWRBWVBZQWpSSGk5QWE5RnNRYXc2ODcyaDlIQVVaZ3lDCmdTcnFSYjBzWEE5RnhpKzJscmxJYjNQT2xEZ3ducnBkWnJiNVZ0MmR0blRoV2YrSWFVeGxja2hrNVVnTUJ1MGsKVUVUalRMVm1jVG9zNVlYYlZ6OTlpQTBDeHgvNWJjNzBySkVkclpCUGJ4K3RTdTJOZDdaWnkxOUhMVmFYemtuegpHc1FnWjRnWmJPT2h4VU13bTU4V3hraEN4N3JzOEtCcnZjTllxVTAvVDV1cnRST3BCWmwrWDExZzRnMnl5MEk3CkFzZHVydUIyaGI4bVFRbUxHODlWZ2pkdDM4R2tRMmEwWTBjS2svWnlUM1FVMXhmZFE5b29hWG1jdUpwZFJiaXkKNTlrVUE3NVJzdXYvVXdRdm5wOCtTM0tHZ0VWQkFOSmoxQjU5Y3dJREFRQUJBb0lCQUVCcUdxZmFDT0FWaHdmaAp5eGF5ejN5aU1tRkZSUlRpRnFzRm80SFF4REUyL0d5V1pHT0l6cktZdUozTEVvcDVITjlXc1dFd2pIWndzN1VzCnM2QWhVNGdsNDBOYmNwMjAvczZBbVNTM0pvRS9xQ1J5K2NqNnpOdGNob2c3QlQ0dVhIUDg2NEJaK3grMjRPR08KRE9VY2htNGloTnZvNGtYKytMZVJ3NzdBYzhHdkUwYWU0akt6ZHZRb0hXNmNkcGxBWGdqRG1EVGVGOVZ6Q2o1SgplaC90OWQvN0V4by83SXJHdWROWnpwcTRZaktrTUdhdVdwcEt0N0FmUXpVU2pTOEh1R0ROL2VpUDhzRXlLdlZmCmwvVmdMb3FzUlRUUzZZNjFkU1FVaHlWSE80Z1VKamV2VVFyMzJFaDF3R2VxMXVDUE9iUjdzd2pnWjhET2kwcDgKam81eFR2a0NnWUVBOUM4Mm1zeDJjdUhLUjZoS2VYbTdhSFJKR0d4MXY1czVMY2lYN0ljMTltM1NROUZHODFBcAp3VjFBOUxydVhpVnoyTFRHV1ZDY2V1ZzZCc0FpTVNXSkF5eGx4TUhEbFVBbXZzT0dLT2N2ZXdlOHRPaUFlQkU0Clo5WWlUcUovZDdxdmdrN1RFdElDTHRDVStKcXRWZmUxVVFnK3FvUHY3Q09GRHplZ1ZrSTF5cDBDZ1lFQXdxdEsKZ3JTQktjaGQvUnlIdG9sbnlkbzYvZk9aWHRIbHkvcGdXQm9ZekZDcFRra3V3TnFjL2J6cE96dFhzL3VZNTlPaQprWUZJcFVLM0cvVnRNRno0UkY1R25mbnFMK0I4cndjcGNJRjJLSXFWYStsR2h5cy9mNWNveWFURHRDWnlSRTRpCmdEb2gyZmhUcEl0ZHN5QkNNdVZGMFRnNE15N1c5aUVTVlNhZm8wOENnWUFaYmVWSTM2d2lNS05wTFB4OGhCSGgKUWVMdTJUUzEvSXRLMms0QUF1QzZ4aHNVbHZIRm12Nk9OWkR6SzVoeFU0TXArVUdDd2FOYUpWOE5udXF3cFpFTQpOSTV3bkNFckpPQWtFNmFnRWR0ZSs2SktVTUE0UU1yWC9YUGJMbzhKdi9aUklyWldpbXBSeDhVTDBzZmtZUVNQCjZNVGw2eEdNVFBLcGNBaVJreG1ZL1FLQmdRQ3ZqSUNZOWVZMG83ZitkU2Y5ZUZQY042eFRMc1gwT0J5ZW9aOFkKVkJCZ3o2eWVLR2k5Q1dmaGVlWnB2ODRMUkt4VEF3cnJaRWI2b1BzM2YwK0QrWkw1Tkh0Q0l3a0pPOHUwbXlUSApqRGZkdjN1WDRMbjFVdzdrSkpCbnB1bkZINWFUK2xJcWlFSFdxcFhqSUxyU3VoaDRoVUU4dHhJWE5mb3I0dzhCCk10OXJDUUtCZ0VLNVZrM21sK1Bsbm1wVmpHMU5wOUFtSDY1c2N0eGhYb0ZkU2VVSUZJSTZLU3plRUZnTlllc0YKajRzRnBQeFhkNk5IaS8wYlZTckJBejFveXI2cXlXK3Iwa2hyV3krb1NRakFqV3ZQdlNiWEwwNE5YcDdDci81MAp6L29OTDRXUVI0eGJyWHlUU1FhbFp4R3EvOEV0MjM0amdnbTl3UWRhTkR6anNtaEZPQ2hRCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== syncResources: - group: apps resources: - deployments - group: "" resources: - pods 查看集群状态,APIService,api资源包括:CRD和Aggregator两种方式注册的资源。 sukai@sukai:~$ kubectl get pediacluster NAME APISERVER VERSION STATUS cluster-sukai https://192.

继续阅读

开发Kubernetes自定义APIServer

前面文章介绍了DaoCloud开源的Clusterpedia的业务流程和资源同步机制,Clusterpedia将多个Kubernetes集群的指定资源对象同步保存到MySQL数据库并对外提供查询和检索。今天我们一起看一下Clusterpedia如何开发一个Kubernetes自定义的APIServer,将保存在数据库中的多个Kubernetes业务集群的资源对外提供查询和检索的。 本文内容分以下部分: 1,Kubernetes APIServer基本知识 2,自定义APIServer开发 Kubernetes APIServer基本知识 Kubernetes APIServer是一个实现了RESTful API的WebServer。 API类型 core group,/api/v1为前缀的API接口PATH,core group不需要在apiVersion字段中指定,示例:apiVersion: v1。 named groups,REST path为/apis/$GROUP_NAME/$VERSION,指定apiVersion: $GROUP_NAME/$VERSION,示例apiVersion: batch/v1。 暴露系统状态的API,比如/metrics、/healthz等。 扩展机制 为了增加Kubernetes API的扩展性,Kubernetes提供了两种机制:1,APIExtensions,创建自定义资源CRD,处理CRD/CR的REST请求。2,Aggretgator聚合机制,注册APIService资源,APIServer将对应的API GroupVersion请求代理转发到注册的Service上。 委托调用链 APIServer使用委托模式,通过DelegationTarget接口,把Aggretgator、API Server、APIExtensions链式串联起来,对外提供服务。 当请求Kubernetes对象时,如果在Aggregator中找不到,就去KubeAPIServer中找,最后到APIExtensions中找。 Clusterpedia通过这种委托模式,注册Aggregator服务,优先于所在Kubernetes集群的APIServer提供api和apis两个group的服务,来访问存储在数据库中的多个业务集群的Kubernetes资源对象,kubectl也可以直接执行命令进行下游集群的资源对象查询检索操作。 资源对象操作 在APIServer中,API请求资源对象时,先通过RESTStorage进行REST API处理,在RESTStorage中调用etcd store进行数据存储操作。 Clusterpedia中,与Kubernetes APIServer类似,先通过RESTStorage进行REST API处理,在RESTStorage中调用ResourceStorage进行数据库操作。 自定义APIServer开发 Clusterpedia APIServer基本流程 1,config-complete-new模式构造GenericAPIServer实例kubeResourceAPIServer NewDefaultConfig初始化默认配置。BuildHandlerChain中WithRequestInfo处理API请求信息保存到context中,WithPanicRecovery处理崩溃日志并恢复,RemoveFieldSelectorFromRequest处理URL Query。 complete完善配置,wrapRequestInfoResolverForNamespace封装处理RequestInfo解析器。 New从空委托者构造GenericAPIServer。创建discoveryManager提供自动发现API处理,NonGoRestfulMux.Handle注册/api和/apis的自动发现路由。创建resourceHandler提供资源对象请求API处理,NonGoRestfulMux.HandlePrefix注册/api和/apis为前缀PATH的路由。NewClusterResourceController创建ClusterPedia控制器,监听ClusterPedia CRD事件,处理下游集群的资源,discoveryManager读取controller更新的资源信息提供自动发现API服务。 2,BuildHandlerChain 将WithRequestQuery添加到HandlerChain,WithRequestQuery保存URL Query到context 3,构造GenericAPIServer实例genericServer config.GenericConfig.New从kubeResourceAPIServer委托者构造一个新的GenericAPIServer实例genericServer。所以API资源请求调用链是,先在kubeResourceAPIServer找,再到genericServer中找。 3,InstallAPIGroup注册API对象 genericServer中注册API对象:GroupVersion:clusterpedia.io/v1beta1,Resources资源为resources,collectionresources对象。每个资源对应一个REST storage,用于处理对应资源的请求。 4,AddPostStartHookOrDie添加APIServer启动后调用函数 APIServer启动后,启动Informer,同步Cache。 5,PrepareRun() 准备健康状态检查,存活检查 6,Run() 启动运行APIServer clusterpedia-apiserver命令 在opts.Config()中: 1,根据配置的数据库类型和配置项,创建storage接口,用于操作数据库 2,根据服务器配置,生成SSL自签名证书 3,生成genericapiserver默认配置 通过Config->Complete->New模式构造一个ClusterPediaServer实例server server.Run运行ClusterPediaServer func NewClusterPediaServerCommand(ctx context.Context) *cobra.

继续阅读

开发Kubernetes自已的Informer

我们在Kubernetes自定义资源CRD控制器开发中都使用过Informer,Informer主要提供了两个功能:1,同步数据到本地缓存。2,监听Kubernetes资源的事件,根据对应的事件操作类型,触发事先注册好的ResourceEventHandle。 前面文章介绍了DaoCloud开源的Clusterpedia通过Informer机制实现了同步多个Kubernetes集群资源到MySQL等数据库。那么如何开发一个简化的自定义的Informer呢?下面我们一起看一下DaoCloud开源的Clusterpedia如何实现Kubernetes资源版本Informer的。 文章内容分以下几部分: 1,Kubernetes原生的Informer机制与实现 2,Clusterpedia的ResourceVersionInformer与原生的Informer比较 3,ResourceVersionInformer代码实现 Kubernetes原生的Informer机制 Informer组件 Reflector:反射器,通过Kubernetes的List/Watch API监控指定类型的资源对象。 DeltaFIFO Queue:将Reflector监控到的变化的对象存放在这个FIFO队列中。 LocalStore:Informer的本地缓存,缓存Kubernetes资源对象,可以被Lister的List/Get方法访问,减少对APIServer的访问压力。 WorkQueue:DeltaFIFO中的事件更新完Store后保存到WorkQueue中,Controller处理WorkQueue中的资源对象事件调用对应的回调函数。 SharedInformer实现 这里可以看到: 1,NewSharedIndexInformer中,初始化了processor,这个processor用于回调用户注册的事件处理回调函数,NewIndexer初始化了一个indexer,这个indexer是作为informer的store本地缓存。listerWatcher指定ListerWatcher接口lw,这个是Kubernetes的client连接用于监控Kubernetes资源对象。objectType指定监控的Kubernetes资源类型。 2,SharedInformer的Run中,NewDeltaFIFOWithOptions构造了一个DeltaFIFO实例fifo,构造了一个controller,这个controller使用fifo队列,使用listerWatcher监控资源对象,ObjectType指定资源类型,Process指定controller处理队列的函数。s.processor.run启动监听通知,调用用户注册的回调函数处理。 type SharedInformer interface { AddEventHandler(handler ResourceEventHandler) AddEventHandlerWithResyncPeriod(handler ResourceEventHandler, resyncPeriod time.Duration) GetStore() Store GetController() Controller Run(stopCh <-chan struct{}) HasSynced() bool LastSyncResourceVersion() string SetWatchErrorHandler(handler WatchErrorHandler) error } func NewSharedIndexInformer(lw ListerWatcher, exampleObject runtime.Object, defaultEventHandlerResyncPeriod time.Duration, indexers Indexers) SharedIndexInformer { realClock := &clock.RealClock{} sharedIndexInformer := &sharedIndexInformer{ processor: &sharedProcessor{clock: realClock}, indexer: NewIndexer(DeletionHandlingMetaNamespaceKeyFunc, indexers), listerWatcher: lw, objectType: exampleObject, resyncCheckPeriod: defaultEventHandlerResyncPeriod, defaultEventHandlerResyncPeriod: defaultEventHandlerResyncPeriod, cacheMutationDetector: NewCacheMutationDetector(fmt.

继续阅读

Golang事件队列开发

前面文章介绍了DaoCloud开源的Clusterpedia通过Informer机制监控Kubernetes资源事件,保存事件对象到队列中,等待事件处理函数将Kubernetes资源对象保存到数据库中。今天一起学习一下DaoCloud开源的Clusterpedia如何实现事件队列的。 下面我们文章首先介绍Clusterpedia如何使用EventQueue的,再来介绍EventQueue如何实现的。主要分以下部分: 1,Clusterpedia事件处理函数HandleDeltas,调用informer.handler,这个handler实现了ResourceEventHandler接口,有OnAdd,OnUpdate,OnDelete方法。 2,实现了ResourceEventHandler接口的ResourceSynchro,ResourceSynchro调用EventQueue接口将对象写入队列 3,实现了EventQueue接口的pressurequeue,pressurequeue负责队列的操作。 事件处理函数HandleDeltas Clusterpedia直接基于client-go底层的cache.Controller开发了自己的resourceVersionInformer,cache.Controller的Process函数调用HandleDeltas来处理资源事件。根据cache.Deltas的操作类型,调用informer.storage和informer.handler的对应操作。这里的handler指的是ResourceEventHandler。 func (informer *resourceVersionInformer) HandleDeltas(deltas cache.Deltas) error { for _, d := range deltas { switch d.Type { case cache.Replaced, cache.Added, cache.Updated: version, exists, err := informer.storage.Get(d.Object) if err != nil { return err } if !exists { if err := informer.storage.Add(d.Object); err != nil { return err } informer.handler.OnAdd(d.Object) break } if d.Type == cache.Replaced { if v := compareResourceVersion(d.Object, version); v <= 0 { if v == 0 { informer.

继续阅读

DaoCloud Clusterpedia多Kubernetes集群资源同步与检索

Clusterpedia是DaoCloud开源的支持同步多个集群的指定资源,将资源对象保存到MySQL等数据库,可以通过Clusterpedia检索排序分页资源。 今天我们一起来看一下Clusterpedia的资源同步控制器代码, 了解他的业务流程。 Clusterpedia架构 Clusterpedia在一个Kubernetes集群中,运行Clusterpedia APIServer和ClusterSynchro Manager,提供聚合API,管理和同步多个Kubernetes集群的资源。Clusterpedia所在的集群可理解为管理集群或者控制集群。Clusterpeida将同步的业务集群的资源保存到MySQL/PostgreSQL数据库中,这部分由代码中的StorageFactory实现。 主要业务流程: 1,在管理集群中通过自定义资源PediaCluster CRD来保存、管理和调谐下调业务集群。 2,每一个PediaCluster资源,对应一个ClusterSynchro,也就是一个业务集群会有一个ClusterSynchro实例,用来保存下游业务集群的RestConfig,storage数据库工厂接口,resourceSynchros同步资源GVR对应的ResourceSynchro。 3,每个集群的每个GVR资源对应一个ResourceSynchro,用来保存GVR/GVK信息,事件队列等信息。 4,在PediaCluster资源调谐过程中,主要负责 a,创建对应的ClusterSynchro,将ClusterSynchro中的同步资源对应的Informer启动,将Informer事件调用ResourceSynchro的事件处理函数进行处理。ResourceSynchro实现了ResourceEventHandler接口。 b,ResourceSynchro的事件处理函数,主要实现将对象放入ResourceSynchro队列queue中。 c,开启worker线程池,等待处理队列中的事件,将对象同步到数据库中。 代码 clustersynchro-manager配置项 1,storage.NewStorageFactory生成存储工厂,支持数据库:MySQL, PostgreSQL 2,生成管理集群的Kubeconfig,创建kubernetes以及自定义资源PediaCluster的clientset连接。 func (o *Options) Config() (*config.Config, error) { if err := o.Validate(); err != nil { return nil, err } storagefactory, err := storage.NewStorageFactory(o.Storage.Name, o.Storage.ConfigPath) if err != nil { return nil, err } kubeconfig, err := clientcmd.BuildConfigFromFlags(o.Master, o.Kubeconfig) if err != nil { return nil, err } client, err := clientset.

继续阅读