惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
T
Threatpost
N
News and Events Feed by Topic
PCI Perspectives
PCI Perspectives
V2EX - 技术
V2EX - 技术
D
Docker
G
Google Developers Blog
Microsoft Security Blog
Microsoft Security Blog
N
News and Events Feed by Topic
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Google Online Security Blog
Google Online Security Blog
The GitHub Blog
The GitHub Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Y
Y Combinator Blog
M
MIT News - Artificial intelligence
Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
T
Troy Hunt's Blog
Webroot Blog
Webroot Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
量子位
Apple Machine Learning Research
Apple Machine Learning Research
H
Help Net Security
F
Full Disclosure
B
Blog
O
OpenAI News
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园_首页
Google DeepMind News
Google DeepMind News
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Engineering at Meta
Engineering at Meta
大猫的无限游戏
大猫的无限游戏
Forbes - Security
Forbes - Security
Know Your Adversary
Know Your Adversary
B
Blog RSS Feed
MongoDB | Blog
MongoDB | Blog
Scott Helme
Scott Helme
T
The Exploit Database - CXSecurity.com
博客园 - 聂微东
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
The Last Watchdog
The Last Watchdog
Recorded Future
Recorded Future
IT之家
IT之家
Project Zero
Project Zero
Stack Overflow Blog
Stack Overflow Blog
小众软件
小众软件
Attack and Defense Labs
Attack and Defense Labs
L
Lohrmann on Cybersecurity
SecWiki News
SecWiki News
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com

陈少文的网站

巨变与机遇的未来十年 Kubernetes 平台管理软件压力测试方案 使用镜像部署 Hexo 静态页面 终于等到你 - GitHub 镜像仓库服务(ghcr.io) 一起来学 Go --(6)Interface 一起来学 Go --(5)Goroutine 和 Channel 什么是函数式编程 如何在 Kubernetes 集群集成 Kata 柯里化与偏函数 使用 PyGithub 自动创建 Label 软件产品是团队能力的输出 Helm 2 、Helm 3 比较 IoT 变现 Kubernetes 中的 DNS 服务 国内的 Helm 镜像源 Harbor 使用自签证书支持 Https 访问 DevOps 工具链之 Prow 如何使用 kfctl 安装 Kubeflow VS Code 无法下载 Go 插件的工具包 工程师更应具有服务精神 你不知道的 Docker 使用技巧 使用 Docker 运行 Tensorflow 论中国 什么是左移 如何清空 Git 仓库全部历史记录 一禅小和尚 有风吹过厨房 时间的玫瑰 如何在 CentOS 安装 GPU 驱动 开发 Tips(19) 使用 Velero 备份 Kubernetes 集群 Kubernetes Cheat Sheet 开发 Tips(18) 如何构建一个 Java 工程 开发 Tips(17) KubeSpray 安装 Kubernetes 报错 ip in ansible_all_ipv4_addresses 基于 Kubernetes 和 Jenkins 搭建自动化测试系统 在 Kubernetes 上动态创建 Jenkins Slave 使用 Jenkins 进行服务拨测 开发 Tips(16) Kubernetes 签发 Ingress 证书及日常故障运维 Kubernetes 中 Deployment 的基本操作 Kubernetes 中的证书 如何使用 KubeBuilder 开发一个 Operator Kubernetes 1.6.0 安装问题汇总 镜像管理工具 -- Harbor 开发 Tips(15) Docker 如何拉取镜像 开发 Tips(14) 使用 Helm 安装 harbor 开发 Tips(13) 使用 S2I 构建云原生应用 在 Kubernetes 中使用 emptyDir、hostPath、localVolume 开发 Tips(12) 开发 Tips(11) 代码质量分析工具 SonarQube 使用 Kubeadm 安装 Kubernetes 集群 一起来学 Go --(4)常用函数 Kubernetes 中的 Ceph Kubernetes 之 Volumes Kubernetes 之 Labels、Selectors 开发 Tips(10) 开源正在重构商业模式 Kubernetes 之网络 Kubernetes 之 API 使用 Helm 和 Operator 快速部署 Prometheus Kubernetes 复杂有状态应用管理框架 -- Operator Kubernetes 的包管理器 -- Helm 一起来学 Go --(3)Go Modules 如何一步一步地优化博客方案 kubectl 实用指南 Kubernetes 中的基本概念 搭建远程 Kubernetes 开发环境 大公司和小公司的 ToB 思路 开发 Tips(9) Go 入门指南 一起来学 Go --(2)数据与逻辑结构 如何预防 Web 富文本中的 XSS 攻击 django-xss-cleaner 云工作时代 一起来学 Go --(1)背景与特点 SaaS 开发团队的不同阶段 你不知道的 Git 使用技巧 输出既服务 微服务设计 继续奔跑 开发 Tips(8) 从账户安全到二次验证 Django 性能之数据库查询优化 Django 性能之分库分表 敏捷开发之研发流程 打造一致性的团队 开发 Tips(7) Pytest 进阶学习之 Mock PaaS 部署之 buildpack Go 开发配置 领域输出才是 PaaS 的核心竞争力 Pytest 入门学习 开发 Tips(6) 如何使用 Jenkins、Docker、GitLab 搭建 Django 自动化部署流程
多集群下的 Tekton 流水线
微信公众号 · 2021-06-26 · via 陈少文的网站

