基于kubeadm搭建istio多集群

语言: CN / TW / HK

前提

准备2台机器。

安装kubernetes

我们基于kubeadm安装。

安装kubeadm

允许 iptables 检查桥接流量

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sudo sysctl --system

安装runtime

选择安装docker,参考 容器运行时

安装 kubeadm、kubelet 和 kubectl

  1. 更新 apt 包索引并安装使用 Kubernetes apt 仓库所需要的包:
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
  1. 添加apt仓库,这边可以选择添加阿里云的库!
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
  1. 更新 apt 包索引,安装 kubelet、kubeadm 和 kubectl,并锁定其版本
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

如果不成功,先通过一些方法下载: https://packages.cloud.google.com/apt/doc/apt-key.gpg, 保存到当前目录。再执行: cat apt-key.gpg | sudo apt-key add - 再执行更新 apt-get update ,成功。

使用 kubeadm 创建集群

拉取镜像

初始化需要的镜像可以通过 kubeadm config images list 来查看:

k8s.gcr.io/kube-apiserver:v1.21.1
k8s.gcr.io/kube-controller-manager:v1.21.1
k8s.gcr.io/kube-scheduler:v1.21.1
k8s.gcr.io/kube-proxy:v1.21.1
k8s.gcr.io/pause:3.4.1
k8s.gcr.io/etcd:3.4.13-0
k8s.gcr.io/coredns/coredns:v1.8.0

使用下面命令提前拉取镜像

kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers

拉取不到的,去docker hub上拉下一样的版本然后docker tag打成需要的样子。

初始化控制平面节点

执行

kubeadm init

kubeadm 还会提示我们第一次使用 Kubernetes 集群所需要的配置命令:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

查看下node

NAME           STATUS   ROLES                  AGE    VERSION
n251-241-069   Ready    control-plane,master   164m   v1.21.1

由于我们只有单节点,如果希望能够在master节点上调度Pod,就可以运行如下的命令:

kubectl taint nodes --all node-role.kubernetes.io/master-

这样就删除主节点上的 node-role.kubernetes.io/master 污点,调度器就能将Pod调度到 master 节点上。

安装网络插件

这里我们选择weave

kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"

部署完成后,我们可以通过 kubectl get 重新检查 Pod 的状态,可以看到codedns也起来了,在部署网络插件前,coredns是不会运行的!:

# kubectl get pods -n kube-system
NAME                               READY   STATUS    RESTARTS   AGE
coredns-74ff55c5b-f95sj            1/1     Running   0          131m
coredns-74ff55c5b-zvjdz            1/1     Running   0          131m
etcd-yxj-test                      1/1     Running   0          131m
kube-apiserver-yxj-test            1/1     Running   0          131m
kube-controller-manager-yxj-test   1/1     Running   0          131m
kube-proxy-nm4tt                   1/1     Running   0          131m
kube-scheduler-yxj-test            1/1     Running   0          131m
weave-net-pl4qp                    2/2     Running   1          126m

优化kubeconfig

用本地终端来操作集群会比较方便,可以把安装好的两个集群的kubeconfig都下载到本地。

可以使用 kubecm 来merge多个kubeconfig,本地切换context即可连接到不同的集群。

安装多网络主从ISTIO集群

  • 我们的环境是多网络,podIP不互通。
  • 其次我们选择共享控制平面,即主从架构。

在此配置中,集群 cluster1 将监测两个集群 API Server 的服务端点。 以这种方式,控制平面就能为两个集群中的工作负载提供服务发现。

跨集群边界的服务负载,通过专用的东西向流量网关,以间接的方式通讯。 每个集群中的网关必须可以从其他集群访问。

cluster2 中的服务将通过相同的的东西向网关访问 cluster1 控制平面。

下载istio

curl -L https://istio.io/downloadIstio | sh -
istio-1.10.0
$ cd istio-1.10.0

