2020年CNCF中國雲原生調查node
10人將獲贈CNCF商店$100美圓禮券!python
[](https://mp.weixin.qq.com/s?__...你填了嗎?git
問卷連接(https://www.wjx.cn/jq/9714648...)github
做者:Thomas Labarussiasshell
兩年前,咱們向大家展現了一個基於 Falco 的 Kubernetes 響應引擎(Kubernetes Response Engine)。其想法是觸發無 Kubeless 無服務器的函數來刪除受感染的 pod,啓動 Sysdig 捕獲或將事件轉發給 GCP PubSub。見README。json
爲了不維護這個自定義堆棧,咱們與社區一塊兒努力將全部組件集成到Falcosidekick中,並改進用戶體驗。在上一個版本 2.20.0 中,咱們有了最後的部分,將 Kubeless 集成爲原生輸出。更多細節請參見咱們的2020 年回顧。segmentfault
在這篇博文中,咱們將解釋使用 Falco + Falcosidekick + Kubeless 堆棧將你本身的響應引擎集成到 K8s 中的基本概念。api
咱們須要 kubernetes 集羣,至少運行 1.17 版本,並安裝 helm 和 kubectl。bash
跟隨官方快速入門頁面:服務器
export RELEASE=$(curl -s https://api.github.com/repos/kubeless/kubeless/releases/latest | grep tag_name | cut -d '"' -f 4) kubectl create ns kubeless kubectl create -f https://github.com/kubeless/kubeless/releases/download/$RELEASE/kubeless-$RELEASE.yaml
幾秒鐘後,咱們能夠檢查控制器是否啓動並運行:
kubectl get pods -n kubeless NAME READY STATUS RESTARTS AGE kubeless-controller-manager-99459cb67-tb99d 3/3 Running 3 2m34s
首先,咱們將建立命名空間給 Falco 和 Falcosidekick:
kubectl create ns falco
增長 helm 倉庫:
helm repo add falcosecurity https://falcosecurity.github.io/charts
在實際的項目中,你應該使用 helm pull falcosecurity/falco --untar 獲取整個 chart,而後配置 values.yaml。在本教程中,咱們會盡可能簡化操做,直接經過 helm install 命令設置配置:
helm install falco falcosecurity/falco --set falco.jsonOutput=true --set falco.httpOutput.enabled=true --set falco.httpOutput.url=http://falcosidekick:2801 -n falco
你應該獲得這樣的輸出:
NAME: falco LAST DEPLOYED: Thu Jan 14 23:43:46 2021 NAMESPACE: falco STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: Falco agents are spinning up on each node in your cluster. After a few seconds, they are going to start monitoring your containers looking for security issues. No further action should be required.
你能夠看到你的新 Falco pod:
kubectl get pods -n falco NAME READY STATUS RESTARTS AGE falco-ctmzg 1/1 Running 0 111s falco-sfnn8 1/1 Running 0 111s falco-rrg28 1/1 Running 0 111s
參數(--set falco.jsonOutput=true --set falco.httpOutput.enabled=true --set falco.httpOutput.url=http://falcosidekick:2801)在那裏配置事件的格式和Falco將發送事件的URL。因爲Falco和Falcosidekick位於同一個命名空間中,咱們能夠直接使用服務的名稱(Falcosidekick)。
過程是挺同樣的:
helm install falcosidekick falcosecurity/falcosidekick --set config.kubeless.namespace=kubeless --set config.kubeless.function=delete-pod -n falco
你應該獲得這樣的輸出:
NAME: falcosidekick LAST DEPLOYED: Thu Jan 14 23:55:12 2021 NAMESPACE: falco STATUS: deployed REVISION: 1 NOTES: 1. Get the application URL by running these commands: export POD_NAME=$(kubectl get pods --namespace falco -l "app.kubernetes.io/name=falcosidekick,app.kubernetes.io/instance=falcosidekick" -o jsonpath="{.items[0].metadata.name}") kubectl port-forward $POD_NAME 2801:2801 echo "Visit http://127.0.0.1:2801 to use your application"
咱們檢查日誌:
kubectl logs deployment/falcosidekick -n falco 2021/01/14 22:55:31 [INFO] : Enabled Outputs : Kubeless 2021/01/14 22:55:31 [INFO] : Falco Sidekick is up and listening on port 2801
Kubeless 顯示爲 enabled 輸出,一切正常 👍。
簡單說明參數:
就是這樣,咱們真的試圖獲得一個很好的 UX😉。
咱們不會解釋如何編寫或如何工做 Kubeless 函數,請閱讀官方文檔瞭解更多信息。
咱們真正基本的函數將從 Falco 接收事件(經過 Falcosidekick),檢查觸發的規則是否在容器中的終端 Shell(參見規則),從事件字段中提取命名空間和 pod 名稱,並刪除相應的 pod:
from kubernetes import client,config config.load_incluster_config() def delete_pod(event, context): rule = event['data']['rule'] or None output_fields = event['data']['output_fields'] or None if rule and rule == "Terminal shell in container" and output_fields: if output_fields['k8s.ns.name'] and output_fields['k8s.pod.name']: pod = output_fields['k8s.pod.name'] namespace = output_fields['k8s.ns.name'] print (f"Deleting pod \"{pod}\" in namespace \"{namespace}\"") client.CoreV1Api().delete_namespaced_pod(name=pod, namespace=namespace, body=client.V1DeleteOptions())
基本上,這個過程是:
+----------+ +---------------+ +----------+ | Falco +-----------------> Falcosidekick +--------------------> Kubeless | +----^-----+ sends event +---------------+ triggers +-----+----+ | | detects a shell | | | | +----+-------+ deletes | | Powned Pod <----------------------------------------------------------+ +------------+
在部署咱們的函數以前,咱們須要爲它建立一個 ServiceAccount,由於它須要在任何命名空間中刪除 pod 的權限:
cat <<EOF | kubectl apply -n kubeless -f - apiVersion: v1 kind: ServiceAccount metadata: name: falco-pod-delete --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: falco-pod-delete-cluster-role rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "delete"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: falco-pod-delete-cluster-role-binding roleRef: kind: ClusterRole name: falco-pod-delete-cluster-role apiGroup: rbac.authorization.k8s.io subjects: - kind: ServiceAccount name: falco-pod-delete namespace: kubeless EOF
namespace: kubelessetetion.k8s.io serviceaccount/falco-pod-delete created clusterrole.rbac.authorization.k8s.io/falco-pod-delete-cluster-role created clusterrolebinding.rbac.authorization.k8s.io/falco-pod-delete-cluster-role-binding created
只剩下函數自己的安裝:
cat <<EOF | kubectl apply -n kubeless -f - apiVersion: kubeless.io/v1beta1 kind: Function metadata: finalizers: - kubeless.io/function generation: 1 labels: created-by: kubeless function: delete-pod name: delete-pod spec: checksum: sha256:a68bf570ea30e578e392eab18ca70dbece27bce850a8dbef2586eff55c5c7aa0 deps: | kubernetes>=12.0.1 function-content-type: text function: |- from kubernetes import client,config config.load_incluster_config() def delete_pod(event, context): rule = event['data']['rule'] or None output_fields = event['data']['output_fields'] or None if rule and rule == "Terminal shell in container" and output_fields: if output_fields['k8s.ns.name'] and output_fields['k8s.pod.name']: pod = output_fields['k8s.pod.name'] namespace = output_fields['k8s.ns.name'] print (f"Deleting pod \"{pod}\" in namespace \"{namespace}\"") client.CoreV1Api().delete_namespaced_pod(name=pod, namespace=namespace, body=client.V1DeleteOptions()) handler: delete-pod.delete_pod runtime: python3.7 deployment: spec: template: spec: serviceAccountName: falco-pod-delete EOF
function.kubeless.io/delete-pod created
在這裏,過了一下子,咱們有了一個 Kubeless 函數在命名空間 Kubeless 中運行,它能夠由端口 8080 上的服務 delete-pod 觸發:
kubectl get pods -n kubeless NAME READY STATUS RESTARTS AGE kubeless-controller-manager-99459cb67-tb99d 3/3 Running 3 3d14h delete-pod-d6f98f6dd-cw228 1/1 Running 0 2m52s
kubectl get svc -n kubeless NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE delete-pod ClusterIP 10.43.211.201 <none> 8080/TCP 4m38s
咱們從建立一個 pod 開始:
kubectl run alpine -n default --image=alpine --restart='Never' -- sh -c "sleep 600"
kubectl get pods -n default NAME READY STATUS RESTARTS AGE alpine 1/1 Running 0 9s
讓咱們在裏面運行一個shell命令,看看會發生什麼:
kubectl exec -i --tty alpine -n default -- sh -c "uptime" 23:44:25 up 1 day, 19:11, load average: 0.87, 0.77, 0.77
正如預期的那樣,咱們獲得了命令的結果,可是,若是如今獲得 pod 的狀態:
kubectl get pods -n default NAME READY STATUS RESTARTS AGE alpine 1/1 Terminating 0 103s
💥已被終止💥
咱們如今能夠檢查組件的日誌了。
Falco:
kubectl logs daemonset/falco -n falco {"output":"23:39:44.834631763: Notice A shell was spawned in a container with an attached terminal (user=root user_loginuid=-1 k8s.ns=default k8s.pod=alpine container=5892b41bcf46 shell=sh parent=<NA> cmdline=sh terminal=34817 container_id=5892b41bcf46 image=<NA>) k8s.ns=default k8s.pod=alpine container=5892b41bcf46","priority":"Notice","rule":"Terminal shell in container","time":"2021-01-14T23:39:44.834631763Z", "output_fields": {"container.id":"5892b41bcf46","container.image.repository":null,"evt.time":1610667584834631763,"k8s.ns.name":"default","k8s.pod.name":"alpine","proc.cmdline":"sh","proc.name":"sh","proc.pname":null,"proc.tty":34817,"user.loginuid":-1,"user.name":"root"}}
Falcosidekick:
kubectl logs deployment/falcosidekick -n falco 2021/01/14 23:39:45 [INFO] : Kubeless - Post OK (200) 2021/01/14 23:39:45 [INFO] : Kubeless - Function Response : 2021/01/14 23:39:45 [INFO] : Kubeless - Call Function "delete-pod" OK
(注意,該函數不返回任何內容,這就是爲何消息日誌是空的)
delete-pod 函數:
kubectl logs deployment/delete-pod -n kubeless 10.42.0.31 - - [14/Jan/2021:23:39:45 +0000] "POST / HTTP/1.1" 200 0 "" "Falcosidekick" 0/965744 Deleting pod "alpine" in namespace "default"
經過這個很是簡單的例子,咱們只觸及了可能性的表面,如今一切皆有可能,因此不要猶豫,請在Kubernetes Slack #falco上與咱們分享你的評論、想法和成功。也歡迎你貢獻。
注 1:你在 Kubernetes 以外運行 Falcosidekick,但仍然想使用 Kubernetes 的輸出?沒有問題,你能夠聲明一個 kubeconfig 文件來使用。見README。
注 2:對於那些想用 Knative 代替 Kubeless 的人來講,它很快就會出現 😉
Enjoy
CNCF (Cloud Native Computing Foundation)成立於2015年12月,隸屬於Linux Foundation,是非營利性組織。
CNCF(雲原生計算基金會)致力於培育和維護一個廠商中立的開源生態系統,來推廣雲原生技術。咱們經過將最前沿的模式民主化,讓這些創新爲大衆所用。掃描二維碼關注CNCF微信公衆號。