Как автоматизировать развертывание в DigitalOcean Kubernetes с помощью CircleCI

_Автор выбрал Tech Education Fund для получения пожертвования в рамках программы Write for DOnations. _

Вступление

Наличие автоматического процесса развертывания является требованием для масштабируемого и отказоустойчивого приложения, и GitOps, или Git-based DevOps, быстро стали популярный метод организации CI / CD с репозиторием Git в качестве «единого источника правды». Такие инструменты, как CircleCI, интегрируются с вашим репозиторием GitHub, позволяя вам автоматически тестировать и развертывать свой код каждый время, когда вы вносите изменения в свой репозиторий. Когда этот вид CI / CD сочетается с гибкостью инфраструктуры Kubernetes, вы можете создать приложение, которое легко масштабируется с изменяющимся спросом.

В этой статье вы будете использовать CircleCI для развертывания примера приложения в кластере DigitalOcean Kubernetes (DOKS). Прочитав это руководство, вы сможете применить эти же методы для развертывания других инструментов CI / CD, которые можно создавать в виде образов Docker.

Предпосылки

Чтобы следовать этому руководству, вам необходимо иметь:

  • Https://cloud.digitalocean.com/registrations/new[DigitalOcean account], который вы можете настроить, следуя Sign up для учетной записи DigitalOcean документация.

  • Docker, установленный на вашей рабочей станции, и знания о том, как создавать, удалять и запускать образы Docker. Вы можете установить Docker в Ubuntu 18.04, следуя инструкциям на Как установить и Используйте Docker в Ubuntu 18.04.

  • Знание того, как работает Kubernetes и как создавать на нем развертывания и сервисы. Настоятельно рекомендуется прочитать статью Introduction to Kubernetes.

  • Https://kubernetes.io/docs/tasks/tools/install-kubectl/ [+ kubectl +] инструмент интерфейса командной строки, установленный на компьютере, с которого вы будете управлять кластером.

  • Учетная запись на Docker Hub, которая будет использоваться для хранения вашего примера образа приложения.

  • Https://github.com/[GitHub] учетная запись и знание основ Git. Вы можете следить за учебными сериями Introduction для Git: установка, использование и ветви и https: // www.digitalocean.com/community/tutorials/how-to-create-a-pull-request-on-github[How Создать запрос на извлечение на GitHub], чтобы получить эти знания.

Для этого урока вы будете использовать Kubernetes версии + 1.13.5 + и + kubectl + version + 1.10.7 +.

Шаг 1 - Создание вашего кластера DigitalOcean Kubernetes

На этом первом шаге вы создадите кластер DigitalOcean Kubernetes (DOKS), из которого вы развернете свое приложение. Команды + kubectl +, выполняемые с вашего локального компьютера, изменят или получат информацию непосредственно из кластера Kubernetes.

Перейдите на страницу Kubernetes в своей учетной записи DigitalOcean.

Нажмите * Создать кластер Kubernetes * или нажмите зеленую кнопку * Создать * в правом верхнем углу страницы и выберите * Кластеры * в раскрывающемся меню.

изображение: https: //assets.digitalocean.com/articles/cart_64920/Create_DOKS.gif [Создание кластера Kubernetes в DigitalOcean]

На следующей странице вы будете указывать детали вашего кластера. Вкл * Выберите версию Kubernetes * выберите версию * 1.13.5-do.0 *. Если этот недоступен, выберите более высокий.

Для * Выберите регион центра обработки данных *, выберите ближайший к вам регион. Этот урок будет использовать * Сан-Франциско - 2 *.

Затем у вас есть возможность создать свой пул * Node *. В Kubernetes узел - это рабочая машина, которая содержит службы, необходимые для запуска модулей. В DigitalOcean каждый узел является каплей. Ваш пул узлов будет состоять из одного * стандартного узла *. Выберите конфигурацию * 2GB / 1vCPU * и измените на * 1 Node * количество узлов.

Вы можете добавить дополнительные теги, если хотите; это может быть полезно, если вы планируете использовать DigitalOcean API или просто лучше организовать свои пулы узлов.

На * Выберите имя *, для этого урока используйте + kubernetes-deploy-tutorial. Это облегчит следовать во время чтения следующих разделов. Наконец, нажмите зеленую кнопку * Создать кластер *, чтобы создать кластер.

После создания кластера в пользовательском интерфейсе появится кнопка для загрузки файла конфигурации с именем * Download Config File *. Это файл, который вы будете использовать для аутентификации команд + kubectl +, которые вы собираетесь запускать на вашем кластере. Загрузите его на свой компьютер + kubectl +.

Способ использования этого файла по умолчанию - всегда передавать флаг + - kubeconfig + и путь к нему во всех командах, которые вы запускаете с помощью + kubectl +. Например, если вы загрузили файл конфигурации в + Desktop +, вы бы запустили команду + kubectl get pods + следующим образом:

kubectl --kubeconfig ~/Desktop/kubernetes-deployment-tutorial-kubeconfig.yaml get pods

Это даст следующий результат:

OutputNo resources found.

Это означает, что вы получили доступ к своему кластеру. Сообщение + Ресурсы не найдены. + Правильное, поскольку в вашем кластере нет модулей.

Если вы не поддерживаете другие кластеры Kubernetes, вы можете скопировать файл kubeconfig в папку в вашем домашнем каталоге с именем + .kube +. Создайте этот каталог, если он не существует:

mkdir -p ~/.kube

Затем скопируйте файл конфигурации во вновь созданный каталог + .kube + и переименуйте его в + config +:

cp  ~/.kube/config

