前置条件

  1. 2个k8s集群(k18-1,k18-2)>=1.13,这里以1.18.6以例
  2. helm

安装kubefedctl

VERSION=0.4.0
OS=linux
ARCH=amd64
curl -LO https://github.com/kubernetes-sigs/kubefed/releases/download/v${VERSION}/kubefedctl-${VERSION}-${OS}-${ARCH}.tgz
tar -zxvf kubefedctl-*.tgz
chmod u+x kubefedctl
sudo mv kubefedctl /usr/local/bin/

安装kubefed控制平面

git clone https://github.com/kubernetes-sigs/kubefed.git
cd charts
# 运行helm install前先将kubefed/values.yaml里面的仓库quay.io/kubernetes-multicluster换成quay.mirrors.ustc.edu.cn/kubernetes-multicluster
helm install kubefed-charts kubefed-charts --namespace kube-federation-system --create-namespace
#加入并查看集群状态
kubefedctl join k18-1 --cluster-context k18-1 \
    --host-cluster-context k18-1 --v=2
kubefedctl join k18-2 --cluster-context k18-2 \
    --host-cluster-context k18-1 --v=2
kubectl -n kube-federation-system get kubefedclusters 

示例

  • 传播指定的资源类型
kubefedctl enable <target API type>
# 如 kubefedctl enable sa,sa类型就会自动传播到所有联邦结点

执行如上命令时,在集群中为自动生成Federated,如:federatedserviceaccounts,以及位于kube-federation-system空间下的FederatedTypeConfig,名称和< target API type >一致,起到关联原类型和传播类型的作用

  • 传播指定资源
kubefedctl federate sa controller --enable-type -n knative-serving
# 传播knative-serving空间下的sa账号controller,--enable-type表示同时传播类型,就免去了上面的操作

传播指定空间knative-serving下所有的资源

kubefedctl federate namespace knative-serving --contents --enable-type
  • 根据yaml传播
kubefedctl federate -f <file>

示例

kubefedctl federate -f serving-crds.yaml |kubectl apply -f -
  • 锁定资源
    为防止误操作,可通过如下操作锁定资源防止删除
kubefedctl orphaning-deletion enable <federated type> <name>
# 查看
#kubefedctl orphaning-deletion status <federated type> <name>
# 解锁
# kubefedctl orphaning-deletion disable <federated type> <name>
  • 分配指定资源给指定集群
    默认federate会作用于k18-1,k18-2,可使用如下方式,修改传播集群
kubectl patch federatedvalidatingwebhookconfigurations config.webhook.serving.knative.dev \
    --type=merge -p '{"spec": {"placement": {"clusters": [{"name": "k18-1"}]}}}'
  • 给集群贴标签
    给集群贴标签的意义在于placement,这样就可以以标签的方式进行传播
kubectl label kubefedclusters -n kube-federation-system cluster1 foo=bar
  • 将某个资源设置传到集群标贴为foo: bar的集群
spec:
  placement:
    clusters: []
    clusterSelector:
      matchLabels:
        foo: bar
  • 来设置selector将传播到所有集群
spec:
  placement:
    clusterSelector: {}
  • 个性化配置
    对不同集群的配置可能不一样,可使用如下操作进行设置:
    将集群cluster1的某个deploy的副本数设置成5,镜像设置为nginx:1.17.0-alpine,添加foo: bar注解,删除foo1注解,在第一个容器下添加-q参数
kind: FederatedDeployment
...
spec:
  ...
  overrides:
  # Apply overrides to cluster1
    - clusterName: cluster1
      clusterOverrides:
        # Set the replicas field to 5
        - path: "/spec/replicas"
          value: 5
        # Set the image of the first container
        - path: "/spec/template/spec/containers/0/image"
          value: "nginx:1.17.0-alpine"
        # Ensure the annotation "foo: bar" exists
        - path: "/metadata/annotations"
          op: "add"
          value:
            foo: bar
        # Ensure an annotation with key "foo" does not exist
        - path: "/metadata/annotations/foo1"
          op: "remove"
        # Adds an argument `-q` at index 0 of the args list
        # this will obviously shift the existing arguments, if any
        - path: "/spec/template/spec/containers/0/args/0"
          op: "add"
          value: "-q"

示例部署knative

  • 以正常方式安装Knative
kubectl apply -f service-crd.yaml
kubectl apply -f service-core.yaml
  • 使用如下脚本对yaml文件传播
package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"gopkg.in/yaml.v2"
)

func main() {
	m := make(map[interface{}]interface{})
	var file string
	if len(os.Args) > 1 {
		file = os.Args[1]
	} else {
		fmt.Println("Usage: fedapply <file>")
		os.Exit(1)
	}
	filename, _ := filepath.Abs(file)
	f, err := ioutil.ReadFile(filename)
	if err != nil {
		panic(err)
	}
	r := bytes.NewReader(f)

	dec := yaml.NewDecoder(r)

	for dec.Decode(&m) == nil {
		kind := m["kind"]
		if kind == nil {
			return
		}
		if kind == "Service" {
			kind = "svc"
		}
		meta := m["metadata"].(map[interface{}]interface{})
		name := meta["name"].(string)
		namespace := meta["namespace"]
		exe := "/usr/local/bin/kubefedctl"
		fmt.Print("running cmd: ", exe, " federate", " --enable-type", " ", kind, " ", name)
		var cmd *exec.Cmd
		if namespace == nil {
			fmt.Println()
			cmd = exec.Command(exe, "federate", "--enable-type", kind.(string), name)
		} else {
			fmt.Println(" -n ", namespace)
			cmd = exec.Command(exe, "federate", "--enable-type", kind.(string), name, "-n", namespace.(string))
		}
		var out bytes.Buffer
		var stderr bytes.Buffer
		cmd.Stdout = &out
		cmd.Stderr = &stderr

		if err := cmd.Run(); err != nil {
			fmt.Println("cmd err", err.Error())
			fmt.Println("console err:", stderr.String())
		} else {
			fmt.Println("output:", out.String())
		}
	}
}

构建生成kubeapply,使用如下命令传播knative集群,期间的报错可忽略,主要是集群k18-1已经安装了。

fedapply service-crd.yaml
fedapply service-core.yaml

示例部署istio

直接fedapply不成功,文件中有好几处空的—段导致后面都不解析,然后也没有创建命名空间。
使用如下命令传播命名空间,及部分资源。

kubefedctl federate namespace istio-system --contents --enable-type
#istio相关hook
fedapply release.yaml

不建议对namespace做federate,容易出问题,正常情况不是所有内容都需要同步的
networking-istio启动不来,config-istio未同步

示例部署knative应用

cat <<EOF | kubectl apply -f -
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: stock-service-example
  namespace: default
spec:
  template:
    metadata:
      name: stock-service-example-first
    spec:
      containers:
      - image: registry.cn-chengdu.aliyuncs.com/kn-sample/rest-api-go
        env:
          - name: RESOURCE
            value: stock
EOF
kubefedctl enable crd
kubefedctl federate crd services.serving.knative.dev
kubefedctl enable services.serving.knative.dev --federated-group kubefed.serving.knative.dev

kubectl patch clusterrole kubefed-role --type='json' -p='[{"op": "add", "path": "/rules/1", "value": {
            "apiGroups": [
                "kubefed.serving.knative.dev"
            ],
            "resources": [
                "*"
            ],
            "verbs": [
                "get",
                "watch",
                "list",
                "update"
            ]
        }
}]'
kubefedctl federate namespace default
kubefedctl federate -n default ksvc stock-service-example

坑点

  • 部分annotations无法传播
  • 部分资源无法传播成功(service),比如重名资源,官方提供指定-federated-group解决
  • 不支持修改传播后的资源类型,目前只能通过重新安装k8集群清理
  • 重新安装集群,已经加入过之前联邦的结点无法再加入新的联邦,可以通过如下命令清理
kubectl delete sa -n kube-federation-system   k18-2-k18-1
kubectl delete clusterrole kubefed-controller-manager:k18-2-k18-1
kubectl delete clusterrolebinding kubefed-controller-manager:k18-2-k18-1
  • 传播命名空间无法保证完整性,比如部分sa未传播,因此要把传播命名空间为第一步,再传播空间内资源
  • 批量传播有可能部分失败,建议将每个资源单独一个文件方便回滚
  • 有可能存在状态不一致,资源未传播但是状态是正常的
  • 有些东西不应该传播,应该由集群各自管理,比如滚动证书,secret
  • 最好不要使用kubectl直接去操作kubefed相关资源不然会导致状态不一致,比如使用
  • api-resource无法消除,k8没有相关接口
kubectl --ignore-not-found=true delete -n kube-federation-system FederatedTypeConfig --all

清理所有的config,停止传播是生效了。但是federated的类型还在,类型好像无法清理

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