มีบทความในบล็อกของเราพูดถึงแล้ว
ทำไม?
แนวคิดของตัวดำเนินการเชลล์นั้นค่อนข้างง่าย: สมัครรับกิจกรรมจากวัตถุ Kubernetes และเมื่อได้รับเหตุการณ์เหล่านี้ ให้เปิดโปรแกรมภายนอกโดยให้ข้อมูลเกี่ยวกับเหตุการณ์:
ความจำเป็นนี้เกิดขึ้นเมื่อระหว่างการทำงานของคลัสเตอร์ งานเล็กๆ เริ่มปรากฏว่าเราต้องการทำให้เป็นอัตโนมัติในวิธีที่ถูกต้องจริงๆ งานเล็ก ๆ เหล่านี้ทั้งหมดได้รับการแก้ไขโดยใช้สคริปต์ทุบตีแบบง่าย ๆ แม้ว่าอย่างที่คุณทราบจะเป็นการดีกว่าถ้าเขียนตัวดำเนินการใน Golang แน่นอนว่าการลงทุนในการพัฒนาผู้ปฏิบัติงานอย่างเต็มรูปแบบสำหรับงานเล็กๆ แต่ละงานจะไม่มีประสิทธิภาพ
เจ้าหน้าที่ดำเนินการภายใน 15 นาที
มาดูตัวอย่างของสิ่งที่สามารถทำให้เป็นอัตโนมัติในคลัสเตอร์ Kubernetes และวิธีที่ผู้ดำเนินการเชลล์สามารถช่วยได้ ตัวอย่างจะเป็นดังต่อไปนี้: การจำลองข้อมูลลับเพื่อเข้าถึงรีจิสทรีนักเทียบท่า
พ็อดที่ใช้รูปภาพจากรีจิสทรีส่วนตัวจะต้องมีลิงก์ไปยังข้อมูลลับพร้อมข้อมูลสำหรับการเข้าถึงรีจิสทรีในรายการ ต้องสร้างข้อมูลลับนี้ในแต่ละเนมสเปซก่อนสร้างพ็อด ซึ่งสามารถทำได้ด้วยตนเอง แต่หากเราตั้งค่าสภาพแวดล้อมแบบไดนามิก เนมสเปซสำหรับแอปพลิเคชันหนึ่งจะมีจำนวนมาก และหากไม่มีแอปพลิเคชัน 2-3 รายการ... จำนวนข้อมูลลับจะมีขนาดใหญ่มาก และอีกอย่างเกี่ยวกับความลับ: ฉันต้องการเปลี่ยนคีย์เพื่อเข้าถึงรีจิสทรีเป็นครั้งคราว ในท้ายที่สุด, การดำเนินการด้วยตนเอง เป็นวิธีแก้ปัญหา ไม่ได้ผลอย่างสมบูรณ์ — เราจำเป็นต้องสร้างและอัปเดตความลับโดยอัตโนมัติ
ระบบอัตโนมัติที่เรียบง่าย
มาเขียนเชลล์สคริปต์ที่ทำงานทุกๆ N วินาทีและตรวจสอบเนมสเปซว่ามีความลับอยู่หรือไม่ และหากไม่มีความลับ ก็จะถูกสร้างขึ้น ข้อดีของโซลูชันนี้คือ ดูเหมือนเชลล์สคริปต์ใน cron ซึ่งเป็นแนวทางที่คลาสสิกและเข้าใจง่ายสำหรับทุกคน ข้อเสียคือในช่วงเวลาระหว่างการเปิดตัว คุณสามารถสร้างเนมสเปซใหม่ได้ และในบางครั้งมันจะคงอยู่โดยไม่มีความลับ ซึ่งจะนำไปสู่ข้อผิดพลาดในการเปิดพ็อด
ระบบอัตโนมัติพร้อมตัวดำเนินการเชลล์
เพื่อให้สคริปต์ของเราทำงานได้อย่างถูกต้อง การเปิดใช้ cron แบบคลาสสิกจะต้องแทนที่ด้วยการเปิดตัวเมื่อมีการเพิ่มเนมสเปซ: ในกรณีนี้ คุณสามารถสร้างข้อมูลลับก่อนใช้งานได้ เรามาดูวิธีการนำไปใช้โดยใช้ตัวดำเนินการเชลล์
ก่อนอื่นเรามาดูสคริปต์กันก่อน สคริปต์ในเงื่อนไขของตัวดำเนินการเชลล์เรียกว่า hooks ตะขอทุกอันเมื่อวิ่งพร้อมธง --config
แจ้งให้ผู้ดำเนินการเชลล์ทราบถึงการเชื่อมโยง เช่น ว่าควรจะเปิดตัวในงานอะไร ในกรณีของเราเราจะใช้ onKubernetesEvent
:
#!/bin/bash
if [[ $1 == "--config" ]] ; then
cat <<EOF
{
"onKubernetesEvent": [
{ "kind": "namespace",
"event":["add"]
}
]}
EOF
fi
มีการอธิบายไว้ที่นี่ว่าเราสนใจที่จะเพิ่มกิจกรรม (add
) วัตถุประเภท namespace
.
ตอนนี้คุณต้องเพิ่มโค้ดที่จะดำเนินการเมื่อมีเหตุการณ์เกิดขึ้น:
#!/bin/bash
if [[ $1 == "--config" ]] ; then
# конфигурация
cat <<EOF
{
"onKubernetesEvent": [
{ "kind": "namespace",
"event":["add"]
}
]}
EOF
else
# реакция:
# узнать, какой namespace появился
createdNamespace=$(jq -r '.[0].resourceName' $BINDING_CONTEXT_PATH)
# создать в нём нужный секрет
kubectl create -n ${createdNamespace} -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
...
data:
...
EOF
fi
ยอดเยี่ยม! ผลลัพธ์ที่ได้คือสคริปต์เล็กๆ ที่สวยงาม หากต้องการ “ฟื้นฟู” มัน เหลืออีกสองขั้นตอน: เตรียมอิมเมจและเปิดใช้งานในคลัสเตอร์
การเตรียมภาพด้วยเบ็ด
หากดูที่สคริปต์จะเห็นว่ามีการใช้คำสั่งต่างๆ kubectl
и jq
. ซึ่งหมายความว่าอิมเมจจะต้องมีสิ่งต่อไปนี้: hook ของเรา ตัวดำเนินการเชลล์ที่จะตรวจสอบเหตุการณ์และรัน hook และคำสั่งที่ใช้โดย hook (kubectl และ jq) Hub.docker.com มีอิมเมจสำเร็จรูปซึ่งมีแพ็คเกจตัวดำเนินการเชลล์, kubectl และ jq อยู่แล้ว สิ่งที่เหลืออยู่คือการเพิ่มเบ็ดง่ายๆ Dockerfile
:
$ cat Dockerfile
FROM flant/shell-operator:v1.0.0-beta.1-alpine3.9
ADD namespace-hook.sh /hooks
$ docker build -t registry.example.com/my-operator:v1 .
$ docker push registry.example.com/my-operator:v1
ทำงานเป็นคลัสเตอร์
มาดูที่ hook อีกครั้ง และคราวนี้จดบันทึกว่าการกระทำใดบ้างและใช้กับอ็อบเจ็กต์ใดบ้างที่ทำในคลัสเตอร์:
- สมัครรับกิจกรรมการสร้างเนมสเปซ
- สร้างความลับในเนมสเปซอื่นที่ไม่ใช่ที่ที่มันถูกเรียกใช้
ปรากฎว่าพ็อดที่อิมเมจของเราจะเปิดตัวจะต้องมีสิทธิ์ในการดำเนินการเหล่านี้ ซึ่งสามารถทำได้โดยการสร้าง ServiceAccount ของคุณเอง การอนุญาตจะต้องทำในรูปแบบของ ClusterRole และ ClusterRoleBinding เนื่องจาก เราสนใจวัตถุจากทั้งคลัสเตอร์
คำอธิบายสุดท้ายใน YAML จะมีลักษณะดังนี้:
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: monitor-namespaces-acc
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: monitor-namespaces
rules:
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["get", "watch", "list"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "create", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: monitor-namespaces
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: monitor-namespaces
subjects:
- kind: ServiceAccount
name: monitor-namespaces-acc
namespace: example-monitor-namespaces
คุณสามารถเปิดอิมเมจที่ประกอบขึ้นเป็นการปรับใช้แบบธรรมดา:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-operator
spec:
template:
spec:
containers:
- name: my-operator
image: registry.example.com/my-operator:v1
serviceAccountName: monitor-namespaces-acc
เพื่อความสะดวก เนมสเปซที่แยกต่างหากจะถูกสร้างขึ้นโดยที่ตัวดำเนินการเชลล์จะถูกเรียกใช้และรายการที่สร้างขึ้นจะถูกนำไปใช้:
$ kubectl create ns example-monitor-namespaces
$ kubectl -n example-monitor-namespaces apply -f rbac.yaml
$ kubectl -n example-monitor-namespaces apply -f deployment.yaml
นั่นคือทั้งหมด: ตัวดำเนินการเชลล์จะเริ่ม สมัครรับกิจกรรมการสร้างเนมสเปซ และรันฮุกเมื่อจำเป็น
ดังนั้น เชลล์สคริปต์ธรรมดากลายเป็นโอเปอเรเตอร์จริงสำหรับ Kubernetes และทำงานเป็นส่วนหนึ่งของคลัสเตอร์ และทั้งหมดนี้ไม่มีกระบวนการที่ซับซ้อนในการพัฒนาตัวดำเนินการใน Golang:
มีภาพประกอบเรื่องนี้อีกเรื่อง...
เราจะเปิดเผยความหมายของมันอย่างละเอียดในสิ่งพิมพ์ต่อไปนี้
กรอง
การติดตามวัตถุเป็นสิ่งที่ดี แต่มักจำเป็นต้องตอบสนอง การเปลี่ยนแปลงคุณสมบัติของวัตถุบางอย่างตัวอย่างเช่น เพื่อเปลี่ยนจำนวนเรพลิกาในการปรับใช้หรือเปลี่ยนเลเบลอ็อบเจ็กต์
เมื่อเหตุการณ์มาถึง ตัวดำเนินการเชลล์จะได้รับไฟล์ Manifest JSON ของอ็อบเจ็กต์ เราสามารถเลือกคุณสมบัติที่เราสนใจใน JSON นี้และเรียกใช้ฮุค เท่านั้น เมื่อพวกเขาเปลี่ยนไป มีสนามสำหรับสิ่งนี้ jqFilter
โดยคุณจะต้องระบุนิพจน์ jq ที่จะใช้กับไฟล์ Manifest JSON
ตัวอย่างเช่น หากต้องการตอบสนองต่อการเปลี่ยนแปลงในป้ายกำกับสำหรับออบเจ็กต์การทำให้ใช้งานได้ คุณจะต้องกรองฟิลด์ labels
ออกจากสนาม metadata
. การกำหนดค่าจะเป็นดังนี้:
cat <<EOF
{
"onKubernetesEvent": [
{ "kind": "deployment",
"event":["update"],
"jqFilter": ".metadata.labels"
}
]}
EOF
นิพจน์ jqFilter นี้จะเปลี่ยนรายการ JSON แบบยาวของการปรับใช้ให้เป็น JSON แบบสั้นพร้อมป้ายกำกับ:
ตัวดำเนินการเชลล์จะรันฮุกเฉพาะเมื่อ JSON แบบสั้นนี้เปลี่ยนแปลง และการเปลี่ยนแปลงคุณสมบัติอื่น ๆ จะถูกละเว้น
บริบทการเปิดตัว Hook
การกำหนดค่า hook ช่วยให้คุณระบุตัวเลือกต่างๆ สำหรับเหตุการณ์ได้ เช่น 2 ตัวเลือกสำหรับเหตุการณ์จาก Kubernetes และ 2 กำหนดการ:
{"onKubernetesEvent":[
{"name":"OnCreatePod",
"kind": "pod",
"event":["add"]
},
{"name":"OnModifiedNamespace",
"kind": "namespace",
"event":["update"],
"jqFilter": ".metadata.labels"
}
],
"schedule": [
{ "name":"every 10 min",
"crontab":"* */10 * * * *"
}, {"name":"on Mondays at 12:10",
"crontab": "* 10 12 * * 1"
]}
การพูดนอกเรื่องเล็กน้อย: ใช่ ตัวดำเนินการเชลล์รองรับ ใช้งานสคริปต์สไตล์ crontab. รายละเอียดเพิ่มเติมสามารถพบได้ใน
เพื่อแยกความแตกต่างว่าทำไม hook ถึงถูกเรียกใช้ ตัวดำเนินการเชลล์จะสร้างไฟล์ชั่วคราวและส่งพาธไปยังไฟล์นั้นในตัวแปรไปยัง hook BINDING_CONTEXT_TYPE
. ไฟล์นี้มีคำอธิบาย JSON ของเหตุผลในการเรียกใช้ฮุค ตัวอย่างเช่น ทุก ๆ 10 นาที hook จะทำงานโดยมีเนื้อหาต่อไปนี้:
[{ "binding": "every 10 min"}]
... และในวันจันทร์จะเริ่มด้วยสิ่งนี้:
[{ "binding": "every 10 min"}, { "binding": "on Mondays at 12:10"}]
สำหรับ onKubernetesEvent
จะมีทริกเกอร์ JSON มากขึ้นเพราะว่า มันมีคำอธิบายของวัตถุ:
[
{
"binding": "onCreatePod",
"resourceEvent": "add",
"resourceKind": "pod",
"resourceName": "foo",
"resourceNamespace": "bar"
}
]
เนื้อหาของฟิลด์สามารถเข้าใจได้จากชื่อและสามารถอ่านรายละเอียดเพิ่มเติมได้ resourceName
การใช้ jq ได้แสดงให้เห็นแล้วใน hook ที่จำลองความลับ:
jq -r '.[0].resourceName' $BINDING_CONTEXT_PATH
คุณสามารถรับช่องอื่นๆ ได้ในลักษณะเดียวกัน
ทำอะไรต่อไป
ในพื้นที่เก็บข้อมูลโครงการใน
มีการรองรับการรวบรวมตัววัดโดยใช้ Prometheus - ตัววัดที่มีอยู่ได้อธิบายไว้ในส่วนนี้
ดังที่คุณอาจเดาได้ Shell-Operator นั้นเขียนด้วยภาษา Go และเผยแพร่ภายใต้ลิขสิทธิ์ Open Source (Apache 2.0) เราจะขอบคุณสำหรับความช่วยเหลือในการพัฒนา
เมื่อปิดม่านแห่งความลับแล้ว เราจะแจ้งให้คุณทราบว่าผู้ปฏิบัติงานเชลล์นั้นคือ เล็ก ส่วนหนึ่งของระบบของเราที่สามารถทำให้ส่วนเสริมที่ติดตั้งในคลัสเตอร์ Kubernetes เป็นปัจจุบันและดำเนินการอัตโนมัติต่างๆ อ่านเพิ่มเติมเกี่ยวกับระบบนี้
เรามีแผนที่จะเปิดส่วนที่เหลือของระบบนี้: ตัวดำเนินการ addon และคอลเลกชั่น hooks และโมดูลของเรา ยังไงก็ตาม addon-operator ก็มีอยู่แล้ว
คอยติดตาม!
PS
อ่านเพิ่มเติมในบล็อกของเรา:
- «
ตัวดำเนินการสำหรับ Kubernetes: วิธีเรียกใช้แอปพลิเคชันแบบเก็บสถานะ "; - «
การเขียนโอเปอเรเตอร์สำหรับ Kubernetes ใน Golang "; - «
ขอแนะนำปลั๊กอินใหม่สำหรับ Grafana - แผง Statusmap "; - «
ขอแนะนำ Loghouse - ระบบโอเพ่นซอร์สสำหรับการทำงานกับบันทึกใน Kubernetes "; - «
เราขอนำเสนอ dapp อย่างเป็นทางการ - ยูทิลิตี้ DevOps สำหรับการบำรุงรักษา CI/CD '
ที่มา: will.com