Файл конфигурации должен теперь иметь путь + ~ / .kube / config +. Это файл, который + kubectl + читает по умолчанию при запуске любой команды, поэтому больше нет необходимости передавать + - kubeconfig +. Запустите следующее:

kubectl get pods

Вы получите следующий вывод:

OutputNo resources found.

Теперь получите доступ к кластеру с помощью следующего:

kubectl get nodes

Вы получите список узлов в вашем кластере. Вывод будет похож на это:

OutputNAME                                    STATUS    ROLES     AGE       VERSION
kubernetes-deployment-tutorial-1-7pto   Ready     <none>    1h        v1.13.5

В этом руководстве вы собираетесь использовать пространство имен + default + для всех команд + kubectl + и manifest files, которые являются файлами, определяющими рабочую нагрузку и рабочие параметры работы в Kubernetes. Namespaces похожи на виртуальные кластеры внутри вашего физического кластера. Вы можете изменить любое другое пространство имен, какое захотите; просто всегда передавайте его с помощью флага + - namespace + в + kubectl +, и / или указав его в Kubernetes, вы увидите поле метаданных. Они являются отличным способом организации развертываний вашей команды и условий их работы; Подробнее о них читайте в official Kubernetes обзор пространств имен.

Завершив этот шаг, вы теперь можете запустить + kubectl + для своего кластера. На следующем шаге вы создадите локальный репозиторий Git, который вы собираетесь использовать для размещения вашего примера приложения.

Шаг 2 - Создание локального Git-репозитория

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

Во-первых, создайте новый Git-репозиторий локально, который позже вы отправите в GitHub. Создайте пустую папку с именем + do-sample-app в вашем домашнем каталоге и добавьте в нее` + cd`:

mkdir ~/do-sample-app
cd ~/do-sample-app

Теперь создайте новый репозиторий Git в этой папке с помощью следующей команды:

git init .

Внутри этого репозитория создайте пустую папку с именем + kube +:

mkdir ~/do-sample-app/kube/

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

Теперь создайте другую папку с именем + kube-general +, но на этот раз за пределами Git-репозитория, который вы только что создали. Сделайте это в вашем домашнем каталоге:

mkdir ~/kube-general/

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

После того, как ваши папки созданы и Git-репозиторий вашего примера приложения на месте, пришло время организовать аутентификацию и авторизацию вашего кластера DOKS.

Шаг 3 - Создание учетной записи службы

Как правило, не рекомендуется использовать пользователя * admin * по умолчанию для аутентификации с других Services в вашем кластере Kubernetes. Если ваши ключи на внешнем провайдере будут скомпрометированы, весь ваш кластер будет скомпрометирован.

Вместо этого вы собираетесь использовать одну Service Account с определенной ролью, которая является частью https: / /kubernetes.io/docs/reference/access-authn-authz/rbac/[RBAC Кубернетская модель авторизации].

Эта модель авторизации основана на Roles и Resources. Вы начинаете с создания учетной записи Service, которая в основном является пользователем в вашем кластере, затем вы создаете роль, в которой вы указываете, к каким ресурсам он имеет доступ в вашем кластере. Наконец, вы создаете Role Binding, который используется для установления соединения между ролью и учетной записью службы, созданной ранее, предоставляя учетной записи службы доступ ко всем ресурсам, к которым у этой роли есть доступ.

Первый ресурс Kubernetes, который вы собираетесь создать, - это служебная учетная запись для вашего пользователя CI / CD, которую этот учебник назовет + cicd +.

Создайте файл + cicd-service-account.yml + внутри папки + ~ / kube-general + и откройте его в своем любимом текстовом редакторе:

nano ~/kube-general/cicd-service-account.yml

Напишите на нем следующее содержание:

Генерал-Кубэ ~ / / cicd-сервис-account.yml

apiVersion: v1
kind: ServiceAccount
metadata:
 name: cicd
 namespace: default

Это файл YAML; все ресурсы Kubernetes представлены с использованием одного. В этом случае вы говорите, что этот ресурс взят из версии API Kubernetes + v1 + (внутренне + kubectl + создает ресурсы, вызывая API API Kubernetes), и это + ServiceAccount +.

Поле + metadata + используется для добавления дополнительной информации об этом ресурсе. В этом случае вы даете этому + ServiceAccount + имя + cicd + и создаете его в пространстве имен + default +.

Теперь вы можете создать эту учетную запись службы в своем кластере, запустив + kubectl apply +, как показано ниже:

kubectl apply -f ~/kube-general/

Вы получите вывод, подобный следующему:

Outputserviceaccount/cicd created

Чтобы убедиться, что ваша служебная учетная запись работает, попробуйте войти в свой кластер, используя ее. Для этого сначала нужно получить соответствующий токен доступа и сохранить его в переменной среды. У каждой учетной записи службы есть токен доступа, который Kubernetes хранит как Secret.

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

TOKEN=$(kubectl get secret $(kubectl get secret | grep cicd-token | awk '{print $1}') -o jsonpath='{.data.token}' | base64 --decode)

Некоторое объяснение того, что делает эта команда:

$(kubectl get secret | grep cicd-token | awk '{print $1}')

Это используется для получения имени секрета, относящегося к нашей учетной записи службы + cicd +. + kubectl get secret + возвращает список секретов в пространстве имен по умолчанию, затем вы используете + grep + для поиска строк, связанных с вашей учетной записью + cicd +. Затем вы возвращаете имя, так как это первое, что в единственной строке возвращается из + grep +.

kubectl get secret  -o jsonpath='{.data.token}' | base64 --decode

