Кластеры Kubernetes в сервисе VPC



    Мы добавили возможность удобного запуска Kubernetes в сервисе Виртуальное приватное облако в режиме раннего beta-тестирования.


    Эта функциональность будет полезна пользователям, которым требуется удобное управление большим количеством приложений, запущенных в виде контейнеров. Kubernetes предлагает средства для масштабирования, самовосстановления, балансировки нагрузки для контейнеров, запущенных внутри кластера.


    Так как сервис Виртуальное приватное облако построен на базе OpenStack, мы используем один из его компонентов — OpenStack Magnum. Он позволяет быстро создавать приватные кластеры Kubernetes с нужным количеством нод.


    В настоящее время любой пользователь нашего сервиса может может создавать в своем проекте несколько независимых друг от друга кластеров. В качестве нод кластера будут использованы виртуальные машины, конфигурацию которых можно выбрать и изменить.


    В этой статье мы расскажем про основные объекты кластера Kubernetes и на примерах рассмотрим процесс создания кластера при помощи OpenStack Magnum.


    Создание и управление кластером Kubernetes


    В настоящее время создание кластера Kubernetes возможно только через консольные утилиты или OpenStack API в зонах доступности ru-1a и ru-1b (Санкт-Петербург).


    Для начала работы вам понадобится:


    • Создать новый или использовать существующий проект VPC;
    • Создать пользователя с SSH-ключом;
    • Добавить пользователя в созданный проект на странице управления проектами;
    • Перейти в проект и получить файл доступа на вкладке Доступ;
    • Установить консольный клиент openstack с библиотекой python-magnumclient;
    • Установить консольный клиент kubectl.

    Для установки консольного клиента openstack можно воспользоваться инструкцией по ссылке, однако, стоит иметь ввиду, что для данного клиента также потребуется установить библиотеку python-magnumclient, для поддержки создания Kubernetes кластеров.


    Полный набор команд для установки openstack клиента с требуемым плагином для операционных систем семейства Ubuntu/Debian:


    $ sudo apt update
    $ sudo apt -y install curl python-pip python-dev python3-dev git libxml2-dev libxslt1-dev python-openssl python3-openssl python-pyasn1 libffi-dev libssl-dev build-essential
    $ sudo pip install -UI pbr setuptools pytz
    $ sudo pip install -UI git+https://github.com/openstack/python-openstackclient
    $ sudo pip install -UI git+https://github.com/openstack/python-magnumclient

    Полный набор команд для установки openstack клиента с требуемым плагином для операционных систем семейства Fedora/CentOS:


    $ sudo yum -y install python-pip gcc libffi-devel python-devel libxslt-devel openssl-devel git libffi-devel
    $ sudo pip install -UI pbr setuptools pytz
    $ sudo pip install -UI git+https://github.com/openstack/python-openstackclient
    $ sudo pip install -UI git+https://github.com/openstack/python-magnumclient

    Для управления объектами Kubernetes вам потребуется консольный клиент kubectl. Способы установки для различных операционных систем описаны в официальной документации.


    Для создания кластера вам потребуется создать или использовать существующие:


    • Шаблон кластера (cluster template);
    • Набор параметров для CPU и RAM виртуальных машин (flavor).

    Вы можете создать cluster template и flavor самостоятельно, или использовать публичные заранее созданные шаблоны.


    Также вам потребуется определиться с зоной доступности, типом дисков для вашего кластера и количеством нод. Стоит учесть, что в мы еще не поддерживаем возможность создания одного кластера в нескольких зонах. Вы можете выбрать любой тип сетевого диска (быстрый, универсальный или базовый).
    Подробнее о типах дисков можно узнать из нашей базы знаний.


    Количество нод может быть разное для master и для minion ролей. На нодах, выполняющих master роль, будут запущены управляющие элементы кластера — controller-manager, scheduler, api. На остальных нодах будут запущены сервисы kubelet, kube-proxy и все контейнеры приложений. Подробнее о компонентах, запускаемых на нодах кластера можно узнать из официальной документации.


    Для доступа на ноды по SSH вам потребуется использовать SSH-ключ, созданный ранее. В примерах команд будет использован ключ с именем ssh-test.


    Мы будем использовать публичные cluster template и flavor, быстрый тип диска, и зону доступности ru-1b.
    В нашем кластере изначально будет запущено 2 master ноды и 3 minion ноды.


    Для проверки указанных параметров воспользуемся командами openstackclient и скачанным файлом доступа (rc.sh):


    # Запуск файла с доступом к проекту для установки требуемых параметров.
    $ source rc.sh
    
    # Конфигурация серверов, которую мы будем использовать для всех нод кластера
    $ openstack flavor show BL1.2-4096 -c ram -c vcpus
    +-------+-------+
    | Field | Value |
    +-------+-------+
    | ram   | 4096  |
    | vcpus | 2     |
    +-------+-------+
    
    # Быстрый тип диска в зоне доступности ru-1b
    $ openstack volume type show fast.ru-1b -c name
    +-------+------------+
    | Field | Value      |
    +-------+------------+
    | name  | fast.ru-1b |
    +-------+------------+
    
    # Доступные шаблоны кластеров Kubernetes
    $ openstack coe cluster template list -c name
    +---------------------------------------+
    | name                                  |
    +---------------------------------------+
    | kubernetes-nofloatingips-ru-1b-v1.9.3 |
    | kubernetes-nofloatingips-ru-1b-v1.9.6 |
    | kubernetes-nofloatingips-ru-1b-v1.9.9 |
    | kubernetes-floatingips-ru-1b-v1.9.3   |
    | kubernetes-floatingips-ru-1b-v1.9.6   |
    | kubernetes-floatingips-ru-1b-v1.9.9   |
    | kubernetes-nofloatingips-ru-1a-v1.9.3 |
    | kubernetes-nofloatingips-ru-1a-v1.9.6 |
    | kubernetes-nofloatingips-ru-1a-v1.9.9 |
    | kubernetes-floatingips-ru-1a-v1.9.3   |
    | kubernetes-floatingips-ru-1a-v1.9.6   |
    | kubernetes-floatingips-ru-1a-v1.9.9   |
    +---------------------------------------+

    Для примера мы выберем второй шаблон кластера, из него не будут созданы публично доступные плавающие адреса для каждой из нод. Нам они не потребуются.


    # Создание кластера Kubernetes с именем test-cluster
    # В качестве keypair используется имя ключа, созданного ранее
    $ openstack coe cluster create \
      --cluster-template kubernetes-nofloatingips-ru-1b-v1.9.9 \
      --master-count 2 \
      --node-count 3 \
      --keypair ssh-test \
      --master-flavor BL1.2-4096 \
      --flavor BL1.2-4096 \
      test-cluster

    Обратите внимание, что мы выбрали одинаковую конфигурацию для разных нод (параметры master-flavor и flavor), вы можете выбирать разные наборы конфигурации в зависимости от требований кластера. Их изменение возможно и после его создания.


    Также стоит учесть, что при создании кластера с несколькими master нодами, автоматически будет создан балансировщик нагрузки для доступа к API Kubernetes.


    Через несколько минут в вашем проекте появится кластер Kubernetes. В панели управления проектом вы увидите новые виртуальные машины, диски и сетевые объекты.


    Вы можете проверить статус вашего кластера через openstackclient:


    openstack coe cluster list -c name -c status
    +--------------+--------------------+
    | name         | status             |
    +--------------+--------------------+
    | test-cluster | CREATE_IN_PROGRESS |
    +--------------+--------------------+

    После того как кластер перейдет в состояние CREATE_COMPLETE, вы сможете управлять его объектами через утилиту kubectl, скачав конфигурационный файл при помощи следующих команд:


    $ mkdir -p ~/test-cluster
    
    $ openstack coe cluster config test-cluster --dir ~/test-cluster

    После этого можно работать с кластером при помощи утилиты kubectl:


    $ export KUBECONFIG=~/test-cluster/config
    
    $ kubectl get pods --all-namespaces -o=custom-columns=NAME:.metadata.name,STATUS:.status.phase
    
    NAME                                               STATUS
    coredns-785dcf9c58-6gnfp                           Running
    heapster-6846cdc674-rm4k6                          Running
    kube-dns-autoscaler-6b94f7bbf8-x5clt               Running
    kubernetes-dashboard-747575c864-wlg6p              Running
    monitoring-grafana-84b4596dd7-zf5rx                Running
    monitoring-influxdb-c8486fc95-bqqb6                Running
    node-exporter-test-cluster-robvp4cvwpt7-minion-0   Running

    При необходимости вы можете увеличить или уменьшить количество minion нод в кластере через openstackclient, передав новое значение node_count:


    $ openstack coe cluster update test-cluster replace node_count=4

    Основные объекты кластера Kubernetes


    Pods


    Несмотря на то, что Kubernetes руководит набором контейнеров, базовой сущностью, которой управляет Kubernetes, является не контейнер, а Pod.


    Pod представляет из себя набор пространства имен ядра Linux и настроек сетевого стека, которые позволяют собирать набор контейнеров в единую сущность.
    Чаще всего, один контейнер с приложением запускается внутри одного отдельного Pod-а.
    При необходимости, можно запускать и несколько контейнеров внутри одного Pod-а, это может быть полезно, когда вам необходимо предоставить доступ из одного контейнера в другой через сетевой интерфейс localhost, либо по каким-то другим причинам запускать несколько контейнеров на одном хосте.
    Все контейнеры, запущенные в одном Pod-е будут иметь один хостнейм, IP-адрес, таблицу маршрутизации и диски.


    Стоит заметить, что при масштабировании количества экземпляров вашего приложения внутри Kubernetes, необходимо увеличивать именно количество Pod-ов, а не количество контейнеров в одном конкретном Pod-е.
    Подробнее в официальной документации Pods.


    Для примера создадим максимально простой Pod с Nginx при помощи описания в формате yaml:


    # nginx-basic.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:
      containers:
      - name: nginx
        image: library/nginx:1.14-alpine
        ports:
        - containerPort: 80

    Для создания Pod-а мы можем воспользоваться утилитой kubectl.
    Мы добавили все примеры, изложенные в статье, в нашу группу Github, поэтому вы можете не создавать файлы у себя на компьютере, а использовать url-адрес файла из публичного репозитория :


    $ kubectl create \
      -f https://raw.githubusercontent.com/selectel/kubernetes-examples/master/pods/nginx-basic.yaml

    После создания мы можем запросить полную информацию о статусе Pod-а, используя команду kubectl describe:


    $ kubectl describe pod nginx
    Name:         nginx
    Namespace:    default
    Node:         test-cluster-nd5c5y6lsfxb-minion-0/10.0.0.5
    Start Time:   Sun, 17 Jun 2018 12:29:03 +0000
    Labels:       <none>
    Annotations:  <none>
    Status:       Running
    IP:           10.100.88.9
    Containers:
      nginx:
        Container ID:   docker://6ca6383b66686c05c61c1f690737110e0f8994eda393f44a7ebfbbf2b2026267
        Image:          library/nginx:1.14-alpine
        Image ID:       docker-pullable://docker.io/nginx@sha256:944b79ca7dbe456ce72e73e70816c1990e39967c8f010349a388c00b77ec519c
        Port:           80/TCP
        Host Port:      0/TCP
        State:          Running
          Started:      Sun, 17 Jun 2018 12:29:16 +0000
        Ready:          True
        Restart Count:  0
        Environment:    <none>
        Mounts:
          /var/run/secrets/kubernetes.io/serviceaccount from default-token-rp5ls (ro)
    Conditions:
      Type           Status
      Initialized    True
      Ready          True
      PodScheduled   True
    Volumes:
      default-token-rp5ls:
        Type:        Secret (a volume populated by a Secret)
        SecretName:  default-token-rp5ls
        Optional:    false
    QoS Class:       BestEffort
    Node-Selectors:  <none>
    Tolerations:     <none>
    Events:
      Type       Reason         Age   From                     Message
       ----          ------             ----     ----                           -------
      Normal  Scheduled     52s   default-scheduler   Successfully assigned nginx to test-cluster-nd5c5y6lsfxb-minion-0
      Normal  SuccessfulMountVolume  51s   kubelet, test-cluster-nd5c5y6lsfxb-minion-0  MountVolume.SetUp succeeded for volume "default-token-rp5ls"
      Normal  Pulling          50s   kubelet, test-cluster-nd5c5y6lsfxb-minion-0  pulling image "library/nginx:1.14-alpine"
      Normal  Pulled           39s   kubelet, test-cluster-nd5c5y6lsfxb-minion-0  Successfully pulled image "library/nginx:1.14-alpine"
      Normal  Created        39s   kubelet, test-cluster-nd5c5y6lsfxb-minion-0  Created container
      Normal  Started         39s   kubelet, test-cluster-nd5c5y6lsfxb-minion-0  Started container

    Как можно заметить, Pod запустился на ноде с именем test-cluster-nd5c5y6lsfxb-minion-0 и получил внутренний IP-адрес 10.100.88.9.


    Из раздела Events видно основные события запуска — выбор ноды для запуска и скачивание образа.


    Мы можем попасть в Pod и проверить состояние процессов внутри контейнера:


    $ kubectl exec -it nginx sh
    
    ps aux
    PID   USER     TIME   COMMAND
      1       root       0:00     nginx: master process nginx -g daemon off;
      7      nginx      0:00     nginx: worker process
     20      root       0:00     sh
     24      root       0:00     ps aux
    
    exit

    Следует иметь ввиду, что IP-адрес 10.100.88.9 не будет доступен другим приложениям внутри и вне Kubernetes кластера, доступ к запущенному Nginx будет возможен только изнутри самого Pod-а:


    $ ping -c 1 10.100.88.9
    PING 10.100.88.9 (10.100.88.9): 56 data bytes
    
    --- 10.100.88.9 ping statistics ---
    1 packets transmitted, 0 packets received, 100% packet loss
    
    $ kubectl exec nginx -- ping -c1 10.100.88.9
    PING 10.100.88.9 (10.100.88.9): 56 data bytes
    64 bytes from 10.100.88.9: seq=0 ttl=64 time=0.075 ms
    
    --- 10.100.88.9 ping statistics ---
    1 packets transmitted, 1 packets received, 0% packet loss
    round-trip min/avg/max = 0.075/0.075/0.075 ms

    Вдобавок к тому, что указанный IP-адрес доступен только из контейнера, он также не является постоянным. Это значит, что если этот Pod будет пересоздан, то он может получить другой IP-адрес.


    Чтобы решить эти проблемы, можно использовать объект под названием Service.


    Services


    Service позволяет назначать постоянные IP-адреса для Pod-ов, предоставлять им доступ из внешних сетей и балансировать запросы между Pod-ами.
    Подробнее про Service можно узнать в официальной документации.


    Для примера нам потребуется удалить запущенный Pod:


    $ kubectl delete pod nginx

    Добавим в описание Pod-а метку (Label), которая потребуется для Service:


    # nginx-labeled.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: webservice
    spec:
      containers:
      - name: nginx
        image: library/nginx:1.14-alpine
        ports:
        - containerPort: 80

    Нам также потребуется описание Service:


    # nginx-nodeport.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-nodeport
      labels:
        app: webservice
    spec:
      type: NodePort
      ports:
      - port: 80
        nodePort: 30001
        protocol: TCP
      selector:
        app: webservice

    Создадим Pod и Service:


    $ kubectl create \
      -f https://raw.githubusercontent.com/selectel/kubernetes-examples/master/pods/nginx-labeled.yaml \
      -f https://raw.githubusercontent.com/selectel/kubernetes-examples/master/services/nginx-nodeport.yaml 

    Так как созданный Service имеет тип NodePort, то на всех нодах кластера будет открыт указанный нами порт 30001 на всех сетевых интерфейсах.
    Это значит, что если мы добавим к любой ноде внешний IP-адрес, то мы сможем получить доступ к запущенному Pod-у с Nginx из внешней сети.


    Чтобы не использовать внешние адреса нод кластера для доступа к Service, мы можем использовать тип LoadBalancer вместо NodePort.
    Нам понадобится новое описание сервиса:


    # nginx-loadbalancer.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-loadbalancer
      labels:
        app: webservice
    spec:
      type: LoadBalancer
      ports:
      - port: 80
        protocol: TCP
      selector:
        app: webservice

    Удалим текущий сервис и применим новое описание:


    $ kubectl delete service nginx-service
    $ kubectl create \
      -f https://raw.githubusercontent.com/selectel/kubernetes-examples/master/services/nginx-loadbalancer.yaml

    После запуска сервиса, Nginx станет доступен по TCP порту 80 из внешней сети, при этом не будет необходимости назначать и использовать внешние адреса для нод кластера. Service с типом LoadBalancer автоматически выделит новый внешний адрес в ваш проект VPC и начнет его использовать.


    Вы можете получить информацию о выделенном внешнем адресе при помощи kubectl:


    $ kubectl get service nginx-service -o=custom-columns=IP:status.loadBalancer.ingress[0].ip
    IP
    xxx.xxx.xxx.xxx

    В наших примерах запускался только один Pod с Nginx. Чтобы масштабировать приложение на большее количество Pod-ов, мы можем использовать Deployment.


    Deployments


    Deployment представляет из себя сущность кластера Kubernetes, позволяющую масштабировать Pod-ы и производить удобное обновление или откат версий для большого количества Pod-ов.
    Вместо Deployment можно также использовать объект ReplicaSet, однако мы не коснемся его в наших примерах.
    Подробнее о Deployment можно узнать в официальной документации.


    Нам снова потребуется удалить Pod (нам не требуется удалять Service):


    $ kubectl delete pod nginx

    Добавим следующее описание Deployment:


    # nginx-1.14.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
    spec:
      replicas: 10
      selector:
        matchLabels:
          app: webservice
     minReadySeconds: 10
     strategy:
        type: RollingUpdate
        rollingUpdate:
          maxUnavailable: 1
          maxSurge: 1
     template:
        metadata:
          labels:
            app: webservice
       spec:
          containers:
          - name: nginx
            image: library/nginx:1.14-alpine
            ports:
            - containerPort: 80

    Создадим указанный Deployment:


    $ kubectl create -f \
      https://raw.githubusercontent.com/selectel/kubernetes-examples/master/deployments/nginx-1.14.yaml

    Мы выбрали значение 10 для параметра replicas, поэтому в нашем кластере будут созданы 10 Pod-ов с приложением Nginx:


    $ kubectl get pods --selector app=webservice
    NAME                                READY     STATUS    RESTARTS   AGE
    nginx-deployment-54bfdc4489-42rrb   1/1       Running   0          4m
    nginx-deployment-54bfdc4489-5lvtc   1/1       Running   0          4m
    nginx-deployment-54bfdc4489-g7rk2   1/1       Running   0          4m
    nginx-deployment-54bfdc4489-h5rxp   1/1       Running   0          4m
    nginx-deployment-54bfdc4489-l9l2d   1/1       Running   0          4m
    nginx-deployment-54bfdc4489-pjpvg   1/1       Running   0          4m
    nginx-deployment-54bfdc4489-q8dnp   1/1       Running   0          4m
    nginx-deployment-54bfdc4489-s4wzf   1/1       Running   0          4m
    nginx-deployment-54bfdc4489-tfxf9   1/1       Running   0          4m
    nginx-deployment-54bfdc4489-xjzb5   1/1       Running   0          4m

    Вы можете получить доступ из внешней сети к запущенному приложению, используя Service, созданный в предыдущем разделе. Service будет производить автоматическую балансировку запросов из внешней сети между 10 экземплярами Nginx.


    При необходимости, мы можем обновить версию Nginx. Обновим описание Deployment, изменив версию образа с 1.14-alpine на 1.15-alpine:


    # nginx-1.15.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
    spec:
      replicas: 10
      selector:
        matchLabels:
          app: webservice
     minReadySeconds: 10
     strategy:
        type: RollingUpdate
        rollingUpdate:
          maxUnavailable: 1
          maxSurge: 1
     template:
        metadata:
          labels:
            app: webservice
       spec:
          containers:
          - name: nginx
            image: library/nginx:1.15-alpine # <-- changed
            ports:
            - containerPort: 80

    Для запуска процесса обновления Pod-ов, воспользуемся командой kubectl. Обратите внимание на аргумент --record, он нам пригодится для последующего удобного отката версии Nginx:


    $ kubectl apply -f \
      https://raw.githubusercontent.com/selectel/kubernetes-examples/master/deployments/nginx-1.15.yaml \
      --record

    Вы можете следить за ходом обновления при помощи следующей команды:


    $ kubectl rollout status deployment nginx-deployment
    Waiting for rollout to finish: 4 out of 10 new replicas have been updated...

    Kubernetes будет ждать 10 секунд после успешного обновления одного Pod-а, так как мы указали значение 10 для параметра minReadySeconds в описании Deployment.


    После завершения обновления все Pod-ы для Deployment перейдут в активное состояние:


    $ kubectl get deployment --selector app=webservice
    NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment   10        10        10           10          23m

    Мы можем произвести откат версии приложения, если что-то пошло не так. Для этого нам потребуется выбрать нужную ревизию Deployment:


    $ kubectl rollout history deployment nginx-deployment
    deployments "nginx-deployment"
    REVISION  CHANGE-CAUSE
    1         <none>
    2         kubectl apply --filename=https://raw.githubusercontent.com/selectel/kubernetes-examples/master/deployments/nginx-1.15.yaml --record=true

    В выводе команды есть 2 ревизии — первая это изначальное создание Deployment, вторая это обновление. Так как мы использовали аргумент --record при обновлении, то мы видим команду, которая создала вторую ревизию Deployment.


    Для отката версии воспользуемся следующей командой:


    $ kubectl rollout undo deployment nginx-deployment --to-revision=1

    Аналогично с обновлением, мы можем следить за выполнением отката версии при помощи команды:


    $ kubectl rollout status deployment nginx-deployment
    Waiting for rollout to finish: 6 out of 10 new replicas have been updated…

    Во всех наших примерах мы использовали контейнеры без постоянного хранилища данных. В следующем разделе мы это исправим.


    Хранение данных


    По умолчанию, все данные контейнеров запущенных внутри Pod-ов являются эфемерными и будут потеряны падении Pod-а.


    Для запуска Pod-ов с постоянным хранилищем данных можно использовать объект PersistentVolumeClaim.


    Создать такой объект в кластере очень просто — достаточно добавить его описание, по аналогии с тем, как мы создавали Pod, Service или Deployment в предыдущих разделах.


    Подробнее можно узнать из официальной документации.


    Пример описания PersistentVolumeClaim, создающего диск размером 10GB:


    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: my-pv-claim
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 10Gi

    Мы можем подключить его в виде диска к нашему Pod, обновив описание Pod c Nginx, созданного ранее:


    # nginx-with-volume.yaml
    apiVersion: v1
    kind: Pod
    metadata:
     name: nginx
    spec:
      containers:
      - name: nginx
        image: library/nginx:1.14-alpine
        ports:
        - containerPort: 80
        volumeMounts:
          - mountPath: "/var/www/html"
            name: data
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: my-pv-claim

    Однако, для того, чтобы диск был создан, вам потребуется указать свойства создаваемого диска в виде StorageClass. В сервисе “Виртуальное приватное облако” можно использовать сетевые диски быстрого, универсального и базового типов в качестве постоянного хранилища данных Pod-ов Kubernetes.


    К примеру, чтобы создать StorageClass, который позволит использовать быстрые диски в зоне доступности ru-1b, вам потребуется следующее описание:


    # fast.ru-1b.yaml
    kind: StorageClass
    apiVersion: storage.k8s.io/v1
    metadata:
      name: fast.ru-1b
      annotations:
        storageclass.beta.kubernetes.io/is-default-class: "true"
    provisioner: kubernetes.io/cinder
    parameters:
      type: fast.ru-1b
      availability: ru-1b

    Перед созданием указанных объектов, удалим Deployment, созданный ранее:


    $ kubectl delete deployment nginx-deployment

    В первую очередь создадим StorageClass, таким образом он станет классом по умолчанию, и созданный впоследствии PersistentVolumeClaim будет использовать его:


    $ kubectl create -f \
    https://raw.githubusercontent.com/selectel/kubernetes-examples/master/storageclasses/fast.ru-1b.yaml  

    Создадим PersistentVolumeClaim и Pod:


    $ kubectl create \
    -f https://raw.githubusercontent.com/selectel/kubernetes-examples/master/persistentvolumeclaims/my-pv-claim.yaml \
    -f https://raw.githubusercontent.com/selectel/kubernetes-examples/master/pods/nginx-with-volume.yaml

    После этого в вашем проекте автоматически будет создан диск, который будет подключен к одной из minion-нод кластера. При её падении, диск будет автоматически переключен в другую ноду.


    Мы можем увидеть диск внутри контейнера с Nginx:


    $ kubectl exec -it nginx sh
    
    mount | grep "/var/www/html"
    /dev/sdc on /var/www/html type ext4 (rw,seclabel,relatime,data=ordered)
    
    exit

    Вы можете подключать диск и к Deployment. С соответствующим примером можно ознакомиться в официальной документации.


    Панель управления Kubernetes


    Вы можете использовать встроенную панель (dashboard) самого Kubernetes для просмотра состояния объектов кластера и их управления.


    Для доступа ко всем возможностям панели вам потребуется создать аккаунт с ролью администратора в вашем кластере.


    Для этого нам понадобится описание аккаунта:


    # admin-user.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: admin-user
      namespace: kube-system

    И описание роли:


    # cluster-admin.yaml
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: admin-user
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cluster-admin
    subjects:
    - kind: ServiceAccount
      name: admin-user
      namespace: kube-system

    Создадим указанные объекты:


    $ kubectl create \
      -f https://raw.githubusercontent.com/selectel/kubernetes-examples/master/accounts/admin-user.yaml \
      -f https://raw.githubusercontent.com/selectel/kubernetes-examples/master/clusterrolebindings/cluster-admin.yaml

    Далее вам потребуется узнать значение сгенерированного токена для этого аккаунта.
    Для этого требуется найти соответствующий объект типа Secret в кластере:


    $ kubectl get secret --namespace=kube-system | grep "admin-user-token"
    admin-user-token-bkfhb                   kubernetes.io/service-account-token   3         22m

    И посмотреть значение токена у найденного Secret с именем admin-user-token-bkfhb:


    $ kubectl describe secret admin-user-token-bkfhb --namespace=kube-system | grep "token:"
    token:      XXXXXX...

    В ответ вы получите значение токена, сохраните его, оно нам пригодится в дальнейшем.
    С подробностями разграничения доступа к объектам Kubernetes можно ознакомиться в официальной документации.


    В том случае, если вы создавали кластер из публичного шаблона, в нем уже существуют Pod и Service, обеспечивающие работу панели:


    $ kubectl get svc kubernetes-dashboard --namespace=kube-system                                                                                                                                                              206ms  Tue Jun 19 14:35:19 2018
    NAME                               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
    kubernetes-dashboard   ClusterIP   10.254.122.245      <none>              443/TCP     2d
    
    $ kubectl get pod --namespace=kube-system --selector k8s-app=kubernetes-dashboard                                                                                                                                                   119ms  Tue Jun 19 14:36:48 2018
    NAME                                                       READY     STATUS    RESTARTS   AGE
    kubernetes-dashboard-747575c864-jpxvt   1/1          Running             0            2d

    Так как Service имеет тип ClusterIP, то он будет доступен только изнутри самого кластера.
    Вы можете получить доступ к панели со своего рабочего компьютера с конфигурационным файлом кластера, используя команду kubectl:


    $ kubectl proxy
    Starting to serve on 127.0.0.1:8001

    Проверьте работоспособность proxy, открыв указанный адрес в браузере:



    Если вы видите ответ, аналогичный скриншоту, то можно перейти на экран панели управления, используя следующий адрес:


    http://127.0.0.1:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/ 

    Перейдя по нему, вы должны увидеть экран логина в панель:



    Вам потребуется указать токен, полученный ранее. После входа вы сможете использовать панель управления:



    Обо всех возможностях панели управления можно узнать в официальной документации.


    Мониторинг объектов Kubernetes


    В случае использования публичного шаблона кластера, у вас будут автоматически запущены компоненты для сбора и отображения метрик — Prometheus и Grafana.


    Аналогично панели управления, в качестве типа Service установлен ClusterIP, доступ к нему возможен только изнутри кластера или посредством kubectl proxy. Вы можете получить доступ к Grafana со своего рабочего компьютера по следующему адресу:


    http://127.0.0.1:8001/api/v1/proxy/namespaces/kube-system/services/monitoring-grafana:80


    Заключение


    В этой статье мы изучили наиболее часто используемые объекты Kubernetes и рассмотрели примеры по запуску и управлению кластером при помощи OpenStack Magnum.


    В ближайшее время станет возможным использование последних релизов Kubernetes, а управление кластером будет доступно через панель управления.


    Будем рады, если вы воспользуетесь нашим сервисом в режиме тестирования и предоставите обратную связь.

    • +24
    • 3,6k
    • 5

    Selectel

    116,68

    ИТ-инфраструктура для бизнеса

    Поделиться публикацией

    Похожие публикации

    Комментарии 5
      +2
      шикарно, спасибо
        –2
        Как будто кусок официальной документации прочитал. Неужели нельзя было что-то пооригинальнее придумать? Рассказали бы лучше на чем у вас Ingress, какие типы PV поддерживаются, что вообще за шаблоны кластеров, чем отличаются друг от друга?
          +4

          Мы попытались не отвлекать пользователей от использования Kubernetes его стандартными средств различными терминами OpenStack.
          В противном случае статья также показалась бы частью документации, но уже не для Kubernetes, а для OpenStack Magnum.


          Касательно особенностей.
          В качестве ingress в кластерах автоматически поднимается Traefik.
          Про PV вкратце описано в разделе "Хранение данных", в качестве бэкенда для всех типов дисков в настоящее время используется только OpenStack Cinder.
          Шаблон кластера это просто некий набор параметров, из которого можно создать свой кластер. Подробнее про них можно узнать из документации: Magnum User Guide.
          Позже, когда мы добавим поддержку Kubernetes в панель управления, данный набор можно будет генерировать на лету, не вдаваясь в различные абстракции компонента OpenStack Magnum.

          0
          А простая возможность добавления/удаления нод после создания кластера имеется?
            +2

            В настоящее время это возможно только через консольный клиент openstack. Вам нужно указать новое значение для количества нод:


            openstack coe cluster update CLUSTER_NAME replace node_count=4

            Количество мастер-нод у запущенного кластера пока-что изменить невозможно.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое