本文分享自华为云社区《基于istio实现多集群流量治理》,作者: 可以交个朋友。

一 背景

对多云、混合云等异构基础设施的服务治理是Istio重点支持的场景之一。为了提高服务的可用性,避免厂商锁定,企业通常会选择将应用部署在多个地域的多个集群,甚至多云、混合云等多种云环境下,多集群的方案逐步成为企业应用部署的最佳选择。因此越来越多的用户对跨集群的服务治理有着强烈的需求,在此背景下Istio作为ServiceMesh领域的事实标准,推出了多种多集群管理方案。

二 简介

目前Istio支持4种多集群模型。

  1. 扁平网络单控制面模型
  2. 扁平网络多控制面模型
  3. 非扁平网络单控制面模型
  4. 非扁平网络多控制面模型

多集群的单控制面模型是指多个集群共用同一套Istio控制面,多集群的多控制面模型指每个集群都要独立使用一套Istio控制面,无论是单控制面还是多控制面模型,每套Istio控制面(istiod)都要连接所有集群的Kube-apiserver,并且List-Watch获取所有集群的Service、Endpoint、Pod 、Node ,并控制面集群内或集群间的服务访问,但是只监听主集群的VirtualService、DestinationRule、Gateway等Istio API对象。

根据集群间网络是否扁平,Istio又对两种控制面模型进行了细分:

  • 扁平网络:多集群容器网络通过VPN等技术打通,Pod跨集群访问直通。
  • 非扁平网络:每个集群的容器网络都相互隔离,跨集群的访问不能直通,必须通过东西向网关

生产环境上在选择 Istio 多集群模型时,当然需要结合自己的实际场景来决定。如果集群之间的网络是扁平的,那么可以选择扁平网络模型,如果集群之间的网络是隔离的,那么可以选择非扁平网络模型。如果集群规模较小,那么可以选择单控制面模型,如果集群规模较大,那么可以选择多控制面模型。

本文档选择非扁平网络多控制面模型来进行安装说明:安装模型如下所示

非扁平网络多控制面模型有如下特点。

  1. 不同的集群不需要在一张大网下,即容器网络不需要三层打通,跨集群的服务访问通过Istio East-West Gateway转发。
  2. 每个kubernetes集群的Pod地址范围与服务地址范围没有限制,可以与其他集群重叠,不同集群之间互不干扰
  3. 每个Kubernetes集群的Sidecar仅连接到本集群的Istio控制面,通信效率更高。
  4. Istiod只监听主集群的Istio配置,因此 VirtualService、DestinationRule、Gateway 等资源存在冗余复制问题
  5. 同一集群内部服务访问: Pod之间直接连接;跨集群的服务访问:依赖DNS代理解析其他集群的服务域名,由于集群之间的网络相互隔离,所以依赖Remote集群的 East-west Gateway中转流量。

三 ClusterMesh 环境搭建

搭建 cluster1 和 cluster2 两个集群,然后每个集群上安装 Istio 控制平面, 且将两者均设置为主集群(primary cluster)。 集群 cluster1 在 network1 网络上,而集群 cluster2 在 network2 网络上。

3.1 前提条件

本次搭建环境信息如下: 使用Kind搭建Kubernetes集群,Kind版本为v0.19.0。 Kubernetes 版本为1.27.3 ; Istio 版本为 1.20.1。

在搭建k8s 集群之前确保Linux节点已安装docker kubectl 和 kind。

下载istioctl二进制

curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.20.1 TARGET_ARCH=x86_64 sh -
将 istioctl 客户端添加到路径

3.2 Kubernetes集群安装

cluster1和cluster2集群安装脚本如下

