前提
准备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
- 更新
apt
包索引并安装使用 Kubernetesapt
仓库所需要的包:
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
- 添加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
- 更新
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 包目录。例如,如果包是
istio-1.10.0
:
$ cd istio-1.10.0
安装目录包含:
samples/
目录下的示例应用程序bin/
目录下的[istioctl](https://istio.io/latest/zh/docs/reference/commands/istioctl)
客户端二进制文件 .
- 将
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
:istiod 使用的生成的证书链root-cert.pem
:根证书
您可以使用一个您选择的字符串来替换 cluster1
。例如,使用 cluster2-cacerts
参数,您可以在一个名为 cluster2
的目录中创建证书和密钥。
如果您正在离线机器上进行此操作,请将生成的目录复制到可以访问集群的机器上。
在每个集群中,创建一个私密 cacerts
,包括所有输入文件 ca-cert.pem
,ca-key.pem
,root-cert.pem
和 cert-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
- 返回 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 网格。