1. 多集群构建 Tekton 的优势

借助于 Kubernetes, Tekton 已经具备很好的弹性, 能够支持大规模构建。同时, 开发 Task 主要使用 Yaml 和 Shell, 这扩大了 Tekton 的各种场景适配范围。

上面是一张 Tekton 在多集群下的示意图。为什么 Tekton 需要多集群执行流水线?

  • 随时可变的 Kubernetes 集群。单一的 Kubernetes 集群, 无法满足运维的要求, 不能随时对集群进行变更。多集群下, 可以下架部分集群进行维护。
  • 更大规模的构建。CI 对 CPU、内存、IO 资源的消耗很大, 容易压垮节点甚至集群。多集群能有效分担负载压力,提高可用性。
  • 业务隔离。业务对代码安全等级、构建速度、构建环境要求不一样, 多集群能够提供隔离的环境, 定制化的流水线服务。

2. Kubernetes Cluster Federation

Kubernetes Cluster Federation 简称 KubeFed。KubeFed v2 相较于 v1 最大的改变是将 API Server 移除, 并且通过 CRD 机制完成 Federated Resource 的扩展。KubeFed Controller 管理这些 CRD, 并实现同步 Resources 跨集群编排等功能,实现模块化和定制化。下面是社区的架构图:

KubeFed 配置了两种类型的信息:

  • Type configuration, 声明 KubeFed 处理的 API 类型
  • Cluster configuration, 声明 KubeFed 管理哪些集群

Type configuration 有三个基本概念:

  • Templates, 定义资源在集群中的模板描述
  • Placement, 定义资源需要分发到哪些集群
  • Overrides, 定义在集群中,需要覆盖 Templates 的字段内容

此外,通过 Status、Policy 和 Scheduling 可以实现更高级的功能:

  • Status 收集分发资源在各个集群中的状态
  • Policy 允许将资源分配给哪些集群的策略控制
  • Scheduling 允许资源跨集群迁移副本

除此,KubeFed 还提供了 MultiClusterDNS,可以用于多集群之间的服务发现。

3. 联邦化 Kubernetes 集群

3.1 准备集群并配置 Context

这里部署两个集群: dev1 作为主集群,用来作为 Tekton 的控制面,不运行流水线任务; dev2 作为子集群,用来执行 Tekton 流水线任务。

  1. 准备两个集群

主集群 dev1

1
2
3
4
kubectl get node

NAME    STATUS   ROLES                         AGE    VERSION
node1   Ready    control-plane,master,worker   151m   v1.20.4
1
2
3
helm version

version.BuildInfo{Version:"v3.2.1", GitCommit:"fe51cd1e31e6a202cba7dead9552a6d418ded79a", GitTreeState:"clean", GoVersion:"go1.13.10"}

子集群 dev2

1
2
3
4
kubectl get node

NAME    STATUS   ROLES                         AGE   VERSION
node1   Ready    control-plane,master,worker   42d   v1.20.4
  1. 在主集群上配置全部集群的 Context(要求集群 Apiserver 入口在一个网络,能够直连),用来添加子集群

