cluster-1번의 ./kube/config 파일을 아래와 같이 수정하여
ctx1 --> cluster-1
ctx2 --> cluster-2
로 지정되도록 설정한다.
apiVersion: v1
clusters:
- cluster:
api-version: v1
certificate-authority-data: XXXXXXXXXXXXXXXXXXXXX
server: "https://10.100.1.x:6443"
name: "cluster-1"
- cluster:
api-version: v1
certificate-authority-data: XXXXXXXXXXXXXXXXXXXXX
server: "https://10.100.1.x:6443"
name: "cluster-2"
kind: Config
preferences: {}
users:
- name: "user-1"
user:
client-certificate-data: XXXXXXXXXXXXXXXXXXXXX
client-key-data: XXXXXXXXXXXXXXXXXXXXX
- name: "user-2"
user:
client-certificate-data: XXXXXXXXXXXXXXXXXXXXX
client-key-data: XXXXXXXXXXXXXXXXXXXXX
contexts:
- context:
cluster: cluster-1
user: user-1
name: ctx-1
- context:
cluster: cluster-2
user: user-2
name: ctx-2
current-context: ctx-1
아래명령어로 두개의 클러스터에 접속이 가능한지 테스트한다.
$ kubectl get nodes --context=ctx-1
NAME STATUS ROLES AGE VERSION
cp-cluster-a-1 Ready control-plane 4h45m v1.25.6
cp-cluster-a-2 NotReady <none> 4h44m v1.25.6
$ kubectl get nodes --context=ctx-2
NAME STATUS ROLES AGE VERSION
cp-cluster-b-1 Ready control-plane 4h41m v1.25.6
cp-cluster-b-2 NotReady <none> 4h39m v1.25.6
step라는 오픈소스를 사용한다.
## step 다운로드 및 /usr/bin 배치
$ wget https://github.com/smallstep/cli/releases/download/v0.24.4/step_linux_0.24.4_amd64.tar.gz -O step.tar.gz
$ tar -xvzf step.tar.gz
$ sudo mv step_0.24.4/bin/step /usr/bin/
$ sudo chmod +x /usr/bin/step
## 폴더 생성
$ mkdir certs
$ mkdir -p certs/cluster-1
$ mkdir -p certs/cluster-2
## rootCA 생성
$ step certificate create root.istio.io certs/root-cert.pem certs/root-ca.key \
--profile root-ca --no-password --insecure --san root.istio.io \
--not-after 87600h --kty RSA
## 1번 Cluster 인증서 생성
$ step certificate create cluster-1.intermediate.istio.io certs/cluster-1/ca-cert.pem certs/cluster-1/ca-key.pem --ca certs/root-cert.pem --ca-key certs/root-ca.key --profile intermediate-ca --not-after 87600h --no-password --insecure --san cluster-1.intermediate.istio.io --kty RSA
$ cat certs/cluster-1/ca-cert.pem certs/root-cert.pem > certs/cluster-1/cert-chain.pem
## 2번 Cluster 인증서 생성
# step certificate create cluster-2.intermediate.istio.io certs/cluster-2/ca-cert.pem certs/cluster-2/ca-key.pem --ca certs/root-cert.pem --ca-key certs/root-ca.key --profile intermediate-ca --not-after 87600h --no-password --insecure --san cluster-2.intermediate.istio.io --kty RSA
$ cat certs/cluster-1/ca-cert.pem certs/root-cert.pem > certs/cluster-1/cert-chain.pem
$ tree certs
certs
├── cluster-1
│ ├── ca-cert.pem
│ ├── ca-key.pem
│ └── cert-chain.pem
├── cluster-2
│ ├── ca-cert.pem
│ ├── ca-key.pem
│ └── cert-chain.pem
├── root-ca.key
└── root-cert.pem
$ wget -c "https://github.com/istio/istio/releases/download/1.15.7/istio-1.15.7-linux-amd64.tar.gz" -O istio.tar.gz
$ tar -xvzf istio.tar.gz
$ sudo mv istio-1.15.7/bin/istioctl /usr/bin/
namespace-1.yaml
apiVersion: v1
kind: Namespace
metadata:
labels:
kubernetes.io/metadata.name: istio-system
topology.istio.io/network: network-1
name: istio-system
controlplain-1.yaml
apiVersion: install.istio.io/v1alpha1
metadata:
name: istio-controlplane
namespace: istio-system
kind: IstioOperator
spec:
profile: demo
meshConfig:
enablePrometheusMerge: false
defaultConfig:
proxyMetadata:
ISTIO_META_DNS_CAPTURE: "true"
ISTIO_META_DNS_AUTO_ALLOCATE: "true"
components:
egressGateways:
- name: istio-egressgateway
enabled: false
ingressGateways:
- name: istio-ingressgateway
enabled: false
values:
sidecarInjectorWebhook:
rewriteAppHTTPProbe: false
global:
meshID: usmesh
multiCluster:
clusterName: cluster-1
network: network-1
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: istio-eastwestgateway
namespace: istio-system
spec:
profile: empty
components:
ingressGateways:
- name: istio-eastwestgateway
label:
istio: eastwestgateway
app: istio-eastwestgateway
topology.istio.io/network: network-1
enabled: true
k8s:
env:
- name: ISTIO_META_ROUTER_MODE
value: "sni-dnat"
# The network to which traffic is routed
- name: ISTIO_META_REQUESTED_NETWORK_VIEW
value: network-1
service:
ports:
- name: status-port
port: 15021
targetPort: 15021
- name: mtls
port: 15443
targetPort: 15443
- name: tcp-istiod
port: 15012
targetPort: 15012
- name: tcp-webhook
port: 15017
targetPort: 15017
values:
global:
meshID: usmesh
multiCluster:
clusterName: cluster-1
network: network-1
expose-services.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: cross-network-gateway
namespace: istio-system
spec:
selector:
istio: eastwestgateway
servers:
- port:
number: 15443
name: tls
protocol: TLS
tls:
mode: AUTO_PASSTHROUGH
hosts:
- "*.local"
namespace-2.yaml
controlplane-2.yaml
eastwest-gateway-2.yaml
위 3개 파일을 신규로 생성하되
내용의 network, cluster name을 2번 cluster에 맞춰 변경해 놓는다.
$ kubectl --context="ctx-1" apply -f tmp/namespace-1.yaml
$ kubectl create secret generic cacerts -n istio-system \
--from-file=./certs/cluster-1/ca-cert.pem \
--from-file=./certs/cluster-1/ca-key.pem \
--from-file=./certs/root-cert.pem \
--from-file=./certs/cluster-1/cert-chain.pem --dry-run -o yaml > tmp/certs.yaml
$ kubectl --context="ctx-1" -n istio-system apply -f tmp/certs.yaml
$ istioctl --context="ctx-1" install -y -f tmp/controlplane-1.yaml
$ istioctl --context="ctx-${CLUSTER_INDEX}" install -y -f tmp/eastwest-gateway-1.yaml
$ kubectl --context="ctx-1" apply -n istio-system -f ./expose-services.yaml
$ kubectl --context="ctx-1" get nodes -o json | jq '.items[].status.addresses[0].address' > tmp/nodes.txt
$ export NODES=`sed -z 's/\n/,/g;s/,$/\n/' tmp/nodes.txt`
$ kubectl --context="ctx-1" patch service istio-eastwestgateway --patch "{\"spec\": {\"externalIPs\": [${NODES}]}}" -n istio-system
$ istioctl --context="ctx-1" x create-remote-secret --name="cluster-1" > tmp/cluster-secret-1.yaml
$ kubectl --context="ctx-1" apply -f tmp/cluster-secret-1.yaml
$ kubectl --context="ctx-2" apply -f tmp/namespace-2.yaml
$ kubectl create secret generic cacerts -n istio-system \
--from-file=./certs/cluster-2/ca-cert.pem \
--from-file=./certs/cluster-2/ca-key.pem \
--from-file=./certs/root-cert.pem \
--from-file=./certs/cluster-2/cert-chain.pem --dry-run -o yaml > tmp/certs.yaml
$ kubectl --context="ctx-2" -n istio-system apply -f tmp/certs.yaml
$ istioctl --context="ctx-2" install -y -f tmp/controlplane-2.yaml
$ istioctl --context="ctx-2" install -y -f tmp/eastwest-gateway-2.yaml
$ kubectl --context="ctx-2" apply -n istio-system -f ./expose-services.yaml
$ kubectl --context="ctx-2" get nodes -o json | jq '.items[].status.addresses[0].address' > tmp/nodes.txt
$ export NODES=`sed -z 's/\n/,/g;s/,$/\n/' tmp/nodes.txt`
$ kubectl --context="ctx-2" patch service istio-eastwestgateway --patch "{\"spec\": {\"externalIPs\": [${NODES}]}}" -n istio-system
$ istioctl --context="ctx-2" x create-remote-secret --name="cluster-2" > tmp/cluster-secret-1.yaml
$ kubectl --context="ctx-2" apply -f tmp/cluster-secret-2.yaml
$ kubectl --context=ctx-1 create ns sample
$ kubectl --context=ctx-2 create ns sample
$
$ kubectl --context=ctx-1 label namespace sample istio-injecti
on=enabled --overwrite
$ kubectl --context=ctx-2 label namespace sample istio-injecti
on=enabled --overwrite
아래 두개 Yaml 파일은 istio를 다운받으면 동일하게 존재하는 Yaml이다.
apiVersion: v1
kind: Service
metadata:
name: helloworld
labels:
app: helloworld
service: helloworld
spec:
ports:
- port: 5000
name: http
selector:
app: helloworld
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloworld-v1
labels:
app: helloworld
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: helloworld
version: v1
template:
metadata:
labels:
app: helloworld
version: v1
spec:
containers:
- name: helloworld
image: docker.io/istio/examples-helloworld-v1
resources:
requests:
cpu: "100m"
imagePullPolicy: IfNotPresent #Always
ports:
- containerPort: 5000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloworld-v2
labels:
app: helloworld
version: v2
spec:
replicas: 1
selector:
matchLabels:
app: helloworld
version: v2
template:
metadata:
labels:
app: helloworld
version: v2
spec:
containers:
- name: helloworld
image: docker.io/istio/examples-helloworld-v2
resources:
requests:
cpu: "100m"
imagePullPolicy: IfNotPresent #Always
ports:
- containerPort: 5000
apiVersion: v1
kind: Service
metadata:
name: helloworld
labels:
app: helloworld
service: helloworld
spec:
ports:
- port: 5000
name: http
selector:
app: helloworld
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: sleep
---
apiVersion: v1
kind: Service
metadata:
name: sleep
labels:
app: sleep
spec:
ports:
- port: 80
name: http
selector:
app: sleep
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sleep
spec:
replicas: 1
selector:
matchLabels:
app: sleep
template:
metadata:
labels:
app: sleep
sidecar.istio.io/inject: "true"
spec:
serviceAccountName: sleep
containers:
- name: sleep
image: curlimages/curl
command: ["/bin/sleep", "3650d"]
imagePullPolicy: IfNotPresent
$ kubectl --context=ctx-1 -n sample apply -f test/helloworld.yaml
$ kubectl --context=ctx-1 -n sample get pods
NAME READY STATUS RESTARTS AGE
helloworld-v1-78b9f5c87f-x7tb9 2/2 Running 0 67m
helloworld-v2-54dddc5567-rg2tr 2/2 Running 0 67m
$ kubectl --context=ctx-1 -n sample get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
helloworld ClusterIP 10.233.18.239 <none> 5000/TCP 67m
$ kubectl --context=ctx-2 -n sample apply -f test/sleep.yaml
$ kubectl --context=ctx-2 -n sample get pods
NAME READY STATUS RESTARTS AGE
sleep-5cc8999566-g77ws 2/2 Running 0 97m
$ kubectl --context=ctx-2 -n sample get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
helloworld ClusterIP 10.233.10.184 <none> 5000/TCP 3h49m
sleep ClusterIP 10.233.29.143 <none> 80/TCP 3h49m
ctx-2번에서 실행중인 sleep pod에 접속하여 helloworld.test:5000으로 curl을 실행하면 정상적으로 리턴되는 것을 볼 수 있다.
ubuntu@cp-cluster-a-1:~/istio-multi-cluster-initializer/tmp$ kubectl --context=ctx-2 -n sample exec -it sleep-5cc8999566-g77ws sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
~ $ curl helloworld.test:5000/hello
Hello version: v2, instance: helloworld-v2-54dddc5567-rg2tr
~ $ curl helloworld.test:5000/hello
Hello version: v1, instance: helloworld-v1-78b9f5c87f-x7tb9