OpenKruise SidecarSet采用Admission Webhook機制,在創建Pod的階段對匹配了目標Label的所有Pod注入Sidecar容器。此時Pod還未調度到虛擬節點,無法僅對調度到虛擬節點的Pod生效。您可以借助虛擬節點組件(ACK Virtual Node)僅為調度到虛擬節點上的Pod自動注入Sidecar容器,來解耦虛擬節點Pod的Sidecar容器與業務容器。
基本概念
Sidecar:一種將應用功能從應用本身剝離出來作為單獨進程的設計方式。該模式允許您向應用無侵入添加多種功能,避免為滿足第三方組件需求而向應用添加額外的配置代碼。
Sidecar容器:將一個容器添加到另一個Pod中作為一個附加容器,以擴展和增強主容器,而無需改變主容器本身。
SidecarSet:是阿里云開源的云原生應用自動化引擎OpenKruise的核心功能之一。使用SidecarSet可以為集群中創建的符合條件的Pod自動注入Sidecar容器,實現Sidecar容器(如監控、日志等agent)的定義和生命周期與業務容器解耦。
使用限制
ACK Virtual Node組件不支持OpenKruise 1.4及以上版本SidecarSet功能。
前提條件
已創建Kubernetes版本為1.22及以上的ACK集群Pro版、ACK Serverless集群Pro版或者ACK專有集群。具體操作,請參見創建Kubernetes托管版集群、創建ACK Serverless集群或創建Kubernetes專有版集群。
已安裝ack-kruise組件,且版本為v1.3.0及以上。更多信息,請參見ack-kruise。
已安裝虛擬節點組件(ACK Virtual Node),且版本為v2.10.0及以上。更多信息,請參見ACK Virtual Node。
已啟用
SidecarSetServerlessPod=true
特性門控。具體操作,請參見自定義管控面組件參數,在Kube API Server組件featureGates中設置SidecarSetServerlessPod=true
。
功能介紹
SidecarSet
您可以使用與默認SidecarSet完全一致的方式來匹配所有調度到虛擬節點的Pod,即通過標簽serverless.alibabacloud.com/virtual-node: "true"
指定。該標簽會在Pod確定調度到虛擬節點后打上。關于默認SidecarSet的使用方法,請參見SidecarSet。
另一個常用的功能是跨命名空間引用ConfigMap和Secret。DaemonSet核心容器運行經常依賴ConfigMap,如配置參數。將DaemonSet核心容器注入到業務Pod中,業務Pod與ConfigMap通常在不同的命名空間,在Sidecar容器Volume中通過namespace/name
方式引用其他命名空間的ConfigMap。
跨命名空間訪問ConfigMap和Secret需要授權。具體方式,請參見下方SidecarSetResourceBinding。
SidecarSetResourceBinding
出于安全考慮,在Sidecar容器Volume中引入其他命名空間的ConfigMap和Secret需要通過SidecarSetResourceBinding顯式授權。
該授權僅授予對ConfigMap和Secret的只讀權限(Get,List,Watch)。
容器啟動和退出順序
Sidecar容器經常需要在業務容器前啟動,在業務容器后退出,您可以通過設置容器啟動和退出順序實現。
自動結束Sidecar容器
對于Job類Pod,Sidecar容器可能會導致業務容器完成后Job無法退出的情況,您可以通過強制終止Sidecar容器并忽略容器退出碼來解決問題。
升級Sidecar容器
使用Sidecar模式后,您可能會有Sidecar容器升級等運維需求。您可以使用OpenKruise已有的Sidecar熱升級功能,該方式能在不影響Pod可用性情況下無縫升級Sidecar容器,且與當前虛擬節點方式完全兼容。
日志收集
通過將虛擬節點Pod標準輸出日志卷掛載到Sidecar容器指定目錄,可以收集業務容器的日志。具體信息,請參見掛載stdlog實現掛載容器標準輸出日志。
apiVersion: apps.kruise.io/v1alpha1
kind: SidecarSet
metadata:
name: filebeat-sidecarset
spec:
selector:
matchLabels:
serverless.alibabacloud.com/virtual-node: "true" # 表示匹配所有調度到虛擬節點的Pod。
updateStrategy:
type: NotUpdate
containers:
# 此示例僅打印Sidecar容器日志內容。
- name: filebeat
image: busybox
imagePullPolicy: IfNotPresent
args: [
"/bin/sh",
"-c",
"cat /var/log/std/filebeat/0.log && sleep 36000",
]
volumeMounts:
- name: stdlog # 掛載Pod標準輸出日志卷/var/log/std目錄以便sidecar容器讀取。
mountPath: /var/log/std
readOnly: true
volumes:
- name: stdlog
flexVolume:
driver: alicloud/pod-stdlog # Pod標準輸出日志卷。
操作示例
下文將以filebeat容器作為Sidecar容器注入到echo-server業務Pod為例,展示完整的使用流程。
部署filebeat容器配置文件。
配置文件是kube-system命名空間的ConfigMap,將被掛載到filebeat容器里。本示例僅將該配置文件掛載到Sidecar容器并打印,相關變量不生效,無需替換。
kubectl apply -f - << EOF apiVersion: v1 kind: ConfigMap metadata: name: filebeat-config namespace: kube-system labels: k8s-app: filebeat data: filebeat.yml: |- filebeat.inputs: - type: log paths: - /var/log/std/*.log processors: - add_kubernetes_metadata: host: ${NODE_NAME} # 不生效,無需修改,請直接使用。 matchers: - logs_path: logs_path: "/var/log/std/" # To enable hints based autodiscover, remove `filebeat.inputs` configuration and uncomment this: #filebeat.autodiscover: # providers: # - type: kubernetes # node: ${NODE_NAME} # hints.enabled: true # hints.default_config: # type: container # paths: # - /var/log/containers/*${data.kubernetes.container.id}.log processors: - add_cloud_metadata: - add_host_metadata: cloud.id: ${ELASTIC_CLOUD_ID} # 不生效,無需修改,請直接使用。 cloud.auth: ${ELASTIC_CLOUD_AUTH} # 不生效,無需修改,請直接使用。 output.elasticsearch: hosts: ['${ELASTICSEARCH_HOST:elasticsearch}:${ELASTICSEARCH_PORT:9200}'] username: ${ELASTICSEARCH_USERNAME} # 不生效,無需修改,請直接使用。 password: ${ELASTICSEARCH_PASSWORD} # 不生效,無需修改,請直接使用。 EOF
部署filebeat容器的SidecarSet描述。
本示例filebeat容器僅打印配置內容。同時,filebeat容器還掛載了業務Pod的標準輸出卷,可以收集業務Pod的標準輸出日志。
kubectl apply -f - << EOF apiVersion: apps.kruise.io/v1alpha1 kind: SidecarSet metadata: name: filebeat-sidecarset spec: selector: matchLabels: serverless.alibabacloud.com/virtual-node: "true" # 表示匹配所有調度到虛擬節點的Pod。 updateStrategy: type: NotUpdate containers: # 此示例未真正運行filebeat,替換為bosybox cat。 #- name: filebeat # image: docker.elastic.co/beats/filebeat:8.6.1 # args: [ # "-c", "/etc/filebeat.yml", # "-e", # ] - name: filebeat image: busybox imagePullPolicy: IfNotPresent args: [ "/bin/sh", "-c", "cat /etc/filebeat.yml && sleep 36000", ] env: - name: ECI_SIDECAR_CONTAINER # 表示Sidecar容器在業務容器后退出。 value: "true" volumeMounts: - name: config mountPath: /etc/filebeat.yml readOnly: true subPath: filebeat.yml - name: stdlog # 掛載Pod標準輸出日志卷/var/log/std目錄以便sidecar容器讀取。 mountPath: /var/log/std readOnly: true volumes: - name: config configMap: name: kube-system/filebeat-config # 使用namespace/name方式指定引用其他namespace下ConfigMap。 - name: stdlog flexVolume: driver: alicloud/pod-stdlog # Pod標準輸出日志卷。 EOF
授權filebeat容器能夠訪問kube-system命名空間下的配置文件。
因為echo-server業務Pod位于default命名空間下,filebeat容器被注入后跨namespace訪問配置文件需要顯式授權。
kubectl apply -f - << EOF # 授權filebeat-sidecarset,SidecarSet匹配的Pod能夠訪問kube-system命名空間下filebeat-config ConfigMap。 apiVersion: sidecarset.alibabacloud.com/v1alpha1 kind: SidecarSetResourceBinding metadata: name: filebeat-sidecarset-resourcebinding namespace: kube-system # 此SidecarSetResourceBinding只能對kube-system命名空間下的資源做授權。 labels: spec: subjects: - kind: SidecarSet name: filebeat-sidecarset resourceRefs: - kind: ConfigMap name: filebeat-config EOF
部署echo-server業務Pod。
kubectl apply -f - << EOF apiVersion: apps/v1 kind: Deployment metadata: name: echo-server labels: app: echo-server spec: replicas: 1 selector: matchLabels: app: echo-server template: metadata: labels: app: echo-server alibabacloud.com/eci: "true" spec: containers: - name: echo-server image: hashicorp/http-echo imagePullPolicy: IfNotPresent args: - -listen=:8080 - -text="hello world" EOF
查看業務Pod。
kubectl get pod NAME READY STATUS RESTARTS AGE echo-server-54f5cf556c-8ms5z 2/2 Running 0 41s
輸出表明,Pod包含2個容器,說明注入成功。
驗證filebeat容器已掛載業務Pod標準輸出日志。
kubectl exec echo-server-54f5cf556c-8ms5z -c filebeat -- cat /var/log/std/echo-server/0.log 2023-07-07T00:40:07.927378153+08:00 stderr F 2023/07/06 16:40:07 Server is listening on :8080
輸出表明,可以看到業務Pod標準輸出日志。
驗證filebeat容器已掛載跨命名空間的配置文件filebeat-config。
kubectl exec echo-server-54f5cf556c-8ms5z -c filebeat -- cat /etc/filebeat.yml filebeat.inputs: - type: log paths: - /var/log/std/*.log # To enable hints based autodiscover, remove `filebeat.inputs` configuration and uncomment this: #filebeat.autodiscover: # providers: # - type: kubernetes # node: ${NODE_NAME} # hints.enabled: true # hints.default_config: # type: container # paths: # - /var/log/containers/*${data.kubernetes.container.id}.log processors: - add_cloud_metadata: - add_host_metadata: cloud.id: ${ELASTIC_CLOUD_ID} cloud.auth: ${ELASTIC_CLOUD_AUTH} output.elasticsearch: hosts: ['${ELASTICSEARCH_HOST:elasticsearch}:${ELASTICSEARCH_PORT:9200}'] username: ${ELASTICSEARCH_USERNAME} password: ${ELASTICSEARCH_PASSWORD}
輸出表明,掛載正常。