这里 contexts 中的 name 不能含义 @ 等特殊字符, 否则 join 时会报错。因为 name 会用来创建 Secret, 需要符合 Kubernetes 的命名规范。

将主集群 dev1 的 kubeconfig 放在 ~/.kube/config-1,并修改 name 等信息,格式如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
apiVersion: v1
clusters:
  - cluster: ...
    name: dev1.cluster.local
contexts:
  - context:
      cluster: dev1.cluster.local
      user: dev1-kubernetes-admin
    name: dev1-context
users:
  - name: dev1-kubernetes-admin
    user: ...

将子集群 dev2 的 kubeconfig 放在 ~/.kube/config-2,并修改 name 等信息,格式如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
apiVersion: v1
clusters:
  - cluster: ...
    name: dev2.cluster.local
contexts:
  - context:
      cluster: dev2.cluster.local
      user: dev2-kubernetes-admin
    name: dev2-context
users:
  - name: dev2-kubernetes-admin
    user: ...
  1. 合并 kubeconfig
1
2
cd $HOME/.kube/
KUBECONFIG=config-1:config-2 kubectl config view --flatten > $HOME/.kube/config
  1. 查看添加的集群 Context
1
2
3
4
5
kubectl config get-contexts

CURRENT   NAME           CLUSTER              AUTHINFO                NAMESPACE
          dev1-context   dev1.cluster.local   dev1-kubernetes-admin
          dev2-context   dev2.cluster.local   dev2-kubernetes-admin
  1. 切换到主集群 dev1
1
2
3
kubectl config use-context dev1-context

Switched to context "dev1-context".

3.2 在主集群上安装 KubeFed

  1. 使用 Helm 安装 KubeFed
1
2
3
git clone https://github.com/kubernetes-sigs/kubefed.git
cd kubefed/charts/
helm install kubefed ./kubefed/ --namespace kube-federation-system --create-namespace
  1. 查看负载
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
kubectl get deploy,pod -n kube-federation-system

NAME                                         READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/kubefed-admission-webhook    1/1     1            1           95s
deployment.apps/kubefed-controller-manager   2/2     2            2           95s

NAME                                              READY   STATUS    RESTARTS   AGE
pod/kubefed-admission-webhook-598bd776c6-gv4qh    1/1     Running   0          95s
pod/kubefed-controller-manager-6d9bf98d74-n8kjz   1/1     Running   0          17s
pod/kubefed-controller-manager-6d9bf98d74-nmb2j   1/1     Running   0          14s

3.3 在主集群上安装 kubefedctl

执行命令:

1
2
3
wget https://github.com/kubernetes-sigs/kubefed/releases/download/v0.8.0/kubefedctl-0.8.0-linux-amd64.tgz
tar -zxvf kubefedctl-*.tgz
mv kubefedctl /usr/local/bin/

3.4 添加集群

在主集群上执行命令, 将 dev1、dev2 都添加到主集群 dev1 上。

1
2
3
4
5
kubefedctl join dev1-context --host-cluster-context dev1-context --kubefed-namespace=kube-federation-system --v=2

I0625 14:32:42.969373   25920 join.go:861] Using secret named: dev1-context-dev1-context-token-2w8km
I0625 14:32:42.972316   25920 join.go:934] Created secret in host cluster named: dev1-context-ln6vx
I0625 14:32:42.991399   25920 join.go:299] Created federated cluster resource
1
2
3
4
5
kubefedctl join dev2-context --host-cluster-context dev1-context --kubefed-namespace=kube-federation-system --v=2

I0625 14:33:11.836472   26424 join.go:861] Using secret named: dev2-context-dev1-context-token-dcl8s
I0625 14:33:11.840121   26424 join.go:934] Created secret in host cluster named: dev2-context-264dz
I0625 14:33:11.898044   26424 join.go:299] Created federated cluster resource

查看集群列表:

1
2
3
4
5
kubectl -n kube-federation-system get kubefedclusters

NAME           AGE   READY
dev1-context   45s   True
dev2-context   16s   True

3.5 测试集群是否联邦成功

  • 查看已经联邦化的资源

