在之前的文章中,我们讲过webhook admission是什么以及如何在代码中实现一个webhook admission。今天我们主要讲下,如何在kubernetes中部署自己的webhook admission。
生成TLS验证的证书
为什么需要TLS验证:
- 首先API服务器与其他程序通信需要保证安全性,所以他们之间要https加密通信。
- webhook程序跟API服务器通信的时候可以理解为webhook程序是服务端,所以它要产生公私匙,将公匙交给客户端,让其加密后再发送数据。但是,客户端不知道服务端发公匙是不是伪造的,所以需要一个第三方机构CA进行证书签名。证书签名是使用CA的私匙加密,然后客户端用CA的公匙解密验证证书的真伪。
关于证书这块,可以两种方式实现,分为:
- 由k8s自带的CA进行签名,因为这样api服务器就可以用自带CA的公匙进行验证。
- 自己通过cfssl签发。
关于k8s自带的CA签名的,大家可以参照下面的脚本 webhook-create-signed-cert.sh
:
#!/bin/bash
set -e
usage() {
cat <> ${tmpdir}/csr.conf
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = ${service}
DNS.2 = ${service}.${namespace}
DNS.3 = ${service}.${namespace}.svc
EOF
openssl genrsa -out ${tmpdir}/server-key.pem 2048
openssl req -new -key ${tmpdir}/server-key.pem -subj "/CN=${service}.${namespace}.svc" -out ${tmpdir}/server.csr -config ${tmpdir}/csr.conf
# clean-up any previously created CSR for our service. Ignore errors if not present.
kubectl delete csr ${csrName} 2>/dev/null || true
# create server cert/key CSR and send to k8s API
cat <&2
exit 1
fi
echo ${serverCert} | openssl base64 -d -A -out ${tmpdir}/server-cert.pem
# create the secret with CA cert and server cert/key
kubectl create secret generic ${secret} \
--from-file=key.pem=${tmpdir}/server-key.pem \
--from-file=cert.pem=${tmpdir}/server-cert.pem \
--dry-run -o yaml |
kubectl -n ${namespace} apply -f -
但是有些特殊的托管集群,为了安全的内容,这种签发是行不通的。所以我们可以使用cfssl 自己签发。
安装cfssl
OS X
brew install cfssl
Linux
wget -q --show-progress --https-only --timestamping \\
https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 \\
https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
chmod +x cfssl_linux-amd64 cfssljson_linux-amd64
sudo mv cfssl_linux-amd64 /usr/local/bin/cfssl
sudo mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
创建CA cert
{
cat > ca-config.json < ca-csr.json <
Results:
ca-key.pem
ca.pem
创建 Server Cert
cat > server-csr.json <
PS: 最重要的是 -hostname
的值, {service-name}.{service-namespace}.svc, service-name代表你webhook 的service名字,service-namespace代表你webhook的命名空间。
Results:
server-key.pem
server.pem
创建WebhookConfiguration
Encode and trim the ca cert.
cat ca.pem | base64
Results:
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURvRENDQW9pZ0F3SUJBZ0lVVkZ0d2UwR09DMzRvbWppWUV6WGZKaGd4L244d0RRWUpLb1pJaHZjTkFRRUwKQlFBd2FERUxNQWtHQTFVRUJoTUNWVk14RHpBTkJnTlZCQWdUQms5eVpXZHZiakVSTUE4R0ExVUVCeE1JVUc5eQpkR3hoYm1ReEV6QVJCZ05WQkFvVENrdDFZbVZ5Ym1WMFpYTXhDekFKQmdOVkJBc1RBa05CTVJNd0VRWURWUVFECkV3cExkV0psY201bGRHVnpNQjRYRFRJd01EUXlPREEzTWprd01Gb1hEVEkxTURReU56QTNNamt3TUZvd2FERUwKTUFrR0ExVUVCaE1DVlZNeER6QU5CZ05WQkFnVEJrOXlaV2R2YmpFUk1BOEdBMVVFQnhNSVVHOXlkR3hoYm1ReApFekFSQmdOVkJBb1RDa3QxWW1WeWJtVjBaWE14Q3pBSkJnTlZCQXNUQWtOQk1STXdFUVlEVlFRREV3cExkV0psCmNtNWxkR1Z6TUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUFydkF5Vzd0Umk0Zk8Ka21lQjFQRFhjN1VjeFRrVW1jSDBETkZ6NzJyVXN0cFdsbVV4SDZBRjNEYTRDU3ZpSHgrOUQ4Z2ZBaEdMcFVxSApzVklaT3NqTDVocVNuZzJEVzZRc2VUc3pHcWV1Z3NueFNlZXhLSzlYUi9RUnFmT3VrM3dqZWR3SGM2MU1BdWNBCndkT2h2SGlKQk5KR0NNSlF4ZGpkMTRaVk5KT2o1djJFHpkcWhzbjlXU3Ivc0ptOVFLRitPeTAyenN0MVUKd2NDSVN5dnpyMmJvRm5tbEgvWWVCRVRsTzJXQm95ZDZ0bHk0YmllRVV5Y0hBMzRnc3liUWVZcUFuSzF2S3UragpYVUxZQ3dXMzFwc1lxQTAxNURDbGlIcjgxNG50Q251NVVGYUJwUmtDTkMrM3A5aEU2WjdKRGVKQS9zVnBST3B5CmxWZ0RjTjEyT1FJREFRQUJvMEl3UURBT0JnTlZIUThCQWY4RUJBTUNBUVl3RHdZRFZSMFRBUUgvQkFVd0F3RUIKL3pBZEJnTlZIUTRFRmdRVUpmQVk2aW5uRXEveFdXSE9kOEJBWE9YdktCOHdEUVlKS29aSWh2Y05BUUVMQlFBRApnZ0VCQUFyQjBSZ1hzN1JhSU96Tk40QTFuVFg2d21keTdDaytSVEE4RXo4MkFPQnBJV2w3c2tCMUY1aFhJYWI5CjhvWi9UUzdhZTJuakJuK2lWVWpTbU5qdlM5M3BmRUxMR1lFZ2ZYYnJkdkNibnRDODRnQnlDM2YxSzJwR01zY1oKQ2N4OUUrSTFZekxDdFFQV2dPS0NEb3VJdGJCcmVTOVpodklNUkI2WjE3QW5CYWI1UGJodkNENjVIM0JYNlpsZgprVEJOUldFZFpDS0tBa2ZyUW1QaWVBRVpTbTd6eFFVZi85Rkx0RytkK3JHejAxeHZSUVFkSHZnbUNhSmx5TEE1CkZZbTRNSGtIb3dIa0I3aWxLVUhQc2ZzZ3ZFNlpweFpsdi9BbTVPcFhINllCZ0NuZVBha1c3RjdzanhxWVBUakMKei85RGNSSm5haDcvWXpROWZweFBha1o5c1dzPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
创建webhook config:
cat mutaing.yaml <
kubectl create -f mutating.yaml
此处需要注意:failurePolicy: Fail
定义了如何处理 admission webhook 中无法识别的错误和超时错误。允许的值为Ignore
或Fail
。
-
Ignore
表示调用 webhook 的错误将被忽略并且允许 API 请求继续。 -
Fail
表示调用 webhook 的错误导致准入失败并且 API 请求被拒绝。
创建 TLS secret for server
cat server.pem | base64
Result:
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVCVENDQXUyZ0F3SUJBZ0lVRUlOL1VvVGpnbWgwN3c2QnBmaDhQeVlCKzdzd0RRWUpLb1pJaHZjTkFRRUwKQlFBd2FERUxNQWtHQTFVRUJoTUNWVk14RHpBTkJnTlZCQWdUQms5eVpXZHZiakVSTUE4R0ExVUVCeE1JVUc5eQpkR3hoYm1ReEV6QVJCZ05WQkFvVENrdDFZbVZ5Ym1WMFpYTXhDekFKQmdOVkJBc1RBa05CTVJNd0VRWURWUVFECkV3cExkV0psY201bGRHVnpNQjRYRFRJd01EUXlPREE1TVRjd01Gb1hEVEl4TURReU9EQTVNVGN3TUZvd2J6RUwKTUFrR0ExVUVCaE1DVlZNeER6QU5CZ05WQkFnVEJrOXlaV2R2YmpFUk1BOEdBMVVFQnhNSVVHOXlkR3hoYm1ReApFekFSQmdOVkJBb1RDa3QxWW1WeWJtVjBaWE14RXpBUkJnTlZCQXNUQ2t0MVltVnlibVYwWlhNeEVqQVFCZ05WCkJBTVRDV0ZrYldsemMybHZiakNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFLQkMKTnF5V3BSc1dmYi8yd3FGeU0vbmo1SGc0ZmJsY2YvQUNPNjFNejV5amIwVDB1NWFHd3pCeWNVMm1sN2ZqaGdscQo3N3BEWGlvaU9OYlY3N2NDNDIzZWV1MXdtajhVeENITDlNTGk5MjlNODBNWDN0NmZHWHVMUDUxTkVpaVY2YUt6Cncya2R4RFYwWklqUTd6YUNwOFExdFpDQXVpbzFzWkdlR205cUJOOHNhZjgvNkQraXRmN1dTUUZKVEt0K2k1ckMKRnVSQXo2ZEdqVmFmd2ZrS1YzeWNoT0IrRitxVm1oV3UyWFJCUjZmMDJESVNNVWFXei9DdUZ1MGpYN3pqcE1yVQpoZCtiU2lsaStodko2RHZYWkd5UUxIMlNuNG95enFSckozQktFcnhuRDBlbDYwRDVjaHUydFR1Q3pHVXhrS1NZCmRzVHNyOVpBRno5QVpFL0JvaHNDQXdFQUFhT0JuekNCbkRBT0JnTlZIUThCQWY4RUJBTUNCYUF3SFFZRFZSMGwKQkJZd0ZBWUlLd1lCQlFVSEF3RUdDQ3NHQVFVRkJ3TUNNQXdHQTFVZEV3RUIvd1FDTUFBd0hRWURWUjBPQkJZRQpGUFlTRTBiOEtKNVphaWpYbnJabjJjalB1dklMTUI4R0ExVWRJd1FZTUJhQUZDWHdHT29wNXhLdjhWbGh6bmZBClFGemw3eWdmTUIwR0ExVWRFUVFXTUJTQ0VtdHRjeTVyZFdKbExXRmtiV2x1TG5OMll6QU5CZ2txaGtpRW9EV2lvd3FWUTJzOUJRSnh2OVZEMEZpdi9Od1JjU2FSZHgrT0tQMHgvCnVyUmlkNHhIVnFBYjFlQ0wwQVF6Skh5MEV6YkU3bjV4NE1aSFhWYnhvdFA1b1RyR1R6T1VuZ0xqeWl0NFZ6UmgKUU9KSlRuVkIwY3MwZFpEVWduWTZ0VGFrSzFJY2d2ZndtVlMzN0FWZmZZcFlSNUdLTG50OGVlWEVwZFlTS1VQOApzdlNCRDRIenBqNGlVd2lLTU9LaGZja05INDM2N1k2S2pOUlhEaHp4OGVnVnp5Q3F6UGhoQWx5NlB0L1FER0ZwCk1RQmo2aFYzaUZ5NlY3UWowc0FZdDVBYzB5bERBT0RqaXc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
cat server-key.pem | base64
Result:
LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBb0VJMnJKYWxHeFo5di9iQ29YSXorZVBrZURoOXVWeC84QUk3clV6UG5LTnZSUFM3CmxvYkRNSEp4VGFhWHQrT0dDV3J2dWtOZUtpSTQxdFh2dHdMamJkNTY3WENhUHhURUljdjB3dUwzYjB6elF4ZmUKM3A4WmU0cy9uVTBTS0pYcG9yUERhUjNFTlhSa2lORHZOb0tueERXMWtJQzZLald4a1o0YWIyb0UzeXhwL3ovbwpQNksxL3RaSkFVbE1xMzZMbXNJVzVFRFBwMGFOVnAvQitRcFhmSnlFNEg0WDZwV2FGYTdaZEVGSHAvVFlNaEl4ClJwYlA4SzRXN1NOZnZPT2t5dFNGMzV0S0tXTDZHOG5vTzlka2JKQXNmWktmaWpMT3BHc25jRW9TdkdjUFI2WHIKUVBseUc3YTFPNExNWlRHUXBKaDJ4T3l2MWtBWFAwQmtUOEdpR3dJREFRQUJBb0lCQUF3dGUrSVpnR3BTaHpPegpHSThVRW9jR25qSFVlUmxBd2lnR3cyb2owQkxqQ0cyQSsxQXc1VndsRmg4RWJicjNleFAwSUV0VEd6Q3djUWxDCk1Ia0RxeXlLSDJVempVVUYydkdHZ2c3ZEdGaEl6S05vaVBMNXZBSDdUdFl4S1JRVWNEQ0E0SFI0WXBSOVI3WnQKeWYrbVpnRXU0NkViWndvV0Vtd3lTMmZ6OG5MUzJsek9qN1kvbFRPcDJPZnRYZ3Q5WGV4TXR2WXc4alNpVTBmSApJMk9UcG9oYlhvL2hkOThsdDNOei9DZzIrYU4waXRvZzAxZVV3TjY2UHh2MndtQ0VsVUd5cmh4enRyY2FaQVFiCjhqQWVWUUJyUnlpUmZpU1FSTXhTOWRPMGpseXhkdzVvNUs5YzFDMEhvRkxNSEJhVmxHNWpEWWNvVGJ2S0FDSzMKVmUydUdZRUNnWUVBd3QrbnVxYVd1WkFDb3k3Vi9remFRY3EyMWxiOUZxSUlEVTVSQ3Npa3l4WktWVmZRRXBQMQpJREV6TThOL1doSFE2bm5namUwdFBXWnhpQkFzcHM2VTB3V3ViQ0VZdmdnN2wvR3AyS2czODVEeTNDWnAwY3JBCkg3cXIrTlhBR2RRS0FrdDN3UDBuNE1rYk1Jd2k2ckZ1b2lKdW5hMWJ1YmEyNUd5U0hhcXJOREVDZ1lFQTBvYjUKbmRONjJFZzM5bFc1OEZzdEtRaDBYUHZrNlE0UEFYZHN4My9RK3dZeWsweWk3aEpIVHR0MjhCMlRrVmU1Z003VQpOYnRJcGs1eUlaQmdTc0VmMktUZWpjS0hVY3NsbEFDWGFOQkJOVXFpNHltdTc1SGhwajhYc2R3Q2tRRU1ERi9vCjZyYmpyNmpHQXpsVE1McDJGRmcrTllJd3J5MjgwRXIvUWhHbnBBc0NnWUJ5dFZZMC8zUi9mQzZoUWFPRFVsZXoKSEpFdGIvMEFRcFo4eHBuYndDbUl4ZkV4ZFVRc2UxMXgrcVFLRjB5eWh3UXowVlFHRnhObkxoTXNKV0V6T3l6TgpYbTNDaG1UYkQxdU00QnE3UnFIUXhJVEFZL2dzSHEyaXY2NFZCalZTdnNhNWZSVGJ5K2lhWDZhYW1CTEJsWG5yCkJGdWFndjRZUGw0LzdVekJHOEkxTVFLQmdHVU1KQU44M2hteGtDck1PdE1DOEVva4RjdNd09mNDJmNHhEOGRNd3ZwRm1rMFZYOE00cHlITENWQwowQW1rS1VxZlZ6Zmw3VWkrUDhFK3VIeWc1QWVNZ1Y4bktXSEd3RVFMMzhJanZVbEdrWlZkUjhETlV6TW16QjRLCkcwekJBb0dCQUxhQTdOb0ltblg4SFZoL1RRZlcxQ3Y0VytaSjdaNFRnb2FjYnZnd05nelFlNU1aMCt5Z3hsaVMKQ1BVdVBwVVV0ejU3MWhOTjI4Q1J2c2JVZFNxS2xyZ2RubGhONFJpZDAyK243R0h1RWYvZUE1NFZab2dQcURkMApnVVdVdnZiTXljTGFiS0c5dG1lQjQ4Q0xPektDSVlyVzJ6Y2RCK1YyeXdvQ29ZQUlSSnduCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
cat > secret.yaml <
kubectl create -f mutating.yaml
创建webhook deployment
将TLS密钥作为卷挂载,以便可以在Web服务中使用它来启动HTTPS服务器。
apiVersion: apps/v1
kind: Deployment
metadata:
name: kms
namespace: kube-admin
labels:
app: kms
spec:
replicas: 2
selector:
matchLabels:
app: kms
template:
metadata:
labels:
app: kms
spec:
containers:
- name: kms
image: xxx/mutation:v0.3.0
imagePullPolicy: Always
args:
- -tlsCertFile=/etc/webhook/certs/cert.pem
- -tlsKeyFile=/etc/webhook/certs/key.pem
- -alsologtostderr
- -v=4
- 2>&1
volumeMounts:
- name: webhook-certs
mountPath: /etc/webhook/certs
readOnly: true
volumes:
- name: webhook-certs
secret:
secretName: kms
创建webhook service
apiVersion: v1
kind: Service
metadata:
name: kms
namespace: kube-admin
spec:
selector:
app: kms
ports:
- protocol: TCP
port: 443
targetPort: 443