安装目录包含:

  • samples/ 目录下的示例应用程序
  • bin/ 目录下的 [istioctl](https://istio.io/latest/zh/docs/reference/commands/istioctl) 客户端二进制文件 .
  1. istioctl 客户端加入搜索路径(Linux or macOS):
$ export PATH=$PWD/bin:$PATH

设置context环境变量

由于涉及到切换集群,我们先设置好环境变量:

$ export CTX_CLUSTER1=<your cluster1 context>
$ export CTX_CLUSTER2=<your cluster2 context>

插入ca证书

在 Istio 安装包的顶层目录下,创建一个目录来存放证书和密钥:

$ mkdir -p certs
$ pushd certs

生成根证书和密钥:

$ make -f ../tools/certs/Makefile.selfsigned.mk root-ca

将会生成以下文件:

  • root-cert.pem :生成的根证书
  • root-key.pem :生成的根密钥
  • root-ca.conf :生成根证书的 openssl 配置
  • root-cert.csr :为根证书生成的 CSR

对于每个集群,为 Istio CA 生成一个中间证书和密钥。 以下是集群 cluster1 的例子:

$ make -f ../tools/certs/Makefile.selfsigned.mk cluster1-cacerts

运行以上命令,将会在名为 cluster1 的目录下生成以下文件:

ca-cert.pem
ca-key.pem
cert-chain.pem
root-cert.pem

您可以使用一个您选择的字符串来替换 cluster1 。例如,使用 cluster2-cacerts 参数,您可以在一个名为 cluster2 的目录中创建证书和密钥。

如果您正在离线机器上进行此操作,请将生成的目录复制到可以访问集群的机器上。

在每个集群中,创建一个私密 cacerts ,包括所有输入文件 ca-cert.pemca-key.pemroot-cert.pemcert-chain.pem 。例如,在 cluster1 集群上:

$ kubectl create namespace istio-system
$ kubectl create secret generic cacerts -n istio-system \
      --from-file=cluster1/ca-cert.pem \
      --from-file=cluster1/ca-key.pem \
      --from-file=cluster1/root-cert.pem \
      --from-file=cluster1/cert-chain.pem
  1. 返回 Istio 安装的顶层目录:
$ popd

安装主从集群

为 cluster1设置缺省网络

创建命名空间 istio-system 之后,我们需要设置集群的网络:

$ kubectl --context="${CTX_CLUSTER1}" get namespace istio-system && \
  kubectl --context="${CTX_CLUSTER1}" label namespace istio-system topology.istio.io/network=network1

将cluster1设为主集群

cluster1 创建 Istio 配置文件:

$ cat <<EOF > cluster1.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  values:
    global:
      meshID: mesh1
      multiCluster:
        clusterName: cluster1
      network: network1
EOF

将配置文件应用到 cluster1

$ istioctl install --context="${CTX_CLUSTER1}" -f cluster1.yaml

在cluster1安装东西向网关

cluster1 安装专用的东西向流量网关。 默认情况下,此网关将被公开到互联网上。 生产系统可能需要额外的访问限制(即:通过防火墙规则)来防止外部攻击。 咨询你的云服务商,了解可用的选择。

$ samples/multicluster/gen-eastwest-gateway.sh \
    --mesh mesh1 --cluster cluster1 --network network1 | \
    istioctl --context="${CTX_CLUSTER1}" install -y -f -

等待东西向网关获取外部 IP 地址

$ kubectl --context="${CTX_CLUSTER1}" get svc istio-eastwestgateway -n istio-system
NAME                    TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)   AGE
istio-eastwestgateway   LoadBalancer   10.80.6.124   34.75.71.237   ...       51s

这时候如果没有云服务商提供LB的话,可以自己配置一个可访问的externalIPs到spec下,edit或者patch对应的svc:

clusterIP: 10.101.23.43
clusterIPs:
- 10.101.23.43
externalTrafficPolicy: Cluster
externalIPs:
- 10.x.x.x

开发cluster1控制面

安装 cluster2 之前,我们需要先开放 cluster1 的控制平面,以便 cluster2 中的服务能访问服务发现。

$ kubectl apply --context="${CTX_CLUSTER1}" -f \
    samples/multicluster/expose-istiod.yaml

开放cluster1的服务

因为集群位于不同的网络,我们需要开放两个集群的东西向网关上的所有用户服务(*.local)。 虽然此网关被公开到互联网,但它背后的服务只能被拥有可信 mTLS 证书和工作负载 ID 的服务访问, 就像它们处于同一个网络一样。

$ kubectl --context="${CTX_CLUSTER1}" apply -n istio-system -f \
    samples/multicluster/expose-services.yaml

为cluster2设置缺省网络

命名空间 istio-system 创建之后,我们需要设置集群的网络:

$ kubectl --context="${CTX_CLUSTER2}" get namespace istio-system && \
  kubectl --context="${CTX_CLUSTER2}" label namespace istio-system topology.istio.io/network=network2

启用API Server访问cluster2配置

为了能够访问 cluster2 API Server,我们要生成一个远程 Secret,并把它应用到 cluster1

$ istioctl x create-remote-secret \
    --context="${CTX_CLUSTER2}" \
    --name=cluster2 | \
    kubectl apply -f - --context="${CTX_CLUSTER1}"

将cluster2设置为从集群

保存 cluster1 东西向网关的地址。

$ export DISCOVERY_ADDRESS=$(kubectl \
    --context="${CTX_CLUSTER1}" \
    -n istio-system get svc istio-eastwestgateway \
    -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

现在,为 cluster2 创建一个从集群配置:

$ cat <<EOF > cluster2.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  profile: remote
  values:
    global:
      meshID: mesh1
      multiCluster:
        clusterName: cluster2
      network: network2
      remotePilotAddress: ${DISCOVERY_ADDRESS}
EOF

将此配置应用到 cluster2

$ istioctl install --context="${CTX_CLUSTER2}" -f cluster2.yaml

在cluster2安装东西向网关

仿照上面 cluster1 的操作,在 cluster2 中安装专用于东西向流量的网关,并且开放用户服务。

$ samples/multicluster/gen-eastwest-gateway.sh \
    --mesh mesh1 --cluster cluster2 --network network2 | \
    istioctl --context="${CTX_CLUSTER2}" install -y -f -

等待东西向网关获取外部 IP 地址:

$ kubectl --context="${CTX_CLUSTER2}" get svc istio-eastwestgateway -n istio-system
NAME                    TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)   AGE
istio-eastwestgateway   LoadBalancer   10.0.12.121   34.122.91.98   ...       51s

开放cluster2中的服务

仿照上面 cluster1 的操作,通过东西向网关开放服务。

$ kubectl --context="${CTX_CLUSTER2}" apply -n istio-system -f \
    samples/multicluster/expose-services.yaml

至此在跨网络、主-从架构的集群上,成功的安装了 Istio 网格。

分享到: