4개의 시리즈 중 세 번 째로, 이번에는 2017/08 최종 버전인 Kubernetes 1.7.4 의 kubeadm 을 통한 클러스터 구축을 서로 다른 네트워크가 L3로 연결된 환경에서 구현하는 과정과 방법에 대해 알아 보고, 기본적 테스트와 검증을 진행하는 내용으로 마무리 하고자 한다.



각 노드에 해당하는 서버의 준비


  • Master: CentOS 7.3(1611), CPU 2, Memory 1.2GB, IP 10.255.10.170
  • Minion 1: CentOS 7.3(1611), CPU 2, Memory 1.2GB, IP 10.255.10.171
  • Minion 2: CentOS 7.3(1611), CPU 2, Memory 1.2GB, IP 10.255.20.170
  • Minion 3: CentOS 7.3(1611), CPU 2, Memory 1.2GB, IP 10.255.20.171



각 노드 기본 설정


* 전체 서버 개별 설정


# hostnamectl set-hostname kubemaster


# hostnamectl set-hostname kubenode1


# hostnamectl set-hostname kubenode2


# hostnamectl set-hostname kubenode3



* 전체 서버 공통 설정


# vi /etc/hosts

...

10.255.10.170 kubemaster

10.255.10.171 kubenode1

10.255.20.170 kubenode2

10.255.20.171 kubenode3

* 필수는 아님: kubeadm 으로 통한 node join 시 Warning 발생 . 작업 환경 내에 직접 관리하는 DNS 가 없을 경우, 편의를 위해 사용하는 방식임


# yum makecache fast

# yum install -y epel-release

# yum provides docker

# yum install -y docker-1.12.6-32.git88a4867.el7.centos.x86_64 chrony

# systemctl stop firewalld && systemctl disable firewalld

# systemctl enable docker && systemctl start docker 


# vi /etc/yum.repos.d/kubernetes.repo

[kubernetes]

name=Kubernetes

baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64

enabled=1

gpgcheck=1

repo_gpgcheck=1

gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg

        https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg



K8s Master 설정


[root@kubemaster ~]# vi /etc/sysctl.conf 

...

net.bridge.bridge-nf-call-iptables=1

net.bridge.bridge-nf-call-ip6tables=1

net.netfilter.nf_conntrack_max = 786432

[root@kubemaster ~]# sysctl -p


[root@kubemaster ~]# vi /etc/chrony.conf

...

server time.bora.net iburst

allow 10.255.0.0/16

local stratum 10

...

[root@kubemaster ~]# systemctl enable chronyd && systemctl restart chronyd

[root@kubemaster ~]# chronyc tracking

[root@kubemaster ~]# chronyc sources -v


[root@kubemaster ~]# yum update -y 

[root@kubemaster ~]# yum install -y kubelet kubeadm kubectl kubernetes-cni nmap bind-utils net-tools chrony wget fping jq git bash-completion

[root@kubemaster ~]# systemctl enable kubelet && systemctl start kubelet


[root@kubemaster ~]# source /etc/profile.d/bash_completion.sh

[root@kubemaster ~]# source <(kubectl completion bash)

* kubectl 명령 옵션의 자동 완성 기능 설정(option 사항임)


[root@kubemaster ~]# setenforce 0

* Permissive 로 임시 전환(부팅 후 enforcing 으로 자동 전환됨)


[root@kubemaster ~]# vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

...

Environment="KUBELET_DNS_ARGS=--cluster-dns=10.128.0.10 --cluster-domain=cluster.local"

...

[root@kubemaster ~]# systemctl daemon-reload

[root@kubemaster ~]# systemctl restart kubelet


* Cluster IP 범위(=service-cidr) 를 Default 값인 10.96.0.0/12 와 다른 값으로 바꾸려면, DNS IP도 그에 맞게 수정해 두어야 한다

* 해당 변경은 모든 Minion 노드에서도 각각 수행해 주어야 함(1.8.x 버전에서는 kubeadm init 옵션에서 이 부분을 동적으로 반영하도록 수정될 수 있음)


[root@kubemaster ~]# kubeadm init --skip-preflight-checks --pod-network-cidr 172.31.0.0/16 --service-cidr 10.128.0.0/12 --service-dns-domain "cluster.local" --apiserver-advertise-address 10.255.10.170

[kubeadm] WARNING: kubeadm is in beta, please do not use it for production clusters.

[init] Using Kubernetes version: v1.7.4

[init] Using Authorization modes: [Node RBAC]

[preflight] Skipping pre-flight checks

[kubeadm] WARNING: starting in 1.8, tokens expire after 24 hours by default (if you require a non-expiring token use --token-ttl 0)

[certificates] Generated CA certificate and key.

[certificates] Generated API server certificate and key.

[certificates] API Server serving cert is signed for DNS names [kubemaster kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.128.0.1 10.255.10.170]

[certificates] Generated API server kubelet client certificate and key.

[certificates] Generated service account token signing key and public key.

[certificates] Generated front-proxy CA certificate and key.

[certificates] Generated front-proxy client certificate and key.

[certificates] Valid certificates and keys now exist in "/etc/kubernetes/pki"

[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/admin.conf"

[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/kubelet.conf"

[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/controller-manager.conf"

[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/scheduler.conf"

[apiclient] Created API client, waiting for the control plane to become ready

[apiclient] All control plane components are healthy after 99.501670 seconds

[token] Using token: 826c89.818bf5757e8aa2cc

[apiconfig] Created RBAC rules

[addons] Applied essential addon: kube-proxy

[addons] Applied essential addon: kube-dns


Your Kubernetes master has initialized successfully!


To start using your cluster, you need to run (as a regular user):


  mkdir -p $HOME/.kube

  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

  sudo chown $(id -u):$(id -g) $HOME/.kube/config


You should now deploy a pod network to the cluster.

Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:

  http://kubernetes.io/docs/admin/addons/


You can now join any number of machines by running the following on each node

as root:


  kubeadm join --token 826c89.818bf5757e8aa2cc 10.255.10.170:6443

* 즉시 완료되지는 않으며, /var/log/message 에 connection refused .. 메시지가 다량 관찰 되며, 수 분~수 십분 가량 걸릴 수 있음

* 완료된 후에도 journal log 또는 /var/log/messages log에는 network plugin is not read: cni config uninitialized 오류는 계속 나옴(정상 상태)



K8s Minion(worker) 노드 전체 설정


[root@kubenode1 ~]# vi /etc/sysctl.conf 

...

net.bridge.bridge-nf-call-iptables=1

net.bridge.bridge-nf-call-ip6tables=1

net.netfilter.nf_conntrack_max = 786432

[root@kubenode1 ~]# sysctl -p


[root@kubenode1 ~]# vi /etc/chrony.conf

...

server 10.255.10.170 iburst

local stratum 10

...

[root@kubenode1 ~]# systemctl enable chronyd && systemctl restart chronyd

[root@kubenode1 ~]# chronyc tracking

[root@kubenode1 ~]# chronyc sources -v


[root@kubenode1 ~]#  yum update -y  

[root@kubenode1 ~]#  yum install -y kubelet kubeadm kubernetes-cni net-tools



K8s Master 노드 kubectl 실행환경 설정


[root@kubemaster ~]# mkdir -p $HOME/.kube

[root@kubemaster ~]# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

[root@kubemaster ~]# chown $(id -u):$(id -g) $HOME/.kube/config

[root@kubemaster ~]# export KUBECONFIG=$HOME/.kube/config

[root@kubemaster ~]# echo "export KUBECONFIG=$HOME/.kube/config" | tee -a ~/.bashrc



K8s Minion 노드 설정 후 각각 추가


[root@kubenode1 ~]# systemctl enable kubelet && systemctl start kubelet

[root@kubenode1 ~]# setenforce 0
[root@kubemaster ~]# vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

...

Environment="KUBELET_DNS_ARGS=--cluster-dns=10.128.0.10 --cluster-domain=cluster.local"

...

[root@kubemaster ~]# systemctl daemon-reload

[root@kubemaster ~]# systemctl restart kubelet


[root@kubenode1 ~]# kubeadm join --token 102952.1a7dd4d8d9f4cc5 10.255.10.170:6443

* Token 값은 새로운 노드를 추가할 떄 재사용 가능하며, 분실시에는 Master에서 'kubeadm token list' 로 알아낼 수 있다


K8s Master, Minion 노드 & Pod 실행 상태 확인


[root@kubemaster ~]# kubectl get nodes

NAME         STATUS     AGE       VERSION

kubemaster   NotReady   3m        v1.7.4

kubenode1    NotReady   9s        v1.7.4

kubenode2    NotReady   5s        v1.7.4

kubenode3    NotReady   1s        v1.7.4


[root@kubemaster ~]# kubectl get pods --all-namespaces

NAMESPACE     NAME                                 READY     STATUS    RESTARTS   AGE

kube-system   etcd-kubemaster                      1/1       Running   0          4m

kube-system   kube-apiserver-kubemaster            1/1       Running   0          3m

kube-system   kube-controller-manager-kubemaster   1/1       Running   0          4m

kube-system   kube-dns-2425271678-08gjk            0/3       Pending   0          4m

kube-system   kube-proxy-5hgsc                     1/1       Running   0          4m

kube-system   kube-proxy-68r71                     1/1       Running   0          1m

kube-system   kube-proxy-h262f                     1/1       Running   0          1m

kube-system   kube-proxy-s4n74                     1/1       Running   0          1m

kube-system   kube-scheduler-kubemaster            1/1       Running   0          4m

* kube-dns 이외의 모든 Pod 는 Running 상태이어야 하며, kube-dns 는 Network fabric solution 을 설치하기 전까지는 Pending 으로 나올 수 있음

(kubeadm은 network provider-agnostic함)



K8s Master, Calico CNI(Container Network Interface) plugin 설치 & 네트워크 활성화


[root@kubemaster ~]# git clone https://github.com/DragOnMe/kubernetes-1.7.3-with-calico-and-test-sample.git k8s-setup-test

[root@kubemaster ~]# cd k8s-setup-test/kube-cni-calico


[root@kubemaster kube-cni-calico]# vi calico.yaml 

...

17     etcd_endpoints: "http://10.128.232.136:6666"

...

113   clusterIP: 10.128.232.136

...

180             # Configure the IP Pool from which Pod IPs will be chosen.

181             - name: CALICO_IPV4POOL_CIDR

182               value: "172.31.0.0/16"

...

* calico_etcd 주소: 10.96.232.136 (default) 에서 10.128.232.136 으로 변경(Cluster IP cidr 범위 내에 있어야 함)

* CALICO_IPV4POOL_CIDR: 172.31.0.0/16(kubeadm init 시의 pod-network-cidr 값과 동일해야 함)

  CALICO_IPV4POOL_CIDR 범위 내의 IP가 Minion 노드의 tunl0 에 할당 되며, Pod에도 동적으로 할당 됨


[root@kubemaster ~]# cd ~

[root@kubemaster ~]# kubectl apply -f k8s-setup-test/kube-cni-calico/calico.yaml

configmap "calico-config" created

daemonset "calico-etcd" created

service "calico-etcd" created

daemonset "calico-node" created

deployment "calico-policy-controller" created

clusterrolebinding "calico-cni-plugin" created

clusterrole "calico-cni-plugin" created

serviceaccount "calico-cni-plugin" created

clusterrolebinding "calico-policy-controller" created

clusterrole "calico-policy-controller" created

serviceaccount "calico-policy-controller" created


[root@kubemaster ~]# kubectl get pods -n kube-system -o wide

NAME                                       READY     STATUS              RESTARTS   AGE       IP              NODE

calico-etcd-695ln                          0/1       ImagePullBackOff    0          5m        10.255.10.170   kubemaster

calico-node-278k3                          0/2       ContainerCreating   0          5m        10.255.20.171   kubenode3

calico-node-4l1f4                          0/2       ContainerCreating   0          5m        10.255.10.170   kubemaster

calico-node-cr5cr                          0/2       ErrImagePull        0          5m        10.255.20.170   kubenode2

calico-node-dr73h                          0/2       ContainerCreating   0          5m        10.255.10.171   kubenode1

calico-policy-controller-336633499-drd9n   0/1       Pending             0          5m        <none>          <none>

etcd-kubemaster                            1/1       Running             0          14m       10.255.10.170   kubemaster

kube-apiserver-kubemaster                  1/1       Running             0          13m       10.255.10.170   kubemaster

kube-controller-manager-kubemaster         1/1       Running             0          14m       10.255.10.170   kubemaster

kube-dns-2425271678-08gjk                  0/3       Pending             0          14m       <none>          <none>

kube-proxy-5hgsc                           1/1       Running             0          14m       10.255.10.170   kubemaster

kube-proxy-68r71                           1/1       Running             0          11m       10.255.10.171   kubenode1

kube-proxy-h262f                           1/1       Running             0          11m       10.255.20.170   kubenode2

kube-proxy-s4n74                           1/1       Running             0          10m       10.255.20.171   kubenode3

kube-scheduler-kubemaster                  1/1       Running             0          14m       10.255.10.170   kubemaster


[root@kubemaster ~]# kubectl get nodes

NAME         STATUS     AGE       VERSION

kubemaster   NotReady   29m       v1.7.4

kubenode1    Ready      26m       v1.7.4

kubenode2    NotReady   25m       v1.7.4

kubenode3    Ready      25m       v1.7.4

* Calico Network Pod가 정상 기동되기 전까지는 모든 노드는 NotReady 상태로 보일 수도 있다. 위의 과정을 보면 Calico Pod 가 Ready로 올라옴에 따라

노드가 하나씩 Ready 상태로 바뀌고 있는 것을 알 수 있다(Calico node Pod 의 경우 전체 Minion에 걸쳐 완료되려면 수 십분 정도 걸릴 수도 있다)


...

Aug 24 02:06:43 localhost kubelet: E0824 02:06:43.126000    3032 pod_workers.go:182] Error syncing pod 0c9bb31d-8825-11e7-b7d7-08002729d0c4 ("calico-etcd-695ln_kube-system(0c9bb31d-8825-11e7-b7d7-08002729d0c4)"), skipping: failed to "StartContainer" for "calico-etcd" with ImagePullBackOff: "Back-off pulling image \"quay.io/coreos/etcd:v3.1.10\""

Aug 24 02:06:43 localhost kubelet: W0824 02:06:43.531722    3032 cni.go:189] Unable to update cni config: No networks found in /etc/cni/net.d

Aug 24 02:06:43 localhost kubelet: E0824 02:06:43.531821    3032 kubelet.go:2136] Container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized

Aug 24 02:06:48 localhost kubelet: W0824 02:06:48.533281    3032 cni.go:189] Unable to update cni config: No networks found in /etc/cni/net.d