# create-cluster.sh
# This script handles the creation of multiple clusters using kind and the
# ability to create and configure an insecure container registry. set -o xtrace
set -o errexit
set -o nounset
set -o pipefail # shellcheck source=util.sh
NUM_CLUSTERS="${NUM_CLUSTERS:-2}"
KIND_IMAGE="${KIND_IMAGE:-}"
KIND_TAG="${KIND_TAG:-v1.27.3@sha256:3966ac761ae0136263ffdb6cfd4db23ef8a83cba8a463690e98317add2c9ba72}"
OS="$(uname)"
function create-clusters() {
local num_clusters=${1} local image_arg=""
if [[ "${KIND_IMAGE}" ]]; then
image_arg="--image=${KIND_IMAGE}"
elif [[ "${KIND_TAG}" ]]; then
image_arg="--image=kindest/node:${KIND_TAG}"
fi
for i in $(seq "${num_clusters}"); do
kind create cluster --name "cluster${i}" "${image_arg}"
fixup-cluster "${i}"
echo done
} function fixup-cluster() {
local i=${1} # cluster num if [ "$OS" != "Darwin" ];then
# Set container IP address as kube API endpoint in order for clusters to reach kube API servers in other clusters.
local docker_ip
docker_ip=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "cluster${i}-control-plane")
kubectl config set-cluster "kind-cluster${i}" --server="https://${docker_ip}:6443"
fi # Simplify context name
kubectl config rename-context "kind-cluster${i}" "cluster${i}"
}
echo "Creating ${NUM_CLUSTERS} clusters"
create-clusters "${NUM_CLUSTERS}"
kubectl config use-context cluster1 echo "Kind CIDR is $(docker network inspect -f '{{$map := index .IPAM.Config 0}}{{index $map "Subnet"}}' kind)" echo "Complete"

以上集群安装的过程中,为了istiod能够访问对方集群的apiserver地址,集群kube-apiserver的地址设置为master节点的地址。因为是kind部署的集群,两个集群的master节点本质上都是同个宿主机上的docker运行的容器。

确认cluster1和cluster2 是否就绪

 

3.3 使用MetalLB为网关分配ExternalIP

由于使用的是kind部署多集群,istio南北向网关和东西向网关创建需要创建LoadBalencer service,均需要使用到ExternalIP。这里借助metalLB 实现LB ip地址的分发和宣告。
查看kind搭建集群使用节点子网网段: 172.18.0.0/16
采用metalLB L2模式进行部署。

cluster1中的metalLB配置清单: metallb-config-1.yaml

### for cluster1
##配置IPAddressPool,用于lbip地址的分配。L2模式下,ippool地址和worker节点处于同一子网即可
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 172.18.1.230-172.18.1.240
---
##配置L2Advertisement,用于地址宣告
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: first-adv
namespace: metallb-system
spec:
ipAddressPools:
- first-pool

cluster2集群中的metalLB配置清单:metallb-config-2.yaml

### for cluster2
##配置IPAddressPool,用于lbip地址的分配。L2模式下,ippool地址和worker节点处于同一子网即可
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: second-pool
namespace: metallb-system
spec:
addresses:
- 172.18.1.241-172.18.1.252
---
##配置L2Advertisement,用于地址宣告
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: second-adv
namespace: metallb-system
spec:
ipAddressPools:
- second-pool

使用脚本进行安装

#!/usr/bin/env bash

set -o xtrace
set -o errexit
set -o nounset
set -o pipefail NUM_CLUSTERS="${NUM_CLUSTERS:-2}"
for i in $(seq "${NUM_CLUSTERS}"); do
echo "Starting metallb deployment in cluster${i}"
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.10/config/manifests/metallb-native.yaml --context "cluster${i}"
kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)" --context "cluster${i}"
## 增加等待时间,如果metallb负载没部署起来,创建IPAddressPool L2Advertisement 会报错
sleep 10
kubectl apply -f ./metallb-config-${i}.yaml --context "cluster${i}"
echo "----"
done

确认metalLB部署情况

确认IPAddressPool信息:

 

3.4 集群共享根CA 配置信任关系

为了支持安全的跨集群mTLS通信,多控制面模型要求每个集群的控制面Istiod都使用相同的CA机构颁发的中间CA证书,供Citatel签发证书使用,以支持跨集群的TLS双向认证。

Istio东西向网关(跨集群访问)工作时使用基于SNI的路由,它根据TLS请求的SNI,自动将其路由到SNI对应的Cluster,因此非扁平网络的跨网络访问要求所有流量都必须经过TLS加密。

在集群中插入证书和密钥,脚本如下(需要将该脚本移动到istio的安装包目录下):

#!/usr/bin/env bash

