Энэ жил Европын Kubernetes-ийн гол хурал болох KubeCon + CloudNativeCon Europe 2020 виртуаль байсан. Гэсэн хэдий ч форматын ийм өөрчлөлт нь бидний удаан хугацаанд төлөвлөсөн “Явах уу? Баш! Shell-оператортой танилцаарай” сэдэвт манай Нээлттэй эхийн төсөлд зориулагдсан болно
Энэхүү ярианаас санаа авсан энэхүү нийтлэл нь Kubernetes-д оператор үүсгэх үйл явцыг хялбарчлах аргыг танилцуулж, shell-operator ашиглан хамгийн бага хүчин чармайлтаар өөрийгөө хэрхэн бүтээхийг харуулж байна.
Танилцуулж байна
Flant-д бид бүх зүйлийг байнга оновчтой болгож, автоматжуулдаг. Өнөөдөр бид өөр нэг сэтгэл хөдөлгөм ойлголтын талаар ярих болно. Уулзах: үүлд суурилсан бүрхүүлийн скрипт!
Гэсэн хэдий ч, энэ бүхэн тохиолддог нөхцөл байдлаас эхэлье: Кубернетес.
Kubernetes API болон хянагч
Kubernetes дахь API нь объект тус бүрийн лавлах бүхий нэг төрлийн файлын сервер хэлбэрээр илэрхийлэгдэж болно. Энэ сервер дээрх объектууд (нөөцүүд) YAML файлуудаар илэрхийлэгддэг. Нэмж дурдахад сервер нь гурван зүйлийг хийх боломжийг олгодог үндсэн API-тай:
- авах нөөцийг төрөл, нэрээр нь;
- өөрчлөх нөөц (энэ тохиолдолд сервер нь зөвхөн "зөв" объектуудыг хадгалдаг - бүх буруу үүсгэгдсэн эсвэл бусад лавлахад зориулагдсан объектуудыг устгадаг);
- мөр нөөцийн хувьд (энэ тохиолдолд хэрэглэгч одоогийн/шинэчилсэн хувилбарыг шууд хүлээн авдаг).
Тиймээс, Кубернетес нь гурван үндсэн аргаар (тиймээ, үнэндээ бусад байдаг, гэхдээ бид тэдгээрийг одоохондоо орхих болно) нэг төрлийн файлын сервер (YAML манифестийн хувьд) үүрэг гүйцэтгэдэг.
Асуудал нь сервер зөвхөн мэдээллийг хадгалах боломжтой юм. Үүнийг ажиллуулахын тулд танд хэрэгтэй хянагч - Кубернетес дэлхийн хоёр дахь хамгийн чухал, үндсэн ойлголт.
Хоёр үндсэн төрлийн хянагч байдаг. Эхнийх нь Кубернетесээс мэдээлэл авч, үүрлэсэн логикийн дагуу боловсруулж, K8s руу буцаадаг. Хоёр дахь нь Кубернетесээс мэдээлэл авдаг боловч эхний төрлөөс ялгаатай нь зарим гадаад нөөцийн төлөвийг өөрчилдөг.
Kubernetes-д байршуулалтыг бий болгох үйл явцыг нарийвчлан авч үзье.
- Байршуулах хянагч (оруулсан
kube-controller-manager
) нь Deployment-ийн талаарх мэдээллийг хүлээн авч, ReplicaSet үүсгэнэ. - ReplicaSet нь энэ мэдээлэл дээр үндэслэн хоёр хуулбар (хоёр pods) үүсгэдэг боловч эдгээр подкуудыг хараахан төлөвлөөгүй байна.
- Хуваарьлагч нь хонхорцогуудын хуваарь гаргаж, тэдгээрийн YAML-д зангилааны мэдээллийг нэмдэг.
- Кубелец гадаад нөөцөд өөрчлөлт оруулдаг (Докер гэж хэлнэ).
Дараа нь энэ бүх дараалал урвуу дарааллаар давтагдана: kubelet нь савыг шалгаж, подын статусыг тооцоолж, буцааж илгээдэг. ReplicaSet хянагч нь статусыг хүлээн авч, хуулбарын багцын төлөвийг шинэчилдэг. Байршуулах хянагчтай ижил зүйл тохиолдож, хэрэглэгч эцэст нь шинэчлэгдсэн (одоогийн) статусыг авдаг.
Бүрхүүлийн оператор
Kubernetes нь янз бүрийн хянагч нарын хамтарсан ажилд суурилдаг болох нь харагдаж байна (Кубернетесийн операторууд бас хянагч юм). Хамгийн бага хүчин чармайлтаар өөрийн операторыг хэрхэн бий болгох вэ гэсэн асуулт гарч ирнэ. Энд бидний боловсруулсан нэг нь аврах ажилд ирдэг
Энгийн жишээ: нууцыг хуулбарлах
Энгийн жишээг харцгаая.
Бидэнд Кубернетес кластер байна гэж бодъё. Энэ нь нэрийн орон зайтай default
ямар нэг нууцтай mysecret
. Нэмж дурдахад кластерт өөр нэрийн орон зай байдаг. Тэдний зарим нь тусгай шошготой байдаг. Бидний зорилго бол Secret-ийг шошготой нэрийн талбарт хуулах явдал юм.
Кластерт шинэ нэрийн орон зай гарч ирэх ба тэдгээрийн зарим нь ийм шошготой байж болох тул даалгавар нь төвөгтэй байдаг. Нөгөө талаас шошгыг устгах үед Нууцыг мөн устгах ёстой. Нэмж дурдахад нууц нь өөрөө өөрчлөгдөж болно: энэ тохиолдолд шинэ нууцыг шошготой бүх нэрийн талбарт хуулах ёстой. Хэрэв ямар нэгэн нэрийн талбарт нууц санамсаргүйгээр устгагдсан бол манай оператор үүнийг даруй сэргээх хэрэгтэй.
Даалгавраа томъёолсон тул shell-оператор ашиглан үүнийг хэрэгжүүлж эхлэх цаг болжээ. Гэхдээ эхлээд бүрхүүлийн операторын талаар хэдэн үг хэлэх нь зүйтэй болов уу.
Бүрхүүлийн оператор хэрхэн ажилладаг
Kubernetes дахь бусад ажлын ачааллын нэгэн адил shell-operator нь өөрийн pod дээр ажилладаг. Лавлах доторх энэ хэсэгт /hooks
гүйцэтгэх боломжтой файлууд хадгалагдана. Эдгээр нь Bash, Python, Ruby гэх мэт скриптүүд байж болно. Бид ийм гүйцэтгэгдэх файлуудыг дэгээ гэж нэрлэдэг (хуукууд).
Shell-оператор нь Kubernetes арга хэмжээнд бүртгүүлж, бидэнд хэрэгтэй үйл явдлын хариуд эдгээр дэгээг ажиллуулдаг.
Бүрхүүлийн оператор аль дэгээ хэзээ ажиллуулахаа яаж мэдэх вэ? Гол нь дэгээ бүр хоёр үе шаттай байдаг. Эхлүүлэх үед бүрхүүлийн оператор бүх дэгээг аргументаар ажиллуулдаг --config
Энэ бол тохиргооны үе шат юм. Үүний дараа дэгээг ердийн аргаар эхлүүлдэг - тэдгээрт холбогдсон үйл явдлын хариуд. Сүүлчийн тохиолдолд дэгээ нь холбох контекстийг хүлээн авдаг (холбох контекст) - JSON форматын өгөгдөл, бид доор дэлгэрэнгүй ярих болно.
Баш дээр оператор хийх
Одоо бид хэрэгжүүлэхэд бэлэн байна. Үүнийг хийхийн тулд бид хоёр функц бичих хэрэгтэй (дашрамд хэлэхэд бид зөвлөж байна Номын сан
- эхнийх нь тохиргооны үе шатанд шаардлагатай - энэ нь холбох контекстийг харуулдаг;
- хоёр дахь нь дэгээний үндсэн логикийг агуулдаг.
#!/bin/bash
source /shell_lib.sh
function __config__() {
cat << EOF
configVersion: v1
# BINDING CONFIGURATION
EOF
}
function __main__() {
# THE LOGIC
}
hook::run "$@"
Дараагийн алхам бол бидэнд ямар объект хэрэгтэйг шийдэх явдал юм. Манай тохиолдолд бид дараахь зүйлийг хянах хэрэгтэй.
- өөрчлөлтийн эх сурвалжийн нууц;
- кластер дахь бүх нэрийн орон зай, ингэснээр та аль нь шошго хавсаргасан болохыг мэдэх болно;
- зорилтот нууцууд нь бүгд эх сурвалжтай синхрончлогдсон эсэхийг баталгаажуулах.
Нууц эх сурвалжид бүртгүүлнэ үү
Үүнийг холбох тохиргоо нь маш энгийн. Бид нууцыг нэрээр нь сонирхож байгаагаа илэрхийлж байна mysecret
нэрийн орон зайд default
:
function __config__() {
cat << EOF
configVersion: v1
kubernetes:
- name: src_secret
apiVersion: v1
kind: Secret
nameSelector:
matchNames:
- mysecret
namespace:
nameSelector:
matchNames: ["default"]
group: main
EOF
Үүний үр дүнд эх сурвалжийн нууц өөрчлөгдөх үед дэгээ ажиллах болно (src_secret
) болон дараах заавал дагаж мөрдөх контекстийг хүлээн авна уу:
Таны харж байгаагаар энэ нь нэр болон объектыг бүхэлд нь агуулна.
Нэрийн орон зайг бүртгэж байна
Одоо та нэрийн орон зайд бүртгүүлэх хэрэгтэй. Үүнийг хийхийн тулд бид дараах холболтын тохиргоог зааж өгнө.
- name: namespaces
group: main
apiVersion: v1
kind: Namespace
jqFilter: |
{
namespace: .metadata.name,
hasLabel: (
.metadata.labels // {} |
contains({"secret": "yes"})
)
}
group: main
keepFullObjectsInMemory: false
Таны харж байгаагаар тохиргоонд нэртэй шинэ талбар гарч ирэв jqFilter. Нэрнээс нь харахад, jqFilter
бүх шаардлагагүй мэдээллийг шүүж, бидний сонирхсон талбар бүхий шинэ JSON объект үүсгэдэг. Ижил төстэй тохиргоотой дэгээ нь дараах контекстийг хүлээн авна.
Энэ нь массив агуулсан filterResults
кластер дахь нэрийн талбар бүрийн хувьд. Булийн хувьсагч hasLabel
өгөгдсөн нэрийн талбарт шошго хавсаргасан эсэхийг заана. Сонгогч keepFullObjectsInMemory: false
бүрэн объектуудыг санах ойд хадгалах шаардлагагүй гэдгийг харуулж байна.
Зорилтот нууцыг хянах
Бид тэмдэглэгээ бүхий бүх нууцыг захиалдаг managed-secret: "yes"
(эдгээр бол бидний зорилго dst_secrets
):
- name: dst_secrets
apiVersion: v1
kind: Secret
labelSelector:
matchLabels:
managed-secret: "yes"
jqFilter: |
{
"namespace":
.metadata.namespace,
"resourceVersion":
.metadata.annotations.resourceVersion
}
group: main
keepFullObjectsInMemory: false
Энэ тохиолдолд jqFilter
нэрийн орон зай болон параметрээс бусад бүх мэдээллийг шүүдэг resourceVersion
. Сүүлчийн параметрийг нууцыг үүсгэх үед тэмдэглэгээнд шилжүүлсэн: энэ нь нууцын хувилбаруудыг харьцуулах, тэдгээрийг шинэчлэн хадгалах боломжийг олгодог.
Ийм байдлаар тохируулсан дэгээ нь гүйцэтгэсэн үед дээр дурдсан гурван холбох контекстийг хүлээн авах болно. Тэдгээрийг нэг төрлийн агшин зуурын зураг гэж үзэж болно (Хормын хувилбар) бөөгнөрөл.
Энэ бүх мэдээлэлд үндэслэн үндсэн алгоритмыг боловсруулж болно. Энэ нь бүх нэрийн орон зайд давтагддаг бөгөөд:
- Хэрэв
hasLabel
асуудалtrue
одоогийн нэрийн орон зайд:- дэлхийн нууцыг орон нутгийн нууцтай харьцуулж:
- хэрэв тэдгээр нь ижил байвал энэ нь юу ч хийхгүй;
- хэрэв тэдгээр нь ялгаатай бол - гүйцэтгэнэ
kubectl replace
буюуcreate
;
- дэлхийн нууцыг орон нутгийн нууцтай харьцуулж:
- Хэрэв
hasLabel
асуудалfalse
одоогийн нэрийн орон зайд:- Нууц нь өгөгдсөн нэрийн талбарт байхгүй эсэхийг шалгана:
- Хэрэв дотоод нууц байгаа бол үүнийг ашиглан устгана уу
kubectl delete
; - хэрэв орон нутгийн нууц илрээгүй бол юу ч хийхгүй.
- Хэрэв дотоод нууц байгаа бол үүнийг ашиглан устгана уу
- Нууц нь өгөгдсөн нэрийн талбарт байхгүй эсэхийг шалгана:
Ингэж бид 35 мөр YAML тохиргоо болон ижил хэмжээний Bash кодыг ашиглан энгийн Kubernetes хянагч үүсгэж чадсан юм! Бүрхүүлийн операторын ажил бол тэдгээрийг хооронд нь холбох явдал юм.
Гэсэн хэдий ч нууцыг хуулбарлах нь уг хэрэгслийн хэрэглээний цорын ганц талбар биш юм. Түүний ямар чадвартайг харуулах өөр хэдэн жишээ энд байна.
Жишээ 1: ConfigMap-д өөрчлөлт оруулж байна
Гурван хонхорцогоос бүрдэх Deployment-ийг харцгаая. Подууд зарим тохиргоог хадгалахын тулд ConfigMap ашигладаг. Подуудыг эхлүүлэх үед ConfigMap тодорхой төлөвт байсан (үүнийг v.1 гэж нэрлэе). Үүний дагуу бүх pods ConfigMap-ийн энэ хувилбарыг ашигладаг.
Одоо ConfigMap өөрчлөгдсөн гэж үзье (v.2). Гэсэн хэдий ч, pods ConfigMap (v.1)-ийн өмнөх хувилбарыг ашиглах болно:
Би тэднийг шинэ ConfigMap (v.2) руу хэрхэн шилжүүлэх вэ? Хариулт нь энгийн: загвар ашиглах. Хэсэгт шалгах нийлбэрийн тэмдэглэгээ нэмье template
Байршуулах тохиргоо:
Үүний үр дүнд энэ хяналтын нийлбэр нь бүх pods-д бүртгэгдэх бөгөөд энэ нь Deployment-тэй ижил байх болно. Одоо та ConfigMap өөрчлөгдөх үед тэмдэглэгээг шинэчлэх хэрэгтэй. Мөн бүрхүүлийн оператор энэ тохиолдолд хэрэг болно. Таны хийх ёстой зүйл бол програм юм ConfigMap-д бүртгүүлж шалгах нийлбэрийг шинэчлэх дэгээ.
Хэрэв хэрэглэгч ConfigMap-д өөрчлөлт хийвэл бүрхүүлийн оператор үүнийг анзаарч шалгах нийлбэрийг дахин тооцоолно. Үүний дараа Кубернетесийн ид шид гарч ирэх болно: найрал хөгжимчин подыг алж, шинийг бүтээж, түүнийг болохыг хүлээнэ. Ready
, дараагийнх руу шилжинэ. Үүний үр дүнд Deployment нь синхрончлогдож, ConfigMap-ийн шинэ хувилбар руу шилжих болно.
Жишээ 2: Тусгай нөөцийн тодорхойлолттой ажиллах
Таны мэдэж байгаагаар Kubernetes нь танд тусгай төрлийн объект үүсгэх боломжийг олгодог. Жишээлбэл, та төрлийг үүсгэж болно MysqlDatabase
. Энэ төрөл нь хоёр мета өгөгдлийн параметртэй гэж үзье: name
и namespace.
apiVersion: example.com/v1alpha1
kind: MysqlDatabase
metadata:
name: foo
namespace: bar
Бидэнд MySQL мэдээллийн санг үүсгэж болох өөр өөр нэрийн орон зай бүхий Kubernetes кластер бий. Энэ тохиолдолд бүрхүүлийн операторыг нөөцийг хянахад ашиглаж болно MysqlDatabase
, тэдгээрийг MySQL сервертэй холбож, кластерын хүссэн болон ажиглагдсан төлөвүүдийг синхрончлох.
Жишээ 3: Кластер сүлжээний хяналт
Таны мэдэж байгаагаар ping ашиглах нь сүлжээг хянах хамгийн энгийн арга юм. Энэ жишээнд бид shell-operator ашиглан ийм хяналтыг хэрхэн хэрэгжүүлэхийг харуулах болно.
Юуны өмнө та зангилааг захиалах хэрэгтэй болно. Бүрхүүлийн оператор нь зангилаа бүрийн нэр, IP хаягийг шаарддаг. Тэдгээрийн тусламжтайгаар тэрээр эдгээр зангилааг ping хийх болно.
configVersion: v1
kubernetes:
- name: nodes
apiVersion: v1
kind: Node
jqFilter: |
{
name: .metadata.name,
ip: (
.status.addresses[] |
select(.type == "InternalIP") |
.address
)
}
group: main
keepFullObjectsInMemory: false
executeHookOnEvent: []
schedule:
- name: every_minute
group: main
crontab: "* * * * *"
Үзүүлэлт executeHookOnEvent: []
аливаа үйл явдлын хариуд (өөрөөр хэлбэл зангилааг өөрчлөх, нэмэх, устгахад хариу үйлдэл үзүүлэх) дэгээ ажиллахаас сэргийлдэг. Гэсэн хэдий ч тэр гүйх болно (мөн зангилааны жагсаалтыг шинэчлэх) Төлөвлөсөн - талбайн заасны дагуу минут тутамд schedule
.
Одоо асуулт гарч ирнэ, бид пакет алдагдах гэх мэт асуудлын талаар яг яаж мэдэх вэ? Кодыг харцгаая:
function __main__() {
for i in $(seq 0 "$(context::jq -r '(.snapshots.nodes | length) - 1')"); do
node_name="$(context::jq -r '.snapshots.nodes['"$i"'].filterResult.name')"
node_ip="$(context::jq -r '.snapshots.nodes['"$i"'].filterResult.ip')"
packets_lost=0
if ! ping -c 1 "$node_ip" -t 1 ; then
packets_lost=1
fi
cat >> "$METRICS_PATH" <<END
{
"name": "node_packets_lost",
"add": $packets_lost,
"labels": {
"node": "$node_name"
}
}
END
done
}
Бид зангилааны жагсаалтыг давтаж, нэр, IP хаягийг нь авч, ping хийж, үр дүнг Prometheus руу илгээдэг. Shell-оператор нь хэмжигдэхүүнийг Prometheus руу экспортлох боломжтой, тэдгээрийг орчны хувьсагчд заасан замын дагуу байрлах файлд хадгалах $METRICS_PATH
.
Дарааллын механизм
Бүрхүүлийн операторт суурилуулсан өөр нэг чухал механизмыг тайлбарлахгүйгээр энэ нийтлэл бүрэн бус байх болно. Энэ нь кластер дахь үйл явдлын хариуд ямар нэгэн төрлийн дэгээ гүйцэтгэдэг гэж төсөөлөөд үз дээ.
- Кластерт нэгэн зэрэг ямар нэг зүйл тохиолдвол яах вэ? дахиад нэг үйл явдал?
- Shell-operator нь дэгээний өөр жишээг ажиллуулах уу?
- Хэрэв кластерт нэгэн зэрэг таван үйл явдал тохиолдвол яах вэ?
- Бүрхүүлийн оператор тэдгээрийг зэрэгцүүлэн боловсруулах уу?
- Санах ой, CPU зэрэг зарцуулсан нөөцийн талаар юу хэлэх вэ?
Аз болоход shell-operator нь дарааллын механизмтай. Бүх үйл явдлыг дараалалд оруулж, дараалан боловсруулдаг.
Үүнийг жишээгээр тайлбарлая. Бид хоёр дэгээтэй гэж бодъё. Эхний үйл явдал нь эхний дэгээ рүү явдаг. Түүний боловсруулалт дууссаны дараа дараалал урагшилна. Дараагийн гурван үйл явдлыг хоёр дахь дэгээ рүү чиглүүлэв - тэдгээрийг дарааллаас гаргаж, "багц" болгон оруулна. Тэр бол hook нь олон тооны үйл явдлыг хүлээн авдаг - эсвэл илүү нарийвчлалтай, холбох контекстүүдийн массив.
Мөн эдгээр үйл явдлуудыг нэг том болгон нэгтгэж болно. Параметр нь үүнийг хариуцдаг group
холбох тохиргоонд.
Та ямар ч тооны дараалал/дэгээ болон тэдгээрийн янз бүрийн хослолыг үүсгэж болно. Жишээлбэл, нэг дараалал нь хоёр дэгээгээр ажиллах боломжтой, эсвэл эсрэгээр.
Таны хийх ёстой зүйл бол талбарыг зохих ёсоор тохируулах явдал юм queue
холбох тохиргоонд. Хэрэв дарааллын нэрийг заагаагүй бол дэгээ нь үндсэн дараалал дээр ажилладаг (default
). Энэхүү дарааллын механизм нь дэгээтэй ажиллахдаа нөөцийн менежментийн бүх асуудлыг бүрэн шийдвэрлэх боломжийг олгодог.
дүгнэлт
Бид бүрхүүл-оператор гэж юу болохыг тайлбарлаж, Кубернетес операторуудыг хурдан бөгөөд хүчин чармайлтгүйгээр бүтээхэд хэрхэн ашиглаж болохыг харуулсан бөгөөд түүний хэрэглээний хэд хэдэн жишээг өгсөн.
Бүрхүүлийн операторын талаархи дэлгэрэнгүй мэдээлэл, мөн үүнийг хэрхэн ашиглах талаар хурдан зааварчилгааг холбогдох хэсгээс авах боломжтой.
Хэрэв танд таалагдсан бол бид GitHub дээр шинэ дугаарууд/PR/одуудыг үзэхдээ баяртай байх болно.
Видео болон слайд
Тоглолтын видео (~23 минут):
Илтгэлийн танилцуулга:
PS
Мөн манай блог дээрээс уншина уу:
- «
Бүрхүүл-оператор бүхий Kubernetes операторуудыг хялбархан үүсгэх: төслийн жилийн явц "; - «
Бүрхүүлийн операторыг танилцуулж байна: Kubernetes-д оператор үүсгэх нь илүү хялбар болсон "; - «
Kubernetes кластер бэлтгэх нь хялбар бөгөөд тохиромжтой юу? Нэмэлт операторыг зарлаж байна "; - «
Kubernetes-ийг өргөжүүлж, нөхөж байна" (хяналт, видео тайлан) .
Эх сурвалж: www.habr.com