对项目重构时有这样一个需求,1)要把代码库某个目录下的所有代码作为一个新代码库的根目录,2)并且之前所有的代码提交记录要一并迁移到这个新的git repo。
当你尝试用
git filter-branch --subdirectory-filter YOUR_SUB_DIR -- --all
来解决问题时,会看到一个警告推荐我们使用 git
filter-repo
。它是一个用于重写git history的多功能小工具,用法参考
filter-repo使用手册
。我们的需求在这里只是它的一个小case。
下面直接列出操作步骤:
- Composite Configuration, 因为可以通过 log4j2.configurationFile 设置多个逗号分隔的配置文件,log4j有一套自己的逻辑对多个配置文件进行merge。所以除非项目中有特定的需求,显示的通过log4j2.configurationFile显示的指定配置文件可以减少不必要的困惑。
在连接上一个 K8S cluster 后执行下面的命令可以看到系统中的ingressclasses。这篇文字用来帮助自己理解下面几行简单的输出。
╰─$ kubectl get ingressclass
NAME CONTROLLER PARAMETERS AGE
awslb ingress.k8s.aws/alb IngressClassParams.elbv2.k8s.aws/alb 20d
nginx nginx.org/ingress-controller <none> 30d
os-nginx k8s.io/ingress-nginx <none> 30d
一些Ingerss Controller实现。
而这篇文章详细讲解了各种Ingress Controller的特性以方便我们根据自己项目的需求做出选择。直接贴上文章的干货图片:
在一个Kubernets集群里可以定义多个不同Ingress Controller实现/类型,那么Ingress对象如何知道自己的数据是提供给哪个Ingress Controller的呢?
在Kubernetes 1.18之前,是通过在Ingress的一个annotation kubernets.io/ingress.class
来声明。
在Kubernetes 1.18正式引入了一个新的k8s资源对象 IngressClass 来帮助Ingress定义它绑定到哪个IngressController。
下面是一个官网的IngressClass对象定义示例,spec.controll
定义了IngressController的实现, spec.parameters
相当于定义了你可以在Ingerss对象里可以向这个IngressController对象能够传递的参数,当然这些参数也是这种IngressControll必须支持的。不同的Ingress Controller实现其需要的parameter肯定是不同的,而k8s 1.18之前通过annoation给IngerssController传递参数的方式就显得比较随意无章可循了,这应该也是IngressClass出现的一个原因。
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb
spec:
controller: example.com/ingress-controller
parameters:
apiGroup: k8s.example.com
kind: IngressParameters
name: external-lb
有了IngressClass,那么在Ingress中只要设置 spec.ingressClassName
为某个IngerssClass的名字,那么就意味着这个Ingress的配置就会被这个IngerssClass所对应的IngressController所获取并被这个IngressControll生成为对应的路由rules,从而完成把一个集群外请求路由到Service的功能。
以上就是关于Kubernetes里Ingerss的几个基本概念。
code doc。
Nginx版自己又分为免费的基于开源Nginx的IngressController实现和商业版。Nginx开源版code doc。
所以就开源的版本来说,一个是Kubernets社区版,一个是Nginx开源版,两个都是基于开源的Nginx实现的,只是owner不通。表现在IngressClass的定义中,就是字段 spec.controller
的值一个是Kubernets社区版的 k8s.io/ingress-nginx
, 一个是nginx开源版的 nginx.org/ingress-controller
下面这个表格列出了Nginx Ingress Controller的 Kubernets社区版和Nginx开源版的区别。可以看到,两者差别不大,k8s社区版功能略好于Nginx开源版。而Nginx开源版因为没有使用Lua性能又好于k8s社区版。
Aspect or Feature
kubernetes/ingress-nginx
nginxinc/kubernetes-ingress with NGINX
nginxinc/kubernetes-ingress with NGINX Plus
Fundamental
NGINX version
Custom NGINX build that includes several third-party modules
NGINX official mainline build
NGINX Plus
Commercial support
Included
Implemented in
Go/Lua (while Nginx is written in C)
Go/Python
Go/Python
Load balancing configuration via the Ingress resource
HTTP load balancing extensions - Annotations
See the supported annotations
See the supported annotations
See the supported annotations
HTTP load balancing extensions – ConfigMap
See the supported ConfigMap keys
See the supported ConfigMap keys
See the supported ConfigMap keys
TCP/UDP
Supported via a ConfigMap
Supported via custom resources
Supported via custom resources
Websocket
Supported
Supported via an annotation
Supported via an annotation
TCP SSL Passthrough
Supported via a ConfigMap
Supported via custom resources
Supported via custom resources
JWT validation
Not supported
Not supported
Supported
Session persistence
Supported via a third-party module
Not supported
Supported
Canary testing (by header, cookie, weight)
Supported via annotations
Supported via custom resources
Supported via custom resources
Configuration templates
See the template
See the templates
See the templates
Load balancing configuration via Custom Resources
Not supported
See VirtualServer and VirtualServerRoute resources
See VirtualServer and VirtualServerRoute resources
TCP/UDP load balancing
Not supported
See TransportServer resource
See TransportServer resource
TCP SSL Passthrough load balancing
Not supported
See TransportServer resource
See TransportServer resource
Deployment
TLS certificate and key for the default server
Required as a command-line argument/ auto-generated
Required as a command-line argument
Required as a command-line argument
Helm chart
Supported
Supported
Supported
Operator
Not supported
Supported
Supported
Operational
Reporting the IP address(es) of the Ingress controller into Ingress resources
Supported
Supported
Supported
Extended Status
Supported via a third-party module
Not supported
Supported
Prometheus Integration
Supported
Supported
Supported
Dynamic reconfiguration of endpoints (no configuration reloading)
Supported with a third-party Lua module
Not supported
Supported
再回到文章开头的命令输出,是不是看到的更多了些?
╰─$ kubectl get ingressclass
NAME CONTROLLER PARAMETERS AGE
awslb ingress.k8s.aws/alb IngressClassParams.elbv2.k8s.aws/alb 20d
nginx nginx.org/ingress-controller <none> 30d
os-nginx k8s.io/ingress-nginx <none> 30d
References:
[1]: Ingress
[2]: IngressController
[3]: IngressClass
[4]: Comparing Ingress Controllers for Kubernetes
[5]: 基于Nginx的Ingress Controller在社区和商业版之间的比较
[6]: Kubernetes社区版
[7]: Nginx开源版
[8]: Nginx Ingress Controll社区版和Nginx开源版的比较
spring security 5.5 中被加入。从spring-security-core-6.0开始,AccessDecisionManager AccessDecisionVoter 已经被 deprecated,由 AuthorizationManager 取代其作用。 对于之前定制化AccessDecisionManager AccessDecisionVoter的代码应该考虑迁移到AuthorizationManager。
AuthorizationManager
AccessDecisionManager
AccessDecisionVoter
- 之前AccessDecisionManager 通过抛出异常,现在default的verify也是通过exception。
- 明确返回AuthorizationDecision来标识。
- 之前有support方法,跟AuthenticationProvider的思路很像。
从方法签名可以直接看出上面这几点。官方文档列出了更有意义的变化:
- AuthorizationManager的API相对于之前FilterSecurityInterCepter/AccessDecisionManager要使用metadata sources, config attributes, decison managers, voters进行授权判断要简化很多。
- 因为通过把AuthenticationManger放在Supplier中实现了对认证数据的延迟访问,这对一些无需认证的授权是有好处的。
- 支持基于Bean的配置。
https://docs.spring.io/spring-security/reference/servlet/authorization/authorize-http-requests.html
关于 FilterSecurityInterceptor,可参考: https://docs.spring.io/spring-security/reference/servlet/authorization/authorize-requests.html
References:
[1]: https://docs.spring.io/spring-security/reference/servlet/authorization/index.html
关于Spring Security里的Authentication,官方文档总结的不错。理解这些classes的作用与关系是正确使用Spring Security Authentication的前提。
认证的方式不同,认证逻辑就不同,这样每个认证方式都会有对应的fitler实现。执行认证的大致流程以 AbstractAuthenticationProcessingFilter 为例描述一下。不同类别的 Authentication Filter 的处理略有差异,但大体逻辑差不多:
- Authentication Filter 接收请求 http request。
- 从request中获取凭证(credential)等数据,封装在Authentication对象中,比如:OAuth2LoginAuthenticationToken, UsernamePasswordAuthenticationToken等。
- 用AuthenticationManager向对其传入的Authentication 进行实际的认证工作。
- 认证成功的处理,比如保存设置了授权信息的Authentication到SecurityContext中。
- 失败进行处理。
https://docs.spring.io/spring-security/reference/servlet/authentication/architecture.html
[2]: 《Spring Security in Action》
在项目中实际使用Spring Security时,我们的大部分工作其实都是配置HttpSecurity。要么通过spring的 http xml element 来配置,要么通过配置类里的HttpSecurity class来配置,所以在理解了DelegatingFilterProxy,FilterChainProxy,SecurityFilterChain之间的关系之后就很有必要了解一下HttpSecurity类了。
HttpSecurity这个类的名称与它的实际功用相差甚远,其实把它称为HttpSecurityFilterChainBuiler应该更合适,因为它的作用就是利用构造器模式构造出SecurityFilterChain的一个实例供FilterChainProxy使用。这点从它的类签名就能看出来。
如果有多个 SecurityFilterChain 被配置、构造出来,它们的顺序可以通过注解 @Order来设定。没有@Order注解的优先级最低。同一order层级的,就可以通过 SecurityFilterChain 中的RequestMatcher 来决定了该chain是否与http request匹配了。我们应该尽量把特殊的匹配放在前面,通用的放在后面。
https://docs.spring.io/spring-security/reference/servlet/configuration/java.html#jc-httpsecurity
[2]: https://docs.spring.io/spring-security/reference/servlet/configuration/java.html#_multiple_httpsecurity
[3]: https://docs.spring.io/spring-security/reference/servlet/configuration/java.html#jc-custom-dsls
[4]: https://www.baeldung.com/spring-onceperrequestfilter
这段文字主要源于对 https://docs.spring.io/spring-security/reference/servlet/architecture.html 的学习和理解,其实就是对下图的理解。
上图表达了下面几个类之间的关系:
DelegatingFilterProxy, FilterChainProxy (springSecurityFilterChain), SecurityFilterChain (security filter)
通过调用 SecurityFilterChain API 把 Security Filters 组装成一个或多个chain,再设置给FilterChainProxy使用。
对于下图这样FilterChainProxy有多个SecurityFilterChain的情况,只会触发第一个匹配的securityFilterChain。
https://www.baeldung.com/spring-web-contexts
[2]: https://docs.spring.io/spring-security/reference/servlet/architecture.html
[3]: https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-security-filters
项目中遇到多个微服务调用需要考虑和处理某个环节失败时的处理。虽然这里不需要很强的事务概念,但是需要对失败的动作进行重试等操作。这里的重试本质上就是rollback的另一种形式,在saga里算是“forward recovery”。
借机又翻看了一下相关的文章,贴到了文末。
https://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf
[2]: 《Microservice Pattern》”Chapter4, Managing transactions with sagas”
[3]: Chris Richardson 在2017年的演讲:https://www.youtube.com/watch?v=YPbGW3Fnmbc
一些中文网文:
[3] 分布式事务:Saga模式 https://www.jianshu.com/p/e4b662407c66
[4] 七种分布式事务的解决方案 https://cloud.tencent.com/developer/article/1806989
[5] 分布式事务六种解决方案 https://zhuanlan.zhihu.com/p/183753774
本文基本是基于此efs workshop的记录和扩展。
要创建一个EFS资源,大致有以下几个步骤:
要在哪个VPC上创建 –> 这个VPC上子网的CIDR
创建一个SG –> 设置这个SG的ingress rule: 对子网开放NFS的2049
创建EFS,根据需求设置不同的参数比如是否加密、备份、performance mode、throughput-mode 等。
找到VPC上的public subnet,在这些public subnet上创建Moint Target。
有了 mount targets,这个NFS就已经可以对外提供服务了。
如果需要对mount的网络文件系统的目录设置特定的user、group属性,那么可以通过在这个NFS上创建 Access Points 完成。
因为EFS是可以跨region在这个region的所有AZ中可用的一个NFS,所以需要 VPC ID 应该是比较容易理解的。
下面介绍一下如何通过 aws cli 创建EFS及其Access Points,完整的脚本可以在这里下载 create_efs.sh, create_access_points.sh。
https://github.com/kubernetes-sigs/aws-efs-csi-driver 查看完整的parameter列表。
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: efs-sc
provisioner: efs.csi.aws.com
mountOptions:
- tls
- iam
parameters:
provisioningMode: efs-ap
fileSystemId: fs-012345678901010
directoryPerms: "700"
gidRangeStart: "1000"
gidRangeEnd: "2000"
basePath: "/dynamic_provisioning"
Reference:
[1]: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/file-storage.html
[2]: https://docs.aws.amazon.com/efs/latest/ug/creating-using.html
[3]: https://docs.aws.amazon.com/cli/latest/reference/efs/create-file-system.html
[4]: https://docs.aws.amazon.com/cli/latest/reference/efs/create-access-point.html
[5]: https://docs.aws.amazon.com/efs/latest/ug/creating-using-create-fs.html#creating-using-fs-part1-cli
[6]: https://stackoverflow.com/questions/48830793/aws-vpc-identify-private-and-public-subnet
[7]: https://www.baeldung.com/linux/jq-command-json
[8]: https://aws.amazon.com/premiumsupport/knowledge-center/eks-troubleshoot-efs-volume-mount-issues/
[9]: https://github.com/kubernetes-sigs/aws-efs-csi-driver
- Use Amazon S3 with Amazon EC2
下面的这张概念图很好的描述各种存储的位置层次。
在EKS的node如果是基于EC2的,那么PV就可以利用以上除去S3之外的其余三种作为底层存储。
参考:https://docs.aws.amazon.com/eks/latest/userguide/storage.html
关于EC2可以使用的存储的特性、使用场景,推荐阅读官方文档:https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Storage.html。
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AmazonEFS.html。
也可以通过使用aws cli在命令行创建,https://www.eksworkshop.com/beginner/190_efs/launching-efs/。
下面是根据上文得到的,通过aws cli创建EFS的脚本。
假设,你的aws profile是myAwsProfile、eks所在region是us-west-2、eks集群名称是myCluster,而要创建的EFS名称是 my-test-efs
为了使用EFS需要创建SecurityGroup来允许对NFS端口2049的使用,这里设置SG名称为 SG_efs_demo。
https://docs.aws.amazon.com/efs/latest/ug/efs-access-points.html
ACCESS_POING_NAME=ap_db2
FILE_SYSTEM_ID=fs-055b5f1fcc7df3e4b
AP_DIR_USER='{"Uid": 70, "Gid": 70, "SecondaryGids": [70]}'
AP_ROOT_DIR='/mydataPath,CreationInfo={OwnerUid=70,OwnerGid=70,Permissions=0755}'
aws efs create-access-point --profile $AWS_PROFILE --region $AWS_REGION \
--tags Key=name,Value=$ACCESS_POING_NAME \
--client-token "$ACCESS_POING_NAME"_2 \
--file-system-id $FILE_SYSTEM_ID \
--posix-user $AP_DIR_USER \
--root-directory Path=$AP_ROOT_DIR