基于cloudflare-worker的docker代理实践
本文介绍了一种基于 Cloudflare Worker 的 Docker 代理方案,用于高效访问官方 Docker 仓库和第三方 Docker 仓库(如 quay.io、k8s.gcr.io 等)。方案基于 cloudflare-docker-proxy,并记录了个人实践过程。
本文介绍了一种基于 Cloudflare Worker 的 Docker 代理方案,用于高效访问官方 Docker 仓库和第三方 Docker 仓库(如 quay.io、k8s.gcr.io 等)。方案基于 cloudflare-docker-proxy,并记录了个人实践过程。
本文介绍一种基于github action的解决方案用于实现private项目自动从public项目同步
不定期更新的服务器攻略指南。
记录服务器的配置管理、软件安装等信息,和附带文章索引。
直到2022年,wslg的体验仍较差,难以用于日常开发,大部分情况下不建议使用
本人使用win11+idea+docker+wsl2作为日常开发测试环境,
随着版本的迭代完善,加上本人丰富的踩坑经验,wsl已基本能满足我对linux单机使用的需求。
故重新整理wsl开发环境相关配置、优化、使用集成,形成本系列文章。
本文为WSL开发系列的开篇,也是目录,建议阅读此篇,再根据需求跳转。
工作经常会遇到需要离线安装软件的情况,特此记录下来,避免每次都得去翻笔记。
使用python实现自定义Transformer以对pyspark的pipeline进行增强
pyspark使用笔记,含1.jupyter-docker环境搭建 2.dataframe2jdbc,jdbc2dataframe 3.模型训练及保存 4.模型导入及使用 等。
工作要求,需要编写vbs实现将wincc数据导出,估计以后也没机会再接触这门古董语言了,所以就记录一下。
因为wincc用得太少了,测试中会使用mysql代替。
本文主要记录hdfs-ftp-server的设计思路、实现过程,使用的话直接看github项目文档即可。
项目地址:https://github.com/linshenkx/hdfs-ftp-server
自用笔记:ubuntu(18.04)制作离线源
.png)
直到2022年,wslg的体验仍较差,难以用于日常开发,大部分情况下不建议使用
以我浅薄的开发经历来说,只有一次,
就是使用wsl的chrome浏览器访问被kerberos保护的hadoop web界面。
虽然理论上windows的浏览器也可以做到,但是麻烦得多。
而在linux系统中,kerberos认证就是kinit一个指令的事情。
这个教程比较多,而且写得都不一样,但大同小异,需要注意的是
输入法没有切换处理很可能是快捷键被windows系统的覆盖了,
需要手动调出来输入法的配置界面,修改快捷键
比方说fcix的是fcitx-config-gtk3命令
然后我的配置是这样的,就是shift键,保持和windows使用习惯统一![]()
这里的教程可以参考:https://monkeywie.cn/2021/09/26/wsl2-gui-idea-config/
搜狗输入法参考:https://zhuanlan.zhihu.com/p/142206571
搜狗输入法配置命令:sogouIme-configtool
我的配置和里面的不一样, 也没有遇到idea切不出输入法的问题
如果有的话参考文章里的方法或者看:https://github.com/microsoft/wslg/issues/278
cd ~/.local/share/applicationssudo cp *.desktop /usr/share/applications参考链接:https://juejin.cn/post/6966630345915498526
很多linux的软件默认不支持root用户启动,如chrome,会报错:
Running as root without --no-sandbox is not supported. See https://crbug.com/638180
这是报错原理:
wslg的应用通过windows快捷方式启动时,用的是wsl默认用户,
而我设置的默认用户是root,会导致闪退。
因为wslg我使用频率很低,故没必要特地去把默认用户改为普通用户。
这里介绍下几种处理方法
使用范围:平常习惯使用sudo命令操作的
有效期:永久
Ubuntu-20.04 config --default-user 系统安装时创建的用户适用范围:可以在启动命令中添加特定选项规避问题的,如chrome可使用--no-sandbox
有效期:直到软件更新(图标刷新)
以下为例子
去 /usr/share/applications 目录对chrome的快捷方式进行编辑,修改其启动命令
vim /usr/share/applications/google-chrome.desktop在其Exec列添加 --no-sandbox ,如下
Exec=/usr/bin/google-chrome-stable --no-sandbox %U适用范围:所有
有效期:重启失效
有些软件(如firefox)就是不支持root用户运行,
这个时候需要修改其windows图标对应启动命令,指定用户启动
如下,linux的图标所在文件夹类似:C:\Users\用户名\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Ubuntu-20.04
将快捷方式-属性-目标由“C:\Windows\System32\wslg.exe ~ -d Ubuntu-20.04 firefox”改为
“C:\Windows\System32\wslg.exe ~ -d Ubuntu-20.04 su 用户名 -c firefox”
![]()
![]()
适用范围:所有
有效期:shell会话
su 普通用户google-chrome/firefoxwslg-chrome安装见:https://learn.microsoft.com/en-us/windows/wsl/tutorials/gui-apps#run-linux-gui-apps
mkdir -p /etc/opt/chrome/policies/managed/cat << 'EOF' > /etc/opt/chrome/policies/managed/kerberos.json{ "AuthServerAllowlist": "*", "AuthNegotiateDelegateAllowlist": "*" }EOFkinit -kt /home/admin02.service.keytab admin02/adp@HADOOP.COMgoogle-chrome --no-sandbox参考 https://blog.csdn.net/sinat_20554629/article/details/105283518 ,
在Windows上,必须使用Firefox + MIT Kerberos Windows客户端进行认证
不支持edge、chrome、ie等
firefox访问kerberos参考:
https://blog.csdn.net/IUNIQUE/article/details/108615090
https://www.cnblogs.com/kischn/p/7443343.html
具体操作流程参考如下:
1.下载并安装mit kerberos客户端
下载地址:https://web.mit.edu/kerberos/dist/
2.修改PATH
安装完了kerberos就自动的在 PATH 里面加上了自己的目录,但是在最后。
jdk也自带了kerberos工具,所以需要跳转PATH里kerberos的优先级在前面
3.将krb5.conf文件内容复制到krb5.ini
完整默认路径:C:\ProgramData\MIT\Kerberos5\krb5.ini
4.kinit登录
5.修改firefox配置
1. 输入 about:config
2. 修改配置项 network.negotiate-auth.trusted-uris 的值为: master01,worker01
3. 修改配置项 network.auth.use-sspi 的值为: false
4. 重启firefox
6.使用firefox打开kerberos页面
注意:机器重启会导致kinit信息失效
因gitlab-ci的k8s-runner会将job里的每个stage都交由单独的pod来执行,导致默认的本地缓存无法使用。
本文记录了基于k8s pv的gitlab-ci的缓存配置方案,无需使用S3分布式存储。
并记录了gitlab-ci-k8s-runner相关的配置、部署步骤等。
参考:https://blog.csdn.net/xichenguan/article/details/101439395
Gitlab cache 机制可以大大加快 CI/CD Job 的执行速度。基础知识可以参看 Gitlab Cache。
下面直接总结在 Kubernetes 环境中的三种 Cache 的解决方案。1. Distributed runners caching
gitlab runner job执行前从分布式存储中检查下载解压 cache 文件,job执行后,压缩上传 cache 文件到分布式存储。这是 gitlab 提供的通用的正宗的方法,在非 Kubernetes 环境中也可以使用;
2. 给 Job Executor Pod 挂载同一个 volume
gitlab runner 提供了本地存储 cache 的方式,如果远程存储没有配置,gitlab runner 照样会压缩 cache 文件,然后按照目录规则存储到指定的目录。这种方式的原理是将此目录配置为 Kubernetes Volume,每个 Job 执行时都挂载此 Volume ,这样就相当于所有的 Job 有了一个集中式的存储。可以参考 使用GitLab CI在Kubernetes服务上运行GitLab Runner并执行Pipeline 尝试配置。
3. 不使用缓存,在 Kubernetes 集群中安装各类仓库的私服
Gitlab CI/CI Job 执行时,配置为使用这些私服,速度也很快。
注意:方式1一般指S3存储,建议使用方式2
export CACHE_DIR=/home/runner-cachemkdir -p $CACHE_DIRchmod -R 777 $CACHE_DIRecho "$CACHE_DIR *(rw,sync,no_root_squash,all_squash,no_subtree_check,anonuid=0,anongid=0)" >> /etc/exportsexportfs -ashowmount -e localhostkubectl -n=命名空间 apply -f gitlab-runner-pv-pvc.yamlkubectl -n=命名空间 create secret docker-registry myregistrykey --docker-server=DUMMY_SERVER \ --docker-username=DUMMY_USERNAME --docker-password=DUMMY_DOCKER_PASSWORD kubectl -n=命名空间 get secret myregistrykeykubectl -n=命名空间 get secret myregistrykey --output=jsongitlab-runner镜像
docker tag registry.gitlab.com/gitlab-org/gitlab-runner:alpine-v15.8.0 私有仓库/gitlab-runner:alpine-v15.8.0docker push 私有仓库/gitlab-runner:alpine-v15.8.0gitlab-runner-helper镜像
docker tag registry.gitlab.com/gitlab-org/gitlab-runner/gitlab-runner-helper:x86_64-12335144 私有仓库/gitlab-runner-helper:x86_64-12335144docker push 私有仓库/gitlab-runner-helper:x86_64-12335144参考:https://docs.gitlab.com/runner/install/kubernetes.html
默认values.yaml文件:https://gitlab.com/gitlab-org/charts/gitlab-runner/blob/main/values.yaml
helm repo add gitlab https://charts.gitlab.iohelm repo update gitlabhelm install --dry-run --debug --namespace 命名空间 \gitlab-runner -f values.yaml gitlab/gitlab-runner > gitlab-runner-all.yamlkubectl -n=命名空间 apply -f gitlab-runner-all.yamldocker run -d --name gitlab-runner --restart always \ -v /home/gitlab-runner/config:/etc/gitlab-runner \ -v /var/run/docker.sock:/var/run/docker.sock \ gitlab/gitlab-runner:latestdocker run --rm -it -v /home/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner registerdocker restart gitlab-runnerdocker logs -f gitlab-runner在gitlab修改配置runner,支持运行未标记的作业
apiVersion: v1kind: PersistentVolumemetadata: name: gitlab-runner-cache-pvspec: storageClassName: gitlab-runner capacity: storage: 100Gi accessModes: - ReadWriteMany nfs: server: $NFS_SERVER path: "$NFS_PATH"---apiVersion: v1kind: PersistentVolumeClaimmetadata: name: gitlab-runner-cache-pvcspec: accessModes: - ReadWriteMany storageClassName: gitlab-runner resources: requests: storage: 100Gi参考:
image: registry: "自行填写" image: "自行填写" tag: "自行填写"imagePullPolicy: IfNotPresentimagePullSecrets: - name: "自行填写"gitlabUrl: "自行填写"runnerRegistrationToken: "自行填写"# runnerToken: ""# unregisterRunners: trueterminationGracePeriodSeconds: 3600# certsSecretName:concurrent: 10checkInterval: 30# logLevel:# logFormat:# sentryDsn:preEntrypointScript: | echo "hello"sessionServer: enabled: false # annotations: {} # timeout: 1800 # internalPort: 8093 # externalPort: 9000 # publicIP: "" # loadBalancerSourceRanges: # - 1.2.3.4/32## For RBAC support:rbac: create: true rules: [] # - resources: ["configmaps", "pods", "pods/attach", "secrets", "services"] # verbs: ["get", "list", "watch", "create", "patch", "update", "delete"] # - apiGroups: [""] # resources: ["pods/exec"] # verbs: ["create", "patch", "delete"] clusterWideAccess: false # serviceAccountName: default # serviceAccountAnnotations: {} podSecurityPolicy: enabled: false resourceNames: - gitlab-runner ## Specify one or more imagePullSecrets used for pulling the runner image ## ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account ## imagePullSecrets: []metrics: enabled: false portName: metrics port: 9252 serviceMonitor: enabled: false ## labels: {} # interval: "" # scheme: "http" # tlsConfig: {} # path: "/metrics" # metricRelabelings: [] ## relabelings: []service: enabled: false # labels: {} # annotations: {} # clusterIP: "" # externalIPs: [] # loadBalancerIP: "" # loadBalancerSourceRanges: [] type: ClusterIP # metrics: # nodePort: "" # additionalPorts: []runners: # runner configuration, where the multi line strings is evaluated as # template so you can specify helm values inside of it. # # tpl: https://helm.sh/docs/howto/charts_tips_and_tricks/#using-the-tpl-function # runner configuration: https://docs.gitlab.com/runner/configuration/advanced-configuration.html # 见:1. https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnerskubernetes-section # 2. https://docs.gitlab.com/runner/executors/kubernetes.html#overwriting-container-resources config: | [[runners]] cache_dir = "/cache" [runners.kubernetes] namespace = "自行填写" image = "自行填写" privileged = true image_pull_secrets = ["自行填写"] image_pull_policy = "if-not-present" helper_image = "自行填写" helper_cpu_limit = "1000m" helper_memory_limit = "2048Mi" helper_cpu_requests = "200m" helper_memory_requests = "512Mi" service_cpu_limit = "1000m" service_memory_limit = "2048Mi" service_cpu_requests = "200m" service_memory_requests = "512Mi" cpu_limit = "1000m" cpu_limit_overwrite_max_allowed = "5000m" memory_limit = "2048Mi" memory_limit_overwrite_max_allowed = "10240Mi" cpu_requests = "200m" cpu_requests_overwrite_max_allowed = "5000m" memory_requests = "512Mi" memory_requests_overwrite_max_allowed = "10240Mi" [[runners.kubernetes.volumes.host_path]] name = "docker" mount_path = "/var/run/docker.sock" read_only = true host_path = "/var/run/docker.sock" [[runners.kubernetes.volumes.pvc]] name = "gitlab-runner-cache-pvc" mount_path = "/cache"securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: false runAsNonRoot: true privileged: false capabilities: drop: ["ALL"]podSecurityContext: runAsUser: 100 # runAsGroup: 65533 fsGroup: 65533 # supplementalGroups: [65533] ## Note: values for the ubuntu image: # runAsUser: 999 # fsGroup: 999## Configure resource requests and limits## ref: http://kubernetes.io/docs/user-guide/compute-resources/##resources: limits: memory: 2048Mi cpu: 1000m requests: memory: 512Mi cpu: 200maffinity: {}nodeSelector: {}tolerations: []# envVars:# - name: RUNNER_EXECUTOR# value: kuberneteshostAliases: [] # Example: # - ip: "127.0.0.1" # hostnames: # - "foo.local" # - "bar.local" # - ip: "10.1.2.3" # hostnames: # - "foo.remote"# - "bar.remote"podAnnotations: {} # Example:# iam.amazonaws.com/role: <my_role_arn>podLabels: {} # Example: # owner.team: <my_cool_team>priorityClassName: ""secrets: [] # Example: # - name: my-secret # - name: myOtherSecret # items: # - key: key_one# path: path_oneconfigMaps: {}volumeMounts: - name: cache mountPath: /cachevolumes: - name: cache persistentVolumeClaim: claimName: gitlab-runner-cache-pvc
使用docker部署tailscale私有中继服务器,并使用nginx四层代理与原有服务共用443端口,最后配置使用并检测。
derper-docker部署及使用较麻烦,本文分享踩坑记录及经验,建议阅读。
推荐阅读:
官方说明(https://tailscale.com/kb/1118/custom-derp-servers/)
TAILSCALE 的一些使用心得(https://leitalk.com/12245)
Tailscale 基础教程:部署私有 DERP 中继服务器(https://icloudnative.io/posts/custom-derp-servers)
参考:https://hub.docker.com/r/fredliang/derper
下面是我个人的配置
注意:
mkdir -p /data/derper/certsdocker rm -f derperdocker run -d \-p 3443:443 \-p 3478:3478/udp \--name derper \--restart=always \-v /data/derper/certs:/app/certs \-v /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock \-e DERP_ADDR=":443" \-e DERP_VERIFY_CLIENTS=true \-e DERP_DOMAIN="derper.linshenkx.cn" \fredliang/derperdocker logs -f derper![]()
虽然有些人说derper运行一段时间就会崩溃(Derper TLS handshake error: remote error: tls: internal error),
但我没有遇到过,按照官方issue和TAILSCALE 的一些使用心得里的说法,可能和墙/备案有关。
顺带一提,如腾讯云这样的国内云服务器提供商,会审查 TLS handshake 里的 SNI 信息, 如果发现 SNI 域名未备案,会阻断 TLS 握手。 所以,我曾经也尝试过用一个境外服务器的域名,然后指向到境内服务器 IP 的形式尝试绕过备案, 然而短暂的用了几分钟后,就遇到了 tls handshake reset 的问题。 目前看来,只要你想用境内服务器,那么备案就是绕不过的问题。
Ps. 如果你有备案域名,那么可以用 nginx stream 反向代理的形式做 443 端口 4 层转发。 nginx stream 可以在四层探测 SNI 信息,然后分发到不同的后端,这样你 derper 的 443 和其他域名的 443 就可以共存在同一个服务器上了。
这里主要知识点是:
具体配置参考我的另外一篇文章:TODO
Access Contros配置内容参考如下:
主要是添加了derpMap,其他都保持默认。
如果有多个derper服务器,建议配置为多个region而非node。
因为延迟的比较是以region为单位的,会方便测试。
一开始不确定derper是否运行正常的时候,建议先把OmitDefaultRegions设置为true,关闭默认的region。
另外,修改Access Contros后,需要重启tailscale服务才能生效!
// Example/default ACLs for unrestricted connections.{ // Declare static groups of users beyond those in the identity service. "groups": { "group:example": [ "user1@example.com", "user2@example.com" ], }, // Declare convenient hostname aliases to use in place of IP addresses. "hosts": { "example-host-1": "100.100.100.100", }, // Access control lists. "acls": [ // Match absolutely everything. Comment out this section if you want // to define specific ACL restrictions. { "action": "accept", "users": ["*"], "ports": ["*:*"] }, ] , "derpMap": { "OmitDefaultRegions": false , "Regions": { "900": { "RegionID": 900, "RegionCode": "lian", "RegionName": "LIAN", "Nodes": [{ "Name": "tx", "RegionID": 900, "HostName": "derper.linshenkx.cn", "DERPPort": 443 } ] } // , // "901": { // "RegionID": 901, // "RegionCode": "lian2", // "RegionName": "LIAN2", // "Nodes": [{ // "Name": "uc", // "RegionID": 901, // "HostName": "derper2.linshenkx.cn", // "DERPPort": 443 // } // ] // } } }}相关命令
# 显示集群状态tailscale status# 显示网络状态tailscale netchecktailscale ping 节点如下图,自定义的derper比默认的延迟要低不上。
(不过只有在极端情况下流量才会走derper,通常derper只要连得上就行,所以延迟影响不大)![]()
需要注意的是,这里显示一切正常,不代表derper就是在正常工作了。
只是说能访问到 https://derper.linshenkx.cn 而已。
关键还是要看ping。![]()
如图,代表了几种情况:
derper日志类似如下![]()
工作经常会遇到需要离线安装软件的情况,特此记录下来,避免每次都得去翻笔记。
在本地创建data目录并挂载到容器里,方便将生成的依赖取出。
mkdir -p /home/lin/ubuntu22/datadocker rm -f ubuntu22docker run -d --name ubuntu22 -v /home/lin/ubuntu22/data:/data ubuntu:22.04 tail -f /dev/nulldocker exec -it ubuntu22 /bin/bash参考阿里的开源镜像站:https://developer.aliyun.com/mirror/
cp -a /etc/apt/sources.list /etc/apt/sources.list.bak \ && sed -i "s@http://.*archive.ubuntu.com@http://repo.huaweicloud.com@g" /etc/apt/sources.list \ && sed -i "s@http://.*security.ubuntu.com@http://repo.huaweicloud.com@g" /etc/apt/sources.list \ && apt-get update以nfs-common为例
apt-get cleanmkdir /data/nfsapt-get install --reinstall -d -y nfs-commonmv /var/cache/apt/archives/*.deb /data/nfs/将生成的文件夹拷贝到目标集群上
dpkg -i *.deb本文主要记录hdfs-ftp-server的设计思路、实现过程,使用的话直接看github项目文档即可。
项目地址:https://github.com/linshenkx/hdfs-ftp-server
hdfs-ftp-server这个项目我在20年的时候就开源过一版了,先做一下前提介绍。
因为我们大数据平台是容器化的,一些简单的操作也需要进入容器里面才能执行,而且传递文件也很繁琐。
所以那时候的主要需求就是实现功能,即通过ftp的方式实现对hdfs文件系统的操作,方便日常操作。
那时候主要是参考github上一些老一点的项目进行改造升级,以适配高可用、kerberos认证连接。
然后再进行易用性改造,更适合生产环境使用。
核心思路是对外作为ftp服务器,内部使用hdfs实现接口功能即可,很简单的功能。
那时候用的hadoop是官方的2.9.2,后面hadoop升级到3.3.1了,
而且有时候还得对接cdh的hadoop,这个时候这个工程就不能直接拿来用了。
这种时候常规解决办法就是修改一下依赖,重新编译。
但是我觉得太麻烦了,这样也不利于代码的管理。
所以就一直想着要把这个工程模块化,核心工程独立且不常变,其他的作为模块工程对接各个版本的hadoop客户端。
针对第一版存在的问题,第二版主要是对项目进行模块化改造
最开始我目标是很明确的,就是用蚂蚁金服的ark框架来实现类隔离,
毕竟不同大版本/发行版本的hdfs依赖多少会有类冲突,直接用是肯定不放心的。
ark我之前就一直有在留意,也跑过demo,觉得还是可以寄予厚望的。
事实上这个工程重构所用的时间一大半都花在ark上。
本来是想把各个实现模块作为ark的插件的,发现ark的插件又不支持动态插拔,其核心是类隔离而不是模块化。
那就把每个模块作为service,来实现动态引用,这也是可以的,也确实改好代码打包好了。
但最终运行的时候还是有bug,类似于:https://github.com/sofastack/sofa-ark/issues/421。
终于还是折腾不下去,放弃ark了,开源支持太差了,我水平有限,玩不动。
不用ark,osgi又太重了,没必要,那就还是老老实实用java的spi吧。
类似于jdbc的用法,添加对应jar包,指定类名进行加载。
但spi并不能实现类隔离,所以就预先打包好各个jar包,运行时再根据对接hadoop版本进行加载。
即每个模块形成一个fatjar,如cdh632.jar,official331.jar。
在对接cdh6.3.2的时候将cdh632.jar添加到类路径下即可,如果是对接官方3.3.1则添加official331.jar。
这里还有一个问题,要不要把hadoop的依赖包也一并打包呢?
这个倒没纠结太久,还是打包了。缺点是体积大很多,优点是摆脱依赖。
你只需要给我hadoop的连接配置文件就行了,而不需要整个hadoop客户端环境。
至于包大点就大点,不差那点流量、空间。
为了简化、统一子模块的开发,我又把gradle任务统一定义在父工程的build.gradle里面。
让子模块更加的简单易懂。
https://github.com/linshenkx/hdfs-ftp-server
应该说还是比较满意的。
虽然就技术来说很简单,毕竟别人十年前就做过的东西,
但还是花了很多时间、心思在上面折腾,把这个小东西做得好用一些。
在这个过程也算有点收获吧。