Это позволит получить только секрет для вашего токена учетной записи службы. Затем вы получаете доступ к полю токена с помощью + jsonpath + и передаете результат в + base64 --decode +. Это необходимо, поскольку токен хранится в виде строки Base64. Сам токен является веб-токеном JSON.

Теперь вы можете попытаться получить ваши модули с помощью учетной записи службы + cicd +. Запустите следующую команду, заменив ++ URL-адресом сервера, который можно найти после + server: + в + ~ kube / config +. Эта команда выдаст конкретную ошибку, о которой вы узнаете позже в этом руководстве:

kubectl --insecure-skip-tls-verify --kubeconfig="/dev/null" --server= --token=$TOKEN get pods

+ - insecure-skip-tls-verify + пропускает этап проверки сертификата сервера, так как вы только тестируете и не должны это проверять. + - kubeconfig =" / dev / null "+ должен убедиться, что + kubectl + не читает ваш файл конфигурации и учетные данные, а вместо этого использует предоставленный токен.

Вывод должен быть похож на это:

OutputError from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:cicd" cannot list resource "pods" in API group "" in the namespace "default"

Это ошибка, но она показывает нам, что токен работал. Полученная вами ошибка связана с тем, что ваша учетная запись службы не имеет необходимых прав для перечисления ресурса + secrets +, но вы смогли получить доступ к самому серверу. Если бы ваш токен не работал, ошибка была бы следующей:

Outputerror: You must be logged in to the server (Unauthorized)

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

Шаг 4 - Создание роли и связывание роли

У Kubernetes есть два способа определения ролей: использование ресурса + Role + или + ClusterRole +. Разница между первым и вторым заключается в том, что первое относится к одному пространству имен, а другое действует для всего кластера.

Поскольку в этом руководстве вы используете одно пространство имен, вы будете использовать + Role +.

Создайте файл + ~ / kube-general / cicd-role.yml + и откройте его в своем любимом текстовом редакторе:

nano ~/kube-general/cicd-role.yml

Основная идея состоит в том, чтобы предоставить доступ для выполнения всего, что связано с большинством ресурсов Kubernetes, в пространстве имен + default +. Ваша + Role + будет выглядеть так:

Генеральный Kube ~ / / cicd-role.yml

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: cicd
 namespace: default
rules:
 - apiGroups: ["", "apps", "batch", "extensions"]
   resources: ["deployments", "services", "replicasets", "pods", "jobs", "cronjobs"]
   verbs: ["*"]

Этот YAML имеет некоторые сходства с тем, который вы создали ранее, но здесь вы говорите, что этот ресурс является + Role +, и он из API Kubernetes + rbac.authorization.k8s.io / v1 +. Вы называете свою роль + cicd + и создаете ее в том же пространстве имен, в котором создали свой + ServiceAccount +, то есть + default +.

Затем у вас есть поле + rules +, представляющее собой список ресурсов, к которым эта роль имеет доступ. В Kubernetes ресурсы определяются на основе группы API, к которой они принадлежат, самого вида ресурса и того, какие действия вы можете выполнять затем, что представлено глаголом. Those глаголы аналогичны глаголам HTTP.

В нашем случае вы говорите, что вашему + Role + разрешено делать все, + * +, на следующих ресурсах: + deployments,` + services`, + replicasets,` + pods + , + jobs + и + cronjobs + . Это также относится к ресурсам, принадлежащим следующим группам API: `+" "+ (пустая строка), + apps +, + batch + и + extensions +. Пустая строка означает корневую группу API. Если вы используете + apiVersion: v1 + при создании ресурса, это означает, что этот ресурс является частью этой группы API.

+ Роль + сама по себе ничего не делает; Вы также должны создать https://kubernetes.io/docs/reference/access-authn-authz/rbac/#rolebinding-and-clusterrolebinding [+ RoleBinding +], который связывает + Role + с чем-то, в этом case, + ServiceAccount +.

Создайте файл + ~ / kube-general / cicd-role-binding.yml + и откройте его:

nano ~/kube-general/cicd-role-binding.yml

Добавьте следующие строки в файл:

Генерал-Кубэ ~ / / cicd-ролевой binding.yml

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: cicd
 namespace: default
subjects:
 - kind: ServiceAccount
   name: cicd
   namespace: default
roleRef:
 kind: Role
 name: cicd
 apiGroup: rbac.authorization.k8s.io

Ваш + RoleBinding + имеет некоторые конкретные поля, которые еще не были рассмотрены в этом руководстве. + roleRef + - это + Role +, которую вы хотите привязать к чему-либо; в данном случае это роль + cicd +, которую вы создали ранее. + subject + - список ресурсов, с которыми вы связываете свою роль; в этом случае это единственный + ServiceAccount +, называемый + cicd +.

После создания этих файлов вы сможете снова использовать + kubectl apply +. Создайте эти новые ресурсы в своем кластере Kubernetes, выполнив следующую команду:

kubectl apply -f ~/kube-general/

Вы получите вывод, подобный следующему:

Outputrolebinding.rbac.authorization.k8s.io/cicd created
role.rbac.authorization.k8s.io/cicd created
serviceaccount/cicd created

Теперь попробуйте команду, которую вы запускали ранее:

kubectl --insecure-skip-tls-verify --kubeconfig="/dev/null" --server= --token=$TOKEN get pods

Поскольку у вас нет стручков, вы получите следующий результат:

OutputNo resources found.

На этом этапе вы предоставили служебной учетной записи, которую собираетесь использовать в CircleCI, необходимые полномочия для выполнения значимых действий в вашем кластере, таких как перечисление, создание и обновление ресурсов. Теперь пришло время создать пример приложения.

Шаг 5 - Создание вашего образца приложения

Kubernetes + Deployment +, который вы собираетесь создать, будет использовать изображение Nginx в качестве основы, и ваше приложение будет простой статической HTML-страницей. Это отличное начало, поскольку оно позволяет вам проверить, работает ли ваше развертывание, предоставляя простой HTML-код непосредственно из Nginx. Как вы увидите позже, вы можете перенаправить весь трафик, поступающий на локальный + адрес: порт +, в ваше развертывание в кластере, чтобы проверить, работает ли он.

Внутри репозитория, который вы установили ранее, создайте новый файл + Dockerfile + и откройте его в любом текстовом редакторе:

nano ~/do-sample-app/Dockerfile

Напишите на нем следующее:

~ / Делать выборки-приложение / Dockerfile

FROM nginx:1.14

COPY index.html /usr/share/nginx/html/index.html

Это скажет Docker построить контейнер приложения из образа + nginx +.

Теперь создайте новый файл + index.html и откройте его:

nano ~/do-sample-app/index.html

Напишите следующее содержание HTML:

~ / Делать выборки-приложение / index.html

<!DOCTYPE html>
<title>DigitalOcean</title>
<body>
 Kubernetes Sample Application
</body>

Этот HTML-код отобразит простое сообщение, которое сообщит вам, работает ли ваше приложение.

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

Сначала создайте образ с помощью следующей команды, заменив ++ своим именем пользователя в Docker Hub. Вы должны указать здесь свое имя пользователя, чтобы при последующем его переносе в Docker Hub оно просто работало:

docker build ~/do-sample-app/ -t /do-kubernetes-sample-app

Теперь запустите изображение. Используйте следующую команду, которая запускает ваш образ и перенаправляет любой локальный трафик через порт + 8080 + на порт + 80 + внутри образа, порт Nginx прослушивает по умолчанию:

docker run --rm -it -p 8080:80 /do-kubernetes-sample-app

Командная строка перестанет быть интерактивной во время выполнения команды. Вместо этого вы увидите журналы доступа Nginx. Если вы откроете + localhost: 8080 + в любом браузере, он должен показать HTML-страницу с содержимым + ~ / do-sample-app / index.html +. Если у вас нет доступного браузера, вы можете открыть новое окно терминала и использовать следующую команду + curl + для извлечения HTML-кода с веб-страницы:

curl localhost:8080

Вы получите следующий вывод:

Output<!DOCTYPE html>
<title>DigitalOcean</title>
<body>
 Kubernetes Sample Application
</body>

Остановите контейнер (+ CTRL + + + C + на терминале, в котором он работает) и отправьте это изображение в свою учетную запись Docker Hub. Для этого сначала войдите в Docker Hub:

docker login

Введите необходимую информацию о вашей учетной записи Docker Hub, затем нажмите на изображение с помощью следующей команды (не забудьте заменить «++» на вашу собственную):

docker push /do-kubernetes-sample-app

Теперь вы отправили образ приложения в свою учетную запись Docker Hub. На следующем шаге вы создадите Deployment в своем кластере DOKS из этого образа.

Шаг 6 - Создание развертывания и обслуживания Kubernetes

С созданным и работающим образом Docker вы теперь создадите манифест, сообщающий Kubernetes о том, как создать из него в вашем кластере Deployment из него.

Создайте файл развертывания YAML + ~ / do-sample-app / kube / do-sample-deploy.yml + и откройте его в текстовом редакторе:

nano ~/do-sample-app/kube/do-sample-deployment.yml

Запишите следующее содержимое файла, убедившись, что заменили ++ на ваше имя пользователя в Docker Hub:

~ / Делать выборки-приложение / Кубэ / сделай образец-deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
 name: do-kubernetes-sample-app
 namespace: default
 labels:
   app: do-kubernetes-sample-app
spec:
 replicas: 1
 selector:
   matchLabels:
     app: do-kubernetes-sample-app
 template:
   metadata:
     labels:
       app: do-kubernetes-sample-app
   spec:
     containers:
       - name: do-kubernetes-sample-app
         image: /do-kubernetes-sample-app:latest
         ports:
           - containerPort: 80
             name: http

Развертывания Kubernetes происходят из группы API + apps +, поэтому для + apiVersion + вашего манифеста установлено значение + apps / v1 +. На + metadata ++ вы добавили новое поле, которое вы не использовали ранее, под названием + metadata.labels. Это полезно для организации вашего развертывания. Поле + spec + представляет спецификацию поведения вашего развертывания. Развертывание отвечает за управление одним или несколькими модулями; в этом случае он будет иметь одну реплику в поле + spec.replicas +. То есть он собирается создавать и управлять одним модулем.

Чтобы управлять модулями, ваше развертывание должно знать, за какие блоки они отвечают. Поле + spec.selector + предоставляет информацию. В этом случае развертывание будет отвечать за все модули с тегами + app = do-kubernetes-sample-app +. Поле + spec.template + содержит подробную информацию о + Pod +, который создаст это развертывание. Внутри шаблона у вас также есть поле + spec.template.metadata. + Метки + внутри этого поля должны совпадать с теми, которые используются в + spec.selector +. + spec.template.spec + - это спецификация самого модуля. В этом случае он содержит один контейнер, называемый + do-kubernetes-sample-app. Изображение этого контейнера - это изображение, которое вы создали ранее и отправили в Docker Hub.

Этот файл YAML также сообщает Kubernetes, что этот контейнер предоставляет порт + 80 +, и дает этому порту имя + http +.