set -o xtrace
#set -o errexit
set -o nounset
set -o pipefail
NUM_CLUSTERS="${NUM_CLUSTERS:-2}"
##在istio安装包的顶层目录下 创建目录 用来存放证书和密钥
mkdir -p certs
pushd certs ##生成根证书和密钥
make -f ../tools/certs/Makefile.selfsigned.mk root-ca for i in $(seq "${NUM_CLUSTERS}"); do
##对于每个集群,为 Istio CA 生成一个中间证书和密钥
make -f ../tools/certs/Makefile.selfsigned.mk "cluster${i}-cacerts"
##对于每个集群,创建istio-system 命名空间
kubectl create namespace istio-system --context "cluster${i}"
## 对于每个集群,通过给istio系统命名空间打上topology.istio.io/network 标签添加网络标识
kubectl --context="cluster${i}" label namespace istio-system topology.istio.io/network="network${i}"
##对于每个集群,给工作节点node打上地域和可用区标签,便于istio实现地域故障转移、地域负载均衡
kubectl --context="cluster${i}" label node "cluster${i}-control-plane" topology.kubernetes.io/region="region${i}"
kubectl --context="cluster${i}" label node "cluster${i}-control-plane" topology.kubernetes.io/zone="zone${i}"
#在每个集群中,创建一个私密 cacerts,使用所有输入文件 ca-cert.pem, ca-key.pem,root-cert.pem 和 cert-chain.pem。
kubectl delete secret cacerts -n istio-system --context "cluster${i}"
kubectl create secret generic cacerts -n istio-system --context "cluster${i}" \
--from-file="cluster${i}/ca-cert.pem" \
--from-file="cluster${i}/ca-key.pem" \
--from-file="cluster${i}/root-cert.pem" \
--from-file="cluster${i}/cert-chain.pem"
echo "----"
done
执行脚本,将会生成根证书和中间证书等文件

3.5 Istio服务网格安装

为cluster1,和cluster2 集群安装多控制面istio网格。

将cluster1 设置为主集群,在istio的安装目录下执行如下命令

cat <<EOF > cluster1.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
values:
global:
meshID: mesh1
multiCluster: ##开启多集群配置
clusterName: cluster1 #指定k8s集群名称
network: network1 #指定网络标识
logging:
level: debug
EOF

将cluster2 设置为主集群,在istio的安装目录下执行如下命令

cat <<EOF > cluster2.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
values:
global:
meshID: mesh2
multiCluster: ##开启多集群配置
clusterName: cluster2 #指定k8s集群名称
network: network2 #指定网络标识
logging:
level: debug
EOF
编写自动化安装脚本
#!/usr/bin/env bash

set -o xtrace
set -o errexit
set -o nounset
set -o pipefail OS="$(uname)"
NUM_CLUSTERS="${NUM_CLUSTERS:-2}" for i in $(seq "${NUM_CLUSTERS}"); do echo "Starting istio deployment in cluster${i}" istioctl install --force --context="cluster${i}" -f "cluster${i}.yaml" echo "Generate eastwest gateway in cluster${i}" ## 在每个集群中安装东西向网关。
bash samples/multicluster/gen-eastwest-gateway.sh \
--mesh "mesh${i}" --cluster "cluster${i}" --network "network${i}" | \
istioctl --context="cluster${i}" install -y -f - echo done

执行脚本,进行istio的安装部署

稍等片刻后,等待安装完成

可以发现每个集群中的网关使用的ExternalIP信息为配置的metalLB设置的IPPool中的地址。

3.6 在东西向网关开放服务

因为集群位于不同的网络中,所以我们需要在两个集群东西向网关上开放所有服务(*.local)。 虽然此网关在互联网上是公开的,但它背后的服务只能被拥有可信 mTLS 证书的服务访问, 就像它们处于同一网络一样。执行下面的命令在两个集群中暴露服务:

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: cross-network-gateway
spec:
selector:
istio: eastwestgateway # 专用于东西向流量的网关
servers:
- port:
number: 15443 # 已经声明了
name: tls
protocol: TLS
tls:
mode: AUTO_PASSTHROUGH # 东西向网关工作模式是 TLS AUTO_PASSTHROUGH
hosts:
- "*.local" # 暴露所有的服务

