添加功能
这是我们添加功能的概述
添加 Cilium 使用 ENI IPAM 模式选项。
向 API 添加字段 ¶
我们希望将此作为一个选项,因此需要向 CiliumNetworkingSpec 添加一个字段
// Ipam specifies the IP address allocation mode to use.
// Possible values are "crd" and "eni".
// "eni" will use AWS native networking for pods. Eni requires masquerade to be set to false.
// "crd" will use CRDs for controlling IP address management.
// Empty value will use host-scope address management.
Ipam string `json:"ipam,omitempty"`
这里需要注意几件事
-
我们可能可以使用布尔值来满足当前需求,但我们希望保留一些灵活性,因此使用字符串。
-
我们为 Cilium 的当前默认模式定义了一个值
crd
,因此我们将默认值 "" 视为“默认模式,无论将来是什么”。
因此,我们只需要检查 Ipam
是否为 eni
来确定配置哪种模式。
我们需要更新版本化的 API 和非版本化的 API,并根据 更新 API 文档 重新生成代码。
验证 ¶
我们应该添加一些验证来确保输入的值有效。我们目前只接受 eni
、crd
或空字符串。
验证在 validation.go 中完成,非常简单 - 如果某个值无效,我们只需将错误添加到一个切片中
if v.Ipam != "" {
// "azure" not supported by kOps
allErrs = append(allErrs, IsValidValue(fldPath.Child("ipam"), &v.Ipam, []string{"crd", "eni"})...)
if v.Ipam == kops.CiliumIpamEni {
if c.CloudProvider != string(kops.CloudProviderAWS) {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("ipam"), "Cilum ENI IPAM is supported only in AWS"))
}
if !v.DisableMasquerade {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("disableMasquerade"), "Masquerade must be disabled when ENI IPAM is used"))
}
}
}
配置 Cilium ¶
Cilium 部署为“引导附加组件”,是一组位于 upup/models/cloudup/resources/addons/networking.cilium.io 下的资源模板文件,每个 Kubernetes 版本范围对应一个文件。这些文件由 upup/pkg/fi/cloudup/bootstrapchannelbuilder.go 引用
首先,我们添加到 cilium-config
ConfigMap 中
{{ with .Ipam }}
ipam: {{ . }}
{{ if eq . "eni" }}
enable-endpoint-routes: "true"
auto-create-cilium-node-resource: "true"
blacklist-conflicting-routes: "false"
{{ end }}
{{ end }}
然后,我们将 cilium-operator 有条件地移动到主节点
{{ if eq .Ipam "eni" }}
nodeSelector:
node-role.kubernetes.io/master: ""
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/master
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
{{ end }}
更改清单文件后,请记住运行 bash hack/update-expected.sh
以获取更新的 manifestHash 值。
配置 kubelet ¶
当 Cilium 处于 ENI 模式时,需要使用本地 IP 地址配置 kubelet
,以便它可以将其与 ENI 使用的辅助 IP 地址区分开来。Kubelet 由 nodeup 在 nodeup/pkg/model/kubelet.go 中配置。该代码在 NodeupModelContext
的 UsesSecondaryIP()
接收器返回 true 时将本地 IP 地址传递给 kubelet
。
因此,我们修改 UsesSecondaryIP()
以在 Cilium 处于 ENI 模式时也返回 true
return (c.Cluster.Spec.Networking.CNI != nil && c.Cluster.Spec.Networking.CNI.UsesSecondaryIP) || c.Cluster.Spec.Networking.AmazonVPC != nil || c.Cluster.Spec.Networking.LyftVPC != nil ||
(c.Cluster.Spec.Networking.Cilium != nil && c.Cluster.Spec.Networking.Cilium.Ipam == kops.CiliumIpamEni)
配置 IAM ¶
当 Cilium 处于 ENI 模式时,主节点上的 cilium-operator
需要额外的 IAM 权限。主节点的 IAM 权限由 pkg/model/iam/iam_builder.go 中的 BuildAWSPolicyMaster()
构建
if b.Cluster.Spec.Networking != nil && b.Cluster.Spec.Networking.Cilium != nil && b.Cluster.Spec.Networking.Cilium.Ipam == kops.CiliumIpamEni {
addCiliumEniPermissions(p, resource, b.Cluster.Spec.IAM.Legacy)
}
func addCiliumEniPermissions(p *Policy, resource stringorslice.StringOrSlice) {
p.Statement = append(p.Statement,
&Statement{
Effect: StatementEffectAllow,
Action: stringorslice.Slice([]string{
"ec2:DescribeSubnets",
"ec2:AttachNetworkInterface",
"ec2:AssignPrivateIpAddresses",
"ec2:UnassignPrivateIpAddresses",
"ec2:CreateNetworkInterface",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeVpcPeeringConnections",
"ec2:DescribeSecurityGroups",
"ec2:DetachNetworkInterface",
"ec2:DeleteNetworkInterface",
"ec2:ModifyNetworkInterfaceAttribute",
"ec2:DescribeVpcs",
}),
Resource: resource,
},
)
}
测试 ¶
在对真实情况进行测试之前,编写一些单元测试会很方便。
我们应该测试验证是否按预期工作(在 validation_test.go 中)
func Test_Validate_Cilium(t *testing.T) {
grid := []struct {
Cilium kops.CiliumNetworkingSpec
Spec kops.ClusterSpec
ExpectedErrors []string
}{
{
Cilium: kops.CiliumNetworkingSpec{},
},
{
Cilium: kops.CiliumNetworkingSpec{
Ipam: "crd",
},
},
{
Cilium: kops.CiliumNetworkingSpec{
DisableMasquerade: true,
Ipam: "eni",
},
Spec: kops.ClusterSpec{
CloudProvider: "aws",
},
},
{
Cilium: kops.CiliumNetworkingSpec{
DisableMasquerade: true,
Ipam: "eni",
},
Spec: kops.ClusterSpec{
CloudProvider: "aws",
},
},
{
Cilium: kops.CiliumNetworkingSpec{
Ipam: "foo",
},
ExpectedErrors: []string{"Unsupported value::cilium.ipam"},
},
{
Cilium: kops.CiliumNetworkingSpec{
Ipam: "eni",
},
Spec: kops.ClusterSpec{
CloudProvider: "aws",
},
ExpectedErrors: []string{"Forbidden::cilium.disableMasquerade"},
},
{
Cilium: kops.CiliumNetworkingSpec{
DisableMasquerade: true,
Ipam: "eni",
},
Spec: kops.ClusterSpec{
CloudProvider: "gce",
},
ExpectedErrors: []string{"Forbidden::cilium.ipam"},
},
}
for _, g := range grid {
g.Spec.Networking = &kops.NetworkingSpec{
Cilium: &g.Cilium,
}
errs := validateNetworkingCilium(&g.Spec, g.Spec.Networking.Cilium, field.NewPath("cilium"))
testErrors(t, g.Spec, errs, g.ExpectedErrors)
}
}
文档 ¶
如果您的功能影响 config
或 cluster.spec
中的重要配置选项,请在 cluster_spec.md 中记录它们。
测试 ¶
您可以本地 make
并运行 kops
。但 nodeup
是从 S3 存储桶中提取的。
要快速测试 nodeup 的更改,您可以构建它,将其通过 scp 传输到运行的机器,并通过 SSH 运行它,并在本地查看输出
make push-aws-run-amd64 TARGET=admin@<publicip>
但是,为了进行更完整的测试,您可能需要执行 nodeup 的私有构建,并从头开始启动集群。
为此,您可以通过设置 KOPS_BASE_URL
环境变量来重新指定 nodeup 源 URL,然后使用以下命令推送 nodeup
export S3_BUCKET_NAME=<yourbucketname>
make kops-install dev-upload UPLOAD_DEST=s3://${S3_BUCKET_NAME}
KOPS_VERSION=`.build/dist/$(go env GOOS)/$(go env GOARCH)/kops version --short`
export KOPS_BASE_URL=https://${S3_BUCKET_NAME}.s3.amazonaws.com/kops/${KOPS_VERSION}/
export KOPS_ARCH=amd64
kops create cluster <clustername> --zones us-east-1b
...
如果您更改了 dns 或 kOps 控制器,您也需要测试它们。为此,请在创建集群之前运行下面的代码段。
对于 dns-controller
KOPS_VERSION=`.build/dist/$(go env GOOS)/$(go env GOARCH)/kops version -- --short`
export DOCKER_IMAGE_PREFIX=${USER}/
export DOCKER_REGISTRY=
make dns-controller-push
export DNSCONTROLLER_IMAGE=${DOCKER_IMAGE_PREFIX}dns-controller:${KOPS_VERSION}
对于 kops-controller
KOPS_VERSION=`.build/dist/$(go env GOOS)/$(go env GOARCH)/kops version -- --short`
export DOCKER_IMAGE_PREFIX=${USER}/
export DOCKER_REGISTRY=
make kops-controller-push
export KOPSCONTROLLER_IMAGE=${DOCKER_IMAGE_PREFIX}kops-controller:${KOPS_VERSION}
使用该功能 ¶
用户只需 kops edit cluster
并添加类似以下的值
spec:
networking:
cilium:
disableMasquerade: true
ipam: eni
然后 kops update cluster --yes
将创建新的 NodeUpConfig,该配置包含在实例启动脚本中,因此需要新的 LaunchTemplate 版本,因此需要 kops-rolling update
。我们正在努力改变设置,使其无需重启即可生效,但对于此特定设置,您可能并不需要经常更改它。
其他步骤 ¶
- 我们还可以为
create cluster
创建一个 CLI 标志。在本例中,这似乎不值得;这是一个比较高级的选项。