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

推荐订阅源

博客园 - Franky
酷 壳 – CoolShell
酷 壳 – CoolShell
Google Online Security Blog
Google Online Security Blog
Engineering at Meta
Engineering at Meta
U
Unit 42
Security Latest
Security Latest
G
Google Developers Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
D
Docker
T
Tailwind CSS Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
云风的 BLOG
云风的 BLOG
Hugging Face - Blog
Hugging Face - Blog
M
MIT News - Artificial intelligence
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
MongoDB | Blog
MongoDB | Blog
H
Help Net Security
Stack Overflow Blog
Stack Overflow Blog
C
Check Point Blog
S
Security Affairs
T
The Exploit Database - CXSecurity.com
S
SegmentFault 最新的问题
N
News and Events Feed by Topic
The GitHub Blog
The GitHub Blog
Apple Machine Learning Research
Apple Machine Learning Research
S
Securelist
IT之家
IT之家
P
Palo Alto Networks Blog
D
DataBreaches.Net
Help Net Security
Help Net Security
N
Netflix TechBlog - Medium
B
Blog RSS Feed
AWS News Blog
AWS News Blog
Scott Helme
Scott Helme
爱范儿
爱范儿
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
腾讯CDC
I
Intezer
J
Java Code Geeks
大猫的无限游戏
大猫的无限游戏
Microsoft Security Blog
Microsoft Security Blog
人人都是产品经理
人人都是产品经理
G
GRAHAM CLULEY
N
News | PayPal Newsroom
博客园 - 三生石上(FineUI控件)
A
Arctic Wolf
F
Fortinet All Blogs
The Register - Security
The Register - Security
Recent Commits to openclaw:main
Recent Commits to openclaw:main
博客园 - 【当耐特】

陈少文的网站

巨变与机遇的未来十年 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 中的证书 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 自动化部署流程 开发 Tips(5)
如何使用 KubeBuilder 开发一个 Operator
微信公众号 · 2019-09-25 · via 陈少文的网站

Please enable Javascript to view the contents

通过 Operator 的方案,可以对 Kubernetes 的功能进行友好地扩展。Operatpr = CRD + Controller。首先通过 yaml 定义,生成 CRD ,然后 Controller 不断地监听 etcd 中的数据,执行相应动作。开发 Operator 时,有很多繁琐且重复的事情。KubeBuilder 可以帮助我们快速生成骨架代码,开发一个 Kubernetes 的扩展功能, 更多介绍可以参考文档:Kubernetes 复杂有状态应用管理框架 – Operator 。本篇文档,主要是尝试使用 KubeBuilder 开发一个 Operator 。

1. 环境准备

  • Go 开发环境

  • 远程 Kubernetes 环境

我准备的是,单节点 Kubernetes 1.15.3 。

  • 本地 Kubectl 访问远程集群的权限

将集群 /etc/kubernetes/admin.conf 拷贝到本地 ~/.kube/config 即可。

2. Hello,Kubebuilder

2.1 安装 kubebuilder、kustomize

以 OS X 为例,当前 kubebuilder 版本为 2.x :

1
2
brew install kubebuilder
brew install kustomize

2.2 初始化项目

1
2
3
4
export GOPATH=$(go env GOPATH)
mkdir -p $GOPATH/src/github.com/kube-api
cd $GOPATH/src/github.com/kube-api
kubebuilder init --domain k8s.chenshaowen.com --license apache2 --owner "chenshaowen"

初始化工程之后,KubeBuilder 会生成一系列配置和代码框架。

 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
38
39
tree -L 3
.
├── Dockerfile
├── Makefile
├── PROJECT
├── bin
│   └── manager
├── config
│   ├── certmanager
│   │   ├── certificate.yaml
│   │   ├── kustomization.yaml
│   │   └── kustomizeconfig.yaml
│   ├── default
│   │   ├── kustomization.yaml
│   │   ├── manager_auth_proxy_patch.yaml
│   │   ├── manager_prometheus_metrics_patch.yaml
│   │   ├── manager_webhook_patch.yaml
│   │   └── webhookcainjection_patch.yaml
│   ├── manager
│   │   ├── kustomization.yaml
│   │   └── manager.yaml
│   ├── rbac
│   │   ├── auth_proxy_role.yaml
│   │   ├── auth_proxy_role_binding.yaml
│   │   ├── auth_proxy_service.yaml
│   │   ├── kustomization.yaml
│   │   ├── leader_election_role.yaml
│   │   ├── leader_election_role_binding.yaml
│   │   └── role_binding.yaml
│   └── webhook
│       ├── kustomization.yaml
│       ├── kustomizeconfig.yaml
│       └── service.yaml
├── go.mod
├── go.sum
├── hack
│   └── boilerplate.go.txt
└── main.go
8 directories, 28 files

2.3. 新增 API

1
2
3
4
5
6
kubebuilder create api --group groupa --version v1beta1 --kind ApiExampleA
Create Resource [y/n]
y
Create Controller [y/n]
y
......