分别在每个集群中应用上述Gateway配置:
kubectl -n istio-system --context=cluster${i} apply -f samples/multicluster/expose-services.yaml

3.7 配置secret以便istiod访问远程集群apiserver

每个k8s集群中的 istiod 需要 List-Watch 其他集群的 Kube-APIServer,使用 K8s 集群的凭据来创建 Secret 对象,以允许 Istio 访问远程 Kubernetes apiserver。

#!/usr/bin/env bash

set -o xtrace
set -o errexit
set -o nounset
set -o pipefail
OS="$(uname)"
NUM_CLUSTERS="${NUM_CLUSTERS:-2}" for i in $(seq "${NUM_CLUSTERS}"); do
for j in $(seq "${NUM_CLUSTERS}"); do
if [ "$i" -ne "$j" ]
then
echo "Enable Endpoint Discovery between cluster${i} and cluster${j}" if [ "$OS" == "Darwin" ]
then
# Set container IP address as kube API endpoint in order for clusters to reach kube API servers in other clusters.
docker_ip=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "cluster${i}-control-plane")
istioctl create-remote-secret \
--context="cluster${i}" \
--server="https://${docker_ip}:6443" \
--name="cluster${i}" | \
kubectl apply --validate=false --context="cluster${j}" -f -
else
istioctl create-remote-secret \
--context="cluster${i}" \
--name="cluster${i}" | \
kubectl apply --validate=false --context="cluster${j}" -f -
fi
fi
done
done

执行以上脚本:remote secret创建完成。

查看istiod日志发现已经监听远程集群了

四 Istio多集群流量治理实践

每个集群创建sample 命名空间,并设置sidecar自动注入

kubectl create --context=cluster1 namespace sample
kubectl create --context=cluster2 namespace sample kubectl label --context=cluster1 namespace sample \
istio-injection=enabled
kubectl label --context=cluster2 namespace sample \
istio-injection=enabled kubectl apply --context=cluster1 \
-f samples/helloworld/helloworld.yaml \
-l service=helloworld -n sample
kubectl apply --context=cluster2 \
-f samples/helloworld/helloworld.yaml \
-l service=helloworld -n sample

分别在不同集群部署不同版本的服务

把应用 helloworld-v1 部署到 cluster1:

kubectl apply --context=cluster1 \
-f samples/helloworld/helloworld.yaml \
-l version=v1 -n sample

把应用 helloworld-v2 部署到 cluster2:

kubectl apply --context=cluster2 \
-f samples/helloworld/helloworld.yaml \
-l version=v2 -n sample

部署测试客户端

kubectl apply --context=cluster1 \
-f samples/sleep/sleep.yaml -n sample
kubectl apply --context=cluster2 \
-f samples/sleep/sleep.yaml -n sample

确认负载实例部署成功,并且sidecar已经注入

4.1 验证跨集群流量

用 Sleep pod 重复调用服务 HelloWorld。 为了确认负载均衡按预期工作,需要从所有集群调用服务 HelloWorld。

从 cluster1 中的 Sleep pod 发送请求给服务 HelloWorld

从 cluster2 中的 Sleep pod 发送请求给服务 HelloWorld

4.3 验证从网关访问

通过网关访问服务端Helloworld

创建virtualservice、gateway等istio资源,配置清单如下

# helloworld-gateway.yaml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: helloworld-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: helloworld
spec:
hosts:
- "*"
gateways:
- helloworld-gateway
http:
- match:
- uri:
exact: /hello
route:
- destination:
host: helloworld
port:
number: 5000

注意: 两个集群都需要应用该配置

访问效果如下:

4.3 验证地域负载均衡

对流量进行更精细的控制,将 region1 -> zone1 和 region1 -> zone2 两个地区的权重分别为 80% 和 20%,使用 DestinationRule 来配置权重分布