Чтобы получить доступ к порту, указанному вашим + Deployment +, создайте Сервис. Создайте файл с именем + ~ / do-sample-app / kube / do-sample-service.yml + и откройте его в своем любимом редакторе:

nano ~/do-sample-app/kube/do-sample-service.yml

Затем добавьте следующие строки в файл:

~ / Делать выборки-приложение / Кубэ / сделай образец-service.yml

apiVersion: v1
kind: Service
metadata:
 name: do-kubernetes-sample-app
 namespace: default
 labels:
   app: do-kubernetes-sample-app
spec:
 type: ClusterIP
 ports:
   - port: 80
     targetPort: http
     name: http
 selector:
   app: do-kubernetes-sample-app

Этот файл дает вашему + Service + те же самые метки, которые используются в вашем развертывании. Это не обязательно, но это помогает организовать ваши приложения на Kubernetes.

Сервисный ресурс также имеет поле + spec +. Поле + spec.type + отвечает за поведение службы. В этом случае это + ClusterIP +, что означает, что служба предоставляется по внутреннему IP-адресу кластера и доступна только изнутри вашего кластера. По умолчанию это + spec.type + для сервисов. + spec.selector + - это критерии выбора меток, которые следует использовать при выборе модулей, которые будут представлены этой службой. Поскольку у вашего модуля есть тег + app: to-kubernetes-sample-app, вы использовали его здесь. + spec.ports + - это порты, предоставляемые контейнерами модуля, которые вы хотите использовать в этом сервисе. В вашем модуле есть один контейнер, который предоставляет порт + 80 + с именем + http +, поэтому вы используете его здесь как + targetPort +. Служба также выставляет этот порт на порт + 80 + с тем же именем, но вы могли использовать другую комбинацию порт / имя, чем та, которая указана в контейнере.

Создав файлы манифеста + Service и` + Deployment`, теперь вы можете создавать эти ресурсы в своем кластере Kubernetes, используя + kubectl:

kubectl apply -f ~/do-sample-app/kube/

Вы получите следующий вывод:

Outputdeployment.apps/do-kubernetes-sample-app created
service/do-kubernetes-sample-app created

Проверьте, работает ли это, перенаправив один порт на вашей машине на порт, который служба предоставляет в вашем кластере Kubernetes. Вы можете сделать это используя + kubectl port-forward +:

kubectl port-forward $(kubectl get pod --selector="app=do-kubernetes-sample-app" --output jsonpath='{.items[0].metadata.name}') 8080:80

Команда subshell + $ (kubectl get pod --selector =" app = do-kubernetes-sample-app "--output jsonpath = '{. Items [0] .metadata.name}') + возвращает имя стручок, соответствующий тегу, который вы использовали. В противном случае вы могли бы извлечь его из списка модулей, используя + kubectl get pods +.

После запуска + port-forward + оболочка перестанет быть интерактивной и вместо этого выведет запросы, перенаправленные в ваш кластер:

OutputForwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80

Открытие + localhost: 8080 + в любом браузере должно отобразить ту же страницу, которую вы видели, когда запускали контейнер локально, но теперь он идет из вашего кластера Kubernetes! Как и раньше, вы также можете использовать + curl + в новом окне терминала, чтобы проверить, работает ли он:

curl localhost:8080

Вы получите следующий вывод:

Output<!DOCTYPE html>
<title>DigitalOcean</title>
<body>
 Kubernetes Sample Application
</body>

Затем пришло время отправить все созданные вами файлы в ваш репозиторий GitHub. Для этого вы должны сначала create репозиторий на GitHub под названием + digital-ocean-kubernetes-deploy +.

Чтобы сохранить этот репозиторий простым для демонстрационных целей, не инициализируйте новый репозиторий файлом + README +, + license + или + .gitignore + при запросе в пользовательском интерфейсе GitHub. Вы можете добавить эти файлы позже.

Создав репозиторий, укажите свой локальный репозиторий на GitHub. Чтобы сделать это, нажмите + CTRL + + + C +, чтобы остановить + kubectl port-forward + и вернуть командную строку, затем выполните следующие команды, чтобы добавить новый пульт с именем + origin +:

cd ~/do-sample-app/
git remote add origin https://github.com//digital-ocean-kubernetes-deploy.git

Там не должно быть никакого вывода из предыдущей команды.

Затем зафиксируйте все файлы, которые вы создали до сих пор, в хранилище GitHub. Сначала добавьте файлы:

git add --all

Затем, зафиксируйте файлы в своем хранилище с сообщением о фиксации в кавычках:

git commit -m "initial commit"

Это даст результат, подобный следующему:

Output[master (root-commit) db321ad] initial commit
4 files changed, 47 insertions(+)
create mode 100644 Dockerfile
create mode 100644 index.html
create mode 100644 kube/do-sample-deployment.yml
create mode 100644 kube/do-sample-service.yml

Наконец, отправьте файлы на GitHub:

git push -u origin master

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

OutputCounting objects: 7, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (7/7), done.
Writing objects: 100% (7/7), 907 bytes | 0 bytes/s, done.
Total 7 (delta 0), reused 0 (delta 0)
To github.com:/digital-ocean-kubernetes-deploy.git
* [new branch]      master -> master
Branch master set up to track remote branch master from origin.

Если вы перейдете на страницу своего репозитория GitHub, вы увидите все файлы там. Теперь, когда ваш проект работает на GitHub, вы можете настроить CircleCI в качестве инструмента CI / CD.

Шаг 7 - Настройка CircleCI

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