安装 KubeFed 之后,常见的很多资源都已经联邦化,可以在 CRD 中查看:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
kubectl get crd |grep federated

federatedclusterroles.types.kubefed.io                2021-06-26T06:22:50Z
federatedconfigmaps.types.kubefed.io                  2021-06-26T06:22:50Z
federateddeployments.types.kubefed.io                 2021-06-26T06:22:50Z
federatedingresses.types.kubefed.io                   2021-06-26T06:22:50Z
federatedjobs.types.kubefed.io                        2021-06-26T06:22:50Z
federatednamespaces.types.kubefed.io                  2021-06-26T06:22:50Z
federatedreplicasets.types.kubefed.io                 2021-06-26T06:22:50Z
federatedsecrets.types.kubefed.io                     2021-06-26T06:22:50Z
federatedserviceaccounts.types.kubefed.io             2021-06-26T06:22:50Z
federatedservices.types.kubefed.io                    2021-06-26T06:22:50Z
federatedservicestatuses.core.kubefed.io              2021-06-26T06:22:50Z
federatedtypeconfigs.core.kubefed.io                  2021-06-26T06:22:50Z

federatedtypeconfigs 中也可以看到已经开启联邦的资源。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
kubectl get federatedtypeconfigs.core.kubefed.io -n kube-federation-system

NAME                                     AGE
clusterroles.rbac.authorization.k8s.io   29m
configmaps                               29m
deployments.apps                         29m
ingresses.extensions                     29m
jobs.batch                               29m
namespaces                               29m
replicasets.apps                         29m
secrets                                  29m
serviceaccounts                          29m
services                                 29m
  • 创建一个联邦的 Namespace

Namespace 级别的资源需要放置在联邦化的 Namespace 下,否则在进行资源分发时,Controller 会报错。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
apiVersion: v1
kind: Namespace
metadata:
  name: testing-fed
---
apiVersion: types.kubefed.io/v1beta1
kind: FederatedNamespace
metadata:
  name: testing-fed
  namespace: testing-fed
spec:
  placement:
    clusters:
      - name: dev1-context
      - name: dev2-context
  • 在主集群创建一个联邦的 Deployment

常见的 Deployment 是这样:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - image: nginx
          name: nginx

而联邦的 Deployment 是这样。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
apiVersion: types.kubefed.io/v1beta1
kind: FederatedDeployment
metadata:
  name: nginx-fed
  namespace: testing-fed
spec:
  overrides:
    - clusterName: dev1-context
      clusterOverrides:
        - path: /spec/replicas
          value: 2
    - clusterName: dev2-context
      clusterOverrides:
        - path: /spec/replicas
          value: 3
  placement:
    clusters:
      - name: dev1-context
      - name: dev2-context
  template:
    metadata:
      labels:
        app: nginx
      namespace: testing-fed
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
            - image: nginx
              name: nginx

FederatedDeployment 编写时,需要注意三个字段

- overrides, 根据不同集群, 需要覆盖的字段属性。这里将 dev1 上的副本数改为 2,而将 dev2 上的副本数改为 3。
- placement, 资源需要放置的集群列表。这里放置在 dev1、dev2 两个集群。
- template, 资源的模板。这里是 Deployment 去掉 apiVersion 和 kind 的剩余部分。
  • 验证资源是否分发成功

在 dev1 集群上

1
2
3
4
5
kubectl -n testing-fed get pod

NAME                         READY   STATUS    RESTARTS   AGE
nginx-fed-6799fc88d8-7llk9   1/1     Running   0          8m2s
nginx-fed-6799fc88d8-clc5w   1/1     Running   0          8m2s

在 dev2 集群上

1
2
3
4
5
6
kubectl -n testing-fed get pod

NAME                         READY   STATUS    RESTARTS   AGE
nginx-fed-6799fc88d8-2ld4k   1/1     Running   0          7m49s
nginx-fed-6799fc88d8-6dncp   1/1     Running   0          7m49s
nginx-fed-6799fc88d8-x64fb   1/1     Running   0          7m49s

4. 联邦化 Tekton 的 CRD 资源

4.1 安装 Tekton

在所有集群上都需要安装 Tekton

