首页
导航
统计
留言
更多
壁纸
直播
关于
推荐
星的魔法
星的导航页
星的云盘
谷歌一下
腾讯视频
Search
1
Ubuntu安装 kubeadm 部署k8s 1.30
140 阅读
2
kubeadm 部署k8s 1.30
100 阅读
3
rockylinux 9.3详细安装drbd
94 阅读
4
rockylinux 9.3详细安装drbd+keepalived
93 阅读
5
ceshi
64 阅读
默认分类
日记
linux
docker
k8s
ELK
Jenkins
Grafana
Harbor
Prometheus
Cepf
k8s安装
Gitlab
golang
Git
Python
Web开发
HTML和CSS
JavaScript
对象模型
登录
/
注册
Search
标签搜索
k8s
linux
docker
drbd+keepalivde
ansible
dcoker
webhook
星
累计撰写
65
篇文章
累计收到
935
条评论
首页
栏目
默认分类
日记
linux
docker
k8s
ELK
Jenkins
Grafana
Harbor
Prometheus
Cepf
k8s安装
Gitlab
golang
Git
Python
Web开发
HTML和CSS
JavaScript
对象模型
页面
导航
统计
留言
壁纸
直播
关于
推荐
星的魔法
星的导航页
星的云盘
谷歌一下
腾讯视频
搜索到
1
篇与
的结果
2023-08-20
k8s的webhook开发
一、知识储备1、Admission Webhooks是什么 请求链路 ------------|--------|-------------》etcd 关卡 关卡 webhook指的是中途拦击请求做定制化处理,包含 (1)mutate:截胡请求之后做修改,改完之后扔回原链路 (2)validate:对请求的数据做校验,不符合规定的直接扔掉 Admission翻译为准入,入指的是入到etcd数据库中2、webhook的执行时机 Admission Webhook 本质是 api-server 的一个 webhook 调用, 总结出两种webhook的触发时机 1、总提来说,Admission Webhooks 机制是在 API Server 接收到请求、执行授权检查后和将请求持久化到 etcd 之前触发。 2、详细的看,Mutating Webhook 在 Validating Webhook 之前触发,因此可以先对资源进行修改,然后再进行验证。 3、Admission Webhook的运行流程 ┌──────────────────────────────────┐ ┌─────────────────┐ │ │ apply │ │ read │ validatingwebhookconfiguration │ ────────────►│ api-server │◄───────────┤ │ │ │ │ mutatingwebhookconfiguration │ └────────┬────────┘ │ │ │ └──────────────────────────────────┘ │ │ 回调 │ │ ┌────────▼────────┐ │ │ │ webhookservice │ │ │ └─────────────────┘4、Admission Webhook的应用场景mutating webhook应用场景举例 自动注入sidecar容器 自动配置资源限制 注入配置或者标签 Validating Webhook应用场景举例 强制标签和注解策略 必须用私有仓库的镜像 安全策略审计:例如不允许使用特权模式二、mutating webhook实战案例1.储备知识:基于flask框架开发一个web程序,对外提供api接口# 安装python3解释器 # 为解释器环境安装flask代码包: pip3 install flask from flask import Flask app = Flask(__name__) # 创建一个 Flask 应用实例 @app.route('/xxx', methods=['GET']) # http://192.168.71.2:8888/xxx def mutate(): print("run....................") return "hello" @app.route('/yyy', methods=['GET']) # http://192.168.71.2:8888/xxx def test(): print("run22222222222222222....................") return "hello2222222222222222222222222" if __name__ == '__main__': app.run(host='0.0.0.0', port=8888,)2.需求:为所有新创建的pod打上标签:environment: production(1)先准备webhook程序cat > webhook.py << 'EOF' from flask import Flask, request, jsonify # 导入 Flask 框架、请求处理和 JSON 响应模块 import json import ssl import base64 app = Flask(__name__) # 创建一个 Flask 应用实例 def create_patch(metadata): """ 创建 JSON Patch 以添加 'mutate' 注释。 如果 metadata.annotations 不存在,则首先创建该路径。 """ if 'labels' in metadata: dic = metadata['labels'] else: dic = {} patch = [ # 添加 'labels' 键,如果不存在 {'op': 'add', 'path': '/metadata/labels', 'value': dic}, # 添加 'environment' 标签 {'op': 'add', 'path': '/metadata/labels/environment', 'value': 'production'} ] patch_json = json.dumps(patch) patch_base64 = base64.b64encode(patch_json.encode('utf-8')).decode('utf-8') return patch_base64 @app.route('/mutate', methods=['POST']) # https://webhook-service.default.svc:443/mutate def mutate(): """ 处理 Mutating Webhook 的请求,对 Pod 对象应用 JSON Patch。 """ admission_review = request.get_json() # 从请求中提取 AdmissionReview 对象 # 验证 AdmissionReview 格式是否正确 # admission_review['request']['object'] if 'request' not in admission_review or 'object' not in admission_review['request']: return jsonify({ 'kind': 'AdmissionReview', 'apiVersion': 'admission.k8s.io/v1', 'response': { 'allowed': False, # 如果格式无效,则禁止当前提交过来的资源请求 'status': {'message': 'Invalid AdmissionReview format'} } }) req = admission_review['request'] # 提取请求对象 print('--->',req) # 生成 JSON Patch metata = req['object']['metadata'] patch_json = create_patch(metata) # 准备 AdmissionResponse 响应 admission_response = { 'kind': 'AdmissionReview', 'apiVersion': 'admission.k8s.io/v1', 'response': { 'uid': req['uid'], 'allowed': True, 'patchType': 'JSONPatch', 'patch': patch_json # 直接包含 Patch 数据作为 JSON 字符串 } } print(admission_response) return jsonify(admission_response) if __name__ == '__main__': # 加载 SSL 证书和私钥 context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) context.load_cert_chain('/certs/tls.crt', '/certs/tls.key') # Run the Flask application with SSL app.run(host='0.0.0.0', port=443, ssl_context=context) EOF python webhook.py(2)制作镜像(包含webhook.py的运行环境,依赖python3解释器、依赖flask框架)文件dockerfile内容如下# 使用官方 Python 镜像作为基础镜像 FROM python:3.9-slim # 设置工作目录 WORKDIR /app # 将当前目录的所有文件复制到容器的 /app 目录 COPY webhook.py . # 安装 Flask 及其依赖 RUN pip install Flask # 启动 Flask 应用 CMD ["python", "webhook.py"] 然后构建镜像:docker build -t egon-mute-webhook:v1.0 .打标签上传docker tag c0f805ffaa01 registry.cn-guangzhou.aliyuncs.com/xingcangku/egon-mute-webhook:v1.0 docker push registry.cn-guangzhou.aliyuncs.com/xingcangku/egon-mute-webhook:v1.0(3)配置 Webhook 的 Secret# 生成 CA 私钥 openssl genrsa -out ca.key 2048 # 生成自签名 CA 证书,有效期为 100 年 openssl req -x509 -new -nodes -key ca.key -subj "/CN=webhook-service.default.svc" -days 36500 -out ca.crt创建证书请求的配置文件cat > webhook-openssl.cnf << 'EOF' [req] default_bits = 2048 prompt = no default_md = sha256 req_extensions = req_ext distinguished_name = dn [ dn ] C = CN ST = Shanghai L = Shanghai O = egonlin OU = egonlin CN = webhook-service.default.svc [ req_ext ] subjectAltName = @alt_names [alt_names] DNS.1 = webhook-service DNS.2 = webhook-service.default DNS.3 = webhook-service.default.svc DNS.4 = webhook-service.default.svc.cluster.local [req_distinguished_name] CN = webhook-service.default.svc [v3_req] keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names [ v3_ext ] authorityKeyIdentifier=keyid,issuer:always basicConstraints=CA:FALSE keyUsage=keyEncipherment,dataEncipherment extendedKeyUsage=serverAuth,clientAuth subjectAltName=@alt_names EOF使用webhook-openssl.cnf这个配置文件生成 CSR:# 生成 Webhook 服务的私钥 openssl genrsa -out webhook.key 2048 # 使用 OpenSSL 配置文件生成 CSR openssl req -new -key webhook.key -out webhook.csr -config webhook-openssl.cnf openssl x509 -req -in webhook.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out webhook.crt -days 36500 -extensions v3_ext -extfile webhook-openssl.cnf #最终得到webhook.crt、webhook.key将生成的证书和私钥存储在 Kubernetes Secret 中#可能有残留可以先删一下 kubectl delete secrets webhook-certs kubectl create secret tls webhook-certs \ --cert=webhook.crt \ --key=webhook.key \ --namespace=default --dry-run=client -o yaml | kubectl apply -f -3.创建deployment来部署webhook服务cat > webhook-deployment.yaml << 'EOF' apiVersion: apps/v1 kind: Deployment metadata: name: webhook-deployment namespace: default spec: replicas: 1 selector: matchLabels: app: webhook template: metadata: labels: app: webhook spec: containers: - name: webhook image: registry.cn-guangzhou.aliyuncs.com/xingcangku/axingcangku:v2.0 command: [ "/bin/sh", "-c", "tail -f /dev/null" ] volumeMounts: - name: webhook-certs mountPath: /certs readOnly: true volumes: - name: webhook-certs secret: secretName: webhook-certs --- apiVersion: v1 kind: Service metadata: name: webhook-service namespace: default spec: ports: - port: 443 targetPort: 443 selector: app: webhook EOF4.基于kind: mutatingwebhookconfiguration 该资源类型创建出一个资源,相当于于一道关卡在该资源中声明把请求转给的目标webhook程序的api地址基于脚本来生成yaml:cat a.sh#!/bin/bash base64 -w 0 ca.crt > ca.crt.base64 # 定义文件路径 ca_base64_file="ca.crt.base64" yaml_file="m-w-c.yaml" # 读取 ca.crt.base64 的内容 ca_base64_content=$(cat "$ca_base64_file" | tr -d '\n') # 生成替换后的 YAML 文件内容 # 将 base64 内容插入到 YAML 文件中 cat <<EOF > "$yaml_file" apiVersion: admissionregistration.k8s.io/v1 kind: MutatingWebhookConfiguration metadata: name: example-mutating-webhook webhooks: - name: example.webhook.com clientConfig: service: name: webhook-service namespace: default path: "/mutate" # 替换为 cat ca.crt.base64的内容 caBundle: "$ca_base64_content" rules: - operations: ["CREATE"] apiGroups: [""] apiVersions: ["v1"] resources: ["pods"] admissionReviewVersions: ["v1"] sideEffects: None EOF echo "YAML 文件已更新。" 5、创建pod进行测试[root@k8s-master-01 word]# cat test.yaml apiVersion: v1 kind: Pod metadata: name: test-pod spec: containers: - name: nginx image: nginx:1.18
2023年08月20日
17 阅读
0 评论
0 点赞