开放策略代理(OPA)插件通过为应用注入OPA Sidecar代理来定义访问控制策略。服务提供了OPA注入范围控制功能,启用该功能后,仅添加了opa-istio-injection=enabled
标签的命名空间下的Pod会注入OPA Sidecar代理。
一、服务网格注入OPA整体流程
二、Webhook介绍
Admission Webhook 是 api-server 对外提供的一个扩展能力,admission webhook 就是提供了这样的能力,比如希望某个特定 label 标签的 pod 再创建的时候都注入 sidercar。
Admission Webhook 包涵两种 CRD:mutatingwebhookconfiguration 和 validatingwebhookconfiguration。
Admission Webhook 本质是 api-server 的一个 webhook 调用,下面是 api-server 的处理流程:
api-server 通过读取 mutatingwebhookconfiguration 和 validatingwebhookconfiguration 的 CR 文件的目标地址,然后回调用户自定义的服务。
MutatingAdmissionWebhook作为kubernetes的ApiServer中Admission Controller的一部分,提供了非常灵活的扩展机制,通过配置MutatingWebhookConfiguration对象,理论上可以监听并修改任何经过ApiServer处理的请求。
三、OPA 自动注入
Sidecar Injector是Istio中实现自动注入Sidecar的组件,它是以Kubernetes准入控制器Admission Controller的形式运行的。Admission Controller的基本工作原理是拦截Kube-apiserver的请求,在对象持久化之前、认证鉴权之后进行拦截。Admission Controller有两种:一种是内置的,另一种是用户自定义的。Kubernetes允许用户以Webhook的方式自定义准入控制器,Sidecar Injector就是这样一种特殊的MutatingAdmissionWebhook。
如图所示,Sidecar Injector只在创建Pod时进行Sidecar容器注入,在Pod的创建请求到达Kube-apiserver后,首先进行认证鉴权,然后在准入控制阶段,Kube-apiserver以REST的方式同步调用Sidecar Injector Webhook服务进行init与istio-proxy容器的注入,最后将Pod对象持久化存储到etcd中。
四、OPA注入配置
############################################################
# OPA admission control policy for injecting OPA-Istio.
############################################################
apiVersion: v1
kind: ConfigMap
metadata:
namespace: opa-istio
name: inject-policy
data:
inject.rego: |
package istio
uid := input.request.uid
inject = {
"apiVersion": "admission.k8s.io/v1",
"kind": "AdmissionReview",
"response": {
"allowed": true,
"uid": uid,
"patchType": "JSONPatch",
"patch": base64.encode(json.marshal(patch)),
},
}
patch = [{
"op": "add",
"path": "/spec/containers/-",
"value": opa_container,
}, {
"op": "add",
"path": "/spec/volumes/-",
"value": opa_config_volume,
}, {
"op": "add",
"path": "/spec/volumes/-",
"value": opa_policy_volume,
}]
opa_container = {
"image": "*****/library/opa:0.53.1-istio-3-static",
"name": "opa-istio",
"args": [
"run",
"--server",
"--config-file=/config/config.yaml",
"--addr=0.0.0.0:8181",
"/policy/policy.rego",
],
"volumeMounts": [{
"mountPath": "/config",
"name": "opa-istio-config",
}, {
"mountPath": "/policy",
"name": "opa-policy",
}]
}
opa_config_volume = {
"name": "opa-istio-config",
"configMap": {"name": "opa-istio-config"},
}
opa_policy_volume = {
"name": "opa-policy",
"configMap": {"name": "opa-policy"},
}
---
############################################################
# Service to expose OPA admission controller (required by Kubernetes.)
############################################################
apiVersion: v1
kind: Service
metadata:
name: admission-controller
namespace: opa-istio
labels:
app: admission-controller
spec:
ports:
- name: https
protocol: TCP
port: 443
targetPort: 8443
selector:
app: admission-controller
---
############################################################
# OPA admission controller deployment for injecting OPA-Istio.
############################################################
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: admission-controller
namespace: opa-istio
name: admission-controller
spec:
replicas: 1
selector:
matchLabels:
app: admission-controller
template:
metadata:
labels:
app: admission-controller
name: admission-controller
spec:
containers:
- image: *****/library/opa:0.53.1-istio-3-static
name: opa
ports:
- containerPort: 8443
args:
- "run"
- "--server"
- "--tls-cert-file=/certs/tls.crt"
- "--tls-private-key-file=/certs/tls.key"
- "--addr=0.0.0.0:8443"
- "/policies/inject.rego"
livenessProbe:
httpGet:
path: /health?plugins
scheme: HTTPS
port: 8443
initialDelaySeconds: 5
periodSeconds: 5
readinessProbe:
httpGet:
path: /health?plugins
scheme: HTTPS
port: 8443
initialDelaySeconds: 5
periodSeconds: 5
volumeMounts:
- readOnly: true
mountPath: /certs
name: server-cert
- readOnly: true
mountPath: /policies
name: inject-policy
volumes:
- name: inject-policy
configMap:
name: inject-policy
- name: server-cert
secret:
secretName: server-cert
---
############################################################
# OPA admission controller configuration.
############################################################
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: opa-istio-admission-controller
webhooks:
- name: istio.openpolicyagent.org
clientConfig:
service:
name: admission-controller
namespace: opa-istio
path: "/v0/data/istio/inject"
caBundle: |-
(省略)
rules:
- operations: ["CREATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
namespaceSelector:
matchLabels:
opa-istio-injection: enabled
failurePolicy: Fail
admissionReviewVersions: ["v1", "v1beta1"]
sideEffects: None
---
MutatingWebhookConfiguration是kubernetes的一个官方的资源提供的对象,下面对该对象的字段做一些简单的说明:
- caBundle:apiServer访问我们自定义的webhook服务时需要的加密认证数据
- service:apiServer访问我们自定义的webhook服务的Service相关信息(包括具体接口信息)
- failurePolicy:当apiServer调用我们自定义的webhook服务异常时,采取的策略(Ignore:忽略异常继续处理,Fail:直接失败退出不继续处理)
- operations:监听apiServer的操作类型,样例中,只有符合UPDATE类型的apiServer调用才会交给我们自定义的webhook服务处理。
- resources:监听apiServer的资源和子资源类型,样例中,只有符合nodes的status字段资源类型的apiServer调用才会交给我们自定义的webhook服务处理。
从以上配置可知,Sidecar Injector只对标签匹配“opa-istio-injection: enabled”的命名空间下的Pod资源对象的创建生效。Webhook服务的访问路径为“/v0/data/istio/inject”,地址及访问凭证等都在clientConfig字段下进行配置。
Sidecar Injector的实现主要由两部分组成:
- 维护MutatingWebhookConfiguration;
- 启动Webhook Server,为应用工作负载自动注入Sidecar容器。
五、验证OPA注入
可以看到opa注入成功。