# locality-lb-weight.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: helloworld
namespace: sample
spec:
host: helloworld.sample.svc.cluster.local
trafficPolicy:
connectionPool:
http:
maxRequestsPerConnection: 1
loadBalancer:
simple: ROUND_ROBIN
localityLbSetting:
enabled: true
distribute:
- from: region1/*
to:
"region1/*": 80
"region2/*": 20
- from: region2/*
to:
"region2/*": 80
"region1/*": 20
outlierDetection:
consecutive5xxErrors: 1
interval: 1s
baseEjectionTime: 1m

注意: 两个集群都需要应用该配置

从 cluster1 中通过网关发送请求给服务 HelloWorld

从 cluster2中通过网关发送请求给服务 HelloWorld

4.4 验证地域故障转移

当多个地区/区域部署多个服务实例时,如果某个地区/区域的服务实例不可用,可以将流量转移到其他地区/区域的服务实例上,实现地域故障转移,这样就可以保证服务的高可用性。

# locality-lb-failover.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: helloworld
namespace: sample
spec:
host: helloworld.sample.svc.cluster.local
trafficPolicy:
connectionPool:
http:
maxRequestsPerConnection: 1 # 关闭 HTTP Keep-Alive,强制每个HTTP请求使用一个新连接的策略
loadBalancer:
simple: ROUND_ROBIN
localityLbSetting: # 地域负载均衡配置,开启异常点检测后,默认开启。
enabled: true
failover: # 地域故障转移策略
- from: region1
to: region2
- from: region2
to: region1
outlierDetection:
consecutive5xxErrors: 1 # 连续 1 次 5xx 错误
interval: 1s # 检测间隔 1s
baseEjectionTime: 1m # 基础驱逐时间 1m

注意: 两个集群都需要应用该配置

从 cluster1 中通过网关发送请求给服务 HelloWorld

模拟故障,手动将cluster1集群中Helloworld V1版本设置故障

再次访问,故障检测生效,触发故障转移,并验证响应中的 version 始终为 v2,也就是说我们访问的是 region2 的 helloworld 服务,这样就实现了地域故障转移。

故障转移的前提是当前region内,所有实例都不可用时,才会转移到到目前region,否则流量还会发往当前region的其他可用实例。

五 备注

参考文献如下:

  1. istio开源社区(跨网络多主架构的安装说明): https://istio.io/latest/zh/docs/setup/install/multicluster/multi-primary_multi-network/

  2. kind安装集群脚本参考: https://github.com/cnych/multi-cluster-istio-kind/tree/main/kind-create

  3. 多集群证书管理参考:https://istio.io/latest/zh/docs/tasks/security/cert-management/plugin-ca-cert/

点击关注,第一时间了解华为云新鲜技术~

基于istio实现多集群流量治理的更多相关文章

  1. 基于Kubernetes的WAF集群介绍

    Kubernetes是Google开源的容器集群管理系统.它构建Docker技术之上,为容器化的应用提供资源调度.部署运行.服务发现.扩容缩容等整一套功能,可看作是基于容器技术的PaaS平台. 本文旨 ...

  2. 容器服务kubernetes federation v2实践五:多集群流量调度

    概述 在federation v2多集群环境中,通过前面几篇文章的介绍,我们可以很容易的进行服务多集群部署,考虑到业务部署和容灾需要,我们通常需要调整服务在各个集群的流量分布.本文下面简单介绍如何在阿 ...

  3. 庐山真面目之十二微服务架构基于Docker搭建Consul集群、Ocelot网关集群和IdentityServer版本实现

    庐山真面目之十二微服务架构基于Docker搭建Consul集群.Ocelot网关集群和IdentityServer版本实现 一.简介      在第七篇文章<庐山真面目之七微服务架构Consul ...

  4. Tomcat:基于Apache+Tomcat的集群搭建

    根据Tomcat的官方文档说明可以知道,使用Tomcat配置集群需要与其它Web Server配合使用才可以完成,典型的有Apache和IIS. 这里就使用Apache+Tomcat方式来完成基于To ...

  5. 基于Twemproxy的Redis集群搭建以及想法

    基于Twemproxy的Redis集群方案(转) redis3.0 已经发布了几个月了,但是我这等菜鸟到网上还是没有找到很好的关于搭建redis3.0集群的文章,而且好像很多公司的redis版本还保持 ...

  6. 基于zookeeper的Swarm集群搭建

    简介 Swarm:docker原生的集群管理工具,将一组docker主机作为一个虚拟的docker主机来管理. 对客户端而言,Swarm集群就像是另一台普通的docker主机. Swarm集群中的每台 ...

  7. 项目实战2—实现基于LVS负载均衡集群的电商网站架构

    负载均衡集群企业级应用实战-LVS 实现基于LVS负载均衡集群的电商网站架构 背景:随着业务的发展,网站的访问量越来越大,网站访问量已经从原来的1000QPS,变为3000QPS,网站已经不堪重负,响 ...

  8. 基于Hadoop2.7.3集群数据仓库Hive1.2.2的部署及使用

    基于Hadoop2.7.3集群数据仓库Hive1.2.2的部署及使用 HBase是一种分布式.面向列的NoSQL数据库,基于HDFS存储,以表的形式存储数据,表由行和列组成,列划分到列族中.HBase ...

  9. 基于Docker的redis集群搭建

    Redis集群官方介绍:http://www.redis.cn/topics/cluster-tutorial.html 基于Docker搭建Redis集群 环境:6个节点,三主三从 制作Redis镜 ...

  10. 基于centos6.5 hbase 集群搭建

    注意本章内容是在上一篇文章“基于centos6.5 hadoop 集群搭建”基础上创建的 1.上传hbase安装包 hbase-0.96.2-hadoop2 我的目录存放在/usr/hadoop/hb ...

随机推荐

  1. 【Azure Redis 缓存 Azure Cache For Redis】Redis支持的版本及不同版本迁移风险

    问题描述 1. Azure Redis缓存支持的版本包括4.0以及6.0(预览) 这种情形下,可以使用PaaS服务提供的 Azure Redis 缓存(4.0版本).Azure Redis对6.0的支 ...

  2. 【Azure API 管理】是否可以将Swagger 的API定义导入导Azure API Management中

    问题描述 是否可以将Swagger 的API定义导入导Azure API Management中? 操作步骤 是的,可以通过APIM门户导入单个的API Swagger定义文件.具体步骤如下: 第一步 ...

  3. 【Azure 应用服务】Storage Queue触发Azure Function时报错 The input is not a valid Base-64 string

    问题描述 创建一个PowerShell脚本的Azure Function,触发方式为 Storage Queue.但执行函数结果一直失败 (Failed). 错误消息为: Executed 'Func ...

  4. Huggingface初上手即ERNIE-gram句子相似性实战

    大模型如火如荼的今天,不学点语言模型(LM)相关的技术实在是说不过去了.只不过由于过往项目用到LM较少,所以学习也主要停留在直面--动眼不动手的水平.Huggingface(HF)也是现在搞LM离不开 ...

  5. Java 封装性的四种权限测试 + 总结

    *    总结封装性:Java提供了4中权限修饰符来修饰类及类的内部结构,体现类及类的内部结构再被调用时的可见性的大小 1 package com.bytezero.circle; 2 3 publi ...

  6. MYSQL中正则表达式检索数据库

    1.MySQL中使用通配符检索数据库,之外还可以使用正则表达式来检索数据. 使用通配符   '_'  和   '%'的区别如下,   使用通配符的技巧:一般的来说 通配符可以处理数据,但是消耗内存较大 ...

  7. vim 学习总结

    vim 学习总结 一.介绍 vi 编辑器是所有 Unix 及 Linux 系统下标准的编辑器,类似于 Windows 系统下的 notepad(记事本)编辑器.在 Unix 及 Linux 系统的任何 ...

  8. 单词本z escort 护卫 es=ex 出去 cor=con=com 一起, 一起出去 = 护卫

    单词本z escort 护卫 es=ex 出去 cor=con=com 一起, 一起出去 = 护卫 escort 护卫, 护送 这个单词按照我自己理解的反而好记住 es = ex = 出 cor = ...

  9. Navicat 通过 Http通道 连接远程 Mysql

    https://jingyan.baidu.com/article/3d69c551aa54dff0cf02d7a0.html 注意本机ip填写 localhost

  10. Springboot K8s Job 一次性任务 如何禁用端口监听

    问题:SpringBoot一次性任务执行时,也会默认监听服务端口,当使用k8s job运行时,可能多个pod执行存在端口冲突 解决办法:命令行禁用SpringBoot一次性任务启动时端口占用 java ...