Skip to content

Commit

Permalink
Merge pull request #33 from ONE7live/main
Browse files Browse the repository at this point in the history
docs: Add zh version of existing doc
  • Loading branch information
kosmos-robot authored Jun 17, 2024
2 parents c76eee6 + 02e1ac1 commit f63e5b4
Show file tree
Hide file tree
Showing 10 changed files with 1,537 additions and 0 deletions.
230 changes: 230 additions & 0 deletions kosmos/docs/i18n/zh/v0.2.0/application-migration_zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
---
id: application-migration_zh
title: '应用迁移'
---

# 应用迁移
Kosmos 提供应用迁移功能,帮助用户将现有应用程序从子集群迁移到 Kosmos 控制平面集群。

## 应用迁移解决方案

### 简介
在 Kosmos 多集群设计架构中,用户可以使用 kubectl、client-go 等工具与控制平面集群的 kube-apiserver 交互,创建部署或有状态的应用程序等。
实际的 Pod 实例在子集群中运行。

然而,对于在子集群中未通过 Kosmos 控制平面创建的现有应用程序,这些应用程序无法在控制平面集群中查看和管理。

Kosmos 提供应用迁移功能,支持将命名空间中的应用程序迁移到控制平面集群。
整个过程无需重新启动应用程序 Pod 实例,确保对业务运营的最小影响。

### 设计细节
应用迁移主要包括三个过程:应用备份 -> 删除所有者对象 -> 在控制平面中重建应用程序。

#### 应用备份
Kosmos 首先备份目标命名空间中的所有命名空间级别资源,以及依赖的集群级别资源,如集群角色、集群角色绑定、持久卷等。
备份文件存储在 Kosmos 的 PVC 中。

#### 删除所有者对象
Kosmos 子集群仅运行 Pod,它们的所有者 StatefulSet 或 ReplicaSet 需要在 Kosmos 控制平面中删除并重建。
类似地,ReplicaSet 的所有者 Deployment,以及 StatefulSet 和 Deployment 的所有者,需要在 Kosmos 控制平面中删除并重建。

通过使用自上而下的级联删除所有者对象(例如,首先删除 Deployment,然后删除 ReplicaSet),Pod 不受影响并保持运行状态。

#### 在控制平面中重建应用程序
基于备份资源,控制平面集群创建所有迁移后的资源,包括命名空间、Pod、部署、配置映射、服务账户等。
为了与子集群中的 Pod 保持一致并保持其运行状态,应用程序使用自下而上的方法进行重建(例如,首先创建 Pod,然后创建 ReplicaSet)。

#### CRD API
提供 PromotePolicy CRD API 用于配置迁移策略。
PromotePolicy 是一个集群范围的 CRD API。以下是如何使用它的示例:
```shell script
apiVersion: kosmos.io/v1alpha1
kind: PromotePolicy
metadata:
name: promote-policy-sample
spec:
includedNamespaces:
- namespace1
- namespace2
excludedNamespaceScopedResources:
- events
- events.events.k8s.io
- endpoints
- endpointslices.discovery.k8s.io
clusterName: member-cluster1
```
其中:
- includedNamespaces: 要迁移的命名空间。
- excludedNamespaceScopedResources: 不应迁移的命名空间级资源。
建议保留示例配置,并根据实际需求添加其他配置。
- clusterName: Kosmos 子集群的名称。

#### 回滚
Kosmos 支持迁移的回滚功能。
成功迁移后,可以将子集群中现有的应用程序恢复到其初始状态。
只需编辑 PromotePolicy YAML 文件,并添加配置 'rollback'=true。
```shell script
apiVersion: kosmos.io/v1alpha1
kind: PromotePolicy
metadata:
name: promote-policy-sample
spec:
rollback: "true"
includedNamespaces:
- namespace1
- namespace2
excludedNamespaceScopedResources:
- events
- events.events.k8s.io
- endpoints
- endpointslices.discovery.k8s.io
clusterName: member-cluster1
```

### 测试计划