Aug 24 02:06:48 localhost kubelet: E0824 02:06:48.533882    3032 kubelet.go:2136] Container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized

...

* Example /var/log/messages


[root@kubemaster ~]# kubectl get pods -n kube-system -o wide

NAME                                       READY     STATUS    RESTARTS   AGE       IP              NODE

calico-etcd-695ln                          1/1       Running   0          45m       10.255.10.170   kubemaster

calico-node-278k3                          2/2       Running   7          45m       10.255.20.171   kubenode3

calico-node-4l1f4                          2/2       Running   5          45m       10.255.10.170   kubemaster

calico-node-cr5cr                          2/2       Running   8          45m       10.255.20.170   kubenode2

calico-node-dr73h                          2/2       Running   6          45m       10.255.10.171   kubenode1

calico-policy-controller-336633499-drd9n   1/1       Running   9          45m       10.255.20.171   kubenode3

etcd-kubemaster                            1/1       Running   0          30m       10.255.10.170   kubemaster

kube-apiserver-kubemaster                  1/1       Running   0          30m       10.255.10.170   kubemaster

kube-controller-manager-kubemaster         1/1       Running   0          30m       10.255.10.170   kubemaster

kube-dns-2425271678-08gjk                  3/3       Running   4          54m       172.31.45.192   kubenode3

kube-proxy-5hgsc                           1/1       Running   0          54m       10.255.10.170   kubemaster

kube-proxy-68r71                           1/1       Running   0          50m       10.255.10.171   kubenode1

kube-proxy-h262f                           1/1       Running   0          50m       10.255.20.170   kubenode2

kube-proxy-s4n74                           1/1       Running   0          50m       10.255.20.171   kubenode3

kube-scheduler-kubemaster                  1/1       Running   0          30m       10.255.10.170   kubemaster

* 시간이 지남에 따라 점차로 Pod들이 자리를 잡으며, 후반으로 가면 kube-dns가 Running 상태로 바뀌고 Pod Network의 IP를 할당 받음을 볼 수 있다


[root@kubemaster ~]# kubectl get nodes

NAME         STATUS    AGE       VERSION

kubemaster   Ready     55m       v1.7.4

kubenode1    Ready     51m       v1.7.4

kubenode2    Ready     51m       v1.7.4

kubenode3    Ready     51m       v1.7.4

* 모든 노드가 Ready 상태로 바뀌면 설치가 완료되어 Cluster 의 사용이 가능한 상태가 된 것이다



Cluster 정상 상태 및 DNS 동작 확인을 위한 Pod 생성


[root@kubemaster ~]# mkdir k8s-test && cd k8s-test

[root@kubemasterk8s-test]# vi busybox-for-dnstest.yaml

apiVersion: v1
kind: Pod
metadata:
  name: busybox-for-dnstest
  namespace: default
spec:
  containers:
  - image: busybox
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
    name: busybox-container
  restartPolicy: Always


[root@kubemasterk8s-test]# vi test-hostnames-deploy.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: hostnames
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: hostnames
    spec:
      containers:
      - name: hostnames
        image: gcr.io/google_containers/serve_hostname
        ports:
        - containerPort: 9376
          protocol: TCP


[root@kubemasterk8s-test]# vi test-hostnames-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: hostnames
spec:
  selector:
    app: hostnames
  ports:
  - name: default
    protocol: TCP
    port: 80
    targetPort: 9376


[root@kubemaster k8s-test]# kubectl create -f busybox-for-dnstest.yaml

