Translate

вівторок, 12 вересня 2017 р.

Kubernetes. Part II: Setup cluster with kubeadm. Plugins

Після ознайомлення з теорією можна перейти і до практичної частини. Цього разу установимо кластер Kubernetes на bare-metal, тобто звичайні віртуальні машини чи залізні сервера, що не входять до існуючих IAAS платформ.

Способів установки Kubernetes кластеру існує дуже багато. Всі ці перераховані варіанти різної актуальності, необхідно дивитись і перевіряти все уважно, щоб не витратити зайвого часу на марні спроби. Найбільш популярні способи:

  • minikube. Найпростіший спосіб установки Kubernetes на власний локальний PC. Буде корисний людям, котрі хочуть приступити до вивчення Kubernetes, не втрачаючи купу часу на його більш повноцінну установку. 
  • kubeadm. Підтримує установку на звичайні bare-metal сервера чи віртуальні машини, що працюють під управлінням наступних операційних систем Ubuntu 16.04+, CentOS 7 чи HypriotOS v1.0.1+ (Debian+Docker для ARM девайсів). Наразі kubeadm перебуває в статусі beta і поки не підтримує створення HA (High Availability) Master інсталяцій, проте підтримку цієї функції обіцяють в наступних релізах.
  • kops. Призначений для розгортання Kubernetes на AWS, для чого використовує API виклики платформи. Написаний на мові Go. Як зазначено на github сторінці проекту, робота kops з GCE та VMware vSphere перебуває в статусі альфа, а в майбутньому також планується підтримка інших хмарних платформ. У якості операційної системи для вузлів використовує Debian/Ubuntu, проте також є початкова підтримка CentOS/RHEL. Підтримує розгортання HA Master конфігурацій.
  • kubespray. По суті це набір Ansible плейбуків для розгортання Kubernetes на платформах AWS, GCE, Azure, OpenStack, vSphere чи bare-metal машинах. Має найбільш обширний список підтримки дистрибутивів Linux: Container Linux by CoreOS, Debian Jessie, Ubuntu 16.04, CentOS/RHEL 7. Це community-проект. https://kubernetes.io/docs/getting-started-guides/kubespray/
  • conjure-up. Комплекс скриптів установки, котрий розробляє компанія Canonical. У основі conjure-up лежать такі технології як Juju, MAAS та LXD. Це чудовий варіант, якщо у якості хост-системи вас задовольняє Ubuntu. Також підтримує довгий перелік можливих cloud платформ. https://kubernetes.io/docs/getting-started-guides/ubuntu/installation/

У цій статті ми розгорнемо власний кластер Kubernetes за допомогою утиліти kubeadm. Це буде не HA інсталяція на основі операційної системи Ubuntu 16.04, що в свою чергу працюватиме в системі віртуалізації VirtualBox. Перелік адрес хостів та їх доменів наступний:

k8s-m1  192.168.60.110
k8s-s1    192.168.60.111
k8s-s2    192.168.60.112
k8s-s3    192.168.60.113

Як рекомендує офіційна документація, кожній віртуальній машині варто виділити як мінімум 1ГБ оперативної пам’яті, інакше може не вистачити місця для запуску додатків.

Kubernetes використовує Docker у якості runtime для запуску контейнерів, тому спочатку його необхідно встановити на всі вузли:

# aptitude update
# aptitude install apt-transport-https ca-certificates linux-image-extra-$(uname -r) linux-image-extra-virtual

# apt-key adv \
--keyserver hkp://ha.pool.sks-keyservers.net:80 \
--recv-keys 58118E89F3A912897C070ADBF76221572C52609D

# echo "deb https://apt.dockerproject.org/repo ubuntu-xenial main" | tee /etc/apt/sources.list.d/docker.list
# aptitude update
# aptitude install docker-engine=1.12.0-0~xenial
# service docker start

Не варто встановлювати версію новішу за 1.12, адже нові версії не протестовані для роботи з Kubernetes. Розумним також буде заблокувати автооновлення пакету docker-engine:

# aptitude hold docker-engine

Проінсталюємо kubectl. Це утиліта управління кластером і необхідна вона лише там, де будуть виконуватись сервісні команди. Проте, можливо, вона не буде зайвою і на всіх вузлах кластеру:

# curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl

# chmod +x ./kubectl
# mv ./kubectl /usr/local/bin/kubectl

За наступним посиланням https://kubernetes.io/docs/tasks/tools/install-kubectl/ можна знайти також kubectl для Mac та Windows.

