From: xinhuili Date: Wed, 14 Aug 2019 06:29:20 +0000 (+0800) Subject: Customise k8s-sidecar X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F04%2F1404%2F1;p=iec%2Fxconnect.git Customise k8s-sidecar This patch is to enable customization in k8s-sidecar. Signed-off-by: XINHUI LI Change-Id: I8d856b00209e40bd5fb7a6e54ad99655768e6395 --- diff --git a/src/k8s-sidecar/.gitignore b/src/k8s-sidecar/.gitignore new file mode 100644 index 0000000..249963d --- /dev/null +++ b/src/k8s-sidecar/.gitignore @@ -0,0 +1,2 @@ +*.iml +.idea/ \ No newline at end of file diff --git a/src/k8s-sidecar/Dockerfile b/src/k8s-sidecar/Dockerfile new file mode 100644 index 0000000..76794d8 --- /dev/null +++ b/src/k8s-sidecar/Dockerfile @@ -0,0 +1,6 @@ +FROM python:3.6-slim-stretch +RUN pip install kubernetes==6.0.0 +COPY sidecar/sidecar.py /app/ +ENV PYTHONUNBUFFERED=1 +WORKDIR /app/ +CMD [ "python", "-u", "/app/sidecar.py" ] diff --git a/src/k8s-sidecar/LICENSE b/src/k8s-sidecar/LICENSE new file mode 100644 index 0000000..51bcf2b --- /dev/null +++ b/src/k8s-sidecar/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Kiwigrid GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/k8s-sidecar/README.md b/src/k8s-sidecar/README.md new file mode 100644 index 0000000..dcb5202 --- /dev/null +++ b/src/k8s-sidecar/README.md @@ -0,0 +1,37 @@ + +[![Docker Automated build](https://img.shields.io/docker/automated/kiwigrid/k8s-sidecar.svg)](https://hub.docker.com/r/kiwigrid/k8s-sidecar/) +[![Docker Build Status](https://img.shields.io/docker/build/kiwigrid/k8s-sidecar.svg)](https://hub.docker.com/r/kiwigrid/k8s-sidecar/) + +# What? + +This is a docker container intended to run inside a kubernetes cluster to collect config maps with a specified label and store the included files in an local folder. The main target is to be run as a sidecar container to supply an application with information from the cluster. The contained python script is working with the Kubernetes API 1.10 + +# Why? + +Currently (April 2018) there is no simple way to hand files in configmaps to a service and keep them updated during runtime. + +# How? + +Run the container created by this repo together you application in an single pod with a shared volume. Specify which label should be monitored and where the files should be stored. + +# Features + +- Extract files from config maps +- Filter based on label +- Update/Delete on change of configmap + +# Usage + +Example for a simple deployment can be found in `example.yaml`. Depending on the cluster setup you have to grant yourself admin rights first: `kubectl create clusterrolebinding cluster-admin-binding --clusterrole cluster-admin --user $(gcloud config get-value account)` + +## Configuration Environment Variables + +- `LABEL` + - description: Label that should be used for filtering + - required: true + - type: string + +- `FOLDER` + - description: Folder where the files should be placed + - required: true + - type: string diff --git a/src/k8s-sidecar/example.yaml b/src/k8s-sidecar/example.yaml new file mode 100644 index 0000000..8f7b0f7 --- /dev/null +++ b/src/k8s-sidecar/example.yaml @@ -0,0 +1,75 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: sample-deployment + labels: + app: sample +spec: + replicas: 1 + selector: + matchLabels: + app: sample + template: + metadata: + labels: + app: sample + spec: + serviceAccountName: sample-acc + containers: + - name: bash + image: bash:4.4.19 + volumeMounts: + - name: shared-volume + mountPath: /tmp/ + command: ["watch"] + args: ["ls", "/tmp/"] + - name: sidecar + image: kiwigrid/k8s-sidecar:latest + volumeMounts: + - name: shared-volume + mountPath: /tmp/ + env: + - name: LABEL + value: "findme" + - name: FOLDER + value: /tmp/ + volumes: + - name: shared-volume + emptyDir: {} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: sample-configmap + labels: + findme: "yea" +data: + hello.world: |- + Hello World! +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: sample-role +rules: +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "watch", "list"] +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: sample-acc +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: sample-rolebind +roleRef: + kind: ClusterRole + name: cluster-admin + apiGroup: rbac.authorization.k8s.io +subjects: +- kind: ServiceAccount + name: sample-acc + namespace: default diff --git a/src/k8s-sidecar/sidecar/sidecar.py b/src/k8s-sidecar/sidecar/sidecar.py new file mode 100644 index 0000000..fcb186a --- /dev/null +++ b/src/k8s-sidecar/sidecar/sidecar.py @@ -0,0 +1,58 @@ +from kubernetes import client, config, watch +import os +import sys + + +def writeTextToFile(folder, filename, data): + with open(folder +"/"+ filename, 'w') as f: + f.write(data) + f.close() + + +def removeFile(folder, filename): + completeFile = folder +"/"+filename + if os.path.isfile(completeFile): + os.remove(completeFile) + else: + print("Error: %s file not found" % completeFile) + + +def watchForChanges(label, targetFolder): + v1 = client.CoreV1Api() + w = watch.Watch() + for event in w.stream(v1.list_config_map_for_all_namespaces): + if event['object'].metadata.labels is None: + continue + print("Working on configmap %s" % event['object'].metadata.name) + if label in event['object'].metadata.labels.keys(): + print("Configmap with label found") + dataMap=event['object'].data + if dataMap is None: + print("Configmap does not have data.") + continue + eventType = event['type'] + for filename in dataMap.keys(): + print("File in configmap %s %s" % (filename, eventType)) + if (eventType == "ADDED") or (eventType == "MODIFIED"): + writeTextToFile(targetFolder, filename, dataMap[filename]) + else: + removeFile(targetFolder, filename) + + +def main(): + print("Starting config map collector") + label = os.getenv('LABEL') + if label is None: + print("Should have added LABEL as environment variable! Exit") + return -1 + targetFolder = os.getenv('FOLDER') + if targetFolder is None: + print("Should have added FOLDER as environment variable! Exit") + return -1 + config.load_incluster_config() + print("Config for cluster api loaded...") + watchForChanges(label, targetFolder) + + +if __name__ == '__main__': + main()