Go рд╣рд╛рд▓ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдЩ рднрд╛рд╖рд╛рд╣рд░реВрдорд╛ рдПрдХрд╛рдзрд┐рдХрд╛рд░ рдЫ рдорд╛рдирд┐рд╕рд╣рд░реВрд▓реЗ Kubernetes рдХреЛ рд▓рд╛рдЧрд┐ рдХрдердирд╣рд░реВ рд▓реЗрдЦреНрди рд░реЛрдЬреНрдЫрдиреНред рдпрд╕рдХрд╛ рд▓рд╛рдЧрд┐ рд╡рд╕реНрддреБрдЧрдд рдХрд╛рд░рдгрд╣рд░реВ рдЫрдиреН, рдЬрд╕реНрддреИ:
- рддреНрдпрд╣рд╛рдБ Go рдорд╛ рдЕрдкрд░реЗрдЯрд░рд╣рд░реВ рд╡рд┐рдХрд╛рд╕ рдЧрд░реНрдирдХреЛ рд▓рд╛рдЧрд┐ рдПрдХ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдлреНрд░реЗрдорд╡рд░реНрдХ рдЫ -
рдЕрдкрд░реЗрдЯрд░ SDK . - Docker рд░ Kubernetes рдЬрд╕реНрддрд╛ рдЧреЗрдо рдкрд░рд┐рд╡рд░реНрддрди рдЧрд░реНрдиреЗ рдПрдкрд╣рд░реВ Go рдорд╛ рд▓реЗрдЦрд┐рдПрдХрд╛ рдЫрдиреНред Go рдорд╛ рдЖрдлреНрдиреЛ рдЕрдкрд░реЗрдЯрд░ рд▓реЗрдЦреНрдиреБ рднрдиреЗрдХреЛ рдЗрдХреЛрд╕рд┐рд╕реНрдЯрдорд╕рдБрдЧ рдЙрд╣реА рднрд╛рд╖рд╛ рдмреЛрд▓реНрдиреБ рд╣реЛред
- рдЧреЛ рдПрдкреНрд▓рд┐рдХреЗрд╕рдирд╣рд░реВрдХреЛ рдЙрдЪреНрдЪ рдкреНрд░рджрд░реНрд╢рди рд░ рдмрд╛рдХрд╕ рдмрд╛рд╣рд┐рд░ рдПрдХрд░реВрдкрддрд╛рд╕рдБрдЧ рдХрд╛рдо рдЧрд░реНрдирдХрд╛ рд▓рд╛рдЧрд┐ рд╕рд░рд▓ рдЙрдкрдХрд░рдгрд╣рд░реВред
NB: рдЦреИрд░, рдЧреЛ рдорд╛ рдЖрдлреНрдиреЛ рдмрдпрд╛рди рдХрд╕рд░реА рд▓реЗрдЦреНрдиреЗ, рд╣рд╛рдореА
рддрд░ рдХреЗ рд╣реБрдиреНрдЫ рдпрджрд┐ рддрдкрд╛рдИрд▓рд╛рдИ рд╕рдордпрдХреЛ рдЕрднрд╛рд╡рдорд╛ рдЧреЛ рд╕рд┐рдХреНрдирдмрд╛рдЯ рд░реЛрдХрд┐рдПрдХреЛ рдЫ рд╡рд╛, рд╕рд░рд▓ рд░реВрдкрдорд╛ рднрдиреНрдиреБрдкрд░реНрджрд╛, рдкреНрд░реЗрд░рдгрд╛рд▓реЗ? рд▓реЗрдЦрд▓реЗ рддрдкрд╛рдЗрдБ рдХрд╕рд░реА рдПрдХ рд╕рдмреИрднрдиреНрджрд╛ рд▓реЛрдХрдкреНрд░рд┐рдп рднрд╛рд╖рд╛рд╣рд░реВ рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рд░рд╛рдореНрд░реЛ рдХрдерди рд▓реЗрдЦреНрди рд╕рдХреНрдиреБрд╣реБрдиреНрдЫ рднрдиреНрдиреЗ рдЙрджрд╛рд╣рд░рдг рдкреНрд░рджрд╛рди рдЧрд░реНрджрдЫ рдЬреБрди рд▓рдЧрднрдЧ рд╣рд░реЗрдХ DevOps рдЗрдиреНрдЬрд┐рдирд┐рдпрд░рд▓рд╛рдИ рдерд╛рд╣рд╛ рдЫ - рдЕрдЬрдЧрд░.
рднреЗрдЯреНрдиреБрд╣реЛрд╕реН: рдХрдкрд┐рдпрд░ - рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдЕрдкрд░реЗрдЯрд░!
рдЙрджрд╛рд╣рд░рдгрдХреЛ рд░реВрдкрдорд╛, рдХрдиреНрдлрд┐рдЧрдореНрдпрд╛рдк рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдЧрд░реНрди рдбрд┐рдЬрд╛рдЗрди рдЧрд░рд┐рдПрдХреЛ рдПрдЙрдЯрд╛ рд╕рд╛рдзрд╛рд░рдг рдХрдерди рд╡рд┐рдХрд╛рд╕ рдЧрд░реНрдиреЗ рд╡рд┐рдЪрд╛рд░ рдЧрд░реНрдиреБрд╣реЛрд╕реН рдЬрдм рдХрд┐ рдирдпрд╛рдБ рдиреЗрдорд╕реНрдкреЗрд╕ рджреЗрдЦрд╛ рдкрд░реНрджрдЫ рд╡рд╛ рдЬрдм рджреБрдИ рд╕рдВрд╕реНрдерд╛рд╣рд░реВ рдордзреНрдпреЗ рдПрдЙрдЯрд╛ рдкрд░рд┐рд╡рд░реНрддрди рд╣реБрдиреНрдЫ: рдХрдиреНрдлрд┐рдЧрдореНрдпрд╛рдк рд░ рд╕реЗрдХреНрд░реЗрдЯред рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рджреГрд╖реНрдЯрд┐рдХреЛрдгрдмрд╛рдЯ, рдЕрдкрд░реЗрдЯрд░ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХрдиреНрдлрд┐рдЧрд░реЗрд╕рдирд╣рд░реВрдХреЛ рдмрд▓реНрдХ рдЕрджреНрдпрд╛рд╡рдзрд┐рдХ рдЧрд░реНрди (рдХрдиреНрдлрд┐рдЧрдореНрдпрд╛рдк рдЕрджреНрдпрд╛рд╡рдзрд┐рдХ рдЧрд░реЗрд░) рд╡рд╛ рдЧреЛрдкреНрдп рдбрд╛рдЯрд╛ рдЕрдкрдбреЗрдЯ рдЧрд░реНрдирдХрд╛ рд▓рд╛рдЧрд┐ рдЙрдкрдпреЛрдЧреА рд╣реБрди рд╕рдХреНрдЫ - рдЙрджрд╛рд╣рд░рдгрдХрд╛ рд▓рд╛рдЧрд┐, рдбрдХрд░ рд░рдЬрд┐рд╕реНрдЯреНрд░реАрд╕рдБрдЧ рдХрд╛рдо рдЧрд░реНрдиреЗ рдХреБрдЮреНрдЬреАрд╣рд░реВ (рдиреЗрдорд╕реНрдкреЗрд╕рдорд╛ рдЧреЛрдкреНрдп рдердкреНрджрд╛)ред
рд░ рддреНрдпрд╕реИрд▓реЗ, рд░рд╛рдореНрд░реЛ рдЕрдкрд░реЗрдЯрд░ рдХреЗ рд╣реБрдиреБрдкрд░реНрдЫ:
- рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдЕрдкрд░реЗрдЯрд░ рд╕рдВрдЧ рдЕрдиреНрддрд░рдХреНрд░рд┐рдпрд╛ рдЧрд░рд┐рдиреНрдЫ
рдЕрдиреБрдХреВрд▓рди рд╕реНрд░реЛрдд рдкрд░рд┐рднрд╛рд╖рд╛рд╣рд░реВ (рдпрд╕рдкрдЫрд┐ CRD рднрдирд┐рдиреНрдЫ)ред - рдЕрдкрд░реЗрдЯрд░ рдХрдиреНрдлрд┐рдЧрд░ рдЧрд░реНрди рд╕рдХрд┐рдиреНрдЫред рдпреЛ рдЧрд░реНрдирдХреЛ рд▓рд╛рдЧрд┐, рд╣рд╛рдореА рдХрдорд╛рдгреНрдб рд▓рд╛рдЗрди рдлреНрд▓реНрдпрд╛рдЧрд╣рд░реВ рд░ рд╡рд╛рддрд╛рд╡рд░рдг рдЪрд░рд╣рд░реВ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреЗрдЫреМрдВред
- рдбрдХрд░ рдХрдиреНрдЯреЗрдирд░ рд░ рд╣реЗрд▓реНрдо рдЪрд╛рд░реНрдЯрдХреЛ рдирд┐рд░реНрдорд╛рдг рдбрд┐рдЬрд╛рдЗрди рдЧрд░рд┐рдПрдХреЛ рдЫ рддрд╛рдХрд┐ рдкреНрд░рдпреЛрдЧрдХрд░реНрддрд╛рд╣рд░реВрд▓реЗ рд╕рдЬрд┐рд▓реИрд╕рдБрдЧ (рд╢рд╛рдмреНрджрд┐рдХ рд░реВрдкрдорд╛ рдПрдЙрдЯрд╛ рдЖрджреЗрд╢рдХреЛ рд╕рд╛рде) рдЕрдкрд░реЗрдЯрд░рд▓рд╛рдИ рддрд┐рдиреАрд╣рд░реВрдХреЛ рдХреБрдмрд░реНрдиреЗрдЯреНрд╕ рдХреНрд▓рд╕реНрдЯрд░рдорд╛ рд╕реНрдерд╛рдкрдирд╛ рдЧрд░реНрди рд╕рдХреВрдиреНред
рд╕реАрдЖрд░рдбреА
рддреНрдпрд╕рдХрд╛рд░рдг рдЕрдкрд░реЗрдЯрд░рд▓рд╛рдИ рдерд╛рд╣рд╛ рдЫ рдХреБрди рд╕реНрд░реЛрддрд╣рд░реВ рд░ рдХрд╣рд╛рдБ рд╣реЗрд░реНрдиреЗ, рд╣рд╛рдореАрд▓реЗ рдЙрд╕рдХреЛ рд▓рд╛рдЧрд┐ рдирд┐рдпрдо рд╕реЗрдЯ рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫред рдкреНрд░рддреНрдпреЗрдХ рдирд┐рдпрдорд▓рд╛рдИ рдПрдХрд▓ CRD рд╡рд╕реНрддреБрдХреЛ рд░реВрдкрдорд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдЧрд░рд┐рдиреЗрдЫред рдпреЛ CRD рдХреЗ рдХреНрд╖реЗрддреНрд░рд╣рд░реВ рд╣реБрдиреБрдкрд░реНрдЫ?
- рд╕реНрд░реЛрдд рдкреНрд░рдХрд╛рд░, рдЬреБрди рд╣рд╛рдореАрд▓реЗ рдЦреЛрдЬреНрдиреЗрдЫреМрдВ (рдХрдиреНрдлрд┐рдЧрдореНрдпрд╛рдк рд╡рд╛ рдЧреЛрдкреНрдп)ред
- рдирд╛рдорд╕реНрдерд╛рдирд╣рд░реВрдХреЛ рд╕реВрдЪреА, рдЬрд╕рдорд╛ рд╕реНрд░реЛрддрд╣рд░реВ рдЕрд╡рд╕реНрдерд┐рдд рд╣реБрдиреБрдкрд░реНрдЫред
- рдЪрдпрдирдХрд░реНрддрд╛, рдЬрд╕рджреНрд╡рд╛рд░рд╛ рд╣рд╛рдореА рдирд╛рдорд╕реНрдерд╛рдирдорд╛ рд╕реНрд░реЛрддрд╣рд░реВ рдЦреЛрдЬреНрдиреЗрдЫреМрдВред
CRD рдХреЛ рд╡рд░реНрдгрди рдЧрд░реМрдВ:
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: copyrator.flant.com
spec:
group: flant.com
versions:
- name: v1
served: true
storage: true
scope: Namespaced
names:
plural: copyrators
singular: copyrator
kind: CopyratorRule
shortNames:
- copyr
validation:
openAPIV3Schema:
type: object
properties:
ruleType:
type: string
namespaces:
type: array
items:
type: string
selector:
type: string
рд░ рд╣рд╛рдореА рдпрд╕рд▓рд╛рдИ рддреБрд░реБрдиреНрддреИ рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░реНрдиреЗрдЫреМрдВ рд╕рд░рд▓ рдирд┐рдпрдо - рдирд╛рдордХреЛ рд╕рд╛рде рдиреЗрдорд╕реНрдкреЗрд╕рдорд╛ рдЦреЛрдЬреА рдЧрд░реНрди default
рд╕рдмреИ рдХрдиреНрдлрд┐рдЧрдореНрдпрд╛рдк рдЬрд╕реНрддрд╛ рд▓реЗрдмрд▓рд╣рд░реВрд╕рдБрдЧ copyrator: "true"
:
apiVersion: flant.com/v1
kind: CopyratorRule
metadata:
name: main-rule
labels:
module: copyrator
ruleType: configmap
selector:
copyrator: "true"
namespace: default
рддрдпрд╛рд░! рдЕрдм рд╣рд╛рдореАрд▓реЗ рд╣рд╛рдореНрд░реЛ рдирд┐рдпрдордХреЛ рдмрд╛рд░реЗрдорд╛ рдЬрд╛рдирдХрд╛рд░реА рд▓рд┐рди рдЖрд╡рд╢реНрдпрдХ рдЫред рдорд▓рд╛рдИ рддреБрд░реБрдиреНрддреИ рд░рд┐рдЬрд░реНрднреЗрд╕рди рдЧрд░реНрди рджрд┐рдиреБрд╣реЛрд╕реН рдХрд┐ рд╣рд╛рдореА рдХреНрд▓рд╕реНрдЯрд░ API рд╕рд░реНрднрд░рдорд╛ рдЕрдиреБрд░реЛрдзрд╣рд░реВ рд▓реЗрдЦреНрдиреЗ рдЫреИрдиреМрдВред рдпреЛ рдЧрд░реНрдирдХреЛ рд▓рд╛рдЧрд┐, рд╣рд╛рдореА рддрдпрд╛рд░-рдирд┐рд░реНрдорд┐рдд рдкрд╛рдЗрдерди рдкреБрд╕реНрддрдХрд╛рд▓рдп рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреЗрдЫреМрдВ
import kubernetes
from contextlib import suppress
CRD_GROUP = 'flant.com'
CRD_VERSION = 'v1'
CRD_PLURAL = 'copyrators'
def load_crd(namespace, name):
client = kubernetes.client.ApiClient()
custom_api = kubernetes.client.CustomObjectsApi(client)
with suppress(kubernetes.client.api_client.ApiException):
crd = custom_api.get_namespaced_custom_object(
CRD_GROUP,
CRD_VERSION,
namespace,
CRD_PLURAL,
name,
)
return {x: crd[x] for x in ('ruleType', 'selector', 'namespace')}
рдпреЛ рдХреЛрдб рдЪрд▓рд╛рдЙрдиреЗ рдкрд░рд┐рдгрд╛рдордХреЛ рд░реВрдкрдорд╛, рд╣рд╛рдореАрд▓реЗ рдирд┐рдореНрди рдкрд╛рдЙрдБрдЫреМрдВ:
{'ruleType': 'configmap', 'selector': {'copyrator': 'true'}, 'namespace': ['default']}
рдЙрддреНрдХреГрд╖реНрдЯ: рд╣рд╛рдореАрд▓реЗ рдЕрдкрд░реЗрдЯрд░рдХреЛ рд▓рд╛рдЧрд┐ рдирд┐рдпрдо рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрди рд╕рдлрд▓ рднрдпреМрдВред рд░ рд╕рдмреИрднрдиреНрджрд╛ рдорд╣рддреНрддреНрд╡рдкреВрд░реНрдг рдХреБрд░рд╛, рд╣рд╛рдореАрд▓реЗ рдХреБрдмрд░реНрдиреЗрдЯреНрд╕ рдорд╛рд░реНрдЧ рднрдирд┐рдиреЗ рдХрд╛рдо рдЧрд░реНрдпреМрдВред
рд╡рд╛рддрд╛рд╡рд░рдг рдЪрд░ рд╡рд╛ рдЭрдгреНрдбрд╛? рд╣рд╛рдореА рд╕рдмреИ рд▓рд┐рдиреНрдЫреМрдВ!
рдореБрдЦреНрдп рдЕрдкрд░реЗрдЯрд░ рдХрдиреНрдлрд┐рдЧрд░реЗрд╕рдирдорд╛ рдЬрд╛рдФрдВред рддреНрдпрд╣рд╛рдБ рдЕрдиреБрдкреНрд░рдпреЛрдЧрд╣рд░реВ рдХрдиреНрдлрд┐рдЧрд░ рдЧрд░реНрди рджреБрдИ рдЖрдзрд╛рд░рднреВрдд рджреГрд╖реНрдЯрд┐рдХреЛрдгрд╣рд░реВ рдЫрдиреН:
- рдЖрджреЗрд╢ рд░реЗрдЦрд╛ рд╡рд┐рдХрд▓реНрдкрд╣рд░реВ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреБрд╣реЛрд╕реН;
- рд╡рд╛рддрд╛рд╡рд░рдг рдЪрд░ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреБрд╣реЛрд╕реНред
рдХрдорд╛рдгреНрдб рд▓рд╛рдЗрди рд╡рд┐рдХрд▓реНрдкрд╣рд░реВрд▓реЗ рддрдкрд╛рдИрдВрд▓рд╛рдИ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рд╕рдорд░реНрдерди рд░ рдкреНрд░рдорд╛рдгреАрдХрд░рдгрдХреЛ рд╕рд╛рде рд╕реЗрдЯрд┐рдЩрд╣рд░реВ рдердк рд▓рдЪрд┐рд▓реЛ рд░реВрдкрдорд╛ рдкрдвреНрди рдЕрдиреБрдорддрд┐ рджрд┐рдиреНрдЫред рдкрд╛рдЗрдердирдХреЛ рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдпрдорд╛ рдореЛрдбреНрдпреБрд▓ рдЫ argparser
, рдЬреБрди рд╣рд╛рдореА рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреЗрдЫреМрдВред рдпрд╕рдХреЛ рдХреНрд╖рдорддрд╛рд╣рд░реВрдХреЛ рд╡рд┐рд╡рд░рдг рд░ рдЙрджрд╛рд╣рд░рдгрд╣рд░реВ рдЙрдкрд▓рдмреНрдз рдЫрдиреН
рд╣рд╛рдореНрд░реЛ рдХреЗрд╕рдХреЛ рд▓рд╛рдЧрд┐, рдпреЛ рдХрд╕реНрддреЛ рджреЗрдЦрд┐рдиреНрдЫ рдХрдорд╛рдгреНрдб рд▓рд╛рдЗрди рдлреНрд▓реНрдпрд╛рдЧрд╣рд░реВ рдкрдвреНрдиреЗ рд╕реЗрдЯрдЕрдк рдЧрд░реНрдиреЗ рдЙрджрд╛рд╣рд░рдг:
parser = ArgumentParser(
description='Copyrator - copy operator.',
prog='copyrator'
)
parser.add_argument(
'--namespace',
type=str,
default=getenv('NAMESPACE', 'default'),
help='Operator Namespace'
)
parser.add_argument(
'--rule-name',
type=str,
default=getenv('RULE_NAME', 'main-rule'),
help='CRD Name'
)
args = parser.parse_args()
рдЕрд░реНрдХреЛрддрд░реНрдл, Kubernetes рдорд╛ рд╡рд╛рддрд╛рд╡рд░рдгреАрдп рдЪрд░рд╣рд░реВ рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░, рддрдкрд╛рдИрдВ рдХрдиреНрдЯреЗрдирд░ рднрд┐рддреНрд░ рдкреЛрдбрдХреЛ рдмрд╛рд░реЗрдорд╛ рд╕реЗрд╡рд╛ рдЬрд╛рдирдХрд╛рд░реА рд╕рдЬрд┐рд▓реИ рд╣рд╕реНрддрд╛рдиреНрддрд░рдг рдЧрд░реНрди рд╕рдХреНрдиреБрд╣реБрдиреНрдЫред рдЙрджрд╛рд╣рд░рдг рдХреЛ рд▓рд╛рдЧреА, рд╣рд╛рдореА рдирд┐рдореНрди рдирд┐рд░реНрдорд╛рдг рд╕рдВрдЧ рдкреЛрдб рдЪрд▓рд┐рд░рд╣реЗрдХреЛ рдиреЗрдорд╕реНрдкреЗрд╕ рдмрд╛рд░реЗ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрди рд╕рдХреНрдЫреМрдВ:
env:
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
рдЕрдкрд░реЗрдЯрд░ рддрд░реНрдХ
рдХрдиреНрдлрд┐рдЧрдореНрдпрд╛рдк рд░ рд╕реЗрдХреНрд░реЗрдЯрд╕рдБрдЧ рдХрд╛рдо рдЧрд░реНрдиреЗ рд╡рд┐рдзрд┐рд╣рд░реВ рдХрд╕рд░реА рдЕрд▓рдЧ рдЧрд░реНрдиреЗ рднрдиреЗрд░ рдмреБрдЭреНрди, рд╣рд╛рдореА рд╡рд┐рд╢реЗрд╖ рдирдХреНрд╕рд╛рд╣рд░реВ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреЗрдЫреМрдВред рддреНрдпрд╕реЛрднрдП рд╣рд╛рдореАрд▓реЗ рд╡рд╕реНрддреБрд▓рд╛рдИ рдЯреНрд░реНрдпрд╛рдХ рдЧрд░реНрди рд░ рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдкрд░реНрдиреЗ рд╡рд┐рдзрд┐рд╣рд░реВ рдмреБрдЭреНрди рд╕рдХреНрдЫреМрдВ:
LIST_TYPES_MAP = {
'configmap': 'list_namespaced_config_map',
'secret': 'list_namespaced_secret',
}
CREATE_TYPES_MAP = {
'configmap': 'create_namespaced_config_map',
'secret': 'create_namespaced_secret',
}
рдЕрд░реНрдХреЛ, рддрдкрд╛рдИрдВрд▓реЗ API рд╕рд░реНрднрд░рдмрд╛рдЯ рдШрдЯрдирд╛рд╣рд░реВ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫред рдпрд╕рд▓рд╛рдИ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЧрд░реМрдВ:
def handle(specs):
kubernetes.config.load_incluster_config()
v1 = kubernetes.client.CoreV1Api()
# ╨Я╨╛╨╗╤Г╤З╨░╨╡╨╝ ╨╝╨╡╤В╨╛╨┤ ╨┤╨╗╤П ╤Б╨╗╨╡╨╢╨╡╨╜╨╕╤П ╨╖╨░ ╨╛╨▒╤К╨╡╨║╤В╨░╨╝╨╕
method = getattr(v1, LIST_TYPES_MAP[specs['ruleType']])
func = partial(method, specs['namespace'])
w = kubernetes.watch.Watch()
for event in w.stream(func, _request_timeout=60):
handle_event(v1, specs, event)
рдШрдЯрдирд╛ рдкреНрд░рд╛рдкреНрдд рдЧрд░реЗрдкрдЫрд┐, рд╣рд╛рдореА рдпрд╕рд▓рд╛рдИ рдкреНрд░рд╢реЛрдзрди рдЧрд░реНрдиреЗ рдореБрдЦреНрдп рддрд░реНрдХрдорд╛ рдЬрд╛рдиреНрдЫреМрдВ:
# ╨в╨╕╨┐╤Л ╤Б╨╛╨▒╤Л╤В╨╕╨╣, ╨╜╨░ ╨║╨╛╤В╨╛╤А╤Л╨╡ ╨▒╤Г╨┤╨╡╨╝ ╤А╨╡╨░╨│╨╕╤А╨╛╨▓╨░╤В╤М
ALLOWED_EVENT_TYPES = {'ADDED', 'UPDATED'}
def handle_event(v1, specs, event):
if event['type'] not in ALLOWED_EVENT_TYPES:
return
object_ = event['object']
labels = object_['metadata'].get('labels', {})
# ╨Ш╤Й╨╡╨╝ ╤Б╨╛╨▓╨┐╨░╨┤╨╡╨╜╨╕╤П ╨┐╨╛ selector'╤Г
for key, value in specs['selector'].items():
if labels.get(key) != value:
return
# ╨Я╨╛╨╗╤Г╤З╨░╨╡╨╝ ╨░╨║╤В╨╕╨▓╨╜╤Л╨╡ namespace'╤Л
namespaces = map(
lambda x: x.metadata.name,
filter(
lambda x: x.status.phase == 'Active',
v1.list_namespace().items
)
)
for namespace in namespaces:
# ╨Ю╤З╨╕╤Й╨░╨╡╨╝ ╨╝╨╡╤В╨░╨┤╨░╨╜╨╜╤Л╨╡, ╤Г╤Б╤В╨░╨╜╨░╨▓╨╗╨╕╨▓╨░╨╡╨╝ namespace
object_['metadata'] = {
'labels': object_['metadata']['labels'],
'namespace': namespace,
'name': object_['metadata']['name'],
}
# ╨Т╤Л╨╖╤Л╨▓╨░╨╡╨╝ ╨╝╨╡╤В╨╛╨┤ ╤Б╨╛╨╖╨┤╨░╨╜╨╕╤П/╨╛╨▒╨╜╨╛╨▓╨╗╨╡╨╜╨╕╤П ╨╛╨▒╤К╨╡╨║╤В╨░
methodcaller(
CREATE_TYPES_MAP[specs['ruleType']],
namespace,
object_
)(v1)
рдореБрдЦреНрдп рддрд░реНрдХ рддрдпрд╛рд░ рдЫ! рдЕрдм рд╣рд╛рдореАрд▓реЗ рдпреЛ рд╕рдмреИрд▓рд╛рдИ рдПрдЙрдЯрд╛ рдкрд╛рдЗрдерди рдкреНрдпрд╛рдХреЗрдЬрдорд╛ рдкреНрдпрд╛рдХреЗрдЬ рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫред рд╣рд╛рдореА рдлрд╛рдЗрд▓ рддрдпрд╛рд░ рдЧрд░реНрдЫреМрдВ setup.py
, рддреНрдпрд╣рд╛рдБ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдмрд╛рд░реЗ рдореЗрдЯрд╛ рдЬрд╛рдирдХрд╛рд░реА рд▓реЗрдЦреНрдиреБрд╣реЛрд╕реН:
from sys import version_info
from setuptools import find_packages, setup
if version_info[:2] < (3, 5):
raise RuntimeError(
'Unsupported python version %s.' % '.'.join(version_info)
)
_NAME = 'copyrator'
setup(
name=_NAME,
version='0.0.1',
packages=find_packages(),
classifiers=[
'Development Status :: 3 - Alpha',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
],
author='Flant',
author_email='[email protected]',
include_package_data=True,
install_requires=[
'kubernetes==9.0.0',
],
entry_points={
'console_scripts': [
'{0} = {0}.cli:main'.format(_NAME),
]
}
)
NB: рдкрд╛рдЗрдердирдХреЛ рд▓рд╛рдЧрд┐ kubernetes рдХреНрд▓рд╛рдЗрдиреНрдЯрдХреЛ рдЖрдлреНрдиреИ рд╕рдВрд╕реНрдХрд░рдг рдЫред рдЧреНрд░рд╛рд╣рдХ рд╕рдВрд╕реНрдХрд░рдгрд╣рд░реВ рд░ Kubernetes рд╕рдВрд╕реНрдХрд░рдгрд╣рд░реВ рдмреАрдЪ рдЕрдиреБрдХреВрд▓рддрд╛ рдмрд╛рд░реЗ рдердк рдЬрд╛рдирдХрд╛рд░реА рдлреЗрд▓рд╛ рдкрд╛рд░реНрди рд╕рдХрд┐рдиреНрдЫ
рдЕрдм рд╣рд╛рдореНрд░реЛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдпрд╕реНрддреЛ рджреЗрдЦрд┐рдиреНрдЫ:
copyrator
тФЬтФАтФА copyrator
тФВ тФЬтФАтФА cli.py # ╨Ы╨╛╨│╨╕╨║╨░ ╤А╨░╨▒╨╛╤В╤Л ╤Б ╨║╨╛╨╝╨░╨╜╨┤╨╜╨╛╨╣ ╤Б╤В╤А╨╛╨║╨╛╨╣
тФВ тФЬтФАтФА constant.py # ╨Ъ╨╛╨╜╤Б╤В╨░╨╜╤В╤Л, ╨║╨╛╤В╨╛╤А╤Л╨╡ ╨╝╤Л ╨┐╤А╨╕╨▓╨╛╨┤╨╕╨╗╨╕ ╨▓╤Л╤И╨╡
тФВ тФЬтФАтФА load_crd.py # ╨Ы╨╛╨│╨╕╨║╨░ ╨╖╨░╨│╤А╤Г╨╖╨║╨╕ CRD
тФВ тФФтФАтФА operator.py # ╨Ю╤Б╨╜╨╛╨▓╨╜╨░╤П ╨╗╨╛╨│╨╕╨║╨░ ╤А╨░╨▒╨╛╤В╤Л ╨╛╨┐╨╡╤А╨░╤В╨╛╤А╨░
тФФтФАтФА setup.py # ╨Ю╤Д╨╛╤А╨╝╨╗╨╡╨╜╨╕╨╡ ╨┐╨░╨║╨╡╤В╨░
рдбрдХрд░ рд░ рд╣реЗрд▓рдо
рдбрдХрд░рдлрд╛рдЗрд▓ рдЕрд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд░реВрдкрдорд╛ рд╕рд░рд▓ рд╣реБрдиреЗрдЫ: рдЖрдзрд╛рд░ рдкрд╛рдЗрдерди-рдЕрд▓реНрдкрд╛рдЗрди рдЫрд╡рд┐ рд▓рд┐рдиреБрд╣реЛрд╕реН рд░ рд╣рд╛рдореНрд░реЛ рдкреНрдпрд╛рдХреЗрдЬ рд╕реНрдерд╛рдкрдирд╛ рдЧрд░реНрдиреБрд╣реЛрд╕реНред рд░рд╛рдореНрд░реЛ рд╕рдордп рд╕рдореНрдо рдпрд╕рдХреЛ рдЕрдкреНрдЯрд┐рдорд╛рдЗрдЬреЗрд╕рди рд╕реНрдердЧрд┐рдд рдЧрд░реМрдВ:
FROM python:3.7.3-alpine3.9
ADD . /app
RUN pip3 install /app
ENTRYPOINT ["copyrator"]
рдЕрдкрд░реЗрдЯрд░рдХреЛ рд▓рд╛рдЧрд┐ рддреИрдирд╛рддреА рдкрдирд┐ рдзреЗрд░реИ рд╕рд░рд▓ рдЫ:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Chart.Name }}
spec:
selector:
matchLabels:
name: {{ .Chart.Name }}
template:
metadata:
labels:
name: {{ .Chart.Name }}
spec:
containers:
- name: {{ .Chart.Name }}
image: privaterepo.yourcompany.com/copyrator:latest
imagePullPolicy: Always
args: ["--rule-type", "main-rule"]
env:
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
serviceAccountName: {{ .Chart.Name }}-acc
рдЕрдиреНрддрдорд╛, рддрдкрд╛рдИрдВрд▓реЗ рдЖрд╡рд╢реНрдпрдХ рдЕрдзрд┐рдХрд╛рд░рд╣рд░реВрдХреЛ рд╕рд╛рде рдЕрдкрд░реЗрдЯрд░рдХреЛ рд▓рд╛рдЧрд┐ рдЙрдкрдпреБрдХреНрдд рднреВрдорд┐рдХрд╛ рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫ:
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Chart.Name }}-acc
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: {{ .Chart.Name }}
rules:
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["get", "watch", "list"]
- apiGroups: [""]
resources: ["secrets", "configmaps"]
verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: {{ .Chart.Name }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ .Chart.Name }}
subjects:
- kind: ServiceAccount
name: {{ .Chart.Name }}
рдкрд░рд┐рдгрд╛рдо
рдпрд╕рд░реА, рдмрд┐рдирд╛ рдбрд░, рдирд┐рдиреНрджрд╛, рд╡рд╛ рд╕рд┐рдХреНрдиреЗ рдЧреЛ, рд╣рд╛рдореАрд▓реЗ рдкрд╛рдЗрдердирдорд╛ Kubernetes рдХреЛ рд▓рд╛рдЧрд┐ рд╣рд╛рдореНрд░реЛ рдЖрдлреНрдиреИ рдЕрдкрд░реЗрдЯрд░ рдирд┐рд░реНрдорд╛рдг рдЧрд░реНрди рд╕рдХреНрд╖рдо рднрдпреМрдВред рдирд┐рд╕реНрд╕рдиреНрджреЗрд╣, рдпрд╕рдорд╛ рдЕрдЭреИ рдмрдвреНрдирдХреЛ рд▓рд╛рдЧрд┐ рдард╛рдЙрдБ рдЫ: рднрд╡рд┐рд╖реНрдпрдорд╛ рдпрд╕рд▓реЗ рдзреЗрд░реИ рдирд┐рдпрдорд╣рд░реВ рдкреНрд░рд╢реЛрдзрди рдЧрд░реНрди, рдмрд╣реБ рдереНрд░реЗрдбрд╣рд░реВрдорд╛ рдХрд╛рдо рдЧрд░реНрди, рд╕реНрд╡рддрдиреНрддреНрд░ рд░реВрдкрдорд╛ рдпрд╕рдХреЛ CRDs рдорд╛ рдкрд░рд┐рд╡рд░реНрддрдирд╣рд░реВ рдирд┐рдЧрд░рд╛рдиреА рдЧрд░реНрди рд╕рдХреНрд╖рдо рд╣реБрдиреЗрдЫред
рддрдкрд╛рдИрдВрд▓рд╛рдИ рдХреЛрдбрдХреЛ рдирдЬрд┐рдХрдмрд╛рдЯ рд╣реЗрд░реНрдирдХреЛ рд▓рд╛рдЧрд┐, рд╣рд╛рдореАрд▓реЗ рдпрд╕рд▓рд╛рдИ рд░рд╛рдЦреЗрдХрд╛ рдЫреМрдВ
PS рд░ рдпрджрд┐ рддрдкрд╛рдЗрдБ Kubernetes рдШрдЯрдирд╛рд╣рд░реВрд╕рдБрдЧ рд╡реНрдпрд╡рд╣рд╛рд░ рдЧрд░реНрди рдзреЗрд░реИ рдЕрд▓реНрдЫреА рд╣реБрдиреБрд╣реБрдиреНрдЫ рд╡рд╛ рддрдкрд╛рдЗрдБ рдХреЗрд╡рд▓ Bash рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рдЕрднреНрдпрд╕реНрдд рд╣реБрдиреБрд╣реБрдиреНрдЫ рднрдиреЗ, рд╣рд╛рдореНрд░рд╛ рд╕рд╣рдХрд░реНрдореАрд╣рд░реВрд▓реЗ рдлрд╛рд░рдордорд╛ рддрдпрд╛рд░ рд╕рдорд╛рдзрд╛рди рддрдпрд╛рд░ рдЧрд░реЗрдХрд╛ рдЫрдиреНред
рдкреАрдкреАрдПрд╕
рд╣рд╛рдореНрд░реЛ рдмреНрд▓рдЧрдорд╛ рдкрдирд┐ рдкрдвреНрдиреБрд╣реЛрд╕реН:
- ┬л
рдХреЗ Kubernetes рдХреНрд▓рд╕реНрдЯрд░ рддрдпрд╛рд░ рдЧрд░реНрди рд╕рдЬрд┐рд▓реЛ рд░ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдЫ? рдПрдбрдЕрди-рдЕрдкрд░реЗрдЯрд░ рдШреЛрд╖рдгрд╛ рдЧрд░реНрджреИ ┬╗; - ┬л
рд╢реЗрд▓-рдЕрдкрд░реЗрдЯрд░рдХреЛ рдкрд░рд┐рдЪрдп рджрд┐рдБрджреИ: Kubernetes рдХреЛ рд▓рд╛рдЧрд┐ рдЕрдкрд░реЗрдЯрд░рд╣рд░реВ рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░реНрди рд╕рдЬрд┐рд▓реЛ рднрдпреЛ ┬╗; - ┬л
Kubernetes рдХреЛ рд╡рд┐рд╕реНрддрд╛рд░ рд░ рдкреВрд░рдХ (рдЕрд╡рд▓реЛрдХрди рд░ рднрд┐рдбрд┐рдпреЛ рд░рд┐рдкреЛрд░реНрдЯ) ┬╗; - ┬л
Golang рдорд╛ Kubernetes рдХреЛ рд▓рд╛рдЧреА рдПрдХ рдЕрдкрд░реЗрдЯрд░ рд▓реЗрдЦреНрджреИ ┬╗; - ┬л
Kubernetes рдХреЛ рд▓рд╛рдЧреА рдЕрдкрд░реЗрдЯрд░рд╣рд░реВ: рд╕реНрдЯреЗрдЯрдлреБрд▓ рдЕрдиреБрдкреНрд░рдпреЛрдЧрд╣рд░реВ рдХрд╕рд░реА рдЪрд▓рд╛рдЙрдиреЗ "ред
рд╕реНрд░реЛрдд: www.habr.com