
Go saiki duwe monopoli ing basa pemrograman sing dipilih wong kanggo nulis pernyataan kanggo Kubernetes. Ana alasan objektif, kayata:
- Ana kerangka kuat kanggo ngembangake operator ing Go - .
- Aplikasi sing ngganti game kaya Docker lan Kubernetes ditulis ing Go. Nulis operator sampeyan ing Go tegese nganggo basa sing padha karo ekosistem.
- Kinerja dhuwur saka aplikasi Go lan alat prasaja kanggo nggarap concurrency metu saka kothak.
NB: Miturut cara, carane nulis statement dhewe ing Go, kita ing salah sawijining terjemahan kita dening penulis asing.
Nanging apa yen sampeyan ora bisa sinau Go amarga ora duwe wektu utawa, kanthi gampang, motivasi? Artikel kasebut menehi conto carane sampeyan bisa nulis statement sing apik nggunakake salah sawijining basa sing paling populer sing meh kabeh insinyur DevOps ngerti - Python.
Meet: Copier - copy operator!
Contone, nimbang ngembangake statement prasaja sing dirancang kanggo nyalin ConfigMap nalika ana spasi jeneng anyar utawa nalika salah siji saka rong entitas diganti: ConfigMap lan Secret. Saka sudut pandang praktis, operator bisa migunani kanggo nganyari konfigurasi aplikasi kanthi akeh (kanthi nganyari ConfigMap) utawa kanggo nganyari data rahasia - contone, tombol kanggo nggarap Registry Docker (nalika nambahake Rahasia menyang ruang jeneng).
Supaya apa operator apik kudu duwe:
- Interaksi karo operator digawa metu nggunakake (sabanjuré diarani CRD).
- Operator bisa diatur. Kanggo nindakake iki, kita bakal nggunakake panji baris printah lan variabel lingkungan.
- Pangwangunan wadhah Docker lan bagan Helm dirancang supaya pangguna bisa kanthi gampang (secara harfiah karo siji printah) nginstal operator menyang kluster Kubernetes.
CRD
Supaya operator ngerti apa sumber daya kanggo nggoleki lan ngendi kanggo katon, kita kudu nyetel aturan kanggo wong. Saben aturan bakal dituduhake minangka obyek CRD siji. Apa lapangan sing kudu diduweni CRD iki?
- jinis sumber daya, sing bakal kita goleki (ConfigMap utawa Secret).
- Dhaptar namespaces, ing ngendi sumber daya kudu dumunung.
- Selector, sing bakal kita goleki sumber daya ing ruang jeneng.
Ayo diterangake 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 Lan kita bakal nggawe langsung aturan sing gampang - kanggo nelusuri ing namespace karo jeneng default kabeh ConfigMap karo label kaya copyrator: "true":
apiVersion: flant.com/v1
kind: CopyratorRule
metadata:
name: main-rule
labels:
module: copyrator
ruleType: configmap
selector:
copyrator: "true"
namespace: defaultsiyap! Saiki kita kudu entuk informasi babagan aturan kita. Ayo kula nggawe leladen langsung sing kita ora bakal nulis panjalukan kanggo kluster API Server dhéwé. Kanggo nindakake iki, kita bakal nggunakake perpustakaan Python siap-digawe :
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')}Minangka asil mbukak kode iki, kita entuk ing ngisor iki:
{'ruleType': 'configmap', 'selector': {'copyrator': 'true'}, 'namespace': ['default']}Apik: kita bisa njaluk aturan kanggo operator. Lan sing paling penting, kita nindakake apa sing diarani cara Kubernetes.
Variabel lingkungan utawa gendera? We njupuk kabeh!
Ayo pindhah menyang konfigurasi operator utama. Ana rong pendekatan dhasar kanggo ngatur aplikasi:
- nggunakake opsi baris printah;
- nggunakake variabel lingkungan.
Opsi baris printah ngidini sampeyan maca setelan kanthi luwih fleksibel, kanthi dhukungan lan validasi jinis data. perpustakaan standar Python wis modul argparser, sing bakal kita gunakake. Rincian lan conto kemampuane kasedhiya ing .
Kanggo kasus kita, iki minangka conto nyetel panji baris perintah maca:
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()Ing sisih liya, nggunakake variabel lingkungan ing Kubernetes, sampeyan bisa kanthi gampang nransfer informasi layanan babagan pod ing wadhah kasebut. Contone, kita bisa entuk informasi babagan ruang jeneng ing ngendi pod mlaku kanthi konstruksi ing ngisor iki:
env:
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace Operator logika
Kanggo mangerteni carane misahake cara kanggo nggarap ConfigMap lan Secret, kita bakal nggunakake peta khusus. Banjur kita bisa ngerti cara apa sing kudu dilacak lan nggawe obyek kasebut:
LIST_TYPES_MAP = {
'configmap': 'list_namespaced_config_map',
'secret': 'list_namespaced_secret',
}
CREATE_TYPES_MAP = {
'configmap': 'create_namespaced_config_map',
'secret': 'create_namespaced_secret',
}Sabanjure, sampeyan kudu nampa acara saka server API. Ayo dileksanakake kaya ing ngisor iki:
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)Sawise nampa acara kasebut, kita pindhah menyang logika utama ngolah:
# Типы событий, на которые будем реагировать
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) Logika utama wis siyap! Saiki kita kudu ngemas kabeh iki dadi siji paket Python. Kita nyiapake file setup.py, tulis informasi meta babagan proyek ing kana:
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='maksim.nabokikh@flant.com',
include_package_data=True,
install_requires=[
'kubernetes==9.0.0',
],
entry_points={
'console_scripts': [
'{0} = {0}.cli:main'.format(_NAME),
]
}
)NB: Klien kubernetes kanggo Python duwe versi dhewe. Informasi liyane babagan kompatibilitas antarane versi klien lan versi Kubernetes bisa ditemokake ing .
Saiki proyek kita katon kaya iki:
copyrator
├── copyrator
│ ├── cli.py # Логика работы с командной строкой
│ ├── constant.py # Константы, которые мы приводили выше
│ ├── load_crd.py # Логика загрузки CRD
│ └── operator.py # Основная логика работы оператора
└── setup.py # Оформление пакетаDocker lan Helm
Dockerfile bakal gampang banget: njupuk gambar python-alpine dhasar lan instal paket kita. Ayo nundha optimasi nganti wektu sing luwih apik:
FROM python:3.7.3-alpine3.9
ADD . /app
RUN pip3 install /app
ENTRYPOINT ["copyrator"]Panyebaran kanggo operator uga gampang banget:
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 }}-accPungkasan, sampeyan kudu nggawe peran sing cocog kanggo operator kanthi hak sing dibutuhake:
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 }}Asile
Mangkono, tanpa wedi, cela, utawa sinau Go, kita bisa mbangun operator dhewe kanggo Kubernetes ing Python. Mesthi wae, isih duwe ruang kanggo tuwuh: ing mangsa ngarep bakal bisa ngolah pirang-pirang aturan, bisa digunakake ing pirang-pirang utas, kanthi mandiri ngawasi owah-owahan ing CRDs ...
Kanggo menehi tampilan sing luwih cetha ing kode, kita wis sijine ing . Yen sampeyan pengin conto operator sing luwih serius sing dileksanakake nggunakake Python, sampeyan bisa nguripake manungsa waé menyang rong operator kanggo deploying mongodb ( и ).
PS Lan yen sampeyan kesed kanggo ngatasi acara Kubernetes utawa sampeyan mung luwih biasa nggunakake Bash, kanca-kanca wis nyiapake solusi sing wis siap ing wangun (We ing April).
PPS
Waca uga ing blog kita:
- «";
- «";
- «";
- «";
- «".
Source: www.habr.com