Сначала перейдите на их домашнюю страницу https://circleci.com [+ https: // circleci.com +] и нажмите * Зарегистрироваться *.

Изображение: https: //assets.digitalocean.com/articles/cart_64920/CircleCI_Main_Site.png [circleci-домашняя страница]

Вы используете GitHub, поэтому нажмите зеленую кнопку * Зарегистрироваться с помощью GitHub *.

CircleCI будет перенаправлять на страницу авторизации на GitHub. CircleCI требуются некоторые разрешения для вашей учетной записи, чтобы можно было приступить к созданию ваших проектов. Это позволяет CircleCI получать вашу электронную почту, развертывать ключи и разрешение на создание хуков в ваших репозиториях и добавлять ключи SSH в вашу учетную запись. Если вам нужна дополнительная информация о том, что CircleCI собирается делать с вашими данными, проверьте их documentation об интеграции GitHub.

Изображение: https: //assets.digitalocean.com/articles/cart_64920/CircleCI_GitHub_Sign_In.png [circleci-GitHub авторизации]

После авторизации CircleCI вы будете перенаправлены на их панель управления.

Изображение: https: //assets.digitalocean.com/articles/cart_64920/CircleCI_Welcome_Page.png [circleci-проект-панель]

Затем настройте свой репозиторий GitHub в CircleCI. Нажмите * Настроить новые проекты * на панели инструментов CircleCI или в качестве ярлыка откройте следующую ссылку, изменив выделенный текст с вашим собственным именем пользователя GitHub: `+ https: //circleci.com/setup-project/gh//digital -ocean-kubernetes развертывание + `.

После этого нажмите * Start Building *. Пока не создавайте файл конфигурации в своем хранилище, и не беспокойтесь, если первая сборка не удалась.

Изображение: https: //assets.digitalocean.com/articles/cart_64840/Set_Up.png [circleci-старт потенциала]

Далее укажите некоторые переменные окружения в настройках CircleCI. Вы можете найти настройки проекта, нажав на маленькую кнопку со значком шестеренки в правом верхнем углу страницы и выбрав * Переменные среды *, или вы можете перейти непосредственно на страницу переменных среды, используя следующий URL-адрес (запомните введите свое имя пользователя): + https: // circleci.com / gh // digital-ocean-kubernetes-deploy / edit # env-vars +. Нажмите * Добавить переменную *, чтобы создать новые переменные среды.

Сначала добавьте две переменные окружения, названные + DOCKERHUB_USERNAME + и + DOCKERHUB_PASS +, которые позже понадобятся для передачи изображения в Docker Hub. Задайте значения для имени пользователя и пароля Docker Hub соответственно.

Затем добавьте еще три: + KUBERNETES_TOKEN +, + KUBERNETES_SERVER + и + KUBERNETES_CLUSTER_CERTIFICATE +.

Значение + KUBERNETES_TOKEN + будет значением локальной переменной среды, которую вы использовали ранее для аутентификации в вашем кластере Kubernetes с использованием вашей учетной записи службы. Если вы закрыли терминал, вы всегда можете запустить следующую команду, чтобы получить его снова:

kubectl get secret $(kubectl get secret | grep cicd-token | awk '{print $1}') -o jsonpath='{.data.token}' | base64 --decode

+ KUBERNETES_SERVER + будет строкой, которую вы передали в качестве флага + - server + для + kubectl + при входе в систему с помощью учетной записи службы + cicd +. Вы можете найти это после + server: + в файле + ~ / .kube / config + или в файле + kubernetes-deploy-tutorial-kubeconfig.yaml +, загруженном с панели мониторинга DigitalOcean, когда вы сделали начальную настройка вашего кластера Kubernetes.

+ KUBERNETES CLUSTER CERTIFICATE + также должен быть доступен в вашем файле + ~ / .kube / config. Это поле + Certificate Authority-Data элемента` + cluster`, связанного с вашим кластером. Это должна быть длинная строка; убедитесь, что скопировали все это.

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

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

Создайте каталог с именем + .circleci + в вашем репозитории примеров приложений:

mkdir ~/do-sample-app/.circleci/

Внутри этого каталога создайте файл с именем + config.yml + и откройте его в своем любимом редакторе:

nano ~/do-sample-app/.circleci/config.yml

Добавьте следующий файл в файл, убедившись, что заменили ++ на ваше имя пользователя Docker Hub:

~ / Делать выборки-приложение / .circleci / config.yml

version: 2.1
jobs:
 build:
   docker:
     - image: circleci/buildpack-deps:stretch
   environment:
     IMAGE_NAME: /do-kubernetes-sample-app
   working_directory: ~/app
   steps:
     - checkout
     - setup_remote_docker
     - run:
         name: Build Docker image
         command: |
           docker build -t $IMAGE_NAME:latest .
     - run:
         name: Push Docker Image
         command: |
           echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin
           docker push $IMAGE_NAME:latest
workflows:
 version: 2
 build-master:
   jobs:
     - build:
         filters:
           branches:
             only: master

Это устанавливает рабочий процесс с одним заданием, называемым + build, которое выполняется для каждого коммита в ветке` + master`. Эта работа использует для запуска своих шагов изображение + circleci / buildpack-deps: stretch +, представляющее собой изображение из CircleCI, основанное на официальном образе Docker + buildpack-deps +, но с некоторыми дополнительными установленными инструментами, такими как исполняемые файлы Docker. самих себя.

