Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d82f83e

Browse files
committed
init
0 parents  commit d82f83e

28 files changed

Lines changed: 2359 additions & 0 deletions

.gitignore

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Temporary Build Files
2+
build/_output
3+
build/_test
4+
# Created by https://www.gitignore.io/api/go,vim,emacs,visualstudiocode
5+
### Emacs ###
6+
# -*- mode: gitignore; -*-
7+
*~
8+
\#*\#
9+
/.emacs.desktop
10+
/.emacs.desktop.lock
11+
*.elc
12+
auto-save-list
13+
tramp
14+
.\#*
15+
# Org-mode
16+
.org-id-locations
17+
*_archive
18+
# flymake-mode
19+
*_flymake.*
20+
# eshell files
21+
/eshell/history
22+
/eshell/lastdir
23+
# elpa packages
24+
/elpa/
25+
# reftex files
26+
*.rel
27+
# AUCTeX auto folder
28+
/auto/
29+
# cask packages
30+
.cask/
31+
dist/
32+
# Flycheck
33+
flycheck_*.el
34+
# server auth directory
35+
/server/
36+
# projectiles files
37+
.projectile
38+
projectile-bookmarks.eld
39+
# directory configuration
40+
.dir-locals.el
41+
# saveplace
42+
places
43+
# url cache
44+
url/cache/
45+
# cedet
46+
ede-projects.el
47+
# smex
48+
smex-items
49+
# company-statistics
50+
company-statistics-cache.el
51+
# anaconda-mode
52+
anaconda-mode/
53+
### Go ###
54+
# Binaries for programs and plugins
55+
*.exe
56+
*.exe~
57+
*.dll
58+
*.so
59+
*.dylib
60+
# Test binary, build with 'go test -c'
61+
*.test
62+
# Output of the go coverage tool, specifically when used with LiteIDE
63+
*.out
64+
### Vim ###
65+
# swap
66+
.sw[a-p]
67+
.*.sw[a-p]
68+
# session
69+
Session.vim
70+
# temporary
71+
.netrwhist
72+
# auto-generated tag files
73+
tags
74+
### VisualStudioCode ###
75+
.vscode/*
76+
.history
77+
# End of https://www.gitignore.io/api/go,vim,emacs,visualstudiocode

README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# 命令合集
2+
3+
* operator-sdk
4+
* operator-sdk version 查看版本
5+
* operator-sdk new cmdbdemo 新建项目
6+
* operator-sdk add api --api-version=app.example.com/v1 --kind=CmdbService 定义新的api CRD
7+
* operator-sdk add controller --api-version=app.example.com/v1 --kind=CmdbService 定义CRD的执行逻辑
8+
* operator-sdk generate k8s 自动生成代码
9+
10+
# 部署
11+
12+
* operator-sdk build cnych/opdemo # 应用打包成docker镜像
13+
* docker push cnych/opdemo # 镜像构建成功后,推送到 docker hub
14+
* sed -i 's|REPLACE_IMAGE|cnych/opdemo|g' deploy/operator.yaml # 修改镜像地址更新Operator的资源清单
15+
* kubectl create -f deploy/service_account.yaml # 创建对应的 RBAC 的对象 Setup Service Account
16+
* kubectl create -f deploy/role.yaml # Setup RBAC
17+
* kubectl create -f deploy/role_binding.yaml S# etup RBAC
18+
* kubectl apply -f deploy/crds/app_v1_appservice_crd.yaml # Setup the CRD
19+
* kubectl create -f deploy/operator.yaml # Deploy the Operator
20+
* kubectl create -f deploy/crds/app_v1_appservice_cr.yaml # 业务逻辑部署
21+
22+
# 清理
23+
24+
```sh
25+
$ kubectl delete -f deploy/crds/app_v1_appservice_cr.yaml
26+
$ kubectl delete -f deploy/operator.yaml
27+
$ kubectl delete -f deploy/role.yaml
28+
$ kubectl delete -f deploy/role_binding.yaml
29+
$ kubectl delete -f deploy/service_account.yaml
30+
$ kubectl delete -f deploy/crds/app_v1_appservice_crd.yaml
31+
```

build/Dockerfile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
FROM registry.access.redhat.com/ubi8/ubi-minimal:latest
2+
3+
ENV OPERATOR=/usr/local/bin/cmdbdemo \
4+
USER_UID=1001 \
5+
USER_NAME=cmdbdemo
6+
7+
# install operator binary
8+
COPY build/_output/bin/cmdbdemo ${OPERATOR}
9+
10+
COPY build/bin /usr/local/bin
11+
RUN /usr/local/bin/user_setup
12+
13+
ENTRYPOINT ["/usr/local/bin/entrypoint"]
14+
15+
USER ${USER_UID}

build/bin/entrypoint

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh -e
2+
3+
exec ${OPERATOR} $@

build/bin/user_setup

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/sh
2+
set -x
3+
4+
# ensure $HOME exists and is accessible by group 0 (we don't know what the runtime UID will be)
5+
echo "${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin" >> /etc/passwd
6+
mkdir -p "${HOME}"
7+
chown "${USER_UID}:0" "${HOME}"
8+
chmod ug+rwx "${HOME}"
9+
10+
# no need for this script to remain in the image after running
11+
rm "$0"

cmd/manager/main.go

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"errors"
6+
"flag"
7+
"fmt"
8+
"os"
9+
"runtime"
10+
"strings"
11+
12+
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
13+
_ "k8s.io/client-go/plugin/pkg/client/auth"
14+
"k8s.io/client-go/rest"
15+
16+
"test/operator-study/cmdbdemo/pkg/apis"
17+
"test/operator-study/cmdbdemo/pkg/controller"
18+
"test/operator-study/cmdbdemo/version"
19+
20+
"github.com/operator-framework/operator-sdk/pkg/k8sutil"
21+
kubemetrics "github.com/operator-framework/operator-sdk/pkg/kube-metrics"
22+
"github.com/operator-framework/operator-sdk/pkg/leader"
23+
"github.com/operator-framework/operator-sdk/pkg/log/zap"
24+
"github.com/operator-framework/operator-sdk/pkg/metrics"
25+
sdkVersion "github.com/operator-framework/operator-sdk/version"
26+
"github.com/spf13/pflag"
27+
v1 "k8s.io/api/core/v1"
28+
"k8s.io/apimachinery/pkg/util/intstr"
29+
"sigs.k8s.io/controller-runtime/pkg/cache"
30+
"sigs.k8s.io/controller-runtime/pkg/client/config"
31+
logf "sigs.k8s.io/controller-runtime/pkg/log"
32+
"sigs.k8s.io/controller-runtime/pkg/manager"
33+
"sigs.k8s.io/controller-runtime/pkg/manager/signals"
34+
)
35+
36+
// Change below variables to serve metrics on different host or port.
37+
var (
38+
metricsHost = "0.0.0.0"
39+
metricsPort int32 = 8383
40+
operatorMetricsPort int32 = 8686
41+
)
42+
var log = logf.Log.WithName("cmd")
43+
44+
func printVersion() {
45+
log.Info(fmt.Sprintf("Operator Version: %s", version.Version))
46+
log.Info(fmt.Sprintf("Go Version: %s", runtime.Version()))
47+
log.Info(fmt.Sprintf("Go OS/Arch: %s/%s", runtime.GOOS, runtime.GOARCH))
48+
log.Info(fmt.Sprintf("Version of operator-sdk: %v", sdkVersion.Version))
49+
}
50+
51+
func main() {
52+
// Add the zap logger flag set to the CLI. The flag set must
53+
// be added before calling pflag.Parse().
54+
pflag.CommandLine.AddFlagSet(zap.FlagSet())
55+
56+
// Add flags registered by imported packages (e.g. glog and
57+
// controller-runtime)
58+
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
59+
60+
pflag.Parse()
61+
62+
// Use a zap logr.Logger implementation. If none of the zap
63+
// flags are configured (or if the zap flag set is not being
64+
// used), this defaults to a production zap logger.
65+
//
66+
// The logger instantiated here can be changed to any logger
67+
// implementing the logr.Logger interface. This logger will
68+
// be propagated through the whole operator, generating
69+
// uniform and structured logs.
70+
logf.SetLogger(zap.Logger())
71+
72+
printVersion()
73+
74+
namespace, err := k8sutil.GetWatchNamespace()
75+
if err != nil {
76+
log.Error(err, "Failed to get watch namespace")
77+
os.Exit(1)
78+
}
79+
80+
// Get a config to talk to the apiserver
81+
cfg, err := config.GetConfig()
82+
if err != nil {
83+
log.Error(err, "")
84+
os.Exit(1)
85+
}
86+
87+
ctx := context.TODO()
88+
// Become the leader before proceeding
89+
err = leader.Become(ctx, "cmdbdemo-lock")
90+
if err != nil {
91+
log.Error(err, "")
92+
os.Exit(1)
93+
}
94+
95+
// Set default manager options
96+
options := manager.Options{
97+
Namespace: namespace,
98+
MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
99+
}
100+
101+
// Add support for MultiNamespace set in WATCH_NAMESPACE (e.g ns1,ns2)
102+
// Note that this is not intended to be used for excluding namespaces, this is better done via a Predicate
103+
// Also note that you may face performance issues when using this with a high number of namespaces.
104+
// More Info: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/cache#MultiNamespacedCacheBuilder
105+
if strings.Contains(namespace, ",") {
106+
options.Namespace = ""
107+
options.NewCache = cache.MultiNamespacedCacheBuilder(strings.Split(namespace, ","))
108+
}
109+
110+
// Create a new manager to provide shared dependencies and start components
111+
mgr, err := manager.New(cfg, options)
112+
if err != nil {
113+
log.Error(err, "")
114+
os.Exit(1)
115+
}
116+
117+
log.Info("Registering Components.")
118+
119+
// Setup Scheme for all resources
120+
if err := apis.AddToScheme(mgr.GetScheme()); err != nil {
121+
log.Error(err, "")
122+
os.Exit(1)
123+
}
124+
125+
// Setup all Controllers
126+
if err := controller.AddToManager(mgr); err != nil {
127+
log.Error(err, "")
128+
os.Exit(1)
129+
}
130+
131+
// Add the Metrics Service
132+
addMetrics(ctx, cfg)
133+
134+
log.Info("Starting the Cmd.")
135+
136+
// Start the Cmd
137+
if err := mgr.Start(signals.SetupSignalHandler()); err != nil {
138+
log.Error(err, "Manager exited non-zero")
139+
os.Exit(1)
140+
}
141+
}
142+
143+
// addMetrics will create the Services and Service Monitors to allow the operator export the metrics by using
144+
// the Prometheus operator
145+
func addMetrics(ctx context.Context, cfg *rest.Config) {
146+
// Get the namespace the operator is currently deployed in.
147+
operatorNs, err := k8sutil.GetOperatorNamespace()
148+
if err != nil {
149+
if errors.Is(err, k8sutil.ErrRunLocal) {
150+
log.Info("Skipping CR metrics server creation; not running in a cluster.")
151+
return
152+
}
153+
}
154+
155+
if err := serveCRMetrics(cfg, operatorNs); err != nil {
156+
log.Info("Could not generate and serve custom resource metrics", "error", err.Error())
157+
}
158+
159+
// Add to the below struct any other metrics ports you want to expose.
160+
servicePorts := []v1.ServicePort{
161+
{Port: metricsPort, Name: metrics.OperatorPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: metricsPort}},
162+
{Port: operatorMetricsPort, Name: metrics.CRPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: operatorMetricsPort}},
163+
}
164+
165+
// Create Service object to expose the metrics port(s).
166+
service, err := metrics.CreateMetricsService(ctx, cfg, servicePorts)
167+
if err != nil {
168+
log.Info("Could not create metrics Service", "error", err.Error())
169+
}
170+
171+
// CreateServiceMonitors will automatically create the prometheus-operator ServiceMonitor resources
172+
// necessary to configure Prometheus to scrape metrics from this operator.
173+
services := []*v1.Service{service}
174+
175+
// The ServiceMonitor is created in the same namespace where the operator is deployed
176+
_, err = metrics.CreateServiceMonitors(cfg, operatorNs, services)
177+
if err != nil {
178+
log.Info("Could not create ServiceMonitor object", "error", err.Error())
179+
// If this operator is deployed to a cluster without the prometheus-operator running, it will return
180+
// ErrServiceMonitorNotPresent, which can be used to safely skip ServiceMonitor creation.
181+
if err == metrics.ErrServiceMonitorNotPresent {
182+
log.Info("Install prometheus-operator in your cluster to create ServiceMonitor objects", "error", err.Error())
183+
}
184+
}
185+
}
186+
187+
// serveCRMetrics gets the Operator/CustomResource GVKs and generates metrics based on those types.
188+
// It serves those metrics on "http://metricsHost:operatorMetricsPort".
189+
func serveCRMetrics(cfg *rest.Config, operatorNs string) error {
190+
// The function below returns a list of filtered operator/CR specific GVKs. For more control, override the GVK list below
191+
// with your own custom logic. Note that if you are adding third party API schemas, probably you will need to
192+
// customize this implementation to avoid permissions issues.
193+
filteredGVK, err := k8sutil.GetGVKsFromAddToScheme(apis.AddToScheme)
194+
if err != nil {
195+
return err
196+
}
197+
198+
// The metrics will be generated from the namespaces which are returned here.
199+
// NOTE that passing nil or an empty list of namespaces in GenerateAndServeCRMetrics will result in an error.
200+
ns, err := kubemetrics.GetNamespacesForMetrics(operatorNs)
201+
if err != nil {
202+
return err
203+
}
204+
205+
// Generate and serve custom resource specific metrics.
206+
err = kubemetrics.GenerateAndServeCRMetrics(cfg, ns, filteredGVK, metricsHost, operatorMetricsPort)
207+
if err != nil {
208+
return err
209+
}
210+
return nil
211+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
apiVersion: apiextensions.k8s.io/v1beta1
2+
kind: CustomResourceDefinition
3+
metadata:
4+
name: cmdbservices.app.example.com
5+
spec:
6+
group: app.example.com
7+
names:
8+
kind: CmdbService
9+
listKind: CmdbServiceList
10+
plural: cmdbservices
11+
singular: cmdbservice
12+
scope: Namespaced
13+
subresources:
14+
status: {}
15+
validation:
16+
openAPIV3Schema:
17+
description: CmdbService is the Schema for the cmdbservices API
18+
properties:
19+
apiVersion:
20+
description: 'APIVersion defines the versioned schema of this representation
21+
of an object. Servers should convert recognized schemas to the latest
22+
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
23+
type: string
24+
kind:
25+
description: 'Kind is a string value representing the REST resource this
26+
object represents. Servers may infer this from the endpoint the client
27+
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
28+
type: string
29+
metadata:
30+
type: object
31+
spec:
32+
description: CmdbServiceSpec defines the desired state of CmdbService
33+
type: object
34+
status:
35+
description: CmdbServiceStatus defines the observed state of CmdbService
36+
type: object
37+
type: object
38+
version: v1
39+
versions:
40+
- name: v1
41+
served: true
42+
storage: true

0 commit comments

Comments
 (0)