KubeBuilder 会将 CRD 和 Controller 添加到工程中。

 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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
tree -L 3
.
├── Dockerfile
├── Makefile
├── PROJECT # 新增 resources 部分
├── api
│   └── v1beta1 # 新增 API 描述
│       ├── apiexamplea_types.go
│       ├── groupversion_info.go
│       └── zz_generated.deepcopy.go
├── bin
│   └── manager
├── config
│   ├── certmanager
│   │   ├── certificate.yaml
│   │   ├── kustomization.yaml
│   │   └── kustomizeconfig.yaml
│   ├── crd # 新增 CRD 定义
│   │   ├── kustomization.yaml
│   │   ├── kustomizeconfig.yaml
│   │   └── patches
│   ├── default
│   │   ├── kustomization.yaml
│   │   ├── manager_auth_proxy_patch.yaml
│   │   ├── manager_prometheus_metrics_patch.yaml
│   │   ├── manager_webhook_patch.yaml
│   │   └── webhookcainjection_patch.yaml
│   ├── manager
│   │   ├── kustomization.yaml
│   │   └── manager.yaml
│   ├── rbac
│   │   ├── auth_proxy_role.yaml
│   │   ├── auth_proxy_role_binding.yaml
│   │   ├── auth_proxy_service.yaml
│   │   ├── kustomization.yaml
│   │   ├── leader_election_role.yaml
│   │   ├── leader_election_role_binding.yaml
│   │   └── role_binding.yaml
│   ├── samples # 新增创建 CRD 对象示例
│   │   └── groupa_v1beta1_apiexamplea.yaml
│   └── webhook
│       ├── kustomization.yaml
│       ├── kustomizeconfig.yaml
│       └── service.yaml
├── controllers # 新增 Controller
│   ├── apiexamplea_controller.go
│   └── suite_test.go
├── go.mod # 新增依赖包
├── go.sum
├── hack
│   └── boilerplate.go.txt
└── main.go # 新增处理逻辑
14 directories, 36 files

2.4 修改配置,适配国内环境

在容器中进行编译时,由于国内网络问题,会导致拉取不到 Go 依赖包和依赖镜像,需要修改 Dockerfile 文件。

  • 增加 GO 代理
  • 修改镜像源
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
@@ -7,7 +7,7 @@ COPY go.mod go.mod
 COPY go.sum go.sum
 # cache deps before building and copying source so that we don't need to re-download as much
 # and so that source changes don't invalidate our downloaded layer
-RUN go mod download
+RUN GOPROXY=https://gocenter.io go mod download

 # Copy the go source
 COPY main.go main.go
@@ -19,7 +19,7 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager

 # Use distroless as minimal base image to package the manager binary
 # Refer to https://github.com/GoogleContainerTools/distroless for more details
-FROM gcr.io/distroless/static:latest
+FROM gcr.azk8s.cn/distroless/static:latest
 WORKDIR /
 COPY --from=builder /workspace/manager .
 ENTRYPOINT ["/manager"]

2.5. 构建并推送镜像测试

  1. 本地构建并推送镜像

由于使用的是远程 Kubernetes 环境,需要借助镜像仓库进行部署。

  • 修改镜像名称
1
2
3
4
5
6
7
@@ -1,6 +1,6 @@

 # Image URL to use all building/pushing image targets
-IMG ?= controller:latest
+IMG ?= docker.io/shaowenchen/controller:latest
 # Produce CRDs that work back to Kubernetes 1.11 (no version conversion)
 CRD_OPTIONS ?= "crd:trivialVersions=true"
  • 登陆 docker.io 的镜像仓库
1
2
3
docker login docker.io -u shaowenchen
Password:
Login Succeeded
  • 构建并推送镜像
1
make docker-build & make docker-push

也可以通过,在执行 make docker-build 等命令时,增加 IMG 变量修改镜像名称。

  1. 部署到 Kubernetes
  • 安装 kustomize
  • 部署 CRD
  • 查看 CRD
1
2
3
kubectl get crd
NAME                                      CREATED AT
apiexampleas.groupa.k8s.chenshaowen.com   2019-09-24T07:24:45Z
  • 部署 Controller
  • 查看 deployment
1
2
3
kubectl get deploy  -n kube-api-system
NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
kube-api-controller-manager   1/1     1            1           46s
  • 创建 CRD 对象
1
kubectl apply -f config/samples/groupa_v1beta1_apiexamplea.yaml
  • 查看 CRD 对象
1
2
3
4
kubectl get apiexampleas.groupa.k8s.chenshaowen.com

NAME                 AGE
apiexamplea-sample   61s
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
kubectl get apiexampleas.groupa.k8s.chenshaowen.com apiexamplea-sample  -o yaml

