istio-sidecar自动注入原理
0.原理
istio通过添加MutatingWebhook识别打了自动注入标签的Pod-create请求,请求pilot暴露的sidecar注入接口,pilot根据template生成sidecar并修改patch到pod元数据中返回完成sidecar注入。
1.指定namespace打注入标签
kubectl label namespace {namespace} istio-injection=enabled --overwrite
2.注入分析
暴露webhook:/inject
xiaohan@xiaohandeMacBook-Pro istio-1.17.2 % -oyaml
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
labels:
app: sidecar-injector
install.operator.istio.io/owning-resource: unknown
install.operator.istio.io/owning-resource-namespace: istio-system
istio.io/rev: default
operator.istio.io/component: Pilot
operator.istio.io/managed: Reconcile
operator.istio.io/version: 1.17.2
release: istio
name: istio-sidecar-injector
webhooks:
- admissionReviewVersions:
- v1beta1
- v1
clientConfig:
caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvVENDQWVXZ0F3SUJBZ0lSQU11cWc3d1psVGJ2elNXUW94VzhlNk13RFFZSktvWklodmNOQVFFTEJRQXcKR0RFV01CUUdBMVVFQ2hNTlkyeDFjM1JsY2k1c2IyTmhiREFlRncweU16QTBNVFF3TmpRM016aGFGdzB6TXpBMApNVEV3TmpRM016aGFNQmd4RmpBVUJnTlZCQW9URFdOc2RYTjBaWEl1Ykc5allXd3dnZ0VpTUEwR0NTcUdTSWIzCkRRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQ2lrc2lQNzlQOWFxcnowQ3d1bFNIQUxlNnVLMFdWdmdPL1pXbDQKRUtWak5oVEkwUnN6TWtSRjBGa3JxVjE2WlhJZVNKQXRROFVOTnpDMW1INWRjU2cyTTR1RTlJTHN4NUh6eTV2MwpteXl5eDIveTlRb2hFdFRGamJ5dmtyMkRoWWtSb040d2tudWtzTHhhd21vbDVDUFR0NXJpQmtxVFJHQXZkbXh5CkIrRmVSZHcyeGtrQzRINTkxSjBrSXlKNzEvaFVUeWtteXR0aEluR1hTM2NQY25UN0I5cFp5Wk85dWUrOGhLOTEKOStLVVRaMFJIdGVUWGJzdmd4QTNmRWdYdDduOEVWUHRFZ2RoazM4MHlkZ0lLSEluNWlicDkyK2FHcEFOdmgwYwpDbldzbWEvTnh6b0EyTnlXajZBTk9CcHZYcTJhWlBrK2hWWW5wTWJGcVZUK3lMWkRBZ01CQUFHalFqQkFNQTRHCkExVWREd0VCL3dRRUF3SUNCREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlRZakpLSngvb2kKelNmREZaVDVJMHFaMGZCT2NqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFpc3hJRk9YWCtkRGhSMzhMYmdsMApNQ1doTlo3bFNldHlkdDZUZy9XS1ljVGdkNUxkZzZMQmM3emF6Q2lqL0lBTUYxcjR4Ni90UE5pWUVac2ozank5CjN3N1ZGeGt3SGYyY2ovR1BjMGR2SFczYUVRM216b3UyMmxBNmVIdUxDZFNkaVYyNjJoc3krYXdpdi9xaTAvVEoKL1NDUXQxcDFSNnlRbm0yalhObHljMllwYk5OWE5WK1I5SE0wVmpZc05Yd3hYdm1xM0tkMVdEN0tOaXNGSTdMRApXRkFzeW9WaitxSlRlbXVGTzR1WUN5TzQvMWx3dEdSQ1VjOFRqb1NzSjBMdHFMOU13NHVRV1FxMU4zM0Rxc29kCmdXNTVKbHlZOWVPaWMzMFZZOU5NLzRXa1o4TnZ5Z3lrcTZ0R1R6R2oyeXpBamUxb3pSQytqYnlWMjlPUkdVbkMKNXc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
service:
name: istiod
namespace: istio-system
path: /inject
port: 443
failurePolicy: Fail
matchPolicy: Equivalent
name: namespace.sidecar-injector.istio.io
namespaceSelector:
matchLabels:
istio.io/deactivated: never-match
objectSelector:
matchLabels:
istio.io/deactivated: never-match
reinvocationPolicy: Never
rules:
- apiGroups:
- ""
apiVersions:
- v1
operations:
- CREATE
resources:
- pods
scope: '*'
/inject server 转发istio-pilot-15017
xiaohan@xiaohandeMacBook-Pro istio-1.17.2 % kubectl get svc -n istio-system istiod -oyaml
apiVersion: v1
kind: Service
metadata:
annotations:
labels:
app: istiod
install.operator.istio.io/owning-resource: unknown
install.operator.istio.io/owning-resource-namespace: istio-system
istio: pilot
istio.io/rev: default
operator.istio.io/component: Pilot
operator.istio.io/managed: Reconcile
operator.istio.io/version: 1.17.2
release: istio
name: istiod
namespace: istio-system
spec:
clusterIP: 10.96.7.238
clusterIPs:
- 10.96.7.238
internalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- name: grpc-xds
port: 15010
protocol: TCP
targetPort: 15010
- name: https-dns
port: 15012
protocol: TCP
targetPort: 15012
- name: https-webhook
port: 443
protocol: TCP
targetPort: 15017
- name: http-monitoring
port: 15014
protocol: TCP
targetPort: 15014
selector:
app: istiod
istio: pilot
sessionAffinity: None
type: ClusterIP
xiaohan@xiaohandeMacBook-Pro istio-1.17.2 % kubectl get po -n istio-system istiod-dbf5ff64-mqgrk -oyaml
apiVersion: v1
kind: Pod
spec:
containers:
- args:
- discovery
- --monitoringAddr=:15014
- --log_output_level=default:info
- --domain
- cluster.local
- --keepaliveMaxServerConnectionAge
- 30m
image: docker.io/istio/pilot:1.17.2
imagePullPolicy: IfNotPresent
name: discovery
ports:
- containerPort: 8080
protocol: TCP
- containerPort: 15010
protocol: TCP
- containerPort: 15017
protocol: TCP
pkg/kube/inject/webhook.go:187 pilot暴露/inject http server
func NewWebhook(p WebhookParameters) (*Webhook, error) {
if p.Mux == nil {
return nil, errors.New("expected mux to be passed, but was not passed")
}
wh := &Webhook{
watcher: p.Watcher,
meshConfig: p.Env.Mesh(),
env: p.Env,
revision: p.Revision,
}
mc := NewMulticast(p.Watcher, wh.GetConfig)
mc.AddHandler(wh.updateConfig)
wh.MultiCast = mc
sidecarConfig, valuesConfig, err := p.Watcher.Get()
if err != nil {
return nil, err
}
if err := wh.updateConfig(sidecarConfig, valuesConfig); err != nil {
log.Errorf("failed to process webhook config: %v", err)
}
p.Mux.HandleFunc("/inject", wh.serveInject)
p.Mux.HandleFunc("/inject/", wh.serveInject)
p.Env.Watcher.AddMeshHandler(func() {
wh.mu.Lock()
wh.meshConfig = p.Env.Mesh()
wh.mu.Unlock()
})
return wh, nil
}
pkg/kube/inject/webhook.go:436 inject sidecar
func injectPod(req InjectionParameters) ([]byte, error) {
checkPreconditions(req)
// The patch will be built relative to the initial pod, capture its current state
originalPodSpec, err := json.Marshal(req.pod)
if err != nil {
return nil, err
}
// Run the injection template, giving us a partial pod spec
mergedPod, injectedPodData, err := RunTemplate(req)
if err != nil {
return nil, fmt.Errorf("failed to run injection template: %v", err)
}
mergedPod, err = reapplyOverwrittenContainers(mergedPod, req.pod, injectedPodData)
if err != nil {
return nil, fmt.Errorf("failed to re apply container: %v", err)
}
// Apply some additional transformations to the pod
if err := postProcessPod(mergedPod, *injectedPodData, req); err != nil {
return nil, fmt.Errorf("failed to process pod: %v", err)
}
patch, err := createPatch(mergedPod, originalPodSpec)
if err != nil {
return nil, fmt.Errorf("failed to create patch: %v", err)
}
log.Debugf("AdmissionResponse: patch=%v\n", string(patch))
return patch, nil
}