Тепер проінсталюємо kubeadm (пакет, завдяки якому збирається кластер) та kubelet. Вони необхідні на всіх вузлах кластеру:

# apt-get update
# apt-get install -y apt-transport-https
# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -

# echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | tee /etc/apt/sources.list.d/kubernetes.list

# apt-get update
# apt-get install -y kubelet kubeadm

Установка kubelet та kubeadm нічим не складніша і для CentOS.

Майстер - це вузол, на якому будуть запущені всі компоненти контролю кластера: etcd, kube-apiserver, kube-controller-manager та інші. У нашому випадку вони всі працюватимуть на одному вузлі. Ініціалізуємо майстер:

root@k8s-m1:~# kubeadm init
[kubeadm] WARNING: kubeadm is in beta, please do not use it for production clusters.
[init] Using Kubernetes version: v1.7.1
[init] Using Authorization modes: [Node RBAC]
[preflight] Running pre-flight checks
[certificates] Generated CA certificate and key.
[certificates] Generated API server certificate and key.
[certificates] API Server serving cert is signed for DNS names [k8s-m1 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.60.110]
[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 83.501445 seconds
[token] Using token: 0112b9.a272913e1e302089
[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 0112b9.a272913e1e302089 192.168.60.110:6443

Далі, як видно із виводу останньої команди, необхідно скопіювати налаштування admin.conf на всі вузли, з яких є необхідність управління кластером:

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

Установити плагін для реалізації оверлейної мережі для зв'язку pod-to-pod чи pod-to-services. Я скористався Weave Net плагіном:

# kubectl apply -n kube-system -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
serviceaccount "weave-net" created
clusterrole "weave-net" created
clusterrolebinding "weave-net" created
daemonset "weave-net" created

Деталі щодо установки інших плагінів та їх перелік доступний в офіційній документації Kubernetes. Тут можна почитати про їхні особливості та продуктивність роботи https://habrahabr.ru/company/flant/blog/332432/.

Наразі нам нічого не заважає приступити до підключення нод (воркерів) до вже працюючого майстра. Тому по черзі підключемо сервери k8-s1 - k8-s3. Значення токену беремо з попереднього виводу kubeadm init:

# kubeadm join --token 0112b9.a272913e1e302089 192.168.60.110:6443 --skip-preflight-checks
[kubeadm] WARNING: kubeadm is in beta, please do not use it for production clusters.
[preflight] Skipping pre-flight checks
[discovery] Trying to connect to API Server "192.168.60.110:6443"
[discovery] Created cluster-info discovery client, requesting info from "https://192.168.60.110:6443"
[discovery] Cluster info signature and contents are valid, will use API Server "https://192.168.60.110:6443"
[discovery] Successfully established connection with API Server "192.168.60.110:6443"
[bootstrap] Detected server version: v1.7.1
[bootstrap] The server supports the Certificates API (certificates.k8s.io/v1beta1)
[csr] Created API client to obtain unique certificate for this node, generating keys and certificate signing request
[csr] Received signed certificate from the API server, generating KubeConfig...
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/kubelet.conf"

Node join complete:
* Certificate signing request sent to master and response
  received.
* Kubelet informed of new secure connection details.

Run 'kubectl get nodes' on the master to see this machine join.

Виведемо список вузлів, що входять в кластер:

root@k8s-m1:~# kubectl get nodes
NAME      STATUS     AGE       VERSION
k8s-m1    Ready      6m        v1.7.1
k8s-s1    Ready      3m        v1.7.1
k8s-s2    Ready      1m        v1.7.1
k8s-s3    Ready      8s        v1.7.1

Та інформацію по кластеру:

# kubectl cluster-info
Kubernetes master is running at https://192.168.60.110:6443
KubeDNS is running at https://192.168.60.110:6443/api/v1/namespaces/kube-system/services/kube-dns/proxy

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


TEST APP: SOCK SHOP


Здається, кластер наразі працює. Запустимо тестовий додаток Sock Shop, щоб в цьому пересвідчитись на прикладі. Створимо новий namespace:

# kubectl create namespace sock-shop
namespace "sock-shop" created

Скориставшись готовим описом Kubernetes об'єктів complete-demo.yaml, задеплоїмо додаток:

# kubectl apply -n sock-shop -f "https://github.com/microservices-demo/microservices-demo/blob/master/deploy/kubernetes/complete-demo.yaml?raw=true"
deployment "carts-db" created
service "carts-db" created
deployment "carts" created
service "carts" created
deployment "catalogue-db" created
service "catalogue-db" created
deployment "catalogue" created
service "catalogue" created
deployment "front-end" created
service "front-end" created
deployment "orders-db" created
service "orders-db" created
deployment "orders" created
service "orders" created
deployment "payment" created
service "payment" created
deployment "queue-master" created
service "queue-master" created
deployment "rabbitmq" created
service "rabbitmq" created
deployment "shipping" created
service "shipping" created
deployment "user-db" created
service "user-db" created
deployment "user" created
service "user" created

Звісно це не миттєва операція, і, можливо, варто буде трохи зачекати. Перевіримо чи всі поди стартонули:

root@k8s-m1:~# kubectl get pods -n sock-shop -o wide
NAME                           READY   STATUS    RESTARTS   AGE    IP           NODE
carts-2469883122-k7np6         1/1     Running   0          2m     10.38.0.18   k8s-s2
carts-db-1721187500-rk1nl      1/1     Running   0          2m     10.40.0.20   k8s-s1
catalogue-4293036822-pss1d     1/1     Running   0          2m     10.38.0.25   k8s-s2
catalogue-db-1846494424-99594  1/1     Running   0          2m     10.40.0.22   k8s-s1
front-end-2337481689-phzzq     1/1     Running   0          2m     10.38.0.27   k8s-s2
orders-733484335-shnc0         1/1     Running   0          2m     10.38.0.28   k8s-s2
orders-db-3728196820-xlr3c     1/1     Running   0          2m     10.34.0.18   k8s-s3
payment-3050936124-xtbdr       1/1     Running   0          2m     10.40.0.25   k8s-s1
queue-master-2067646375-qhm4f  1/1     Running   0          2m     10.34.0.20   k8s-s3
rabbitmq-241640118-1v8vh       1/1     Running   0          2m     10.38.0.32   k8s-s2
shipping-2463450563-cv9k6      1/1     Running   0          2m     10.34.0.21   k8s-s3
user-1574605338-n9h9d          1/1     Running   0          2m     10.34.0.22   k8s-s3
user-db-3152184577-z72wj       1/1     Running   0          2m     10.40.0.28   k8s-s1

Також можна переглянути всі об'єкти які стосуються нового додатка: поди (po), сервіси (svc), деплойменти (deploy), replicaSets(rs)

root@k8s-m1:~# kubectl get all -n sock-shop
NAME                               READY     STATUS    RESTARTS   AGE
po/carts-2469883122-k7np6          1/1       Running   0          2m
po/carts-db-1721187500-rk1nl       1/1       Running   0          2m
po/catalogue-4293036822-pss1d      1/1       Running   0          2m
po/catalogue-db-1846494424-99594   1/1       Running   0          2m
po/front-end-2337481689-phzzq      1/1       Running   0          2m
po/orders-733484335-shnc0          1/1       Running   0          2m
po/orders-db-3728196820-xlr3c      1/1       Running   0          2m
po/payment-3050936124-xtbdr        1/1       Running   0          2m
po/queue-master-2067646375-qhm4f   1/1       Running   0          2m
po/rabbitmq-241640118-1v8vh        1/1       Running   0          2m
po/shipping-2463450563-cv9k6       1/1       Running   0          2m
po/user-1574605338-n9h9d           1/1       Running   0          2m
po/user-db-3152184577-z72wj        1/1       Running   0          2m

NAME               CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
svc/carts          10.106.126.55    <none>        80/TCP         2m
svc/carts-db       10.104.201.231   <none>        27017/TCP      2m
svc/catalogue      10.99.227.31     <none>        80/TCP         2m
svc/catalogue-db   10.109.40.138    <none>        3306/TCP       2m
svc/front-end      10.106.182.240   <nodes>       80:30001/TCP   2m
svc/orders         10.106.43.216    <none>        80/TCP         2m
svc/orders-db      10.99.23.238     <none>        27017/TCP      2m
svc/payment        10.104.15.122    <none>        80/TCP         2m
svc/queue-master   10.108.239.139   <none>        80/TCP         2m
svc/rabbitmq       10.103.223.16    <none>        5672/TCP       2m
svc/shipping       10.105.112.68    <none>        80/TCP         2m
svc/user           10.111.111.224   <none>        80/TCP         2m
svc/user-db        10.102.78.107    <none>        27017/TCP      2m

NAME                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/carts          1         1         1            1           2m
deploy/carts-db       1         1         1            1           2m
deploy/catalogue      1         1         1            1           2m
deploy/catalogue-db   1         1         1            1           2m
deploy/front-end      1         1         1            1           2m
deploy/orders         1         1         1            1           2m
deploy/orders-db      1         1         1            1           2m
deploy/payment        1         1         1            1           2m
deploy/queue-master   1         1         1            1           2m
deploy/rabbitmq       1         1         1            1           2m
deploy/shipping       1         1         1            1           2m
deploy/user           1         1         1            1           2m
deploy/user-db        1         1         1            1           2m

NAME                         DESIRED   CURRENT   READY     AGE
rs/carts-2469883122          1         1         1         2m
rs/carts-db-1721187500       1         1         1         2m
rs/catalogue-4293036822      1         1         1         2m
rs/catalogue-db-1846494424   1         1         1         2m
rs/front-end-2337481689      1         1         1         2m
rs/orders-733484335          1         1         1         2m
rs/orders-db-3728196820      1         1         1         2m
rs/payment-3050936124        1         1         1         2m
rs/queue-master-2067646375   1         1         1         2m
rs/rabbitmq-241640118        1         1         1         2m
rs/shipping-2463450563       1         1         1         2m
rs/user-1574605338           1         1         1         2m
rs/user-db-3152184577        1         1         1         2m

Завдяки опції nodePort: 30001 сервісу front-end можна перевірити роботу додатку в браузері, якщо перебувати в тій же мережі, що і вузли кластеру:


Пересвідчитись в цьому також можна через kubectl:

root@k8s-m1:~# kubectl describe svc front-end -n sock-shop
Name: front-end
Namespace: sock-shop
Labels: name=front-end
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"name":"front-end"},"name":"front-end","namespace":"sock-shop"},"spec":{"por...
Selector: name=front-end
Type: NodePort
IP: 10.106.182.240
Port: <unset> 80/TCP
NodePort: <unset> 30001/TCP
Endpoints: 10.38.0.27:8079
Session Affinity: None
Events: <none>

root@k8s-m1:~# kubectl -n sock-shop get svc front-end
NAME        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
front-end   10.106.182.240   <nodes>       80:30001/TCP   18h

Додаток Sock Shop доступний також і для інших платформ контейнеризації та оркестрації.


CONTAINER RESOURCE MONITORING (heapster/influxdb/graphana)


По-замовчуванню Kubernetes не збирає метрики контейнерів, проте має готові власні рішення. Для цього необхідно встановити аддон-сервіс Heapster, котрий відповідальний за опитування Kubelet на кожному вузлі. Останній же в свою чергу опитує cAdvisor. В останніх релізах Kubernetes cAdvisor вже вкомпільовано в kubelet.

Web-інтерфейс cAdvisor по-замовчуванню вимкнено, проте його можна активувати, відредагувавши 10-kubeadm.conf і перезапустивши kubelet:

root@k8s-m1:~# sed "s/cadvisor-port=0/cadvisor-port=4194/g" -i /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
root@k8s-m1:~# systemctl daemon-reload
root@k8s-m1:~# systemctl restart kubelet

Відповідно, якщо робота cAdvisor важлива на всіх вузлах - попередні дії також необхідно виконати всюди. cAdvisor має наступний вигляд:



Перейдемо до установки Heapster з логуванням в Influxdb та представлення даних через Grafana.

$ cd /tmp
$ git clone git@github.com:kubernetes/heapster.git

Доступ до інстансу Grafana буде відбуватись завдяки опції type: NodePort, адже у нас немає стороннього балансувальника. Тому перед створенням відповідних подів варто відредагувати файл grafana.yaml:

$ vim heapster/deploy/kube-config/influxdb/grafana.yaml

і в ньому розкоментувати рядок 'type: NodePort'

$ kubectl create -f heapster/deploy/kube-config/influxdb/
deployment "monitoring-grafana" created
service "monitoring-grafana" created
serviceaccount "heapster" created
deployment "heapster" created
service "heapster" created
deployment "monitoring-influxdb" created
service "monitoring-influxdb" created

$ kubectl create -f heapster/deploy/kube-config/rbac/heapster-rbac.yaml

Перевіряємось чи вже працюють нові поди:

$ kubectl get pods --namespace=kube-system | egrep 'grafana|heapster|influx'
heapster-84017538-ng80v                 1/1       Running   0          3m
monitoring-grafana-1500490092-fnnr6     1/1       Running   0          3m
monitoring-influxdb-1870447071-h8fvm    1/1       Running   0          3m

Та через який порт доступна Grafana:

$ kubectl -n kube-system get svc monitoring-grafana
NAME                 CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
monitoring-grafana   10.109.245.164   <nodes>       80:32757/TCP   4m

Далі необхідно залогінитись (логін та пароль по-замовчуванню - admin), додати data source InfluxDB і через декілька хвилин, можна спостерігати нові графіки:


Доступ до Grafana також можна організувати наступним чином:

$ kubectl port-forward -n kube-system $(kubectl get -n kube-system pod --selector=k8s-app=grafana -o jsonpath='{.items..metadata.name}') 9999:3000
Forwarding from 127.0.0.1:9999 -> 3000
Forwarding from [::1]:9999 -> 3000

Де 9999 - порт що буде слухатись локально, а 3000 порт, на котрому працює Grafana в оверлейній мережі.


KUBERNETES DASHBOARD


Це один із додатків, що працюють в окремих подах простору імен kube-system. Його установка досить тривіальна:

# kubectl create -f https://git.io/kube-dashboard
serviceaccount "kubernetes-dashboard" created
clusterrolebinding "kubernetes-dashboard" created
deployment "kubernetes-dashboard" created
service "kubernetes-dashboard" created

Перевіримо чи працює відповідний под:

# kubectl get pods --namespace=kube-system | egrep 'kubernetes-dashboard'
kubernetes-dashboard-2209332821-wsq4x   1/1       Running   0         2m

Щоб переглянути Dashboard на віддаленій машині необхідно запустити проксі з відповідною конфігурацією з будь-якого хосту кластера:

$ scp username@192.168.60.110:/etc/kubernetes/admin.conf .

На віддаленій машині має бути встановлений kubectl. Повторюсь, що інструкцію для його установки можна знайти за посиланням https://kubernetes.io/docs/tasks/tools/install-kubectl:

$ kubectl --kubeconfig ./admin.conf proxy
Starting to serve on 127.0.0.1:8001

Після цього все можна переглядати в браузері, звернувшись до локального порту:




Для роботи Kubernetes Dashboard не обов'язково встановлювати Heapster, але без нього не будуть працювати базові графіки вгорі.


WEAVE SCOPE


Розробка компанії Weaveworks, також розробника оверлейної мережі Weave Net. Є чудовим доповненням до стандартної панелі Kubernetes Dashboards.

Установка відбувається наступним чином:

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

Доступ до панелі може бути реалізований за допомогою LoadBalancer чи NodePort (як у випадку з Grafana) опцій. Ми ж просто перенаправимо локальний порт прямо в контейнер з додатком, щоб переглядати панель на будь-якому хосту:

$ kubectl port-forward -n kube-system "$(kubectl get -n kube-system pod --selector=weave-scope-component=app -o jsonpath='{.items..metadata.name}')" 4040
Forwarding from 127.0.0.1:4040 -> 4040
Forwarding from [::1]:4040 -> 4040
Handling connection for 4040

У результаті посилання для доступу до панелі матиме вигляд http://localhost:4040/.

Поговоримо трохи про можливості Weave Scope. Ця панель ілюструє взаємодію вузлів/подів/контейнерів/процесів:




Відображає споживання ресурсів окремими вузлами/процесами:


Надає термінальний доступ одразу з панелі до контейнерів:


Показує базову сервісну інформацію одиниць Kubernetes: подів, сервісів, деплоїв і, навіть, вміє управляти деякими їхніми параметрами:


На цьому все. У наступній статті ми познайомимость ближче з одиницями Kubеrnetes та побачимо як вони організовані.

Посилання:
https://github.com/kubernetes-incubator/kubespray/blob/master/docs/comparisons.md
https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/
https://kubernetes.io/docs/admin/high-availability/
https://github.com/kubernetes-incubator/kubespray/blob/master/docs/ha-mode.md
https://platform9.com/blog/create-highly-available-kubernetes-cluster/
https://kubernetes.io/docs/tasks/debug-application-cluster/resource-usage-monitoring/
https://github.com/kubernetes/heapster/blob/master/docs/influxdb.md
https://deis.com/blog/2016/kubernetes-logging-with-elasticsearch-and-kibana/
https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/
https://www.outcoldman.com/en/archive/2017/06/20/using-kubeadm-to-create-kubernetes-on-ubuntu-server/
https://www.outcoldman.com/en/archive/2017/07/09/kubernetes-monitoring-resources/
https://www.weave.works/docs/scope/latest/installing/#k8s

Немає коментарів:

Дописати коментар