pod "busybox-for-dnstest" created

[root@kubemaster k8s-test]# kubectl create -f test-hostnames-deploy.yaml 

deployment "hostnames" created

[root@kubemaster k8s-test]# kubectl create -f test-hostnames-svc.yaml 

service "hostnames" created



Cluster DNS 정상 작동 상태 확인


* Kubernetes 클러스터의 정상적인 서비스를 위해서 가장 중요한 요소 중 하나인 DNS 기능을 확인해 봄으로써, 전체 클러스터의 기본적 동작을 점검할 수 있다.


[root@kubemaster k8s-test]# kubectl exec -it busybox-for-dnstest -- sh

/ # nslookup yahoo.com

Server:    10.128.0.10

Address 1: 10.128.0.10 kube-dns.kube-system.svc.cluster.local


Name:      yahoo.com

Address 1: 2001:4998:58:c02::a9 ir1.fp.vip.bf1.yahoo.com

Address 2: 2001:4998:c:a06::2:4008 ir1.fp.vip.gq1.yahoo.com

Address 3: 2001:4998:44:204::a7 ir1.fp.vip.ne1.yahoo.com

Address 4: 206.190.36.45 ir1.fp.vip.gq1.yahoo.com

Address 5: 98.138.253.109 ir1.fp.vip.ne1.yahoo.com

Address 6: 98.139.180.149 ir1.fp.vip.bf1.yahoo.com

/ # nslookup kubernetes

Server:    10.128.0.10

Address 1: 10.128.0.10 kube-dns.kube-system.svc.cluster.local


Name:      kubernetes

Address 1: 10.128.0.1 kubernetes.default.svc.cluster.local

/ # nslookup hostnames

Server:    10.128.0.10

Address 1: 10.128.0.10 kube-dns.kube-system.svc.cluster.local


Name:      hostnames

Address 1: 10.128.89.48 hostnames.default.svc.cluster.local


/ # wget -O- http://hostnames

Connecting to hostnames (10.98.89.48:80)

hostnames-2923313648-rtlgg

-                    100% |*******************************|    27   0:00:00 ETA

/ # wget -O- http://hostnames

Connecting to hostnames (10.98.89.48:80)

hostnames-2923313648-f8s4x

-                    100% |*******************************|    27   0:00:00 ETA

/ # wget -O- http://hostnames

Connecting to hostnames (10.98.89.48:80)

hostnames-2923313648-rtlgg

-                    100% |*******************************|    27   0:00:00 ETA

/ # wget -O- http://hostnames

Connecting to hostnames (10.98.89.48:80)

hostnames-2923313648-j5tp0

-                    100% |*******************************|    27   0:00:00 ETA

/ # wget -O- http://hostnames

Connecting to hostnames (10.98.89.48:80)

hostnames-2923313648-rtlgg

-                    100% |*******************************|    27   0:00:00 ETA

/ # wget -O- http://hostnames

Connecting to hostnames (10.98.89.48:80)

hostnames-2923313648-f8s4x

-                    100% |*******************************|    27   0:00:00 ETA

* DNS의 Round-Robin 에 의해, wget 실행시 마다 다른 Pod에 번갈아서 접속됨을 확인할 수 있다



Cluster Network 정상 작동 확인(Master 노드 - ping - Cluster IP)


* Kubernetes 클러스터 내의 가상네트워크(ClusterIP) 의 정상 동작 여부 확인

[root@kubemaster k8s-test]# kubectl get pods -o wide

NAME                         READY     STATUS    RESTARTS   AGE       IP               NODE

busybox-for-dnstest          1/1       Running   0          4m        172.31.35.72     kubenode2

hostnames-2923313648-3104j   1/1       Running   0          4m        172.31.35.73     kubenode2

hostnames-2923313648-h4n8j   1/1       Running   0          4m        172.31.45.199    kubenode3

hostnames-2923313648-r89h4   1/1       Running   0          4m        172.31.205.197   kubenode1


[root@kubemaster k8s-test] kubectl get po -o json | jq .items[].status.podIP -r | fping

172.31.35.72 is alive

172.31.35.73 is alive

172.31.45.199 is alive

172.31.205.197 is alive

* 현재 리스트업 되는 모든 pod 들에 대해 ping 실행



Addon 설치 - Dashboard with Heapster, InfluxDB/Grafana


* Heapster, influxdb & grafana 설치

[root@kubemaster ~]# cd ~/k8s-setup-test/heapster

[root@kubemaster heapster]# kubectl create -f deploy/kube-config/influxdb

[root@kubemaster heapster]# kubectl create -f deploy/kube-config/rbac/heapster-rbac.yaml

* k8s-setup-test/heapster 의 내용은 https://github.com/kubernetes/heapster 의 내용과 동일함


* kubernetes-dashboard 설치

[root@kubemaster ~]# cd ~/k8s-setup-test/kubernetes-dashboard/

[root@kubemaster kubernetes-dashboard]# kubectl apply -f kubernetes-dashboard.yaml

* k8s-setup-test/kubernetes-dashboard/kubernetes-dashboard.yaml 내용은   https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/kubernetes-dashboard.yaml 의 내용과 동일함


* Dashboard 접속 URL 확인

[root@kubemaster ~]# kubectl -n kube-system expose deployment kubernetes-dashboard --name kubernetes-dashboard-nodeport --type=NodePort

[root@kubemaster ~]# kubectl get svc -nkube-system

NAME                            CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE

calico-etcd                     10.128.232.136    <none>        6666/TCP         20h

heapster                        10.108.175.104   <none>        80/TCP           15h

kube-dns                        10.128.0.10       <none>        53/UDP,53/TCP    21h

kubernetes-dashboard            10.103.62.100    <none>        80/TCP           1h

kubernetes-dashboard-nodeport   10.102.218.165   <nodes>       9090:30707/TCP   1h

monitoring-grafana              10.102.181.221   <none>        80/TCP           15h

monitoring-influxdb             10.99.75.72      <none>        8086/TCP         15h

* http://10.255.10.170:30707/ 로 dashboard 접속