#### 准备工作
首先,需要部署 [Kosmos](https://github.com/kosmos-io/kosmos)(必须安装 clustertree 模块)并添加一个子集群。

#### 在子集群中创建现有应用程序
以在子集群中部署 nginx 应用程序为例。
```shell script
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: nginx-test
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14-alpine
ports:
- containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
namespace: nginx-test
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
```

#### 创建迁移策略
```shell script
# kubectl apply -f promote-nginx.yaml
apiVersion: kosmos.io/v1alpha1
kind: PromotePolicy
metadata:
name: promote-policy-example
spec:
includedNamespaces:
- nginx-test
excludedNamespaceScopedResources:
- events
- events.events.k8s.io
- endpoints
- endpointslices.discovery.k8s.io
clusterName: cluster-36-28
```

#### 检查迁移结果
检查迁移进度:
```shell script
# kubectl describe promotepolicy promote-policy-example
Name: promote-policy-example
Namespace: default
Labels: <none>
Annotations: <none>
API Version: kosmos.io/v1alpha1
Kind: PromotePolicy
Metadata:
Creation Timestamp: 2024-03-11T10:57:47Z
Generation: 3
Resource Version: 405947183
UID: 0e32dd93-c370-4874-b9a7-37a6894cd373
Spec:
Cluster Name: cluster-36-28
Excluded Namespace Scoped Resources:
events
events.events.k8s.io
endpoints
endpointslices.discovery.k8s.io
controllerrevisions.apps
Included Namespaces:
nginx-test
Status:
Backedup File: /data/backup/promote-policy-sample20240311-104907
Phase: Completed
Events: <none>
```
当 Status.Phase 为 'Completed' 时,表示迁移成功。
此时,可以在控制平面集群中查看和管理 nginx-test 命名空间中的所有应用程序。

#### 回滚
编辑 promote-nginx.yml 文件,并添加配置 'rollback'=true:
```shell script
# kubectl apply -f promote-nginx.yaml
apiVersion: kosmos.io/v1alpha1
kind: PromotePolicy
metadata:
name: promote-policy-example
spec:
rollback: "true"
includedNamespaces:
- nginx-test
excludedNamespaceScopedResources:
- events
- events.events.k8s.io
- endpoints
- endpointslices.discovery.k8s.io
clusterName: cluster-36-28
```

回滚结果检查:
```shell script
# kubectl describe promotepolicy promote-policy-example
Name: promote-policy-example
Namespace: default
Labels: <none>
Annotations: <none>
API Version: kosmos.io/v1alpha1
Kind: PromotePolicy
Metadata:
Creation Timestamp: 2024-03-11T10:57:47Z
Generation: 5
Resource Version: 405953692
UID: 0e32dd93-c370-4874-b9a7-37a6894cd373
Spec:
Cluster Name: cluster-36-28
Excluded Namespace Scoped Resources:
events
events.events.k8s.io
endpoints
endpointslices.discovery.k8s.io
controllerrevisions.apps
Included Namespaces:
nginx-test
Status:
Backedup File: /data/backup/promote-policy-sample20240311-104907
Phase: RolledBack
Events: <none>
```
`Status.Phase` 为 'RolledBack' 时,表示回滚成功。
此时,nginx-test 命名空间中的应用程序在控制平面集群中无法查询到。
136 changes: 136 additions & 0 deletions kosmos/docs/i18n/zh/v0.2.0/ccn-ipsec-tunnel_zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
---
id: ipsec-network_zh
title: 'IPsec跨集群网络'
---

# IPsec跨集群容器网络解决方案

## 使用IPsec隧道在公共IP上进行跨集群容器网络通信

### 简介
Kosmos是一个多集群解决方案,网络是其重要组成部分。
有时候,需要在不同网络的Kubernetes集群之间进行通信。
在某些情况下,两个或多个集群只能通过公共互联网进行通信。
为了解决这个问题,Kosmos实现了基于IPsec隧道的跨集群容器网络通信解决方案。

### 动机
出于灾难恢复的考虑,应用部署可能需要在多云多集群环境的不同区域(跨VPC)之间进行通信。
在这种情况下,由于机器的内部IP地址通常无法直接访问而没有专用网络连接,容器通信变得具有挑战性。
常见的CNI隧道技术如VxLAN或IPIP在公共互联网环境下可能无法有效工作。
为解决此问题,Kosmos实现了基于IPsec隧道的容器网络通信解决方案,用于通过公共互联网进行跨云通信。
该解决方案旨在满足在公共网络中进行通信的需求,并考虑数据传输的安全性。

### 目标
目标是使用弹性公共IP地址使两个集群中的Pod能够通信。下图展示了流量的流向:

![IPsec_Tunnel](img/IPsec_Tunnel.jpeg)

:::info NOTE
此解决方案不涉及集群内主机网络模式下的容器网络通信。
仅关注IPv4容器网络通信,并不涵盖IPv6容器网络。
:::

## 设计细节

### API变更

#### Cluster API变更
此解决方案向 `.spec.ClusterLinkOptions` 添加了三个字段:`NodeElasticIPMap``ClusterPodCIDRs``UseExternalApiserver`
````shell script
type ClusterLinkOptions struct {
...
// NodeElasticIPMap表示Kubernetes中节点名称与挂载在节点上的弹性IP之间的映射关系
// +optional
NodeElasticIPMap map[string]string `json:"nodeElasticIPMap,omitempty"`
// +optional
ClusterPodCIDRs []string `json:"clusterpodCIDRs,omitempty"`
// +optional
UseExternalApiserver bool `json:"useexternalapiserver,omitempty"`
}
````
- `NodeElasticIPMap` 字段表示Kubernetes中节点名称与挂载在节点上的弹性公共IP之间的映射关系。
- `ClusterPodCIDRs` 字段用于输入Pod CIDR,因为对于某些CNI插件来说获取Pod CIDR并不总是容易的。

通常情况下,Kosmos通过kube-apiserver参数获取服务CIDR。
然而,在某些情况下,kube-apiserver不是集群内的一个Pod。
因此,添加了 `UseExternalApiserver` 字段以处理这种情况。

#### Clusternode API变更
此解决方案向 `.spec` 添加了一个新字段 `ElasticIP`,并向 `.status` 添加了一个新字段 `NodeStatus`
````shell script
type ClusterNodeSpec struct {
...
// +optional
ElasticIP string `json:"elasticip,omitempty"`
}

type ClusterNodeStatus struct {
// +optional
NodeStatus string `json:"nodeStatus,omitempty"`
}
````
- `ElasticIP` 字段描述了挂载在节点上的弹性公共IP。
- `NodeStatus` 字段描述了节点的状态,可以是 "Ready" 或 "NotReady"。

#### Nodeconfig API变更
此解决方案向 `.spec` 添加了两个新字段 `XfrmPoliciesXfrmStates``IPsetsAvoidMasqs`
````shell script
type NodeConfigSpec struct {
XfrmPolicies []XfrmPolicy `json:"xfrmpolicies,omitempty"`
XfrmStates []XfrmState `json:"xfrmstates,omitempty"`
IPsetsAvoidMasqs []IPset `json:"ipsetsavoidmasq,omitempty"`
}

type XfrmPolicy struct {
LeftIP string `json:"leftip"`
LeftNet string `json:"leftnet"`
RightIP string `json:"rightip"`
RightNet string `json:"rightnet"`
ReqID int `json:"reqid"`
Dir int `json:"dir"`
}

type XfrmState struct {
LeftIP string `json:"leftip"`
RightIP string `json:"rightip"`
ReqID int `json:"reqid"`
SPI uint32 `json:"spi"`
PSK string `json:"PSK"`
}

type IPset struct {
CIDR string `json:"cidr"`
Name string `json:"name"`
}
````
新的 `XfrmPolicies``XfrmStates` 字段定义了Kosmos创建的与IPsec相关的规则。

`IPsetsAvoidMasqs` 字段描述了需要避免伪装的网络段,允许容器的出站流量保留其容器IP地址。

### 组件修改

#### Clusterlink-controller-manager
处理kube-apiserver不在集群内的情况:
- 集群控制器通过 `GetSvcByCreateInvalidSvc` 函数优化服务CIDR的获取。

节点状态同步:
- 节点控制器基于 `Cluster` 对象的 `NodeElasticIPMap` 字段值,同步 `clusternode` 对象的 `ElasticIP` 字段。
- 节点控制器现在根据节点的状态("Ready" 或 "NotReady")更新 `clusternode` 对象的 `.Status.NodeStatus` 字段。

#### Clusterlink-elector
选举模块用于在网关模式中选择网关。现在,它可以从处于 "Ready" 状态的节点中选择一个网关。

#### Clusterlink-network-manager
1. 添加对某些CNI插件的支持
对于某些CNI插件,添加了iptables规则以避免伪装,允许容器的出站流量保留其容器IP地址。

2. 构建IPsec规则
通常情况下,Kosmos创建路由以实现容器通信。在IPsec隧道模式下,如果 `clusternode``ElasticIP` 字段不为空,Kosmos会创建 `ip xfrm state``ip xfrm policy` 规则。

#### clusterlink-agent
添加了执行特定操作的函数,相当于在操作系统上执行 `ip xfrm state add/del``ip xfrm policy add/del` 命令。

为了避免伪装,添加了执行 `ipset` 命令和创建iptables规则的函数。

#### kosmosctl
添加了 `NodeElasticIP``UseExternalApiserver``ClusterPodCIDRs` 输入参数,用于填充 `Cluster` CRD 中的新字段 `NodeElasticIPMap``UseExternalApiserver``ClusterPodCIDRs`
Loading

0 comments on commit f63e5b4

Please sign in to comment.