1
kubectl apply -f https://raw.githubusercontent.com/shaowenchen/image-syncer/main/tekton/v0.24.1-release-0.24.1.yaml

由于 Tekton 社区使用的是 gcr.io 的镜像, 有些主机环境上可能无法拉取。我在 Dockerhub 上对其进行了备份, 在这里可以找到相关的 yaml, https://github.com/shaowenchen/image-syncer/tree/main/tekton

4.2 联邦化 Tekton 的 CRD

安装 KubeFed 时, 会默认将常见的 Deployment、Secret 等联邦化, 但如果是用户自定义的 CRD 就需要手动开启。

执行命令:

1
2
3
4
5
6
7
8
kubefedctl enable clustertasks.tekton.dev
kubefedctl enable conditions.tekton.dev
kubefedctl enable pipelineresources.tekton.dev
kubefedctl enable pipelineruns.tekton.dev
kubefedctl enable pipelines.tekton.dev
kubefedctl enable runs.tekton.dev
kubefedctl enable taskruns.tekton.dev
kubefedctl enable tasks.tekton.dev

以 taskruns 为例, kubefedctl enable taskruns.tekton.dev 会自动创建两个资源:

  • customresourcedefinition.apiextensions.k8s.io/federatedtaskruns.types.kubefed.io, 联邦 CRD 资源 federatedtaskruns
  • federatedtypeconfig.core.kubefed.io/taskruns.tekton.dev, 在 kube-federation-system 命名空间下, 创建 federatedtypeconfig 类型的资源 taskruns 开启资源分发使能

4.3 编辑新创建的联邦 CRD 资源添加字段

缺少这一步, 会导致同步到子集群的 CR 资源内容为空。因为 kubefedctl enable 联邦化 CRD 资源缺少 template 字段。

执行命令:

1
kubectl edit crd federatedtasks.types.kubefed.io

在与 overridesplacement 平级的层次,添加下面示例的 template 内容即可。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
apiVersion: apiextensions.k8s.io/v1
...
spec:
  versions:
  - name: v1beta1
    schema:
      openAPIV3Schema:
        properties:
          spec:
            properties:
              overrides:
                ...
              placement:
                ...
              template:
                type: object
                x-kubernetes-preserve-unknown-fields: true
            type: object

如果觉得不够清晰,可以参考 https://github.com/shaowenchen/demo/tree/master/tekton-0.24.1-kubefed 修改。如果你也是使用版本 0.24.1, 可以直接 kubectl apply 这些 CRD 资源。

4.4 测试多集群下分发 Tekton 对象

这里为了避免粘贴大量 yaml, 直接提前预先在子集群上创建 Task 资源, 而没有使用 FederatedTask 进行分发。

  • 在子集群上创建 Task
1
kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/main/task/git-clone/0.4/git-clone.yaml -n testing-fed
  • 在主集群 dev1 上创建 FederatedTaskRun 资源分发到子集群 dev2
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: types.kubefed.io/v1beta1
kind: FederatedTaskRun
metadata:
  name: git-clone-test
  namespace: testing-fed
spec:
  placement:
    clusters:
      - name: dev2-context
  template:
    metadata:
      namespace: testing-fed
    spec:
      workspaces:
        - name: output
          emptyDir: {}
      taskRef:
        name: git-clone
      params:
        - name: url
          value: https://github.com/kelseyhightower/nocode
  • 在子集群 dev2 上查看 Tekton 的 Taskrun 任务
1
2
3
4
kubectl get taskrun -n testing-fed

NAME             SUCCEEDED   REASON      STARTTIME   COMPLETIONTIME
git-clone-test   True        Succeeded   15s         7s

5. 总结

本文主要介绍并实践了利用 KubeFed 管理多集群,对 Tekton CRD 资源进行联邦化。

多集群下的 Tekton,使用主集群管理资源,使用子集群执行流水线,能够有效均衡负载,增加流水线的并发执行量,提高 CICD 系统的可维护性。

这里的 KubeFed 主要是用来存储并分发 Tekton 对象资源。如果自研编码,可以通过数据存储加循环控制器完成,但是利用 KubeFed Controller 能快速实现,同时避免了很多潜在的问题。KubeFed 用于做跨集群的资源分发,非常适用。

6. 参考