클러스터 유지보수, 해체 등 운영 방법


  • 불가피한 사정으로 Cluster 를 셧다운 시는 Minion - Master 순으로 수행
  • 재기동 시는 Master-Minion 순으로 수행


* Minion 노드 유지보수(At master node)

[root@kubemaster ~]# kubectl get nodes

NAME         STATUS    AGE       VERSION

kubemaster   Ready     6d        v1.7.4

kubenode1    Ready     6d        v1.7.4

kubenode2    Ready     6d        v1.7.4

kubenode3    Ready     6d        v1.7.4

[root@kubemaster ~]#  kubectl drain hostname --force --ignore-daemonsets

node "hostname" cordoned

WARNING: Ignoring DaemonSet-managed pods: calico-node-f6an0, kube-proxy-jv53g

* 해당 노드는 cordoned 상태가 되며, 내부의 Pod는 유지되나, Pod의 추가 deploy 대상에서 제외됨


* 점검 후 복귀

[root@kubemaster ~]# kubectl uncordon node hostname


* 삭제 후 재투입(drain 후)

[root@kubemaster ~]# kubectl delete node hostname

[root@kubemaster ~]# kubeadm join --token xxxxxxxxxxxxxx 10.255.10.170:6443

* Minion 노드 재설치 및 신규 투입 과정과 동일함



* Cluster 해체시

[root@kubemaster ~]# kubectl drain hostname1 --delete-local-data --force --ignore-daemonsets

[root@kubemaster ~]# kubectl delete node hostname1

[root@kubemaster ~]# kubectl drain hostname2 --delete-local-data --force --ignore-daemonsets

[root@kubemaster ~]# kubectl delete node hostname2

...

[root@kubemaster ~]# kubeadm reset

[root@kubemaster ~]# systemctl daemon-reload

[root@kubemaster ~]# systemctl restart docker

[root@kubemaster ~]# systemctl restart kubelet

...

* At master node


[root@kubenode1 ~]# kubeadm reset

[root@kubenode1 ~]# systemctl daemon-reload

[root@kubenode1 ~]# systemctl restart docker

[root@kubenode1 ~]# systemctl restart kubelet

* Minion nodes



- Barracuda -


[관련 글 목록]

[Technical/Cloud, 가상화, PaaS] - [Kubernetes] CentOS 7.3 으로 Kubernetes Cluster 구성(with Flannel)-1/4

[Technical/Cloud, 가상화, PaaS] - [Kubernetes] CentOS 7.3 으로 Kubernetes Cluster 구성(노드 추가하기)-2/4

[Technical/Cloud, 가상화, PaaS] - [Kubernetes] 1.7.3/1.7.4, kubeadm 으로 L3 네트워크 기반 Cluster 구성(with Calico CNI)-3/4

[Technical/Cloud, 가상화, PaaS] - [Kubernetes] Hyper-converged GlusterFs integration with Heketi -4/4

[Technical/Cloud, 가상화, PaaS] - [GlusterFS & Kubernetes] External Gluster PV with Heketi CLI/Rest API



저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들


Kubernetes 를 CentOS 7 에서 설치하는 방법을 정리해 둔다. 3개의 VM을 준비하고, Mater 하나와 두 개의 Minion(Slave 또는 worker node, 그냥 노드라고도 한다) 구성의 Custer를 구현하되, 네트워크 백엔드 솔루션(Network Fabric)은 CoreOS 에서 기본 채택하고 있는 Flannel을 사용하여 서로 다른 호스트(Worker node, Minion)의 컨테이너간 터널링을 통한 연결이 가능하게 설정할 것이다(총 4개의 시리즈로, 마지막 포스팅에서는 Kubeadm 을 통해, BGP 라우팅이 가능한 Calico Network를 적용한 Kubernetes 클러스터를 구현해볼 예정이다)


Docker Engine과 함께 Kubernetes 를 설치하는 방법은, 모든 필수 패키지를 수작업으로 개별 설치하거나, Playbook 레시피를 적용하여 Ansible을 통해 자동화된 설치를 진행할 수도 있고 또는 Kubeadm 을 통해 간편하게 설치 및 설정을 할 수도 있다. 여기서는 첫 번 째에 언급한 수작업 설치(v1.5.2 기준, v1.6.x 이전 버전)을 진행해 보고자 한다.




준비 사항