Рабочий процесс состоит из четырех этапов:

  • + checkout + извлекает код из GitHub.

  • + setup_remote_docker + устанавливает удаленную изолированную среду для каждой сборки. Это необходимо, прежде чем использовать какую-либо команду + docker внутри шага задания. Это необходимо, потому что, поскольку шаги выполняются внутри образа докера, + setup_remote_docker + выделяет другой компьютер для запуска там команд.

  • Первый шаг + run + строит образ, как вы делали это ранее локально. Для этого вы используете переменную окружения, которую вы объявили в + environment: +, + IMAGE_NAME + (не забудьте изменить выделенный раздел вашей собственной информацией).

  • Последний шаг + run + отправляет образ в Dockerhub, используя переменные окружения, которые вы настроили в настройках проекта для аутентификации.

Зафиксируйте новый файл в своем хранилище и отправьте изменения вверх по течению:

cd ~/do-sample-app/
git add .circleci/
git commit -m "add CircleCI config"
git push

Это вызовет новую сборку на CircleCI. Рабочий процесс CircleCI будет правильно собирать и передавать ваш образ в Docker Hub.

изображение: https: //assets.digitalocean.com/articles/cart_64840/Build.png [страница сборки CircleCI с информацией об успешной сборке]

Теперь, когда вы создали и протестировали рабочий процесс CircleCI, вы можете настроить кластер DOKS на получение обновленного образа из Docker Hub и его автоматическое развертывание при внесении изменений.

Шаг 8 - Обновление развертывания в кластере Kubernetes

Теперь, когда образ вашего приложения создается и отправляется в Docker Hub каждый раз, когда вы вносите изменения в ветку + master + на GitHub, пришло время обновить ваше развертывание в кластере Kubernetes, чтобы оно получало новый образ и использовало его как база для развертывания.

Для этого сначала исправьте одну проблему в своем развертывании: в настоящее время она зависит от образа с тегом + latest +. Этот тег не сообщает нам, какую версию изображения вы используете. Вы не можете легко заблокировать ваше развертывание для этого тега, потому что оно перезаписывается каждый раз, когда вы отправляете новый образ в Docker Hub, и при его использовании вы теряете одно из лучших преимуществ использования контейнерных приложений: воспроизводимость.

Вы можете узнать больше об этом в этой статье о том, почему depending от последнего тега Docker является антишаблоном.

Чтобы исправить это, сначала необходимо внести некоторые изменения в шаг сборки + Push Docker Image в файле` + ~ / do-sample-app / .circleci / config.yml`. Откройте файл:

nano ~/do-sample-app/.circleci/config.yml

Затем добавьте выделенные строки к вашему шагу + Push Docker Image +:

~ / Делать выборки-приложение / .circleci / config.yml: 16-22

...
     - run:
         name: Push Docker Image
         command: |
           echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin

           docker push $IMAGE_NAME:latest

...

Сохраните и выйдите из файла.

CircleCI имеет некоторые специальные переменные окружения, установленные по умолчанию. Одним из них является + CIRCLE_SHA1 +, который содержит хэш коммита, который он создает. Изменения, которые вы внесли в + ~ / do-sample-app / .circleci / config.yml +, будут использовать эту переменную среды, чтобы пометить ваше изображение коммитом, из которого оно было построено, всегда помечая самую последнюю сборку последним тегом. Таким образом, вы всегда имеете в наличии определенные изображения, не перезаписывая их, когда вы добавляете что-то новое в свой репозиторий.

Затем измените файл манифеста развертывания, чтобы он указывал на этот файл. Это было бы просто, если бы внутри + ~ / do-sample-app / kube / do-sample-deploy.yml + вы могли установить свое изображение как + / do-kubernetes-sample-app: $ COMMIT_SHA1 +, но + kubectl + `не выполняет подстановку переменных внутри манифестов, когда вы используете + kubectl apply + . Чтобы учесть это, вы можете использовать https://www.gnu.org/software/gettext/manual/html_node/envsubst-Invocation.html [+ envsubst `]. ` envsubst +` - это инструмент cli, часть проекта gettext для GNU. Он позволяет вам передать ему некоторый текст, и, если он найдет какую-либо переменную внутри текста с соответствующей переменной окружения, он будет заменен соответствующим значением. Полученный текст затем возвращается в качестве вывода.

Чтобы использовать это, вы создадите простой bash-скрипт, который будет отвечать за ваше развертывание. Создайте новую папку с именем + scripts + внутри + ~ / do-sample-app / +:

mkdir ~/do-sample-app/scripts/

Внутри этой папки создайте новый скрипт bash с именем + ci-deploy.sh + и откройте его в своем любимом текстовом редакторе:

nano ~/do-sample-app/scripts/ci-deploy.sh

Внутри него напишите следующий скрипт bash:

~ / Делать выборки-приложение / скрипты / ci-deploy.sh

#! /bin/bash
# exit script when any command ran here returns with non-zero exit code
set -e

COMMIT_SHA1=$CIRCLE_SHA1

# We must export it so it's available for envsubst
export COMMIT_SHA1=$COMMIT_SHA1

# since the only way for envsubst to work on files is using input/output redirection,
#  it's not possible to do in-place substitution, so we need to save the output to another file
#  and overwrite the original with that one.
envsubst <./kube/do-sample-deployment.yml >./kube/do-sample-deployment.yml.out
mv ./kube/do-sample-deployment.yml.out ./kube/do-sample-deployment.yml

echo "$KUBERNETES_CLUSTER_CERTIFICATE" | base64 --decode > cert.crt

./kubectl \
 --kubeconfig=/dev/null \
 --server=$KUBERNETES_SERVER \
 --certificate-authority=cert.crt \
 --token=$KUBERNETES_TOKEN \
 apply -f ./kube/