apiVersion: groupa.k8s.chenshaowen.com/v1beta1
kind: ApiExampleA
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"groupa.k8s.chenshaowen.com/v1beta1","kind":"ApiExampleA","metadata":{"annotations":{},"name":"apiexamplea-sample","namespace":"default"},"spec":{"foo":"bar"}}
  creationTimestamp: "2019-09-24T07:29:16Z"
  generation: 1
  name: apiexamplea-sample
  namespace: default
  resourceVersion: "635450"
  selfLink: /apis/groupa.k8s.chenshaowen.com/v1beta1/namespaces/default/apiexampleas/apiexamplea-sample
  uid: 05398ab4-7d4a-4f2e-af30-b59e61680c7e
spec:
  foo: bar

3. 在 Project 中写入逻辑

通过上面的操作,我们新增了 Kubernetes 对象类型 apiexampleas.groupa.k8s.chenshaowen.comApiExampleA),并实例化对象进行操作。

这些操作仅仅只是对 etcd 数据的操作,没有触发有效动作。下面,尝试往工程中注入一点自定义逻辑。实现一个简单的功能:给自定义的 CRD 增加两个字段,FirstName、SecondName ;创建对象时,在 Controller 中获取这两个字段,并输出到日志中。

  1. 修改代码
  • 增加 CRD 字段

api/v1beta1/apiexamplea_types.go 文件 ApiExampleASpec 结构体中增加两个字段:

1
2
3
4
5
6
type ApiExampleASpec struct {
	// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
	// Important: Run "make" to regenerate code after modifying this file
	FirstName  string `json:"firstname"` // add
	SecondName string `json:"secondname"` // add
}
  • 增加 Controller 逻辑

首先在 import 中新增 log 包:

1
2
3
import (
  "log" // add
  ...

然后在 Reconcile 函数中,处理逻辑

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
func (r *ApiExampleAReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
	// _ = context.Background()
	// _ = r.Log.WithValues("apiexamplea", req.NamespacedName)

	// // your logic here

	// return ctrl.Result{}, nil
	ctx := context.Background()
	_ = r.Log.WithValues("apiexamplea", req.NamespacedName)

	obja := &groupav1beta1.ApiExampleA{}
	if err := r.Get(ctx, req.NamespacedName, obja); err != nil {
		log.Println(err, "unable to fetch New Object")
	} else {
		log.Println("fetch New Object:", obja.Spec.FirstName, obja.Spec.SecondName)
	}

	return ctrl.Result{}, nil
}
  1. 修改镜像 tag

修改镜像 tag 是为了远程 Kubernetes 集群远程部署 Deployment 时,能够重新拉取镜像,使用指定的镜像进行部署。

修改 Makefile 文件中的变量 IMG 为:IMG ?= docker.io/shaowenchen/controller:1

  1. 构建发布
1
make & make docker-build & make docker-push
  1. 部署
  1. 生成一个 CRD 对象实例

config/samples/groupa_v1beta1_apiexamplea.yaml 文件中修改 name 值,并在 spec 字段新增两个字段:

1
2
3
4
5
6
7
8
9
apiVersion: groupa.k8s.chenshaowen.com/v1beta1
kind: ApiExampleA
metadata:
  name: apiexamplea-sample2
spec:
  # Add fields here
  # foo: bar
  firstname: shaowen
  secondname: chen

创建 CRD 对象

1
kubectl create -f config/samples/groupa_v1beta1_apiexamplea.yaml

查看 Controller 的 Pod Name

1
2
3
kubectl get pod -n kube-api-system
NAME                                           READY   STATUS    RESTARTS   AGE
kube-api-controller-manager-7d8bb9fc6f-8bmg9   2/2     Running   0          22m

查看创建日志

1
2
3
4
5
6
7
8
9
kubectl logs kube-api-controller-manager-7d8bb9fc6f-8bmg9 -c manager -n kube-api-system
2019-09-25T07:09:51.124Z	INFO	controller-runtime.metrics	metrics server is starting to listen	{"addr": "127.0.0.1:8080"}
2019-09-25T07:09:51.216Z	INFO	controller-runtime.controller	Starting EventSource	{"controller": "apiexamplea", "source": "kind source: /, Kind="}
2019-09-25T07:09:51.217Z	INFO	setup	starting manager
2019-09-25T07:09:51.217Z	INFO	controller-runtime.manager	starting metrics server	{"path": "/metrics"}
2019-09-25T07:10:08.111Z	INFO	controller-runtime.controller	Starting Controller	{"controller": "apiexamplea"}
2019-09-25T07:10:08.111Z	DEBUG	controller-runtime.manager.events	Normal	{"object": {"kind":"ConfigMap","namespace":"kube-api-system","name":"controller-leader-election-helper","uid":"bf307b9a-829f-478e-9306-68b6c47671fa","apiVersion":"v1","resourceVersion":"871886"}, "reason": "LeaderElection", "message": "kube-api-controller-manager-7d8bb9fc6f-8bmg9_77815cc0-df63-11e9-b8c4-e6f6cfac380f became leader"}
2019-09-25T07:10:08.211Z	INFO	controller-runtime.controller	Starting workers	{"controller": "apiexamplea", "worker count": 1}
2019/09/25 07:10:08 fetch New Object: shaowen chen

4. 参考


微信公众号