VirtualBox VM 3개를 준비(예를 들어 본 Blog의 다른 포스트 - http://bryan.wiki/282 - 의 방법을 통해 CentOS 7.3 VM 3개를 찍어내 두도록 한다, 또는 VM 3개를 각각 만들고 일일이 ConeOS 7.3을 설치하는 수고로움을 즐겨도 좋다).


* Master: CPU 1, Memory 2GB, IP 10.255.10.180

* Minion 1: CPU 1, Memory 1.2GB, IP 10.255.10.181

* Minion 2: CPU 1, Memory 1.2GB, IP 10.255.10.182



[주의] 클러스터 구성에서 각 서버간의 시간동기화가 중요한 이슈가 될 수 있으므로, 기본적으로 ntp 또는 chrony 를 설정하고 Master 노드 또는 해당 환경 내의 전용 Time Server를 기준으로 설정해야 한다. 본 내용에서는 시간동기화 설정에 따로 다루지 않을 것이므로, 이전 포스팅 중 http://bryan.wiki/273 의 내용 중 일부를 찾아서 참고하기를 권한다.



클러스터 구성


아래의 그림과 유사한 아키텍처의 물리적 구성을 해도 좋고, VirtualBox를 통한 가상화 구성을 해도 좋다. 기본적으로 1개의 물리적 네트워크(인터넷 등 외부와 연결되는 External network)와 2개의 가상 네트워크를 사용하여 Kubernetes(=k8s) 클러스터를 구성하게 된다.





* External Private Network: 10.255.10.0/24 - Master/Minion 서버에서 사용하는 기본 네트워크

* Backend Network(Fabric): 172.31.0.0/16 - Container(Pod)가 사용하는 가상 네트워크(Flannel 을 통한 터널링)

* Service Cluster Network: 10.100.0.0/16 - Cluster 내부 DNS에 의해 IP를 자동 할당/관리하게되는 서비스용 가상 네트워크

* K8s에 의해 최초 생성되는 서비스는 'kubernetes' 이며, 항상 Service Cluster Network의 첫번째 IP(10.100.0.1)가 할당됨

* Cluster 내부 DNS(kube-dns 서비스)에는 Service Cluster Network의 IP 중 임의의 하나를 결정하고 할당(10.100.0.100)



각 노드에서 yum repository 설정, Docker/K8s/etcd/flannel 을 설치



# vi /etc/yum.repos.d/virt7-docker-common-release.repo

[virt7-docker-common-release]

name=virt7-docker-common-release

baseurl=http://cbs.centos.org/repos/virt7-docker-common-release/x86_64/os/

gpgcheck=0


# yum -y install --enablerepo=virt7-docker-common-release kubernetes etcd flannel wget git

* Kubernetes 1.5.2 버전(2016/12월 releae)이 설치된다. 아래에 소개 되는 설치/운영 방식은 이후 버전에서는 더 이상 적용되지 않는다.

* [참고] 1.6.0(2017/3월 release) 이후 버전부터는 kubeadm 을 통한 Cluster 설치/설정 운영 방식으로 동작하며, Minion 노드의 kube-proxy는 각 노드에 고루 존재하는 DaemonSet 방식의 Pod로 편재되는 아키텍처로 바뀌었으며 TLS 를 통한 암호화 통신을 기본으로 하는 등 높은 완성도와 안정화를 이루었다.



각 노드에서 Kunernetes 기본 설정


# vi /etc/kubernetes/config

# Comma separated list of nodes running etcd cluster

KUBE_ETCD_SERVERS="--etcd-servers=http://10.255.10.180:2379"


# Logging will be stored in system journal

KUBE_LOGTOSTDERR="--logtostderr=true"


# Journal message level, 0 is debug

KUBE_LOG_LEVEL="--v=0"


# Should this cluster be allowed to run privileged docker containers

KUBE_ALLOW_PRIV="--allow-privileged=false"


# Api-server endpoint used in scheduler and controller-manager

KUBE_MASTER="--master=http://10.255.10.180:8080"



Master 노드에서 etcd, API Server, Controller Manager 설정


[root@kubemaster ~]# vi /etc/etcd/etcd.conf

#[member]

ETCD_NAME=default

ETCD_DATA_DIR="/var/lib/etcd/default.etcd"

ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"

#[cluster]

ETCD_ADVERTISE_CLIENT_URLS="http://0.0.0.0:2379"


API Server 를 설정하기 위해서는 API 요청시 인증을 처리하기 위한 작업을 진행해야 한다. 웹 브라우저에서 github.com 의 공식 repository를 통해 make-ca-cert.sh 를 열어서 전체 내용을 복사, 작업 디렉토리(~/cacert)에 make-ca-cert.sh 로 저장 후, 30번쨰 라인을 다음과 같이 수정한 후, 지정된 Master와 k8s service 도메인에 대해 인증서를 생성한다.


[root@kubemaster ~]# vi make-ca-cert.sh

...

# /etc/group 에 kube 그룹이 존재함을 확인해 볼 것

cert_group=${CERT_GROUP:-kube}

...

[root@kubemaster ~]# chmod a+x make-ca-cert.sh


[root@kubemaster ~]# bash make-ca-cert.sh "10.255.10.180" "IP:10.255.10.180,IP:10.100.0.1,DNS:kubernetes,DNS:kubernetes.default,DNS:kubernetes.default.svc,DNS:kubernetes.default.svc.cluster.local"


이제 API Server 를 설정한다.


[root@kubemaster ~]# vi /etc/kubernetes/apiserver

# Bind kube API server to this IP

KUBE_API_ADDRESS="--address=0.0.0.0"


# Port that kube api server listens to.

KUBE_API_PORT="--port=8080"


# Port kubelet listen on

#KUBELET_PORT="--kubelet-port=10250"


# Comma separated list of nodes in the etcd cluster

KUBE_ETCD_SERVERS="--etcd-servers=http://10.255.10.180:2379"


# Address range to use for services(Work unit of Kubernetes)

KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.100.0.0/16"


# default admission control policies

KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"


# Add your own!

KUBE_API_ARGS="--client-ca-file=/srv/kubernetes/ca.crt --tls-cert-file=/srv/kubernetes/server.cert --tls-private-key-file=/srv/kubernetes/server.key"


Controller Manager 를 설정한다.


[root@kubemaster ~]# vi /etc/kubernetes/controller-manager

# Comma separated list of minions

KUBELET_ADDRESSES="--machines=10.255.10.181, 10.255.10.182"


# Add your own!

KUBE_CONTROLLER_MANAGER_ARGS="--root-ca-file=/srv/kubernetes/ca.crt --service-account-private-key-file=/srv/kubernetes/server.key"



각 Minion 노드에서 kubelet을 설정


[root@kubenode1 ~]# vi /etc/kubernetes/kubelet 

###

# kubernetes kubelet (minion) config


# The address for the info server to serve on (set to 0.0.0.0 or "" for all interfaces)

KUBELET_ADDRESS="--address=0.0.0.0"


# The port for the info server to serve on

#KUBELET_PORT="--port=10250"


# You may leave this blank to use the actual hostname

KUBELET_HOSTNAME="--hostname-override=10.255.10.181"


# location of the api-server

KUBELET_API_SERVER="--api-servers=http://10.255.10.180:8080"


# pod infrastructure container

#KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"


# Add your own!

KUBELET_ARGS="--cluster-dns=10.100.0.100 --cluster-domain=cluster.local"


[root@kubenode2 ~]# vi /etc/kubernetes/kubelet 

###

# kubernetes kubelet (minion) config


# The address for the info server to serve on (set to 0.0.0.0 or "" for all interfaces)

KUBELET_ADDRESS="--address=0.0.0.0"


# The port for the info server to serve on

#KUBELET_PORT="--port=10250"


# You may leave this blank to use the actual hostname

KUBELET_HOSTNAME="--hostname-override=10.255.10.182"


# location of the api-server

KUBELET_API_SERVER="--api-servers=http://10.255.10.180:8080"


# pod infrastructure container

#KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"


# Add your own!

KUBELET_ARGS="--cluster-dns=10.100.0.100 --cluster-domain=cluster.local"



컨테이너(Pod) 간 백엔드 네트워크를 위한 Flannel 설정


Master 노드에서 etcd 를 시작한다


[root@kubemaster ~]# systemctl enable etcd

[root@kubemaster ~]# systemctl start etcd



etcd 내에 flannel 을 위한 네트워크 정보 저장 공간을 위한 Key를 생성하고, 네트워크 설정 값을 등록한다. 다음과 같이 등록하면, /16 네트워크에 대한 /24 크기의 Flannel 서브넷이 각 Minion에 자동 할당된다


[root@kubemaster ~]# etcdctl mkdir /kube-centos/network

[root@kubemaster ~]# etcdctl mk /kube-centos/network/config "{ \"Network\": \"172.31.0.0/16\", \"SubnetLen\": 24, \"Backend\": { \"Type\": \"vxlan\" } }"



이제 모든 노드에서 다음과 같이 Flannel 에 대한 설정을 진행한다


# vi /etc/sysconfig/flanneld

# etcd URL location.  Point this to the server where etcd runs

FLANNEL_ETCD_ENDPOINTS="http://10.255.10.180:2379"


# etcd config key.  This is the configuration key that flannel queries

# For address range assignment

FLANNEL_ETCD_PREFIX="/kube-centos/network"


# Any additional options that you want to pass

#FLANNEL_OPTIONS=""



Master와 Minion 에서 firewall을 설정하고 각각 서비스를 enable한 후, 기동

(최초 설치를 시작할 때, 노드에 firewalld 패키지를 설치하지 않았다면 아래 방화벽 설정 부분은 무시해도 되며, 여기서는 Master/etcd node 에 대해서만 방화벽을 설정해 보도록 한다. Port 허용 정보는 -> 참고)


[root@kubemaster ~]# systemctl enable firewalld

[root@kubemaster ~]# systemctl start firewalld

[root@kubemaster ~]# firewall-cmd --permanent --zone=public --add-port=443/tcp

[root@kubemaster ~]# firewall-cmd --permanent --zone=public --add-port=6443/tcp

[root@kubemaster ~]# firewall-cmd --permanent --zone=public --add-port=8080/tcp

[root@kubemaster ~]# firewall-cmd --permanent --zone=public --add-port=8285/udp

[root@kubemaster ~]# firewall-cmd --permanent --zone=public --add-port=8472/udp

[root@kubemaster ~]# firewall-cmd --permanent --zone=public --add-port=2379-2380/tcp

[root@kubemaster ~]# firewall-cmd --reload


[root@kubemaster ~]# systemctl enable flanneld

[root@kubemaster ~]# systemctl start flanneld

[root@kubemaster ~]# systemctl enable kube-controller-manager

[root@kubemaster ~]# systemctl start kube-controller-manager

[root@kubemaster ~]# systemctl enable kube-scheduler

[root@kubemaster ~]# systemctl start kube-scheduler

[root@kubemaster ~]# systemctl enable kube-apiserver

[root@kubemaster ~]# systemctl start kube-apiserver


[root@kubenode1 ~]# systemctl disable firewalld

[root@kubenode1 ~]# systemctl stop firewalld


[root@kubenode1 ~]# systemctl enable flanneld

[root@kubenode1 ~]# systemctl start flanneld

[root@kubenode1 ~]# systemctl enable docker

[root@kubenode1 ~]# systemctl start docker

[root@kubenode1 ~]# systemctl enable kubelet

[root@kubenode1 ~]# systemctl start kubelet

[root@kubenode1 ~]# systemctl enable kube-proxy

[root@kubenode1 ~]# systemctl start kube-proxy



각 노드에서 /24 크기의 Flannel 서브넷의 첫 번째 IP가 docker0에 할당되어 있는지 확인해 본다


[root@kubenode02 ~]# ifconfig

docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450

        inet 172.31.83.1  netmask 255.255.255.0  broadcast 0.0.0.0

        inet6 fe80::42:80ff:fe4a:e1d6  prefixlen 64  scopeid 0x20<link>

        ether 02:42:80:4a:e1:d6  txqueuelen 0  (Ethernet)

        RX packets 236  bytes 20760 (20.2 KiB)

        RX errors 0  dropped 0  overruns 0  frame 0

        TX packets 115  bytes 8656 (8.4 KiB)

        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

...

flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450

        inet 172.31.83.0  netmask 255.255.255.255  broadcast 0.0.0.0

        ether d2:bd:7a:e9:cd:e4  txqueuelen 0  (Ethernet)

        RX packets 108  bytes 7310 (7.1 KiB)

        RX errors 0  dropped 0  overruns 0  frame 0

        TX packets 80  bytes 10160 (9.9 KiB)

        TX errors 0  dropped 1 overruns 0  carrier 0  collisions 0



현재까지의 설정이 끝나면, Master 노드에서는 kube-apiserver, etcd, kube-controller-manager, kube-scheduler, flanneld 가 정상 가동 되고 있어야 하며,

Minion 노드에서는 kube-proxy, kubelet, flanneld, docker 가 정상 가동 되고 있어야 한다(systemctl status ~ 로 확인 또는 마지막 부분의 kube-check~ 스크립트를 작성하고 실행).



클러스터의 현재 상태를 확인해 보자


[root@kubemaster ~]# kubectl get nodes

NAME            STATUS    AGE

10.255.10.181   Ready     3m

10.255.10.182   Ready     3m

[root@kubemaster ~]# kubectl cluster-info

Kubernetes master is running at http://localhost:8080


To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.



k8s Addon 의 설치와 설정


kube-dns 서비스(Cluster 내부 DNS) 의 설정으로 서비스 discovery를 가능하게 해 보자. Master 노드에서 다음과 같이 kube-dns ReplicationController와 Service를 기동한다


# mkdir k8s-addon && cd k8s-addon

# git clone https://github.com/DragOnMe/kubernetes-mod-skydns-dashboard-mon.git

# cd kubernetes-mod-skydns-dashboard-mon

# kubectl create -f DNS/skydns-rc.yaml

# vi DNS/skydns-svc.yaml

...

   clusterIP: 10.100.0.100

...

# kubectl create -f DNS/skydns-svc.yaml


각 Minion 노드의 kubelet 서비스를 재시작해 준다


# systemctl restart kubelet


kube-system 네임스페이스에 kube-dns 서비스가 작동중인지 확인해 보자


[root@kubemaster ~]# kubectl get svc --all-namespaces

NAMESPACE     NAME         CLUSTER-IP     EXTERNAL-IP   PORT(S)         AGE

default       kubernetes   10.100.0.1     <none>        443/TCP         44m

kube-system   kube-dns     10.100.0.100   <none>        53/UDP,53/TCP   46s



필수적인 것은 아니지만, k8s 클러스터의 상태 모니터링 등을 위해 도움이 되는 dashboard Addon을 설치해 보자


[root@kubemaster kubernetes-mod-skydns-dashboard-mon]# kubectl create -f Dashboard/dashboard-controller.yaml

deployment "kubernetes-dashboard" created

[root@kubemaster kubernetes-mod-skydns-dashboard-mon]# kubectl create -f Dashboard/dashboard-service.yaml

service "kubernetes-dashboard" created


dashboard 서비스의 접속은 http://10.255.10.180:8080/ui 로 접속해 보면 된다.




Heapster와 Grafana, InfluxDB를 이용한 dashboard 상의 monitoring Addon(Arun Dhyani 님 제공) 을 설치해 보자


[root@kubemaster kubernetes-mod-skydns-dashboard-mon]# kubectl create -f cluster-monitoring/influxdb

service "monitoring-grafana" created

deployment "heapster-v1.2.0" created

service "heapster" created

replicationcontroller "monitoring-influxdb-grafana-v4" created

service "monitoring-influxdb" created


Google의 gcr.io 로부터 heapster 구동에 필요한 컨테이너의 Pull & Deploy 가 진행중이다


Heapster와 influxdb, grafana 의 설치가 완료되면 대쉬보드에서 그래프와 차트가 나타남을 확인할 수 있다



부팅/종료 및 데몬 서비스 기동 순서 & Sample Script


클러스터 운영/관리 단계에서 Master 노드와 Worker 노드를 종료, 기동하는 순서와, 각 데몬 서비스를 종료하고 시작하는 순서가 중요하다. 반드시 다음의 순서를 지켜 주어야 한다


* Kubernetes 클러스터 부팅시: Master 를 먼저 시작하고 데몬 서비스 로딩이 완료되면 Worker 노드를 차례로 시작하고 데몬 서비스 로딩 확인

  Kubernetes 클러스터 종료시: Worker 노드를 먼저 종료하고 마지막에 Master 노드를 종료


* 노드 내의 데몬 서비스 기동 순서(종료는 기동 순서의 역순)

  - Master 노드: etcd > flanneld > kube-controller-manager > kube-scheduler > kube-apiserver

  - Worker 노드: flanneld > docker > kubelet > kube-proxy



* Master 노드 관리 Script

[root@kubemaster ~]# cat kube-check-master.sh 

#!/bin/bash
for SERVICES in etcd flanneld kube-apiserver kube-controller-manager kube-scheduler;
    do echo --- $SERVICES --- ;
    systemctl is-active $SERVICES ;
    systemctl is-enabled $SERVICES ;
    echo "";  
done


[root@kubemaster ~]# cat kube-start-master.sh 

#!/bin/bash
for SERVICES in etcd flanneld kube-controller-manager kube-scheduler kube-apiserver ;
    do echo --- Starting $SERVICES --- ;
    systemctl start $SERVICES ;
    echo "Done";  
    echo "";  
done


[root@kubemaster ~]# cat kube-stop-master.sh 

#!/bin/bash
for SERVICES in kube-apiserver kube-scheduler kube-controller-manager flanneld etcd ;
    do echo --- Stopping $SERVICES --- ;
    systemctl stop $SERVICES ;
    echo "Done";  
    echo "";  
done


* Worker 노드 관리 Script

[root@kubenode01 ~]# cat kube-check-node.sh 

#!/bin/bash
for SERVICES in docker flanneld kubelet kube-proxy;
    do echo --- $SERVICES --- ;
    systemctl is-active $SERVICES ;
    systemctl is-enabled $SERVICES ;
    echo "";  
done


[root@kubenode01 ~]# cat kube-start-node.sh 

#!/bin/bash
for SERVICES in flanneld docker kubelet kube-proxy ;
    do echo --- Starting $SERVICES --- ;
    systemctl start $SERVICES ;
    echo "Done";  
    echo "";  
done


[root@kubenode01 ~]# cat kube-stop-node.sh 

#!/bin/bash
for SERVICES in kube-proxy kubelet docker flanneld;
    do echo --- Stopping $SERVICES --- ;
    systemctl stop $SERVICES ;
    echo "Done";  
    echo "";  
done



- Barracuda -


[관련 글 목록]

[Technical/Cloud, 가상화, PaaS] - [Kubernetes] CentOS 7.3 으로 Kubernetes Cluster 구성(with Flannel)-1/4

[Technical/Cloud, 가상화, PaaS] - [Kubernetes] CentOS 7.3 으로 Kubernetes Cluster 구성(노드 추가하기)-2/4

[Technical/Cloud, 가상화, PaaS] - [Kubernetes] 1.7.3/1.7.4, kubeadm 으로 L3 네트워크 기반 Cluster 구성(with Calico CNI)-3/4

[Technical/Cloud, 가상화, PaaS] - [Kubernetes] Hyper-converged GlusterFs integration with Heketi -4/4

[Technical/Cloud, 가상화, PaaS] - [GlusterFS & Kubernetes] External Gluster PV with Heketi CLI/Rest API



저작자 표시 비영리 변경 금지
신고
블로그 이미지

Barracuda

Bryan의 MemoLog. 쉽게 익혀 보는 IT 실습과 개념원리, 코딩 세계의 얕은 맛보기들, 평범한 삶 주변의 현상 그리고 進上, 眞想, 진상들