Давайте пройдемся по этому сценарию, используя комментарии в файле. Во-первых, есть следующее:

set -e

Эта строка гарантирует, что любая неудачная команда останавливает выполнение скрипта bash. Таким образом, если одна команда завершится неудачно, следующие не будут выполнены.

COMMIT_SHA1=$CIRCLE_SHA1
export COMMIT_SHA1=$COMMIT_SHA1

Эти строки экспортируют переменную окружения CircleCI + $ CIRCLE_SHA1 + с новым именем. Если вы только что объявили переменную, не экспортируя ее с помощью + export +, она не будет видна для команды + envsubst +.

envsubst <./kube/do-sample-deployment.yml >./kube/do-sample-deployment.yml.out
mv ./kube/do-sample-deployment.yml.out ./kube/do-sample-deployment.yml

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

echo "$KUBERNETES_CLUSTER_CERTIFICATE" | base64 --decode > cert.crt

Переменная среды + $ KUBERNETES_CLUSTER_CERTIFICATE +, которую вы создали ранее в настройках проекта CircleCI, на самом деле является строкой в ​​кодировке Base64. Чтобы использовать его с + kubectl +, вы должны декодировать его содержимое и сохранить его в файл. В этом случае вы сохраняете его в файл с именем + cert.crt + внутри текущего рабочего каталога.

./kubectl \
 --kubeconfig=/dev/null \
 --server=$KUBERNETES_SERVER \
 --certificate-authority=cert.crt \
 --token=$KUBERNETES_TOKEN \
 apply -f ./kube/

Наконец, вы запускаете + kubectl +. Команда имеет аргументы, аналогичные тем, которые вы запускали при тестировании своей учетной записи службы. Вы вызываете + apply -f. / Kube / +, поскольку в CircleCI текущий рабочий каталог является корневой папкой вашего проекта. +. / kube / + - это ваша папка + ~ / do-sample-app / kube +.

Сохраните файл и убедитесь, что он исполняемый:

chmod +x ~/do-sample-app/scripts/ci-deploy.sh

Теперь отредактируйте + ~ / do-sample-app / kube / do-sample-deploy.yml +:

nano ~/do-sample-app/kube/do-sample-deployment.yml

Измените тег значения изображения контейнера, чтобы он выглядел следующим образом:

~ / Делать выборки-приложение / Кубэ / сделай образец-deployment.yml

     # ...
     containers:
       - name: do-kubernetes-sample-app
         image: /do-kubernetes-sample-app:
         ports:
           - containerPort: 80
             name: http

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

Откройте + ~ / do-sample-app / .circleci / config.yml + в вашем любимом текстовом редакторе:

nano ~/do-sample-app/.circleci/config.yml

Напишите следующие новые шаги прямо под + Push Docker Image +, который у вас был ранее:

~ / Делать выборки-приложение / .circleci / config.yml

...
     - run:
         name: Install envsubst
         command: |
           sudo apt-get update && sudo apt-get -y install gettext-base
     - run:
         name: Install kubectl
         command: |
           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 u+x ./kubectl
     - run:
         name: Deploy Code
         command: ./scripts/ci-deploy.sh

Первые два шага устанавливают некоторые зависимости, сначала + envsubst +, а затем + kubectl +. Шаг + Deploy Code + отвечает за запуск нашего сценария развертывания.

Чтобы убедиться, что изменения действительно будут отражены в вашем развертывании в Kubernetes, отредактируйте ваш + index.html +. Измените HTML на что-то другое, например:

~ / Делать выборки-приложение / index.html

<!DOCTYPE html>
<title>DigitalOcean</title>
<body>
 Automatic Deployment is Working!
</body>

После того, как вы сохранили вышеупомянутое изменение, зафиксируйте все измененные файлы в хранилище и отправьте изменения в исходное состояние:

cd ~/do-sample-app/
git add --all
git commit -m "add deploy script and add new steps to circleci config"
git push

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

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

kubectl port-forward $(kubectl get pod --selector="app=do-kubernetes-sample-app" --output jsonpath='{.items[0].metadata.name}') 8080:80

Убедитесь, что все работает, открыв браузер по URL + localhost: 8080 + или сделав запрос + curl + к нему. Должен отображаться обновленный HTML:

curl localhost:8080

Вы получите следующий вывод:

Output<!DOCTYPE html>
<title>DigitalOcean</title>
<body>
 Automatic Deployment is Working!
</body>

Поздравляем, вы настроили автоматическое развертывание с CircleCI!

Заключение

Это было базовое руководство по развертыванию в DigitalOcean Kubernetes с использованием CircleCI. Отсюда вы можете улучшить свой конвейер разными способами. Первое, что вы можете сделать, это создать одно задание `+ build + 'для нескольких развертываний, каждое из которых развертывается в разных кластерах Kubernetes или в разных пространствах имен. Это может быть чрезвычайно полезно, когда у вас есть разные ветки Git для сред разработки / подготовки / производства, гарантируя, что развертывания всегда разделены.

Вы также можете создать свой собственный образ для использования в CircleCI вместо использования + buildpack-deps +. Этот образ может быть основан на нем, но уже может иметь установленные зависимости + kubectl + и + envsubst +.

Если вы хотите узнать больше о CI / CD на Kubernetes, ознакомьтесь с руководствами для наших CI/CD Серия вебинаров Kubernetes, или для получения дополнительной информации о приложениях в Kubernetes, см. Https://www.digitalocean.com/community/tutorials/modernizing-applications-for-kubernetes[Modernizing Applications for Kubernetes].

Related